summaryrefslogtreecommitdiff
path: root/bsp/raspberry-pi
diff options
context:
space:
mode:
authorGuEe-GUI <[email protected]>2026-08-15 22:36:46 +0800
committerRbb666 <[email protected]>2026-08-16 19:56:03 +0800
commitf7258a6bb80d9be12e73675ab35a04651e32eda3 (patch)
tree050411e5f5e9990179a554bc8d0608762fabfa05 /bsp/raspberry-pi
parent2bcc47d418a4aed421d9750569a565a954daf045 (diff)
[bsp/raspberry-pi] update DM support
- reorganize common Raspberry Pi drivers under the device framework - add the Raspberry Pi 5 BSP, configuration and documentation - add BCM2712 and DesignWare AXI DMA controller support - distinguish BCM2712 DMA32 and DMA40 channels by channel mask - restore DesignWare AXI DMA enable bits after controller reset - support a shared AXI maximum burst length across DMA channels Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'bsp/raspberry-pi')
-rw-r--r--bsp/raspberry-pi/.gitignore8
-rwxr-xr-xbsp/raspberry-pi/dm/Kconfig33
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/dm/SConscript (renamed from bsp/raspberry-pi/raspi-dm2.0/SConscript)1
-rwxr-xr-xbsp/raspberry-pi/dm/adc/Kconfig6
-rwxr-xr-xbsp/raspberry-pi/dm/adc/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/adc/adc-rp1.c328
-rwxr-xr-xbsp/raspberry-pi/dm/audio/Kconfig4
-rwxr-xr-xbsp/raspberry-pi/dm/audio/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/audio/bcm2835-i2s.c724
-rwxr-xr-xbsp/raspberry-pi/dm/clk/Kconfig19
-rwxr-xr-xbsp/raspberry-pi/dm/clk/SConscript22
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-bcm2711-dvp.c237
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-bcm2835-aux.c220
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-bcm2835.c1976
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-dsi.c139
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-raspberrypi.c405
-rwxr-xr-xbsp/raspberry-pi/dm/clk/clk-rp1.c1797
-rwxr-xr-xbsp/raspberry-pi/dm/clock_time/Kconfig3
-rwxr-xr-xbsp/raspberry-pi/dm/clock_time/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/clock_time/clock_time-bcm2835_timer.c268
-rwxr-xr-xbsp/raspberry-pi/dm/dma/Kconfig3
-rwxr-xr-xbsp/raspberry-pi/dm/dma/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/dma/dma-bcm2835.c805
-rwxr-xr-xbsp/raspberry-pi/dm/dts/bcm2711-rpi-4-b.dts796
-rwxr-xr-xbsp/raspberry-pi/dm/dts/bcm283x-rpi-3-b.dts657
-rwxr-xr-xbsp/raspberry-pi/dm/dvfs/Kconfig4
-rwxr-xr-xbsp/raspberry-pi/dm/dvfs/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/dvfs/dvfs-raspberrypi-cpufreq.c276
-rwxr-xr-xbsp/raspberry-pi/dm/ethernet/Kconfig3
-rwxr-xr-xbsp/raspberry-pi/dm/ethernet/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/ethernet/eth-bcmgenet.c1219
-rwxr-xr-xbsp/raspberry-pi/dm/firmware/Kconfig6
-rwxr-xr-xbsp/raspberry-pi/dm/firmware/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/firmware/firmware-raspberrypi.c453
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/backlight/Kconfig5
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/backlight/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/backlight/backlight-rpi.c148
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/framebuffer/Kconfig9
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/framebuffer/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/framebuffer/fb-bcm2708.c508
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/framebuffer/fb-rpisense.c215
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/logo/Kconfig2
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/logo/Kconfig.path5
-rwxr-xr-xbsp/raspberry-pi/dm/graphic/logo/logo-raspi-clut224.ppm883
-rwxr-xr-xbsp/raspberry-pi/dm/hwcrypto/Kconfig14
-rwxr-xr-xbsp/raspberry-pi/dm/hwcrypto/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/hwcrypto/hw-rng-bcm2835.c330
-rwxr-xr-xbsp/raspberry-pi/dm/hwcrypto/hw-rng-iproc-rng200.c326
-rwxr-xr-xbsp/raspberry-pi/dm/i2c/Kconfig9
-rwxr-xr-xbsp/raspberry-pi/dm/i2c/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/i2c/i2c-bcm2835.c502
-rwxr-xr-xbsp/raspberry-pi/dm/i2c/i2c-brcmstb.c723
-rwxr-xr-xbsp/raspberry-pi/dm/include/bcm2835-pm.h23
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835-aux.h15
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835.h68
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/clock/rp1.h66
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/mfd/rp1.h236
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/pinctrl/bcm2835.h25
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/power/bcm2835-pm.h32
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/power/raspberrypi-power.h36
-rwxr-xr-xbsp/raspberry-pi/dm/include/dt-bindings/reset/raspberrypi,firmware-reset.h13
-rw-r--r--bsp/raspberry-pi/dm/include/dvfs-raspberrypi-cpufreq.h21
-rwxr-xr-xbsp/raspberry-pi/dm/include/firmware-raspberrypi.h219
-rwxr-xr-xbsp/raspberry-pi/dm/include/rpi-sense.h44
-rwxr-xr-xbsp/raspberry-pi/dm/input/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/input/joystick/Kconfig5
-rwxr-xr-xbsp/raspberry-pi/dm/input/joystick/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/input/joystick/js-rpisense.c154
-rwxr-xr-xbsp/raspberry-pi/dm/input/touchscreen/Kconfig9
-rwxr-xr-xbsp/raspberry-pi/dm/input/touchscreen/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/input/touchscreen/ts-raspberrypi.c264
-rwxr-xr-xbsp/raspberry-pi/dm/mailbox/Kconfig3
-rwxr-xr-xbsp/raspberry-pi/dm/mailbox/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/mailbox/mailbox-bcm2835.c251
-rwxr-xr-xbsp/raspberry-pi/dm/mfd/Kconfig18
-rwxr-xr-xbsp/raspberry-pi/dm/mfd/SConscript19
-rwxr-xr-xbsp/raspberry-pi/dm/mfd/bcm2835-pm.c119
-rwxr-xr-xbsp/raspberry-pi/dm/mfd/rp1.c415
-rwxr-xr-xbsp/raspberry-pi/dm/mfd/rpi-sense.c165
-rwxr-xr-xbsp/raspberry-pi/dm/nvmem/Kconfig4
-rwxr-xr-xbsp/raspberry-pi/dm/nvmem/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/nvmem/raspberrypi-otp.c180
-rwxr-xr-xbsp/raspberry-pi/dm/pci/Kconfig5
-rwxr-xr-xbsp/raspberry-pi/dm/pci/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/pci/pcie-brcmstb.c2669
-rwxr-xr-xbsp/raspberry-pi/dm/phy/Kconfig7
-rwxr-xr-xbsp/raspberry-pi/dm/phy/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/phy/mdio-bcm-unimac.c324
-rw-r--r--bsp/raspberry-pi/dm/phy/phy-bcm54213.c190
-rwxr-xr-xbsp/raspberry-pi/dm/pic/Kconfig19
-rwxr-xr-xbsp/raspberry-pi/dm/pic/SConscript22
-rwxr-xr-xbsp/raspberry-pi/dm/pic/pic-bcm2712-mip.c435
-rwxr-xr-xbsp/raspberry-pi/dm/pic/pic-bcm2835.c247
-rwxr-xr-xbsp/raspberry-pi/dm/pic/pic-bcm2836.c341
-rw-r--r--bsp/raspberry-pi/dm/pic/pic-brcmstb-l2.c324
-rwxr-xr-xbsp/raspberry-pi/dm/pin/Kconfig15
-rwxr-xr-xbsp/raspberry-pi/dm/pin/SConscript19
-rwxr-xr-xbsp/raspberry-pi/dm/pin/pin-bcm-virt.c188
-rw-r--r--bsp/raspberry-pi/dm/pin/pin-brcmstb.c571
-rwxr-xr-xbsp/raspberry-pi/dm/pin/pin-raspberrypi-exp.c311
-rwxr-xr-xbsp/raspberry-pi/dm/pinctrl/Kconfig14
-rwxr-xr-xbsp/raspberry-pi/dm/pinctrl/SConscript19
-rwxr-xr-xbsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2712.c988
-rwxr-xr-xbsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2835.c682
-rwxr-xr-xbsp/raspberry-pi/dm/pinctrl/pinctrl-rp1.c925
-rwxr-xr-xbsp/raspberry-pi/dm/pmdomain/Kconfig8
-rwxr-xr-xbsp/raspberry-pi/dm/pmdomain/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/pmdomain/pm-domain-bcm2835.c752
-rwxr-xr-xbsp/raspberry-pi/dm/pmdomain/pm-domain-raspberrypi.c241
-rwxr-xr-xbsp/raspberry-pi/dm/pwm/Kconfig20
-rwxr-xr-xbsp/raspberry-pi/dm/pwm/SConscript19
-rwxr-xr-xbsp/raspberry-pi/dm/pwm/pwm-bcm2835.c272
-rwxr-xr-xbsp/raspberry-pi/dm/pwm/pwm-brcmstb.c329
-rwxr-xr-xbsp/raspberry-pi/dm/pwm/pwm-rp1.c339
-rwxr-xr-xbsp/raspberry-pi/dm/reset/Kconfig15
-rwxr-xr-xbsp/raspberry-pi/dm/reset/SConscript19
-rwxr-xr-xbsp/raspberry-pi/dm/reset/reset-brcmstb-rescal.c165
-rwxr-xr-xbsp/raspberry-pi/dm/reset/reset-brcmstb.c143
-rwxr-xr-xbsp/raspberry-pi/dm/reset/reset-raspberrypi.c151
-rwxr-xr-xbsp/raspberry-pi/dm/rtc/Kconfig5
-rwxr-xr-xbsp/raspberry-pi/dm/rtc/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/rtc/rtc-rpi.c335
-rwxr-xr-xbsp/raspberry-pi/dm/sdio/Kconfig9
-rwxr-xr-xbsp/raspberry-pi/dm/sdio/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/sdio/sdhci-brcmstb.c580
-rwxr-xr-xbsp/raspberry-pi/dm/sdio/sdhci-iproc.c410
-rwxr-xr-xbsp/raspberry-pi/dm/serial/8250-bcm2835aux.c163
-rwxr-xr-xbsp/raspberry-pi/dm/serial/8250-bcm7271.c1095
-rwxr-xr-xbsp/raspberry-pi/dm/serial/Kconfig11
-rwxr-xr-xbsp/raspberry-pi/dm/serial/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/soc/Kconfig6
-rwxr-xr-xbsp/raspberry-pi/dm/soc/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/soc/raspberrypi-voltage-monitor.c204
-rwxr-xr-xbsp/raspberry-pi/dm/spi/Kconfig15
-rwxr-xr-xbsp/raspberry-pi/dm/spi/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/spi/spi-bcm2835.c558
-rwxr-xr-xbsp/raspberry-pi/dm/spi/spi-bcm2835aux.c489
-rwxr-xr-xbsp/raspberry-pi/dm/thermal/Kconfig9
-rwxr-xr-xbsp/raspberry-pi/dm/thermal/SConscript16
-rwxr-xr-xbsp/raspberry-pi/dm/thermal/thermal-bcm2711.c138
-rwxr-xr-xbsp/raspberry-pi/dm/thermal/thermal-bcm2835.c270
-rwxr-xr-xbsp/raspberry-pi/dm/watchdog/Kconfig5
-rwxr-xr-xbsp/raspberry-pi/dm/watchdog/SConscript13
-rwxr-xr-xbsp/raspberry-pi/dm/watchdog/watchdog-bcm2835.c240
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/README.md33
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/applications/SConscript14
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/applications/main.c19
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtbbin49833 -> 0 bytes
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig13
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript25
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/board.c32
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/board.h35
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c219
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h117
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c418
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h108
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig3
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript18
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h74
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h815
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h31
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h411
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h76
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c125
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c3606
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c303
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c44
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c37
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/qemu.sh9
-rw-r--r--bsp/raspberry-pi/raspi-dm2.0/rtconfig.py54
-rw-r--r--bsp/raspberry-pi/raspi3-64/.config453
-rw-r--r--bsp/raspberry-pi/raspi3-64/Kconfig13
-rw-r--r--bsp/raspberry-pi/raspi3-64/SConscript2
-rw-r--r--bsp/raspberry-pi/raspi3-64/SConstruct1
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi3-64/applications/SConscript2
-rw-r--r--bsp/raspberry-pi/raspi3-64/applications/main.c43
-rw-r--r--bsp/raspberry-pi/raspi3-64/applications/mnt.c28
-rw-r--r--bsp/raspberry-pi/raspi3-64/applications/test/gpio.h45
-rw-r--r--bsp/raspberry-pi/raspi3-64/applications/test/uart.c103
-rw-r--r--bsp/raspberry-pi/raspi3-64/applications/test/uart.h29
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/Kconfig116
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/SConscript23
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/board.c171
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/board.h17
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_fb.c314
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_fb.h26
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c320
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h43
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c238
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h43
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c137
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h26
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c588
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h253
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_spi.c287
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_spi.h102
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_timer.c159
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_timer.h24
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_uart.c182
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_uart.h42
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c140
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h26
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/mbox.c452
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/mbox.h125
-rw-r--r--bsp/raspberry-pi/raspi3-64/driver/raspi.h454
-rw-r--r--bsp/raspberry-pi/raspi3-64/link.lds141
-rwxr-xr-xbsp/raspberry-pi/raspi3-64/qemu-64.bat6
-rw-r--r--bsp/raspberry-pi/raspi3-64/qemu-64.sh4
-rwxr-xr-xbsp/raspberry-pi/raspi3-64/qemu.py74
-rw-r--r--bsp/raspberry-pi/raspi3-64/rtconfig.h251
-rw-r--r--bsp/raspberry-pi/raspi3-64/rtconfig.py11
-rw-r--r--bsp/raspberry-pi/raspi4-64/.config365
-rw-r--r--bsp/raspberry-pi/raspi4-64/Kconfig11
-rw-r--r--bsp/raspberry-pi/raspi4-64/README.md2
-rw-r--r--bsp/raspberry-pi/raspi4-64/SConscript2
-rw-r--r--bsp/raspberry-pi/raspi4-64/SConstruct11
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi4-64/applications/SConscript0
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi4-64/applications/main.c2
-rw-r--r--bsp/raspberry-pi/raspi4-64/applications/mnt.c40
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/Kconfig139
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/SConscript19
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/board.c223
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/board.h22
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c243
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c714
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h225
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c439
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h140
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c74
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c353
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h27
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c651
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h253
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c296
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h87
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c418
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h108
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c135
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h25
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/mbox.c516
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/mbox.h180
-rw-r--r--bsp/raspberry-pi/raspi4-64/drivers/raspi4.h200
-rwxr-xr-xbsp/raspberry-pi/raspi4-64/qemu.py70
-rw-r--r--bsp/raspberry-pi/raspi4-64/rtconfig.h206
-rw-r--r--bsp/raspberry-pi/raspi4-64/rtconfig.py14
-rw-r--r--bsp/raspberry-pi/raspi5/.config (renamed from bsp/raspberry-pi/raspi-dm2.0/.config)507
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi5/Kconfig (renamed from bsp/raspberry-pi/raspi-dm2.0/Kconfig)11
-rw-r--r--bsp/raspberry-pi/raspi5/README.md217
-rw-r--r--bsp/raspberry-pi/raspi5/README_en.md217
-rwxr-xr-xbsp/raspberry-pi/raspi5/SConscript17
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi5/SConstruct (renamed from bsp/raspberry-pi/raspi-dm2.0/SConstruct)11
-rwxr-xr-xbsp/raspberry-pi/raspi5/applications/SConscript9
-rw-r--r--bsp/raspberry-pi/raspi5/applications/main.c18
-rwxr-xr-xbsp/raspberry-pi/raspi5/drivers/SConscript12
-rwxr-xr-xbsp/raspberry-pi/raspi5/drivers/board.c116
-rwxr-xr-xbsp/raspberry-pi/raspi5/drivers/board.h16
-rwxr-xr-x[-rw-r--r--]bsp/raspberry-pi/raspi5/rtconfig.h (renamed from bsp/raspberry-pi/raspi-dm2.0/rtconfig.h)308
-rwxr-xr-xbsp/raspberry-pi/raspi5/rtconfig.py88
-rw-r--r--bsp/raspberry-pi/raspi5/tools/config.txt2
-rw-r--r--bsp/raspberry-pi/tools/sdk_dist.py30
261 files changed, 34580 insertions, 17565 deletions
diff --git a/bsp/raspberry-pi/.gitignore b/bsp/raspberry-pi/.gitignore
new file mode 100644
index 0000000000..b2033bca9f
--- /dev/null
+++ b/bsp/raspberry-pi/.gitignore
@@ -0,0 +1,8 @@
+kernel*.img
+rtthread.bin
+*.dtb
+*.qcow2
+flash.bin
+rtt.asm
+rtthread.map
+build/
diff --git a/bsp/raspberry-pi/dm/Kconfig b/bsp/raspberry-pi/dm/Kconfig
new file mode 100755
index 0000000000..2bb0202a03
--- /dev/null
+++ b/bsp/raspberry-pi/dm/Kconfig
@@ -0,0 +1,33 @@
+SOC_DM_ADC_DIR = $(SOC_DM_DIR)/adc
+SOC_DM_AUDIO_DIR = $(SOC_DM_DIR)/audio
+SOC_DM_CLK_DIR = $(SOC_DM_DIR)/clk
+SOC_DM_DMA_DIR = $(SOC_DM_DIR)/dma
+SOC_DM_DVFS_CPUFREQ_DIR = $(SOC_DM_DIR)/dvfs
+SOC_DM_ETHERNET_DIR = $(SOC_DM_DIR)/ethernet
+SOC_DM_FIRMWARE_DIR = $(SOC_DM_DIR)/firmware
+SOC_DM_GRAPHIC_BACKLIGHT_DIR = $(SOC_DM_DIR)/graphic/backlight
+SOC_DM_GRAPHIC_FB_DIR = $(SOC_DM_DIR)/graphic/framebuffer
+SOC_DM_GRAPHIC_LOGO_DIR = $(SOC_DM_DIR)/graphic/logo
+SOC_DM_HWCRYPTO_DIR = $(SOC_DM_DIR)/hwcrypto
+SOC_DM_CLOCK_TIME_DIR = $(SOC_DM_DIR)/clock_time
+SOC_DM_I2C_DIR = $(SOC_DM_DIR)/i2c
+SOC_DM_INPUT_JOYSTICK_DIR = $(SOC_DM_DIR)/input/joystick
+SOC_DM_INPUT_TOUCHSCREEN_DIR = $(SOC_DM_DIR)/input/touchscreen
+SOC_DM_MBOX_DIR = $(SOC_DM_DIR)/mailbox
+SOC_DM_MFD_DIR = $(SOC_DM_DIR)/mfd
+SOC_DM_NVMEM_DIR = $(SOC_DM_DIR)/nvmem
+SOC_DM_PCI_DIR = $(SOC_DM_DIR)/pci
+SOC_DM_PHY_DIR = $(SOC_DM_DIR)/phy
+SOC_DM_PIC_DIR = $(SOC_DM_DIR)/pic
+SOC_DM_PIN_DIR = $(SOC_DM_DIR)/pin
+SOC_DM_PINCTRL_DIR = $(SOC_DM_DIR)/pinctrl
+SOC_DM_PMDOMAIN_DIR = $(SOC_DM_DIR)/pmdomain
+SOC_DM_PWM_DIR = $(SOC_DM_DIR)/pwm
+SOC_DM_RESET_DIR = $(SOC_DM_DIR)/reset
+SOC_DM_RTC_DIR = $(SOC_DM_DIR)/rtc
+SOC_DM_SDIO_DIR = $(SOC_DM_DIR)/sdio
+SOC_DM_SERIAL_DIR = $(SOC_DM_DIR)/serial
+SOC_DM_SOC_DIR = $(SOC_DM_DIR)/soc
+SOC_DM_SPI_DIR = $(SOC_DM_DIR)/spi
+SOC_DM_THERMAL_DIR = $(SOC_DM_DIR)/thermal
+SOC_DM_WDT_DIR = $(SOC_DM_DIR)/watchdog
diff --git a/bsp/raspberry-pi/raspi-dm2.0/SConscript b/bsp/raspberry-pi/dm/SConscript
index c7ef7659ec..3d15055d62 100644..100755
--- a/bsp/raspberry-pi/raspi-dm2.0/SConscript
+++ b/bsp/raspberry-pi/dm/SConscript
@@ -1,4 +1,3 @@
-# for module compiling
import os
from building import *
diff --git a/bsp/raspberry-pi/dm/adc/Kconfig b/bsp/raspberry-pi/dm/adc/Kconfig
new file mode 100755
index 0000000000..69c057cf88
--- /dev/null
+++ b/bsp/raspberry-pi/dm/adc/Kconfig
@@ -0,0 +1,6 @@
+config RT_ADC_RP1
+ bool "RP1 ADC and temperature sensor driver"
+ depends on RT_USING_DM
+ depends on RT_USING_ADC
+ depends on RT_USING_REGULATOR
+ default n
diff --git a/bsp/raspberry-pi/dm/adc/SConscript b/bsp/raspberry-pi/dm/adc/SConscript
new file mode 100755
index 0000000000..b8fe67491c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/adc/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_ADC_RP1']):
+ src += ['adc-rp1.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/adc/adc-rp1.c b/bsp/raspberry-pi/dm/adc/adc-rp1.c
new file mode 100755
index 0000000000..d85d9a602c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/adc/adc-rp1.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define RP1_ADC_CS 0x00
+#define RP1_ADC_RESULT 0x04
+#define RP1_ADC_FCS 0x08
+#define RP1_ADC_FIFO 0x0c
+#define RP1_ADC_DIV 0x10
+
+#define RP1_ADC_INTR 0x14
+#define RP1_ADC_INTE 0x18
+#define RP1_ADC_INTF 0x1c
+#define RP1_ADC_INTS 0x20
+
+#define RP1_ADC_RWTYPE_SET 0x2000
+#define RP1_ADC_RWTYPE_CLR 0x3000
+
+#define RP1_ADC_CS_RROBIN_MASK 0x1f
+#define RP1_ADC_CS_RROBIN_SHIFT 16
+#define RP1_ADC_CS_AINSEL_MASK 0x7
+#define RP1_ADC_CS_AINSEL_SHIFT 12
+#define RP1_ADC_CS_ERR_STICKY 0x400
+#define RP1_ADC_CS_ERR 0x200
+#define RP1_ADC_CS_READY 0x100
+#define RP1_ADC_CS_START_MANY 0x8
+#define RP1_ADC_CS_START_ONCE 0x4
+#define RP1_ADC_CS_TS_EN 0x2
+#define RP1_ADC_CS_EN 0x1
+
+#define RP1_ADC_FCS_THRESH_MASK 0xf
+#define RP1_ADC_FCS_THRESH_SHIFT 24
+#define RP1_ADC_FCS_LEVEL_MASK 0xf
+#define RP1_ADC_FCS_LEVEL_SHIFT 16
+#define RP1_ADC_FCS_OVER 0x800
+#define RP1_ADC_FCS_UNDER 0x400
+#define RP1_ADC_FCS_FULL 0x200
+#define RP1_ADC_FCS_EMPTY 0x100
+#define RP1_ADC_FCS_DREQ_EN 0x8
+#define RP1_ADC_FCS_ERR 0x4
+#define RP1_ADC_FCS_SHIFR 0x2
+#define RP1_ADC_FCS_EN 0x1
+
+#define RP1_ADC_FIFO_ERR 0x8000
+#define RP1_ADC_FIFO_VAL_MASK 0xfff
+
+#define RP1_ADC_DIV_INT_MASK 0xffff
+#define RP1_ADC_DIV_INT_SHIFT 8
+#define RP1_ADC_DIV_FRAC_MASK 0xff
+#define RP1_ADC_DIV_FRAC_SHIFT 0
+
+enum
+{
+ RP1_ADC_IN,
+ RP1_ADC_RAW,
+ RP1_ADC_TEMP,
+};
+
+struct rp1_adc_channel
+{
+ rt_uint32_t type;
+
+ const char *name;
+};
+
+struct rp1_adc
+{
+ struct rt_adc_device parent;
+
+ void *regs;
+ int vref_mv;
+
+ struct rt_clk *clk;
+ struct rt_regulator *vref;
+
+ rt_size_t channel_nr;
+ struct rp1_adc_channel *channel;
+
+ struct rt_spinlock lock;
+};
+
+#define raw_to_rp1_adc(raw) rt_container_of(raw, struct rp1_adc, parent)
+
+static rt_err_t rp1_adc_ready_wait(struct rp1_adc *radc)
+{
+ int retries = 10;
+
+ while (retries && !(HWREG32(radc->regs + RP1_ADC_CS) & RP1_ADC_CS_READY))
+ {
+ --retries;
+ }
+
+ return retries ? 0 : -RT_EIO;
+}
+
+static rt_err_t rp1_adc_read(struct rp1_adc *radc, int channel, rt_uint32_t *val)
+{
+ rt_err_t err;
+
+ rt_hw_spin_lock(&radc->lock.lock);
+
+ HWREG32(radc->regs + RP1_ADC_RWTYPE_CLR + RP1_ADC_CS) =
+ RP1_ADC_CS_AINSEL_MASK << RP1_ADC_CS_AINSEL_SHIFT;
+ HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) =
+ channel << RP1_ADC_CS_AINSEL_SHIFT;
+ HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) =
+ RP1_ADC_CS_START_ONCE;
+
+ if ((err = rp1_adc_ready_wait(radc)))
+ {
+ goto _out_lock;
+ }
+
+ /* Asserted if the completed conversion had a convergence error */
+ if (HWREG32(radc->regs + RP1_ADC_CS) & RP1_ADC_CS_ERR)
+ {
+ err = -RT_EIO;
+ goto _out_lock;
+ }
+
+ *val = HWREG32(radc->regs + RP1_ADC_RESULT);
+
+_out_lock:
+ rt_hw_spin_unlock(&radc->lock.lock);
+
+ return err;
+}
+
+static int rp1_adc_to_mv(struct rp1_adc *radc, rt_uint32_t val)
+{
+ return ((rt_uint64_t)radc->vref_mv * val) / 0xfff;
+}
+
+static struct rp1_adc_channel adc_channel[] =
+{
+ { .type = RP1_ADC_IN, .name = "in1-input" },
+ { .type = RP1_ADC_IN, .name = "in2-input" },
+ { .type = RP1_ADC_IN, .name = "in3-input" },
+ { .type = RP1_ADC_IN, .name = "in4-input" },
+ { .type = RP1_ADC_TEMP, .name = "temp1-input" },
+ { .type = RP1_ADC_RAW, .name = "in1-raw" },
+ { .type = RP1_ADC_RAW, .name = "in2-raw" },
+ { .type = RP1_ADC_RAW, .name = "in3-raw" },
+ { .type = RP1_ADC_RAW, .name = "in4-raw" },
+ { .type = RP1_ADC_RAW, .name = "temp1-raw" },
+};
+
+static rt_err_t rp1_adc_enabled(struct rt_adc_device *adc, rt_int8_t channel, rt_bool_t enabled)
+{
+ return RT_EOK;
+}
+
+static rt_err_t rp1_adc_convert(struct rt_adc_device *adc, rt_int8_t channel, rt_uint32_t *value)
+{
+ rt_err_t err;
+ rt_uint32_t val;
+ struct rp1_adc_channel *chan;
+ struct rp1_adc *radc = raw_to_rp1_adc(adc);
+
+ if (channel >= radc->channel_nr)
+ {
+ return -RT_EINVAL;
+ }
+
+ chan = &radc->channel[channel];
+
+ if (chan->type == RP1_ADC_TEMP)
+ {
+ int mv;
+
+ HWREG32(radc->regs + RP1_ADC_RWTYPE_SET + RP1_ADC_CS) = RP1_ADC_CS_TS_EN;
+
+ if ((err = rp1_adc_read(radc, channel, &val)))
+ {
+ return err;
+ }
+
+ mv = rp1_adc_to_mv(radc, val);
+
+ /* T = 27 - (ADC_voltage - 0.706)/0.001721 */
+
+ *value = 27000 - RT_DIV_ROUND_CLOSEST((mv - 706) * (rt_int64_t)1000000, 1721);
+ }
+ else if (chan->type == RP1_ADC_IN || chan->type == RP1_ADC_RAW)
+ {
+ if ((err = rp1_adc_read(radc, channel, &val)))
+ {
+ return err;
+ }
+
+ *value = val;
+ }
+
+ return RT_EOK;
+}
+
+static const struct rt_adc_ops rp1_adc_ops =
+{
+ .enabled = rp1_adc_enabled,
+ .convert = rp1_adc_convert,
+};
+
+static void rp1_adc_free(struct rp1_adc *radc)
+{
+ if (radc->regs)
+ {
+ rt_iounmap(radc->regs);
+ }
+
+ if (!rt_is_err_or_null(radc->clk))
+ {
+ rt_clk_disable_unprepare(radc->clk);
+ rt_clk_put(radc->clk);
+ }
+
+ rt_free(radc);
+}
+
+static rt_err_t rp1_adc_probe(struct rt_platform_device *pdev)
+{
+ int vref_uv;
+ rt_err_t err;
+ const char *dev_name;
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_adc *radc = rt_calloc(1, sizeof(*radc));
+
+ if (!radc)
+ {
+ return -RT_ENOMEM;
+ }
+
+ radc->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!radc->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ radc->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(radc->clk))
+ {
+ err = rt_ptr_err(radc->clk);
+ goto _fail;
+ }
+
+ rt_clk_set_rate(radc->clk, 50000000);
+ rt_clk_prepare_enable(radc->clk);
+
+ radc->vref = rt_regulator_get(dev, "vref");
+
+ if (rt_is_err(radc->vref))
+ {
+ err = rt_ptr_err(radc->vref);
+ goto _fail;
+ }
+
+ vref_uv = rt_regulator_get_voltage(radc->vref);
+ radc->vref_mv = RT_DIV_ROUND_CLOSEST(vref_uv, 1000);
+
+ radc->channel_nr = RT_ARRAY_SIZE(adc_channel);
+ radc->channel = adc_channel;
+
+ rt_spin_lock_init(&radc->lock);
+
+ dev->user_data = radc;
+
+ rt_dm_dev_set_name_auto(&radc->parent.parent, "adc");
+ dev_name = rt_dm_dev_get_name(&radc->parent.parent);
+
+ rt_hw_adc_register(&radc->parent, dev_name, &rp1_adc_ops, radc);
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, radc);
+
+ /* Disable interrupts */
+ HWREG32(radc->regs + RP1_ADC_INTE) = 0;
+
+ /* Enable the block, clearing any sticky error */
+ HWREG32(radc->regs + RP1_ADC_CS) = RP1_ADC_CS_EN | RP1_ADC_CS_ERR_STICKY;
+
+ return RT_EOK;
+
+_fail:
+ rp1_adc_free(radc);
+
+ return err;
+}
+
+static rt_err_t rp1_adc_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_adc *radc = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ rt_device_unregister(&radc->parent.parent);
+
+ rp1_adc_free(radc);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rp1_adc_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rp1-adc" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rp1_adc_driver =
+{
+ .name = "rp1-adc",
+ .ids = rp1_adc_ofw_ids,
+
+ .probe = rp1_adc_probe,
+ .remove = rp1_adc_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rp1_adc_driver);
diff --git a/bsp/raspberry-pi/dm/audio/Kconfig b/bsp/raspberry-pi/dm/audio/Kconfig
new file mode 100755
index 0000000000..68ea51b350
--- /dev/null
+++ b/bsp/raspberry-pi/dm/audio/Kconfig
@@ -0,0 +1,4 @@
+config RT_AUDIO_BCM2835_I2S
+ bool "Broadcom BCM2835 I2S"
+ depends on RT_USING_DMA
+ default n
diff --git a/bsp/raspberry-pi/dm/audio/SConscript b/bsp/raspberry-pi/dm/audio/SConscript
new file mode 100755
index 0000000000..591d525124
--- /dev/null
+++ b/bsp/raspberry-pi/dm/audio/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_AUDIO_BCM2835_I2S']):
+ src += ['bcm2835-i2s.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/audio/bcm2835-i2s.c b/bsp/raspberry-pi/dm/audio/bcm2835-i2s.c
new file mode 100755
index 0000000000..7b9e948654
--- /dev/null
+++ b/bsp/raspberry-pi/dm/audio/bcm2835-i2s.c
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "audio.bcm2835-i2s"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+/* I2S registers */
+#define BCM2835_I2S_CS_A_REG 0x00
+#define BCM2835_I2S_FIFO_A_REG 0x04
+#define BCM2835_I2S_MODE_A_REG 0x08
+#define BCM2835_I2S_RXC_A_REG 0x0c
+#define BCM2835_I2S_TXC_A_REG 0x10
+#define BCM2835_I2S_DREQ_A_REG 0x14
+#define BCM2835_I2S_INTEN_A_REG 0x18
+#define BCM2835_I2S_INTSTC_A_REG 0x1c
+#define BCM2835_I2S_GRAY_REG 0x20
+
+/* I2S register settings */
+#define BCM2835_I2S_STBY RT_BIT(25)
+#define BCM2835_I2S_SYNC RT_BIT(24)
+#define BCM2835_I2S_RXSEX RT_BIT(23)
+#define BCM2835_I2S_RXF RT_BIT(22)
+#define BCM2835_I2S_TXE RT_BIT(21)
+#define BCM2835_I2S_RXD RT_BIT(20)
+#define BCM2835_I2S_TXD RT_BIT(19)
+#define BCM2835_I2S_RXR RT_BIT(18)
+#define BCM2835_I2S_TXW RT_BIT(17)
+#define BCM2835_I2S_CS_RXERR RT_BIT(16)
+#define BCM2835_I2S_CS_TXERR RT_BIT(15)
+#define BCM2835_I2S_RXSYNC RT_BIT(14)
+#define BCM2835_I2S_TXSYNC RT_BIT(13)
+#define BCM2835_I2S_DMAEN RT_BIT(9)
+#define BCM2835_I2S_RXTHR(v) ((v) << 7)
+#define BCM2835_I2S_TXTHR(v) ((v) << 5)
+#define BCM2835_I2S_RXCLR RT_BIT(4)
+#define BCM2835_I2S_TXCLR RT_BIT(3)
+#define BCM2835_I2S_TXON RT_BIT(2)
+#define BCM2835_I2S_RXON RT_BIT(1)
+#define BCM2835_I2S_EN (1)
+
+#define BCM2835_I2S_CLKDIS RT_BIT(28)
+#define BCM2835_I2S_PDMN RT_BIT(27)
+#define BCM2835_I2S_PDME RT_BIT(26)
+#define BCM2835_I2S_FRXP RT_BIT(25)
+#define BCM2835_I2S_FTXP RT_BIT(24)
+#define BCM2835_I2S_CLKM RT_BIT(23)
+#define BCM2835_I2S_CLKI RT_BIT(22)
+#define BCM2835_I2S_FSM RT_BIT(21)
+#define BCM2835_I2S_FSI RT_BIT(20)
+#define BCM2835_I2S_FLEN(v) ((v) << 10)
+#define BCM2835_I2S_FSLEN(v) (v)
+
+#define BCM2835_I2S_CHWEX RT_BIT(15)
+#define BCM2835_I2S_CHEN RT_BIT(14)
+#define BCM2835_I2S_CHPOS(v) ((v) << 4)
+#define BCM2835_I2S_CHWID(v) (v)
+#define BCM2835_I2S_CH1(v) ((v) << 16)
+#define BCM2835_I2S_CH2(v) (v)
+#define BCM2835_I2S_CH1_POS(v) BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(v))
+#define BCM2835_I2S_CH2_POS(v) BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(v))
+
+#define BCM2835_I2S_TX_PANIC(v) ((v) << 24)
+#define BCM2835_I2S_RX_PANIC(v) ((v) << 16)
+#define BCM2835_I2S_TX(v) ((v) << 8)
+#define BCM2835_I2S_RX(v) (v)
+
+#define BCM2835_I2S_INT_RXERR RT_BIT(3)
+#define BCM2835_I2S_INT_TXERR RT_BIT(2)
+#define BCM2835_I2S_INT_RXR RT_BIT(1)
+#define BCM2835_I2S_INT_TXW RT_BIT(0)
+
+#define BCM2835_I2S_MAX_FRAME_LENGTH 1024 /* Frame length register is 10 bit, maximum length 1024 */
+#define BCM2835_I2S_MAX_FIFO_LENGTH (64 * 32) /* 64 * 32 bit TX/RX FIFO */
+
+struct bcm2835_i2s
+{
+ struct rt_audio_device parent;
+ struct rt_audio_configure audio_config;
+ struct rt_device *dev;
+
+ void *regs;
+ struct rt_clk *clk;
+ rt_bool_t clk_prepared;
+ rt_bool_t hifi_hat;
+
+ void *playback_buf;
+ void *capture_buf;
+ rt_ubase_t playback_dma;
+ rt_ubase_t capture_dma;
+
+ rt_ubase_t fifo_dma;
+ struct rt_dma_chan *dma_rx;
+ struct rt_dma_chan *dma_tx;
+};
+
+#define raw_to_bcm2835_i2s(raw) rt_container_of(raw, struct bcm2835_i2s, parent)
+
+static void bcm2835_i2s_start_clock(struct bcm2835_i2s *i2s)
+{
+ if (i2s->clk_prepared)
+ {
+ return;
+ }
+
+ rt_clk_prepare_enable(i2s->clk);
+ i2s->clk_prepared = RT_TRUE;
+}
+
+static void bcm2835_i2s_stop_clock(struct bcm2835_i2s *i2s)
+{
+ if (i2s->clk_prepared)
+ {
+ rt_clk_disable_unprepare(i2s->clk);
+ }
+
+ i2s->clk_prepared = RT_FALSE;
+}
+
+static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s *i2s, rt_bool_t tx, rt_bool_t rx)
+{
+ int timeout = 1000;
+ rt_bool_t clk_was_prepared;
+ rt_uint32_t syncval, csreg, i2s_active_state, off, clr;
+
+ off = (tx ? BCM2835_I2S_TXON : 0) | (rx ? BCM2835_I2S_RXON : 0);
+ clr = (tx ? BCM2835_I2S_TXCLR : 0) | (rx ? BCM2835_I2S_RXCLR : 0);
+
+ /* Backup the current state */
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON);
+
+ /* Start clock if not running */
+ if (!(clk_was_prepared = i2s->clk_prepared))
+ {
+ bcm2835_i2s_start_clock(i2s);
+ }
+
+ /* Stop I2S module */
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~off;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg;
+
+ /* Clear the FIFOs, Requires at least 2 PCM clock cycles to take effect */
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~clr;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | clr;
+
+ /* Wait for 2 PCM clock cycles */
+
+ /* Toggle the SYNC flag. After 2 PCM clock cycles it can be read back */
+ syncval = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) & BCM2835_I2S_SYNC;
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~BCM2835_I2S_SYNC;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | ~syncval;
+
+ /* Wait for the SYNC flag changing it's state */
+ while (--timeout)
+ {
+ if ((HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) & BCM2835_I2S_SYNC) != syncval)
+ {
+ break;
+ }
+ }
+
+ if (!timeout)
+ {
+ LOG_E("%s: sync error", rt_dm_dev_get_name(&i2s->parent.parent));
+ }
+
+ /* Stop clock if it was not running before */
+ if (!clk_was_prepared)
+ {
+ bcm2835_i2s_stop_clock(i2s);
+ }
+
+ /* Restore I2S state */
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~(BCM2835_I2S_RXON | BCM2835_I2S_TXON);
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | i2s_active_state;
+}
+
+static rt_err_t bcm2835_i2s_audio_getcaps(struct rt_audio_device *audio,
+ struct rt_audio_caps *caps)
+{
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ switch (caps->main_type)
+ {
+ case AUDIO_TYPE_QUERY:
+ i2s->hifi_hat = caps->udata.value > 0;
+
+ switch (caps->sub_type)
+ {
+ case AUDIO_TYPE_QUERY:
+ caps->udata.mask = AUDIO_TYPE_OUTPUT | AUDIO_TYPE_MIXER;
+ break;
+
+ default:
+ return -RT_ENOSYS;
+ }
+ break;
+
+ case AUDIO_TYPE_OUTPUT:
+ case AUDIO_TYPE_INPUT:
+ switch(caps->sub_type)
+ {
+ case AUDIO_DSP_PARAM:
+ caps->udata.config.channels = i2s->audio_config.channels;
+ caps->udata.config.samplebits = i2s->audio_config.samplebits;
+ caps->udata.config.samplerate = i2s->audio_config.samplerate;
+ break;
+
+ case AUDIO_DSP_SAMPLERATE:
+ caps->udata.config.samplerate = i2s->audio_config.samplerate;
+ break;
+
+ case AUDIO_DSP_CHANNELS:
+ caps->udata.config.channels = i2s->audio_config.channels;
+ break;
+
+ case AUDIO_DSP_SAMPLEBITS:
+ caps->udata.config.samplebits = i2s->audio_config.samplebits;
+ break;
+
+ default:
+ return -RT_ENOSYS;
+ }
+ break;
+
+ default:
+ return -RT_ENOSYS;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_i2s_audio_configure(struct rt_audio_device *audio,
+ struct rt_audio_caps *caps)
+{
+ rt_uint32_t csreg, value, frame_length;
+ struct rt_audio_configure audio_config;
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+
+ if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON))
+ {
+ return -RT_EBUSY;
+ }
+
+ rt_memcpy(&audio_config, &i2s->audio_config, sizeof(audio_config));
+
+ switch (caps->main_type)
+ {
+ case AUDIO_TYPE_OUTPUT:
+ case AUDIO_TYPE_INPUT:
+ switch (caps->sub_type)
+ {
+ case AUDIO_DSP_PARAM:
+ audio_config.channels = caps->udata.config.channels;
+ audio_config.samplebits = caps->udata.config.samplebits;
+ audio_config.samplerate = caps->udata.config.samplerate;
+ break;
+
+ case AUDIO_DSP_SAMPLERATE:
+ audio_config.samplerate = caps->udata.config.samplerate;
+ break;
+
+ case AUDIO_DSP_CHANNELS:
+ audio_config.channels = caps->udata.config.channels;
+ break;
+
+ case AUDIO_DSP_SAMPLEBITS:
+ audio_config.samplebits = caps->udata.config.samplebits;
+ break;
+
+ default:
+ return -RT_ENOSYS;
+ }
+ break;
+
+ default:
+ return -RT_ENOSYS;
+ }
+
+ if (audio_config.channels > 2)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (audio_config.samplerate < 8000 || audio_config.samplerate > 384000)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (audio_config.samplebits != 16 &&
+ audio_config.samplebits != 24 &&
+ audio_config.samplebits != 32)
+ {
+ return -RT_EINVAL;
+ }
+
+ rt_memcpy(&i2s->audio_config, &audio_config, sizeof(audio_config));
+
+ if (i2s->hifi_hat)
+ {
+ /* Clock setting */
+ bcm2835_i2s_stop_clock(i2s);
+
+ rt_clk_set_rate(i2s->clk, audio_config.samplerate);
+
+ bcm2835_i2s_start_clock(i2s);
+ }
+
+ /* Setup the frame format */
+ value = BCM2835_I2S_CHEN;
+
+ if (audio_config.samplebits >= 24)
+ {
+ value |= BCM2835_I2S_CHWEX;
+ }
+
+ value |= BCM2835_I2S_CHWID((audio_config.samplebits - 8) & 0xf);
+ /* CH2 format is the same as for CH1 */
+ value = BCM2835_I2S_CH1(value) | BCM2835_I2S_CH2(value);
+
+ HWREG32(i2s->regs + BCM2835_I2S_RXC_A_REG) = value |
+ BCM2835_I2S_CH1_POS(1) | BCM2835_I2S_CH2_POS(33);
+ HWREG32(i2s->regs + BCM2835_I2S_TXC_A_REG) = value |
+ BCM2835_I2S_CH1_POS(1) | BCM2835_I2S_CH2_POS(33);
+
+ /* Setup the I2S mode */
+ value = 0;
+ frame_length = audio_config.channels * audio_config.samplebits;
+
+ if (audio_config.samplebits <= 16)
+ {
+ /* Use frame packed mode (2 channels per 32 bit word) */
+ value |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
+ }
+
+ value |= BCM2835_I2S_FLEN(frame_length - 1);
+ value |= BCM2835_I2S_FSLEN(frame_length / 2);
+
+ if (!i2s->hifi_hat)
+ {
+ value |= BCM2835_I2S_CLKM | BCM2835_I2S_CLKI | BCM2835_I2S_FSM;
+ }
+
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = value;
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~(BCM2835_I2S_RXTHR(1) | BCM2835_I2S_TXTHR(1) | BCM2835_I2S_DMAEN);
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | 0xffffffff;
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~(BCM2835_I2S_TX_PANIC(0x10) | BCM2835_I2S_RX_PANIC(0x30) |
+ BCM2835_I2S_TX(0x30) | BCM2835_I2S_RX(0x20));
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | 0xffffffff;
+
+ bcm2835_i2s_clear_fifos(i2s, RT_TRUE, RT_TRUE);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_i2s_audio_init(struct rt_audio_device *audio)
+{
+ rt_uint32_t csreg;
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ i2s->audio_config.samplerate = 8000; /* 8000 ~ 384000 */
+ i2s->audio_config.samplebits = 16; /* 16/24/32 */
+ i2s->audio_config.channels = 2;
+
+ bcm2835_i2s_stop_clock(i2s);
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~BCM2835_I2S_EN;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | BCM2835_I2S_EN;
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~BCM2835_I2S_STBY;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | BCM2835_I2S_STBY;
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_i2s_audio_start(struct rt_audio_device *audio, int stream)
+{
+ rt_uint32_t csreg, mask;
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ bcm2835_i2s_start_clock(i2s);
+
+ if (stream == AUDIO_STREAM_RECORD)
+ {
+ mask = BCM2835_I2S_RXON;
+ }
+ else if (stream == AUDIO_STREAM_REPLAY)
+ {
+ mask = BCM2835_I2S_TXON;
+ }
+ else
+ {
+ return -RT_EINVAL;
+ }
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~mask;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg | mask;
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_i2s_audio_stop(struct rt_audio_device *audio, int stream)
+{
+ rt_uint32_t csreg, mask;
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ if (stream == AUDIO_STREAM_RECORD)
+ {
+ mask = BCM2835_I2S_RXON;
+ }
+ else if (stream == AUDIO_STREAM_REPLAY)
+ {
+ mask = BCM2835_I2S_TXON;
+ }
+ else
+ {
+ return -RT_EINVAL;
+ }
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~mask;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg;
+
+ bcm2835_i2s_stop_clock(i2s);
+
+ return RT_EOK;
+}
+
+static rt_ssize_t bcm2835_i2s_audio_transmit(struct rt_audio_device *audio,
+ const void *write_buf, void *read_buf, rt_size_t size)
+{
+ rt_err_t err;
+ struct rt_dma_chan *chan;
+ struct rt_dma_slave_config config;
+ struct rt_dma_slave_transfer transfer;
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ rt_memset(&config, 0, sizeof(config));
+
+ if (write_buf)
+ {
+ config.dst_addr_width = RT_DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.dst_maxburst = 2;
+
+ config.direction = RT_DMA_MEM_TO_DEV;
+ config.src_addr = (write_buf - i2s->playback_buf) + i2s->playback_dma;
+ config.dst_addr = i2s->fifo_dma;
+
+ chan = i2s->dma_tx;
+ }
+ else if (read_buf)
+ {
+ config.src_addr_width = RT_DMA_SLAVE_BUSWIDTH_4_BYTES;
+ config.src_maxburst = 2;
+
+ config.direction = RT_DMA_DEV_TO_MEM;
+ config.src_addr = i2s->fifo_dma;
+ config.dst_addr = i2s->capture_dma;
+
+ chan = i2s->dma_rx;
+ }
+ else
+ {
+ return -RT_EINVAL;
+ }
+
+ if ((err = rt_dma_chan_config(chan, &config)))
+ {
+ LOG_E("Config DMA error = %s", rt_strerror(err));
+ return err;
+ }
+
+ rt_memset(&transfer, 0, sizeof(transfer));
+ transfer.buffer_len = size;
+ transfer.src_addr = config.src_addr;
+ transfer.dst_addr = config.dst_addr;
+ transfer.period_len = BCM2835_I2S_MAX_FRAME_LENGTH;
+
+ if (chan == i2s->dma_rx)
+ {
+ transfer.buffer = read_buf;
+ }
+
+ if ((err = rt_dma_prep_cyclic(chan, &transfer)))
+ {
+ LOG_E("Prepare DMA error = %s", rt_strerror(err));
+ return err;
+ }
+
+ if ((err = rt_dma_chan_start(chan)))
+ {
+ LOG_E("Start DMA error = %s", rt_strerror(err));
+ return err;
+ }
+
+ return size;
+}
+
+static void bcm2835_i2s_audio_buffer_info(struct rt_audio_device *audio,
+ struct rt_audio_buf_info *info)
+{
+ struct bcm2835_i2s *i2s = raw_to_bcm2835_i2s(audio);
+
+ info->buffer = i2s->playback_buf;
+ info->total_size = BCM2835_I2S_MAX_FIFO_LENGTH;
+ info->block_size = BCM2835_I2S_MAX_FRAME_LENGTH;
+ info->block_count = BCM2835_I2S_MAX_FIFO_LENGTH / BCM2835_I2S_MAX_FRAME_LENGTH;
+}
+
+const static struct rt_audio_ops bcm2835_i2s_audio_ops =
+{
+ .getcaps = bcm2835_i2s_audio_getcaps,
+ .configure = bcm2835_i2s_audio_configure,
+ .init = bcm2835_i2s_audio_init,
+ .start = bcm2835_i2s_audio_start,
+ .stop = bcm2835_i2s_audio_stop,
+ .transmit = bcm2835_i2s_audio_transmit,
+ .buffer_info = bcm2835_i2s_audio_buffer_info,
+};
+
+static void bcm2835_i2s_dma_rx_done(struct rt_dma_chan *chan, rt_size_t size)
+{
+ void *buffer;
+ struct bcm2835_i2s *i2s = chan->priv;
+
+ buffer = chan->transfer.buffer;
+ chan->transfer.buffer += size;
+
+ rt_memcpy(buffer, i2s->capture_buf, size);
+ rt_audio_rx_done(&i2s->parent, buffer, size);
+}
+
+static void bcm2835_i2s_dma_tx_done(struct rt_dma_chan *chan, rt_size_t size)
+{
+ struct bcm2835_i2s *i2s = chan->priv;
+
+ rt_audio_tx_complete(&i2s->parent);
+}
+
+static void bcm2835_i2s_free(struct bcm2835_i2s *i2s)
+{
+ if (!rt_is_err_or_null(i2s->dma_rx))
+ {
+ rt_dma_chan_release(i2s->dma_rx);
+ }
+
+ if (!rt_is_err_or_null(i2s->dma_tx))
+ {
+ rt_dma_chan_release(i2s->dma_tx);
+ }
+
+ if (i2s->playback_buf)
+ {
+ rt_dma_free_coherent(i2s->dev, BCM2835_I2S_MAX_FIFO_LENGTH,
+ i2s->playback_buf, i2s->playback_dma);
+ }
+
+ if (i2s->capture_buf)
+ {
+ rt_dma_free_coherent(i2s->dev, BCM2835_I2S_MAX_FIFO_LENGTH,
+ i2s->capture_buf, i2s->capture_dma);
+ }
+
+ if (!rt_is_err_or_null(i2s->clk))
+ {
+ rt_clk_put(i2s->clk);
+ }
+
+ if (i2s->regs)
+ {
+ rt_iounmap(i2s->regs);
+ }
+
+ rt_free(i2s);
+}
+
+static rt_err_t bcm2835_i2s_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ const char *dev_name;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_i2s *i2s = rt_calloc(1, sizeof(*i2s));
+
+ if (!i2s)
+ {
+ return -RT_ENOMEM;
+ }
+
+ i2s->dev = dev;
+ i2s->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!i2s->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ i2s->playback_buf = rt_dma_alloc_coherent(dev,
+ BCM2835_I2S_MAX_FIFO_LENGTH, &i2s->playback_dma);
+
+ if (!i2s->playback_buf)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ i2s->capture_buf = rt_dma_alloc_coherent(dev,
+ BCM2835_I2S_MAX_FIFO_LENGTH, &i2s->capture_dma);
+
+ if (!i2s->capture_buf)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ i2s->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(i2s->clk))
+ {
+ err = rt_ptr_err(i2s->clk);
+ goto _fail;
+ }
+
+ i2s->dma_rx = rt_dma_chan_request(dev, "rx");
+
+ if (rt_is_err(i2s->dma_rx))
+ {
+ err = rt_ptr_err(i2s->clk);
+ goto _fail;
+ }
+
+ i2s->dma_tx = rt_dma_chan_request(dev, "tx");
+
+ if (rt_is_err(i2s->dma_tx))
+ {
+ err = rt_ptr_err(i2s->clk);
+ goto _fail;
+ }
+
+ i2s->dma_rx->callback = bcm2835_i2s_dma_rx_done;
+ i2s->dma_tx->callback = bcm2835_i2s_dma_tx_done;
+
+ i2s->dma_rx->priv = i2s;
+ i2s->dma_tx->priv = i2s;
+
+ i2s->fifo_dma = (rt_ubase_t)rt_kmem_v2p(i2s->regs) + BCM2835_I2S_FIFO_A_REG;
+
+ rt_dm_dev_set_name_auto(&i2s->parent.parent, "sound");
+ dev_name = rt_dm_dev_get_name(&i2s->parent.parent);
+
+ i2s->parent.ops = (struct rt_audio_ops *)&bcm2835_i2s_audio_ops;
+ if ((err = rt_audio_register(&i2s->parent, dev_name, RT_DEVICE_FLAG_RDWR, i2s)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = i2s;
+
+ return RT_EOK;
+
+_fail:
+ bcm2835_i2s_free(i2s);
+
+ return err;
+}
+
+static rt_err_t bcm2835_i2s_remove(struct rt_platform_device *pdev)
+{
+ rt_uint32_t csreg;
+ struct bcm2835_i2s *i2s = pdev->parent.user_data;
+
+ csreg = HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG);
+ csreg &= ~BCM2835_I2S_EN;
+ HWREG32(i2s->regs + BCM2835_I2S_CS_A_REG) = csreg;
+
+ bcm2835_i2s_stop_clock(i2s);
+
+ rt_device_unregister(&i2s->parent.parent);
+
+ bcm2835_i2s_free(i2s);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_i2s_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-i2s" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_i2s_driver =
+{
+ .name = "bcm2835-i2s",
+ .ids = bcm2835_i2s_ofw_ids,
+
+ .probe = bcm2835_i2s_probe,
+ .remove = bcm2835_i2s_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_i2s_driver);
diff --git a/bsp/raspberry-pi/dm/clk/Kconfig b/bsp/raspberry-pi/dm/clk/Kconfig
new file mode 100755
index 0000000000..443774e188
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/Kconfig
@@ -0,0 +1,19 @@
+config RT_CLK_BCM2711_DVP
+ bool "Broadcom BCM2711 DVP support"
+ depends on RT_USING_OFW
+ default n
+
+config RT_CLK_BCM2835
+ bool "Broadcom BCM2835 clock support"
+ depends on RT_USING_OFW
+ default n
+
+config RT_CLK_RASPBERRYPI
+ bool "Raspberry Pi firmware based clock support"
+ depends on RT_USING_OFW
+ default n
+
+config RT_CLK_RP1
+ bool "RP1 clock support"
+ depends on RT_USING_OFW
+ default n
diff --git a/bsp/raspberry-pi/dm/clk/SConscript b/bsp/raspberry-pi/dm/clk/SConscript
new file mode 100755
index 0000000000..630644edf3
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/SConscript
@@ -0,0 +1,22 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_CLK_BCM2711_DVP']):
+ src += ['clk-bcm2711-dvp.c']
+
+if GetDepend(['RT_CLK_BCM2835']):
+ src += ['clk-bcm2835-aux.c', 'clk-bcm2835.c', 'clk-dsi.c']
+
+if GetDepend(['RT_CLK_RASPBERRYPI']):
+ src += ['clk-raspberrypi.c']
+
+if GetDepend(['RT_CLK_RP1']):
+ src += ['clk-rp1.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/clk/clk-bcm2711-dvp.c b/bsp/raspberry-pi/dm/clk/clk-bcm2711-dvp.c
new file mode 100755
index 0000000000..eb357d8b72
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-bcm2711-dvp.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.bcm2711.dvp"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "../../reset/reset-simple.h"
+
+#define DVP_HT_RPI_SW_INIT 0x04
+#define DVP_HT_RPI_MISC_CONFIG 0x08
+
+struct bcm2711_dvp_clk
+{
+ struct rt_clk_node clk_parent;
+ struct reset_simple reset_parent;
+
+ void *regs;
+ struct rt_clk *clk;
+};
+
+#define raw_to_bcm2711_dvp_clk(raw) rt_container_of(raw, struct bcm2711_dvp_clk, clk_parent)
+
+struct dvp_clk_gate
+{
+ struct rt_clk_cell cell;
+
+ rt_uint8_t bit_idx;
+};
+
+#define raw_to_dvp_clk_gate(raw) rt_container_of(raw, struct dvp_clk_gate, cell)
+
+static void bcm2711_dvp_clk_endisable(struct rt_clk_cell *cell, int enable)
+{
+ rt_ubase_t level;
+ rt_uint32_t value;
+ int set = 1 ^ enable;
+ struct dvp_clk_gate *gate = raw_to_dvp_clk_gate(cell);
+ struct bcm2711_dvp_clk *dvp_clk = raw_to_bcm2711_dvp_clk(cell->clk_np);
+
+ level = rt_spin_lock_irqsave(&dvp_clk->reset_parent.lock);
+
+ value = HWREG32(dvp_clk->regs + DVP_HT_RPI_MISC_CONFIG);
+ if (set)
+ {
+ value |= RT_BIT(gate->bit_idx);
+ }
+ else
+ {
+ value &= ~RT_BIT(gate->bit_idx);
+ }
+ HWREG32(dvp_clk->regs + DVP_HT_RPI_MISC_CONFIG) = value;
+
+ rt_spin_unlock_irqrestore(&dvp_clk->reset_parent.lock, level);
+}
+
+static rt_err_t bcm2711_dvp_clk_enable(struct rt_clk_cell *cell)
+{
+ bcm2711_dvp_clk_endisable(cell, 1);
+
+ return RT_EOK;
+}
+
+static void bcm2711_dvp_clk_disable(struct rt_clk_cell *cell)
+{
+ bcm2711_dvp_clk_endisable(cell, 0);
+}
+
+static rt_bool_t bcm2711_dvp_clk_is_enabled(struct rt_clk_cell *cell)
+{
+ rt_uint32_t value;
+ struct dvp_clk_gate *gate = raw_to_dvp_clk_gate(cell);
+ struct bcm2711_dvp_clk *dvp_clk = raw_to_bcm2711_dvp_clk(cell->clk_np);
+
+ value = HWREG32(dvp_clk->regs + DVP_HT_RPI_MISC_CONFIG);
+ value ^= RT_BIT(gate->bit_idx);
+ value &= RT_BIT(gate->bit_idx);
+
+ return !!value;
+}
+
+static rt_ubase_t bcm2711_dvp_clk_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct bcm2711_dvp_clk *dvp_clk = raw_to_bcm2711_dvp_clk(cell->clk_np);
+
+ return rt_clk_cell_get_rate(dvp_clk->clk->cell);
+}
+
+const struct rt_clk_ops bcm2711_dvp_clk_ops =
+{
+ .enable = bcm2711_dvp_clk_enable,
+ .disable = bcm2711_dvp_clk_disable,
+ .is_enabled = bcm2711_dvp_clk_is_enabled,
+ .recalc_rate = bcm2711_dvp_clk_recalc_rate,
+};
+
+static struct dvp_clk_gate hdmi0_108mhz =
+{
+ .cell.name = "hdmi0-108MHz",
+ .cell.ops = &bcm2711_dvp_clk_ops,
+ .bit_idx = 3,
+};
+
+static struct dvp_clk_gate hdmi1_108mhz =
+{
+ .cell.name = "hdmi1-108MHz",
+ .cell.ops = &bcm2711_dvp_clk_ops,
+ .bit_idx = 4,
+};
+
+static struct rt_clk_cell *dvp_clk_cell[] =
+{
+ &hdmi0_108mhz.cell,
+ &hdmi1_108mhz.cell,
+};
+
+static rt_err_t bcm2711_dvp_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct reset_simple *rsts;
+ struct rt_reset_controller *rstcer;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2711_dvp_clk *dvp_clk = rt_calloc(1, sizeof(*dvp_clk));
+
+ if (!dvp_clk)
+ {
+ return -RT_ENOMEM;
+ }
+
+ dvp_clk->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!dvp_clk->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ dvp_clk->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(dvp_clk->clk))
+ {
+ err = rt_ptr_err(dvp_clk->clk);
+ goto _fail;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(dvp_clk_cell); ++i)
+ {
+ struct rt_clk_cell *cell = dvp_clk_cell[i];
+
+ cell->parents_nr = 1;
+ cell->parent_name = dvp_clk->clk->cell->name;
+ }
+
+ dvp_clk->clk_parent.dev = dev;
+ dvp_clk->clk_parent.cells = dvp_clk_cell;
+ dvp_clk->clk_parent.cells_nr = RT_ARRAY_SIZE(dvp_clk_cell);
+
+ if ((err = rt_clk_register(&dvp_clk->clk_parent)))
+ {
+ goto _fail;
+ }
+
+ /* Reset */
+ rsts = &dvp_clk->reset_parent;
+
+ rt_spin_lock_init(&rsts->lock);
+ rsts->mmio_base = dvp_clk->regs + DVP_HT_RPI_SW_INIT;
+
+ rstcer = &rsts->parent;
+ rstcer->priv = rsts;
+ rstcer->ofw_node = dev->ofw_node;
+ rstcer->ops = &reset_simple_ops;
+
+ if ((err = rt_reset_controller_register(rstcer)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (dvp_clk->regs)
+ {
+ rt_iounmap(dvp_clk->regs);
+ }
+
+ if (dvp_clk->clk_parent.dev)
+ {
+ rt_clk_unregister(&dvp_clk->clk_parent);
+ }
+
+ if (dvp_clk->reset_parent.parent.ops)
+ {
+ rt_reset_controller_unregister(&dvp_clk->reset_parent.parent);
+ }
+
+ if (rt_is_err_or_null(dvp_clk->clk))
+ {
+ rt_clk_put(dvp_clk->clk);
+ }
+
+ rt_free(dvp_clk);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id bcm2711_dvp_clk_ofw_ids[] =
+{
+ { .compatible = "brcm,brcm2711-dvp", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2711_dvp_clk_driver =
+{
+ .name = "clk-brcm2711-dvp",
+ .ids = bcm2711_dvp_clk_ofw_ids,
+
+ .probe = bcm2711_dvp_clk_probe,
+};
+
+static int bcm2711_dvp_clk_register(void)
+{
+ rt_platform_driver_register(&bcm2711_dvp_clk_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2711_dvp_clk_register);
diff --git a/bsp/raspberry-pi/dm/clk/clk-bcm2835-aux.c b/bsp/raspberry-pi/dm/clk/clk-bcm2835-aux.c
new file mode 100755
index 0000000000..7bf9e08cbf
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-bcm2835-aux.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.bcm2835.aux"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <dt-bindings/clock/bcm2835-aux.h>
+
+#define BCM2835_AUXIRQ 0x00
+#define BCM2835_AUXENB 0x04
+
+struct bcm2835_aux_clk
+{
+ struct rt_clk_node parent;
+
+ void *regs;
+ struct rt_clk *clk;
+};
+
+#define raw_to_bcm2835_aux_clk(raw) rt_container_of(raw, struct bcm2835_aux_clk, parent)
+
+struct aux_clk_gate
+{
+ struct rt_clk_cell cell;
+
+ rt_uint8_t bit_idx;
+};
+
+#define raw_to_aux_clk_gate(raw) rt_container_of(raw, struct aux_clk_gate, cell)
+
+static void bcm2835_aux_clk_endisable(struct rt_clk_cell *cell, int enable)
+{
+ int set = 0 ^ enable;
+ rt_uint32_t value, bit_idx;
+ struct aux_clk_gate *gate = raw_to_aux_clk_gate(cell);
+ struct bcm2835_aux_clk *aux_clk = raw_to_bcm2835_aux_clk(cell->clk_np);
+
+ bit_idx = gate->bit_idx;
+
+ value = HWREG32(aux_clk->regs);
+ if (set)
+ {
+ value |= RT_BIT(bit_idx);
+ }
+ else
+ {
+ value &= ~RT_BIT(bit_idx);
+ }
+ HWREG32(aux_clk->regs) = value;
+}
+
+static rt_err_t bcm2835_aux_clk_enable(struct rt_clk_cell *cell)
+{
+ bcm2835_aux_clk_endisable(cell, 1);
+
+ return RT_EOK;
+}
+
+static void bcm2835_aux_clk_disable(struct rt_clk_cell *cell)
+{
+ bcm2835_aux_clk_endisable(cell, 0);
+}
+
+static rt_bool_t bcm2835_aux_clk_is_enabled(struct rt_clk_cell *cell)
+{
+ rt_uint32_t value, bit_idx;
+ struct aux_clk_gate *gate = raw_to_aux_clk_gate(cell);
+ struct bcm2835_aux_clk *aux_clk = raw_to_bcm2835_aux_clk(cell->clk_np);
+
+ bit_idx = gate->bit_idx;
+
+ value = HWREG32(aux_clk->regs + BCM2835_AUXENB);
+ value &= RT_BIT(bit_idx);
+
+ return !!value;
+}
+
+static rt_ubase_t bcm2835_aux_clk_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct bcm2835_aux_clk *aux_clk = raw_to_bcm2835_aux_clk(cell->clk_np);
+
+ return rt_clk_cell_get_rate(aux_clk->clk->cell);
+}
+
+const struct rt_clk_ops bcm2835_aux_clk_ops =
+{
+ .enable = bcm2835_aux_clk_enable,
+ .disable = bcm2835_aux_clk_disable,
+ .is_enabled = bcm2835_aux_clk_is_enabled,
+ .recalc_rate = bcm2835_aux_clk_recalc_rate,
+};
+
+static struct aux_clk_gate aux_uart =
+{
+ .cell.name = "aux_uart",
+ .cell.ops = &bcm2835_aux_clk_ops,
+ .bit_idx = 0,
+};
+
+static struct aux_clk_gate aux_spi1 =
+{
+ .cell.name = "aux_spi1",
+ .cell.ops = &bcm2835_aux_clk_ops,
+ .bit_idx = 1,
+};
+
+static struct aux_clk_gate aux_spi2 =
+{
+ .cell.name = "aux_spi2",
+ .cell.ops = &bcm2835_aux_clk_ops,
+ .bit_idx = 2,
+};
+
+static struct rt_clk_cell *bcm2835_aux_clk_cell[] =
+{
+ [BCM2835_AUX_CLOCK_UART] = &aux_uart.cell,
+ [BCM2835_AUX_CLOCK_SPI1] = &aux_spi1.cell,
+ [BCM2835_AUX_CLOCK_SPI2] = &aux_spi2.cell,
+};
+
+static rt_err_t bcm2835_aux_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_aux_clk *aux_clk = rt_calloc(1, sizeof(*aux_clk));
+
+ if (!aux_clk)
+ {
+ return -RT_ENOMEM;
+ }
+
+ aux_clk->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!aux_clk->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ aux_clk->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(aux_clk->clk))
+ {
+ err = rt_ptr_err(aux_clk->clk);
+ goto _fail;
+ }
+
+ if (aux_clk->clk)
+ {
+ for (int i = 0; i < RT_ARRAY_SIZE(bcm2835_aux_clk_cell); ++i)
+ {
+ struct rt_clk_cell *cell = bcm2835_aux_clk_cell[i];
+
+ if (cell)
+ {
+ cell->parents_nr = 1;
+ cell->parent_name = aux_clk->clk->cell->name;
+ }
+ }
+ }
+
+ aux_clk->parent.dev = dev;
+ aux_clk->parent.cells = bcm2835_aux_clk_cell;
+ aux_clk->parent.cells_nr = RT_ARRAY_SIZE(bcm2835_aux_clk_cell);
+
+ if ((err = rt_clk_register(&aux_clk->parent)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (aux_clk->regs)
+ {
+ rt_iounmap(aux_clk->regs);
+ }
+
+ if (!rt_is_err_or_null(aux_clk->clk))
+ {
+ rt_clk_put(aux_clk->clk);
+ }
+
+ rt_free(aux_clk);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id bcm2835_aux_clk_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-aux", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_aux_clk_driver =
+{
+ .name = "clk-bcm2835-aux",
+ .ids = bcm2835_aux_clk_ofw_ids,
+
+ .probe = bcm2835_aux_clk_probe,
+};
+
+static int bcm2835_aux_clk_register(void)
+{
+ rt_platform_driver_register(&bcm2835_aux_clk_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_aux_clk_register);
diff --git a/bsp/raspberry-pi/dm/clk/clk-bcm2835.c b/bsp/raspberry-pi/dm/clk/clk-bcm2835.c
new file mode 100755
index 0000000000..c1c80de444
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-bcm2835.c
@@ -0,0 +1,1976 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <dt-bindings/clock/bcm2835.h>
+#include <firmware-raspberrypi.h>
+
+#define CM_PASSWORD 0x5a000000
+
+#define CM_GNRICCTL 0x000
+#define CM_GNRICDIV 0x004
+#define CM_DIV_FRAC_BITS 12
+#define CM_DIV_FRAC_MASK RT_GENMASK(CM_DIV_FRAC_BITS - 1, 0)
+
+#define CM_VPUCTL 0x008
+#define CM_VPUDIV 0x00c
+#define CM_SYSCTL 0x010
+#define CM_SYSDIV 0x014
+#define CM_PERIACTL 0x018
+#define CM_PERIADIV 0x01c
+#define CM_PERIICTL 0x020
+#define CM_PERIIDIV 0x024
+#define CM_H264CTL 0x028
+#define CM_H264DIV 0x02c
+#define CM_ISPCTL 0x030
+#define CM_ISPDIV 0x034
+#define CM_V3DCTL 0x038
+#define CM_V3DDIV 0x03c
+#define CM_CAM0CTL 0x040
+#define CM_CAM0DIV 0x044
+#define CM_CAM1CTL 0x048
+#define CM_CAM1DIV 0x04c
+#define CM_CCP2CTL 0x050
+#define CM_CCP2DIV 0x054
+#define CM_DSI0ECTL 0x058
+#define CM_DSI0EDIV 0x05c
+#define CM_DSI0PCTL 0x060
+#define CM_DSI0PDIV 0x064
+#define CM_DPICTL 0x068
+#define CM_DPIDIV 0x06c
+#define CM_GP0CTL 0x070
+#define CM_GP0DIV 0x074
+#define CM_GP1CTL 0x078
+#define CM_GP1DIV 0x07c
+#define CM_GP2CTL 0x080
+#define CM_GP2DIV 0x084
+#define CM_HSMCTL 0x088
+#define CM_HSMDIV 0x08c
+#define CM_OTPCTL 0x090
+#define CM_OTPDIV 0x094
+#define CM_PCMCTL 0x098
+#define CM_PCMDIV 0x09c
+#define CM_PWMCTL 0x0a0
+#define CM_PWMDIV 0x0a4
+#define CM_SLIMCTL 0x0a8
+#define CM_SLIMDIV 0x0ac
+#define CM_SMICTL 0x0b0
+#define CM_SMIDIV 0x0b4
+/* No definition for 0x0b8 and 0x0bc */
+#define CM_TCNTCTL 0x0c0
+#define CM_TCNT_SRC1_SHIFT 12
+#define CM_TCNTCNT 0x0c4
+#define CM_TECCTL 0x0c8
+#define CM_TECDIV 0x0cc
+#define CM_TD0CTL 0x0d0
+#define CM_TD0DIV 0x0d4
+#define CM_TD1CTL 0x0d8
+#define CM_TD1DIV 0x0dc
+#define CM_TSENSCTL 0x0e0
+#define CM_TSENSDIV 0x0e4
+#define CM_TIMERCTL 0x0e8
+#define CM_TIMERDIV 0x0ec
+#define CM_UARTCTL 0x0f0
+#define CM_UARTDIV 0x0f4
+#define CM_VECCTL 0x0f8
+#define CM_VECDIV 0x0fc
+#define CM_DSI0HSCK 0x120
+#define CM_PULSECTL 0x190
+#define CM_PULSEDIV 0x194
+#define CM_SDCCTL 0x1a8
+#define CM_SDCDIV 0x1ac
+#define CM_ARMCTL 0x1b0
+#define CM_AVEOCTL 0x1b8
+#define CM_AVEODIV 0x1bc
+#define CM_EMMCCTL 0x1c0
+#define CM_EMMCDIV 0x1c4
+#define CM_EMMC2CTL 0x1d0
+#define CM_EMMC2DIV 0x1d4
+
+/* General bits for the CM_*CTL regs */
+#define CM_ENABLE RT_BIT(4)
+#define CM_KILL RT_BIT(5)
+#define CM_GATE_BIT 6
+#define CM_GATE RT_BIT(CM_GATE_BIT)
+#define CM_BUSY RT_BIT(7)
+#define CM_BUSYD RT_BIT(8)
+#define CM_FRAC RT_BIT(9)
+#define CM_SRC_SHIFT 0
+#define CM_SRC_BITS 4
+#define CM_SRC_MASK 0xf
+#define CM_SRC_GND 0
+#define CM_SRC_OSC 1
+#define CM_SRC_TESTDEBUG0 2
+#define CM_SRC_TESTDEBUG1 3
+#define CM_SRC_PLLA_CORE 4
+#define CM_SRC_PLLA_PER 4
+#define CM_SRC_PLLC_CORE0 5
+#define CM_SRC_PLLC_PER 5
+#define CM_SRC_PLLC_CORE1 8
+#define CM_SRC_PLLD_CORE 6
+#define CM_SRC_PLLD_PER 6
+#define CM_SRC_PLLH_AUX 7
+#define CM_SRC_PLLC_CORE1 8
+#define CM_SRC_PLLC_CORE2 9
+
+#define CM_OSCCOUNT 0x100
+
+#define CM_PLLA 0x104
+#define CM_PLL_ANARST RT_BIT(8)
+#define CM_PLLA_HOLDPER RT_BIT(7)
+#define CM_PLLA_LOADPER RT_BIT(6)
+#define CM_PLLA_HOLDCORE RT_BIT(5)
+#define CM_PLLA_LOADCORE RT_BIT(4)
+#define CM_PLLA_HOLDCCP2 RT_BIT(3)
+#define CM_PLLA_LOADCCP2 RT_BIT(2)
+#define CM_PLLA_HOLDDSI0 RT_BIT(1)
+#define CM_PLLA_LOADDSI0 RT_BIT(0)
+
+#define CM_PLLC 0x108
+#define CM_PLLC_HOLDPER RT_BIT(7)
+#define CM_PLLC_LOADPER RT_BIT(6)
+#define CM_PLLC_HOLDCORE2 RT_BIT(5)
+#define CM_PLLC_LOADCORE2 RT_BIT(4)
+#define CM_PLLC_HOLDCORE1 RT_BIT(3)
+#define CM_PLLC_LOADCORE1 RT_BIT(2)
+#define CM_PLLC_HOLDCORE0 RT_BIT(1)
+#define CM_PLLC_LOADCORE0 RT_BIT(0)
+
+#define CM_PLLD 0x10c
+#define CM_PLLD_HOLDPER RT_BIT(7)
+#define CM_PLLD_LOADPER RT_BIT(6)
+#define CM_PLLD_HOLDCORE RT_BIT(5)
+#define CM_PLLD_LOADCORE RT_BIT(4)
+#define CM_PLLD_HOLDDSI1 RT_BIT(3)
+#define CM_PLLD_LOADDSI1 RT_BIT(2)
+#define CM_PLLD_HOLDDSI0 RT_BIT(1)
+#define CM_PLLD_LOADDSI0 RT_BIT(0)
+
+#define CM_PLLH 0x110
+#define CM_PLLH_LOADRCAL RT_BIT(2)
+#define CM_PLLH_LOADAUX RT_BIT(1)
+#define CM_PLLH_LOADPIX RT_BIT(0)
+
+#define CM_LOCK 0x114
+#define CM_LOCK_FLOCKH RT_BIT(12)
+#define CM_LOCK_FLOCKD RT_BIT(11)
+#define CM_LOCK_FLOCKC RT_BIT(10)
+#define CM_LOCK_FLOCKB RT_BIT(9)
+#define CM_LOCK_FLOCKA RT_BIT(8)
+
+#define CM_EVENT 0x118
+#define CM_DSI1ECTL 0x158
+#define CM_DSI1EDIV 0x15c
+#define CM_DSI1PCTL 0x160
+#define CM_DSI1PDIV 0x164
+#define CM_DFTCTL 0x168
+#define CM_DFTDIV 0x16c
+
+#define CM_PLLB 0x170
+#define CM_PLLB_HOLDARM RT_BIT(1)
+#define CM_PLLB_LOADARM RT_BIT(0)
+
+#define A2W_PLLA_CTRL 0x1100
+#define A2W_PLLC_CTRL 0x1120
+#define A2W_PLLD_CTRL 0x1140
+#define A2W_PLLH_CTRL 0x1160
+#define A2W_PLLB_CTRL 0x11e0
+#define A2W_PLL_CTRL_PRST_DISABLE RT_BIT(17)
+#define A2W_PLL_CTRL_PWRDN RT_BIT(16)
+#define A2W_PLL_CTRL_PDIV_MASK 0x000007000
+#define A2W_PLL_CTRL_PDIV_SHIFT 12
+#define A2W_PLL_CTRL_NDIV_MASK 0x0000003ff
+#define A2W_PLL_CTRL_NDIV_SHIFT 0
+
+#define A2W_PLLA_ANA0 0x1010
+#define A2W_PLLC_ANA0 0x1030
+#define A2W_PLLD_ANA0 0x1050
+#define A2W_PLLH_ANA0 0x1070
+#define A2W_PLLB_ANA0 0x10f0
+
+#define A2W_PLL_KA_SHIFT 7
+#define A2W_PLL_KA_MASK RT_GENMASK(9, 7)
+#define A2W_PLL_KI_SHIFT 19
+#define A2W_PLL_KI_MASK RT_GENMASK(21, 19)
+#define A2W_PLL_KP_SHIFT 15
+#define A2W_PLL_KP_MASK RT_GENMASK(18, 15)
+
+#define A2W_PLLH_KA_SHIFT 19
+#define A2W_PLLH_KA_MASK RT_GENMASK(21, 19)
+#define A2W_PLLH_KI_LOW_SHIFT 22
+#define A2W_PLLH_KI_LOW_MASK RT_GENMASK(23, 22)
+#define A2W_PLLH_KI_HIGH_SHIFT 0
+#define A2W_PLLH_KI_HIGH_MASK RT_GENMASK(0, 0)
+#define A2W_PLLH_KP_SHIFT 1
+#define A2W_PLLH_KP_MASK RT_GENMASK(4, 1)
+
+#define A2W_XOSC_CTRL 0x1190
+#define A2W_XOSC_CTRL_PLLB_ENABLE RT_BIT(7)
+#define A2W_XOSC_CTRL_PLLA_ENABLE RT_BIT(6)
+#define A2W_XOSC_CTRL_PLLD_ENABLE RT_BIT(5)
+#define A2W_XOSC_CTRL_DDR_ENABLE RT_BIT(4)
+#define A2W_XOSC_CTRL_CPR1_ENABLE RT_BIT(3)
+#define A2W_XOSC_CTRL_USB_ENABLE RT_BIT(2)
+#define A2W_XOSC_CTRL_HDMI_ENABLE RT_BIT(1)
+#define A2W_XOSC_CTRL_PLLC_ENABLE RT_BIT(0)
+
+#define A2W_PLLA_FRAC 0x1200
+#define A2W_PLLC_FRAC 0x1220
+#define A2W_PLLD_FRAC 0x1240
+#define A2W_PLLH_FRAC 0x1260
+#define A2W_PLLB_FRAC 0x12e0
+#define A2W_PLL_FRAC_MASK ((1 << A2W_PLL_FRAC_BITS) - 1)
+#define A2W_PLL_FRAC_BITS 20
+
+#define A2W_PLL_CHANNEL_DISABLE RT_BIT(8)
+#define A2W_PLL_DIV_BITS 8
+#define A2W_PLL_DIV_SHIFT 0
+
+#define A2W_PLLA_DSI0 0x1300
+#define A2W_PLLA_CORE 0x1400
+#define A2W_PLLA_PER 0x1500
+#define A2W_PLLA_CCP2 0x1600
+
+#define A2W_PLLC_CORE2 0x1320
+#define A2W_PLLC_CORE1 0x1420
+#define A2W_PLLC_PER 0x1520
+#define A2W_PLLC_CORE0 0x1620
+
+#define A2W_PLLD_DSI0 0x1340
+#define A2W_PLLD_CORE 0x1440
+#define A2W_PLLD_PER 0x1540
+#define A2W_PLLD_DSI1 0x1640
+
+#define A2W_PLLH_AUX 0x1360
+#define A2W_PLLH_RCAL 0x1460
+#define A2W_PLLH_PIX 0x1560
+#define A2W_PLLH_STS 0x1660
+
+#define A2W_PLLH_CTRLR 0x1960
+#define A2W_PLLH_FRACR 0x1a60
+#define A2W_PLLH_AUXR 0x1b60
+#define A2W_PLLH_RCALR 0x1c60
+#define A2W_PLLH_PIXR 0x1d60
+#define A2W_PLLH_STSR 0x1e60
+
+#define A2W_PLLB_ARM 0x13e0
+#define A2W_PLLB_SP0 0x14e0
+#define A2W_PLLB_SP1 0x15e0
+#define A2W_PLLB_SP2 0x16e0
+
+#define LOCK_TIMEOUT_NS 100000000
+#define LOCK_TIMEOUT_US (LOCK_TIMEOUT_NS / 1000)
+#define BCM2835_MAX_FB_RATE 1750000000U
+
+#define CLK_TYPE_PLL 0
+#define CLK_TYPE_DIV 1
+#define CLK_TYPE_CLK 2
+#define CLK_TYPE_VPU 3
+
+#define SOC_TYPE_BCM2835 RT_BIT(0)
+#define SOC_TYPE_BCM2711 RT_BIT(1)
+#define SOC_ALL (SOC_TYPE_BCM2835 | SOC_TYPE_BCM2711)
+
+#define VCMSG_ID_CORE_CLOCK 4
+
+struct bcm2835_cprman;
+
+struct cprman_soc_data
+{
+ rt_uint32_t soc;
+};
+
+struct bcm2835_clock_data
+{
+ struct rt_clk_cell cell;
+
+ struct bcm2835_cprman *cprman;
+ void (*init)(struct bcm2835_cprman *cprman, struct bcm2835_clock_data *cdata);
+
+ rt_uint32_t supported;
+
+ /* Bitmap encoding which parents accept rate change propagation. */
+ rt_uint32_t set_rate_parent;
+
+ rt_uint32_t ctl_reg;
+ rt_uint32_t div_reg;
+
+ /* Number of integer bits in the divider */
+ rt_uint32_t int_bits;
+ /* Number of fractional bits in the divider */
+ rt_uint32_t frac_bits;
+
+ rt_uint32_t flags;
+
+ rt_bool_t is_vpu_clock;
+ rt_bool_t is_mash_clock;
+ rt_bool_t low_jitter;
+
+ rt_uint32_t tcnt_mux;
+
+ rt_bool_t round_up;
+};
+
+#define cell_to_bcm2835_clock_data(cell) rt_container_of(cell, struct bcm2835_clock_data, cell);
+
+static const char *const cprman_parent_names[] =
+{
+ "osc", "dsi0_byte", "dsi0_ddr2", "dsi0_ddr", "dsi1_byte", "dsi1_ddr2", "dsi1_ddr",
+};
+
+struct bcm2835_cprman
+{
+ struct rt_clk_node parent;
+
+ void *regs;
+ struct rt_clk *osc_clk;
+ struct rpi_firmware *fw;
+
+ rt_uint32_t soc;
+ const char *real_parent_names[RT_ARRAY_SIZE(cprman_parent_names)];
+};
+
+#define raw_to_bcm2835_cprman(raw) rt_container_of(raw, struct bcm2835_cprman, parent)
+
+rt_inline void cprman_write(struct bcm2835_cprman *cprman,
+ rt_uint32_t reg, rt_uint32_t val)
+{
+ HWREG32(cprman->regs + reg) = CM_PASSWORD | val;
+}
+
+rt_inline rt_uint32_t cprman_read(struct bcm2835_cprman *cprman, rt_uint32_t reg)
+{
+ return HWREG32(cprman->regs + reg);
+}
+
+static rt_bool_t bcm2835_clk_is_claimed(const char *name);
+
+/* ---------------------------------- PLL ----------------------------------- */
+struct bcm2835_pll_ana_bits
+{
+ rt_uint32_t mask0;
+ rt_uint32_t set0;
+ rt_uint32_t mask1;
+ rt_uint32_t set1;
+ rt_uint32_t mask3;
+ rt_uint32_t set3;
+ rt_uint32_t fb_prediv_mask;
+};
+
+struct bcm2835_pll_data
+{
+ struct bcm2835_clock_data cdata;
+
+ rt_uint32_t cm_ctrl_reg;
+ rt_uint32_t a2w_ctrl_reg;
+ rt_uint32_t frac_reg;
+ rt_uint32_t ana_reg_base;
+ rt_uint32_t reference_enable_mask;
+ /* Bit in CM_LOCK to indicate when the PLL has locked. */
+ rt_uint32_t lock_mask;
+
+ const struct bcm2835_pll_ana_bits *ana;
+
+ rt_ubase_t min_rate;
+ rt_ubase_t max_rate;
+ /*
+ * Highest rate for the VCO before we have to use the
+ * pre-divide-by-2.
+ */
+ rt_ubase_t max_fb_rate;
+};
+
+rt_inline struct bcm2835_pll_data *cell_to_bcm2835_pll_data(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock_data *cdata = cell_to_bcm2835_clock_data(cell);
+
+ return rt_container_of(cdata, struct bcm2835_pll_data, cdata);
+}
+
+static const struct bcm2835_pll_ana_bits bcm2835_ana_default =
+{
+ .mask0 = 0,
+ .set0 = 0,
+ .mask1 = A2W_PLL_KI_MASK | A2W_PLL_KP_MASK,
+ .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
+ .mask3 = A2W_PLL_KA_MASK,
+ .set3 = (2 << A2W_PLL_KA_SHIFT),
+ .fb_prediv_mask = RT_BIT(14),
+};
+
+static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh =
+{
+ .mask0 = A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK,
+ .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
+ .mask1 = A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK,
+ .set1 = (6 << A2W_PLLH_KP_SHIFT),
+ .mask3 = 0,
+ .set3 = 0,
+ .fb_prediv_mask = RT_BIT(11),
+};
+
+static void bcm2835_pll_choose_ndiv_and_fdiv(rt_base_t rate,
+ rt_base_t parent_rate, rt_uint32_t *ndiv, rt_uint32_t *fdiv)
+{
+ rt_uint64_t div;
+
+ div = (rt_uint64_t)rate << A2W_PLL_FRAC_BITS;
+ rt_do_div(div, parent_rate);
+
+ *ndiv = div >> A2W_PLL_FRAC_BITS;
+ *fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
+}
+
+static rt_uint32_t bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman,
+ struct bcm2835_pll_data *data)
+{
+ /*
+ * On BCM2711 there isn't a pre-divisor available in the PLL feedback
+ * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed
+ * for to for VCO RANGE bits.
+ */
+ if (cprman->soc & SOC_TYPE_BCM2711)
+ {
+ return 0;
+ }
+
+ return data->ana->fb_prediv_mask;
+}
+
+static rt_ubase_t bcm2835_pll_rate_from_divisors(rt_base_t parent_rate,
+ rt_uint32_t ndiv, rt_uint32_t fdiv, rt_uint32_t pdiv)
+{
+ rt_uint64_t rate;
+
+ if (pdiv == 0)
+ {
+ return 0;
+ }
+
+ rate = (rt_uint64_t)parent_rate * ((ndiv << A2W_PLL_FRAC_BITS) + fdiv);
+ rt_do_div(rate, pdiv);
+
+ return rate >> A2W_PLL_FRAC_BITS;
+}
+
+static void bcm2835_pll_write_ana(struct bcm2835_cprman *cprman,
+ rt_uint32_t ana_reg_base, rt_uint32_t *ana)
+{
+ /*
+ * ANA register setup is done as a series of writes to ANA3-ANA0,
+ * in that order. This lets us write all 4 registers as a single cycle of
+ * the serdes interface (taking 100 xosc clocks),
+ * whereas if we were to update ana0, 1, and 3 individually through
+ * their partial-write registers, each would be their own serdes cycle.
+ */
+ for (int i = 3; i >= 0; --i)
+ {
+ cprman_write(cprman, ana_reg_base + i * 4, ana[i]);
+ }
+}
+
+static rt_err_t bcm2835_pll_on(struct rt_clk_cell *cell)
+{
+ rt_tick_t timeout;
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ cprman_write(cprman, data->a2w_ctrl_reg,
+ cprman_read(cprman, data->a2w_ctrl_reg) & ~A2W_PLL_CTRL_PWRDN);
+
+ /* Take the PLL out of reset. */
+ cprman_write(cprman, data->cm_ctrl_reg,
+ cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
+
+ /* Wait for the PLL to lock. */
+ if (rt_strcmp(cell->name, "pllh"))
+ {
+ timeout = rt_tick_from_millisecond(LOCK_TIMEOUT_US / 1000);
+ timeout += rt_tick_get();
+
+ while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask))
+ {
+ if (rt_tick_get() > timeout)
+ {
+ return -RT_ETIMEOUT;
+ }
+
+ rt_hw_cpu_relax();
+ }
+ }
+
+ cprman_write(cprman, data->a2w_ctrl_reg,
+ cprman_read(cprman, data->a2w_ctrl_reg) | A2W_PLL_CTRL_PRST_DISABLE);
+
+ return RT_EOK;
+}
+
+static void bcm2835_pll_off(struct rt_clk_cell *cell)
+{
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
+ cprman_write(cprman, data->a2w_ctrl_reg,
+ cprman_read(cprman, data->a2w_ctrl_reg) | A2W_PLL_CTRL_PWRDN);
+}
+
+static rt_bool_t bcm2835_pll_is_on(struct rt_clk_cell *cell)
+{
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ return !!(cprman_read(cprman, data->a2w_ctrl_reg) & A2W_PLL_CTRL_PRST_DISABLE);
+}
+
+static rt_ubase_t bcm2835_pll_get_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_bool_t using_prediv;
+ rt_uint32_t ndiv, pdiv, fdiv, a2wctrl;
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ if (parent_rate == 0)
+ {
+ return 0;
+ }
+
+ a2wctrl = cprman_read(cprman, data->a2w_ctrl_reg);
+
+ fdiv = cprman_read(cprman, data->frac_reg) & A2W_PLL_FRAC_MASK;
+ ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
+ pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
+ using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
+ bcm2835_pll_get_prediv_mask(cprman, data);
+
+ if (using_prediv)
+ {
+ ndiv *= 2;
+ fdiv *= 2;
+ }
+
+ return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv);
+}
+
+static rt_base_t bcm2835_pll_round_rate(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ rt_uint32_t ndiv, fdiv;
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+
+ rate = rt_clamp(rate, data->min_rate, data->max_rate);
+
+ bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
+
+ return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
+}
+
+static rt_err_t bcm2835_pll_set_rate(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t prediv_mask, ndiv, fdiv, a2w_ctl, ana[4];
+ rt_bool_t was_using_prediv, use_fb_prediv, do_ana_setup_first;
+ struct bcm2835_pll_data *data = cell_to_bcm2835_pll_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data);
+
+ if (rate > data->max_fb_rate)
+ {
+ use_fb_prediv = RT_TRUE;
+ rate /= 2;
+ }
+ else
+ {
+ use_fb_prediv = RT_FALSE;
+ }
+
+ bcm2835_pll_choose_ndiv_and_fdiv(rate, parent_rate, &ndiv, &fdiv);
+
+ for (int i = 3; i >= 0; --i)
+ {
+ ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);
+ }
+
+ was_using_prediv = ana[1] & prediv_mask;
+
+ ana[0] &= ~data->ana->mask0;
+ ana[0] |= data->ana->set0;
+ ana[1] &= ~data->ana->mask1;
+ ana[1] |= data->ana->set1;
+ ana[3] &= ~data->ana->mask3;
+ ana[3] |= data->ana->set3;
+
+ if (was_using_prediv && !use_fb_prediv)
+ {
+ ana[1] &= ~prediv_mask;
+ do_ana_setup_first = RT_TRUE;
+ }
+ else if (!was_using_prediv && use_fb_prediv)
+ {
+ ana[1] |= prediv_mask;
+ do_ana_setup_first = RT_FALSE;
+ }
+ else
+ {
+ do_ana_setup_first = RT_TRUE;
+ }
+
+ /* Unmask the reference clock from the oscillator. */
+ cprman_write(cprman, A2W_XOSC_CTRL,
+ cprman_read(cprman, A2W_XOSC_CTRL) | data->reference_enable_mask);
+
+ if (do_ana_setup_first)
+ {
+ bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
+ }
+
+ /* Set the PLL multiplier from the oscillator. */
+ cprman_write(cprman, data->frac_reg, fdiv);
+
+ a2w_ctl = cprman_read(cprman, data->a2w_ctrl_reg);
+ a2w_ctl &= ~A2W_PLL_CTRL_NDIV_MASK;
+ a2w_ctl |= ndiv << A2W_PLL_CTRL_NDIV_SHIFT;
+ a2w_ctl &= ~A2W_PLL_CTRL_PDIV_MASK;
+ a2w_ctl |= 1 << A2W_PLL_CTRL_PDIV_SHIFT;
+ cprman_write(cprman, data->a2w_ctrl_reg, a2w_ctl);
+
+ if (!do_ana_setup_first)
+ {
+ bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
+ }
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops bcm2835_pll_clk_ops =
+{
+ .prepare = bcm2835_pll_on,
+ .unprepare = bcm2835_pll_off,
+ .is_prepared = bcm2835_pll_is_on,
+ .recalc_rate = bcm2835_pll_get_rate,
+ .round_rate = bcm2835_pll_round_rate,
+ .set_rate = bcm2835_pll_set_rate,
+};
+
+static void bcm2835_pll_init(struct bcm2835_cprman *cprman, struct bcm2835_clock_data *cdata)
+{
+ struct rt_clk_cell *cell = &cdata->cell;
+
+ /* All of the PLLs derive from the external oscillator. */
+ cell->parents_nr = 1;
+ cell->parent_name = cprman->real_parent_names[0];
+
+ if (!bcm2835_clk_is_claimed(cell->name))
+ {
+ cell->flags |= RT_CLK_F_IS_CRITICAL;
+ }
+}
+
+#define REGISTER_PLL(_struct, _name, _supported, _flags, ...) \
+static struct bcm2835_pll_data _struct = \
+{ \
+ .cdata = \
+ { \
+ .cell.name = _name, \
+ .cell.ops = &bcm2835_pll_clk_ops, \
+ .cell.flags = RT_CLK_F_IGNORE_UNUSED | _flags, \
+ .init = bcm2835_pll_init, \
+ .supported = _supported, \
+ }, \
+ __VA_ARGS__ \
+};
+/* ---------------------------------- PLL ----------------------------------- */
+
+/* ------------------------------ PLL Divider ------------------------------- */
+struct bcm2835_pll_divider_data
+{
+ struct bcm2835_clock_data cdata;
+
+ rt_uint32_t cm_reg;
+ rt_uint32_t a2w_reg;
+
+ rt_uint32_t load_mask;
+ rt_uint32_t hold_mask;
+ rt_uint32_t fixed_divider;
+};
+
+rt_inline struct bcm2835_pll_divider_data *cell_to_bcm2835_divider_data(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock_data *cdata = cell_to_bcm2835_clock_data(cell);
+
+ return rt_container_of(cdata, struct bcm2835_pll_divider_data, cdata);
+}
+
+static rt_err_t bcm2835_pll_divider_on(struct rt_clk_cell *cell)
+{
+ struct bcm2835_pll_divider_data *data = cell_to_bcm2835_divider_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ cprman_write(cprman, data->a2w_reg,
+ cprman_read(cprman, data->a2w_reg) & ~A2W_PLL_CHANNEL_DISABLE);
+
+ cprman_write(cprman, data->cm_reg,
+ cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
+
+ return RT_EOK;
+}
+
+static void bcm2835_pll_divider_off(struct rt_clk_cell *cell)
+{
+ struct bcm2835_pll_divider_data *data = cell_to_bcm2835_divider_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ cprman_write(cprman, data->cm_reg,
+ (cprman_read(cprman, data->cm_reg) & ~data->load_mask) | data->hold_mask);
+ cprman_write(cprman, data->a2w_reg,
+ cprman_read(cprman, data->a2w_reg) | A2W_PLL_CHANNEL_DISABLE);
+}
+
+static rt_bool_t bcm2835_pll_divider_is_on(struct rt_clk_cell *cell)
+{
+ struct bcm2835_pll_divider_data *data = cell_to_bcm2835_divider_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ return !(cprman_read(cprman, data->a2w_reg) & A2W_PLL_CHANNEL_DISABLE);
+}
+
+static rt_ubase_t bcm2835_pll_divider_get_rate(struct rt_clk_cell *cell,
+ rt_ubase_t parent_rate)
+{
+ rt_uint32_t val, div;
+ struct bcm2835_pll_divider_data *data = cell_to_bcm2835_divider_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ val = cprman_read(cprman, data->a2w_reg) >> A2W_PLL_DIV_SHIFT;
+ val &= (1 << A2W_PLL_DIV_BITS) - 1;
+
+ div = val ? val : (1 << A2W_PLL_DIV_BITS);
+
+ return div ? RT_DIV_ROUND_UP_ULL((rt_uint64_t)parent_rate, div) : parent_rate;
+}
+
+static rt_err_t bcm2835_pll_divider_set_rate(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t cm, div, max_div = 1 << A2W_PLL_DIV_BITS;
+ struct bcm2835_pll_divider_data *data = cell_to_bcm2835_divider_data(cell);
+ struct bcm2835_cprman *cprman = data->cdata.cprman;
+
+ div = RT_DIV_ROUND_UP_ULL(parent_rate, rate);
+
+ div = rt_min(div, max_div);
+ if (div == max_div)
+ {
+ div = 0;
+ }
+
+ cprman_write(cprman, data->a2w_reg, div);
+ cm = cprman_read(cprman, data->cm_reg);
+ cprman_write(cprman, data->cm_reg, cm | data->load_mask);
+ cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops bcm2835_pll_divider_clk_ops =
+{
+ .prepare = bcm2835_pll_divider_on,
+ .unprepare = bcm2835_pll_divider_off,
+ .is_prepared = bcm2835_pll_divider_is_on,
+ .recalc_rate = bcm2835_pll_divider_get_rate,
+ .set_rate = bcm2835_pll_divider_set_rate,
+};
+
+static void bcm2835_pll_divider_init(struct bcm2835_cprman *cprman, struct bcm2835_clock_data *cdata)
+{
+ struct rt_clk_cell *cell = &cdata->cell;
+ struct bcm2835_pll_divider_data *divider_data = cell_to_bcm2835_divider_data(cell);;
+
+ if (!(cprman_read(cprman, divider_data->cm_reg) & divider_data->hold_mask))
+ {
+ if (!bcm2835_clk_is_claimed(cell->parent_name) ||
+ !bcm2835_clk_is_claimed(cell->name))
+ {
+ cell->flags |= RT_CLK_F_IS_CRITICAL;
+ }
+ }
+}
+
+#define REGISTER_PLL_DIV(_struct, _name, _parent, _supported, _flags, ...) \
+static struct bcm2835_pll_divider_data _struct = \
+{ \
+ .cdata = \
+ { \
+ .cell.name = _name, \
+ .cell.ops = &bcm2835_pll_divider_clk_ops, \
+ .cell.parents_nr = 1, \
+ .cell.parent_name = _parent, \
+ .cell.flags = RT_CLK_F_IGNORE_UNUSED | _flags, \
+ .init = bcm2835_pll_divider_init, \
+ .supported = _supported, \
+ }, \
+ __VA_ARGS__ \
+};
+/* ------------------------------ PLL Divider ------------------------------- */
+
+/* ---------------------------------- CLK ----------------------------------- */
+/*
+ * The CM dividers do fixed-point division, so we can't use the
+ * generic integer divider code like the PLL dividers do (and we can't
+ * fake it by having some fixed shifts preceding it in the clock tree,
+ * because we'd run out of bits in a 32-bit rt_ubase_t).
+ */
+struct bcm2835_clock
+{
+ struct bcm2835_clock_data cdata;
+};
+
+rt_inline struct bcm2835_clock *cell_to_bcm2835_clock(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock_data *cdata = cell_to_bcm2835_clock_data(cell);
+
+ return rt_container_of(cdata, struct bcm2835_clock, cdata);
+}
+
+static rt_uint32_t bcm2835_clock_choose_div(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint64_t temp;
+ rt_uint32_t unused_frac_mask, div, mindiv, maxdiv;
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+
+ unused_frac_mask = RT_GENMASK(CM_DIV_FRAC_BITS - cdata->frac_bits, 0) >> 1;
+ temp = (rt_uint64_t)parent_rate << CM_DIV_FRAC_BITS;
+
+ rt_do_div(temp, rate);
+ div = temp;
+ div &= ~unused_frac_mask;
+
+ /* Different clamping limits apply for a mash clock */
+ if (cdata->is_mash_clock)
+ {
+ /* Clamp to min divider of 2 */
+ mindiv = 2 << CM_DIV_FRAC_BITS;
+ /* Clamp to the highest possible integer divider */
+ maxdiv = (RT_BIT(cdata->int_bits) - 1) << CM_DIV_FRAC_BITS;
+ }
+ else
+ {
+ /* Clamp to min divider of 1 */
+ mindiv = 1 << CM_DIV_FRAC_BITS;
+ /* Clamp to the highest possible fractional divider */
+ maxdiv = RT_GENMASK(cdata->int_bits + CM_DIV_FRAC_BITS - 1,
+ CM_DIV_FRAC_BITS - cdata->frac_bits);
+ }
+
+ /* Apply the clamping limits */
+ div = rt_max_t(rt_uint32_t, div, mindiv);
+ div = rt_min_t(rt_uint32_t, div, maxdiv);
+
+ return div;
+}
+
+static rt_ubase_t bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
+ rt_ubase_t parent_rate, rt_uint32_t div)
+{
+ rt_uint64_t temp;
+ struct bcm2835_clock_data *data = &clock->cdata;
+
+ if (data->int_bits == 0 && data->frac_bits == 0)
+ {
+ return parent_rate;
+ }
+
+ /*
+ * The divisor is a 12.12 fixed point field, but only some of
+ * the bits are populated in any given clock.
+ */
+ div >>= CM_DIV_FRAC_BITS - data->frac_bits;
+ div &= (1 << (data->int_bits + data->frac_bits)) - 1;
+
+ if (div == 0)
+ {
+ return 0;
+ }
+
+ temp = (rt_uint64_t)parent_rate << data->frac_bits;
+
+ rt_do_div(temp, div);
+
+ return temp;
+}
+
+static rt_ubase_t bcm2835_round_rate(rt_ubase_t rate)
+{
+ rt_ubase_t scaler = 1, limit;
+
+ limit = rate / 100000;
+
+ while (scaler < limit)
+ {
+ scaler *= 10;
+ }
+
+ /*
+ * If increasing a clock by less than 0.1% changes it
+ * from ..999.. to ..000.., round up.
+ */
+ if ((rate + scaler - 1) / scaler % 1000 == 0)
+ {
+ rate = rt_roundup(rate, scaler);
+ }
+
+ return rate;
+}
+
+static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
+{
+ rt_tick_t timeout;
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ timeout = rt_tick_from_millisecond(LOCK_TIMEOUT_US / 1000);
+ timeout += rt_tick_get();
+
+ while (cprman_read(cprman, cdata->ctl_reg) & CM_BUSY)
+ {
+ if (rt_tick_get() > timeout)
+ {
+ LOG_E("%s: couldn't lock PLL", cdata->cell.name);
+ return;
+ }
+
+ rt_hw_cpu_relax();
+ }
+}
+
+static void bcm2835_clock_off(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ cprman_write(cprman, cdata->ctl_reg,
+ cprman_read(cprman, cdata->ctl_reg) & ~CM_ENABLE);
+
+ /* BUSY will remain high until the divider completes its cycle. */
+ bcm2835_clock_wait_busy(clock);
+}
+
+static rt_err_t bcm2835_clock_on(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ cprman_write(cprman, cdata->ctl_reg,
+ cprman_read(cprman, cdata->ctl_reg) | CM_ENABLE | CM_GATE);
+
+ return RT_EOK;
+}
+
+static rt_bool_t bcm2835_clock_is_on(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ return (cprman_read(cprman, cdata->ctl_reg) & CM_ENABLE) != 0;
+}
+
+static rt_ubase_t bcm2835_clock_get_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_uint32_t div;
+ rt_ubase_t rate;
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ if (cdata->int_bits == 0 && cdata->frac_bits == 0)
+ {
+ return parent_rate;
+ }
+
+ div = cprman_read(cprman, cdata->div_reg);
+
+ rate = bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
+
+ if (cdata->round_up)
+ {
+ rate = bcm2835_round_rate(rate);
+ }
+
+ return rate;
+}
+
+static rt_ubase_t bcm2835_clock_get_rate_vpu(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ if (cprman->fw)
+ {
+ struct
+ {
+ rt_uint32_t id;
+ rt_uint32_t val;
+ } packet;
+
+ packet.id = VCMSG_ID_CORE_CLOCK;
+ packet.val = 0;
+
+ if (!rpi_firmware_property(cprman->fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ &packet, sizeof(packet)))
+ {
+ return packet.val;
+ }
+ }
+
+ return bcm2835_clock_get_rate(cell, parent_rate);
+}
+
+static rt_err_t bcm2835_clock_set_rate(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t div, ctl;
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ div = bcm2835_clock_choose_div(cell, rate, parent_rate);
+ ctl = cprman_read(cprman, cdata->ctl_reg);
+
+ /*
+ * If the clock is running, we have to pause clock generation while
+ * updating the control and div regs. This is glitchless (no clock
+ * signals generated faster than the rate) but each reg access is two
+ * OSC cycles so the clock will slow down for a moment.
+ */
+ if (ctl & CM_ENABLE)
+ {
+ cprman_write(cprman, cdata->ctl_reg, ctl & ~CM_ENABLE);
+ bcm2835_clock_wait_busy(clock);
+ }
+
+ ctl &= ~CM_FRAC;
+ ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+ cprman_write(cprman, cdata->ctl_reg, ctl);
+
+ cprman_write(cprman, cdata->div_reg, div);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_clock_set_parent(struct rt_clk_cell *cell, rt_uint8_t idx)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ cprman_write(cprman, cdata->ctl_reg, (idx << CM_SRC_SHIFT) & CM_SRC_MASK);
+
+ return RT_EOK;
+}
+
+static rt_uint8_t bcm2835_clock_get_parent(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock *clock = cell_to_bcm2835_clock(cell);
+ struct bcm2835_clock_data *cdata = &clock->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ return (cprman_read(cprman, cdata->ctl_reg) & CM_SRC_MASK) >> CM_SRC_SHIFT;
+}
+
+static const struct rt_clk_ops bcm2835_clock_clk_ops =
+{
+ .prepare = bcm2835_clock_on,
+ .unprepare = bcm2835_clock_off,
+ .is_prepared = bcm2835_clock_is_on,
+ .recalc_rate = bcm2835_clock_get_rate,
+ .set_rate = bcm2835_clock_set_rate,
+ .set_parent = bcm2835_clock_set_parent,
+ .get_parent = bcm2835_clock_get_parent,
+};
+
+static rt_bool_t bcm2835_vpu_clock_is_on(struct rt_clk_cell *cell)
+{
+ return RT_TRUE;
+}
+
+/*
+ * The VPU clock can never be disabled (it doesn't have an ENABLE bit),
+ * so it gets its own set of clock ops.
+ */
+static const struct rt_clk_ops bcm2835_vpu_clock_clk_ops =
+{
+ .is_prepared = bcm2835_vpu_clock_is_on,
+ .recalc_rate = bcm2835_clock_get_rate_vpu,
+ .set_rate = bcm2835_clock_set_rate,
+ .set_parent = bcm2835_clock_set_parent,
+ .get_parent = bcm2835_clock_get_parent,
+};
+
+static void bcm2835_clock_init(struct bcm2835_cprman *cprman, struct bcm2835_clock_data *cdata)
+{
+ struct rt_clk_cell *cell = &cdata->cell;
+
+ /*
+ * Some GPIO clocks for ethernet/wifi PLLs are marked as
+ * critical (since some platforms use them), but if the
+ * firmware didn't have them turned on then they clearly
+ * aren't actually critical.
+ */
+ if ((cprman_read(cprman, cdata->ctl_reg) & CM_ENABLE) == 0)
+ {
+ cell->flags &= ~RT_CLK_F_IS_CRITICAL;
+ }
+
+ /*
+ * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
+ * rate changes on at least of the parents.
+ */
+ if (cdata->set_rate_parent)
+ {
+ cell->flags |= RT_CLK_F_SET_RATE_PARENT;
+ }
+
+ if (cdata->is_vpu_clock)
+ {
+ cell->ops = &bcm2835_vpu_clock_clk_ops;
+ }
+ else
+ {
+ /* If the clock wasn't actually enabled at boot, it's not critical. */
+ if (!(cprman_read(cprman, cdata->ctl_reg) & CM_ENABLE))
+ {
+ cell->flags &= ~RT_CLK_F_IS_CRITICAL;
+ }
+ }
+}
+
+#define REGISTER_CLK(_struct, _name, _parents, _supported, _flags, ...) \
+static struct bcm2835_clock _struct = \
+{ \
+ .cdata = \
+ { \
+ .cell.name = _name, \
+ .cell.parents_nr = RT_ARRAY_SIZE(_parents), \
+ .cell.parent_names = _parents, \
+ .cell.ops = &bcm2835_clock_clk_ops, \
+ .cell.flags = RT_CLK_F_IGNORE_UNUSED | _flags, \
+ .init = bcm2835_clock_init, \
+ .supported = _supported, \
+ }, \
+ __VA_ARGS__ \
+};
+/* ---------------------------------- CLK ----------------------------------- */
+
+/* -------------------------------- PLL Gate -------------------------------- */
+struct bcm2835_gate_data
+{
+ struct bcm2835_clock_data cdata;
+};
+
+rt_inline struct bcm2835_gate_data *cell_to_bcm2835_gate_data(struct rt_clk_cell *cell)
+{
+ struct bcm2835_clock_data *cdata = cell_to_bcm2835_clock_data(cell);
+
+ return rt_container_of(cdata, struct bcm2835_gate_data, cdata);
+}
+
+static void bcm2835_clock_gate_endisable(struct rt_clk_cell *cell, int enable)
+{
+ rt_uint32_t value;
+ int set = 0 ^ enable;
+ struct bcm2835_gate_data *gate = cell_to_bcm2835_gate_data(cell);
+ struct bcm2835_clock_data *cdata = &gate->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ value = cprman_read(cprman, cdata->ctl_reg);
+ if (set)
+ {
+ value |= RT_BIT(CM_GATE_BIT);
+ }
+ else
+ {
+ value &= ~RT_BIT(CM_GATE_BIT);
+ }
+ cprman_write(cprman, cdata->ctl_reg, value);
+}
+
+static rt_err_t bcm2835_clock_gate_enable(struct rt_clk_cell *cell)
+{
+ bcm2835_clock_gate_endisable(cell, 1);
+
+ return RT_EOK;
+}
+
+static void bcm2835_clock_gate_disable(struct rt_clk_cell *cell)
+{
+ bcm2835_clock_gate_endisable(cell, 0);
+}
+
+static rt_bool_t bcm2835_clock_gate_is_enabled(struct rt_clk_cell *cell)
+{
+ rt_uint32_t value;
+ struct bcm2835_gate_data *gate = cell_to_bcm2835_gate_data(cell);
+ struct bcm2835_clock_data *cdata = &gate->cdata;
+ struct bcm2835_cprman *cprman = cdata->cprman;
+
+ value = cprman_read(cprman, cdata->ctl_reg);
+ value &= RT_BIT(CM_GATE_BIT);
+
+ return !!value;
+}
+
+const struct rt_clk_ops bcm2835_clock_gate_ops =
+{
+ .enable = bcm2835_clock_gate_enable,
+ .disable = bcm2835_clock_gate_disable,
+ .is_enabled = bcm2835_clock_gate_is_enabled,
+};
+
+#define REGISTER_GATE(_struct, _name, _parent, _supported, _flags, ...) \
+static struct bcm2835_gate_data _struct = \
+{ \
+ .cdata = \
+ { \
+ .cell.name = _name, \
+ .cell.ops = &bcm2835_clock_gate_ops, \
+ .cell.parents_nr = 1, \
+ .cell.parent_name = _parent, \
+ .cell.flags = RT_CLK_F_SET_RATE_GATE | \
+ RT_CLK_F_IGNORE_UNUSED | _flags, \
+ .supported = _supported, \
+ }, \
+ __VA_ARGS__ \
+};
+/* -------------------------------- PLL Gate -------------------------------- */
+
+/*
+ * PLLA is the auxiliary PLL, used to drive the CCP2
+ * (Compact Camera Port 2) transmitter clock.
+ *
+ * It is in the PX LDO power domain, which is on when the
+ * AUDIO domain is on.
+ */
+REGISTER_PLL(plla, "plla", SOC_ALL, 0,
+ .cm_ctrl_reg = CM_PLLA,
+ .a2w_ctrl_reg = A2W_PLLA_CTRL,
+ .frac_reg = A2W_PLLA_FRAC,
+ .ana_reg_base = A2W_PLLA_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKA,
+ .ana = &bcm2835_ana_default,
+ .min_rate = 600000000U,
+ .max_rate = 2400000000U,
+ .max_fb_rate = BCM2835_MAX_FB_RATE);
+/* PLLB is used for the ARM's clock. */
+REGISTER_PLL(pllb, "pllb", SOC_ALL, RT_CLK_F_GET_RATE_NOCACHE,
+ .cm_ctrl_reg = CM_PLLB,
+ .a2w_ctrl_reg = A2W_PLLB_CTRL,
+ .frac_reg = A2W_PLLB_FRAC,
+ .ana_reg_base = A2W_PLLB_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKB,
+ .ana = &bcm2835_ana_default,
+ .min_rate = 600000000U,
+ .max_rate = 3000000000U,
+ .max_fb_rate = BCM2835_MAX_FB_RATE);
+/*
+ * PLLC is the core PLL, used to drive the core VPU clock.
+ *
+ * It is in the PX LDO power domain, which is on when the
+ * AUDIO domain is on.
+ */
+REGISTER_PLL(pllc, "pllc", SOC_ALL, 0,
+ .cm_ctrl_reg = CM_PLLC,
+ .a2w_ctrl_reg = A2W_PLLC_CTRL,
+ .frac_reg = A2W_PLLC_FRAC,
+ .ana_reg_base = A2W_PLLC_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKC,
+ .ana = &bcm2835_ana_default,
+ .min_rate = 600000000U,
+ .max_rate = 3000000000U,
+ .max_fb_rate = BCM2835_MAX_FB_RATE);
+/*
+ * PLLD is the display PLL, used to drive DSI display panels.
+ *
+ * It is in the PX LDO power domain, which is on when the
+ * AUDIO domain is on.
+ */
+REGISTER_PLL(plld, "plld", SOC_ALL, 0,
+ .cm_ctrl_reg = CM_PLLD,
+ .a2w_ctrl_reg = A2W_PLLD_CTRL,
+ .frac_reg = A2W_PLLD_FRAC,
+ .ana_reg_base = A2W_PLLD_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKD,
+ .ana = &bcm2835_ana_default,
+ .min_rate = 600000000U,
+ .max_rate = 2400000000U,
+ .max_fb_rate = BCM2835_MAX_FB_RATE);
+
+/*
+ * PLLH is used to supply the pixel clock or the AUX clock for the
+ * TV encoder.
+ *
+ * It is in the HDMI power domain.
+ */
+REGISTER_PLL(pllh, "pllh", SOC_TYPE_BCM2835, 0,
+ .cm_ctrl_reg = CM_PLLH,
+ .a2w_ctrl_reg = A2W_PLLH_CTRL,
+ .frac_reg = A2W_PLLH_FRAC,
+ .ana_reg_base = A2W_PLLH_ANA0,
+ .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+ .lock_mask = CM_LOCK_FLOCKH,
+ .ana = &bcm2835_ana_pllh,
+ .min_rate = 600000000U,
+ .max_rate = 3000000000U,
+ .max_fb_rate = BCM2835_MAX_FB_RATE);
+
+REGISTER_PLL_DIV(plla_core, "plla_core", "plla", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLA,
+ .a2w_reg = A2W_PLLA_CORE,
+ .load_mask = CM_PLLA_LOADCORE,
+ .hold_mask = CM_PLLA_HOLDCORE,
+ .fixed_divider = 1);
+
+/*
+ * PLLA_PER is used for gpu clocks. Controlled by firmware, see
+ * clk-raspberrypi.c.
+ */
+REGISTER_PLL_DIV(plla_dsi0, "plla_dsi0", "plla", SOC_ALL, 0,
+ .cm_reg = CM_PLLA,
+ .a2w_reg = A2W_PLLA_DSI0,
+ .load_mask = CM_PLLA_LOADDSI0,
+ .hold_mask = CM_PLLA_HOLDDSI0,
+ .fixed_divider = 1);
+
+REGISTER_PLL_DIV(plla_ccp2, "plla_ccp2", "plla", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLA,
+ .a2w_reg = A2W_PLLA_CCP2,
+ .load_mask = CM_PLLA_LOADCCP2,
+ .hold_mask = CM_PLLA_HOLDCCP2,
+ .fixed_divider = 1);
+
+REGISTER_PLL_DIV(pllb_arm, "pllb_arm", "pllb", SOC_ALL, RT_CLK_F_SET_RATE_PARENT | RT_CLK_F_GET_RATE_NOCACHE,
+ .cm_reg = CM_PLLB,
+ .a2w_reg = A2W_PLLB_ARM,
+ .load_mask = CM_PLLB_LOADARM,
+ .hold_mask = CM_PLLB_HOLDARM,
+ .fixed_divider = 1);
+
+REGISTER_PLL_DIV(pllc_core0, "pllc_core0", "pllc", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_CORE0,
+ .load_mask = CM_PLLC_LOADCORE0,
+ .hold_mask = CM_PLLC_HOLDCORE0,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(pllc_core1, "pllc_core1", "pllc", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_CORE1,
+ .load_mask = CM_PLLC_LOADCORE1,
+ .hold_mask = CM_PLLC_HOLDCORE1,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(pllc_core2, "pllc_core2", "pllc", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_CORE2,
+ .load_mask = CM_PLLC_LOADCORE2,
+ .hold_mask = CM_PLLC_HOLDCORE2,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(pllc_per, "pllc_per", "pllc", SOC_ALL, RT_CLK_F_IS_CRITICAL | RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLC,
+ .a2w_reg = A2W_PLLC_PER,
+ .load_mask = CM_PLLC_LOADPER,
+ .hold_mask = CM_PLLC_HOLDPER,
+ .fixed_divider = 1);
+
+REGISTER_PLL_DIV(plld_core, "plld_core", "plld", SOC_ALL, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_CORE,
+ .load_mask = CM_PLLD_LOADCORE,
+ .hold_mask = CM_PLLD_HOLDCORE,
+ .fixed_divider = 1);
+/*
+ * VPU firmware assumes that PLLD_PER isn't disabled by the ARM core.
+ * Otherwise this could cause firmware lookups. That's why we mark
+ * it as critical.
+ */
+REGISTER_PLL_DIV(plld_per, "plld_per", "plld", SOC_ALL, RT_CLK_F_IS_CRITICAL | RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_PER,
+ .load_mask = CM_PLLD_LOADPER,
+ .hold_mask = CM_PLLD_HOLDPER,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(plld_dsi0, "plld_dsi0", "plld", SOC_ALL, 0,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_DSI0,
+ .load_mask = CM_PLLD_LOADDSI0,
+ .hold_mask = CM_PLLD_HOLDDSI0,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(plld_dsi1, "plld_dsi1", "plld", SOC_ALL, 0,
+ .cm_reg = CM_PLLD,
+ .a2w_reg = A2W_PLLD_DSI1,
+ .load_mask = CM_PLLD_LOADDSI1,
+ .hold_mask = CM_PLLD_HOLDDSI1,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(pllh_rcal, "pllh_rcal", "pllh", SOC_TYPE_BCM2835, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_RCAL,
+ .load_mask = CM_PLLH_LOADRCAL,
+ .hold_mask = 0,
+ .fixed_divider = 10);
+REGISTER_PLL_DIV(pllh_aux, "pllh_aux", "pllh", SOC_TYPE_BCM2835, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_AUX,
+ .load_mask = CM_PLLH_LOADAUX,
+ .hold_mask = 0,
+ .fixed_divider = 1);
+REGISTER_PLL_DIV(pllh_pix, "pllh_pix", "pllh", SOC_TYPE_BCM2835, RT_CLK_F_SET_RATE_PARENT,
+ .cm_reg = CM_PLLH,
+ .a2w_reg = A2W_PLLH_PIX,
+ .load_mask = CM_PLLH_LOADPIX,
+ .hold_mask = 0,
+ .fixed_divider = 10);
+
+/* Main oscillator parent mux */
+static const char *const bcm2835_clock_osc_parents[] =
+{
+ "gnd", "osc", "testdebug0", "testdebug1"
+};
+
+/* One Time Programmable Memory clock. Maximum 10Mhz. */
+REGISTER_CLK(clock_otp, "otp", bcm2835_clock_osc_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_OTPCTL,
+ .cdata.div_reg = CM_OTPDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 0,
+ .cdata.tcnt_mux = 6);
+/*
+ * Used for a 1Mhz clock for the system clocksource, and also used
+ * bythe watchdog timer and the camera pulse generator.
+ */
+REGISTER_CLK(clock_timer, "timer", bcm2835_clock_osc_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_TIMERCTL,
+ .cdata.div_reg = CM_TIMERDIV,
+ .cdata.int_bits = 6,
+ .cdata.frac_bits = 12);
+/*
+ * Clock for the temperature sensor.
+ * Generally run at 2Mhz, max 5Mhz.
+ */
+REGISTER_CLK(clock_tsens, "tsens", bcm2835_clock_osc_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_TSENSCTL,
+ .cdata.div_reg = CM_TSENSDIV,
+ .cdata.int_bits = 5,
+ .cdata.frac_bits = 0);
+REGISTER_CLK(clock_tec, "tec", bcm2835_clock_osc_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_TECCTL,
+ .cdata.div_reg = CM_TECDIV,
+ .cdata.int_bits = 6,
+ .cdata.frac_bits = 0);
+
+/* Main peripherial parent mux */
+static const char *const bcm2835_clock_per_parents[] =
+{
+ "gnd", "osc", "testdebug0", "testdebug1", "plla_per", "pllc_per", "plld_per", "pllh_aux",
+};
+
+/* Clocks with per parent mux */
+REGISTER_CLK(clock_aveo, "aveo", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_AVEOCTL,
+ .cdata.div_reg = CM_AVEODIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 0,
+ .cdata.tcnt_mux = 38);
+REGISTER_CLK(clock_cam0, "cam0", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_CAM0CTL,
+ .cdata.div_reg = CM_CAM0DIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 14);
+REGISTER_CLK(clock_cam1, "cam1", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_CAM1CTL,
+ .cdata.div_reg = CM_CAM1DIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 15);
+REGISTER_CLK(clock_dft, "dft", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DFTCTL,
+ .cdata.div_reg = CM_DFTDIV,
+ .cdata.int_bits = 5,
+ .cdata.frac_bits = 0);
+REGISTER_CLK(clock_dpi, "dpi", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DPICTL,
+ .cdata.div_reg = CM_DPIDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 17);
+
+/* Arasan EMMC clock */
+REGISTER_CLK(clock_emmc, "emmc", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_EMMCCTL,
+ .cdata.div_reg = CM_EMMCDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 39);
+
+/* EMMC2 clock (only available for BCM2711) */
+REGISTER_CLK(clock_emmc2, "emmc2", bcm2835_clock_per_parents, SOC_TYPE_BCM2711, 0,
+ .cdata.ctl_reg = CM_EMMC2CTL,
+ .cdata.div_reg = CM_EMMC2DIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 42);
+
+/* General purpose (GPIO) clocks */
+REGISTER_CLK(clock_gp0, "gp0", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_GP0CTL,
+ .cdata.div_reg = CM_GP0DIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12,
+ .cdata.is_mash_clock = RT_TRUE,
+ .cdata.tcnt_mux = 20);
+REGISTER_CLK(clock_gp1, "gp1", bcm2835_clock_per_parents, SOC_ALL, RT_CLK_F_IS_CRITICAL,
+ .cdata.ctl_reg = CM_GP1CTL,
+ .cdata.div_reg = CM_GP1DIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12,
+ .cdata.is_mash_clock = RT_TRUE,
+ .cdata.tcnt_mux = 21);
+REGISTER_CLK(clock_gp2, "gp2", bcm2835_clock_per_parents, SOC_ALL, RT_CLK_F_IS_CRITICAL,
+ .cdata.ctl_reg = CM_GP2CTL,
+ .cdata.div_reg = CM_GP2DIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12);
+
+/* HDMI state machine */
+REGISTER_CLK(clock_hsm, "hsm", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_HSMCTL,
+ .cdata.div_reg = CM_HSMDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 22);
+REGISTER_CLK(clock_pwm, "pwm", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_PWMCTL,
+ .cdata.div_reg = CM_PWMDIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12,
+ .cdata.is_mash_clock = RT_TRUE,
+ .cdata.tcnt_mux = 24);
+REGISTER_CLK(clock_slim, "slim", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_SLIMCTL,
+ .cdata.div_reg = CM_SLIMDIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12,
+ .cdata.is_mash_clock = RT_TRUE,
+ .cdata.tcnt_mux = 25);
+REGISTER_CLK(clock_smi, "smi", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_SMICTL,
+ .cdata.div_reg = CM_SMIDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 27);
+REGISTER_CLK(clock_uart, "uart", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_UARTCTL,
+ .cdata.div_reg = CM_UARTDIV,
+ .cdata.int_bits = 10,
+ .cdata.frac_bits = 12,
+ .cdata.tcnt_mux = 28,
+ .cdata.round_up = RT_TRUE);
+
+/* Dsi clocks */
+REGISTER_CLK(clock_dsi0e, "dsi0e", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DSI0ECTL,
+ .cdata.div_reg = CM_DSI0EDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 18);
+REGISTER_CLK(clock_dsi1e, "dsi1e", bcm2835_clock_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DSI1ECTL,
+ .cdata.div_reg = CM_DSI1EDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 19);
+
+/*
+ * Restrict clock sources for the PCM peripheral to the oscillator and
+ * PLLD_PER because other source may have varying rates or be switched
+ * off.
+ *
+ * Prevent other sources from being selected by replacing their names in
+ * the list of potential parents with dummy entries (entry index is
+ * significant).
+ */
+static const char *const bcm2835_pcm_per_parents[] =
+{
+ "-", "osc", "-", "-", "-", "-", "plld_per", "-",
+};
+
+REGISTER_CLK(clock_pcm, "pcm", bcm2835_pcm_per_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_PCMCTL,
+ .cdata.div_reg = CM_PCMDIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 12,
+ .cdata.is_mash_clock = RT_TRUE,
+ .cdata.low_jitter = RT_TRUE,
+ .cdata.tcnt_mux = 23);
+
+/* Main vpu parent mux */
+static const char *const bcm2835_clock_vpu_parents[] =
+{
+ "gnd", "osc", "testdebug0", "testdebug1", "plla_core", "pllc_core0",
+ "plld_core", "pllh_aux", "pllc_core1", "pllc_core2",
+};
+
+/* Clocks with vpu parent mux */
+REGISTER_CLK(clock_h264, "h264", bcm2835_clock_vpu_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_H264CTL,
+ .cdata.div_reg = CM_H264DIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 1);
+REGISTER_CLK(clock_isp, "isp", bcm2835_clock_vpu_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_ISPCTL,
+ .cdata.div_reg = CM_ISPDIV,
+ .cdata.int_bits = 4,
+ .cdata.frac_bits = 8,
+ .cdata.tcnt_mux = 2);
+
+/*
+ * Secondary SDRAM clock. Used for low-voltage modes when the PLL
+ * in the SDRAM controller can't be used.
+ */
+REGISTER_CLK(clock_sdram, "sdram", bcm2835_clock_vpu_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_SDCCTL,
+ .cdata.div_reg = CM_SDCDIV,
+ .cdata.int_bits = 6,
+ .cdata.frac_bits = 0,
+ .cdata.tcnt_mux = 3);
+/*
+ * CLOCK_V3D is used for v3d clock. Controlled by firmware, see
+ * clk-raspberrypi.c.
+ */
+
+/*
+ * VPU clock. This doesn't have an enable bit, since it drives
+ * the bus for everything else, and is special so it doesn't need
+ * to be gated for rate changes. It is also known as "clk_audio"
+ * in various hardware documentation.
+ */
+REGISTER_CLK(clock_vpu, "vpu", bcm2835_clock_vpu_parents, SOC_ALL, RT_CLK_F_IS_CRITICAL,
+ .cdata.ctl_reg = CM_VPUCTL,
+ .cdata.div_reg = CM_VPUDIV,
+ .cdata.int_bits = 12,
+ .cdata.frac_bits = 8,
+ .cdata.is_vpu_clock = RT_TRUE,
+ .cdata.tcnt_mux = 5);
+
+/*
+ * DSI parent clocks. The DSI byte/DDR/DDR2 clocks come from the DSI
+ * analog PHY. The _inv variants are generated internally to cprman,
+ * but we don't use them so they aren't hooked up.
+ */
+static const char *const bcm2835_clock_dsi0_parents[] =
+{
+ "gnd", "osc", "testdebug0", "testdebug1", "dsi0_ddr", "dsi0_ddr_inv", "dsi0_ddr2",
+ "dsi0_ddr2_inv", "dsi0_byte", "dsi0_byte_inv",
+};
+
+REGISTER_CLK(clock_dsi0p, "dsi0p", bcm2835_clock_dsi0_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DSI0PCTL,
+ .cdata.div_reg = CM_DSI0PDIV,
+ .cdata.int_bits = 0,
+ .cdata.frac_bits = 0,
+ .cdata.tcnt_mux = 12);
+
+static const char *const bcm2835_clock_dsi1_parents[] =
+{
+ "gnd", "osc", "testdebug0", "testdebug1", "dsi1_ddr", "dsi1_ddr_inv", "dsi1_ddr2",
+ "dsi1_ddr2_inv", "dsi1_byte", "dsi1_byte_inv",
+};
+
+REGISTER_CLK(clock_dsi1p, "dsi1p", bcm2835_clock_dsi1_parents, SOC_ALL, 0,
+ .cdata.ctl_reg = CM_DSI1PCTL,
+ .cdata.div_reg = CM_DSI1PDIV,
+ .cdata.int_bits = 0,
+ .cdata.frac_bits = 0,
+ .cdata.tcnt_mux = 13);
+/*
+ * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
+ * you have the debug bit set in the power manager, which we
+ * don't bother exposing) are individual gates off of the
+ * non-stop vpu clock.
+ */
+REGISTER_GATE(clock_peri_image, "peri_image", "vpu", SOC_ALL, 0,
+ .cdata.ctl_reg = CM_PERIICTL);
+
+static struct rt_clk_cell *bcm2835_clk_cell[] =
+{
+ [BCM2835_PLLA] = &plla.cdata.cell,
+ [BCM2835_PLLB] = &pllb.cdata.cell,
+ [BCM2835_PLLC] = &pllc.cdata.cell,
+ [BCM2835_PLLD] = &plld.cdata.cell,
+ [BCM2835_PLLH] = &pllh.cdata.cell,
+
+ [BCM2835_PLLA_CORE] = &plla_core.cdata.cell,
+ [BCM2835_PLLA_DSI0] = &plla_dsi0.cdata.cell,
+ [BCM2835_PLLA_CCP2] = &plla_ccp2.cdata.cell,
+ [BCM2835_PLLB_ARM] = &pllb_arm.cdata.cell,
+ [BCM2835_PLLC_CORE0] = &pllc_core0.cdata.cell,
+ [BCM2835_PLLC_CORE1] = &pllc_core1.cdata.cell,
+ [BCM2835_PLLC_CORE2] = &pllc_core2.cdata.cell,
+ [BCM2835_PLLC_PER] = &pllc_per.cdata.cell,
+ [BCM2835_PLLD_CORE] = &plld_core.cdata.cell,
+ [BCM2835_PLLD_PER] = &plld_per.cdata.cell,
+ [BCM2835_PLLD_DSI0] = &plld_dsi0.cdata.cell,
+ [BCM2835_PLLD_DSI1] = &plld_dsi1.cdata.cell,
+ [BCM2835_PLLH_RCAL] = &pllh_rcal.cdata.cell,
+ [BCM2835_PLLH_AUX] = &pllh_aux.cdata.cell,
+ [BCM2835_PLLH_PIX] = &pllh_pix.cdata.cell,
+
+ [BCM2835_CLOCK_OTP] = &clock_otp.cdata.cell,
+ [BCM2835_CLOCK_TIMER] = &clock_timer.cdata.cell,
+ [BCM2835_CLOCK_TSENS] = &clock_tsens.cdata.cell,
+ [BCM2835_CLOCK_TEC] = &clock_tec.cdata.cell,
+ [BCM2835_CLOCK_AVEO] = &clock_aveo.cdata.cell,
+ [BCM2835_CLOCK_CAM0] = &clock_cam0.cdata.cell,
+ [BCM2835_CLOCK_CAM1] = &clock_cam1.cdata.cell,
+ [BCM2835_CLOCK_DFT] = &clock_dft.cdata.cell,
+ [BCM2835_CLOCK_DPI] = &clock_dpi.cdata.cell,
+ [BCM2835_CLOCK_EMMC] = &clock_emmc.cdata.cell,
+ [BCM2711_CLOCK_EMMC2] = &clock_emmc2.cdata.cell,
+ [BCM2835_CLOCK_GP0] = &clock_gp0.cdata.cell,
+ [BCM2835_CLOCK_GP1] = &clock_gp1.cdata.cell,
+ [BCM2835_CLOCK_GP2] = &clock_gp2.cdata.cell,
+ [BCM2835_CLOCK_HSM] = &clock_hsm.cdata.cell,
+ [BCM2835_CLOCK_PWM] = &clock_pwm.cdata.cell,
+ [BCM2835_CLOCK_SLIM] = &clock_slim.cdata.cell,
+ [BCM2835_CLOCK_SMI] = &clock_smi.cdata.cell,
+ [BCM2835_CLOCK_UART] = &clock_uart.cdata.cell,
+ [BCM2835_CLOCK_DSI0E] = &clock_dsi0e.cdata.cell,
+ [BCM2835_CLOCK_DSI1E] = &clock_dsi1e.cdata.cell,
+ [BCM2835_CLOCK_PCM] = &clock_pcm.cdata.cell,
+ [BCM2835_CLOCK_H264] = &clock_h264.cdata.cell,
+ [BCM2835_CLOCK_ISP] = &clock_isp.cdata.cell,
+ [BCM2835_CLOCK_SDRAM] = &clock_sdram.cdata.cell,
+ [BCM2835_CLOCK_VPU] = &clock_vpu.cdata.cell,
+ [BCM2835_CLOCK_DSI0P] = &clock_dsi0p.cdata.cell,
+ [BCM2835_CLOCK_DSI1P] = &clock_dsi1p.cdata.cell,
+
+ [BCM2835_CLOCK_PERI_IMAGE] = &clock_peri_image.cdata.cell,
+};
+
+static rt_bool_t bcm2835_clk_claimed[RT_ARRAY_SIZE(bcm2835_clk_cell)];
+
+static rt_bool_t bcm2835_clk_is_claimed(const char *name)
+{
+ for (int i = 0; i < RT_ARRAY_SIZE(bcm2835_clk_cell); ++i)
+ {
+ if (bcm2835_clk_cell[i])
+ {
+ if (!rt_strcmp(name, bcm2835_clk_cell[i]->name))
+ {
+ return bcm2835_clk_claimed[i];
+ }
+ }
+ }
+
+ return RT_FALSE;
+}
+
+/*
+ * Permanently take a reference on the parent of the SDRAM clock.
+ *
+ * While the SDRAM is being driven by its dedicated PLL most of the
+ * time, there is a little loop running in the firmware that
+ * periodically switches the SDRAM to using our CM clock to do PVT
+ * recalibration, with the assumption that the previously configured
+ * SDRAM parent is still enabled and running.
+ */
+static void bcm2835_mark_sdc_parent_critical(struct rt_clk_cell *cell)
+{
+ struct rt_clk_cell *parent = rt_clk_cell_get_parent(cell);
+
+ if (parent)
+ {
+ rt_clk_prepare_enable(parent->clk);
+ }
+}
+
+static rt_err_t bcm2835_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t value;
+ struct rt_clk_cell *cell;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct bcm2835_clock_data *cdata;
+ const struct cprman_soc_data *pdata = pdev->id->data;
+ struct bcm2835_cprman *cprman = rt_calloc(1, sizeof(*cprman));
+
+ if (!cprman)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pdata = pdev->id->data;
+ cprman->soc = pdata->soc;
+
+ cprman->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!cprman->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if ((fw_np = rt_ofw_parse_phandle(np, "firmware", 0)))
+ {
+ if (!(cprman->fw = rpi_firmware_get(fw_np)))
+ {
+ err = -RT_ENOSYS;
+ goto _fail;
+ }
+
+ rt_ofw_node_put(fw_np);
+ }
+
+ /* Mux DSI0 clock to PLLD */
+ cprman_write(cprman, CM_DSI0HSCK, 1);
+
+ rt_memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed));
+
+ for (int i = 0; !rt_dm_dev_prop_read_u32_index(dev, "claim-clocks", i, &value); ++i)
+ {
+ bcm2835_clk_claimed[value]= RT_TRUE;
+ }
+
+ rt_memcpy(cprman->real_parent_names, cprman_parent_names, sizeof(cprman_parent_names));
+
+ for (int i = 0; i < RT_ARRAY_SIZE(cprman_parent_names); ++i)
+ {
+ if (!(cprman->real_parent_names[i] = rt_ofw_clk_get_parent_name(np, i)))
+ {
+ break;
+ }
+ }
+
+ /*
+ * Make sure the external oscillator has been registered.
+ *
+ * The other (DSI) clocks are not present on older device
+ * trees, which we still need to support for backwards
+ * compatibility.
+ */
+ if (!cprman->real_parent_names[0])
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(bcm2835_clk_cell); ++i)
+ {
+ cell = bcm2835_clk_cell[i];
+
+ if (!cell)
+ {
+ continue;
+ }
+
+ cdata = cell_to_bcm2835_clock_data(cell);
+
+ if (cdata->supported & cprman->soc)
+ {
+ cdata->cprman = cprman;
+
+ if (cdata->init)
+ {
+ cdata->init(cprman, cdata);
+ }
+ }
+ else
+ {
+ bcm2835_clk_cell[i] = RT_NULL;
+ }
+ }
+
+ cprman->parent.dev = dev;
+ cprman->parent.cells = bcm2835_clk_cell;
+ cprman->parent.cells_nr = RT_ARRAY_SIZE(bcm2835_clk_cell);
+
+ if ((err = rt_clk_register(&cprman->parent)))
+ {
+ goto _fail;
+ }
+
+ bcm2835_mark_sdc_parent_critical(bcm2835_clk_cell[BCM2835_CLOCK_SDRAM]);
+
+ return RT_EOK;
+
+_fail:
+ if (cprman->fw)
+ {
+ rpi_firmware_put(cprman->fw);
+ }
+
+ if (cprman->regs)
+ {
+ rt_iounmap(cprman->regs);
+ }
+
+ rt_free(cprman);
+
+ return err;
+}
+
+static const struct cprman_soc_data cprman_bcm2835_plat_data =
+{
+ .soc = SOC_TYPE_BCM2835,
+};
+
+static const struct cprman_soc_data cprman_bcm2711_plat_data =
+{
+ .soc = SOC_TYPE_BCM2711,
+};
+
+static const struct rt_ofw_node_id bcm2835_clk_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
+ { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
+ { /* Sentinel */ }
+};
+
+static struct rt_platform_driver clk_bcm2835_driver =
+{
+ .name = "clk-bcm2835",
+ .ids = bcm2835_clk_ofw_ids,
+
+ .probe = bcm2835_clk_probe,
+};
+
+static int clk_bcm2835_register(void)
+{
+ rt_platform_driver_register(&clk_bcm2835_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(clk_bcm2835_register);
diff --git a/bsp/raspberry-pi/dm/clk/clk-dsi.c b/bsp/raspberry-pi/dm/clk/clk-dsi.c
new file mode 100755
index 0000000000..3a17849a96
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-dsi.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.dsi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+struct dsi_clk
+{
+ struct rt_clk_node parent;
+};
+
+struct dsi_clk_output
+{
+ struct rt_clk_cell cell;
+
+ rt_ubase_t div;
+};
+
+static rt_ubase_t dsi_clk_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct dsi_clk_output *clk = rt_container_of(cell, struct dsi_clk_output, cell);
+
+ return parent_rate / clk->div;
+}
+
+static rt_base_t dsi_clk_round_rate(struct rt_clk_cell *cell, rt_ubase_t drate, rt_ubase_t *prate)
+{
+ struct dsi_clk_output *clk = rt_container_of(cell, struct dsi_clk_output, cell);
+
+ return *prate / clk->div;
+}
+
+const struct rt_clk_ops dsi_clk_ops =
+{
+ .recalc_rate = dsi_clk_recalc_rate,
+ .round_rate = dsi_clk_round_rate,
+};
+
+#define REGISTER_CLK_DSI(_name, _div) \
+(void *)&(struct dsi_clk_output) \
+{ \
+ .cell.name = _name, \
+ .cell.ops = &dsi_clk_ops, \
+ .div = _div, \
+}
+
+static struct rt_clk_cell *dsi0_clk_cell[] =
+{
+ REGISTER_CLK_DSI("dsi0_byte", 8),
+ REGISTER_CLK_DSI("dsi0_ddr2", 4),
+ REGISTER_CLK_DSI("dsi0_ddr", 2),
+};
+
+static struct rt_clk_cell *dsi1_clk_cell[] =
+{
+ REGISTER_CLK_DSI("dsi1_byte", 8),
+ REGISTER_CLK_DSI("dsi1_ddr2", 4),
+ REGISTER_CLK_DSI("dsi1_ddr", 2),
+};
+
+static rt_err_t dsi_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_clk_cell **dsi_clk_cell = (void *)pdev->id->data;
+ struct dsi_clk *dclk = rt_calloc(1, sizeof(*dclk));
+
+ if (!dclk)
+ {
+ return -RT_ENOMEM;
+ }
+
+ for (int i = 0; i < 3; ++i)
+ {
+ struct dsi_clk_output *clk = rt_container_of(dsi_clk_cell[i], struct dsi_clk_output, cell);
+
+ rt_dm_dev_prop_read_string_index(dev, "clock-output-names", i, &clk->cell.name);
+ }
+
+ dclk->parent.dev = dev;
+ dclk->parent.cells = dsi_clk_cell;
+ dclk->parent.cells_nr = 3;
+ dclk->parent.parents_clk = rt_err_ptr(-RT_EEMPTY);
+
+ if ((err = rt_clk_register(&dclk->parent)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+_fail:
+ rt_free(dclk);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id dsi_clk_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-dsi0", .data = dsi0_clk_cell },
+ { .compatible = "brcm,bcm2835-dsi1", .data = dsi1_clk_cell },
+ { .compatible = "brcm,bcm2711-dsi0", .data = dsi0_clk_cell },
+ { .compatible = "brcm,bcm2711-dsi1", .data = dsi1_clk_cell },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver dsi_clk_driver =
+{
+ .name = "clk-dsi",
+ .ids = dsi_clk_ofw_ids,
+
+ .probe = dsi_clk_probe,
+};
+
+static int dsi_clk_register(void)
+{
+ struct rt_ofw_node *np = RT_NULL;
+
+ rt_platform_driver_register(&dsi_clk_driver);
+
+ /* Force probing of the DSIx clock */
+ while ((np = rt_ofw_find_node_by_ids(np, dsi_clk_ofw_ids)))
+ {
+ rt_platform_ofw_device_probe_child(np);
+ }
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(dsi_clk_register);
diff --git a/bsp/raspberry-pi/dm/clk/clk-raspberrypi.c b/bsp/raspberry-pi/dm/clk/clk-raspberrypi.c
new file mode 100755
index 0000000000..d6d43fb9e3
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-raspberrypi.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.raspberrypi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <drivers/byteorder.h>
+#include <firmware-raspberrypi.h>
+
+#define RPI_FIRMWARE_STATE_ENABLE_BIT RT_BIT(0)
+#define RPI_FIRMWARE_STATE_WAIT_BIT RT_BIT(1)
+
+/*
+ * Structure of the message passed to Raspberry Pi's firmware in order to
+ * change clock rates. The 'disable_turbo' option is only available to the ARM
+ * clock (pllb) which we enable by default as turbo mode will alter multiple
+ * clocks at once.
+ *
+ * Even though we're able to access the clock registers directly we're bound to
+ * use the firmware interface as the firmware ultimately takes care of
+ * mitigating overheating/undervoltage situations and we would be changing
+ * frequencies behind his back.
+ *
+ * For more information on the firmware interface check:
+ * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
+ */
+rt_packed(struct raspberrypi_firmware_prop
+{
+ rt_le32_t id;
+ rt_le32_t val;
+ rt_le32_t disable_turbo;
+});
+
+struct rpi_firmware_get_clocks_response
+{
+ rt_uint32_t parent;
+ rt_uint32_t id;
+};
+
+struct raspberrypi_clk_data
+{
+ struct rt_clk_cell cell;
+
+ rt_uint32_t id;
+ rt_bool_t export;
+ rt_bool_t minimize;
+ rt_ubase_t min_rate;
+};
+
+#define cell_to_raspberrypi_clk_data(cell) rt_container_of(cell, struct raspberrypi_clk_data, cell)
+
+struct raspberrypi_clk
+{
+ struct rt_clk_node parent;
+
+ struct rpi_firmware *rpi_fw;
+};
+
+#define raw_to_raspberrypi_clk(raw) rt_container_of(raw, struct raspberrypi_clk, parent)
+
+static rt_err_t raspberrypi_clock_property(struct rpi_firmware *firmware,
+ struct raspberrypi_clk_data *data, rt_uint32_t tag, rt_uint32_t *val)
+{
+ rt_err_t err;
+ struct raspberrypi_firmware_prop msg =
+ {
+ .id = rt_cpu_to_le32(data->id),
+ .val = rt_cpu_to_le32(*val),
+ .disable_turbo = rt_cpu_to_le32(0),
+ };
+
+ if ((err = rpi_firmware_property(firmware, tag, &msg, sizeof(msg))))
+ {
+ return err;
+ }
+
+ *val = rt_le32_to_cpu(msg.val);
+
+ return RT_EOK;
+}
+
+static rt_bool_t raspberrypi_fw_is_prepared(struct rt_clk_cell *cell)
+{
+ rt_err_t err;
+ rt_uint32_t val = 0;
+ struct raspberrypi_clk_data *data = cell_to_raspberrypi_clk_data(cell);
+ struct raspberrypi_clk *rpi_clk = raw_to_raspberrypi_clk(cell->clk_np);
+
+ if ((err = raspberrypi_clock_property(rpi_clk->rpi_fw, data,
+ RPI_FIRMWARE_GET_CLOCK_STATE, &val)))
+ {
+ return RT_FALSE;
+ }
+
+ return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
+}
+
+static rt_ubase_t raspberrypi_fw_get_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_err_t err;
+ rt_uint32_t val = 0;
+ struct raspberrypi_clk_data *data = cell_to_raspberrypi_clk_data(cell);
+ struct raspberrypi_clk *rpi_clk = raw_to_raspberrypi_clk(cell->clk_np);
+
+ if ((err = raspberrypi_clock_property(rpi_clk->rpi_fw, data,
+ RPI_FIRMWARE_GET_CLOCK_RATE, &val)))
+ {
+ return -RT_EIO;
+ }
+
+ return val;
+}
+
+static rt_err_t raspberrypi_fw_set_rate(struct rt_clk_cell *cell,
+ rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_err_t err;
+ rt_uint32_t in_rate = rate;
+ struct raspberrypi_clk_data *data = cell_to_raspberrypi_clk_data(cell);
+ struct raspberrypi_clk *rpi_clk = raw_to_raspberrypi_clk(cell->clk_np);
+
+ if ((err = raspberrypi_clock_property(rpi_clk->rpi_fw, data,
+ RPI_FIRMWARE_SET_CLOCK_RATE, &in_rate)))
+ {
+ return err;
+ }
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops raspberrypi_firmware_clk_ops =
+{
+ .is_prepared = raspberrypi_fw_is_prepared,
+ .recalc_rate = raspberrypi_fw_get_rate,
+ .set_rate = raspberrypi_fw_set_rate,
+};
+
+#define REGISTER_CLK(_struct, _name, ...) \
+static struct raspberrypi_clk_data _struct = \
+{ \
+ .cell.name = _name, \
+ .cell.ops = &raspberrypi_firmware_clk_ops, \
+ .cell.flags = RT_CLK_F_GET_RATE_NOCACHE, \
+ __VA_ARGS__ \
+};
+
+REGISTER_CLK(clk_emmc, "emmc");
+REGISTER_CLK(clk_uart, "uart");
+REGISTER_CLK(clk_arm, "arm", .export = RT_TRUE);
+REGISTER_CLK(clk_core, "core",
+ .export = RT_TRUE,
+
+ /*
+ * The clock is shared between the HVS and the CSI
+ * controllers, on the BCM2711 and will change depending
+ * on the pixels composited on the HVS and the capture
+ * resolution on Unicam.
+ *
+ * Since the rate can get quite large, and we need to
+ * coordinate between both driver instances, let's
+ * always use the minimum the drivers will let us.
+ */
+ .minimize = RT_TRUE);
+REGISTER_CLK(clk_v3d, "v3d", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_h264, "h264");
+REGISTER_CLK(clk_isp, "isp", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_sdram, "sdram");
+REGISTER_CLK(clk_pixel, "pixel", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_pwm, "pwm");
+REGISTER_CLK(clk_hevc, "hevc", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_emmc2, "emmc2");
+REGISTER_CLK(clk_m2mc, "m2mc",
+ .export = RT_TRUE,
+ /*
+ * If we boot without any cable connected to any of the
+ * HDMI connector, the firmware will skip the HSM
+ * initialization and leave it with a rate of 0,
+ * resulting in a bus lockup when we're accessing the
+ * registers even if it's enabled.
+ *
+ * Let's put a sensible default so that we don't end up
+ * in this situation.
+ */
+ .min_rate = 120000000,
+ /*
+ * The clock is shared between the two HDMI controllers
+ * on the BCM2711 and will change depending on the
+ * resolution output on each. Since the rate can get
+ * quite large, and we need to coordinate between both
+ * driver instances, let's always use the minimum the
+ * drivers will let us.
+ */
+ .minimize = RT_TRUE);
+REGISTER_CLK(clk_pixel_bvb, "pixel-bvb", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_vec, "vec", .export = RT_TRUE, .minimize = RT_TRUE);
+REGISTER_CLK(clk_disp, "disp", .export = RT_TRUE, .minimize = RT_TRUE);
+
+static struct rt_clk_cell *raspberrypi_clk_cell[RPI_FIRMWARE_NUM_CLK_ID] =
+{
+ [RPI_FIRMWARE_EMMC_CLK_ID] = &clk_emmc.cell,
+ [RPI_FIRMWARE_UART_CLK_ID] = &clk_uart.cell,
+ [RPI_FIRMWARE_ARM_CLK_ID] = &clk_arm.cell,
+ [RPI_FIRMWARE_CORE_CLK_ID] = &clk_core.cell,
+ [RPI_FIRMWARE_V3D_CLK_ID] = &clk_v3d.cell,
+ [RPI_FIRMWARE_H264_CLK_ID] = &clk_h264.cell,
+ [RPI_FIRMWARE_ISP_CLK_ID] = &clk_isp.cell,
+ [RPI_FIRMWARE_SDRAM_CLK_ID] = &clk_sdram.cell,
+ [RPI_FIRMWARE_PIXEL_CLK_ID] = &clk_pixel.cell,
+ [RPI_FIRMWARE_PWM_CLK_ID] = &clk_pwm.cell,
+ [RPI_FIRMWARE_HEVC_CLK_ID] = &clk_hevc.cell,
+ [RPI_FIRMWARE_EMMC2_CLK_ID] = &clk_emmc2.cell,
+ [RPI_FIRMWARE_M2MC_CLK_ID] = &clk_m2mc.cell,
+ [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = &clk_pixel_bvb.cell,
+ [RPI_FIRMWARE_VEC_CLK_ID] = &clk_vec.cell,
+ [RPI_FIRMWARE_DISP_CLK_ID] = &clk_disp.cell,
+};
+
+struct rt_clk *raspberrypi_arm_clk_get(void)
+{
+ if (!clk_arm.cell.clk_np)
+ {
+ return RT_NULL;
+ }
+
+ return rt_clk_cell_get_clk(&clk_arm.cell, RT_NULL);
+}
+
+static rt_err_t raspberrypi_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_firmware_get_clocks_response *clks;
+ struct raspberrypi_clk *rpi_clk = rt_calloc(1, sizeof(*rpi_clk));
+
+ if (!rpi_clk)
+ {
+ return -RT_ENOMEM;
+ }
+
+ if (np)
+ {
+ fw_np = rt_ofw_get_parent(np);
+
+ if (fw_np)
+ {
+ rpi_clk->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+ }
+ }
+
+ if (!rpi_clk->rpi_fw)
+ {
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (fw_np)
+ {
+ rpi_clk->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+ }
+ }
+
+ if (!rpi_clk->rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (!(clks = rt_malloc(sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID)))
+ {
+ goto _fail;
+ }
+
+ if ((err = rpi_firmware_property(rpi_clk->rpi_fw, RPI_FIRMWARE_GET_CLOCKS,
+ clks, sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID)))
+ {
+ rt_free(clks);
+ goto _fail;
+ }
+
+ for (int i = 0; i < RPI_FIRMWARE_NUM_CLK_ID; ++i)
+ {
+ rt_uint32_t min_rate = 0, max_rate = 0;
+ struct rt_clk *clk;
+ struct rt_clk_cell *cell;
+ struct raspberrypi_clk_data *data;
+ struct rpi_firmware_get_clocks_response *clk_req = &clks[i];
+
+ if (!clk_req->id)
+ {
+ break;
+ }
+ cell = raspberrypi_clk_cell[clk_req->id];
+ if (!cell)
+ {
+ continue;
+ }
+
+ cell->clk_np = &rpi_clk->parent;
+ data = cell_to_raspberrypi_clk_data(cell);
+
+ data->id = clk_req->id;
+
+ if (raspberrypi_clock_property(rpi_clk->rpi_fw, data,
+ RPI_FIRMWARE_GET_MIN_CLOCK_RATE, &min_rate))
+ {
+ LOG_W("clock %u: get min rate failed", clk_req->id);
+ }
+
+ if (raspberrypi_clock_property(rpi_clk->rpi_fw, data,
+ RPI_FIRMWARE_GET_MAX_CLOCK_RATE, &max_rate))
+ {
+ LOG_W("clock %u: get max rate failed", clk_req->id);
+ }
+
+ if (!max_rate)
+ {
+ continue;
+ }
+
+ if (clk_req->id == RPI_FIRMWARE_M2MC_CLK_ID)
+ {
+ min_rate = rt_min_t(rt_uint32_t, min_rate, 120000000);
+ }
+
+ clk = rt_clk_cell_get_clk(cell, RT_NULL);
+
+ if (!clk)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ rt_clk_set_rate_range(clk, min_rate, max_rate);
+
+ if (data->min_rate)
+ {
+ rt_ubase_t rate;
+
+ rt_clk_set_rate_range(clk, data->min_rate, max_rate);
+
+ rate = raspberrypi_fw_get_rate(cell, 0);
+ if (rate != (rt_ubase_t)-RT_EIO && rate < data->min_rate)
+ {
+ raspberrypi_fw_set_rate(cell, data->min_rate, 0);
+ }
+ }
+ }
+
+ rt_free(clks);
+
+ rpi_clk->parent.dev = dev;
+ rpi_clk->parent.cells = raspberrypi_clk_cell;
+ rpi_clk->parent.cells_nr = RT_ARRAY_SIZE(raspberrypi_clk_cell);
+
+ if ((err = rt_clk_register(&rpi_clk->parent)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (rpi_clk->rpi_fw)
+ {
+ rpi_firmware_put(rpi_clk->rpi_fw);
+ }
+
+ rt_free(rpi_clk);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id raspberrypi_clk_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,firmware-clocks" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver raspberrypi_clk_driver =
+{
+ .name = "clk-raspberrypi",
+ .ids = raspberrypi_clk_ofw_ids,
+
+ .probe = raspberrypi_clk_probe,
+};
+
+static int raspberrypi_clk_register(void)
+{
+ rt_platform_driver_register(&raspberrypi_clk_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(raspberrypi_clk_register);
diff --git a/bsp/raspberry-pi/dm/clk/clk-rp1.c b/bsp/raspberry-pi/dm/clk/clk-rp1.c
new file mode 100755
index 0000000000..719763e23a
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clk/clk-rp1.c
@@ -0,0 +1,1797 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "clk.rp1"
+#define DBG_LVL DBG_LOG
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <dt-bindings/clock/rp1.h>
+
+#define PLL_SYS_CS 0x08000
+#define PLL_SYS_PWR 0x08004
+#define PLL_SYS_FBDIV_INT 0x08008
+#define PLL_SYS_FBDIV_FRAC 0x0800c
+#define PLL_SYS_PRIM 0x08010
+#define PLL_SYS_SEC 0x08014
+
+#define PLL_AUDIO_CS 0x0c000
+#define PLL_AUDIO_PWR 0x0c004
+#define PLL_AUDIO_FBDIV_INT 0x0c008
+#define PLL_AUDIO_FBDIV_FRAC 0x0c00c
+#define PLL_AUDIO_PRIM 0x0c010
+#define PLL_AUDIO_SEC 0x0c014
+#define PLL_AUDIO_TERN 0x0c018
+
+#define PLL_VIDEO_CS 0x10000
+#define PLL_VIDEO_PWR 0x10004
+#define PLL_VIDEO_FBDIV_INT 0x10008
+#define PLL_VIDEO_FBDIV_FRAC 0x1000c
+#define PLL_VIDEO_PRIM 0x10010
+#define PLL_VIDEO_SEC 0x10014
+
+#define GPCLK_OE_CTRL 0x00000
+
+#define CLK_SYS_CTRL 0x00014
+#define CLK_SYS_DIV_INT 0x00018
+#define CLK_SYS_SEL 0x00020
+
+#define CLK_SLOW_SYS_CTRL 0x00024
+#define CLK_SLOW_SYS_DIV_INT 0x00028
+#define CLK_SLOW_SYS_SEL 0x00030
+
+#define CLK_DMA_CTRL 0x00044
+#define CLK_DMA_DIV_INT 0x00048
+#define CLK_DMA_SEL 0x00050
+
+#define CLK_UART_CTRL 0x00054
+#define CLK_UART_DIV_INT 0x00058
+#define CLK_UART_SEL 0x00060
+
+#define CLK_ETH_CTRL 0x00064
+#define CLK_ETH_DIV_INT 0x00068
+#define CLK_ETH_SEL 0x00070
+
+#define CLK_PWM0_CTRL 0x00074
+#define CLK_PWM0_DIV_INT 0x00078
+#define CLK_PWM0_DIV_FRAC 0x0007c
+#define CLK_PWM0_SEL 0x00080
+
+#define CLK_PWM1_CTRL 0x00084
+#define CLK_PWM1_DIV_INT 0x00088
+#define CLK_PWM1_DIV_FRAC 0x0008c
+#define CLK_PWM1_SEL 0x00090
+
+#define CLK_AUDIO_IN_CTRL 0x00094
+#define CLK_AUDIO_IN_DIV_INT 0x00098
+#define CLK_AUDIO_IN_SEL 0x000a0
+
+#define CLK_AUDIO_OUT_CTRL 0x000a4
+#define CLK_AUDIO_OUT_DIV_INT 0x000a8
+#define CLK_AUDIO_OUT_SEL 0x000b0
+
+#define CLK_I2S_CTRL 0x000b4
+#define CLK_I2S_DIV_INT 0x000b8
+#define CLK_I2S_SEL 0x000c0
+
+#define CLK_MIPI0_CFG_CTRL 0x000c4
+#define CLK_MIPI0_CFG_DIV_INT 0x000c8
+#define CLK_MIPI0_CFG_SEL 0x000d0
+
+#define CLK_MIPI1_CFG_CTRL 0x000d4
+#define CLK_MIPI1_CFG_DIV_INT 0x000d8
+#define CLK_MIPI1_CFG_SEL 0x000e0
+
+#define CLK_PCIE_AUX_CTRL 0x000e4
+#define CLK_PCIE_AUX_DIV_INT 0x000e8
+#define CLK_PCIE_AUX_SEL 0x000f0
+
+#define CLK_USBH0_MICROFRAME_CTRL 0x000f4
+#define CLK_USBH0_MICROFRAME_DIV_INT 0x000f8
+#define CLK_USBH0_MICROFRAME_SEL 0x00100
+
+#define CLK_USBH1_MICROFRAME_CTRL 0x00104
+#define CLK_USBH1_MICROFRAME_DIV_INT 0x00108
+#define CLK_USBH1_MICROFRAME_SEL 0x00110
+
+#define CLK_USBH0_SUSPEND_CTRL 0x00114
+#define CLK_USBH0_SUSPEND_DIV_INT 0x00118
+#define CLK_USBH0_SUSPEND_SEL 0x00120
+
+#define CLK_USBH1_SUSPEND_CTRL 0x00124
+#define CLK_USBH1_SUSPEND_DIV_INT 0x00128
+#define CLK_USBH1_SUSPEND_SEL 0x00130
+
+#define CLK_ETH_TSU_CTRL 0x00134
+#define CLK_ETH_TSU_DIV_INT 0x00138
+#define CLK_ETH_TSU_SEL 0x00140
+
+#define CLK_ADC_CTRL 0x00144
+#define CLK_ADC_DIV_INT 0x00148
+#define CLK_ADC_SEL 0x00150
+
+#define CLK_SDIO_TIMER_CTRL 0x00154
+#define CLK_SDIO_TIMER_DIV_INT 0x00158
+#define CLK_SDIO_TIMER_SEL 0x00160
+
+#define CLK_SDIO_ALT_SRC_CTRL 0x00164
+#define CLK_SDIO_ALT_SRC_DIV_INT 0x00168
+#define CLK_SDIO_ALT_SRC_SEL 0x00170
+
+#define CLK_GP0_CTRL 0x00174
+#define CLK_GP0_DIV_INT 0x00178
+#define CLK_GP0_DIV_FRAC 0x0017c
+#define CLK_GP0_SEL 0x00180
+
+#define CLK_GP1_CTRL 0x00184
+#define CLK_GP1_DIV_INT 0x00188
+#define CLK_GP1_DIV_FRAC 0x0018c
+#define CLK_GP1_SEL 0x00190
+
+#define CLK_GP2_CTRL 0x00194
+#define CLK_GP2_DIV_INT 0x00198
+#define CLK_GP2_DIV_FRAC 0x0019c
+#define CLK_GP2_SEL 0x001a0
+
+#define CLK_GP3_CTRL 0x001a4
+#define CLK_GP3_DIV_INT 0x001a8
+#define CLK_GP3_DIV_FRAC 0x001ac
+#define CLK_GP3_SEL 0x001b0
+
+#define CLK_GP4_CTRL 0x001b4
+#define CLK_GP4_DIV_INT 0x001b8
+#define CLK_GP4_DIV_FRAC 0x001bc
+#define CLK_GP4_SEL 0x001c0
+
+#define CLK_GP5_CTRL 0x001c4
+#define CLK_GP5_DIV_INT 0x001c8
+#define CLK_GP5_DIV_FRAC 0x001cc
+#define CLK_GP5_SEL 0x001d0
+
+#define CLK_SYS_RESUS_CTRL 0x0020c
+
+#define CLK_SLOW_SYS_RESUS_CTRL 0x00214
+
+#define FC0_REF_KHZ 0x0021c
+#define FC0_MIN_KHZ 0x00220
+#define FC0_MAX_KHZ 0x00224
+#define FC0_DELAY 0x00228
+#define FC0_INTERVAL 0x0022c
+#define FC0_SRC 0x00230
+#define FC0_STATUS 0x00234
+#define FC0_RESULT 0x00238
+#define FC_SIZE 0x20
+#define FC_COUNT 8
+#define FC_NUM(idx, off) ((idx) * 32 + (off))
+
+#define AUX_SEL 1
+
+#define VIDEO_CLOCKS_OFFSET 0x4000
+#define VIDEO_CLK_VEC_CTRL (VIDEO_CLOCKS_OFFSET + 0x0000)
+#define VIDEO_CLK_VEC_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0004)
+#define VIDEO_CLK_VEC_SEL (VIDEO_CLOCKS_OFFSET + 0x000c)
+#define VIDEO_CLK_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0010)
+#define VIDEO_CLK_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0014)
+#define VIDEO_CLK_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x001c)
+#define VIDEO_CLK_MIPI0_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0020)
+#define VIDEO_CLK_MIPI0_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0024)
+#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0028)
+#define VIDEO_CLK_MIPI0_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x002c)
+#define VIDEO_CLK_MIPI1_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0030)
+#define VIDEO_CLK_MIPI1_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0034)
+#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0038)
+#define VIDEO_CLK_MIPI1_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x003c)
+
+#define DIV_INT_8BIT_MAX 0x000000ffU /* max divide for most clocks */
+#define DIV_INT_16BIT_MAX 0x0000ffffU /* max divide for GPx, PWM */
+#define DIV_INT_24BIT_MAX 0x00ffffffU /* max divide for CLK_SYS */
+
+#define FC0_STATUS_DONE RT_BIT(4)
+#define FC0_STATUS_RUNNING RT_BIT(8)
+#define FC0_RESULT_FRAC_SHIFT 5
+
+#define PLL_PRIM_DIV1_SHIFT 16
+#define PLL_PRIM_DIV1_MASK 0x00070000
+#define PLL_PRIM_DIV2_SHIFT 12
+#define PLL_PRIM_DIV2_MASK 0x00007000
+
+#define PLL_SEC_DIV_SHIFT 8
+#define PLL_SEC_DIV_WIDTH 5
+#define PLL_SEC_DIV_MASK 0x00001f00
+
+#define PLL_CS_LOCK RT_BIT(31)
+#define PLL_CS_REFDIV_SHIFT 0
+
+#define PLL_PWR_PD RT_BIT(0)
+#define PLL_PWR_DACPD RT_BIT(1)
+#define PLL_PWR_DSMPD RT_BIT(2)
+#define PLL_PWR_POSTDIVPD RT_BIT(3)
+#define PLL_PWR_4PHASEPD RT_BIT(4)
+#define PLL_PWR_VCOPD RT_BIT(5)
+#define PLL_PWR_MASK 0x0000003f
+
+#define PLL_SEC_RST RT_BIT(16)
+#define PLL_SEC_IMPL RT_BIT(31)
+
+/* PLL phase output for both PRI and SEC */
+#define PLL_PH_EN RT_BIT(4)
+#define PLL_PH_PHASE_SHIFT 0
+
+#define RP1_PLL_PHASE_0 0
+#define RP1_PLL_PHASE_90 1
+#define RP1_PLL_PHASE_180 2
+#define RP1_PLL_PHASE_270 3
+
+/* Clock fields for all clocks */
+#define CLK_CTRL_ENABLE RT_BIT(11)
+#define CLK_CTRL_AUXSRC_MASK 0x000003e0
+#define CLK_CTRL_AUXSRC_SHIFT 5
+#define CLK_CTRL_SRC_SHIFT 0
+#define CLK_DIV_FRAC_BITS 16
+
+#define KHz 1000
+#define MHz (KHz * KHz)
+#define RP1_XOSC_RATE 19200000
+#define LOCK_TIMEOUT_NS 100000000
+#define FC_TIMEOUT_NS 100000000
+
+#define MAX_CLK_PARENTS 16
+
+#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
+#define DIV_NEAREST(a, b) (((a) + ((b) >> 1)) / (b))
+#define DIV_U64_NEAREST(a, b) rt_div_u64(((a) + ((b) >> 1)), (b))
+
+struct clk_div_table
+{
+ rt_uint32_t val;
+ rt_uint32_t div;
+};
+
+struct rp1_clockman
+{
+ struct rt_clk_node parent;
+
+ void *regs;
+
+ struct rt_clk_cell *clk_cell_xosc;
+ struct rt_clk_cell *clk_cell_audio;
+ struct rt_clk_cell *clk_cell_i2s;
+ struct rt_clk_cell *clk_cell_slow_sys;
+};
+
+#define raw_to_rp1_clockman(raw) rt_container_of(raw, struct rp1_clockman, parent)
+
+#define RP1_CLK_BASE \
+ struct rt_clk_cell cell; \
+ void (*init)(struct rp1_clockman *clockman, struct rt_clk_cell *cell);
+
+struct rp1_clk_common
+{
+ RP1_CLK_BASE;
+};
+
+rt_inline rt_uint32_t set_register_field(rt_uint32_t reg, rt_uint32_t val,
+ rt_uint32_t mask, rt_uint32_t shift)
+{
+ reg &= ~mask;
+ reg |= (val << shift) & mask;
+
+ return reg;
+}
+
+rt_inline void clockman_write(struct rp1_clockman *clockman,
+ rt_uint32_t reg, rt_uint32_t val)
+{
+ HWREG32(clockman->regs + reg) = val;
+}
+
+rt_inline rt_uint32_t clockman_read(struct rp1_clockman *clockman, rt_uint32_t reg)
+{
+ return HWREG32(clockman->regs + reg);
+}
+
+struct rp1_pll_core_data
+{
+ RP1_CLK_BASE;
+
+ rt_ubase_t cached_rate;
+
+ rt_uint32_t cs_reg;
+ rt_uint32_t pwr_reg;
+ rt_uint32_t fbdiv_int_reg;
+ rt_uint32_t fbdiv_frac_reg;
+ rt_uint32_t fc0_src;
+};
+
+#define cell_to_rp1_pll_core_data(cell) rt_container_of(cell, struct rp1_pll_core_data, cell)
+
+static rt_err_t rp1_pll_core_on(struct rt_clk_cell *cell)
+{
+ rt_tick_t timeout;
+ rt_uint32_t fbdiv_frac;
+ struct rp1_pll_core_data *pll_core = cell_to_rp1_pll_core_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ if (!(clockman_read(clockman, pll_core->cs_reg) & PLL_CS_LOCK))
+ {
+ /* Reset to a known state. */
+ clockman_write(clockman, pll_core->pwr_reg, PLL_PWR_MASK);
+ clockman_write(clockman, pll_core->fbdiv_int_reg, 20);
+ clockman_write(clockman, pll_core->fbdiv_frac_reg, 0);
+ clockman_write(clockman, pll_core->cs_reg, 1 << PLL_CS_REFDIV_SHIFT);
+ }
+
+ /* Come out of reset. */
+ fbdiv_frac = clockman_read(clockman, pll_core->fbdiv_frac_reg);
+ clockman_write(clockman, pll_core->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD);
+
+ /* Wait for the PLL to lock. */
+ timeout = rt_tick_from_millisecond(LOCK_TIMEOUT_NS / 1000000);
+ timeout += rt_tick_get();
+
+ while (!(clockman_read(clockman, pll_core->cs_reg) & PLL_CS_LOCK))
+ {
+ if (rt_tick_get() > timeout)
+ {
+ LOG_E("%s: can't lock PLL", cell->name);
+ return -RT_ETIMEOUT;
+ }
+
+ rt_hw_cpu_relax();
+ }
+
+ return RT_EOK;
+}
+
+static void rp1_pll_core_off(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_core_data *pll_core = cell_to_rp1_pll_core_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, pll_core->pwr_reg, 0);
+}
+
+static rt_bool_t rp1_pll_core_is_on(struct rt_clk_cell *cell)
+{
+ rt_uint32_t pwr;
+ struct rp1_pll_core_data *pll_core = cell_to_rp1_pll_core_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ pwr = clockman_read(clockman, pll_core->pwr_reg);
+
+ return (pwr & PLL_PWR_PD) || (pwr & PLL_PWR_POSTDIVPD);
+}
+
+static rt_ubase_t rp1_pll_core_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_ubase_t calc_rate;
+ rt_uint32_t fbdiv_int, fbdiv_frac;
+ struct rp1_pll_core_data *pll_core = cell_to_rp1_pll_core_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ fbdiv_int = clockman_read(clockman, pll_core->fbdiv_int_reg);
+ fbdiv_frac = clockman_read(clockman, pll_core->fbdiv_frac_reg);
+ calc_rate = ((rt_uint64_t)parent_rate * (((rt_uint64_t)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24;
+
+ return calc_rate;
+}
+
+static rt_ubase_t get_pll_core_divider(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate,
+ rt_uint32_t *div_int, rt_uint32_t *div_frac)
+{
+ rt_ubase_t calc_rate;
+ rt_uint32_t fbdiv_int, fbdiv_frac;
+ rt_uint64_t div_fp64; /* 32.32 fixed point fraction. */
+
+ /* Factor of reference clock to VCO frequency. */
+ div_fp64 = (rt_uint64_t)rate << 32;
+ div_fp64 = DIV_U64_NEAREST(div_fp64, parent_rate);
+
+ /* Round the fractional component at 24 bits. */
+ div_fp64 += 1 << (32 - 24 - 1);
+
+ fbdiv_int = div_fp64 >> 32;
+ fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff;
+
+ calc_rate = ((rt_uint64_t)parent_rate * (((rt_uint64_t)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24;
+
+ *div_int = fbdiv_int;
+ *div_frac = fbdiv_frac;
+
+ return calc_rate;
+}
+
+static rt_base_t rp1_pll_core_round_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ rt_base_t calc_rate;
+ rt_uint32_t fbdiv_int, fbdiv_frac;
+
+ calc_rate = get_pll_core_divider(cell, rate, *parent_rate, &fbdiv_int, &fbdiv_frac);
+
+ return calc_rate;
+}
+
+static rt_err_t rp1_pll_core_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_ubase_t calc_rate;
+ rt_uint32_t fbdiv_int, fbdiv_frac;
+ struct rp1_pll_core_data *pll_core = cell_to_rp1_pll_core_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ /* Disable dividers to start with. */
+ clockman_write(clockman, pll_core->fbdiv_int_reg, 0);
+ clockman_write(clockman, pll_core->fbdiv_frac_reg, 0);
+
+ calc_rate = get_pll_core_divider(cell, rate, parent_rate, &fbdiv_int, &fbdiv_frac);
+
+ clockman_write(clockman, pll_core->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD);
+ clockman_write(clockman, pll_core->fbdiv_int_reg, fbdiv_int);
+ clockman_write(clockman, pll_core->fbdiv_frac_reg, fbdiv_frac);
+
+ pll_core->cached_rate = calc_rate;
+
+ /* Don't need to divide ref unless parent_rate > (output freq / 16) */
+ clockman_write(clockman, pll_core->cs_reg,
+ clockman_read(clockman, pll_core->cs_reg) | (1 << PLL_CS_REFDIV_SHIFT));
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops rp1_pll_core_ops =
+{
+ .prepare = rp1_pll_core_on,
+ .unprepare = rp1_pll_core_off,
+ .is_prepared = rp1_pll_core_is_on,
+ .recalc_rate = rp1_pll_core_recalc_rate,
+ .round_rate = rp1_pll_core_round_rate,
+ .set_rate = rp1_pll_core_set_rate,
+};
+
+static void rp1_init_pll_core(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ cell->parents_nr = 1;
+ cell->parent_name = "xosc";
+ cell->ops = &rp1_pll_core_ops;
+ cell->flags |= RT_CLK_F_IS_CRITICAL;
+}
+
+#define REGISTER_PLL_CORE(...) (void *)&(struct rp1_pll_core_data){ .init = rp1_init_pll_core, __VA_ARGS__ }
+
+struct rp1_pll_data
+{
+ RP1_CLK_BASE;
+
+ rt_ubase_t cached_rate;
+
+ rt_uint32_t ctrl_reg;
+ rt_uint32_t fc0_src;
+};
+
+#define cell_to_rp1_pll_data(cell) rt_container_of(cell, struct rp1_pll_data, cell)
+
+static rt_ubase_t rp1_pll_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_uint32_t prim, prim_div1, prim_div2;
+ struct rp1_pll_data *pll = cell_to_rp1_pll_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ prim = clockman_read(clockman, pll->ctrl_reg);
+ prim_div1 = (prim & PLL_PRIM_DIV1_MASK) >> PLL_PRIM_DIV1_SHIFT;
+ prim_div2 = (prim & PLL_PRIM_DIV2_MASK) >> PLL_PRIM_DIV2_SHIFT;
+
+ if (!prim_div1 || !prim_div2)
+ {
+ LOG_E("%s: zero divider value", cell->name);
+ return 0;
+ }
+
+ return RT_DIV_ROUND_CLOSEST(parent_rate, prim_div1 * prim_div2);
+}
+
+static void get_pll_prim_dividers(rt_ubase_t rate, rt_ubase_t parent_rate,
+ rt_uint32_t *divider1, rt_uint32_t *divider2)
+{
+ rt_base_t rate_diff, calc_rate;
+ rt_uint32_t div1, div2, best_div1 = 7, best_div2 = 7;
+ rt_ubase_t best_rate_diff = ABS_DIFF(RT_DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate);
+
+ for (div1 = 1; div1 <= 7; ++div1)
+ {
+ for (div2 = 1; div2 <= div1; ++div2)
+ {
+ calc_rate = RT_DIV_ROUND_CLOSEST(parent_rate, div1 * div2);
+ rate_diff = ABS_DIFF(calc_rate, rate);
+
+ if (calc_rate == rate)
+ {
+ best_div1 = div1;
+ best_div2 = div2;
+ goto _done;
+ }
+ else if (rate_diff < best_rate_diff)
+ {
+ best_div1 = div1;
+ best_div2 = div2;
+ best_rate_diff = rate_diff;
+ }
+ }
+ }
+
+_done:
+ *divider1 = best_div1;
+ *divider2 = best_div2;
+}
+
+static rt_ubase_t rp1_get_xosc_rate(struct rp1_clockman *clockman)
+{
+ if (clockman->clk_cell_xosc)
+ {
+ return rt_clk_cell_get_rate(clockman->clk_cell_xosc);
+ }
+
+ return RP1_XOSC_RATE;
+}
+
+static rt_ubase_t calc_core_pll_rate(struct rp1_clockman *clockman,
+ rt_ubase_t target_rate, int *pdiv_prim, int *pdiv_clk)
+{
+ const rt_ubase_t xosc_rate = rp1_get_xosc_rate(clockman);
+ const rt_ubase_t core_max = 2400000000;
+ const rt_ubase_t core_min = xosc_rate * 16;
+ static const int prim_divs[] =
+ {
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16,
+ 18, 20, 21, 24, 25, 28, 30, 35, 36, 42, 49,
+ };
+ rt_ubase_t core_rate = 0, best_rate = core_max + 1;
+ int div_int, div_frac, best_div_prim = 1, best_div_clk = 1;
+ rt_uint64_t div;
+
+ /* Given the target rate, choose a set of divisors/multipliers */
+ for (int i = 0; i < RT_ARRAY_SIZE(prim_divs); ++i)
+ {
+ int div_clk, div_prim = prim_divs[i];
+
+ for (div_clk = 1; div_clk <= 256; ++div_clk)
+ {
+ core_rate = target_rate * div_clk * div_prim;
+ if (core_rate >= core_min)
+ {
+ if (core_rate < best_rate)
+ {
+ best_rate = core_rate;
+ best_div_prim = div_prim;
+ best_div_clk = div_clk;
+ }
+ break;
+ }
+ }
+ }
+
+ if (best_rate < core_max)
+ {
+ div = ((best_rate << 24) + xosc_rate / 2) / xosc_rate;
+ div_int = div >> 24;
+ div_frac = div % (1 << 24);
+ core_rate = (xosc_rate * ((div_int << 24) + div_frac) + (1 << 23)) >> 24;
+ }
+ else
+ {
+ core_rate = 0;
+ }
+
+ if (pdiv_prim)
+ {
+ *pdiv_prim = best_div_prim;
+ }
+ if (pdiv_clk)
+ {
+ *pdiv_clk = best_div_clk;
+ }
+
+ return core_rate;
+}
+
+static rt_base_t rp1_pll_round_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ int div_prim, div_clk;
+ rt_uint32_t div1, div2;
+ rt_ubase_t audio_rate, core_rate;
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ core_rate = calc_core_pll_rate(clockman, rate, &div_prim, &div_clk);
+ audio_rate = DIV_NEAREST(core_rate, div_prim);
+
+ if (cell == clockman->clk_cell_audio && audio_rate == rate)
+ {
+ *parent_rate = audio_rate;
+ }
+
+ get_pll_prim_dividers(rate, *parent_rate, &div1, &div2);
+
+ return RT_DIV_ROUND_CLOSEST(*parent_rate, div1 * div2);
+}
+
+static rt_err_t rp1_pll_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t prim, prim_div1, prim_div2;
+ struct rp1_pll_data *pll = cell_to_rp1_pll_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ get_pll_prim_dividers(rate, parent_rate, &prim_div1, &prim_div2);
+
+ prim = clockman_read(clockman, pll->ctrl_reg);
+ prim = set_register_field(prim, prim_div1, PLL_PRIM_DIV1_MASK, PLL_PRIM_DIV1_SHIFT);
+ prim = set_register_field(prim, prim_div2, PLL_PRIM_DIV2_MASK, PLL_PRIM_DIV2_SHIFT);
+ clockman_write(clockman, pll->ctrl_reg, prim);
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops rp1_pll_ops =
+{
+ .recalc_rate = rp1_pll_recalc_rate,
+ .round_rate = rp1_pll_round_rate,
+ .set_rate = rp1_pll_set_rate,
+};
+
+static void rp1_init_pll(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ cell->ops = &rp1_pll_ops;
+}
+
+#define REGISTER_PLL(...) (void *)&(struct rp1_pll_data){ .init = rp1_init_pll, __VA_ARGS__ }
+
+struct rp1_pll_div_data
+{
+ RP1_CLK_BASE;
+
+ rt_ubase_t cached_rate;
+
+ rt_uint32_t ctrl_reg;
+ rt_uint32_t fc0_src;
+};
+
+#define cell_to_rp1_pll_div_data(cell) rt_container_of(cell, struct rp1_pll_div_data, cell)
+
+static const struct clk_div_table pll_sec_div_table[] =
+{
+ { 0x00, 19 },
+ { 0x01, 19 },
+ { 0x02, 19 },
+ { 0x03, 19 },
+ { 0x04, 19 },
+ { 0x05, 19 },
+ { 0x06, 19 },
+ { 0x07, 19 },
+ { 0x08, 8 },
+ { 0x09, 9 },
+ { 0x0a, 10 },
+ { 0x0b, 11 },
+ { 0x0c, 12 },
+ { 0x0d, 13 },
+ { 0x0e, 14 },
+ { 0x0f, 15 },
+ { 0x10, 16 },
+ { 0x11, 17 },
+ { 0x12, 18 },
+ { 0x13, 19 },
+ { 0x14, 19 },
+ { 0x15, 19 },
+ { 0x16, 19 },
+ { 0x17, 19 },
+ { 0x18, 19 },
+ { 0x19, 19 },
+ { 0x1a, 19 },
+ { 0x1b, 19 },
+ { 0x1c, 19 },
+ { 0x1d, 19 },
+ { 0x1e, 19 },
+ { 0x1f, 19 },
+};
+
+static rt_err_t rp1_pll_divider_on(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_div_data *pll_div = cell_to_rp1_pll_div_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, pll_div->ctrl_reg,
+ clockman_read(clockman, pll_div->ctrl_reg) & ~PLL_SEC_RST);
+
+ return RT_EOK;
+}
+
+static void rp1_pll_divider_off(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_div_data *pll_div = cell_to_rp1_pll_div_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, pll_div->ctrl_reg,
+ clockman_read(clockman, pll_div->ctrl_reg) | PLL_SEC_RST);
+}
+
+static rt_bool_t rp1_pll_divider_is_on(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_div_data *pll_div = cell_to_rp1_pll_div_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ return !(clockman_read(clockman, pll_div->ctrl_reg) & PLL_SEC_RST);
+}
+
+static rt_ubase_t rp1_pll_divider_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_uint32_t val, div;
+ struct rp1_pll_div_data *pll_div = cell_to_rp1_pll_div_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ val = clockman_read(clockman, pll_div->ctrl_reg) >> PLL_SEC_DIV_SHIFT;
+ val &= (1 << (PLL_SEC_DIV_WIDTH)) - 1;
+
+ div = val + 1;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pll_sec_div_table); ++i)
+ {
+ const struct clk_div_table *clkt = &pll_sec_div_table[i];
+
+ if (clkt->val == val)
+ {
+ div = clkt->div;
+ break;
+ }
+ }
+
+ return div ? RT_DIV_ROUND_UP_ULL((rt_uint64_t)parent_rate, div) : parent_rate;
+}
+
+static rt_base_t rp1_pll_divider_round_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ int bestdiv = 0, div, up, down;
+ rt_ubase_t up_rate, down_rate, maxdiv = 0;
+ rt_uint32_t mask = (1 << (PLL_SEC_DIV_WIDTH)) - 1;
+
+ if (!rate)
+ {
+ rate = 1;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pll_sec_div_table); ++i)
+ {
+ const struct clk_div_table *clkt = &pll_sec_div_table[i];
+
+ if (clkt->div > maxdiv && clkt->val <= mask)
+ {
+ maxdiv = clkt->div;
+ }
+ }
+
+ up = RT_DIV_ROUND_UP_ULL((rt_uint64_t)*parent_rate, rate);
+ down = *parent_rate / rate;
+
+ /* Round up table */
+ div = up;
+ up = RT_UINT32_MAX >> 1;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pll_sec_div_table); ++i)
+ {
+ const struct clk_div_table *clkt = &pll_sec_div_table[i];
+
+ if (clkt->div == div)
+ {
+ up = clkt->div;
+ break;
+ }
+ else if (clkt->div < div)
+ {
+ continue;
+ }
+
+ if (clkt->div - div < up - div)
+ {
+ up = clkt->div;
+ }
+ }
+
+ /* Round down table */
+ div = down;
+ down = RT_UINT32_MAX;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pll_sec_div_table); ++i)
+ {
+ const struct clk_div_table *clkt = &pll_sec_div_table[i];
+
+ if (clkt->div < down)
+ {
+ down = clkt->div;
+ }
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pll_sec_div_table); ++i)
+ {
+ const struct clk_div_table *clkt = &pll_sec_div_table[i];
+
+ if (clkt->div == div)
+ {
+ down = clkt->div;
+ break;
+ }
+ else if (clkt->div > div)
+ {
+ continue;
+ }
+
+ if (div - clkt->div < div - down)
+ {
+ down = clkt->div;
+ }
+ }
+
+ up_rate = RT_DIV_ROUND_UP_ULL((rt_uint64_t)*parent_rate, up);
+ down_rate = RT_DIV_ROUND_UP_ULL((rt_uint64_t)*parent_rate, down);
+
+ bestdiv = (rate - up_rate) <= (down_rate - rate) ? up : down;
+ bestdiv = bestdiv == 0 ? 1 : bestdiv;
+ bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+
+ return RT_DIV_ROUND_UP_ULL((rt_uint64_t)*parent_rate, div);
+}
+
+static rt_err_t rp1_pll_divider_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t div, sec;
+ struct rp1_pll_div_data *pll_div = cell_to_rp1_pll_div_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ div = RT_DIV_ROUND_UP_ULL(parent_rate, rate);
+ div = rt_clamp(div, 8U, 19U);
+
+ sec = clockman_read(clockman, pll_div->ctrl_reg);
+ sec = set_register_field(sec, div, PLL_SEC_DIV_MASK, PLL_SEC_DIV_SHIFT);
+
+ /* Must keep the divider in reset to change the value. */
+ sec |= PLL_SEC_RST;
+ clockman_write(clockman, pll_div->ctrl_reg, sec);
+
+ sec &= ~PLL_SEC_RST;
+ clockman_write(clockman, pll_div->ctrl_reg, sec);
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops rp1_pll_divider_ops =
+{
+ .prepare = rp1_pll_divider_on,
+ .unprepare = rp1_pll_divider_off,
+ .is_prepared = rp1_pll_divider_is_on,
+ .recalc_rate = rp1_pll_divider_recalc_rate,
+ .round_rate = rp1_pll_divider_round_rate,
+ .set_rate = rp1_pll_divider_set_rate,
+};
+
+static void rp1_init_pll_divider(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ cell->ops = &rp1_pll_divider_ops;
+}
+
+#define REGISTER_PLL_DIV(...) (void *)&(struct rp1_pll_div_data){ .init = rp1_init_pll_divider, __VA_ARGS__ }
+
+struct rp1_pll_ph_data
+{
+ RP1_CLK_BASE;
+
+ rt_uint32_t phase;
+ rt_uint32_t fixed_divider;
+ rt_uint32_t ph_reg;
+ rt_uint32_t fc0_src;
+};
+
+#define cell_to_rp1_pll_ph_data(cell) rt_container_of(cell, struct rp1_pll_ph_data, cell)
+
+static rt_err_t rp1_pll_ph_on(struct rt_clk_cell *cell)
+{
+ rt_uint32_t ph_reg;
+ struct rp1_pll_ph_data *pll_ph = cell_to_rp1_pll_ph_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ ph_reg = clockman_read(clockman, pll_ph->ph_reg);
+ ph_reg |= pll_ph->phase << PLL_PH_PHASE_SHIFT;
+ ph_reg |= PLL_PH_EN;
+ clockman_write(clockman, pll_ph->ph_reg, ph_reg);
+
+ return RT_EOK;
+}
+
+static void rp1_pll_ph_off(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_ph_data *pll_ph = cell_to_rp1_pll_ph_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, pll_ph->ph_reg,
+ clockman_read(clockman, pll_ph->ph_reg) & ~PLL_PH_EN);
+}
+
+static rt_bool_t rp1_pll_ph_is_on(struct rt_clk_cell *cell)
+{
+ struct rp1_pll_ph_data *pll_ph = cell_to_rp1_pll_ph_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ return !!(clockman_read(clockman, pll_ph->ph_reg) & PLL_PH_EN);
+}
+
+static rt_ubase_t rp1_pll_ph_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct rp1_pll_ph_data *pll_ph = cell_to_rp1_pll_ph_data(cell);
+
+ return parent_rate / pll_ph->fixed_divider;
+}
+
+static rt_base_t rp1_pll_ph_round_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ struct rp1_pll_ph_data *pll_ph = cell_to_rp1_pll_ph_data(cell);
+
+ return *parent_rate / pll_ph->fixed_divider;
+}
+
+static rt_err_t rp1_pll_ph_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops rp1_pll_ph_ops =
+{
+ .prepare = rp1_pll_ph_on,
+ .unprepare = rp1_pll_ph_off,
+ .is_prepared = rp1_pll_ph_is_on,
+ .recalc_rate = rp1_pll_ph_recalc_rate,
+ .round_rate = rp1_pll_ph_round_rate,
+ .set_rate = rp1_pll_ph_set_rate,
+};
+
+static void rp1_init_pll_ph(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ cell->ops = &rp1_pll_ph_ops;
+}
+
+#define REGISTER_PLL_PH(...) (void *)&(struct rp1_pll_ph_data){ .init = rp1_init_pll_ph, __VA_ARGS__ }
+
+struct rp1_clock_data
+{
+ RP1_CLK_BASE;
+
+ rt_ubase_t cached_rate;
+
+ int num_std_parents;
+ int num_aux_parents;
+
+ rt_uint32_t oe_mask;
+ rt_uint32_t clk_src_mask;
+ rt_uint32_t ctrl_reg;
+ rt_uint32_t div_int_reg;
+ rt_uint32_t div_frac_reg;
+ rt_uint32_t sel_reg;
+ rt_uint32_t div_int_max;
+ rt_ubase_t max_freq;
+ rt_uint32_t fc0_src;
+};
+
+#define cell_to_rp1_clock_data(cell) rt_container_of(cell, struct rp1_clock_data, cell)
+
+static rt_err_t rp1_clock_on(struct rt_clk_cell *cell)
+{
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, clock->ctrl_reg,
+ clockman_read(clockman, clock->ctrl_reg) | CLK_CTRL_ENABLE);
+
+ /* If this is a GPCLK, turn on the output-enable */
+ if (clock->oe_mask)
+ {
+ clockman_write(clockman, GPCLK_OE_CTRL,
+ clockman_read(clockman, GPCLK_OE_CTRL) | clock->oe_mask);
+ }
+
+ return RT_EOK;
+}
+
+static void rp1_clock_off(struct rt_clk_cell *cell)
+{
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ clockman_write(clockman, clock->ctrl_reg,
+ clockman_read(clockman, clock->ctrl_reg) & ~CLK_CTRL_ENABLE);
+ /* If this is a GPCLK, turn off the output-enable */
+ if (clock->oe_mask)
+ {
+ clockman_write(clockman, GPCLK_OE_CTRL,
+ clockman_read(clockman, GPCLK_OE_CTRL) & ~clock->oe_mask);
+ }
+}
+
+static rt_bool_t rp1_clock_is_on(struct rt_clk_cell *cell)
+{
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ return !!(clockman_read(clockman, clock->ctrl_reg) & CLK_CTRL_ENABLE);
+}
+
+static rt_ubase_t rp1_clock_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ rt_uint32_t frac;
+ rt_uint64_t calc_rate, div;
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ div = clockman_read(clockman, clock->div_int_reg);
+ frac = (clock->div_frac_reg != 0) ? clockman_read(clockman, clock->div_frac_reg) : 0;
+
+ /* If the integer portion of the divider is 0, treat it as 2^16 */
+ if (!div)
+ {
+ div = 1 << 16;
+ }
+
+ div = (div << CLK_DIV_FRAC_BITS) | (frac >> (32 - CLK_DIV_FRAC_BITS));
+
+ calc_rate = (rt_uint64_t)parent_rate << CLK_DIV_FRAC_BITS;
+ calc_rate = calc_rate / div;
+
+ return calc_rate;
+}
+
+static rt_uint32_t rp1_clock_choose_div(rt_ubase_t rate, rt_ubase_t parent_rate,
+ const struct rp1_clock_data *clock)
+{
+ rt_uint64_t div;
+
+ /*
+ * Due to earlier rounding, calculated parent_rate may differ from
+ * expected value. Don't fail on a small discrepancy near unity divide.
+ */
+ if (!rate || rate > parent_rate + (parent_rate >> CLK_DIV_FRAC_BITS))
+ {
+ return 0;
+ }
+
+ /*
+ * Always express div in fixed-point format for fractional division;
+ * If no fractional divider is present, the fraction part will be zero.
+ */
+ if (clock->div_frac_reg)
+ {
+ div = (rt_uint64_t)parent_rate << CLK_DIV_FRAC_BITS;
+ div = DIV_U64_NEAREST(div, rate);
+ }
+ else
+ {
+ div = DIV_U64_NEAREST(parent_rate, rate);
+ div <<= CLK_DIV_FRAC_BITS;
+ }
+
+ div = rt_clamp(div,
+ (rt_uint64_t)(1ULL << CLK_DIV_FRAC_BITS),
+ (rt_uint64_t)clock->div_int_max << CLK_DIV_FRAC_BITS);
+
+ return div;
+}
+
+static rt_err_t rp1_clock_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t div;
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ div = rp1_clock_choose_div(rate, parent_rate, clock);
+
+ if (!div)
+ {
+ div = 1 << CLK_DIV_FRAC_BITS;
+ }
+
+ clockman_write(clockman, clock->div_int_reg, div >> CLK_DIV_FRAC_BITS);
+
+ if (clock->div_frac_reg)
+ {
+ clockman_write(clockman, clock->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS));
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_clock_set_parent(struct rt_clk_cell *cell, rt_uint8_t index)
+{
+ rt_uint32_t ctrl;
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ ctrl = clockman_read(clockman, clock->ctrl_reg);
+
+ if (index >= clock->num_std_parents)
+ {
+ /* This is an aux source request */
+ if (index >= clock->num_std_parents + clock->num_aux_parents)
+ {
+ return -RT_EINVAL;
+ }
+
+ /* Select parent from aux list */
+ ctrl = set_register_field(ctrl, index - clock->num_std_parents,
+ CLK_CTRL_AUXSRC_MASK, CLK_CTRL_AUXSRC_SHIFT);
+ /* Set src to aux list */
+ ctrl = set_register_field(ctrl, AUX_SEL, clock->clk_src_mask,
+ CLK_CTRL_SRC_SHIFT);
+ }
+ else
+ {
+ ctrl = set_register_field(ctrl, index, clock->clk_src_mask,
+ CLK_CTRL_SRC_SHIFT);
+ }
+
+ clockman_write(clockman, clock->ctrl_reg, ctrl);
+
+ return RT_EOK;
+}
+
+static rt_uint8_t rp1_clock_get_parent(struct rt_clk_cell *cell)
+{
+ rt_uint8_t parent;
+ rt_uint32_t sel, ctrl;
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+ struct rp1_clockman *clockman = raw_to_rp1_clockman(cell->clk_np);
+
+ sel = clockman_read(clockman, clock->sel_reg);
+ parent = __rt_ffs(sel) - 1;
+
+ /* sel == 0 implies the parent clock is not enabled yet. */
+ if (!sel)
+ {
+ /* Read the clock src from the CTRL register instead */
+ ctrl = clockman_read(clockman, clock->ctrl_reg);
+ parent = (ctrl & clock->clk_src_mask) >> CLK_CTRL_SRC_SHIFT;
+ }
+
+ if (parent >= clock->num_std_parents)
+ {
+ parent = AUX_SEL;
+ }
+
+ if (parent == AUX_SEL)
+ {
+ /*
+ * Clock parent is an auxiliary source, so get the parent from
+ * the AUXSRC register field.
+ */
+ ctrl = clockman_read(clockman, clock->ctrl_reg);
+ parent = (ctrl & CLK_CTRL_AUXSRC_MASK) >> CLK_CTRL_AUXSRC_SHIFT;
+ parent += clock->num_std_parents;
+ }
+
+ if (parent >= cell->parents_nr)
+ {
+ parent = 0;
+ }
+
+ return parent;
+}
+
+static const struct rt_clk_ops rp1_clk_ops =
+{
+ .prepare = rp1_clock_on,
+ .unprepare = rp1_clock_off,
+ .is_prepared = rp1_clock_is_on,
+ .recalc_rate = rp1_clock_recalc_rate,
+ .set_rate = rp1_clock_set_rate,
+ .set_parent = rp1_clock_set_parent,
+ .get_parent = rp1_clock_get_parent,
+};
+
+static void rp1_init_clock(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ struct rp1_clock_data *clock = cell_to_rp1_clock_data(cell);
+
+ cell->parents_nr = clock->num_std_parents + clock->num_aux_parents;
+ cell->ops = &rp1_clk_ops;
+}
+
+#define REGISTER_CLK(...) (void *)&(struct rp1_clock_data){ .init = rp1_init_clock, __VA_ARGS__ }
+
+struct rp1_varsrc_data
+{
+ RP1_CLK_BASE;
+ rt_ubase_t rate;
+};
+
+#define cell_to_rp1_varsrc(cell) rt_container_of(cell, struct rp1_varsrc_data, cell)
+
+static rt_ubase_t rp1_varsrc_recalc_rate(struct rt_clk_cell *cell, rt_ubase_t parent_rate)
+{
+ struct rp1_varsrc_data *varsrc = cell_to_rp1_varsrc(cell);
+
+ return varsrc->rate;
+}
+
+static rt_base_t rp1_varsrc_round_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t *parent_rate)
+{
+ return rate;
+}
+
+static rt_err_t rp1_varsrc_set_rate(struct rt_clk_cell *cell, rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ struct rp1_varsrc_data *varsrc = cell_to_rp1_varsrc(cell);
+
+ /*
+ * "varsrc" exists purely to let clock dividers know the frequency
+ * of an externally-managed clock source (such as MIPI DSI byte-clock)
+ * which may change at run-time as a side-effect of some other driver.
+ */
+ varsrc->rate = rate;
+
+ return RT_EOK;
+}
+
+static const struct rt_clk_ops rp1_varsrc_ops =
+{
+ .recalc_rate = rp1_varsrc_recalc_rate,
+ .round_rate = rp1_varsrc_round_rate,
+ .set_rate = rp1_varsrc_set_rate,
+};
+
+static void rp1_init_varsrc(struct rp1_clockman *clockman, struct rt_clk_cell *cell)
+{
+ cell->parents_nr = 1;
+ cell->parent_name = "xosc";
+ cell->ops = &rp1_varsrc_ops;
+}
+
+#define REGISTER_VARSRC(...) (void *)&(struct rp1_varsrc_data){ .init = rp1_init_varsrc, __VA_ARGS__ }
+
+static struct rt_clk_cell *rp1_clk_cell[] =
+{
+ [RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE(
+ .cell.name = "pll_sys_core",
+ .cs_reg = PLL_SYS_CS,
+ .pwr_reg = PLL_SYS_PWR,
+ .fbdiv_int_reg = PLL_SYS_FBDIV_INT,
+ .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC),
+
+ [RP1_PLL_AUDIO_CORE] = REGISTER_PLL_CORE(
+ .cell.name = "pll_audio_core",
+ .cs_reg = PLL_AUDIO_CS,
+ .pwr_reg = PLL_AUDIO_PWR,
+ .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT,
+ .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC),
+
+ [RP1_PLL_VIDEO_CORE] = REGISTER_PLL_CORE(
+ .cell.name = "pll_video_core",
+ .cs_reg = PLL_VIDEO_CS,
+ .pwr_reg = PLL_VIDEO_PWR,
+ .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT,
+ .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC),
+
+ [RP1_PLL_SYS] = REGISTER_PLL(
+ .cell.name = "pll_sys",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_sys_core",
+ .ctrl_reg = PLL_SYS_PRIM,
+ .fc0_src = FC_NUM(0, 2)),
+
+ [RP1_PLL_AUDIO] = REGISTER_PLL(
+ .cell.name = "pll_audio",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_audio_core",
+ .cell.flags = RT_CLK_F_SET_RATE_PARENT,
+ .ctrl_reg = PLL_AUDIO_PRIM,
+ .fc0_src = FC_NUM(4, 2)),
+
+ [RP1_PLL_VIDEO] = REGISTER_PLL(
+ .cell.name = "pll_video",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_video_core",
+ .ctrl_reg = PLL_VIDEO_PRIM,
+ .fc0_src = FC_NUM(3, 2)),
+
+ [RP1_PLL_SYS_PRI_PH] = REGISTER_PLL_PH(
+ .cell.name = "pll_sys_pri_ph",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_sys",
+ .ph_reg = PLL_SYS_PRIM,
+ .fixed_divider = 2,
+ .phase = RP1_PLL_PHASE_0,
+ .fc0_src = FC_NUM(1, 2)),
+
+ [RP1_PLL_AUDIO_PRI_PH] = REGISTER_PLL_PH(
+ .cell.name = "pll_audio_pri_ph",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_audio",
+ .ph_reg = PLL_AUDIO_PRIM,
+ .fixed_divider = 2,
+ .phase = RP1_PLL_PHASE_0,
+ .fc0_src = FC_NUM(5, 1)),
+
+ [RP1_PLL_VIDEO_PRI_PH] = REGISTER_PLL_PH(
+ .cell.name = "pll_video_pri_ph",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_video",
+ .ph_reg = PLL_VIDEO_PRIM,
+ .fixed_divider = 2,
+ .phase = RP1_PLL_PHASE_0,
+ .fc0_src = FC_NUM(4, 3)),
+
+ [RP1_PLL_SYS_SEC] = REGISTER_PLL_DIV(
+ .cell.name = "pll_sys_sec",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_sys_core",
+ .ctrl_reg = PLL_SYS_SEC,
+ .fc0_src = FC_NUM(2, 2)),
+
+ [RP1_PLL_AUDIO_SEC] = REGISTER_PLL_DIV(
+ .cell.name = "pll_audio_sec",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_audio_core",
+ .ctrl_reg = PLL_AUDIO_SEC,
+ .fc0_src = FC_NUM(6, 2)),
+
+ [RP1_PLL_VIDEO_SEC] = REGISTER_PLL_DIV(
+ .cell.name = "pll_video_sec",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_video_core",
+ .ctrl_reg = PLL_VIDEO_SEC,
+ .fc0_src = FC_NUM(5, 3)),
+
+ [RP1_PLL_AUDIO_TERN] = REGISTER_PLL_DIV(
+ .cell.name = "pll_audio_tern",
+ .cell.parents_nr = 1,
+ .cell.parent_name = "pll_audio_core",
+ .ctrl_reg = PLL_AUDIO_TERN,
+ .fc0_src = FC_NUM(6, 2)),
+
+ [RP1_CLK_SYS] = REGISTER_CLK(
+ .cell.name = "clk_sys",
+ .cell.parent_names = (const char *[]){ "xosc", "", "pll_sys" },
+ .cell.flags = RT_CLK_F_IS_CRITICAL,
+ .num_std_parents = 3,
+ .num_aux_parents = 0,
+ .ctrl_reg = CLK_SYS_CTRL,
+ .div_int_reg = CLK_SYS_DIV_INT,
+ .sel_reg = CLK_SYS_SEL,
+ .div_int_max = DIV_INT_24BIT_MAX,
+ .max_freq = 200 * MHz,
+ .fc0_src = FC_NUM(0, 4),
+ .clk_src_mask = 0x3),
+
+ [RP1_CLK_SLOW_SYS] = REGISTER_CLK(
+ .cell.name = "clk_slow_sys",
+ .cell.parent_name = "xosc",
+ .cell.flags = RT_CLK_F_IS_CRITICAL,
+ .num_std_parents = 1,
+ .num_aux_parents = 0,
+ .ctrl_reg = CLK_SLOW_SYS_CTRL,
+ .div_int_reg = CLK_SLOW_SYS_DIV_INT,
+ .sel_reg = CLK_SLOW_SYS_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(1, 4),
+ .clk_src_mask = 0x1),
+
+ [RP1_CLK_DMA] = REGISTER_CLK(
+ .cell.name = "clk_dma",
+ .cell.parent_names = (const char *[]){ "pll_sys_pri_ph", "pll_video", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_DMA_CTRL,
+ .div_int_reg = CLK_DMA_DIV_INT,
+ .sel_reg = CLK_DMA_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(2, 2)),
+
+ [RP1_CLK_UART] = REGISTER_CLK(
+ .cell.name = "clk_uart",
+ .cell.parent_names = (const char *[]){ "pll_sys_pri_ph", "pll_video", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_UART_CTRL,
+ .div_int_reg = CLK_UART_DIV_INT,
+ .sel_reg = CLK_UART_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(6, 7)),
+
+ [RP1_CLK_ETH] = REGISTER_CLK(
+ .cell.name = "clk_eth",
+ .cell.parent_names = (const char *[]){ "pll_sys_sec", "pll_sys", "pll_video_sec" },
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_ETH_CTRL,
+ .div_int_reg = CLK_ETH_DIV_INT,
+ .sel_reg = CLK_ETH_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 125 * MHz,
+ .fc0_src = FC_NUM(4, 6)),
+
+ [RP1_CLK_PWM0] = REGISTER_CLK(
+ .cell.name = "clk_pwm0",
+ .cell.parent_names = (const char *[]){ "", "pll_video_sec", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_PWM0_CTRL,
+ .div_int_reg = CLK_PWM0_DIV_INT,
+ .div_frac_reg = CLK_PWM0_DIV_FRAC,
+ .sel_reg = CLK_PWM0_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 76800 * KHz,
+ .fc0_src = FC_NUM(0, 5)),
+
+ [RP1_CLK_PWM1] = REGISTER_CLK(
+ .cell.name = "clk_pwm1",
+ .cell.parent_names = (const char *[]){ "", "pll_video_sec", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_PWM1_CTRL,
+ .div_int_reg = CLK_PWM1_DIV_INT,
+ .div_frac_reg = CLK_PWM1_DIV_FRAC,
+ .sel_reg = CLK_PWM1_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 76800 * KHz,
+ .fc0_src = FC_NUM(1, 5)),
+
+ [RP1_CLK_AUDIO_IN] = REGISTER_CLK(
+ .cell.name = "clk_audio_in",
+ .cell.parent_names = (const char *[]){ "", "", "", "pll_video_sec", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 5,
+ .ctrl_reg = CLK_AUDIO_IN_CTRL,
+ .div_int_reg = CLK_AUDIO_IN_DIV_INT,
+ .sel_reg = CLK_AUDIO_IN_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 76800 * KHz,
+ .fc0_src = FC_NUM(2, 5)),
+
+ [RP1_CLK_AUDIO_OUT] = REGISTER_CLK(
+ .cell.name = "clk_audio_out",
+ .cell.parent_names = (const char *[]){ "", "pll_audio_sec", "pll_video_sec", "xosc" },
+ .num_std_parents = 0,
+ .num_aux_parents = 4,
+ .ctrl_reg = CLK_AUDIO_OUT_CTRL,
+ .div_int_reg = CLK_AUDIO_OUT_DIV_INT,
+ .sel_reg = CLK_AUDIO_OUT_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 153600 * KHz,
+ .fc0_src = FC_NUM(3, 5)),
+
+ [RP1_CLK_I2S] = REGISTER_CLK(
+ .cell.name = "clk_i2s",
+ .cell.parent_names = (const char *[]){ "xosc", "pll_audio", "pll_audio_sec" },
+ .cell.flags = RT_CLK_F_SET_RATE_PARENT,
+ .num_std_parents = 0,
+ .num_aux_parents = 3,
+ .ctrl_reg = CLK_I2S_CTRL,
+ .div_int_reg = CLK_I2S_DIV_INT,
+ .sel_reg = CLK_I2S_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(4, 4)),
+
+ [RP1_CLK_MIPI0_CFG] = REGISTER_CLK(
+ .cell.name = "clk_mipi0_cfg",
+ .cell.parent_name = "xosc",
+ .num_std_parents = 0,
+ .num_aux_parents = 1,
+ .ctrl_reg = CLK_MIPI0_CFG_CTRL,
+ .div_int_reg = CLK_MIPI0_CFG_DIV_INT,
+ .sel_reg = CLK_MIPI0_CFG_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(4, 5)),
+
+ [RP1_CLK_MIPI1_CFG] = REGISTER_CLK(
+ .cell.name = "clk_mipi1_cfg",
+ .cell.parent_name = "xosc",
+ .num_std_parents = 0,
+ .num_aux_parents = 1,
+ .ctrl_reg = CLK_MIPI1_CFG_CTRL,
+ .div_int_reg = CLK_MIPI1_CFG_DIV_INT,
+ .sel_reg = CLK_MIPI1_CFG_SEL,
+ .clk_src_mask = 1,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(5, 6)),
+
+ [RP1_CLK_ETH_TSU] = REGISTER_CLK(
+ .cell.name = "clk_eth_tsu",
+ .cell.parent_names = (const char *[]){ "xosc", "pll_video_sec", "", "", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 8,
+ .ctrl_reg = CLK_ETH_TSU_CTRL,
+ .div_int_reg = CLK_ETH_TSU_DIV_INT,
+ .sel_reg = CLK_ETH_TSU_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(5, 7)),
+
+ [RP1_CLK_ADC] = REGISTER_CLK(
+ .cell.name = "clk_adc",
+ .cell.parent_name = "xosc",
+ .num_std_parents = 0,
+ .num_aux_parents = 1,
+ .ctrl_reg = CLK_ADC_CTRL,
+ .div_int_reg = CLK_ADC_DIV_INT,
+ .sel_reg = CLK_ADC_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(5, 5)),
+
+ [RP1_CLK_SDIO_TIMER] = REGISTER_CLK(
+ .cell.name = "clk_sdio_timer",
+ .cell.parent_name = "xosc",
+ .num_std_parents = 0,
+ .num_aux_parents = 1,
+ .ctrl_reg = CLK_SDIO_TIMER_CTRL,
+ .div_int_reg = CLK_SDIO_TIMER_DIV_INT,
+ .sel_reg = CLK_SDIO_TIMER_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 50 * MHz,
+ .fc0_src = FC_NUM(3, 4)),
+
+ [RP1_CLK_SDIO_ALT_SRC] = REGISTER_CLK(
+ .cell.name = "clk_sdio_alt_src",
+ .cell.parent_name = "pll_sys",
+ .num_std_parents = 0,
+ .num_aux_parents = 1,
+ .ctrl_reg = CLK_SDIO_ALT_SRC_CTRL,
+ .div_int_reg = CLK_SDIO_ALT_SRC_DIV_INT,
+ .sel_reg = CLK_SDIO_ALT_SRC_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 200 * MHz,
+ .fc0_src = FC_NUM(5, 4)),
+
+ [RP1_CLK_GP0] = REGISTER_CLK(
+ .cell.name = "clk_gp0",
+ .cell.parent_names = (const char *[]){ "xosc", "", "", "", "", "", "pll_sys", "", "", "", "clk_i2s", "clk_adc", "", "", "", "clk_sys" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(0),
+ .ctrl_reg = CLK_GP0_CTRL,
+ .div_int_reg = CLK_GP0_DIV_INT,
+ .div_frac_reg = CLK_GP0_DIV_FRAC,
+ .sel_reg = CLK_GP0_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(0, 1)),
+
+ [RP1_CLK_GP1] = REGISTER_CLK(
+ .cell.name = "clk_gp1",
+ .cell.parent_names = (const char *[]){ "clk_sdio_timer", "", "", "", "", "", "pll_sys_pri_ph", "", "", "", "clk_adc", "clk_dpi", "clk_pwm0", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(1),
+ .ctrl_reg = CLK_GP1_CTRL,
+ .div_int_reg = CLK_GP1_DIV_INT,
+ .div_frac_reg = CLK_GP1_DIV_FRAC,
+ .sel_reg = CLK_GP1_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(1, 1)),
+
+ [RP1_CLK_GP2] = REGISTER_CLK(
+ .cell.name = "clk_gp2",
+ .cell.parent_names = (const char *[]){ "clk_sdio_alt_src", "", "", "", "", "", "pll_sys_sec", "", "pll_video", "clk_audio_in", "clk_dpi", "clk_pwm0", "clk_pwm1", "clk_mipi0_dpi", "clk_mipi1_cfg", "clk_sys" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(2),
+ .ctrl_reg = CLK_GP2_CTRL,
+ .div_int_reg = CLK_GP2_DIV_INT,
+ .div_frac_reg = CLK_GP2_DIV_FRAC,
+ .sel_reg = CLK_GP2_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(2, 1)),
+
+ [RP1_CLK_GP3] = REGISTER_CLK(
+ .cell.name = "clk_gp3",
+ .cell.parent_names = (const char *[]){ "xosc", "", "", "", "", "", "", "", "pll_video_pri_ph", "clk_audio_out", "", "", "clk_mipi1_dpi", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(3),
+ .ctrl_reg = CLK_GP3_CTRL,
+ .div_int_reg = CLK_GP3_DIV_INT,
+ .div_frac_reg = CLK_GP3_DIV_FRAC,
+ .sel_reg = CLK_GP3_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(3, 1)),
+
+ [RP1_CLK_GP4] = REGISTER_CLK(
+ .cell.name = "clk_gp4",
+ .cell.parent_names = (const char *[]){ "xosc", "", "", "", "", "", "", "pll_video_sec", "", "", "", "clk_mipi0_cfg", "clk_uart", "", "", "clk_sys" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(4),
+ .ctrl_reg = CLK_GP4_CTRL,
+ .div_int_reg = CLK_GP4_DIV_INT,
+ .div_frac_reg = CLK_GP4_DIV_FRAC,
+ .sel_reg = CLK_GP4_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(4, 1)),
+
+ [RP1_CLK_GP5] = REGISTER_CLK(
+ .cell.name = "clk_gp5",
+ .cell.parent_names = (const char *[]){ "xosc", "", "", "", "", "", "", "pll_video_sec", "clk_eth_tsu", "", "clk_vec", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 16,
+ .oe_mask = RT_BIT(5),
+ .ctrl_reg = CLK_GP5_CTRL,
+ .div_int_reg = CLK_GP5_DIV_INT,
+ .div_frac_reg = CLK_GP5_DIV_FRAC,
+ .sel_reg = CLK_GP5_SEL,
+ .div_int_max = DIV_INT_16BIT_MAX,
+ .max_freq = 100 * MHz,
+ .fc0_src = FC_NUM(5, 1)),
+
+ [RP1_CLK_VEC] = REGISTER_CLK(
+ .cell.name = "clk_vec",
+ .cell.parent_names = (const char *[]){ "pll_sys_pri_ph", "pll_video_sec", "pll_video", "", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 8,
+ .ctrl_reg = VIDEO_CLK_VEC_CTRL,
+ .div_int_reg = VIDEO_CLK_VEC_DIV_INT,
+ .sel_reg = VIDEO_CLK_VEC_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 108 * MHz,
+ .fc0_src = FC_NUM(0, 6)),
+
+ [RP1_CLK_DPI] = REGISTER_CLK(
+ .cell.name = "clk_dpi",
+ .cell.parent_names = (const char *[]){ "pll_sys", "pll_video_sec", "pll_video", "", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 8,
+ .ctrl_reg = VIDEO_CLK_DPI_CTRL,
+ .div_int_reg = VIDEO_CLK_DPI_DIV_INT,
+ .sel_reg = VIDEO_CLK_DPI_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 200 * MHz,
+ .fc0_src = FC_NUM(1, 6)),
+
+ [RP1_CLK_MIPI0_DPI] = REGISTER_CLK(
+ .cell.name = "clk_mipi0_dpi",
+ .cell.parent_names = (const char *[]){ "pll_sys", "pll_video_sec", "pll_video", "clksrc_mipi0_dsi_byteclk", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 8,
+ .ctrl_reg = VIDEO_CLK_MIPI0_DPI_CTRL,
+ .div_int_reg = VIDEO_CLK_MIPI0_DPI_DIV_INT,
+ .div_frac_reg = VIDEO_CLK_MIPI0_DPI_DIV_FRAC,
+ .sel_reg = VIDEO_CLK_MIPI0_DPI_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 200 * MHz,
+ .fc0_src = FC_NUM(2, 6)),
+
+ [RP1_CLK_MIPI1_DPI] = REGISTER_CLK(
+ .cell.name = "clk_mipi1_dpi",
+ .cell.parent_names = (const char *[]){ "pll_sys", "pll_video_sec", "pll_video", "clksrc_mipi1_dsi_byteclk", "", "", "", "" },
+ .num_std_parents = 0,
+ .num_aux_parents = 8,
+ .ctrl_reg = VIDEO_CLK_MIPI1_DPI_CTRL,
+ .div_int_reg = VIDEO_CLK_MIPI1_DPI_DIV_INT,
+ .div_frac_reg = VIDEO_CLK_MIPI1_DPI_DIV_FRAC,
+ .sel_reg = VIDEO_CLK_MIPI1_DPI_SEL,
+ .div_int_max = DIV_INT_8BIT_MAX,
+ .max_freq = 200 * MHz,
+ .fc0_src = FC_NUM(3, 6)),
+
+ [RP1_CLK_MIPI0_DSI_BYTECLOCK] = REGISTER_VARSRC(
+ .cell.name = "clksrc_mipi0_dsi_byteclk"),
+ [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC(
+ .cell.name = "clksrc_mipi1_dsi_byteclk"),
+};
+
+static rt_err_t rp1_clk_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_clockman *clockman = rt_calloc(1, sizeof(*clockman));
+
+ if (!clockman)
+ {
+ return -RT_ENOMEM;
+ }
+
+ clockman->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!clockman->regs)
+ {
+ LOG_E("%s: ioremap failed", rt_ofw_node_full_name(dev->ofw_node));
+ err = -RT_EIO;
+ goto _free;
+ }
+
+ clockman->clk_cell_i2s = rp1_clk_cell[RP1_CLK_I2S];
+ clockman->clk_cell_slow_sys = rp1_clk_cell[RP1_CLK_SLOW_SYS];
+
+ for (int i = 0; i < RT_ARRAY_SIZE(rp1_clk_cell); ++i)
+ {
+ struct rp1_clk_common *common;
+ struct rt_clk_cell *cell = rp1_clk_cell[i];
+
+ if (!cell)
+ {
+ continue;
+ }
+
+ common = rt_container_of(cell, struct rp1_clk_common, cell);
+
+ if (common->init)
+ {
+ common->init(clockman, cell);
+ }
+ }
+
+ clockman->parent.dev = dev;
+ clockman->parent.cells = rp1_clk_cell;
+ clockman->parent.cells_nr = RT_ARRAY_SIZE(rp1_clk_cell);
+
+ for (int i = 0; i < RT_ARRAY_SIZE(rp1_clk_cell); ++i)
+ {
+ struct rt_clk_cell *cell = rp1_clk_cell[i];
+
+ if (cell)
+ {
+ cell->clk_np = &clockman->parent;
+ }
+ }
+
+ clockman->clk_cell_xosc = rt_clk_cell_get_parent_by_index(clockman->clk_cell_i2s, 0);
+ clockman->clk_cell_audio = rt_clk_cell_get_parent_by_index(clockman->clk_cell_i2s, 1);
+
+ if ((err = rt_clk_register(&clockman->parent)))
+ {
+ LOG_E("%s: rt_clk_register failed err=%s",
+ rt_ofw_node_full_name(dev->ofw_node), rt_strerror(err));
+ goto _free;
+ }
+
+ return RT_EOK;
+
+_free:
+ if (clockman->regs)
+ {
+ rt_iounmap(clockman->regs);
+ }
+
+ rt_free(clockman);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rp1_clk_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rp1-clocks" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rp1_clk_driver =
+{
+ .name = "clk-rp1",
+ .ids = rp1_clk_ofw_ids,
+
+ .probe = rp1_clk_probe,
+};
+
+static int rp1_clk_register(void)
+{
+ rt_platform_driver_register(&rp1_clk_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rp1_clk_register);
diff --git a/bsp/raspberry-pi/dm/clock_time/Kconfig b/bsp/raspberry-pi/dm/clock_time/Kconfig
new file mode 100755
index 0000000000..f903a973d6
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clock_time/Kconfig
@@ -0,0 +1,3 @@
+config RT_CLOCK_TIME_BCM2835
+ bool "BCM2835 Timer"
+ default y
diff --git a/bsp/raspberry-pi/dm/clock_time/SConscript b/bsp/raspberry-pi/dm/clock_time/SConscript
new file mode 100755
index 0000000000..c6026dac73
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clock_time/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_CLOCK_TIME_BCM2835']):
+ src += ['clock_time-bcm2835_timer.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/clock_time/clock_time-bcm2835_timer.c b/bsp/raspberry-pi/dm/clock_time/clock_time-bcm2835_timer.c
new file mode 100755
index 0000000000..9b011bd070
--- /dev/null
+++ b/bsp/raspberry-pi/dm/clock_time/clock_time-bcm2835_timer.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-12-06 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <drivers/clock_time.h>
+
+#define REG_CONTROL 0x00
+#define REG_COUNTER_LO 0x04
+#define REG_COUNTER_HI 0x08
+#define REG_COMPARE(n) (0x0c + (n) * 4)
+#define MAX_TIMER 4
+
+struct bcm2835_timer;
+
+struct bcm2835_timer_device
+{
+ struct rt_clock_timer_device parent;
+
+ int id;
+ int irq;
+ void *compare;
+
+ struct bcm2835_timer *timer;
+};
+
+struct bcm2835_timer
+{
+ void *base;
+
+ struct bcm2835_timer_device device[MAX_TIMER];
+ struct rt_clock_timer_info info;
+};
+
+#define raw_to_bcm2835_timer(raw) rt_container_of(raw, struct bcm2835_timer_device, parent)
+
+static void bcm2835_timer_init(struct rt_clock_timer_device *timer, rt_uint32_t state)
+{
+ RT_UNUSED(timer);
+ RT_UNUSED(state);
+}
+
+static rt_err_t bcm2835_timer_start(struct rt_clock_timer_device *timer, rt_uint32_t cnt, rt_clock_timer_mode_t mode)
+{
+ rt_err_t err = RT_EOK;
+ struct bcm2835_timer_device *timer_dev = raw_to_bcm2835_timer(timer);
+
+ switch (mode)
+ {
+ case CLOCK_TIMER_MODE_ONESHOT:
+ HWREG32(timer_dev->compare) = HWREG32(timer_dev->timer->base + REG_COUNTER_LO) + cnt;
+ break;
+
+ case CLOCK_TIMER_MODE_PERIOD:
+ err = -RT_ENOSYS;
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ if (!err)
+ {
+ timer->cycles = cnt;
+ timer->mode = mode;
+ }
+
+ return err;
+}
+
+static void bcm2835_timer_stop(struct rt_clock_timer_device *timer)
+{
+ RT_UNUSED(timer);
+}
+
+static rt_uint32_t bcm2835_timer_count_get(struct rt_clock_timer_device *timer)
+{
+ struct bcm2835_timer_device *timer_dev = raw_to_bcm2835_timer(timer);
+
+ return HWREG32(timer_dev->timer->base + REG_COUNTER_LO);
+}
+
+static rt_err_t bcm2835_timer_ctrl(struct rt_clock_timer_device *timer, rt_uint32_t cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct bcm2835_timer_device *timer_dev = raw_to_bcm2835_timer(timer);
+
+ switch (cmd)
+ {
+ case CLOCK_TIMER_CTRL_FREQ_SET:
+ err = -RT_ENOSYS;
+ break;
+
+ case CLOCK_TIMER_CTRL_STOP:
+ bcm2835_timer_stop(timer);
+ break;
+
+ case CLOCK_TIMER_CTRL_INFO_GET:
+ if (args)
+ {
+ rt_memcpy(args, &timer_dev->timer->info, sizeof(timer_dev->timer->info));
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+ break;
+
+ case CLOCK_TIMER_CTRL_MODE_SET:
+ err = bcm2835_timer_start(timer, timer->cycles, (rt_clock_timer_mode_t)(rt_ubase_t)args);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+const static struct rt_clock_timer_ops bcm2835_timer_ops =
+{
+ .init = bcm2835_timer_init,
+ .start = bcm2835_timer_start,
+ .stop = bcm2835_timer_stop,
+ .count_get = bcm2835_timer_count_get,
+ .control = bcm2835_timer_ctrl,
+};
+
+static void bcm2835_timer_isr(int irqno, void *param)
+{
+ struct bcm2835_timer_device *timer_dev = param;
+ struct bcm2835_timer *timer = timer_dev->timer;
+
+ RT_UNUSED(irqno);
+
+ if (HWREG32(timer->base + REG_CONTROL) & RT_BIT(timer_dev->id))
+ {
+ /* ACK */
+ HWREG32(timer->base + REG_CONTROL) = RT_BIT(timer_dev->id);
+
+ rt_clock_timer_isr(&timer_dev->parent);
+ }
+}
+
+static rt_err_t bcm2835_timer_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ rt_uint32_t freq;
+ const char *dev_name;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_timer *timer = rt_calloc(1, sizeof(*timer));
+
+ if (!timer)
+ {
+ return -RT_ENOMEM;
+ }
+
+ timer->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!timer->base)
+ {
+ err = -RT_EIO;
+
+ goto _fail;
+ }
+
+ if (rt_dm_dev_prop_read_u32(dev, "clock-frequency", &freq))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ timer->info.maxfreq = freq;
+ timer->info.minfreq = freq;
+ timer->info.maxcnt = 0xffffffff;
+ timer->info.cntmode = CLOCK_TIMER_CNTMODE_UP;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(timer->device); ++i)
+ {
+ struct bcm2835_timer_device *timer_dev = &timer->device[i];
+
+ if ((timer_dev->irq = rt_dm_dev_get_irq(dev, i)) < 0)
+ {
+ continue;
+ }
+
+ timer_dev->id = i;
+ timer_dev->compare = timer->base + REG_COMPARE(i);
+ timer_dev->timer = timer;
+
+ timer_dev->parent.ops = &bcm2835_timer_ops;
+ timer_dev->parent.info = &timer->info;
+ timer_dev->parent.freq = freq;
+
+ rt_dm_dev_set_name_auto(&timer_dev->parent.parent, "timer");
+ dev_name = rt_dm_dev_get_name(&timer_dev->parent.parent);
+
+ rt_clock_timer_register(&timer_dev->parent, dev_name, RT_NULL);
+ rt_pic_attach_irq(timer_dev->irq, bcm2835_timer_isr, timer_dev, dev_name, RT_IRQ_F_NONE);
+ rt_pic_irq_unmask(timer_dev->irq);
+ }
+
+ dev->user_data = timer;
+
+ return RT_EOK;
+
+_fail:
+ if (timer->base)
+ {
+ rt_iounmap(timer->base);
+ }
+ rt_free(timer);
+
+ return err;
+}
+
+static rt_err_t bcm2835_timer_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_timer *timer = pdev->parent.user_data;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(timer->device); ++i)
+ {
+ struct bcm2835_timer_device *timer_dev = &timer->device[i];
+
+ if (timer_dev->irq < 0)
+ {
+ continue;
+ }
+
+ bcm2835_timer_stop(&timer_dev->parent);
+
+ rt_pic_irq_mask(timer_dev->irq);
+ rt_pic_detach_irq(timer_dev->irq, timer_dev);
+
+ rt_device_unregister(&timer_dev->parent.parent);
+ }
+
+ rt_iounmap(timer->base);
+ rt_free(timer);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_timer_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-system-timer", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_timer_driver =
+{
+ .name = "clock_timer-bcm2835",
+ .ids = bcm2835_timer_ofw_ids,
+
+ .probe = bcm2835_timer_probe,
+ .remove = bcm2835_timer_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_timer_driver);
diff --git a/bsp/raspberry-pi/dm/dma/Kconfig b/bsp/raspberry-pi/dm/dma/Kconfig
new file mode 100755
index 0000000000..ad1f7f595e
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dma/Kconfig
@@ -0,0 +1,3 @@
+config RT_DMA_BCM2835
+ bool "BCM2835 DMA"
+ default n
diff --git a/bsp/raspberry-pi/dm/dma/SConscript b/bsp/raspberry-pi/dm/dma/SConscript
new file mode 100755
index 0000000000..f6dfdc5466
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dma/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_DMA_BCM2835']):
+ src += ['dma-bcm2835.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/dma/dma-bcm2835.c b/bsp/raspberry-pi/dm/dma/dma-bcm2835.c
new file mode 100755
index 0000000000..b62adb926d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dma/dma-bcm2835.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <dt-bindings/size.h>
+
+#define DBG_TAG "dma.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define BCM2835_DMA_CS 0x00
+#define BCM2835_DMA_ADDR 0x04
+#define BCM2835_DMA_TI 0x08
+#define BCM2835_DMA_SOURCE_AD 0x0c
+#define BCM2835_DMA_DEST_AD 0x10
+#define BCM2835_DMA_LEN 0x14
+#define BCM2835_DMA_STRIDE 0x18
+#define BCM2835_DMA_NEXTCB 0x1c
+#define BCM2835_DMA_DEBUG 0x20
+
+/* DMA CS Control and Status bits */
+#define BCM2835_DMA_ACTIVE RT_BIT(0) /* Activate the DMA */
+#define BCM2835_DMA_END RT_BIT(1) /* Current CB has ended */
+#define BCM2835_DMA_INT RT_BIT(2) /* Interrupt status */
+#define BCM2835_DMA_DREQ RT_BIT(3) /* DREQ state */
+#define BCM2835_DMA_ISPAUSED RT_BIT(4) /* Pause requested or not active */
+#define BCM2835_DMA_ISHELD RT_BIT(5) /* Is held by DREQ flow control */
+#define BCM2835_DMA_WAITING_FOR_WRITES RT_BIT(6) /* Waiting for last AXI-write to ack */
+#define BCM2835_DMA_ERR RT_BIT(8)
+#define BCM2835_DMA_PRIORITY(x) ((x & 15) << 16) /* AXI priority */
+#define BCM2835_DMA_PANIC_PRIORITY(x) ((x & 15) << 20) /* Panic priority */
+#define BCM2835_DMA_WAIT_FOR_WRITES RT_BIT(28)
+#define BCM2835_DMA_DIS_DEBUG RT_BIT(29) /* Disable debug pause signal */
+#define BCM2835_DMA_ABORT RT_BIT(30) /* Stop current CB, go to next, WO */
+#define BCM2835_DMA_RESET RT_BIT(31) /* WO, self clearing */
+
+#define BCM2835_DMA_DEBUG_LITE RT_BIT(28)
+
+#define BCM2835_DMA_INT_EN RT_BIT(0)
+#define BCM2835_DMA_TDMODE RT_BIT(1) /* 2D-Mode */
+#define BCM2835_DMA_WAIT_RESP RT_BIT(3) /* wait for AXI-write to be acked */
+#define BCM2835_DMA_D_INC RT_BIT(4)
+#define BCM2835_DMA_D_WIDTH RT_BIT(5) /* 128bit writes if set */
+#define BCM2835_DMA_D_DREQ RT_BIT(6) /* Enable DREQ for destination */
+#define BCM2835_DMA_D_IGNORE RT_BIT(7) /* Ignore destination writes */
+#define BCM2835_DMA_S_INC RT_BIT(8)
+#define BCM2835_DMA_S_WIDTH RT_BIT(9) /* 128bit writes if set */
+#define BCM2835_DMA_S_DREQ RT_BIT(10) /* Enable SREQ for source */
+#define BCM2835_DMA_S_IGNORE RT_BIT(11) /* Ignore source reads - read 0 */
+#define BCM2835_DMA_BURST_LENGTH(x) (((x) & 15) << 12)
+#define BCM2835_DMA_GET_BURST_LENGTH(x) (((x) >> 12) & 15)
+#define BCM2835_DMA_CS_FLAGS(x) (x & (BCM2835_DMA_PRIORITY(15) | BCM2835_DMA_PANIC_PRIORITY(15) | \
+ BCM2835_DMA_WAIT_FOR_WRITES | BCM2835_DMA_DIS_DEBUG))
+
+#define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */
+#define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* Add DMA-wait cycles */
+#define BCM2835_DMA_NO_WIDE_BURSTS RT_BIT(26) /* No 2 beat write bursts */
+
+/* A fake bit to request that the driver doesn't set the WAIT_RESP bit. */
+#define BCM2835_DMA_NO_WAIT_RESP RT_BIT(27)
+#define WAIT_RESP(x) ((x & BCM2835_DMA_NO_WAIT_RESP) ? 0 : BCM2835_DMA_WAIT_RESP)
+
+/* A fake bit to request that the driver requires wide reads */
+#define BCM2835_DMA_WIDE_SOURCE RT_BIT(24)
+#define WIDE_SOURCE(x) ((x & BCM2835_DMA_WIDE_SOURCE) ? BCM2835_DMA_S_WIDTH : 0)
+
+/* A fake bit to request that the driver requires wide writes */
+#define BCM2835_DMA_WIDE_DEST RT_BIT(25)
+#define WIDE_DEST(x) ((x & BCM2835_DMA_WIDE_DEST) ? BCM2835_DMA_D_WIDTH : 0)
+
+/* A fake bit to request that the driver requires multi-beat burst */
+#define BCM2835_DMA_BURST RT_BIT(30)
+#define BURST_LENGTH(x) ((x & BCM2835_DMA_BURST) ? BCM2835_DMA_BURST_LENGTH(3) : 0)
+
+/* Valid only for channels 0 - 14, 15 has its own base address */
+#define BCM2835_DMA_CHAN_SIZE 0x100
+#define BCM2835_DMA_CHAN(n) ((n) * BCM2835_DMA_CHAN_SIZE) /* Base address */
+#define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
+
+/* 40-bit DMA support */
+#define BCM2711_DMA40_CS 0x00
+#define BCM2711_DMA40_CB 0x04
+#define BCM2711_DMA40_DEBUG 0x0c
+#define BCM2711_DMA40_TI 0x10
+#define BCM2711_DMA40_SRC 0x14
+#define BCM2711_DMA40_SRCI 0x18
+#define BCM2711_DMA40_DEST 0x1c
+#define BCM2711_DMA40_DESTI 0x20
+#define BCM2711_DMA40_LEN 0x24
+#define BCM2711_DMA40_NEXT_CB 0x28
+#define BCM2711_DMA40_DEBUG2 0x2c
+
+#define BCM2711_DMA40_DEBUG_RESET RT_BIT(23)
+
+#define BCM2711_DMA40_ACTIVE RT_BIT(0)
+#define BCM2711_DMA40_END RT_BIT(1)
+#define BCM2711_DMA40_INT RT_BIT(2)
+#define BCM2711_DMA40_DREQ RT_BIT(3) /* DREQ state */
+#define BCM2711_DMA40_RD_PAUSED RT_BIT(4) /* Reading is paused */
+#define BCM2711_DMA40_WR_PAUSED RT_BIT(5) /* Writing is paused */
+#define BCM2711_DMA40_DREQ_PAUSED RT_BIT(6) /* Is paused by DREQ flow control */
+#define BCM2711_DMA40_WAITING_FOR_WRITES RT_BIT(7) /* Waiting for last write */
+#define BCM2711_DMA40_PROT (RT_BIT(8) | RT_BIT(9))
+#define BCM2711_DMA40_ERR RT_BIT(10)
+#define BCM2711_DMA40_QOS(x) (((x) & 0x1f) << 16)
+#define BCM2711_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20)
+#define BCM2711_DMA40_TRANSACTIONS RT_BIT(25)
+#define BCM2711_DMA40_WAIT_FOR_WRITES RT_BIT(28)
+#define BCM2711_DMA40_DISDEBUG RT_BIT(29)
+#define BCM2711_DMA40_ABORT RT_BIT(30)
+#define BCM2711_DMA40_HALT RT_BIT(31)
+
+#define BCM2711_DMA40_CS_FLAGS(x) (x & (BCM2711_DMA40_QOS(15) | BCM2711_DMA40_PANIC_QOS(15) | \
+ BCM2711_DMA40_WAIT_FOR_WRITES | BCM2711_DMA40_DISDEBUG))
+
+#define BCM2711_DMA40_INTEN RT_BIT(0)
+#define BCM2711_DMA40_TDMODE RT_BIT(1) /* 2D-Mode */
+#define BCM2711_DMA40_WAIT_RESP RT_BIT(2) /* Wait for AXI write to be acked */
+#define BCM2711_DMA40_WAIT_RD_RESP RT_BIT(3) /* Wait for AXI read to complete */
+#define BCM2711_DMA40_PER_MAP(x) ((x & 31) << 9) /* REQ source */
+#define BCM2711_DMA40_S_DREQ RT_BIT(14) /* Enable SREQ for source */
+#define BCM2711_DMA40_D_DREQ RT_BIT(15) /* Enable DREQ for destination */
+#define BCM2711_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* Add DMA read-wait cycles */
+#define BCM2711_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* Add DMA write-wait cycles */
+
+#define BCM2711_DMA40_BURST_LEN(x) (((x) & 15) << 8)
+#define BCM2711_DMA40_INC RT_BIT(12)
+#define BCM2711_DMA40_SIZE_32 (0 << 13)
+#define BCM2711_DMA40_SIZE_64 (1 << 13)
+#define BCM2711_DMA40_SIZE_128 (2 << 13)
+#define BCM2711_DMA40_SIZE_256 (3 << 13)
+#define BCM2711_DMA40_IGNORE RT_BIT(15)
+#define BCM2711_DMA40_STRIDE(x) ((x) << 16) /* For 2D mode */
+
+#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
+#define BCM2835_DMA_CHAN_NAME_SIZE 8
+#define BCM2835_DMA_BULK_MASK RT_BIT(0)
+#define BCM2711_DMA_MEMCPY_CHAN 14
+
+#define MAX_DMA_LEN SIZE_GB
+#define MAX_LITE_DMA_LEN (64 * SIZE_KB - 4)
+
+struct bcm2835_dma_control_block
+{
+ rt_uint32_t info;
+ rt_uint32_t src;
+ rt_uint32_t dst;
+ rt_uint32_t length;
+ rt_uint32_t stride;
+ rt_uint32_t next;
+ rt_uint32_t padding[2];
+};
+
+struct bcm2711_dma40_control_block
+{
+ rt_uint32_t ti;
+ rt_uint32_t src;
+ rt_uint32_t srci;
+ rt_uint32_t dst;
+ rt_uint32_t dsti;
+ rt_uint32_t len;
+ rt_uint32_t next_cb;
+ rt_uint32_t rsvd;
+};
+
+struct bcm2835_dma_soc_data
+{
+ rt_uint32_t chan_40bit_mask;
+ rt_uint64_t dma_mask;
+};
+
+struct bcm2835_chan
+{
+ struct rt_dma_chan parent;
+
+ int irq;
+ void *base;
+
+ rt_size_t size;
+ rt_uint32_t dreq;
+ rt_bool_t enabled;
+
+ void *control_block;
+ rt_ubase_t control_block_dma;
+};
+
+struct bcm2835_dma
+{
+ struct rt_dma_controller parent;
+ const struct bcm2835_dma_soc_data *data;
+
+ void *base;
+ rt_uint32_t num_chans;
+ struct bcm2835_chan *chans;
+
+ rt_size_t max_frame_length;
+
+ rt_bool_t is_2712;
+ rt_bool_t is_40bit;
+};
+#define raw_to_bcm2835_dma(raw) rt_container_of(raw, struct bcm2835_dma, parent)
+#define raw_to_bcm2835_dma_chan(raw) rt_container_of(raw, struct bcm2835_chan, parent)
+
+rt_inline rt_ubase_t to_40bit_cbaddr(rt_ubase_t addr)
+{
+ return addr >> 5;
+}
+
+rt_inline rt_uint32_t to_bcm2711_ti(rt_uint32_t info)
+{
+ return ((info & BCM2835_DMA_INT_EN) ? BCM2711_DMA40_INTEN : 0) |
+ ((info & BCM2835_DMA_WAIT_RESP) ? BCM2711_DMA40_WAIT_RESP : 0) |
+ ((info & BCM2835_DMA_S_DREQ) ?
+ (BCM2711_DMA40_S_DREQ | BCM2711_DMA40_WAIT_RD_RESP) : 0) |
+ ((info & BCM2835_DMA_D_DREQ) ? BCM2711_DMA40_D_DREQ : 0) |
+ BCM2711_DMA40_PER_MAP((info >> 16) & 0x1f);
+}
+
+rt_inline rt_uint32_t to_bcm2711_srci(rt_uint32_t info)
+{
+ return ((info & BCM2835_DMA_S_INC) ? BCM2711_DMA40_INC : 0) |
+ ((info & BCM2835_DMA_S_WIDTH) ? BCM2711_DMA40_SIZE_128 : 0) |
+ BCM2711_DMA40_BURST_LEN(BCM2835_DMA_GET_BURST_LENGTH(info));
+}
+
+rt_inline rt_uint32_t to_bcm2711_dsti(rt_uint32_t info)
+{
+ return ((info & BCM2835_DMA_D_INC) ? BCM2711_DMA40_INC : 0) |
+ ((info & BCM2835_DMA_D_WIDTH) ? BCM2711_DMA40_SIZE_128 : 0) |
+ BCM2711_DMA40_BURST_LEN(BCM2835_DMA_GET_BURST_LENGTH(info));
+}
+
+rt_inline rt_size_t bcm2835_dma_frames_for_length(rt_size_t len, rt_size_t max_len)
+{
+ return RT_DIV_ROUND_UP(len, max_len);
+}
+
+static rt_err_t bcm2835_dma_fill_prep(struct bcm2835_chan *chan, enum rt_dma_transfer_direction dir,
+ rt_bool_t cyclic, rt_uint32_t info, rt_uint32_t finalextrainfo, rt_size_t frames,
+ rt_ubase_t src, rt_ubase_t dst, rt_size_t buf_len, rt_size_t period_len)
+{
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->parent.ctrl);
+
+ if (frames > 1)
+ {
+ /*
+ * Should create dma buffer and fill the CB list if enable,
+ * This demand is rare or even non-existent on RT-thread.
+ */
+ return -RT_ENOSYS;
+ }
+ info |= finalextrainfo;
+
+ if (dma->is_40bit)
+ {
+ struct bcm2711_dma40_control_block *cb = chan->control_block;
+
+ cb->ti = to_bcm2711_ti(info);
+ cb->src = rt_lower_32_bits(src);
+ cb->srci = rt_upper_32_bits(src) | to_bcm2711_srci(info);
+ cb->dst = rt_lower_32_bits(dst);
+ cb->dsti = rt_upper_32_bits(dst) | to_bcm2711_dsti(info);
+ cb->len = buf_len;
+ cb->next_cb = 0;
+ }
+ else
+ {
+ struct bcm2835_dma_control_block *cb = chan->control_block;
+
+ cb->info = info;
+ cb->src = src;
+ cb->dst = dst;
+ cb->length = buf_len;
+
+ if (dma->is_2712)
+ {
+ cb->stride = (rt_upper_32_bits(dst) << 8) | rt_upper_32_bits(src);
+ }
+ else
+ {
+ cb->stride = 0;
+ }
+
+ cb->next = 0;
+ }
+
+ return RT_EOK;
+}
+
+static struct rt_dma_chan *bcm2835_dma_request_chan(struct rt_dma_controller *ctrl,
+ struct rt_device *slave, void *fw_data)
+{
+ rt_size_t size;
+ struct bcm2835_chan *chan = RT_NULL;
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(ctrl);
+ struct rt_ofw_cell_args *args = fw_data;
+
+ for (int i = 0; i < dma->num_chans; ++i)
+ {
+ if (!dma->chans[i].enabled)
+ {
+ chan = &dma->chans[i];
+ break;
+ }
+ }
+
+ if (!chan)
+ {
+ return rt_err_ptr(-RT_EBUSY);
+ }
+
+ if (dma->is_40bit)
+ {
+ size = sizeof(struct bcm2711_dma40_control_block);
+ }
+ else
+ {
+ size = sizeof(struct bcm2835_dma_control_block);
+ }
+
+ chan->control_block = rt_dma_alloc_coherent(slave, size, &chan->control_block_dma);
+
+ if (!chan->control_block)
+ {
+ return rt_err_ptr(-RT_ENOMEM);
+ }
+
+ chan->dreq = args ? args->args[0] : 0;
+ chan->enabled = RT_TRUE;
+
+ return &chan->parent;
+}
+
+static rt_err_t bcm2835_dma_release_chan(struct rt_dma_chan *chan)
+{
+ rt_size_t size;
+ struct bcm2835_chan *bcm_chan = rt_container_of(chan, struct bcm2835_chan, parent);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ bcm_chan->enabled = RT_FALSE;
+
+ if (dma->is_40bit)
+ {
+ size = sizeof(struct bcm2711_dma40_control_block);
+ }
+ else
+ {
+ size = sizeof(struct bcm2835_dma_control_block);
+ }
+
+ rt_dma_free_coherent(chan->slave, size,
+ bcm_chan->control_block, bcm_chan->control_block_dma);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_dma_start(struct rt_dma_chan *chan)
+{
+ void *base;
+ rt_ubase_t cb_dma;
+ struct bcm2835_chan *bcm_chan = raw_to_bcm2835_dma_chan(chan);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ base = bcm_chan->base;
+ cb_dma = bcm_chan->control_block_dma;
+
+ if (dma->is_40bit)
+ {
+ HWREG32(base + BCM2711_DMA40_CB) = to_40bit_cbaddr(cb_dma);
+ HWREG32(base + BCM2711_DMA40_CS) =
+ BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT | BCM2711_DMA40_CS_FLAGS(bcm_chan->dreq);
+ }
+ else
+ {
+ HWREG32(base + BCM2835_DMA_CS) = RT_BIT(31);
+ HWREG32(base + BCM2835_DMA_ADDR) = dma->is_2712 ? to_40bit_cbaddr(cb_dma) : cb_dma;
+ HWREG32(base + BCM2835_DMA_CS) = BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(bcm_chan->dreq);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_dma_stop(struct rt_dma_chan *chan)
+{
+ void *base;
+ rt_uint32_t timeout = 100;
+ struct bcm2835_chan *bcm_chan = raw_to_bcm2835_dma_chan(chan);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ base = bcm_chan->base;
+
+ if (dma->is_40bit)
+ {
+ if (!HWREG32(base + BCM2711_DMA40_CB))
+ {
+ return RT_EOK;
+ }
+
+ /* Pause the current DMA */
+ HWREG32(base + BCM2711_DMA40_CS) = HWREG32(base + BCM2711_DMA40_CS) & ~BCM2711_DMA40_ACTIVE;
+
+ /* wait for outstanding transactions to complete */
+ while ((HWREG32(base + BCM2711_DMA40_CS) & BCM2711_DMA40_TRANSACTIONS) && --timeout)
+ {
+ rt_hw_cpu_relax();
+ }
+
+ /* Peripheral might be stuck and fail to complete */
+ if (!timeout)
+ {
+ LOG_E("Failed to complete pause on dma[%d] CS:%08x", bcm_chan - dma->chans,
+ HWREG32(base + BCM2711_DMA40_CS));
+ }
+
+ /* Set CS back to default state */
+ HWREG32(base + BCM2711_DMA40_CS) = BCM2711_DMA40_PROT;
+
+ /* Reset the DMA */
+ HWREG32(base + BCM2711_DMA40_DEBUG) |= BCM2711_DMA40_DEBUG_RESET;
+ }
+ else
+ {
+ if (!HWREG32(base + BCM2835_DMA_ADDR))
+ {
+ return RT_EOK;
+ }
+
+ /* We need to clear the next DMA block pending */
+ HWREG32(base + BCM2835_DMA_NEXTCB) = 0;
+
+ /* Abort the DMA, which needs to be enabled to complete */
+ HWREG32(base + BCM2835_DMA_CS) =
+ HWREG32(base + BCM2835_DMA_CS) | BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE;
+
+ /* Wait for DMA to be aborted */
+ while ((HWREG32(base + BCM2835_DMA_CS) & BCM2835_DMA_ABORT) && --timeout)
+ {
+ rt_hw_cpu_relax();
+ }
+
+ /* Write 0 to the active bit - Pause the DMA */
+ HWREG32(base + BCM2835_DMA_CS) =
+ HWREG32(base + BCM2835_DMA_CS) & ~BCM2835_DMA_ACTIVE;
+
+ if (!timeout && !(HWREG32(base + BCM2835_DMA_TI) &
+ (BCM2835_DMA_S_DREQ | BCM2835_DMA_D_DREQ)))
+ {
+ LOG_E("Failed to complete pause on dma[%d] CS:%08x", bcm_chan - dma->chans,
+ HWREG32(base + BCM2835_DMA_CS));
+ }
+
+ /* Set CS back to default state and reset the DMA */
+ HWREG32(base + BCM2835_DMA_CS) = BCM2835_DMA_RESET;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_dma_config(struct rt_dma_chan *chan,
+ struct rt_dma_slave_config *conf)
+{
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_dma_prep_memcpy(struct rt_dma_chan *chan,
+ rt_ubase_t dma_addr_src, rt_ubase_t dma_addr_dst, rt_size_t len)
+{
+ rt_size_t frames;
+ rt_uint32_t info, extra;
+ struct bcm2835_chan *bcm_chan = raw_to_bcm2835_dma_chan(chan);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC |
+ WAIT_RESP(bcm_chan->dreq) | WIDE_SOURCE(bcm_chan->dreq) |
+ WIDE_DEST(bcm_chan->dreq) | BURST_LENGTH(bcm_chan->dreq);
+ extra = BCM2835_DMA_INT_EN;
+ frames = bcm2835_dma_frames_for_length(len, dma->max_frame_length);
+
+ bcm_chan->size = len;
+
+ return bcm2835_dma_fill_prep(bcm_chan, RT_DMA_MEM_TO_MEM, RT_FALSE,
+ info, extra, frames, dma_addr_src, dma_addr_dst, len, 0);
+}
+
+static rt_err_t bcm2835_dma_prep_cyclic(struct rt_dma_chan *chan,
+ rt_ubase_t dma_buf_addr, rt_size_t buf_len, rt_size_t period_len,
+ enum rt_dma_transfer_direction dir)
+{
+ rt_size_t frames;
+ rt_ubase_t src, dst;
+ rt_uint32_t info, extra;
+ struct bcm2835_chan *bcm_chan = raw_to_bcm2835_dma_chan(chan);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ info = WAIT_RESP(bcm_chan->dreq) | WIDE_SOURCE(bcm_chan->dreq) |
+ WIDE_DEST(bcm_chan->dreq) | BURST_LENGTH(bcm_chan->dreq);
+ extra = 0;
+
+ if (bcm_chan->dreq)
+ {
+ info |= BCM2835_DMA_PER_MAP(bcm_chan->dreq);
+ }
+
+ if (dir == RT_DMA_DEV_TO_MEM)
+ {
+ if (chan->conf.src_addr_width != RT_DMA_SLAVE_BUSWIDTH_4_BYTES)
+ {
+ return -RT_EINVAL;
+ }
+
+ src = chan->conf.src_addr;
+ dst = dma_buf_addr;
+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
+ }
+ else
+ {
+ if (chan->conf.dst_addr_width != RT_DMA_SLAVE_BUSWIDTH_4_BYTES)
+ {
+ return -RT_EINVAL;
+ }
+
+ dst = chan->conf.dst_addr;
+ src = dma_buf_addr;
+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+ }
+
+ frames = RT_DIV_ROUND_UP(buf_len, period_len) *
+ bcm2835_dma_frames_for_length(period_len, dma->max_frame_length);
+
+ bcm_chan->size = buf_len;
+
+ return bcm2835_dma_fill_prep(bcm_chan, dir, RT_TRUE,
+ info, extra, frames, src, dst, buf_len, period_len);
+}
+
+static rt_err_t bcm2835_dma_prep_single(struct rt_dma_chan *chan,
+ rt_ubase_t dma_buf_addr, rt_size_t buf_len,
+ enum rt_dma_transfer_direction dir)
+{
+ rt_size_t frames;
+ rt_ubase_t src, dst;
+ rt_uint32_t info, extra;
+ struct bcm2835_chan *bcm_chan = raw_to_bcm2835_dma_chan(chan);
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->ctrl);
+
+ info = WAIT_RESP(bcm_chan->dreq) | WIDE_SOURCE(bcm_chan->dreq) |
+ WIDE_DEST(bcm_chan->dreq) | BURST_LENGTH(bcm_chan->dreq);
+ extra = BCM2835_DMA_INT_EN;
+
+ if (bcm_chan->dreq)
+ {
+ info |= BCM2835_DMA_PER_MAP(bcm_chan->dreq);
+ }
+
+ if (dir == RT_DMA_DEV_TO_MEM)
+ {
+ if (chan->conf.src_addr_width != RT_DMA_SLAVE_BUSWIDTH_4_BYTES)
+ {
+ return -RT_EINVAL;
+ }
+
+ dst = dma_buf_addr;
+ src = chan->conf.src_addr;
+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
+ }
+ else
+ {
+ if (chan->conf.dst_addr_width != RT_DMA_SLAVE_BUSWIDTH_4_BYTES)
+ {
+ return -RT_EINVAL;
+ }
+
+ dst = chan->conf.dst_addr;
+ src = dma_buf_addr;
+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+ }
+
+ frames = bcm2835_dma_frames_for_length(buf_len, dma->max_frame_length);
+ bcm_chan->size = buf_len;
+
+ return bcm2835_dma_fill_prep(bcm_chan, dir, RT_FALSE,
+ info, extra, frames, src, dst, buf_len, 0);
+}
+
+static const struct rt_dma_controller_ops bcm2835_dma_ops =
+{
+ .request_chan = bcm2835_dma_request_chan,
+ .release_chan = bcm2835_dma_release_chan,
+ .start = bcm2835_dma_start,
+ .stop = bcm2835_dma_stop,
+ .config = bcm2835_dma_config,
+ .prep_memcpy = bcm2835_dma_prep_memcpy,
+ .prep_cyclic = bcm2835_dma_prep_cyclic,
+ .prep_single = bcm2835_dma_prep_single,
+};
+
+static void bcm2835_dma_isr(int irq, void *param)
+{
+ struct bcm2835_chan *chan = param;
+ struct bcm2835_dma *dma = raw_to_bcm2835_dma(chan->parent.ctrl);
+
+ /* Check for share IRQ */
+ if (!(HWREG32(chan->base + BCM2835_DMA_CS) & BCM2835_DMA_INT))
+ {
+ return;
+ }
+
+ if (dma->is_40bit)
+ {
+ HWREG32(chan->base + BCM2711_DMA40_CS) =
+ BCM2835_DMA_INT | BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT |
+ BCM2711_DMA40_CS_FLAGS(chan->dreq);
+ }
+ else
+ {
+ HWREG32(chan->base + BCM2835_DMA_CS) =
+ BCM2835_DMA_INT | BCM2835_DMA_ACTIVE |
+ BCM2835_DMA_CS_FLAGS(chan->dreq);
+ }
+
+ rt_dma_chan_done(&chan->parent, chan->size);
+}
+
+static rt_err_t bcm2835_dma_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint64_t addr, size;
+ rt_uint32_t channel_mask = ~0U;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_dma *dma = rt_calloc(1, sizeof(*dma));
+
+ if (!dma)
+ {
+ return -RT_ENOMEM;
+ }
+ dma->data = pdev->id->data;
+
+ if (dma->data->dma_mask == RT_DMA_ADDR_MASK(40))
+ {
+ dma->is_2712 = RT_TRUE;
+ }
+
+ rt_ofw_prop_read_u32(dev->ofw_node, "brcm,dma-channel-mask", &channel_mask);
+ dma->is_40bit = !!(dma->data->chan_40bit_mask & channel_mask);
+
+ if ((err = rt_dm_dev_get_address(dev, 0, &addr, &size)))
+ {
+ goto _fail;
+ }
+
+ if (!(dma->base = rt_ioremap((void *)addr, size)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if (HWREG32(dma->base + BCM2835_DMA_DEBUG) & BCM2835_DMA_DEBUG_LITE)
+ {
+ dma->max_frame_length = MAX_LITE_DMA_LEN;
+ }
+ else
+ {
+ dma->max_frame_length = MAX_DMA_LEN;
+ }
+
+ dma->num_chans = size / BCM2835_DMA_CHAN_SIZE;
+
+ dma->chans = rt_calloc(dma->num_chans, sizeof(dma->chans[0]));
+
+ if (!dma->chans)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ for (int i = 0; i < dma->num_chans; ++i)
+ {
+ struct bcm2835_chan *chan = &dma->chans[i];
+
+ chan->irq = rt_dm_dev_get_irq(dev, i);
+
+ if (chan->irq < 0)
+ {
+ err = chan->irq;
+ goto _fail;
+ }
+ }
+
+ dma->parent.dev = dev;
+ dma->parent.ops = &bcm2835_dma_ops;
+ rt_dma_controller_add_direction(&dma->parent, RT_DMA_MEM_TO_MEM);
+ rt_dma_controller_add_direction(&dma->parent, RT_DMA_MEM_TO_DEV);
+ rt_dma_controller_add_direction(&dma->parent, RT_DMA_DEV_TO_MEM);
+ rt_dma_controller_set_addr_mask(&dma->parent, dma->data->dma_mask);
+
+ if ((err = rt_dma_controller_register(&dma->parent)))
+ {
+ goto _fail;
+ }
+
+ for (int i = 0; i < dma->num_chans; ++i)
+ {
+ char isr_name[RT_NAME_MAX];
+ struct bcm2835_chan *chan = &dma->chans[i];
+
+ chan->base = dma->base + i * BCM2835_DMA_CHAN_SIZE;
+
+ rt_sprintf(isr_name, "dma-%u", i);
+
+ rt_hw_interrupt_install(chan->irq, bcm2835_dma_isr, chan, isr_name);
+ rt_hw_interrupt_umask(chan->irq);
+ }
+
+ dev->user_data = dma;
+
+ return err;
+
+_fail:
+ if (dma->chans)
+ {
+ rt_free(dma->chans);
+ }
+
+ if (dma->base)
+ {
+ rt_iounmap(dma->base);
+ }
+
+ rt_free(dma);
+
+ return err;
+}
+
+static rt_err_t bcm2835_dma_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_dma *dma = pdev->parent.user_data;
+
+ rt_dma_controller_unregister(&dma->parent);
+
+ for (int i = 0; i < dma->num_chans; ++i)
+ {
+ struct bcm2835_chan *chan = &dma->chans[i];
+
+ rt_hw_interrupt_mask(chan->irq);
+ rt_pic_detach_irq(chan->irq, chan);
+ }
+
+ rt_free(dma->chans);
+ rt_iounmap(dma->base);
+
+ rt_free(dma);
+
+ return RT_EOK;
+}
+
+static const struct bcm2835_dma_soc_data bcm2835_dma_data =
+{
+ .chan_40bit_mask = 0,
+ .dma_mask = RT_DMA_ADDR_MASK(32),
+};
+
+static const struct bcm2835_dma_soc_data bcm2711_dma_data =
+{
+ .chan_40bit_mask = RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14),
+ .dma_mask = RT_DMA_ADDR_MASK(36),
+};
+
+static const struct bcm2835_dma_soc_data bcm2712_dma_data =
+{
+ .chan_40bit_mask = RT_BIT(6) | RT_BIT(7) | RT_BIT(8) | RT_BIT(9) | RT_BIT(10) | RT_BIT(11),
+ .dma_mask = RT_DMA_ADDR_MASK(40),
+};
+
+static const struct rt_ofw_node_id bcm2835_dma_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_data },
+ { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_dma_data },
+ { .compatible = "brcm,bcm2712-dma", .data = &bcm2712_dma_data },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_dma_driver =
+{
+ .name = "dma-bcm2835",
+ .ids = bcm2835_dma_ofw_ids,
+
+ .probe = bcm2835_dma_probe,
+ .remove = bcm2835_dma_remove,
+};
+
+static int bcm2835_dma_drv_register(void)
+{
+ rt_platform_driver_register(&bcm2835_dma_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_dma_drv_register);
diff --git a/bsp/raspberry-pi/dm/dts/bcm2711-rpi-4-b.dts b/bsp/raspberry-pi/dm/dts/bcm2711-rpi-4-b.dts
new file mode 100755
index 0000000000..68d9bfd1d5
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dts/bcm2711-rpi-4-b.dts
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+/dts-v1/;
+#include <dt-bindings/pinctrl/bcm2835.h>
+#include <dt-bindings/clock/bcm2835.h>
+#include <dt-bindings/clock/bcm2835-aux.h>
+#include <dt-bindings/pin/pin.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/bcm2835-pm.h>
+#include <dt-bindings/power/raspberrypi-power.h>
+#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/*
+ * NOTE: Just for QEMU, not the really board!
+ */
+
+/*
+ * firmware-provided startup stubs live here, where the secondary CPUs are
+ * spinning.
+ */
+/memreserve/ 0x00000000 0x00001000;
+
+/ {
+ compatible = "raspberrypi,4-model-b", "brcm,bcm2711";
+ model = "Raspberry Pi 4 Model B Rev 1.2";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ interrupt-parent = <&gicv2>;
+
+ aliases {
+ serial0 = "/soc/serial@7e215040";
+ serial1 = "/soc/serial@7e201000";
+ mmc0 = "/soc/mmcnr@7e300000";
+ spi0 = "/soc/spi@7e204000";
+ i2c0 = "/soc/i2c@7e205000";
+ i2c1 = "/soc/i2c@7e804000";
+ i2c2 = "/soc/i2c@7e805000";
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* For ARM 32-bit */
+ enable-method = "brcm,bcm2836-smp";
+
+ /*
+ * Source for d/i-cache-line-size and d/i-cache-sets
+ * https://developer.arm.com/documentation/100095/0003
+ * /Level-1-Memory-System/About-the-L1-memory-system?lang=en
+ * Source for d/i-cache-size
+ * https://www.raspberrypi.com/documentation/computers
+ * /processors.html#bcm2711
+ */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000d8>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e0>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e8>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000f0>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ i-cache-size = <0xc000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 48KiB(size)/64(line-size)=768ways/3-way set
+ next-level-cache = <&l2>;
+ };
+
+ /*
+ * Source for d/i-cache-line-size and d/i-cache-sets
+ * https://developer.arm.com/documentation/100095/0003
+ * /Level-2-Memory-System/About-the-L2-memory-system?lang=en
+ * Source for d/i-cache-size
+ * https://www.raspberrypi.com/documentation/computers
+ * /processors.html#bcm2711
+ */
+ l2: l2-cache0 {
+ compatible = "cache";
+ cache-size = <0x100000>;
+ cache-line-size = <64>;
+ cache-sets = <1024>; // 1MiB(size)/64(line-size)=16384ways/16-way set
+ cache-level = <2>;
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a72-pmu", "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ /* This only applies to the ARMv7 stub */
+ arm,cpu-registers-not-fw-configured;
+ };
+
+ thermal-zones {
+
+ cpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+ thermal-sensors = <&thermal>;
+ coefficients = <(-487) 410040>;
+
+ trips {
+ cpu-crit {
+ temperature = <110000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ /*
+ * Defined ranges:
+ * Common BCM283x peripherals
+ * BCM2711-specific peripherals
+ * ARM-local peripherals
+ */
+ ranges = <0x7e000000 0x0 0xfe000000 0x01800000>,
+ <0x7c000000 0x0 0xfc000000 0x02000000>,
+ <0x40000000 0x0 0xff800000 0x00800000>;
+ /* Emulate a contiguous 30-bit address range for DMA */
+ dma-ranges = <0xc0000000 0x0 0x00000000 0x40000000>,
+ <0x7c000000 0x0 0xfc000000 0x03800000>;
+
+ system_timer: timer@7e003000 {
+ compatible = "brcm,bcm2835-system-timer";
+ reg = <0x7e003000 0x1000>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ /*
+ * This could be a reference to BCM2835_CLOCK_TIMER,
+ * but we don't have the driver using the common clock
+ * support yet.
+ */
+ clock-frequency = <1000000>;
+ };
+
+ dsi0: dsi@7e209000 {
+ compatible = "brcm,bcm2711-dsi0","brcm,bcm2835-dsi0";
+ reg = <0x7e209000 0x78>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ clocks = <&clocks BCM2835_PLLA_DSI0>,
+ <&clocks BCM2835_CLOCK_DSI0E>,
+ <&clocks BCM2835_CLOCK_DSI0P>;
+ clock-names = "phy", "escape", "pixel";
+ clock-output-names = "dsi0_byte", "dsi0_ddr2", "dsi0_ddr";
+ status = "disabled";
+ };
+
+ dsi1: dsi@7e700000 {
+ compatible = "brcm,bcm2711-dsi1","brcm,bcm2835-dsi1";
+ reg = <0x7e700000 0x8c>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <1>;
+ clocks = <&clocks BCM2835_PLLD_DSI1>,
+ <&clocks BCM2835_CLOCK_DSI1E>,
+ <&clocks BCM2835_CLOCK_DSI1P>;
+ clock-names = "phy", "escape", "pixel";
+ clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
+ status = "disabled";
+ };
+
+ clocks: cprman@7e101000 {
+ compatible = "brcm,bcm2835-cprman";
+ #clock-cells = <1>;
+ reg = <0x7e101000 0x2000>;
+
+ /*
+ * CPRMAN derives almost everything from the
+ * platform's oscillator. However, the DSI
+ * pixel clocks come from the DSI analog PHY.
+ */
+ clocks = <&clk_osc>,
+ <&dsi0 0>,<&dsi0 1>,<&dsi0 2>,
+ <&dsi1 0>,<&dsi1 1>,<&dsi1 2>;
+ firmware = <&firmware>;
+ };
+
+ mailbox: mailbox@7e00b880 {
+ compatible = "brcm,bcm2835-mbox";
+ reg = <0x7e00b880 0x40>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <0>;
+ };
+
+ gpio: gpio@7e200000 {
+ compatible = "brcm,bcm2711-gpio";
+ reg = <0x7e200000 0xb4>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gpio-ranges = <&gpio 0 0 58>;
+ pinctrl-names = "default";
+
+ /*
+ * Parts taken from rpi_SCH_4b_4p0_reduced.pdf and
+ * the official GPU firmware DT blob.
+ *
+ * Legend:
+ * "FOO" = GPIO line named "FOO" on the schematic
+ * "FOO_N" = GPIO line named "FOO" on schematic, active low
+ */
+ gpio-line-names = "ID_SDA", /* 0 */
+ "ID_SCL",
+ "SDA1",
+ "SCL1",
+ "GPIO_GCLK",
+ "GPIO5", /* 5 */
+ "GPIO6",
+ "SPI_CE1_N",
+ "SPI_CE0_N",
+ "SPI_MISO",
+ "SPI_MOSI", /* 10 */
+ "SPI_SCLK",
+ "GPIO12",
+ "GPIO13",
+ /* Serial port */
+ "TXD1",
+ "RXD1", /* 15 */
+ "GPIO16",
+ "GPIO17",
+ "GPIO18",
+ "GPIO19",
+ "GPIO20", /* 20 */
+ "GPIO21",
+ "GPIO22",
+ "GPIO23",
+ "GPIO24",
+ "GPIO25", /* 25 */
+ "GPIO26",
+ "GPIO27",
+ "RGMII_MDIO",
+ "RGMIO_MDC",
+ /* Used by BT module */
+ "CTS0", /* 30 */
+ "RTS0",
+ "TXD0",
+ "RXD0",
+ /* Used by Wifi */
+ "SD1_CLK",
+ "SD1_CMD", /* 35 */
+ "SD1_DATA0",
+ "SD1_DATA1",
+ "SD1_DATA2",
+ "SD1_DATA3",
+ /* Shared with SPI flash */
+ "PWM0_MISO", /* 40 */
+ "PWM1_MOSI",
+ "STATUS_LED_G_CLK",
+ "SPIFLASH_CE_N",
+ "SDA0",
+ "SCL0", /* 45 */
+ "RGMII_RXCLK",
+ "RGMII_RXCTL",
+ "RGMII_RXD0",
+ "RGMII_RXD1",
+ "RGMII_RXD2", /* 50 */
+ "RGMII_RXD3",
+ "RGMII_TXCLK",
+ "RGMII_TXCTL",
+ "RGMII_TXD0",
+ "RGMII_TXD1", /* 55 */
+ "RGMII_TXD2",
+ "RGMII_TXD3";
+
+ spi0_pins: spi0_pins {
+ brcm,pins = <9 10 11>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ spi0_cs_pins: spi0_cs_pins {
+ brcm,pins = <8 7>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ i2c0_gpio0: i2c0_gpio0 {
+ brcm,pins = <0 1>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ i2c1_gpio2: i2c1_gpio2 {
+ brcm,pins = <2 3>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ sdio_pins: sdio_pins {
+ brcm,pins = <34 35 36 37 38 39>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ brcm,pull = <BCM2835_PUD_OFF>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>;
+ };
+
+ bt_pins: bt_pins {
+ brcm,pins = "-";
+ brcm,function = <0>;
+ brcm,pull = <BCM2835_PUD_UP>;
+ };
+
+ uart0_pins: uart0_pins {
+ brcm,pins = <32 33>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
+ };
+
+ uart0_gpio14: uart0-gpio14 {
+ brcm,pins = <14 15>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ uart1_pins: uart1_pins {
+ brcm,pins;
+ brcm,function;
+ brcm,pull;
+ };
+ };
+
+ serial@7e201000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x7e201000 0x200>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_UART>,
+ <&clocks BCM2835_CLOCK_VPU>;
+ clock-names = "uartclk", "apb_pclk";
+ arm,primecell-periphid = <0x241011>;
+ cts-event-workaround;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins &bt_pins>;
+ uart-has-rtscts;
+ skip-init;
+ };
+
+ spi@7e204000 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7e204000 0x200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dmas = <&dma 6>, <&dma 7>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x00>;
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+ };
+
+ i2c@7e205000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e205000 0x200>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_gpio0>;
+ clock-frequency = <100000>;
+
+ rtc@68 {
+ compatible = "st,m41t00", "dallas,ds1338";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@7e804000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e804000 0x1000>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_gpio2>;
+ clock-frequency = <100000>;
+ };
+
+ i2c@7e805000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e805000 0x1000>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ };
+
+ aux: aux@7e215000 {
+ compatible = "brcm,bcm2835-aux";
+ #clock-cells = <1>;
+ reg = <0x7e215000 0x8>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ };
+
+ serial@7e215040 {
+ compatible = "brcm,bcm2835-aux-uart";
+ reg = <0x7e215040 0x40>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&aux BCM2835_AUX_CLOCK_UART>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ skip-init;
+ };
+
+ usb: usb@7e980000 {
+ compatible = "brcm,bcm2708-usb";
+ reg = <0x7e980000 0x10000>,
+ <0x7e00b200 0x200>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "usb", "soft";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk_usb>;
+ clock-names = "otg";
+ phys = <&usbphy>;
+ phy-names = "usb2-phy";
+ power-domains = <&power RPI_POWER_DOMAIN_USB>;
+ };
+
+ /*
+ * This node is the provider for the enable-method for
+ * bringing up secondary cores.
+ */
+ local_intc: local_intc@40000000 {
+ compatible = "brcm,bcm2836-l1-intc";
+ reg = <0x40000000 0x100>;
+ };
+
+ gicv2: interrupt-controller@40041000 {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "arm,gic-400";
+ reg = <0x40041000 0x1000>,
+ <0x40042000 0x2000>,
+ <0x40044000 0x2000>,
+ <0x40046000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ avs_monitor: avs-monitor@7d5d2000 {
+ compatible = "brcm,bcm2711-avs-monitor", "syscon", "simple-mfd";
+ reg = <0x7d5d2000 0xf00>;
+
+ thermal: thermal {
+ compatible = "brcm,bcm2711-thermal";
+ #thermal-sensor-cells = <0>;
+ };
+ };
+
+ dma: dma@7e007000 {
+ compatible = "brcm,bcm2835-dma";
+ reg = <0x7e007000 0xb00>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+ /* DMA lite 7 - 10 */
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dma0",
+ "dma1",
+ "dma2",
+ "dma3",
+ "dma4",
+ "dma5",
+ "dma6",
+ "dma7",
+ "dma8",
+ "dma9",
+ "dma10";
+ #dma-cells = <1>;
+ brcm,dma-channel-mask = <0x07f5>;
+ };
+
+ pm: watchdog@7e100000 {
+ compatible = "brcm,bcm2711-pm", "brcm,bcm2835-pm-wdt";
+ #power-domain-cells = <1>;
+ #reset-cells = <1>;
+ reg = <0x7e100000 0x114>,
+ <0x7e00a000 0x24>,
+ <0x7ec11000 0x20>;
+ reg-names = "pm", "asb", "rpivid_asb";
+ clocks = <&clocks BCM2835_CLOCK_V3D>,
+ <&clocks BCM2835_CLOCK_PERI_IMAGE>,
+ <&clocks BCM2835_CLOCK_H264>,
+ <&clocks BCM2835_CLOCK_ISP>;
+ clock-names = "v3d", "peri_image", "h264", "isp";
+ system-power-controller;
+ };
+
+ random: rng@7e104000 {
+ compatible = "brcm,bcm2711-rng200";
+ reg = <0x7e104000 0x28>;
+ };
+
+ dvp: clock@7ef00000 {
+ compatible = "brcm,brcm2711-dvp";
+ reg = <0x7ef00000 0x10>;
+ clocks = <&clk_108MHz>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ aon_intr: interrupt-controller@7ef00100 {
+ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
+ reg = <0x7ef00100 0x30>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ status = "disabled";
+ };
+
+ mmcnr@7e300000 {
+ compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
+ reg = <0x7e300000 0x100>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clocks BCM2835_CLOCK_EMMC>;
+ dmas = <&dma 11>;
+ dma-names = "rx-tx";
+ brcm,overclock-50 = <0>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+ bus-width = <4>;
+ };
+
+ firmware: firmware {
+ compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ mboxes = <&mailbox>;
+ dma-ranges;
+
+ firmware_clocks: clocks {
+ compatible = "raspberrypi,firmware-clocks";
+ #clock-cells = <1>;
+ };
+
+ expgpio: gpio {
+ compatible = "raspberrypi,firmware-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ reset: reset {
+ compatible = "raspberrypi,firmware-reset";
+ #reset-cells = <1>;
+ };
+ };
+
+ power: power {
+ compatible = "raspberrypi,bcm2835-power";
+ firmware = <&firmware>;
+ #power-domain-cells = <1>;
+ };
+
+ fb: fb {
+ compatible = "brcm,bcm2708-fb";
+ firmware = <&firmware>;
+ };
+ };
+
+ clocks {
+
+ clk_osc: clk-osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "osc";
+ clock-frequency = <54000000>;
+ };
+
+ clk_usb: clk-usb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "otg";
+ clock-frequency = <480000000>;
+ };
+ };
+
+ usbphy: phy {
+ compatible = "usb-nop-xceiv";
+ #phy-cells = <0>;
+ };
+
+ clk_27MHz: clk-27M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <27000000>;
+ clock-output-names = "27MHz-clock";
+ };
+
+ clk_108MHz: clk-108M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <108000000>;
+ clock-output-names = "108MHz-clock";
+ };
+
+ scb {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ ranges = <0x0 0x7c000000 0x0 0xfc000000 0x03800000>,
+ <0x6 0x00000000 0x6 0x00000000 0x40000000>;
+
+ pcie0: pcie@7d500000 {
+ compatible = "brcm,bcm2711-pcie";
+ reg = <0x0 0x7d500000 0x9310>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "pcie", "msi";
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gicv2 GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gicv2 GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gicv2 GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ msi-controller;
+ msi-parent = <&pcie0>;
+
+ ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
+ /*
+ * The wrapper around the PCIe block has a bug
+ * preventing it from accessing beyond the first 3GB of
+ * memory.
+ */
+ dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 0x0 0xc0000000>;
+ brcm,enable-ssc;
+
+ pci@0,0 {
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ reg = <0 0 0 0 0>;
+
+ usb@0,0 {
+ reg = <0 0 0 0 0>;
+ resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>;
+ };
+ };
+ };
+
+ genet: ethernet@7d580000 {
+ compatible = "brcm,bcm2711-genet-v5";
+ reg = <0x0 0x7d580000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+ phy-handle = <&mdio_phy>;
+ phy-mode = "rgmii-rxid";
+
+ genet_mdio: mdio@e14 {
+ compatible = "brcm,genet-mdio-v5";
+ reg = <0xe14 0x8>;
+ reg-names = "mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio_phy: ethernet-phy@1 {
+ reg = <0x01>;
+ led-modes = <0x00 0x08>; /* link/activity link */
+ };
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-act {
+ label = "ACT";
+ default-state = "off";
+ rt-thread,default-trigger = "mmc0";
+ gpios = <&gpio 42 PIN_ACTIVE_HIGH>;
+ };
+
+ led-pwr {
+ label = "PWR";
+ default-state = "off";
+ gpios = <&expgpio 2 PIN_ACTIVE_LOW>;
+ rt-thread,default-trigger = "default-on";
+ };
+ };
+};
diff --git a/bsp/raspberry-pi/dm/dts/bcm283x-rpi-3-b.dts b/bsp/raspberry-pi/dm/dts/bcm283x-rpi-3-b.dts
new file mode 100755
index 0000000000..ff3d3f8f6b
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dts/bcm283x-rpi-3-b.dts
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+/dts-v1/;
+#include <dt-bindings/pinctrl/bcm2835.h>
+#include <dt-bindings/clock/bcm2835.h>
+#include <dt-bindings/clock/bcm2835-aux.h>
+#include <dt-bindings/pin/pin.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/bcm2835-pm.h>
+#include <dt-bindings/power/raspberrypi-power.h>
+
+/*
+ * NOTE: Just for QEMU, not the really board!
+ */
+
+/*
+ * firmware-provided startup stubs live here, where the secondary CPUs are
+ * spinning.
+ */
+/memreserve/ 0x00000000 0x00001000;
+
+/ {
+ compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
+ model = "Raspberry Pi 3 Model B";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ aliases {
+ serial0 = "/soc/serial@7e215040";
+ serial1 = "/soc/serial@7e201000";
+ mmc0 = "/soc/mmcnr@7e300000";
+ spi0 = "/soc/spi@7e204000";
+ i2c0 = "/soc/i2c@7e205000";
+ i2c1 = "/soc/i2c@7e804000";
+ i2c2 = "/soc/i2c@7e805000";
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* For ARM 32-bit */
+ enable-method = "brcm,bcm2836-smp";
+
+ /*
+ * Source for d/i-cache-line-size and d/i-cache-sets
+ * https://developer.arm.com/documentation/ddi0500/e/level-1-memory-system
+ * /about-the-l1-memory-system?lang=en
+ *
+ * Source for d/i-cache-size
+ * https://magpi.raspberrypi.com/articles/raspberry-pi-3-specs-benchmarks
+ */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000d8>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e0>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <2>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000e8>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ next-level-cache = <&l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <3>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x000000f0>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+ next-level-cache = <&l2>;
+ };
+
+ /*
+ * Source for cache-line-size + cache-sets
+ * https://developer.arm.com/documentation/ddi0500
+ * /e/level-2-memory-system/about-the-l2-memory-system?lang=en
+ * Source for cache-size
+ * https://datasheets.raspberrypi.com/cm/cm1-and-cm3-datasheet.pdf
+ */
+ l2: l2-cache0 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>; // 512KiB(size)/64(line-size)=8192ways/16-way set
+ cache-level = <2>;
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a53-pmu", "arm,cortex-a7-pmu";
+ interrupt-parent = <&local_intc>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&local_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI
+ <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI
+ <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI
+ <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI
+ always-on;
+ };
+
+ thermal-zones {
+
+ cpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+ thermal-sensors = <&thermal>;
+ coefficients = <(-538) 412000>;
+
+ trips {
+ cpu-crit {
+ temperature = <90000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x7e000000 0x3f000000 0x1000000>,
+ <0x40000000 0x40000000 0x00001000>;
+ dma-ranges = <0xc0000000 0x00000000 0x3f000000>,
+ <0x7e000000 0x3f000000 0x01000000>;
+
+ system_timer: timer@7e003000 {
+ compatible = "brcm,bcm2835-system-timer";
+ reg = <0x7e003000 0x1000>;
+ interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
+ /*
+ * This could be a reference to BCM2835_CLOCK_TIMER,
+ * but we don't have the driver using the common clock
+ * support yet.
+ */
+ clock-frequency = <1000000>;
+ };
+
+ clocks: cprman@7e101000 {
+ compatible = "brcm,bcm2835-cprman";
+ #clock-cells = <1>;
+ reg = <0x7e101000 0x2000>;
+
+ /*
+ * CPRMAN derives almost everything from the
+ * platform's oscillator. However, the DSI
+ * pixel clocks come from the DSI analog PHY.
+ */
+ clocks = <&clk_osc>;
+ };
+
+ mailbox: mailbox@7e00b880 {
+ compatible = "brcm,bcm2835-mbox";
+ reg = <0x7e00b880 0x40>;
+ interrupts = <0 1>;
+ #mbox-cells = <0>;
+ };
+
+ gpio: gpio@7e200000 {
+ compatible = "brcm,bcm2835-gpio";
+ reg = <0x7e200000 0xb4>;
+ interrupts = <2 17>, <2 18>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gpio-ranges = <&gpio 0 0 54>;
+ pinctrl-names = "default";
+ gpio-line-names = "ID_SDA",
+ "ID_SCL",
+ "SDA1",
+ "SCL1",
+ "GPIO_GCLK",
+ "GPIO5",
+ "GPIO6",
+ "SPI_CE1_N",
+ "SPI_CE0_N",
+ "SPI_MISO",
+ "SPI_MOSI",
+ "SPI_SCLK",
+ "GPIO12",
+ "GPIO13",
+ /* Serial port */
+ "TXD1",
+ "RXD1",
+ "GPIO16",
+ "GPIO17",
+ "GPIO18",
+ "GPIO19",
+ "GPIO20",
+ "GPIO21",
+ "GPIO22",
+ "GPIO23",
+ "GPIO24",
+ "GPIO25",
+ "GPIO26",
+ "GPIO27",
+ "NC", /* GPIO 28 */
+ "LAN_RUN_BOOT",
+ /* Used by BT module */
+ "CTS0",
+ "RTS0",
+ "TXD0",
+ "RXD0",
+ /* Used by Wifi */
+ "SD1_CLK",
+ "SD1_CMD",
+ "SD1_DATA0",
+ "SD1_DATA1",
+ "SD1_DATA2",
+ "SD1_DATA3",
+ "PWM0_OUT",
+ "PWM1_OUT",
+ "ETH_CLK",
+ "WIFI_CLK",
+ "SDA0",
+ "SCL0",
+ "SMPS_SCL",
+ "SMPS_SDA",
+ /* Used by SD Card */
+ "SD_CLK_R",
+ "SD_CMD_R",
+ "SD_DATA0_R",
+ "SD_DATA1_R",
+ "SD_DATA2_R",
+ "SD_DATA3_R";
+
+ spi0_pins: spi0_pins {
+ brcm,pins = <9 10 11>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ spi0_cs_pins: spi0_cs_pins {
+ brcm,pins = <8 7>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ i2c0_gpio0: i2c0_gpio0 {
+ brcm,pins = <0 1>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ i2c1_gpio2: i2c1_gpio2 {
+ brcm,pins = <2 3>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ sdio_pins: sdio_pins {
+ brcm,pins = <34 35 36 37 38 39>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ brcm,pull = <BCM2835_PUD_OFF>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>,
+ <BCM2835_PUD_UP>;
+ };
+
+ bt_pins: bt_pins {
+ brcm,pins = <43>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ brcm,pull = <BCM2835_PUD_OFF>;
+ };
+
+ uart0_pins: uart0_pins {
+ brcm,pins = <32 33>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
+ };
+
+ uart1_pins: uart1_pins {
+ brcm,pins;
+ brcm,function;
+ brcm,pull;
+ };
+ };
+
+ serial@7e201000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x7e201000 0x200>;
+ interrupts = <2 25>;
+ clocks = <&clocks BCM2835_CLOCK_UART>,
+ <&clocks BCM2835_CLOCK_VPU>;
+ clock-names = "uartclk", "apb_pclk";
+ arm,primecell-periphid = <0x00241011>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>, <&bt_pins>;
+ skip-init;
+ };
+
+ spi@7e204000 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7e204000 0x200>;
+ interrupts = <2 22>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dmas = <&dma 6>, <&dma 7>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>, <&spi0_cs_pins>;
+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x00>;
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+ };
+
+ i2c@7e205000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e205000 0x200>;
+ interrupts = <2 21>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_gpio0>;
+ clock-frequency = <100000>;
+
+ rtc@68 {
+ compatible = "st,m41t00", "dallas,ds1338";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@7e804000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e804000 0x1000>;
+ interrupts = <2 21>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_gpio2>;
+ clock-frequency = <100000>;
+ };
+
+ i2c@7e805000 {
+ compatible = "brcm,bcm2835-i2c";
+ reg = <0x7e805000 0x1000>;
+ interrupts = <2 21>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ };
+
+ aux: aux@7e215000 {
+ compatible = "brcm,bcm2835-aux";
+ #clock-cells = <1>;
+ reg = <0x7e215000 0x8>;
+ clocks = <&clocks BCM2835_CLOCK_VPU>;
+ };
+
+ serial@7e215040 {
+ compatible = "brcm,bcm2835-aux-uart";
+ reg = <0x7e215040 0x40>;
+ interrupts = <1 29>;
+ clocks = <&aux BCM2835_AUX_CLOCK_UART>;
+ skip-init;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ };
+
+ usb: usb@7e980000 {
+ compatible = "brcm,bcm2835-usb";
+ reg = <0x7e980000 0x10000>,
+ <0x7e006000 0x1000>;
+ interrupts = <1 9>, <2 0>;
+ interrupt-names = "usb", "soft";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clk_usb>;
+ clock-names = "otg";
+ phys = <&usbphy>;
+ phy-names = "usb2-phy";
+ power-domains = <&power RPI_POWER_DOMAIN_USB>;
+ };
+
+ dma: dma@7e007000 {
+ compatible = "brcm,bcm2835-dma";
+ reg = <0x7e007000 0xf00>;
+ interrupts = <1 16>,
+ <1 17>,
+ <1 18>,
+ <1 19>,
+ <1 20>,
+ <1 21>,
+ <1 22>,
+ <1 23>,
+ <1 24>,
+ <1 25>,
+ <1 26>,
+ /* dma channel 11-14 share one irq */
+ <1 27>,
+ <1 27>,
+ <1 27>,
+ <1 27>,
+ /* unused shared irq for all channels */
+ <1 28>;
+ interrupt-names = "dma0",
+ "dma1",
+ "dma2",
+ "dma3",
+ "dma4",
+ "dma5",
+ "dma6",
+ "dma7",
+ "dma8",
+ "dma9",
+ "dma10",
+ "dma11",
+ "dma12",
+ "dma13",
+ "dma14",
+ "dma-shared-all";
+ #dma-cells = <1>;
+ brcm,dma-channel-mask = <0x7f35>;
+ };
+
+ intc: interrupt-controller@7e00b200 {
+ compatible = "brcm,bcm2836-armctrl-ic";
+ reg = <0x7e00b200 0x200>;
+ interrupt-parent = <&local_intc>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pm: watchdog@7e100000 {
+ compatible = "brcm,bcm2835-pm", "brcm,bcm2835-pm-wdt";
+ #power-domain-cells = <1>;
+ #reset-cells = <1>;
+ reg = <0x7e100000 0x114>,
+ <0x7e00a000 0x24>;
+ reg-names = "pm", "asb";
+ clocks = <&clocks BCM2835_CLOCK_V3D>,
+ <&clocks BCM2835_CLOCK_PERI_IMAGE>,
+ <&clocks BCM2835_CLOCK_H264>,
+ <&clocks BCM2835_CLOCK_ISP>;
+ clock-names = "v3d", "peri_image", "h264", "isp";
+ system-power-controller;
+ };
+
+ random: rng@7e104000 {
+ compatible = "brcm,bcm2835-rng";
+ reg = <0x7e104000 0x10>;
+ interrupts = <2 29>;
+ };
+
+ thermal: thermal@7e212000 {
+ compatible = "brcm,bcm2837-thermal";
+ reg = <0x7e212000 0x8>;
+ clocks = <&clocks BCM2835_CLOCK_TSENS>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ local_intc: local_intc@40000000 {
+ compatible = "brcm,bcm2836-l1-intc";
+ reg = <0x40000000 0x100>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&local_intc>;
+ };
+
+ mmcnr@7e300000 {
+ compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci";
+ reg = <0x7e300000 0x100>;
+ interrupts = <2 30>;
+ clocks = <&clocks BCM2835_CLOCK_EMMC>;
+ dmas = <&dma 11>;
+ dma-names = "rx-tx";
+ brcm,overclock-50 = <0>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+ bus-width = <4>;
+ };
+
+ firmware: firmware {
+ compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ mboxes = <&mailbox>;
+ ranges;
+
+ clocks {
+ compatible = "raspberrypi,firmware-clocks";
+ #clock-cells = <1>;
+ };
+
+ expgpio: expgpio {
+ compatible = "raspberrypi,firmware-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "BT_ON",
+ "WL_ON",
+ "STATUS_LED",
+ "LAN_RUN",
+ "HDMI_HPD_N",
+ "CAM_GPIO0",
+ "CAM_GPIO1",
+ "PWR_LOW_N";
+ };
+ };
+
+ power: power {
+ compatible = "raspberrypi,bcm2835-power";
+ firmware = <&firmware>;
+ #power-domain-cells = <1>;
+ };
+
+ fb: fb {
+ compatible = "brcm,bcm2708-fb";
+ firmware = <&firmware>;
+ };
+
+ virtgpio: virtgpio {
+ compatible = "brcm,bcm2835-virtgpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ firmware = <&firmware>;
+ };
+
+ nvmem {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nvmem_otp: nvmem_otp {
+ compatible = "raspberrypi,rpi-otp";
+ firmware = <&firmware>;
+ reg = <0 166>;
+ };
+
+ nvmem_cust: nvmem_cust {
+ compatible = "raspberrypi,rpi-otp";
+ firmware = <&firmware>;
+ reg = <1 8>;
+ };
+
+ nvmem_priv: nvmem_priv {
+ compatible = "raspberrypi,rpi-otp";
+ firmware = <&firmware>;
+ reg = <3 8>;
+ };
+ };
+ };
+
+ clocks {
+
+ /* The oscillator is the root of the clock tree. */
+ clk_osc: clk-osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "osc";
+ clock-frequency = <19200000>;
+ };
+
+ clk_usb: clk-usb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "otg";
+ clock-frequency = <480000000>;
+ };
+ };
+
+ usbphy: phy {
+ compatible = "usb-nop-xceiv";
+ #phy-cells = <0>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-act {
+ label = "ACT";
+ default-state = "off";
+ rt-thread,default-trigger = "mmc0";
+ gpios = <&virtgpio 0 0>;
+ };
+
+ led-pwr {
+ label = "PWR";
+ default-state = "off";
+ rt-thread,default-trigger = "input";
+ gpios = <&expgpio 7 0>;
+ };
+ };
+};
diff --git a/bsp/raspberry-pi/dm/dvfs/Kconfig b/bsp/raspberry-pi/dm/dvfs/Kconfig
new file mode 100755
index 0000000000..2ad5f6ca25
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dvfs/Kconfig
@@ -0,0 +1,4 @@
+config RT_DVFS_RASPBERRY_CPUFREQ
+ bool "Raspberry firmware CPUfreq driver"
+ depends on RT_USING_DVFS
+ default n
diff --git a/bsp/raspberry-pi/dm/dvfs/SConscript b/bsp/raspberry-pi/dm/dvfs/SConscript
new file mode 100755
index 0000000000..fa9ea116d4
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dvfs/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_DVFS_RASPBERRY_CPUFREQ']):
+ src += ['dvfs-raspberrypi-cpufreq.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DVFS'], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/dvfs/dvfs-raspberrypi-cpufreq.c b/bsp/raspberry-pi/dm/dvfs/dvfs-raspberrypi-cpufreq.c
new file mode 100755
index 0000000000..a915842656
--- /dev/null
+++ b/bsp/raspberry-pi/dm/dvfs/dvfs-raspberrypi-cpufreq.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "dvfs.raspberrypi-cpufreq"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <drivers/misc.h>
+#include <drivers/byteorder.h>
+#include <dvfs-raspberrypi-cpufreq.h>
+
+#define RASPBERRYPI_FREQ_INTERVAL 100000000
+
+static rt_err_t raspberrypi_firmware_clk_rate(struct rpi_firmware *rpi_fw,
+ rt_uint32_t tag, rt_uint32_t id, rt_uint32_t *rate)
+{
+ struct rpi_firmware_clk_rate_request msg =
+ {
+ .id = rt_cpu_to_le32(id),
+ };
+
+ if (!rpi_fw || !rate)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (rpi_firmware_property(rpi_fw, tag, &msg, sizeof(msg)))
+ {
+ return -RT_EIO;
+ }
+
+ *rate = rt_le32_to_cpu(msg.rate);
+
+ return RT_EOK;
+}
+
+static rt_err_t raspberrypi_arm_clk_get_range(struct rt_clk *arm_clk,
+ struct rpi_firmware *rpi_fw, rt_ubase_t *min, rt_ubase_t *max)
+{
+ rt_uint32_t min_hz = 0, max_hz = 0;
+
+ if (!arm_clk || !min || !max)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (arm_clk->min_rate && arm_clk->max_rate)
+ {
+ *min = arm_clk->min_rate;
+ *max = arm_clk->max_rate;
+ return RT_EOK;
+ }
+
+ if (!rpi_fw)
+ {
+ LOG_E("ARM clk range missing and no firmware handle");
+ return -RT_EINVAL;
+ }
+
+ if (raspberrypi_firmware_clk_rate(rpi_fw, RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
+ RPI_FIRMWARE_ARM_CLK_ID, &min_hz))
+ {
+ LOG_E("firmware %s for ARM failed", "GET_MIN_CLOCK_RATE");
+ return -RT_EIO;
+ }
+
+ if (raspberrypi_firmware_clk_rate(rpi_fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ RPI_FIRMWARE_ARM_CLK_ID, &max_hz))
+ {
+ LOG_E("firmware %s for ARM failed", "GET_MAX_CLOCK_RATE");
+ return -RT_EIO;
+ }
+
+ if (!min_hz || !max_hz || min_hz > max_hz)
+ {
+ LOG_E("firmware ARM range invalid: %u-%u Hz", min_hz, max_hz);
+ return -RT_EINVAL;
+ }
+
+ rt_clk_set_rate_range(arm_clk, min_hz, max_hz);
+ *min = min_hz;
+ *max = max_hz;
+
+ return RT_EOK;
+}
+
+static void raspberrypi_cpufreq_cleanup(struct rt_dvfs_scaling *scaling,
+ struct rt_dvfs_cpufreq *cpufreq)
+{
+ if (scaling && scaling->opp_table)
+ {
+ rt_dvfs_scaling_remove_opp_all(scaling);
+ }
+
+ rt_free(cpufreq);
+}
+
+/*
+ * Board-specific helper: build the OPP table and hand the cpufreq object
+ * to the generic "ofw-cpufreq" platform driver (see dvfs-ofw.c).
+ */
+rt_err_t raspberrypi_cpufreq_register(struct rt_clk *arm_clk, struct rt_ofw_node *cpu_np,
+ struct rpi_firmware *rpi_fw)
+{
+ rt_err_t err;
+ rt_ubase_t min, max, rate;
+ rt_uint32_t opp_count = 0;
+ struct rt_dvfs_cpufreq *cpufreq;
+ struct rt_dvfs_scaling *scaling;
+ struct rt_platform_device *pdev;
+
+ if (!arm_clk || rt_is_err_or_null(arm_clk) || !cpu_np)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (!(cpufreq = rt_calloc(1, sizeof(*cpufreq))))
+ {
+ return -RT_ENOMEM;
+ }
+
+ scaling = rt_dvfs_cpufreq_to_scaling(cpufreq);
+ scaling->clk = arm_clk;
+ /*
+ * VideoCore owns voltage/thermal mitigation; no extra settling time is
+ * needed after firmware clock changes.
+ */
+ scaling->transition_latency = 0;
+ scaling->retry_delay = 100000;
+ rt_memset(cpufreq->cpus_map, 0xff, sizeof(cpufreq->cpus_map));
+
+ if ((err = raspberrypi_arm_clk_get_range(arm_clk, rpi_fw, &min, &max)))
+ {
+ LOG_E("ARM clock range unavailable: %s", rt_strerror(err));
+ raspberrypi_cpufreq_cleanup(scaling, cpufreq);
+ return err;
+ }
+
+ min = rt_roundup(min, RASPBERRYPI_FREQ_INTERVAL);
+ max = rt_roundup(max, RASPBERRYPI_FREQ_INTERVAL);
+
+ if (!min || !max || min > max)
+ {
+ LOG_E("invalid ARM clock range: %lu-%lu Hz", min, max);
+ raspberrypi_cpufreq_cleanup(scaling, cpufreq);
+ return -RT_EINVAL;
+ }
+
+ for (rate = min; rate <= max; rate += RASPBERRYPI_FREQ_INTERVAL)
+ {
+ if (!rt_dvfs_scaling_add_opp(scaling, rate, 0))
+ {
+ LOG_E("failed to add OPP %lu Hz (added %u so far)", rate, opp_count);
+ raspberrypi_cpufreq_cleanup(scaling, cpufreq);
+ return -RT_ERROR;
+ }
+
+ ++opp_count;
+ }
+
+ /*
+ * Keep the current boot frequency. ofw_dvfs_setup() eventually calls
+ * rt_dvfs_scaling_register(), which skips dvfs_scaling_init_frequency()
+ * when cur_freq is already set.
+ */
+ rate = rt_clk_get_rate(arm_clk);
+
+ if (rate)
+ {
+ struct rt_dvfs_opp *opp = rt_dvfs_scaling_find_floor_opp(scaling, rate);
+
+ if (!opp)
+ {
+ opp = rt_dvfs_scaling_find_ceil_opp(scaling, rate);
+ }
+
+ if (opp)
+ {
+ scaling->cur_freq = opp->freq;
+ }
+ else
+ {
+ LOG_W("no matching OPP for current rate %lu Hz", rate);
+ }
+ }
+
+ if (!(pdev = rt_platform_device_alloc("ofw-cpufreq")))
+ {
+ LOG_E("alloc ofw-cpufreq failed");
+ err = -RT_ENOMEM;
+ goto _free_cpufreq;
+ }
+
+ pdev->priv = cpufreq;
+
+ rt_dm_dev_set_name_auto(&pdev->parent, "cpufreq");
+
+ if ((err = rt_device_register(&pdev->parent, rt_dm_dev_get_name(&pdev->parent),
+ RT_DEVICE_FLAG_DEACTIVATE)))
+ {
+ goto _free;
+ }
+
+ if ((err = rt_platform_device_register(pdev)))
+ {
+ goto _unregister;
+ }
+
+ if (!pdev->parent.drv)
+ {
+ err = -RT_ERROR;
+ goto _free_bus;
+ }
+
+ return RT_EOK;
+_free_bus:
+ rt_bus_remove_device(&pdev->parent);
+_unregister:
+ rt_device_unregister(&pdev->parent);
+_free:
+ rt_free(pdev);
+_free_cpufreq:
+ raspberrypi_cpufreq_cleanup(scaling, cpufreq);
+ return err;
+}
+
+static int raspberrypi_dvfs_cpufreq_init(void)
+{
+ rt_err_t err;
+ struct rt_clk *arm_clk;
+ struct rt_ofw_node *cpu_np, *fw_np;
+ struct rpi_firmware *rpi_fw = RT_NULL;
+
+ if (!(arm_clk = raspberrypi_arm_clk_get()))
+ {
+ LOG_E("ARM clock not ready, skip cpufreq");
+ return 0;
+ }
+
+ if (!(cpu_np = rt_ofw_get_next_cpu_node(RT_NULL)))
+ {
+ LOG_E("no CPU node, skip cpufreq");
+ return 0;
+ }
+
+ if ((fw_np = rpi_firmware_find_node()))
+ {
+ rpi_fw = rpi_firmware_get(fw_np);
+ }
+
+ err = raspberrypi_cpufreq_register(arm_clk, cpu_np, rpi_fw);
+
+ if (rpi_fw)
+ {
+ rpi_firmware_put(rpi_fw);
+ }
+ rt_ofw_node_put(cpu_np);
+
+ if (err)
+ {
+ LOG_W("cpufreq init failed: %s", rt_strerror(err));
+ }
+
+ return 0;
+}
+INIT_ENV_EXPORT(raspberrypi_dvfs_cpufreq_init);
diff --git a/bsp/raspberry-pi/dm/ethernet/Kconfig b/bsp/raspberry-pi/dm/ethernet/Kconfig
new file mode 100755
index 0000000000..c481be0cef
--- /dev/null
+++ b/bsp/raspberry-pi/dm/ethernet/Kconfig
@@ -0,0 +1,3 @@
+config RT_ETHERNET_BCMGENET
+ bool "BCMGENET V5 Ethernet MAC"
+ default n
diff --git a/bsp/raspberry-pi/dm/ethernet/SConscript b/bsp/raspberry-pi/dm/ethernet/SConscript
new file mode 100755
index 0000000000..47abea403d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/ethernet/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_ETHERNET_BCMGENET']):
+ src += ['eth-bcmgenet.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/ethernet/eth-bcmgenet.c b/bsp/raspberry-pi/dm/ethernet/eth-bcmgenet.c
new file mode 100755
index 0000000000..a15796f7bd
--- /dev/null
+++ b/bsp/raspberry-pi/dm/ethernet/eth-bcmgenet.c
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "eth.bcmgenet"
+#define DBG_LVL DBG_WARNING
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <drivers/dma.h>
+#include <drivers/phy.h>
+#include <netif/ethernetif.h>
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+#include <ipc/workqueue.h>
+#endif
+#include <firmware-raspberrypi.h>
+
+#define SYS_REV_CTRL 0x00
+
+#define SYS_PORT_CTRL 0x04
+#define PORT_MODE_EXT_GPHY 3
+
+#define GENET_SYS_OFF 0x0000
+#define SYS_RBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x08)
+#define SYS_TBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x0c)
+
+#define GENET_EXT_OFF 0x0080
+#define EXT_RGMII_OOB_CTRL (GENET_EXT_OFF + 0x0c)
+#define RGMII_LINK RT_BIT(4)
+#define OOB_DISABLE RT_BIT(5)
+#define RGMII_MODE_EN RT_BIT(6)
+#define ID_MODE_DIS RT_BIT(16)
+
+#define GENET_RBUF_OFF 0x0300
+#define RBUF_CTRL (GENET_RBUF_OFF + 0x00)
+#define RBUF_64B_EN RT_BIT(0)
+#define RBUF_ALIGN_2B RT_BIT(1)
+#define RBUF_CHK_CTRL (GENET_RBUF_OFF + 0x14)
+#define RBUF_RXCHK_EN RT_BIT(0)
+#define RBUF_L3_PARSE_DIS RT_BIT(1)
+#define RBUF_TBUF_SIZE_CTRL (GENET_RBUF_OFF + 0xb4)
+
+#define GENET_TBUF_OFF 0x0600
+#define TBUF_CTRL (GENET_TBUF_OFF + 0x00)
+#define TBUF_64B_EN RT_BIT(0)
+
+#define GENET_UMAC_OFF 0x0800
+#define UMAC_MIB_CTRL (GENET_UMAC_OFF + 0x580)
+#define UMAC_MAX_FRAME_LEN (GENET_UMAC_OFF + 0x014)
+#define UMAC_MAC0 (GENET_UMAC_OFF + 0x00c)
+#define UMAC_MAC1 (GENET_UMAC_OFF + 0x010)
+#define UMAC_CMD (GENET_UMAC_OFF + 0x008)
+#define MDIO_CMD (GENET_UMAC_OFF + 0x614)
+#define UMAC_TX_FLUSH (GENET_UMAC_OFF + 0x334)
+#define MDIO_START_BUSY RT_BIT(29)
+#define MDIO_READ_FAIL RT_BIT(28)
+#define MDIO_RD (2 << 26)
+#define MDIO_WR RT_BIT(26)
+#define MDIO_PMD_SHIFT 21
+#define MDIO_PMD_MASK 0x1f
+#define MDIO_REG_SHIFT 16
+#define MDIO_REG_MASK 0x1f
+
+#define CMD_TX_EN RT_BIT(0)
+#define CMD_RX_EN RT_BIT(1)
+#define UMAC_SPEED_10 0
+#define UMAC_SPEED_100 1
+#define UMAC_SPEED_1000 2
+#define UMAC_SPEED_2500 3
+#define CMD_SPEED_SHIFT 2
+#define CMD_SPEED_MASK 3
+#define CMD_HD_EN RT_BIT(10)
+#define CMD_RX_PAUSE_IGNORE RT_BIT(8)
+#define CMD_TX_PAUSE_IGNORE RT_BIT(28)
+#define CMD_SW_RESET RT_BIT(13)
+#define CMD_LCL_LOOP_EN RT_BIT(15)
+#define CMD_PROMISC RT_BIT(4)
+
+#define UMAC_MDF_CTRL (GENET_UMAC_OFF + 0x650)
+#define UMAC_MDF_ADDR (GENET_UMAC_OFF + 0x654)
+#define MAX_MDF_FILTER 17
+
+#define MIB_RESET_RX RT_BIT(0)
+#define MIB_RESET_RUNT RT_BIT(1)
+#define MIB_RESET_TX RT_BIT(2)
+
+/* Total number of Buffer Descriptors, same for Rx/Tx */
+#define TOTAL_DESCS 256
+#define RX_DESCS TOTAL_DESCS
+#define DESC_INDEX 16
+#define DEFAULT_RING 16
+#define TX_DESCS TOTAL_DESCS
+
+/* Per-ring register block size and total ring control area (rings 0..16). */
+#define DMA_RING_SIZE 0x40
+#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DESC_INDEX + 1))
+
+/*
+ * Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
+ * 1536 is multiple of 256 bytes
+ */
+#define ENET_BRCM_TAG_LEN 6
+#define ENET_PAD 8
+#define ENET_DATA_LEN 1500 /* Max. octets in payload */
+#define ENET_HLEN 14 /* Total octets in header */
+#define ENET_FCS_LEN 4 /* Octets in the FCS */
+#define ENET_VLAN_HLEN 4
+#define ENET_MAX_MTU_SIZE (ENET_DATA_LEN + ENET_HLEN + ENET_VLAN_HLEN + ENET_BRCM_TAG_LEN + ENET_FCS_LEN + ENET_PAD)
+
+/* Tx/Rx Dma Descriptor common bits */
+#define DMA_EN RT_BIT(0)
+#define DMA_RING_BUF_EN_SHIFT 0x01
+#define DMA_RING_BUF_EN_MASK 0xffff
+#define DMA_BUFLENGTH_MASK 0x0fff
+#define DMA_BUFLENGTH_SHIFT 16
+#define DMA_RING_SIZE_SHIFT 16
+#define DMA_OWN 0x8000
+#define DMA_EOP 0x4000
+#define DMA_SOP 0x2000
+#define DMA_WRAP 0x1000
+#define DMA_MAX_BURST_LENGTH 0x8
+/* Tx specific DMA descriptor bits */
+#define DMA_TX_UNDERRUN 0x0200
+#define DMA_TX_APPEND_CRC 0x0040
+#define DMA_TX_OW_CRC 0x0020
+#define DMA_TX_DO_CSUM 0x0010
+#define DMA_TX_QTAG_SHIFT 7
+
+/* DMA descriptor */
+#define DMA_DESC_LENGTH_STATUS 0x00
+#define DMA_DESC_ADDRESS_LO 0x04
+#define DMA_DESC_ADDRESS_HI 0x08
+#define DMA_DESC_SIZE 12
+
+#define GENET_RX_OFF 0x2000
+#define GENET_RDMA_REG_OFF (GENET_RX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
+#define GENET_TX_OFF 0x4000
+#define GENET_TDMA_REG_OFF (GENET_TX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
+
+#define DMA_FC_THRESH_HI (RX_DESCS >> 4)
+#define DMA_FC_THRESH_LO 5
+#define DMA_FC_THRESH_VALUE ((DMA_FC_THRESH_LO << 16) | DMA_FC_THRESH_HI)
+
+#define DMA_XOFF_THRESHOLD_SHIFT 16
+
+#define TDMA_RING_REG_BASE (GENET_TDMA_REG_OFF + DEFAULT_RING * DMA_RING_SIZE)
+#define TDMA_READ_PTR (TDMA_RING_REG_BASE + 0x00)
+#define TDMA_CONS_INDEX (TDMA_RING_REG_BASE + 0x08)
+#define TDMA_PROD_INDEX (TDMA_RING_REG_BASE + 0x0c)
+#define DMA_RING_BUF_SIZE 0x10
+#define DMA_START_ADDR 0x14
+#define DMA_END_ADDR 0x1c
+#define DMA_MBUF_DONE_THRESH 0x24
+#define TDMA_FLOW_PERIOD (TDMA_RING_REG_BASE + 0x28)
+#define TDMA_WRITE_PTR (TDMA_RING_REG_BASE + 0x2c)
+
+#define RDMA_RING_REG_BASE (GENET_RDMA_REG_OFF + DEFAULT_RING * DMA_RING_SIZE)
+#define RDMA_WRITE_PTR (RDMA_RING_REG_BASE + 0x00)
+#define RDMA_PROD_INDEX (RDMA_RING_REG_BASE + 0x08)
+#define RDMA_CONS_INDEX (RDMA_RING_REG_BASE + 0x0c)
+#define RDMA_XON_XOFF_THRESH (RDMA_RING_REG_BASE + 0x28)
+#define RDMA_READ_PTR (RDMA_RING_REG_BASE + 0x2c)
+
+#define TDMA_REG_BASE (GENET_TDMA_REG_OFF + DMA_RINGS_SIZE)
+#define RDMA_REG_BASE (GENET_RDMA_REG_OFF + DMA_RINGS_SIZE)
+#define DMA_RING_CFG 0x00
+#define DMA_CTRL 0x04
+#define DMA_SCB_BURST_SIZE 0x0c
+
+#define DMA_P_INDEX_MASK 0xffff
+
+#define RX_BUF_LENGTH 2048
+#define RX_TOTAL_BUFSIZE (RX_BUF_LENGTH * RX_DESCS)
+#define TX_TOTAL_BUFSIZE RX_TOTAL_BUFSIZE
+#define GENET_RX_RSB_SIZE 66
+#define GENET_TX_TSB_SIZE 64
+#define RX_BUF_OFFSET 2
+
+#define PHY_RETRY_INTERVAL_MS 2000
+#define PHY_RETRY_MAX 15
+
+#define GENET_INTRL2_0_OFF 0x0200
+#define GENET_INTRL2_1_OFF 0x0240
+/* uniMac intrl2 registers */
+#define INTRL2_CPU_STAT 0x00
+#define INTRL2_CPU_SET 0x04
+#define INTRL2_CPU_CLEAR 0x08
+#define INTRL2_CPU_MASK_STATUS 0x0c
+#define INTRL2_CPU_MASK_SET 0x10
+#define INTRL2_CPU_MASK_CLEAR 0x14
+
+/* INTRL2 instance 0 definitions */
+#define UMAC_IRQ_SCB RT_BIT(0)
+#define UMAC_IRQ_EPHY RT_BIT(1)
+#define UMAC_IRQ_PHY_DET_R RT_BIT(2)
+#define UMAC_IRQ_PHY_DET_F RT_BIT(3)
+#define UMAC_IRQ_LINK_UP RT_BIT(4)
+#define UMAC_IRQ_LINK_DOWN RT_BIT(5)
+#define UMAC_IRQ_LINK_EVENT (UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_DOWN)
+#define UMAC_IRQ_UMAC RT_BIT(6)
+#define UMAC_IRQ_UMAC_TSV RT_BIT(7)
+#define UMAC_IRQ_TBUF_UNDERRUN RT_BIT(8)
+#define UMAC_IRQ_RBUF_OVERFLOW RT_BIT(9)
+#define UMAC_IRQ_HFB_SM RT_BIT(10)
+#define UMAC_IRQ_HFB_MM RT_BIT(11)
+#define UMAC_IRQ_MPD_R RT_BIT(12)
+#define UMAC_IRQ_WAKE_EVENT (UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM | UMAC_IRQ_MPD_R)
+#define UMAC_IRQ_RXDMA_MBDONE RT_BIT(13)
+#define UMAC_IRQ_RXDMA_PDONE RT_BIT(14)
+#define UMAC_IRQ_RXDMA_BDONE RT_BIT(15)
+#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
+#define UMAC_IRQ_TXDMA_MBDONE RT_BIT(16)
+#define UMAC_IRQ_TXDMA_PDONE RT_BIT(17)
+#define UMAC_IRQ_TXDMA_BDONE RT_BIT(18)
+#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
+
+/* Only valid for GENETv3+ */
+#define UMAC_IRQ_MDIO_DONE RT_BIT(23)
+#define UMAC_IRQ_MDIO_ERROR RT_BIT(24)
+
+/* INTRL2 instance 1 definitions */
+#define UMAC_IRQ1_RX_INTR_SHIFT 16
+#define UMAC_IRQ1_TX_INTR(ring) RT_BIT(ring)
+#define UMAC_IRQ1_RX_INTR(ring) RT_BIT(UMAC_IRQ1_RX_INTR_SHIFT + (ring))
+
+#define HWREGCLR32(reg, clr) HWREG32(reg) &= ~(clr)
+#define HWREGSET32(reg, set) HWREG32(reg) |= (set)
+#define HWREGCLRSET32(reg, clr, set) HWREG32(reg) = (HWREG32(reg) & ~(clr)) | (set)
+
+struct bcmgenet_eth
+{
+ struct eth_device parent;
+ struct rt_phy_device *phy;
+ struct rt_device *dev;
+
+ void *base;
+ void *tx_desc_base;
+ void *rx_desc_base;
+ int irq0, irq1;
+
+ rt_uint8_t mac[6];
+ rt_uint32_t speed;
+ rt_phy_interface interface;
+
+ int tx_index;
+ int rx_index;
+ int c_index;
+ rt_uint8_t *rxbuffer;
+ rt_uint8_t *txbuffer;
+ rt_ubase_t rxbuffer_dma;
+ rt_ubase_t txbuffer_dma;
+
+ struct rt_semaphore tx_done;
+
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+ struct rt_work link_work;
+ struct rt_work phy_retry_work;
+ int phy_retry_count;
+#endif
+
+ rt_size_t dma_buf_size;
+
+#ifdef RT_USING_OFW
+ struct rt_ofw_node *phy_np;
+#endif
+};
+
+#define raw_to_bcmgenet_eth(raw) \
+ rt_container_of(rt_container_of(raw, struct eth_device, parent), struct bcmgenet_eth, parent)
+
+static void bcmgenet_umac_reset(struct bcmgenet_eth *eth)
+{
+ rt_uint32_t reg;
+
+ reg = HWREG32(eth->base + SYS_RBUF_FLUSH_CTRL);
+ reg |= RT_BIT(1);
+ HWREG32(eth->base + SYS_RBUF_FLUSH_CTRL) = reg;
+ rt_hw_us_delay(10);
+
+ reg &= ~RT_BIT(1);
+ HWREG32(eth->base + SYS_RBUF_FLUSH_CTRL) = reg;
+ rt_hw_us_delay(10);
+
+ HWREG32(eth->base + SYS_RBUF_FLUSH_CTRL) = 0;
+ rt_hw_us_delay(10);
+
+ HWREG32(eth->base + UMAC_CMD) = 0;
+
+ HWREG32(eth->base + UMAC_CMD) = CMD_SW_RESET | CMD_LCL_LOOP_EN;
+ rt_hw_us_delay(2);
+ HWREG32(eth->base + UMAC_CMD) = 0;
+
+ /* Clear tx/rx counter */
+ HWREG32(eth->base + UMAC_MIB_CTRL) = MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT;
+ HWREG32(eth->base + UMAC_MIB_CTRL) = 0;
+
+ HWREG32(eth->base + UMAC_MAX_FRAME_LEN) = ENET_MAX_MTU_SIZE;
+
+ /* Enable 64-byte transmit status block */
+ reg = HWREG32(eth->base + TBUF_CTRL);
+ reg |= TBUF_64B_EN;
+ HWREG32(eth->base + TBUF_CTRL) = reg;
+
+ /* Enable 2-byte IP align (matches working raspi4 drv_eth, no 64B RSB). */
+ reg = HWREG32(eth->base + RBUF_CTRL);
+ reg |= RBUF_ALIGN_2B;
+ reg &= ~RBUF_64B_EN;
+ HWREG32(eth->base + RBUF_CTRL) = reg;
+
+ reg = HWREG32(eth->base + RBUF_CHK_CTRL);
+ reg |= RBUF_RXCHK_EN | RBUF_L3_PARSE_DIS;
+ HWREG32(eth->base + RBUF_CHK_CTRL) = reg;
+
+ HWREG32(eth->base + RBUF_TBUF_SIZE_CTRL) = 1;
+}
+
+static void bcmgenet_gmac_write_hwaddr(struct bcmgenet_eth *eth)
+{
+ rt_uint32_t reg;
+ rt_uint8_t *addr = eth->mac;
+
+ reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
+ HWREG32(eth->base + UMAC_MAC0) = reg;
+ rt_hw_wmb();
+
+ reg = addr[4] << 8 | addr[5];
+ HWREG32(eth->base + UMAC_MAC1) = reg;
+ rt_hw_wmb();
+}
+
+static void bcmgenet_disable_dma(struct bcmgenet_eth *eth)
+{
+ HWREGCLR32(eth->base + TDMA_REG_BASE + DMA_CTRL, DMA_EN);
+ HWREGCLR32(eth->base + RDMA_REG_BASE + DMA_CTRL, DMA_EN);
+
+ HWREG32(eth->base + UMAC_TX_FLUSH) = 1;
+ rt_hw_us_delay(10);
+ HWREG32(eth->base + UMAC_TX_FLUSH) = 0;
+}
+
+static void bcmgenet_enable_dma(struct bcmgenet_eth *eth)
+{
+ rt_uint32_t dma_ctrl = (1 << (DEFAULT_RING + DMA_RING_BUF_EN_SHIFT)) | DMA_EN;
+
+ HWREG32(eth->base + TDMA_REG_BASE + DMA_CTRL) = dma_ctrl;
+ HWREGSET32(eth->base + RDMA_REG_BASE + DMA_CTRL, dma_ctrl);
+}
+
+static void bcmgenet_rx_descs_init(struct bcmgenet_eth *eth)
+{
+ void *desc = eth->rx_desc_base;
+ rt_ubase_t rxbuffs_dma = eth->rxbuffer_dma;
+ rt_uint32_t len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
+
+ for (int i = 0; i < RX_DESCS; ++i)
+ {
+ HWREG32(desc + DMA_DESC_ADDRESS_LO) = rt_lower_32_bits(rxbuffs_dma);
+ HWREG32(desc + DMA_DESC_ADDRESS_HI) = rt_upper_32_bits(rxbuffs_dma);
+ HWREG32(desc + DMA_DESC_LENGTH_STATUS) = len_stat;
+
+ desc += DMA_DESC_SIZE;
+ rxbuffs_dma += RX_BUF_LENGTH;
+ }
+}
+
+static void bcmgenet_rx_ring_init(struct bcmgenet_eth *eth)
+{
+ HWREG32(eth->base + RDMA_REG_BASE + DMA_SCB_BURST_SIZE) = DMA_MAX_BURST_LENGTH;
+
+ HWREG32(eth->base + RDMA_RING_REG_BASE + DMA_START_ADDR) = 0x0;
+ HWREG32(eth->base + RDMA_READ_PTR) = 0x0;
+ HWREG32(eth->base + RDMA_WRITE_PTR) = 0x0;
+ HWREG32(eth->base + RDMA_RING_REG_BASE + DMA_END_ADDR) = RX_DESCS * DMA_DESC_SIZE / 4 - 1;
+
+ HWREG32(eth->base + RDMA_PROD_INDEX) = 0;
+ HWREG32(eth->base + RDMA_CONS_INDEX) = 0;
+ eth->c_index = 0;
+ eth->rx_index = 0;
+
+ HWREG32(eth->base + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE) =
+ (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH;
+ HWREG32(eth->base + RDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH) = 0x1;
+ HWREG32(eth->base + RDMA_XON_XOFF_THRESH) =
+ (DMA_FC_THRESH_LO << DMA_XOFF_THRESHOLD_SHIFT) | DMA_FC_THRESH_HI;
+ HWREG32(eth->base + RDMA_REG_BASE + DMA_RING_CFG) = 1 << DEFAULT_RING;
+}
+
+static void bcmgenet_tx_ring_init(struct bcmgenet_eth *eth)
+{
+ HWREG32(eth->base + TDMA_REG_BASE + DMA_SCB_BURST_SIZE) = DMA_MAX_BURST_LENGTH;
+
+ HWREG32(eth->base + TDMA_RING_REG_BASE + DMA_START_ADDR) = 0x0;
+ HWREG32(eth->base + TDMA_READ_PTR) = 0x0;
+ HWREG32(eth->base + TDMA_WRITE_PTR) = 0x0;
+ HWREG32(eth->base + TDMA_RING_REG_BASE + DMA_END_ADDR) = TX_DESCS * DMA_DESC_SIZE / 4 - 1;
+
+ HWREG32(eth->base + TDMA_PROD_INDEX) = 0;
+ HWREG32(eth->base + TDMA_CONS_INDEX) = 0;
+ eth->tx_index = 0;
+
+ HWREG32(eth->base + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH) = 0x1;
+ HWREG32(eth->base + TDMA_FLOW_PERIOD) = 0x0;
+ HWREG32(eth->base + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE) =
+ (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH;
+
+ HWREG32(eth->base + TDMA_REG_BASE + DMA_RING_CFG) = 1 << DEFAULT_RING;
+}
+
+static void bcmgenet_mii_config(struct bcmgenet_eth *eth)
+{
+ rt_uint32_t reg;
+
+ HWREG32(eth->base + SYS_PORT_CTRL) = PORT_MODE_EXT_GPHY;
+
+ reg = HWREG32(eth->base + EXT_RGMII_OOB_CTRL);
+ reg &= ~OOB_DISABLE;
+ reg &= ~ID_MODE_DIS;
+ if (eth->interface == RT_PHY_INTERFACE_MODE_RGMII)
+ reg |= ID_MODE_DIS;
+ reg |= RGMII_MODE_EN;
+ HWREG32(eth->base + EXT_RGMII_OOB_CTRL) = reg;
+}
+
+static void bcmgenet_set_rx_mode(struct bcmgenet_eth *eth)
+{
+ /* Promiscuous: bypass MDF until full multicast/uc filter support. */
+ HWREGSET32(eth->base + UMAC_CMD, CMD_PROMISC);
+ HWREG32(eth->base + UMAC_MDF_CTRL) = 0;
+}
+
+static rt_err_t bcmgenet_adjust_link(struct bcmgenet_eth *eth, rt_bool_t link_up)
+{
+ rt_uint32_t reg, cmd_bits = 0;
+ struct rt_phy_device *phy = eth->phy;
+
+ reg = HWREG32(eth->base + EXT_RGMII_OOB_CTRL);
+ if (link_up)
+ reg |= RGMII_LINK;
+ else
+ reg &= ~RGMII_LINK;
+ HWREG32(eth->base + EXT_RGMII_OOB_CTRL) = reg;
+
+ if (!link_up)
+ return RT_EOK;
+
+ switch (phy->speed)
+ {
+ case SPEED_1000:
+ cmd_bits = UMAC_SPEED_1000;
+ break;
+
+ case SPEED_100:
+ cmd_bits = UMAC_SPEED_100;
+ break;
+
+ case SPEED_10:
+ cmd_bits = UMAC_SPEED_10;
+ break;
+
+ default:
+ LOG_E("Unsupported PHY speed: %d", phy->speed);
+ return -RT_EINVAL;
+ }
+ cmd_bits <<= CMD_SPEED_SHIFT;
+
+ if (phy->duplex != DUPLEX_FULL)
+ cmd_bits |= CMD_HD_EN | CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
+
+ reg = HWREG32(eth->base + UMAC_CMD);
+ reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
+ CMD_HD_EN | CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
+ reg |= cmd_bits;
+ reg |= CMD_TX_EN | CMD_RX_EN;
+ HWREG32(eth->base + UMAC_CMD) = reg;
+
+ return RT_EOK;
+}
+
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+static rt_bool_t bcmgenet_phy_poll_link(struct bcmgenet_eth *eth)
+{
+ int bmsr;
+
+ bmsr = rt_phy_read(eth->phy, RT_MDIO_DEVAD_NONE, RT_MII_BMSR);
+ if (bmsr < 0)
+ {
+ return RT_FALSE;
+ }
+
+ bmsr = rt_phy_read(eth->phy, RT_MDIO_DEVAD_NONE, RT_MII_BMSR);
+ if (!(bmsr & RT_BMSR_LSTATUS))
+ {
+ eth->phy->link = 0;
+ return RT_FALSE;
+ }
+
+ eth->phy->link = 1;
+ if (rt_genphy_parse_link(eth->phy))
+ {
+ eth->phy->link = 0;
+ return RT_FALSE;
+ }
+
+ return RT_TRUE;
+}
+
+static void bcmgenet_phy_link_up(struct bcmgenet_eth *eth)
+{
+ if (bcmgenet_adjust_link(eth, RT_TRUE))
+ {
+ LOG_E("Adjust PHY link failed");
+ return;
+ }
+
+ bcmgenet_set_rx_mode(eth);
+ LOG_I("Link up speed=%d duplex=%d", eth->phy->speed, eth->phy->duplex);
+ eth_device_linkchange(&eth->parent, RT_TRUE);
+}
+
+static void bcmgenet_phy_link_down(struct bcmgenet_eth *eth)
+{
+ eth->phy->link = 0;
+
+ if (bcmgenet_adjust_link(eth, RT_FALSE))
+ {
+ LOG_E("Adjust PHY link failed");
+ return;
+ }
+
+ LOG_W("Link down");
+ eth_device_linkchange(&eth->parent, RT_FALSE);
+}
+
+static void bcmgenet_phy_retry_work(struct rt_work *work, void *work_data)
+{
+ struct bcmgenet_eth *eth = work_data;
+
+ RT_UNUSED(work);
+
+ if (eth->phy->link)
+ {
+ eth->phy_retry_count = 0;
+ return;
+ }
+
+ if (bcmgenet_phy_poll_link(eth))
+ {
+ eth->phy_retry_count = 0;
+ bcmgenet_phy_link_up(eth);
+ return;
+ }
+
+ eth->phy_retry_count++;
+ if (eth->phy_retry_count < PHY_RETRY_MAX)
+ {
+ rt_work_submit(&eth->phy_retry_work,
+ rt_tick_from_millisecond(PHY_RETRY_INTERVAL_MS));
+ }
+ else
+ {
+ LOG_W("PHY link retry stopped, wait for link IRQ");
+ eth->phy_retry_count = 0;
+ }
+}
+
+static void bcmgenet_link_work(struct rt_work *work, void *work_data)
+{
+ struct bcmgenet_eth *eth = work_data;
+ rt_bool_t link_up;
+
+ RT_UNUSED(work);
+
+ link_up = bcmgenet_phy_poll_link(eth);
+ eth->phy_retry_count = 0;
+
+ if (link_up)
+ {
+ bcmgenet_phy_link_up(eth);
+ }
+ else
+ {
+ bcmgenet_phy_link_down(eth);
+ }
+}
+#endif
+
+static struct pbuf *bcmgenet_eth_rx(rt_device_t dev);
+
+static void bcmgenet_enable_intr(struct bcmgenet_eth *eth)
+{
+ rt_uint32_t intr;
+
+ /* Ring 16 (raspi4 drv_eth): TX/RX done on INTRL2_0 bits 16/13. */
+ intr = UMAC_IRQ_LINK_EVENT;
+ intr |= UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR;
+ intr |= UMAC_IRQ_RXDMA_DONE | UMAC_IRQ_TXDMA_DONE;
+ HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_MASK_CLEAR) = intr;
+
+#if DEFAULT_RING <= 15
+ intr = UMAC_IRQ1_TX_INTR(DEFAULT_RING) | UMAC_IRQ1_RX_INTR(DEFAULT_RING);
+ HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_MASK_CLEAR) = intr;
+#endif
+}
+
+static void bcmgenet_disable_intr(struct bcmgenet_eth *eth)
+{
+ HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_MASK_SET) = 0xffffffff;
+ HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_CLEAR) = 0xffffffff;
+ HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_MASK_SET) = 0xffffffff;
+ HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_CLEAR) = 0xffffffff;
+}
+
+static rt_err_t bcmgenet_start(struct bcmgenet_eth *eth)
+{
+ rt_err_t err;
+
+ eth->tx_desc_base = eth->base + GENET_TX_OFF;
+ eth->rx_desc_base = eth->base + GENET_RX_OFF;
+
+ bcmgenet_umac_reset(eth);
+
+ bcmgenet_gmac_write_hwaddr(eth);
+
+ /* Disable RX/TX DMA and flush TX queues */
+ bcmgenet_disable_dma(eth);
+
+ bcmgenet_rx_ring_init(eth);
+ bcmgenet_rx_descs_init(eth);
+
+ bcmgenet_tx_ring_init(eth);
+
+ /* Enable RX/TX DMA */
+ bcmgenet_enable_dma(eth);
+
+ /* Sync RX ring indices with hardware (raspi4 drv_eth). */
+ eth->c_index = HWREG32(eth->base + RDMA_PROD_INDEX) & DMA_P_INDEX_MASK;
+ eth->rx_index = eth->c_index % RX_DESCS;
+ HWREG32(eth->base + RDMA_CONS_INDEX) = eth->c_index;
+ HWREG32(eth->base + RDMA_PROD_INDEX) = eth->c_index;
+
+ if ((err = rt_phy_config(eth->phy)))
+ {
+ LOG_E("PHY config failed: %s", rt_strerror(err));
+ return err;
+ }
+
+ if ((err = rt_phy_startup(eth->phy)))
+ {
+ LOG_E("PHY startup failed: %s", rt_strerror(err));
+ return err;
+ }
+
+ /* Update MAC registers based on PHY property */
+ if ((err = bcmgenet_adjust_link(eth, eth->phy->link)))
+ {
+ LOG_E("Adjust PHY link failed: %s", rt_strerror(err));
+ return err;
+ }
+
+ /* Enable Rx/Tx */
+ HWREGSET32(eth->base + UMAC_CMD, CMD_TX_EN | CMD_RX_EN);
+
+ bcmgenet_set_rx_mode(eth);
+ bcmgenet_enable_intr(eth);
+
+ LOG_I("Started: link=%d speed=%d duplex=%d",
+ eth->phy->link, eth->phy->speed, eth->phy->duplex);
+
+ return RT_EOK;
+}
+
+static void bcmgenet_stop(struct bcmgenet_eth *eth)
+{
+ HWREGCLR32(eth->base + UMAC_CMD, CMD_TX_EN | CMD_RX_EN);
+
+ bcmgenet_disable_intr(eth);
+
+ bcmgenet_disable_dma(eth);
+}
+
+static void bcmgenet_rx_refill_desc(struct bcmgenet_eth *eth, void *desc, rt_ubase_t packet_dma)
+{
+ rt_uint32_t len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
+
+ HWREG32(desc + DMA_DESC_ADDRESS_LO) = rt_lower_32_bits(packet_dma);
+ HWREG32(desc + DMA_DESC_ADDRESS_HI) = rt_upper_32_bits(packet_dma);
+ HWREG32(desc + DMA_DESC_LENGTH_STATUS) = len_stat;
+}
+
+static void bcmgenet_tx_wait_done(struct bcmgenet_eth *eth, rt_uint32_t prod_index)
+{
+ rt_uint32_t cons;
+ rt_tick_t start = rt_tick_get();
+ rt_tick_t limit = rt_tick_from_millisecond(50);
+
+ while (rt_tick_get() - start < limit)
+ {
+ cons = HWREG32(eth->base + TDMA_CONS_INDEX) & 0xffff;
+ if (cons == prod_index)
+ {
+ return;
+ }
+ rt_thread_mdelay(1);
+ }
+
+ if (rt_sem_take(&eth->tx_done, rt_tick_from_millisecond(50)) == RT_EOK)
+ {
+ return;
+ }
+
+ LOG_W("TX timeout prod=%u cons=%u", prod_index,
+ HWREG32(eth->base + TDMA_CONS_INDEX) & 0xffff);
+}
+
+static rt_err_t bcmgenet_eth_tx(rt_device_t dev, struct pbuf *p)
+{
+ void *desc, *packet;
+ rt_ubase_t packet_dma;
+ rt_uint32_t len_stat, prod_index, cons_index, n;
+ struct bcmgenet_eth *eth = raw_to_bcmgenet_eth(dev);
+
+ prod_index = HWREG32(eth->base + TDMA_PROD_INDEX) & 0xffff;
+ cons_index = HWREG32(eth->base + TDMA_CONS_INDEX) & 0xffff;
+
+ for (n = 0; ((prod_index + 1) & 0xffff) == cons_index && n < 50; n++)
+ {
+ cons_index = HWREG32(eth->base + TDMA_CONS_INDEX) & 0xffff;
+ rt_thread_mdelay(1);
+ }
+
+ if (((prod_index + 1) & 0xffff) == cons_index)
+ {
+ LOG_W("TX ring full prod=%u cons=%u", prod_index, cons_index);
+ return -RT_EBUSY;
+ }
+
+ packet = eth->txbuffer + eth->tx_index * RX_BUF_LENGTH;
+ packet_dma = eth->txbuffer_dma + (packet - (void *)eth->txbuffer);
+
+ rt_memset(packet, 0, GENET_TX_TSB_SIZE);
+ pbuf_copy_partial(p, packet + GENET_TX_TSB_SIZE, p->tot_len, 0);
+
+ len_stat = (GENET_TX_TSB_SIZE + p->tot_len) << DMA_BUFLENGTH_SHIFT;
+ len_stat |= 0x3f << DMA_TX_QTAG_SHIFT;
+ len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP;
+ desc = eth->tx_desc_base + eth->tx_index * DMA_DESC_SIZE;
+
+ HWREG32(desc + DMA_DESC_ADDRESS_LO) = rt_lower_32_bits(packet_dma);
+ HWREG32(desc + DMA_DESC_ADDRESS_HI) = rt_upper_32_bits(packet_dma);
+ HWREG32(desc + DMA_DESC_LENGTH_STATUS) = len_stat;
+
+ if (++eth->tx_index >= TX_DESCS)
+ {
+ eth->tx_index = 0;
+ }
+
+ prod_index = (prod_index + 1) & 0xffff;
+ HWREG32(eth->base + TDMA_PROD_INDEX) = prod_index;
+
+ bcmgenet_tx_wait_done(eth, prod_index);
+ eth_device_ready(&eth->parent);
+
+ return RT_EOK;
+}
+
+static struct pbuf *bcmgenet_eth_rx(rt_device_t dev)
+{
+ void *desc, *packet;
+ rt_uint64_t packet_dma;
+ rt_uint32_t prod_index, length, length_status;
+ struct pbuf *p = RT_NULL;
+ struct bcmgenet_eth *eth = raw_to_bcmgenet_eth(dev);
+
+ prod_index = HWREG32(eth->base + RDMA_PROD_INDEX) & DMA_P_INDEX_MASK;
+
+ HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_CLEAR) =
+ UMAC_IRQ_RXDMA_DONE;
+#if DEFAULT_RING <= 15
+ HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_CLEAR) =
+ UMAC_IRQ1_RX_INTR(DEFAULT_RING);
+#endif
+
+ if (prod_index == eth->c_index)
+ {
+ return RT_NULL;
+ }
+
+ desc = eth->rx_desc_base + eth->rx_index * DMA_DESC_SIZE;
+
+ rt_hw_rmb();
+ length_status = HWREG32(desc + DMA_DESC_LENGTH_STATUS);
+
+ length = (length_status >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK;
+
+ packet_dma = HWREG32(desc + DMA_DESC_ADDRESS_HI);
+ packet_dma <<= 32;
+ packet_dma |= HWREG32(desc + DMA_DESC_ADDRESS_LO);
+ packet = eth->rxbuffer + (packet_dma - eth->rxbuffer_dma);
+
+ if (length <= RX_BUF_OFFSET)
+ {
+ goto _repost;
+ }
+
+ packet += RX_BUF_OFFSET;
+
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, packet, length);
+
+ if (!(p = pbuf_alloc(PBUF_RAW, length, PBUF_RAM)))
+ {
+ goto _repost;
+ }
+
+ rt_memcpy(p->payload, packet, length);
+
+_repost:
+ packet_dma = HWREG32(desc + DMA_DESC_ADDRESS_HI);
+ packet_dma <<= 32;
+ packet_dma |= HWREG32(desc + DMA_DESC_ADDRESS_LO);
+
+ bcmgenet_rx_refill_desc(eth, desc, packet_dma);
+
+ eth->c_index = (eth->c_index + 1) & 0xffff;
+ HWREG32(eth->base + RDMA_CONS_INDEX) = eth->c_index;
+
+ if (++eth->rx_index >= RX_DESCS)
+ {
+ eth->rx_index = 0;
+ }
+
+ return p;
+}
+
+static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct bcmgenet_eth *eth = raw_to_bcmgenet_eth(dev);
+
+ switch (cmd)
+ {
+ case NIOCTL_GADDR:
+ if (args)
+ {
+ rt_memcpy(args, eth->mac, sizeof(eth->mac));
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+ break;
+
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+
+ return err;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops bcmgenet_eth_ops =
+{
+ .control = bcmgenet_eth_control,
+};
+#endif
+
+/* Handle Rx and Tx default queues + other stuff */
+static void bcmgenet_eth_isr0(int irq, void *param)
+{
+ rt_uint32_t status;
+ struct bcmgenet_eth *eth = param;
+
+ /* Read irq status */
+ status = HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_STAT) &
+ ~HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_MASK_STATUS);
+
+ /* Clear interrupts */
+ HWREG32(eth->base + GENET_INTRL2_0_OFF + INTRL2_CPU_CLEAR) = status;
+
+ if (status & UMAC_IRQ_TXDMA_DONE)
+ {
+ rt_sem_release(&eth->tx_done);
+ }
+
+ if (status & UMAC_IRQ_RXDMA_DONE)
+ {
+ eth_device_ready(&eth->parent);
+ }
+
+ if (status & UMAC_IRQ_RBUF_OVERFLOW)
+ {
+ LOG_W("RX buffer overflow");
+ }
+
+ status &= (UMAC_IRQ_LINK_EVENT | UMAC_IRQ_PHY_DET_R);
+ if (status & UMAC_IRQ_LINK_EVENT)
+ {
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+ rt_work_submit(&eth->link_work, 0);
+#endif
+ }
+}
+
+/* Handle Rx and Tx priority queues */
+static void bcmgenet_eth_isr1(int irq, void *param)
+{
+ rt_uint32_t status;
+ struct bcmgenet_eth *eth = param;
+
+ /* Read irq status */
+ status = HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_STAT) &
+ ~HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_MASK_STATUS);
+
+ /* Clear interrupts */
+ HWREG32(eth->base + GENET_INTRL2_1_OFF + INTRL2_CPU_CLEAR) = status;
+
+#if DEFAULT_RING <= 15
+ if (status & UMAC_IRQ1_TX_INTR(DEFAULT_RING))
+ {
+ rt_sem_release(&eth->tx_done);
+ }
+#endif
+
+#if DEFAULT_RING <= 15
+ if (status & UMAC_IRQ1_RX_INTR(DEFAULT_RING))
+ {
+ eth_device_ready(&eth->parent);
+ }
+#endif
+}
+
+static rt_err_t bcmgenet_eth_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t value;
+ struct mii_bus *bus;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *mdio_np, *phy_np, *fw_np;
+ struct bcmgenet_eth *eth = rt_calloc(1, sizeof(*eth));
+
+ if (!eth)
+ {
+ return -RT_ENOMEM;
+ }
+
+ eth->dev = dev;
+ eth->dma_buf_size = RX_TOTAL_BUFSIZE + TX_TOTAL_BUFSIZE;
+
+ if (!(eth->base = rt_dm_dev_iomap(dev, 0)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ value = HWREG32(eth->base + SYS_REV_CTRL);
+ value = (value >> 24) & 0x0f;
+
+ if (value != 6)
+ {
+ if (value == 5)
+ {
+ value = 4;
+ }
+ else if (value == 0)
+ {
+ value = 1;
+ }
+
+ LOG_E("Unsupported GENETv%d.%d",
+ value, (HWREG32(eth->base + SYS_REV_CTRL) >> 16) & 0x0f);
+
+ err = -RT_ENOSYS;
+ goto _fail;
+ }
+
+ if ((eth->irq0 = rt_dm_dev_get_irq(dev, 0)) < 0)
+ {
+ err = eth->irq0;
+ goto _fail;
+ }
+
+ if ((eth->irq1 = rt_dm_dev_get_irq(dev, 1)) < 0)
+ {
+ err = eth->irq1;
+ goto _fail;
+ }
+
+ /* For PHY & MDIO */
+ mdio_np = rt_ofw_get_child_by_tag(np, "mdio");
+ rt_platform_ofw_device_probe_child(mdio_np);
+ rt_ofw_node_put(mdio_np);
+
+ if (!(bus = rt_mdio_get_bus_by_name("unimac MII bus")))
+ {
+ err = -RT_ENOSYS;
+ goto _fail;
+ }
+
+ if (!(phy_np = rt_ofw_parse_phandle(np, "phy-handle", 0)))
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (rt_ofw_prop_read_u32(phy_np, "reg", &value))
+ {
+ rt_ofw_node_put(phy_np);
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (!(eth->phy = rt_phy_find_by_mask(bus, 1 << value)))
+ {
+ rt_ofw_node_put(phy_np);
+ err = -RT_ENOSYS;
+ goto _fail;
+ }
+
+ eth->phy_np = phy_np;
+ eth->phy->node = phy_np;
+
+ rt_ofw_get_interface(np, &eth->interface);
+ eth->phy->interface = eth->interface;
+
+ switch (eth->interface)
+ {
+ case RT_PHY_INTERFACE_MODE_RGMII:
+ case RT_PHY_INTERFACE_MODE_RGMII_RXID:
+ break;
+
+ default:
+ LOG_E("Unknown PHY mode: %d", eth->interface);
+ err = -RT_ENOSYS;
+ goto _fail;
+ }
+
+ bcmgenet_mii_config(eth);
+
+ HWREG32(eth->base + SYS_RBUF_FLUSH_CTRL) = 0;
+ rt_hw_us_delay(10);
+ /* Disable MAC while updating its registers */
+ HWREG32(eth->base + UMAC_CMD) = 0;
+ /* Issue soft reset with (rg)mii loopback to ensure a stable rxclk */
+ HWREG32(eth->base + UMAC_CMD) = CMD_SW_RESET | CMD_LCL_LOOP_EN;
+
+ /* Connect PHY */
+ if (!rt_dm_dev_prop_read_u32(dev, "max-speed", &eth->speed))
+ {
+ if ((err = rt_phy_set_supported(eth->phy, eth->speed)))
+ {
+ goto _fail;
+ }
+ }
+
+ /* PHY config/startup deferred until MAC rings are ready in bcmgenet_start() */
+
+ /* For MAC address */
+ if ((fw_np = rpi_firmware_find_node()))
+ {
+ struct rpi_firmware *rpi_fw = rpi_firmware_get(fw_np);
+
+ err = rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS,
+ eth->mac, sizeof(eth->mac));
+
+ rt_ofw_node_put(fw_np);
+ rpi_firmware_put(rpi_fw);
+ }
+
+ if ((!fw_np || err) && (err = rt_ofw_get_mac_addr(np, eth->mac)))
+ {
+ goto _fail;
+ }
+
+ if (!(eth->rxbuffer = rt_dma_alloc_coherent(dev, eth->dma_buf_size, &eth->rxbuffer_dma)))
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+ eth->txbuffer = eth->rxbuffer + RX_TOTAL_BUFSIZE;
+ eth->txbuffer_dma = eth->rxbuffer_dma + RX_TOTAL_BUFSIZE;
+
+ rt_sem_init(&eth->tx_done, "genet_tx", 0, RT_IPC_FLAG_FIFO);
+
+ if ((err = bcmgenet_start(eth)))
+ {
+ goto _fail;
+ }
+
+#ifdef RT_USING_DEVICE_OPS
+ eth->parent.parent.ops = &bcmgenet_eth_ops;
+#else
+ eth->parent.parent.control = bcmgenet_eth_control;
+#endif
+ eth->parent.eth_tx = bcmgenet_eth_tx;
+ eth->parent.eth_rx = bcmgenet_eth_rx;
+
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+ rt_work_init(&eth->link_work, bcmgenet_link_work, eth);
+ rt_work_init(&eth->phy_retry_work, bcmgenet_phy_retry_work, eth);
+#endif
+
+ dev->user_data = eth;
+
+ if ((err = rt_dm_dev_set_name_auto(&eth->parent.parent, "e")) < 0)
+ {
+ goto _stop;
+ }
+
+ if ((err = eth_device_init(&eth->parent, rt_dm_dev_get_name(&eth->parent.parent))))
+ {
+ goto _stop;
+ }
+
+ rt_hw_interrupt_install(eth->irq0, bcmgenet_eth_isr0, eth, "bcmgenet0");
+ rt_hw_interrupt_umask(eth->irq0);
+
+ rt_hw_interrupt_install(eth->irq1, bcmgenet_eth_isr1, eth, "bcmgenet1");
+ rt_hw_interrupt_umask(eth->irq1);
+
+ if (eth->phy->link)
+ {
+ eth_device_linkchange(&eth->parent, RT_TRUE);
+ }
+ else
+ {
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+ eth->phy_retry_count = 0;
+ rt_work_submit(&eth->phy_retry_work,
+ rt_tick_from_millisecond(PHY_RETRY_INTERVAL_MS));
+#endif
+ }
+
+ return RT_EOK;
+
+_stop:
+ bcmgenet_stop(eth);
+ rt_sem_detach(&eth->tx_done);
+
+_fail:
+ if (eth && eth->phy_np)
+ {
+ rt_ofw_node_put(eth->phy_np);
+ }
+
+ if (eth && eth->base)
+ {
+ rt_iounmap(eth->base);
+ }
+
+ if (eth->rxbuffer)
+ {
+ rt_dma_free_coherent(eth->dev, eth->dma_buf_size,
+ eth->rxbuffer, eth->rxbuffer_dma);
+ }
+
+ rt_free(eth);
+
+ return err;
+}
+
+static rt_err_t bcmgenet_eth_remove(struct rt_platform_device *pdev)
+{
+ struct bcmgenet_eth *eth = pdev->parent.user_data;
+
+ eth_device_linkchange(&eth->parent, RT_FALSE);
+ eth_device_deinit(&eth->parent);
+
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+ rt_work_cancel(&eth->link_work);
+ rt_work_cancel(&eth->phy_retry_work);
+#endif
+
+ rt_sem_detach(&eth->tx_done);
+ bcmgenet_stop(eth);
+
+ rt_hw_interrupt_mask(eth->irq0);
+ rt_pic_detach_irq(eth->irq0, eth);
+
+ rt_hw_interrupt_mask(eth->irq1);
+ rt_pic_detach_irq(eth->irq1, eth);
+
+ if (eth->phy_np)
+ {
+ rt_ofw_node_put(eth->phy_np);
+ }
+
+ rt_dma_free_coherent(eth->dev, eth->dma_buf_size, eth->rxbuffer, eth->rxbuffer_dma);
+
+ rt_free(eth);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcmgenet_eth_ofw_ids[] =
+{
+ { .compatible = "brcm,genet-v5" },
+ { .compatible = "brcm,bcm2711-genet-v5" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcmgenet_eth_driver =
+{
+ .name = "eth-bcmgenet",
+ .ids = bcmgenet_eth_ofw_ids,
+
+ .probe = bcmgenet_eth_probe,
+ .remove = bcmgenet_eth_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcmgenet_eth_driver);
diff --git a/bsp/raspberry-pi/dm/firmware/Kconfig b/bsp/raspberry-pi/dm/firmware/Kconfig
new file mode 100755
index 0000000000..33ccccceb8
--- /dev/null
+++ b/bsp/raspberry-pi/dm/firmware/Kconfig
@@ -0,0 +1,6 @@
+config RT_FIRMWARE_RASPBERRYPI
+ bool "Raspberrypi Firmware"
+ depends on RT_USING_OFW
+ depends on RT_USING_MBOX
+ depends on RT_USING_DMA
+ default n
diff --git a/bsp/raspberry-pi/dm/firmware/SConscript b/bsp/raspberry-pi/dm/firmware/SConscript
new file mode 100755
index 0000000000..64797072ab
--- /dev/null
+++ b/bsp/raspberry-pi/dm/firmware/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_FIRMWARE_RASPBERRYPI']):
+ src += ['firmware-raspberrypi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/firmware/firmware-raspberrypi.c b/bsp/raspberry-pi/dm/firmware/firmware-raspberrypi.c
new file mode 100755
index 0000000000..95130886af
--- /dev/null
+++ b/bsp/raspberry-pi/dm/firmware/firmware-raspberrypi.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define DBG_TAG "fw.raspberrypi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <firmware-raspberrypi.h>
+#include <drivers/mailbox.h>
+
+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
+#define MBOX_CHAN(msg) ((msg) & 0xf)
+#define MBOX_DATA28(msg) ((msg) & ~0xf)
+#define MBOX_CHAN_PROPERTY 8
+
+struct rpi_firmware
+{
+ struct rt_mbox_client parent;
+
+ /* The property channel. */
+ struct rt_mbox_chan *chan;
+ rt_bool_t done;
+ rt_uint32_t enabled;
+
+ struct rt_ref consumers;
+ rt_uint32_t get_throttled;
+
+ struct rt_spinlock transaction_lock;
+};
+
+static struct rt_device *rpi_firmware_dma_dev(struct rpi_firmware *rpi_fw)
+{
+ if (rpi_fw && rpi_fw->chan && rpi_fw->chan->ctrl && rpi_fw->chan->ctrl->dev)
+ {
+ return rpi_fw->chan->ctrl->dev;
+ }
+
+ return rpi_fw ? rpi_fw->parent.dev : RT_NULL;
+}
+
+static rt_err_t rpi_firmware_transaction(struct rpi_firmware *rpi_fw,
+ rt_uint32_t chan, rt_uint32_t data)
+{
+ rt_ssize_t res;
+ rt_uint32_t message = MBOX_MSG(chan, data);
+
+ rt_hw_spin_lock(&rpi_fw->transaction_lock.lock);
+
+ rpi_fw->done = RT_FALSE;
+ res = rt_mbox_send(rpi_fw->chan, &message, RT_WAITING_FOREVER);
+
+ rt_hw_rmb();
+
+ if (res == RT_EOK)
+ {
+ if (!rpi_fw->done)
+ {
+ res = -RT_ETIMEOUT;
+ LOG_W("Firmware transaction timeout");
+ }
+ }
+ else if (res == -RT_ETIMEOUT && rpi_fw->done)
+ {
+ res = RT_EOK;
+ }
+ else if (res == -RT_ETIMEOUT)
+ {
+ LOG_W("Firmware transaction timeout");
+ }
+ else
+ {
+ LOG_E("Mailbox send message error = %s", rt_strerror(res));
+ }
+
+ rt_hw_spin_unlock(&rpi_fw->transaction_lock.lock);
+
+ return res;
+}
+
+/* RPI made the F*CKING hardware so I written the F*CKING code:) */
+void *rpi_firmware_property_raw_alloc(struct rpi_firmware *rpi_fw,
+ rt_size_t max_header_tag_size, rt_ubase_t *out_bus_addr)
+{
+ void *buf;
+ rt_size_t size = max_header_tag_size + 12;
+
+ buf = rt_dma_alloc_coherent(rpi_firmware_dma_dev(rpi_fw),
+ RT_ALIGN(size, ARCH_PAGE_SIZE), out_bus_addr);
+
+ return buf ? buf + 8 : RT_NULL;
+}
+
+void rpi_firmware_property_raw_free(struct rpi_firmware *rpi_fw,
+ rt_size_t max_header_tag_size, void *buf, rt_ubase_t bus_addr)
+{
+ rt_size_t size = max_header_tag_size + 12;
+
+ rt_dma_free_coherent(rpi_firmware_dma_dev(rpi_fw),
+ RT_ALIGN(size, ARCH_PAGE_SIZE), buf - 8, bus_addr);
+}
+
+rt_err_t rpi_firmware_property(struct rpi_firmware *rpi_fw,
+ rt_uint32_t tag, void *tag_data, rt_size_t buf_size)
+{
+ rt_err_t err;
+ void *buf;
+ rt_ubase_t bus_addr;
+ rt_size_t max_size;
+ struct rpi_firmware_property_tag_header *header;
+
+ max_size = sizeof(*header) + buf_size;
+ buf = rpi_firmware_property_raw_alloc(rpi_fw, max_size, &bus_addr);
+
+ if (!buf)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rt_memcpy(buf + sizeof(*header), tag_data, buf_size);
+ err = rpi_firmware_property_raw(rpi_fw, tag, bus_addr, buf, max_size);
+
+ if (!err)
+ {
+ rt_memcpy(tag_data, buf + sizeof(*header), buf_size);
+ }
+
+ rpi_firmware_property_raw_free(rpi_fw, max_size, buf, bus_addr);
+
+ return err;
+}
+
+rt_err_t rpi_firmware_property_raw(struct rpi_firmware *rpi_fw, rt_uint32_t tag,
+ rt_ubase_t bus_addr, struct rpi_firmware_property_tag_header *header, rt_size_t req_size)
+{
+ header->tag = tag;
+ header->buf_size = req_size - sizeof(*header);
+ header->req_resp_size = 0;
+
+ return rpi_firmware_property_list_raw(rpi_fw, bus_addr, (void *)header, req_size);
+}
+
+rt_err_t rpi_firmware_property_list(struct rpi_firmware *rpi_fw,
+ void *data, rt_size_t tag_size)
+{
+ rt_err_t err;
+ rt_ubase_t bus_addr;
+ void *buf = rpi_firmware_property_raw_alloc(rpi_fw, tag_size, &bus_addr);
+
+ if (!buf)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rt_memcpy(buf, data, tag_size);
+
+ if (!(err = rpi_firmware_property_list_raw(rpi_fw, bus_addr, buf, tag_size)))
+ {
+ rt_memcpy(data, buf, tag_size);
+ }
+
+ rpi_firmware_property_raw_free(rpi_fw, tag_size, buf, bus_addr);
+
+ return err;
+}
+
+rt_err_t rpi_firmware_property_list_raw(struct rpi_firmware *rpi_fw,
+ rt_ubase_t bus_addr, void *data, rt_size_t tag_size)
+{
+ rt_err_t err;
+ rt_uint32_t *buf = data - 8;
+ rt_size_t size = tag_size + 12;
+
+ /* Packets are processed a dword at a time. */
+ if (size & 3)
+ {
+ return -RT_EINVAL;
+ }
+
+ buf[0] = size;
+ buf[1] = RPI_FIRMWARE_STATUS_REQUEST;
+ buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END;
+ rt_hw_wmb();
+
+ err = rpi_firmware_transaction(rpi_fw, MBOX_CHAN_PROPERTY, bus_addr);
+
+ rt_hw_rmb();
+
+ if (err == RT_EOK && !(buf[1] & RPI_FIRMWARE_STATUS_SUCCESS))
+ {
+ /*
+ * The tag name here might not be the one causing the
+ * error, if there were multiple tags in the request.
+ * But single-tag is the most common, so go with it.
+ */
+ LOG_E("Request 0x%08x returned status 0x%08x", buf[2], buf[1]);
+ err = -RT_EINVAL;
+ }
+ else if (err == RT_EOK && buf[1] == RPI_FIRMWARE_STATUS_ERROR)
+ {
+ LOG_E("Request 0x%08x returned error status 0x%08x", buf[2], buf[1]);
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+rt_uint32_t rpi_firmware_clk_get_max_rate(struct rpi_firmware *rpi_fw, rt_uint32_t id)
+{
+ struct rpi_firmware_clk_rate_request msg = RPI_FIRMWARE_CLK_RATE_REQUEST(id);
+
+ if (rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ &msg, sizeof(msg)))
+ {
+ return RT_UINT32_MAX;
+ }
+
+ return rt_le32_to_cpu(msg.rate);
+}
+
+static const struct rt_ofw_node_id rpi_firmware_ofw_ids[];
+
+struct rt_ofw_node *rpi_firmware_find_node(void)
+{
+ return rt_ofw_find_node_by_ids(RT_NULL, rpi_firmware_ofw_ids);
+}
+
+struct rpi_firmware *rpi_firmware_get(struct rt_ofw_node *fw_np)
+{
+ struct rpi_firmware *rpi_fw = rt_ofw_data(fw_np);
+
+ if (!rpi_fw)
+ {
+ rt_platform_ofw_request(fw_np);
+ rpi_fw = rt_ofw_data(fw_np);
+ }
+
+ if (!rpi_fw)
+ {
+ return RT_NULL;
+ }
+
+ if (!rt_ref_get_unless_zero(&rpi_fw->consumers))
+ {
+ return RT_NULL;
+ }
+
+ return rpi_fw;
+}
+
+static void rpi_firmware_release(struct rt_ref *ref)
+{
+ struct rpi_firmware *rpi_fw = rt_container_of(ref, struct rpi_firmware, consumers);
+
+ rt_mbox_release(rpi_fw->chan);
+ rt_free(rpi_fw);
+}
+
+void rpi_firmware_put(struct rpi_firmware *rpi_fw)
+{
+ rt_ref_put(&rpi_fw->consumers, rpi_firmware_release);
+}
+
+static rt_err_t rpi_firmware_notify_reboot(struct rt_device *dev, char *cmd)
+{
+ rt_uint32_t reboot_flags = 0;
+ struct rpi_firmware *rpi_fw = dev->user_data;
+
+ if (cmd && rt_strstr(cmd, "tryboot"))
+ {
+ reboot_flags |= 0x1;
+ }
+
+ if (reboot_flags)
+ {
+ rpi_firmware_property(rpi_fw, RPI_FIRMWARE_SET_REBOOT_FLAGS,
+ &reboot_flags, sizeof(reboot_flags));
+ }
+
+ rpi_firmware_property(rpi_fw, RPI_FIRMWARE_NOTIFY_REBOOT, RT_NULL, 0);
+
+ return RT_EOK;
+}
+
+static void rpi_firmware_rx_callback(struct rt_mbox_client *client, void *data)
+{
+ struct rpi_firmware *rpi_fw = rt_container_of(client, struct rpi_firmware, parent);
+
+ rpi_fw->done = RT_TRUE;
+ rt_hw_wmb();
+}
+
+static void rpi_firmware_check_revision_info(struct rpi_firmware *rpi_fw)
+{
+ struct tm *tm;
+ rt_uint32_t revision, variant, hash[5];
+ static const char * const variant_strs[] =
+ {
+ "unknown",
+ "start",
+ "start_x",
+ "start_db",
+ "start_cd",
+ };
+ const char *variant_str = "cmd unsupported";
+
+ if (rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_FIRMWARE_REVISION,
+ &revision, sizeof(revision)))
+ {
+ goto _check_hash;
+ }
+
+ tm = localtime((time_t *)&revision);
+
+ if (!rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_FIRMWARE_VARIANT,
+ &variant, sizeof(variant)))
+ {
+ if (variant >= RT_ARRAY_SIZE(variant_strs))
+ {
+ variant = 0;
+ }
+
+ variant_str = variant_strs[variant];
+ }
+
+ LOG_I("Attached to firmware from %04d-%02d-%02d %02d:%02d:%02d, variant %s",
+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, variant_str);
+ (void)tm;
+ (void)variant_str;
+
+_check_hash:
+ if (rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_FIRMWARE_HASH,
+ hash, sizeof(hash)))
+ {
+ return;
+ }
+
+ LOG_I("Firmware hash is %08x%08x%08x%08x%08x",
+ hash[0], hash[1], hash[2], hash[3], hash[4]);
+}
+
+static rt_err_t rpi_firmware_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t packet;
+ struct rt_device *dev = &pdev->parent;
+ struct rpi_firmware *rpi_fw = rt_calloc(1, sizeof(*rpi_fw));
+
+ if (!rpi_fw)
+ {
+ return -RT_ENOMEM;
+ }
+
+ dev->user_data = rpi_fw;
+ rpi_fw->parent.dev = dev;
+ rpi_fw->parent.rx_callback = rpi_firmware_rx_callback;
+
+ rpi_fw->chan = rt_mbox_request_by_index(&rpi_fw->parent, 0);
+
+ if (rt_is_err_or_null(rpi_fw->chan))
+ {
+ err = -RT_EINVAL;
+ LOG_E("Request mailbox fail");
+
+ goto _fail;
+ }
+
+ if ((err = rt_dm_reboot_mode_register(dev, &rpi_firmware_notify_reboot)))
+ {
+ goto _fail;
+ }
+
+ rt_ref_init(&rpi_fw->consumers);
+ rt_spin_lock_init(&rpi_fw->transaction_lock);
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, rpi_fw);
+
+ rpi_firmware_check_revision_info(rpi_fw);
+
+ if (!rpi_firmware_property(rpi_fw, RPI_FIRMWARE_GET_THROTTLED,
+ &packet, sizeof(packet)))
+ {
+ struct rt_platform_device *voltage_monitor;
+
+ if (!(voltage_monitor = rt_calloc(1, sizeof(*voltage_monitor))))
+ {
+ LOG_E("No memory to create voltage monitor");
+
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ voltage_monitor->name = "raspberrypi-voltage-monitor";
+ voltage_monitor->priv = dev;
+
+ rt_bus_add_device(pdev->parent.bus, &voltage_monitor->parent);
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (!rt_is_err_or_null(rpi_fw->chan))
+ {
+ rt_mbox_release(rpi_fw->chan);
+ }
+
+ rt_free(rpi_fw);
+
+ return err;
+}
+
+static rt_err_t rpi_firmware_shutdown(struct rt_platform_device *pdev)
+{
+ struct rpi_firmware *rpi_fw = pdev->parent.user_data;
+
+ rpi_firmware_property(rpi_fw, RPI_FIRMWARE_NOTIFY_REBOOT, RT_NULL, 0);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rpi_firmware_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,bcm2835-firmware", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_firmware_driver =
+{
+ .name = "raspberrypi-firmware",
+ .ids = rpi_firmware_ofw_ids,
+
+ .probe = rpi_firmware_probe,
+ .shutdown = rpi_firmware_shutdown,
+};
+
+static int rpi_firmware_drv_register(void)
+{
+ rt_platform_driver_register(&rpi_firmware_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rpi_firmware_drv_register);
diff --git a/bsp/raspberry-pi/dm/graphic/SConscript b/bsp/raspberry-pi/dm/graphic/SConscript
new file mode 100755
index 0000000000..3d15055d62
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/SConscript
@@ -0,0 +1,13 @@
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+ path = os.path.join(cwd, d)
+ if os.path.isfile(os.path.join(path, 'SConscript')):
+ objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')
diff --git a/bsp/raspberry-pi/dm/graphic/backlight/Kconfig b/bsp/raspberry-pi/dm/graphic/backlight/Kconfig
new file mode 100755
index 0000000000..d29076aaf5
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/backlight/Kconfig
@@ -0,0 +1,5 @@
+config RT_GRAPHIC_BACKLIGHT_RPI
+ bool "Raspberry Pi display firmware driven backlight"
+ depends on RT_GRAPHIC_BACKLIGHT
+ depends on RT_FIRMWARE_RASPBERRYPI
+ default n
diff --git a/bsp/raspberry-pi/dm/graphic/backlight/SConscript b/bsp/raspberry-pi/dm/graphic/backlight/SConscript
new file mode 100755
index 0000000000..2a29615ad7
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/backlight/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_GRAPHIC_BACKLIGHT_RPI']):
+ src += ['backlight-rpi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/graphic/backlight/backlight-rpi.c b/bsp/raspberry-pi/dm/graphic/backlight/backlight-rpi.c
new file mode 100755
index 0000000000..438e7d85f7
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/backlight/backlight-rpi.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "video.backlight.rpi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+
+struct rpi_backlight
+{
+ struct rt_backlight_device parent;
+
+ struct rpi_firmware *rpi_fw;
+};
+
+#define raw_to_rpi_backlight(raw) rt_container_of(raw, struct rpi_backlight, parent)
+
+static rt_err_t rpi_backlight_update_status(struct rt_backlight_device *bl)
+{
+ rt_err_t err;
+ struct rpi_backlight *rbl = raw_to_rpi_backlight(bl);
+ rt_uint32_t brightness = bl->props.brightness;
+
+ if (bl->props.power != RT_BACKLIGHT_POWER_UNBLANK)
+ {
+ brightness = 0;
+ }
+
+ err = rpi_firmware_property(rbl->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, &brightness, sizeof(brightness));
+
+ if (err)
+ {
+ LOG_E("Failed to set brightness");
+
+ return err;
+ }
+
+ if ((int)brightness < 0)
+ {
+ LOG_E("Backlight change failed");
+
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+static struct rt_backlight_ops rpi_backlight_ops =
+{
+ .update_status = rpi_backlight_update_status,
+};
+
+static rt_err_t rpi_backlight_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ struct rpi_firmware *rpi_fw;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_backlight *rbl = rt_calloc(1, sizeof(*rbl));
+
+ if (!rbl)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ dev->user_data = rbl;
+
+ rbl->rpi_fw = rpi_fw;
+ rbl->parent.props.max_brightness = 255;
+ rbl->parent.ops = &rpi_backlight_ops;
+
+ if ((err = rt_backlight_register(&rbl->parent)))
+ {
+ goto _fail;
+ }
+
+ rt_backlight_set_brightness(&rbl->parent, 255);
+
+ return RT_EOK;
+
+_fail:
+ if (rbl->rpi_fw)
+ {
+ rpi_firmware_put(rbl->rpi_fw);
+ }
+
+ rt_free(rbl);
+
+ return err;
+}
+
+static rt_err_t rpi_backlight_remove(struct rt_platform_device *pdev)
+{
+ struct rpi_backlight *rbl = pdev->parent.user_data;
+
+ rt_backlight_unregister(&rbl->parent);
+
+ rpi_firmware_put(rbl->rpi_fw);
+ rt_free(rbl);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rpi_backlight_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rpi-backlight" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_backlight_driver =
+{
+ .name = "rpi-backlight",
+ .ids = rpi_backlight_ofw_ids,
+
+ .probe = rpi_backlight_probe,
+ .remove = rpi_backlight_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpi_backlight_driver);
diff --git a/bsp/raspberry-pi/dm/graphic/framebuffer/Kconfig b/bsp/raspberry-pi/dm/graphic/framebuffer/Kconfig
new file mode 100755
index 0000000000..40c7d9e691
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/framebuffer/Kconfig
@@ -0,0 +1,9 @@
+config RT_GRAPHIC_FB_BCM2708
+ bool "BCM2708 framebuffer support"
+ depends on RT_FIRMWARE_RASPBERRYPI
+ default n
+
+config RT_GRAPHIC_FB_RPISENSE
+ bool "Raspberry Pi Sense HAT framebuffer"
+ depends on RT_MFD_RPI_SENSE
+ default n
diff --git a/bsp/raspberry-pi/dm/graphic/framebuffer/SConscript b/bsp/raspberry-pi/dm/graphic/framebuffer/SConscript
new file mode 100755
index 0000000000..d1329b7f90
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/framebuffer/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_GRAPHIC_FB_BCM2708']):
+ src += ['fb-bcm2708.c']
+
+if GetDepend(['RT_GRAPHIC_FB_RPISENSE']):
+ src += ['fb-rpisense.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/graphic/framebuffer/fb-bcm2708.c b/bsp/raspberry-pi/dm/graphic/framebuffer/fb-bcm2708.c
new file mode 100755
index 0000000000..90d282073c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/framebuffer/fb-bcm2708.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "fb.bcm2708"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+
+#define MAX_FRAMEBUFFERS 3
+#define FRAMEBUFFER_ALIGNMENT 4096
+
+struct fb_alloc_tags
+{
+ struct rpi_firmware_property_tag_header tag1;
+ rt_uint32_t xres, yres;
+
+ struct rpi_firmware_property_tag_header tag2;
+ rt_uint32_t xres_virtual, yres_virtual;
+
+ struct rpi_firmware_property_tag_header tag3;
+ rt_uint32_t bpp;
+
+ struct rpi_firmware_property_tag_header tag4;
+ rt_uint32_t xoffset, yoffset;
+
+ struct rpi_firmware_property_tag_header tag5;
+ rt_uint32_t base, screen_size;
+
+ struct rpi_firmware_property_tag_header tag6;
+ rt_uint32_t pitch;
+};
+
+struct vc4_display_settings
+{
+ rt_uint32_t display_num;
+ rt_uint32_t width;
+ rt_uint32_t height;
+ rt_uint32_t depth;
+ rt_uint32_t pitch;
+ rt_uint32_t virtual_width;
+ rt_uint32_t virtual_height;
+ rt_uint32_t virtual_width_offset;
+ rt_uint32_t virtual_height_offset;
+ rt_ubase_t fb_bus_address;
+};
+
+struct bcm2708fb;
+
+struct bcm2708fb_display
+{
+ struct rt_graphic_device parent;
+
+ struct bcm2708fb *fb;
+
+ void *framebuffer;
+ rt_ubase_t framebuffer_dma;
+ rt_size_t framebuffer_size;
+ rt_size_t stride;
+
+ struct vc4_display_settings display_settings;
+ struct { rt_uint32_t base, length; } gpu_mem;
+};
+
+struct bcm2708fb
+{
+ struct rpi_firmware *rpi_fw;
+
+ struct bcm2708fb_display displays[MAX_FRAMEBUFFERS];
+};
+
+static rt_err_t bcm2708fb_plane_fb_remap(struct rt_graphic_plane *plane,
+ rt_uint32_t mode, struct rt_device_rect_info *rect)
+{
+ struct bcm2708fb_display *display;
+
+ display = rt_container_of(plane->graphic, struct bcm2708fb_display, parent);
+
+ plane->line_length = display->stride;
+ plane->bits_per_pixel = rt_graphic_mode_bpp(mode);
+
+ plane->framebuffer = display->framebuffer;
+ plane->screen_len = display->framebuffer_size;
+ plane->framebuffer_len = display->framebuffer_size;
+
+ return RT_EOK;
+}
+
+static const struct rt_graphic_plane_ops bcm2708fb_plane_ops =
+{
+ .fb_remap = bcm2708fb_plane_fb_remap,
+};
+
+static rt_err_t bcm2708fb_dpms_switch(struct rt_graphic_device *gdev, rt_uint32_t dpms)
+{
+ rt_err_t err;
+ rt_uint32_t value;
+ struct bcm2708fb_display *display;
+
+ display = rt_container_of(gdev, struct bcm2708fb_display, parent);
+ value = display->display_settings.display_num;
+
+ if ((err = rpi_firmware_property(display->fb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, &value, sizeof(value))))
+ {
+ return err;
+ }
+
+ switch (dpms)
+ {
+ case RT_GRAPHIC_DPMS_ON:
+ value = 0;
+ break;
+
+ case RT_GRAPHIC_DPMS_STANDBY:
+ case RT_GRAPHIC_DPMS_SUSPEND:
+ case RT_GRAPHIC_DPMS_OFF:
+ value = 1;
+ break;
+ }
+
+ return rpi_firmware_property(display->fb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_BLANK, &value, sizeof(value));
+}
+
+static rt_err_t bcm2708fb_wait_vsync(struct rt_graphic_device *gdev)
+{
+ rt_err_t err;
+ rt_uint32_t value;
+ struct bcm2708fb_display *display;
+
+ display = rt_container_of(gdev, struct bcm2708fb_display, parent);
+ value = display->display_settings.display_num;
+
+ if ((err = rpi_firmware_property(display->fb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, &value, sizeof(value))))
+ {
+ return err;
+ }
+
+ return rpi_firmware_property(display->fb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, &value, sizeof(value));
+}
+
+static struct rt_graphic_device_ops bcm2708fb_ops =
+{
+ .dpms_switch = bcm2708fb_dpms_switch,
+ .wait_vsync = bcm2708fb_wait_vsync,
+};
+
+static rt_uint32_t bcm2708fb_modes[] =
+{
+ RTGRAPHIC_PIXEL_FORMAT_RGB565,
+ RTGRAPHIC_PIXEL_FORMAT_BGR888,
+ RTGRAPHIC_PIXEL_FORMAT_ABGR888,
+};
+
+static rt_err_t bcm2708fb_firmware_alloc(struct rpi_firmware *rpi_fw,
+ struct bcm2708fb_display *display, rt_uint32_t depth,
+ struct fb_alloc_tags *fbinfo)
+{
+ rt_err_t err;
+
+ rt_memset(fbinfo, 0, sizeof(*fbinfo));
+
+ fbinfo->tag1 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT, 8, 0,
+ };
+ fbinfo->xres = display->display_settings.width;
+ fbinfo->yres = display->display_settings.height;
+ fbinfo->tag2 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT, 8, 0,
+ };
+ fbinfo->xres_virtual = display->display_settings.virtual_width;
+ fbinfo->yres_virtual = display->display_settings.virtual_height;
+ fbinfo->tag3 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, 4, 0,
+ };
+ fbinfo->bpp = depth;
+ fbinfo->tag4 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, 8, 0,
+ };
+ fbinfo->xoffset = display->display_settings.virtual_width_offset;
+ fbinfo->yoffset = display->display_settings.virtual_height_offset;
+ fbinfo->tag5 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, 8, 0,
+ };
+ fbinfo->base = FRAMEBUFFER_ALIGNMENT;
+ fbinfo->tag6 = (struct rpi_firmware_property_tag_header)
+ {
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, 4, 0,
+ };
+
+ err = rpi_firmware_property_list(rpi_fw, fbinfo, sizeof(*fbinfo));
+
+ if (!err && (!fbinfo->base || !fbinfo->screen_size || !fbinfo->pitch))
+ {
+ err = -RT_ENOMEM;
+ }
+
+ if (!err && (fbinfo->bpp != depth ||
+ fbinfo->pitch < (fbinfo->xres_virtual * depth) / 8))
+ {
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+static rt_err_t bcm2708fb_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t num_displays;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct { rt_uint32_t base, length; } gpu_mem;
+ struct bcm2708fb *bfb = rt_calloc(1, sizeof(*bfb));
+
+ if (!bfb)
+ {
+ LOG_E("No memory for framebuffer state");
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ LOG_E("Missing firmware phandle");
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ bfb->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!bfb->rpi_fw)
+ {
+ LOG_E("Raspberry Pi firmware is unavailable");
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ err = rpi_firmware_property(bfb->rpi_fw, RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
+ &num_displays, sizeof(num_displays));
+
+ if (err)
+ {
+ LOG_E("GET_NUM_DISPLAYS failed: %s", rt_strerror(err));
+ goto _fail;
+ }
+
+ if (num_displays == 0)
+ {
+ LOG_E("Firmware reported no displays");
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ num_displays = rt_min_t(rt_uint32_t, num_displays, MAX_FRAMEBUFFERS);
+ LOG_I("Firmware reported %u display(s)", num_displays);
+
+ rpi_firmware_property(bfb->rpi_fw, RPI_FIRMWARE_GET_VC_MEMORY,
+ &gpu_mem, sizeof(gpu_mem));
+
+ rt_uint32_t num_registered = 0;
+
+ for (int i = 0; i < num_displays; ++i)
+ {
+ rt_uint32_t midx, value, requested_depth, effective_depth, stride_width;
+ struct fb_alloc_tags fbinfo;
+ struct bcm2708fb_display *display = &bfb->displays[i];
+
+ display->display_settings.display_num = i;
+
+ err = rpi_firmware_property(bfb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS,
+ &display->display_settings, GET_DISPLAY_SETTINGS_PAYLOAD_SIZE);
+
+ if (err)
+ {
+ goto _display_fail;
+ }
+
+ if (!display->display_settings.width)
+ {
+ display->display_settings.width = 800;
+ display->display_settings.height = 480;
+ display->display_settings.depth = 32;
+ }
+
+ if (!display->display_settings.virtual_width)
+ {
+ display->display_settings.virtual_width = display->display_settings.width;
+ }
+
+ if (!display->display_settings.virtual_height)
+ {
+ display->display_settings.virtual_height = display->display_settings.height;
+ }
+
+ requested_depth = display->display_settings.depth;
+ value = i;
+
+ if ((err = rpi_firmware_property(bfb->rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM, &value, sizeof(value))))
+ {
+ goto _display_fail;
+ }
+
+ err = bcm2708fb_firmware_alloc(bfb->rpi_fw, display,
+ requested_depth, &fbinfo);
+
+ if (err && requested_depth != 16)
+ {
+ LOG_W("Display(%d) preferred %ubpp unavailable, trying 16bpp",
+ i, requested_depth);
+ requested_depth = 16;
+ err = bcm2708fb_firmware_alloc(bfb->rpi_fw, display,
+ requested_depth, &fbinfo);
+ }
+
+ if (err)
+ {
+ LOG_E("Display(%d) firmware allocation failed: base=0x%08x size=%u pitch=%u",
+ i, fbinfo.base, fbinfo.screen_size, fbinfo.pitch);
+ goto _display_fail;
+ }
+
+ fbinfo.base &= ~0xc0000000;
+ display->framebuffer_dma = fbinfo.base;
+ display->framebuffer_size = fbinfo.screen_size;
+ display->stride = fbinfo.pitch;
+ display->framebuffer = rt_ioremap_wt(
+ (void *)display->framebuffer_dma, display->framebuffer_size);
+
+ if (!display->framebuffer)
+ {
+ err = -RT_ENOMEM;
+ goto _display_fail;
+ }
+
+ LOG_I("Display(%d) firmware framebuffer: bpp=%u pitch=%u size=%u",
+ i, fbinfo.bpp, fbinfo.pitch, fbinfo.screen_size);
+
+ if (!fbinfo.bpp || !fbinfo.pitch)
+ {
+ err = -RT_EINVAL;
+ goto _display_fail;
+ }
+
+ effective_depth = fbinfo.bpp;
+ stride_width = fbinfo.xres_virtual ? fbinfo.xres_virtual :
+ display->display_settings.virtual_width;
+
+ /* Pi 5 firmware can report stale bpp while returning the active pitch. */
+ if (stride_width && fbinfo.pitch != (stride_width * fbinfo.bpp) / 8)
+ {
+ if (fbinfo.pitch == stride_width * 2)
+ {
+ effective_depth = 16;
+ }
+ else if (fbinfo.pitch == stride_width * 3)
+ {
+ effective_depth = 24;
+ }
+ else if (fbinfo.pitch == stride_width * 4)
+ {
+ effective_depth = 32;
+ }
+
+ if (effective_depth != fbinfo.bpp)
+ {
+ LOG_W("Display(%d) inconsistent format: bpp=%u pitch=%u width=%u; using %ubpp",
+ i, fbinfo.bpp, fbinfo.pitch, stride_width, effective_depth);
+ }
+ }
+
+ display->display_settings.depth = effective_depth;
+ display->stride = fbinfo.pitch;
+
+ if (requested_depth != effective_depth)
+ {
+ LOG_W("Display(%d) depth adjusted by firmware: %u -> %u",
+ i, requested_depth, effective_depth);
+ }
+
+ switch (display->display_settings.depth)
+ {
+ case 16: midx = 0; break;
+ case 24: midx = 1; break;
+ case 32: midx = 2; break;
+ default:
+ err = -RT_EINVAL;
+ goto _display_fail;
+ }
+
+ display->fb = bfb;
+ display->gpu_mem.base = gpu_mem.base;
+ display->gpu_mem.length = gpu_mem.length;
+
+ display->parent.ops = &bcm2708fb_ops;
+
+ rt_memset(display->framebuffer, 0, display->framebuffer_size);
+
+ if ((err = rt_graphic_device_simple_register(&display->parent,
+ display->display_settings.width, display->display_settings.height, 0,
+ &bcm2708fb_plane_ops, &bcm2708fb_modes[midx], 1)))
+ {
+ goto _display_fail;
+ }
+
+ LOG_I("Display(%d) registered: %ux%u@%u, pitch=%u, fb=%p",
+ i, display->display_settings.width, display->display_settings.height,
+ display->display_settings.depth, (rt_uint32_t)display->stride,
+ display->framebuffer);
+
+ num_registered++;
+ continue;
+
+ _display_fail:
+ if (display->framebuffer)
+ {
+ rt_iounmap(display->framebuffer);
+ }
+
+ display->display_settings.display_num = MAX_FRAMEBUFFERS;
+ LOG_W("Display(%d) init error = %s", i, rt_strerror(err));
+ }
+
+ if (!num_registered)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ pdev->parent.user_data = bfb;
+
+ return RT_EOK;
+
+_fail:
+ if (bfb->rpi_fw)
+ {
+ rpi_firmware_put(bfb->rpi_fw);
+ }
+
+ rt_free(bfb);
+
+ return err;
+}
+
+static rt_err_t bcm2708fb_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2708fb *bfb = dev->user_data;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(bfb->displays); ++i)
+ {
+ struct bcm2708fb_display *display = &bfb->displays[i];
+
+ if (display->display_settings.display_num == MAX_FRAMEBUFFERS)
+ {
+ continue;
+ }
+
+ rt_graphic_device_simple_unregister(&display->parent);
+
+ rt_iounmap(display->framebuffer);
+ }
+
+ rpi_firmware_put(bfb->rpi_fw);
+
+ rt_free(bfb);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2708fb_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2708-fb" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2708fb_driver =
+{
+ .name = "bcm2708-framebuffer",
+ .ids = bcm2708fb_ofw_ids,
+
+ .probe = bcm2708fb_probe,
+ .remove = bcm2708fb_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2708fb_driver);
diff --git a/bsp/raspberry-pi/dm/graphic/framebuffer/fb-rpisense.c b/bsp/raspberry-pi/dm/graphic/framebuffer/fb-rpisense.c
new file mode 100755
index 0000000000..6640a9c31f
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/framebuffer/fb-rpisense.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <mmu.h>
+#include <rpi-sense.h>
+
+struct rpisense_framebuffer
+{
+ struct rt_graphic_device parent;
+
+ struct rpisense *rpisense;
+
+ rt_uint8_t *gamma;
+
+ rt_uint8_t vram[128];
+ rt_uint8_t vram_work[193];
+ rt_uint8_t gamma_user[32];
+};
+
+#define raw_to_rpisense_framebuffer(raw) rt_container_of(raw, struct rpisense_framebuffer, parent)
+
+static rt_uint8_t gamma_default[32] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x11,
+ 0x12, 0x14, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f,
+};
+
+static rt_uint8_t gamma_low[32] =
+{
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
+ 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06,
+ 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0a,
+};
+
+static void rpisense_fb_deferred_io(struct rpisense_framebuffer *rpisense_fb)
+{
+ rt_uint8_t *gamma = rpisense_fb->gamma;
+ rt_uint8_t *vram_work = rpisense_fb->vram_work;
+ rt_uint16_t *vram = (rt_uint16_t *)rpisense_fb->vram;
+ struct rt_graphic_plane *primary_plane = rpisense_fb->parent.primary_plane;
+
+ vram_work[0] = 0;
+
+ for (int y = 0; y < primary_plane->height; ++y)
+ {
+ for (int x = 0; x < primary_plane->width; ++x)
+ {
+ vram_work[(y * 24) + x + 1] = gamma[(vram[(y * 8) + x] >> 11) & 0x1f];
+ vram_work[(y * 24) + (x + 8) + 1] = gamma[(vram[(y * 8) + x] >> 6) & 0x1f];
+ vram_work[(y * 24) + (x + 16) + 1] = gamma[(vram[(y * 8) + x]) & 0x1f];
+ }
+ }
+
+ rpisense_block_write(rpisense_fb->rpisense,
+ (const void *)vram_work, sizeof(rpisense_fb->vram_work));
+}
+
+static rt_err_t rpisense_fb_plane_update(struct rt_graphic_plane *plane,
+ struct rt_device_rect_info *rect)
+{
+ struct rpisense_framebuffer *rpisense_fb = raw_to_rpisense_framebuffer(plane->graphic);
+
+ rpisense_fb_deferred_io(rpisense_fb);
+
+ return RT_EOK;
+}
+
+static rt_err_t rpisense_fb_plane_fb_remap(struct rt_graphic_plane *plane,
+ rt_uint32_t mode, struct rt_device_rect_info *rect)
+{
+ struct rpisense_framebuffer *rpisense_fb = raw_to_rpisense_framebuffer(plane->graphic);
+
+ plane->line_length = 16;
+ plane->bits_per_pixel = 16;
+
+ plane->framebuffer = rpisense_fb->vram;
+ plane->screen_len = sizeof(rpisense_fb->vram);
+ plane->framebuffer_len = sizeof(rpisense_fb->vram);
+
+ return RT_EOK;
+}
+
+static const struct rt_graphic_plane_ops rpisense_fb_plane_ops =
+{
+ .update = rpisense_fb_plane_update,
+ .fb_remap = rpisense_fb_plane_fb_remap,
+};
+
+static rt_err_t rpisense_fb_wait_vsync(struct rt_graphic_device *gdev)
+{
+ struct rpisense_framebuffer *rpisense_fb = raw_to_rpisense_framebuffer(gdev);
+
+ rpisense_fb_deferred_io(rpisense_fb);
+
+ return RT_EOK;
+}
+
+static rt_err_t rpisense_fb_control(struct rt_graphic_device *gdev, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct rpisense_framebuffer *rpisense_fb = raw_to_rpisense_framebuffer(gdev);
+
+ switch (cmd)
+ {
+ case SENSEFB_FBIOGET_GAMMA:
+ rt_memcpy(args, rpisense_fb->gamma, sizeof(rpisense_fb->gamma_user));
+ break;
+
+ case SENSEFB_FBIOSET_GAMMA:
+ rt_memcpy(rpisense_fb->gamma_user, args, sizeof(rpisense_fb->gamma_user));
+ rpisense_fb->gamma = rpisense_fb->gamma_user;
+ break;
+
+ case SENSEFB_FBIORESET_GAMMA:
+ switch ((rt_ubase_t)args)
+ {
+ case 0:
+ rpisense_fb->gamma = gamma_default;
+ break;
+
+ case 1:
+ rpisense_fb->gamma = gamma_low;
+ break;
+
+ case 2:
+ rpisense_fb->gamma = rpisense_fb->gamma_user;
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+ break;
+
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+
+ return err;
+}
+
+static const struct rt_graphic_device_ops rpisense_fb_ops =
+{
+ .wait_vsync = rpisense_fb_wait_vsync,
+ .control = rpisense_fb_control,
+};
+
+static rt_uint32_t rpisense_fb_modes[] =
+{
+ RTGRAPHIC_PIXEL_FORMAT_RGB565,
+};
+
+static rt_err_t rpisense_fb_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rpisense *rpisense = pdev->priv;
+ struct rpisense_framebuffer *rpisense_fb = rt_calloc(1, sizeof(*rpisense_fb));
+
+ if (!rpisense_fb)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rpisense_fb->rpisense = rpisense;
+ rpisense_fb->gamma = gamma_default;
+ rpisense_fb->parent.ops = &rpisense_fb_ops;
+
+ if ((err = rt_graphic_device_simple_register(&rpisense_fb->parent,
+ 8, 8, 0, &rpisense_fb_plane_ops,
+ rpisense_fb_modes, RT_ARRAY_SIZE(rpisense_fb_modes))))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ rt_free(rpisense_fb);
+
+ return err;
+}
+
+static rt_err_t rpisense_fb_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+
+ rt_device_unregister(&pdev->parent);
+
+ rt_free(rt_container_of(dev->user_data, struct rpisense_framebuffer, parent));
+
+ return RT_EOK;
+}
+
+static struct rt_platform_driver rpisense_fb_driver =
+{
+ .name = "rpi-sense-fb",
+
+ .probe = rpisense_fb_probe,
+ .remove = rpisense_fb_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpisense_fb_driver);
diff --git a/bsp/raspberry-pi/dm/graphic/logo/Kconfig b/bsp/raspberry-pi/dm/graphic/logo/Kconfig
new file mode 100755
index 0000000000..24d25996fe
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/logo/Kconfig
@@ -0,0 +1,2 @@
+config RT_GRAPHIC_LOGO_RASPI_CLUT224
+ bool "Standard 224-color Raspberry PI logo"
diff --git a/bsp/raspberry-pi/dm/graphic/logo/Kconfig.path b/bsp/raspberry-pi/dm/graphic/logo/Kconfig.path
new file mode 100755
index 0000000000..ff6fdbc075
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/logo/Kconfig.path
@@ -0,0 +1,5 @@
+if RT_GRAPHIC_LOGO_RASPI_CLUT224
+ config RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH
+ string
+ default "../dm/graphic/logo/logo-raspi-clut224.ppm"
+endif
diff --git a/bsp/raspberry-pi/dm/graphic/logo/logo-raspi-clut224.ppm b/bsp/raspberry-pi/dm/graphic/logo/logo-raspi-clut224.ppm
new file mode 100755
index 0000000000..7626beb6a5
--- /dev/null
+++ b/bsp/raspberry-pi/dm/graphic/logo/logo-raspi-clut224.ppm
@@ -0,0 +1,883 @@
+P3
+63 80
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0
+0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
+0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+10 15 3 2 3 1 12 18 4 42 61 14 19 27 6 11 16 4
+38 55 13 10 15 3 3 4 1 10 15 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 1
+12 18 4 1 1 0 23 34 8 31 45 11 10 15 3 32 47 11
+34 49 12 3 4 1 3 4 1 3 4 1 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 10 15 3 29 42 10 26 37 9 12 18 4
+55 80 19 81 118 28 55 80 19 92 132 31 106 153 36 69 100 23
+100 144 34 80 116 27 42 61 14 81 118 28 23 34 8 27 40 9
+15 21 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 1 1 0 29 42 10 15 21 5 50 72 17
+74 107 25 45 64 15 102 148 35 80 116 27 84 121 28 111 160 38
+69 100 23 65 94 22 81 118 28 29 42 10 17 25 6 29 42 10
+23 34 8 2 3 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 4 1
+15 21 5 15 21 5 34 49 12 101 146 34 111 161 38 97 141 33
+97 141 33 119 172 41 117 170 40 116 167 40 118 170 40 118 171 40
+117 169 40 118 170 40 111 160 38 118 170 40 96 138 32 89 128 30
+81 118 28 11 16 4 10 15 3 1 1 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+3 4 1 3 4 1 34 49 12 101 146 34 79 115 27 111 160 38
+114 165 39 113 163 39 118 170 40 117 169 40 118 171 40 117 169 40
+116 167 40 119 172 41 113 163 39 92 132 31 105 151 36 113 163 39
+75 109 26 19 27 6 16 23 5 11 16 4 0 1 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 15 3
+80 116 27 106 153 36 105 151 36 114 165 39 118 170 40 118 171 40
+118 171 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 170 40 117 169 40 118 170 40 118 170 40
+117 170 40 75 109 26 75 109 26 34 49 12 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 4 1
+64 92 22 65 94 22 100 144 34 118 171 40 118 170 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 118 171 41 118 170 40 117 169 40
+109 158 37 105 151 36 104 150 35 47 69 16 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+42 61 14 115 167 39 118 170 40 117 169 40 117 169 40 117 169 40
+117 170 40 117 170 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 118 170 40 96 138 32 17 25 6 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 69 16
+114 165 39 117 168 40 117 170 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 118 170 40 117 169 40 117 169 40 117 169 40
+117 170 40 119 172 41 96 138 32 12 18 4 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 15 3
+32 47 11 105 151 36 118 170 40 117 169 40 117 169 40 116 168 40
+109 157 37 111 160 38 117 169 40 118 171 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 118 171 40 69 100 23 2 3 1
+0 0 0 0 0 0 0 0 0 0 0 0 19 27 6 101 146 34
+118 171 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 170 40
+118 171 40 115 166 39 107 154 36 111 161 38 117 169 40 117 169 40
+117 169 40 118 171 40 75 109 26 19 27 6 2 3 1 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 23 5
+89 128 30 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+111 160 38 92 132 31 79 115 27 96 138 32 115 166 39 119 171 41
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 118 170 40 109 157 37 26 37 9
+0 0 0 0 0 0 0 0 0 0 0 0 64 92 22 118 171 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 118 170 40 118 171 40 109 157 37
+89 128 30 81 118 28 100 144 34 115 166 39 117 169 40 117 169 40
+117 169 40 117 170 40 113 163 39 60 86 20 1 1 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+27 40 9 96 138 32 118 170 40 117 169 40 117 169 40 117 169 40
+117 170 40 117 169 40 101 146 34 67 96 23 55 80 19 84 121 28
+113 163 39 119 171 41 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 119 171 41 65 94 22
+0 0 0 0 0 0 0 0 0 15 21 5 101 146 34 118 171 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 118 170 40 118 171 40 104 150 35 69 100 23 53 76 18
+81 118 28 111 160 38 118 170 40 117 169 40 117 169 40 117 169 40
+117 169 40 114 165 39 69 100 23 10 15 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+31 45 11 77 111 26 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 118 170 40 116 168 40 92 132 31 47 69 16
+38 55 13 81 118 28 113 163 39 119 171 41 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 118 171 41 92 132 31
+10 15 3 0 0 0 0 0 0 36 52 12 115 166 39 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 118 170 40
+118 171 40 102 148 35 64 92 22 34 49 12 65 94 22 106 153 36
+118 171 40 117 170 40 117 169 40 117 169 40 117 169 40 117 169 40
+118 170 40 107 154 36 55 80 19 15 21 5 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+29 42 10 101 146 34 118 171 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 118 171 40 113 163 39
+75 109 26 27 40 9 36 52 12 89 128 30 116 167 40 118 171 40
+117 169 40 117 169 40 117 169 40 117 169 40 118 170 40 104 150 35
+16 23 5 0 0 0 0 0 0 53 76 18 118 171 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 119 171 41 109 157 37
+67 96 23 23 34 8 42 61 14 96 138 32 118 170 40 118 170 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 74 107 25 10 15 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 31 45 11 101 146 34 118 170 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+119 171 41 102 148 35 47 69 16 14 20 5 50 72 17 102 148 35
+118 171 40 117 169 40 117 169 40 117 169 40 118 170 40 102 148 35
+15 21 5 0 0 0 0 0 0 50 72 17 118 170 40 117 169 40
+117 169 40 117 169 40 118 170 40 116 167 40 84 121 28 27 40 9
+19 27 6 74 107 25 114 165 39 118 171 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 75 109 26 10 15 4 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 38 55 13 102 148 35 118 171 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 118 170 40 115 167 39 77 111 26 17 25 6 19 27 6
+77 111 26 115 166 39 118 170 40 117 169 40 119 172 41 81 118 28
+3 4 1 0 0 0 0 0 0 27 40 9 111 160 38 118 170 40
+117 169 40 118 171 40 105 151 36 50 72 17 10 15 3 38 55 13
+100 144 34 118 171 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 79 115 27 15 21 5 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 10 15 3 64 92 22 111 160 38 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 118 171 40 96 138 32 32 47 11
+3 4 1 50 72 17 107 154 36 120 173 41 105 151 36 31 45 11
+0 0 0 0 0 0 0 0 0 3 4 1 65 94 22 117 169 40
+118 170 40 89 128 30 26 37 9 3 4 1 60 86 20 111 161 38
+118 171 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+97 141 33 36 52 12 1 1 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 14 20 5 75 109 26 117 168 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 118 171 40 107 154 36
+45 64 15 2 3 1 31 45 11 75 109 26 32 47 11 0 1 0
+0 0 0 0 0 0 0 0 0 0 0 0 10 15 3 55 80 19
+65 94 22 11 16 4 11 16 4 75 109 26 116 168 40 118 170 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 118 170 40 107 154 36
+47 69 16 3 4 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 12 18 4 69 100 23 111 161 38 118 171 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 118 170 40
+111 160 38 50 72 17 2 3 1 2 3 1 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
+1 1 0 12 18 4 81 118 28 118 170 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 170 40 118 171 40 101 146 34
+42 61 14 2 3 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 3 4 1 36 52 12 89 128 30
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+118 171 41 101 146 34 14 20 5 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 47 69 16 118 170 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 170 40 111 160 38 69 100 23 19 27 6
+0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 11 16 4 69 100 23
+115 167 39 119 172 41 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+119 172 41 75 109 26 3 4 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 23 34 8 106 153 36 118 170 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+117 169 40 118 170 40 119 172 41 105 151 36 42 61 14 2 3 1
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 15 21 5
+45 64 15 80 116 27 114 165 39 118 170 40 117 169 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 119 172 41
+97 141 33 20 30 7 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 1 1 0 53 76 18 114 165 39 118 171 40 117 169 40
+117 169 40 117 169 40 117 169 40 117 169 40 117 169 40 117 169 40
+118 171 40 104 150 35 64 92 22 31 45 11 10 15 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 36 52 12 97 141 33 109 158 37 113 163 39 116 168 40
+117 169 40 117 170 40 118 170 40 119 172 41 115 167 39 84 121 28
+23 34 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 3 4 1 50 72 17 102 148 35 118 171 40
+119 171 41 118 170 40 117 169 40 117 169 40 115 166 39 111 161 38
+109 157 37 79 115 27 12 18 4 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 3 4 1 15 21 5 23 34 8 45 64 15 106 153 36
+116 167 40 111 160 38 101 146 34 79 115 27 42 61 14 10 15 3
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 1 1 0 20 30 7 60 86 20
+89 128 30 106 153 36 113 163 39 117 169 40 84 121 28 29 42 10
+19 27 6 10 15 3 2 3 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 16 23 5 38 55 13
+36 52 12 26 37 9 12 18 4 2 3 1 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 1 0 0 19 2 7 52 5 18
+78 7 27 88 8 31 81 7 29 56 5 19 25 2 9 3 0 1
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+3 4 1 19 27 6 31 45 11 38 55 13 32 47 11 3 4 1
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 1
+9 0 3 12 1 4 9 0 3 4 0 1 0 0 0 0 0 0
+0 0 0 0 0 0 28 3 10 99 9 35 156 14 55 182 16 64
+189 17 66 190 17 67 189 17 66 184 17 65 166 15 58 118 13 41
+45 4 16 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 11 1 4 52 5 18 101 9 35 134 12 47
+151 14 53 154 14 54 151 14 53 113 10 40 11 1 4 0 0 0
+3 0 1 67 6 24 159 14 56 190 17 67 190 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 191 17 67
+174 16 61 101 9 35 14 1 5 0 0 0 35 3 12 108 10 38
+122 11 43 122 11 43 112 10 39 87 8 30 50 5 17 13 1 5
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+3 0 1 56 5 19 141 13 49 182 16 64 191 17 67 191 17 67
+190 17 67 190 17 67 191 17 67 113 10 40 3 0 1 1 0 0
+79 7 28 180 16 63 190 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+189 17 66 188 17 66 122 11 43 11 1 4 41 4 14 176 16 62
+191 17 67 191 17 67 191 17 67 190 17 67 181 16 63 146 13 51
+75 7 26 10 1 4 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 1 2
+90 8 32 178 16 62 191 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 190 17 67 141 13 49 22 2 8 0 0 0 41 4 14
+173 16 61 190 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 88 8 31 1 0 0 89 8 31
+185 17 65 189 17 66 188 17 66 188 17 66 189 17 66 191 17 67
+186 17 65 124 11 43 25 2 9 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 89 8 31
+184 17 65 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+190 17 67 151 14 53 34 3 12 0 0 0 0 0 0 79 7 28
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 191 17 67 146 13 51 9 1 3 7 1 2
+108 10 38 187 17 66 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 190 17 67 141 13 49 22 2 8 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 52 5 18 176 16 62
+189 17 66 188 17 66 188 17 66 188 17 66 188 17 66 190 17 67
+151 14 53 38 3 13 0 0 0 0 0 0 0 0 0 50 5 17
+180 16 63 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 191 17 67 141 13 49 7 1 3 0 0 0
+11 1 4 112 10 39 187 17 66 189 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 190 17 67 113 10 40 5 0 2 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 7 1 3 132 12 46 191 17 67
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 146 13 51
+35 3 12 0 0 0 0 0 0 0 0 0 0 0 0 5 0 2
+101 9 35 185 17 65 190 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 190 17 67 180 16 63 67 6 24 0 0 0 0 0 0
+0 0 0 11 1 4 108 10 38 186 17 65 189 17 66 188 17 66
+188 17 66 188 17 66 189 17 66 180 16 63 56 5 19 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 44 4 15 177 16 62 189 17 66
+188 17 66 188 17 66 189 17 66 189 17 66 134 12 47 28 3 10
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+8 1 3 79 7 28 159 14 56 188 17 66 191 17 67 190 17 67
+189 17 66 189 17 66 189 17 66 189 17 66 190 17 67 191 17 67
+188 17 66 158 14 55 72 7 25 4 0 1 0 0 0 0 0 0
+0 0 0 0 0 0 8 1 3 95 9 33 182 16 64 189 17 67
+188 17 66 188 17 66 188 17 66 191 17 67 122 11 43 3 0 1
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 88 8 31 190 17 67 188 17 66
+188 17 66 189 17 66 185 17 65 113 10 40 18 2 6 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 1 0 0 24 2 8 77 7 27 124 11 43 154 14 54
+168 15 59 173 16 61 173 16 61 168 15 59 154 14 54 124 11 43
+77 7 27 22 2 8 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 5 0 2 77 7 27 173 16 61
+190 17 67 188 17 66 188 17 66 190 17 67 164 15 57 23 2 8
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 1 0 0 118 13 41 191 17 67 188 17 66
+190 17 67 174 16 61 87 8 30 8 1 3 0 0 0 0 0 0
+0 0 0 0 0 0 10 1 4 29 3 10 40 4 14 36 3 13
+18 2 6 2 0 1 0 0 0 0 0 0 3 0 1 14 1 5
+26 2 9 33 3 11 32 3 11 25 2 9 13 1 5 3 0 1
+0 0 0 14 1 5 56 5 19 95 9 33 109 10 38 101 9 35
+77 7 27 35 3 12 5 0 2 0 0 0 1 0 0 56 5 19
+156 14 55 190 17 67 188 17 66 188 17 66 182 16 64 50 5 17
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 5 0 2 134 12 47 191 17 67 189 17 66
+151 14 53 52 5 18 2 0 1 0 0 0 0 0 0 1 0 0
+28 3 10 90 8 32 146 13 51 170 15 60 178 16 62 174 16 61
+158 14 55 112 10 39 40 4 14 1 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 1
+56 5 19 146 13 51 183 17 64 191 17 67 191 17 67 191 17 67
+188 17 66 173 16 61 122 11 43 41 4 14 1 0 0 0 0 0
+30 3 10 124 11 43 185 17 65 190 17 67 187 17 66 67 6 24
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 6 1 2 134 12 47 168 15 59 99 9 35
+21 2 7 0 0 0 0 0 0 0 0 0 6 1 2 77 7 27
+162 15 57 190 17 67 191 17 67 189 17 66 189 17 66 189 17 66
+190 17 67 191 17 67 169 15 59 75 7 26 3 0 1 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 79 7 28
+178 16 62 191 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 191 17 67 170 15 60 79 7 28 5 0 2
+0 0 0 10 1 3 78 7 27 159 14 56 188 17 66 75 7 26
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 1 0 0 35 3 12 29 3 10 2 0 1
+0 0 0 0 0 0 0 0 0 9 1 3 101 9 35 183 17 64
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 190 17 67 178 16 63 67 6 23 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 52 5 18 174 16 61
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 190 17 67 182 16 64 89 8 31
+4 0 1 0 0 0 0 0 0 25 2 9 73 7 26 31 3 11
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 4 0 1 98 9 34 187 17 66 189 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 190 17 67 158 14 55 25 2 9
+0 0 0 0 0 0 0 0 0 8 1 3 134 12 47 191 17 67
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 189 17 66 180 16 63
+68 6 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 6 1 2 19 2 7 3 0 1 0 0 0 0 0 0
+0 0 0 0 0 0 65 6 23 180 16 63 189 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 189 17 66 83 8 29
+0 0 0 0 0 0 0 0 0 41 4 14 177 16 62 189 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 190 17 67
+159 14 56 28 3 10 0 0 0 0 0 0 0 0 0 23 2 8
+41 4 14 5 0 2 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+23 2 8 113 10 40 159 14 56 65 6 23 0 0 0 0 0 0
+0 0 0 16 1 6 146 13 51 191 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 191 17 67 132 12 46
+5 0 2 0 0 0 0 0 0 77 7 27 189 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+190 17 67 98 9 34 0 0 0 0 0 0 12 1 4 134 12 47
+178 16 63 108 10 38 16 1 6 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 3 10
+141 13 49 190 17 67 191 17 67 134 12 47 6 1 2 0 0 0
+0 0 0 68 6 24 186 17 65 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 156 14 55
+14 1 5 0 0 0 0 0 0 98 9 34 191 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+190 17 67 156 14 55 19 2 7 0 0 0 47 4 16 181 16 63
+190 17 67 189 17 66 126 14 44 17 2 6 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 16 1 6 134 12 47
+191 17 67 188 17 66 190 17 67 162 15 57 19 2 7 0 0 0
+3 0 1 123 11 43 191 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 163 15 57
+20 2 7 0 0 0 0 0 0 101 9 35 191 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 182 16 64 52 5 18 0 0 0 73 7 26 188 17 66
+188 17 66 188 17 66 189 17 66 109 10 38 5 0 2 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 95 9 33 189 17 66
+188 17 66 188 17 66 189 17 66 171 15 60 29 3 10 0 0 0
+16 1 6 156 14 55 190 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 158 14 55
+17 2 6 0 0 0 0 0 0 85 8 30 190 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 81 7 29 0 0 0 85 8 30 190 17 67
+188 17 66 188 17 66 189 17 66 180 16 63 56 5 19 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 25 2 9 162 15 57 190 17 67
+188 17 66 188 17 66 189 17 66 173 16 61 31 3 11 0 0 0
+30 3 10 171 15 60 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 191 17 67 141 13 49
+7 1 2 0 0 0 0 0 0 56 5 19 183 17 64 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 191 17 67 98 9 34 0 0 0 88 8 31 190 17 67
+188 17 66 188 17 66 188 17 66 191 17 67 124 11 43 5 0 2
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 68 6 24 187 17 66 188 17 66
+188 17 66 188 17 66 189 17 66 170 15 60 28 3 10 0 0 0
+34 3 12 174 16 61 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 191 17 67 101 9 35
+0 0 0 0 0 0 0 0 0 21 2 7 159 14 56 190 17 67
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 191 17 67 98 9 34 0 0 0 81 7 29 189 17 66
+188 17 66 188 17 66 188 17 66 189 17 66 168 15 59 28 3 10
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 109 10 38 191 17 67 188 17 66
+188 17 66 188 17 66 190 17 67 163 15 57 21 2 7 0 0 0
+26 2 9 168 15 59 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 189 17 66 180 16 63 47 4 16
+0 0 0 0 0 0 0 0 0 0 0 0 108 10 38 190 17 67
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 78 7 27 0 0 0 68 6 24 187 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 183 17 64 56 5 19
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 3 0 1 131 12 46 191 17 67 188 17 66
+188 17 66 188 17 66 190 17 67 151 14 53 12 1 4 0 0 0
+11 1 4 146 13 51 190 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 191 17 67 126 14 44 7 1 2
+0 0 0 0 0 0 0 0 0 0 0 0 32 3 11 164 15 58
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+189 17 66 178 16 62 44 4 15 0 0 0 50 5 17 182 16 64
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 72 7 25
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 5 0 2 134 12 47 191 17 67 188 17 66
+188 17 66 188 17 66 191 17 67 131 12 46 3 0 1 0 0 0
+0 0 0 101 9 35 190 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 190 17 67 170 15 60 44 4 15 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 7 27
+183 17 64 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+191 17 67 134 12 47 9 1 3 0 0 0 31 3 11 171 15 60
+189 17 66 188 17 66 188 17 66 188 17 66 188 17 66 72 7 25
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 2 0 1 124 11 43 191 17 67 188 17 66
+188 17 66 188 17 66 191 17 67 101 9 35 0 0 0 0 0 0
+0 0 0 35 3 12 168 15 59 190 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 182 16 64 77 7 27 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 1 2
+99 9 35 185 17 65 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 189 17 66
+177 16 62 56 5 19 0 0 0 0 0 0 13 1 5 151 14 53
+190 17 67 188 17 66 188 17 66 188 17 66 185 17 65 56 5 19
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 99 9 35 191 17 67 188 17 66
+188 17 66 188 17 66 186 17 65 65 6 23 0 0 0 0 0 0
+0 0 0 0 0 0 79 7 28 182 16 64 190 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+191 17 67 177 16 62 83 8 29 4 0 1 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+8 1 3 89 8 31 175 16 62 191 17 67 189 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 181 16 63
+85 8 30 3 0 1 0 0 0 0 0 0 1 0 0 118 13 41
+191 17 67 188 17 66 188 17 66 189 17 66 173 16 61 34 3 12
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 56 5 19 183 17 64 188 17 66
+188 17 66 189 17 66 169 15 59 30 3 10 0 0 0 0 0 0
+0 0 0 0 0 0 5 0 2 83 8 29 173 16 61 191 17 67
+190 17 67 189 17 66 189 17 66 190 17 67 191 17 67 187 17 66
+151 14 53 56 5 19 3 0 1 0 0 0 16 1 6 50 5 17
+79 7 28 95 9 33 95 9 33 75 7 26 41 4 14 10 1 4
+0 0 0 2 0 1 50 5 17 132 12 46 178 16 62 190 17 67
+191 17 67 191 17 67 191 17 67 186 17 65 154 14 54 68 6 24
+4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 72 7 25
+187 17 66 188 17 66 188 17 66 191 17 67 141 13 49 9 1 3
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 14 1 5 151 14 53 190 17 67
+188 17 66 191 17 67 131 12 46 5 0 2 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 2 0 1 44 4 15 113 10 40
+156 14 55 173 16 61 174 16 61 164 15 58 134 12 47 77 7 27
+18 2 6 0 0 0 16 1 6 85 8 30 151 14 53 182 16 64
+189 17 66 191 17 67 190 17 67 188 17 66 177 16 62 141 13 49
+68 6 24 8 1 3 0 0 0 8 1 3 44 4 15 88 8 31
+113 10 40 122 11 43 108 10 38 67 6 24 20 2 7 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 3 10
+166 15 58 190 17 67 188 17 66 187 17 66 79 7 28 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 73 7 26 185 17 65
+189 17 66 184 17 65 65 6 23 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1
+17 2 6 32 3 11 34 3 12 22 2 8 6 1 2 0 0 0
+0 0 0 38 3 13 141 13 49 188 17 66 190 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 189 17 66 191 17 67
+184 17 65 122 11 43 21 2 7 0 0 0 0 0 0 0 0 0
+0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
+108 10 38 191 17 67 191 17 67 141 13 49 16 1 6 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 8 1 3 112 10 39
+186 17 65 124 11 43 10 1 4 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+36 3 13 156 14 55 191 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+189 17 66 190 17 67 134 12 47 18 2 6 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7 1 2 41 4 14 75 7 26 66 5 23 19 2 7
+26 2 9 144 13 50 154 14 54 40 4 14 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 1 5
+56 5 19 19 2 7 0 0 0 7 1 2 29 3 10 35 3 12
+19 2 7 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 1 5
+134 12 47 191 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 189 17 67 108 10 38 3 0 1 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
+40 4 14 124 11 43 177 16 62 188 17 66 187 17 66 144 13 50
+24 2 8 17 2 6 22 2 8 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 19 2 7 122 11 43 171 15 60 175 16 62
+159 14 56 112 10 39 40 4 14 2 0 1 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 7 25
+186 17 65 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 189 17 66 174 16 61 41 4 14 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 3 0 1 72 7 25
+168 15 59 191 17 67 189 17 66 188 17 66 188 17 66 190 17 67
+95 9 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 95 9 33 191 17 67 189 17 66 189 17 66
+190 17 67 191 17 67 171 15 60 90 8 32 12 1 4 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 5 0 2 132 12 46
+191 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 190 17 67 98 9 34 0 0 0
+0 0 0 0 0 0 0 0 0 5 0 2 88 8 31 180 16 63
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 191 17 67
+146 13 51 11 1 4 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 9 1 3 144 13 50 191 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 189 17 66 187 17 66 123 11 43 20 2 7
+0 0 0 0 0 0 0 0 0 0 0 0 21 2 7 163 15 57
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 191 17 67 134 12 47 5 0 2
+0 0 0 0 0 0 3 0 1 88 8 31 182 16 64 189 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 189 17 66
+171 15 60 31 3 11 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 20 2 7 162 15 57 190 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 132 12 46
+20 2 7 0 0 0 0 0 0 0 0 0 32 3 11 173 16 61
+189 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 190 17 67 151 14 53 12 1 4
+0 0 0 0 0 0 72 7 25 180 16 63 189 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+181 16 63 47 4 16 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 21 2 7 163 15 57 190 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 190 17 67
+122 11 43 9 1 3 0 0 0 0 0 0 30 3 10 171 15 60
+189 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 190 17 67 146 13 51 10 1 4
+0 0 0 38 3 13 166 15 58 190 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+183 17 64 52 5 18 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 13 1 5 154 14 54 190 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+186 17 65 79 7 28 0 0 0 0 0 0 14 1 5 156 14 54
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 191 17 67 124 11 43 2 0 1
+5 0 2 122 11 43 191 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+182 16 64 47 4 16 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 3 0 1 126 14 44 191 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+190 17 67 158 14 55 23 2 8 0 0 0 1 0 0 113 10 40
+191 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 78 7 27 0 0 0
+47 4 16 177 16 62 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 189 17 66
+173 16 61 34 3 12 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 85 8 30 189 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 79 7 28 0 0 0 0 0 0 47 4 16
+175 16 62 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 190 17 67 156 14 55 22 2 8 0 0 0
+109 10 38 191 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 190 17 67
+151 14 53 13 1 5 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 35 3 12 173 16 61 189 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 191 17 67 134 12 47 7 1 2 0 0 0 3 0 1
+99 9 35 188 17 66 189 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 181 16 63 68 6 24 0 0 0 18 2 6
+156 14 55 190 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 190 17 67
+101 9 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 3 0 1 118 13 41 191 17 67 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 168 15 59 28 3 10 0 0 0 0 0 0
+12 1 4 113 10 40 187 17 66 189 17 67 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+190 17 67 180 16 63 88 8 31 4 0 1 0 0 0 47 4 16
+180 16 63 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 190 17 67 168 15 59
+36 3 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 38 3 13 164 15 58 190 17 67
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 182 16 64 50 5 17 0 0 0 0 0 0
+0 0 0 11 1 4 90 8 32 169 15 59 190 17 67 190 17 67
+189 17 66 189 17 66 189 17 66 189 17 66 191 17 67 189 17 66
+158 14 55 68 6 24 4 0 1 0 0 0 0 0 0 73 7 26
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 189 17 66 185 17 65 83 8 29
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 65 6 23 174 16 61
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 185 17 65 56 5 19 0 0 0 0 0 0
+0 0 0 0 0 0 2 0 1 35 3 12 99 9 35 146 13 51
+170 15 60 177 16 62 177 16 62 166 15 58 141 13 49 85 8 30
+24 2 8 0 0 0 0 0 0 0 0 0 0 0 0 85 8 30
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 189 17 66 112 10 39 8 1 3
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 68 6 24
+170 15 60 191 17 67 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 182 16 64 50 5 17 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 11 1 4
+28 3 10 40 4 14 38 3 13 25 2 9 8 1 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 78 7 27
+189 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 187 17 66 113 10 40 14 1 5 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
+47 4 16 141 13 49 186 17 65 191 17 67 190 17 67 189 17 66
+189 17 66 191 17 67 156 14 55 20 2 7 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 4 15
+178 16 62 190 17 67 188 17 66 188 17 66 188 17 66 190 17 67
+191 17 67 173 16 61 90 8 32 10 1 4 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 14 1 5 68 6 24 131 12 46 162 15 57 174 16 61
+171 15 60 146 13 51 56 5 19 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 3 0 1 14 1 5 29 3 10
+41 4 14 47 4 16 50 5 17 45 4 16 34 3 12 18 2 6
+5 0 2 0 0 0 0 0 0 0 0 0 0 0 0 5 0 2
+90 8 32 169 15 59 185 17 65 187 17 66 182 16 64 163 15 57
+113 10 40 41 4 14 2 0 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 5 0 2 21 2 7 34 3 12
+29 3 10 11 1 4 0 0 0 0 0 0 0 0 0 0 0 0
+3 0 1 32 3 11 79 7 28 124 11 43 154 14 54 171 15 60
+180 16 63 182 16 64 182 16 64 180 16 63 174 16 61 159 14 56
+132 12 46 88 8 31 34 3 12 3 0 1 0 0 0 0 0 0
+3 0 1 29 3 10 56 5 19 65 6 23 50 5 17 23 2 8
+3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 2 9
+109 10 38 169 15 59 189 17 66 191 17 67 190 17 67 189 17 66
+189 17 66 188 17 66 188 17 66 188 17 66 189 17 66 190 17 67
+191 17 67 190 17 67 171 15 60 98 9 34 10 1 3 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 14 1 5 141 13 49
+191 17 67 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 189 17 67 186 17 65 65 6 23 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 23 2 8 166 15 58
+190 17 67 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 189 17 66 176 16 62 45 4 16 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 83 8 29
+183 17 64 189 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+188 17 66 189 17 66 185 17 65 95 9 33 3 0 1 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 2
+85 8 30 176 16 62 191 17 67 188 17 66 188 17 66 188 17 66
+188 17 66 188 17 66 188 17 66 188 17 66 188 17 66 188 17 66
+191 17 67 180 16 63 95 9 33 7 1 3 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+2 0 1 52 5 18 141 13 49 185 17 65 191 17 67 189 17 67
+189 17 66 188 17 66 188 17 66 189 17 66 191 17 67 187 17 66
+146 13 51 56 5 19 4 0 1 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 14 1 5 68 6 24 131 12 46 166 15 58
+180 16 63 183 17 64 180 16 63 168 15 59 134 12 47 75 7 26
+17 2 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 5 0 2 24 2 8
+44 4 15 52 5 18 45 4 16 26 2 9 6 1 2 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
diff --git a/bsp/raspberry-pi/dm/hwcrypto/Kconfig b/bsp/raspberry-pi/dm/hwcrypto/Kconfig
new file mode 100755
index 0000000000..0a09e8d05d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/hwcrypto/Kconfig
@@ -0,0 +1,14 @@
+config RT_HWCRYPTO_RNG_BCM2835
+ bool "Broadcom BCM2835/BCM63xx Random Number Generator support"
+ depends on RT_USING_DM
+ depends on RT_USING_HWCRYPTO
+ depends on RT_HWCRYPTO_USING_RNG
+ depends on RT_USING_RESET
+ default n
+
+config RT_HWCRYPTO_RNG_IPROC_RNG200
+ bool "Broadcom iProc/STB RNG200 support"
+ depends on RT_USING_DM
+ depends on RT_USING_HWCRYPTO
+ depends on RT_HWCRYPTO_USING_RNG
+ default n
diff --git a/bsp/raspberry-pi/dm/hwcrypto/SConscript b/bsp/raspberry-pi/dm/hwcrypto/SConscript
new file mode 100755
index 0000000000..9cf5e7f8a7
--- /dev/null
+++ b/bsp/raspberry-pi/dm/hwcrypto/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_HWCRYPTO_RNG_BCM2835']):
+ src += ['hw-rng-bcm2835.c']
+
+if GetDepend(['RT_HWCRYPTO_RNG_IPROC_RNG200']):
+ src += ['hw-rng-iproc-rng200.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/hwcrypto/hw-rng-bcm2835.c b/bsp/raspberry-pi/dm/hwcrypto/hw-rng-bcm2835.c
new file mode 100755
index 0000000000..93667c56ba
--- /dev/null
+++ b/bsp/raspberry-pi/dm/hwcrypto/hw-rng-bcm2835.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "rng.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define RNG_CTRL 0x0
+#define RNG_STATUS 0x4
+#define RNG_DATA 0x8
+#define RNG_INT_MASK 0x10
+
+/* enable rng */
+#define RNG_RBGEN 0x1
+
+/* the initial numbers generated are "less random" so will be discarded */
+#define RNG_WARMUP_COUNT 0x40000
+
+#define RNG_INT_OFF 0x1
+
+struct bcm2835_rng_soc_data
+{
+ rt_bool_t mask_interrupts;
+};
+
+struct bcm2835_rng
+{
+ struct rt_hwcrypto_device parent;
+
+ void *regs;
+
+ rt_bool_t mask_interrupts;
+ struct rt_clk *clk;
+ struct rt_reset_control *rstc;
+};
+
+#define raw_to_bcm2835_rng(raw) rt_container_of(raw, struct bcm2835_rng, parent)
+
+rt_inline rt_uint32_t rng_readl(struct bcm2835_rng *brng, int offset)
+{
+ return HWREG32(brng->regs + offset);
+}
+
+rt_inline void rng_writel(struct bcm2835_rng *brng, int offset, rt_uint32_t val)
+{
+ HWREG32(brng->regs + offset) = val;
+}
+
+static rt_uint32_t bcm2835_rng_read(struct bcm2835_rng *brng, void *buf,
+ rt_size_t max, rt_bool_t wait)
+{
+ rt_uint32_t max_words = max / sizeof(rt_uint32_t), num_words;
+
+ while ((rng_readl(brng, RNG_STATUS) >> 24) == 0)
+ {
+ if (!wait)
+ {
+ return 0;
+ }
+
+ rt_thread_mdelay(1000);
+ }
+
+ num_words = rng_readl(brng, RNG_STATUS) >> 24;
+
+ if (num_words > max_words)
+ {
+ num_words = max_words;
+ }
+
+ for (int count = 0; count < num_words; ++count)
+ {
+ ((rt_uint32_t *)buf)[count] = rng_readl(brng, RNG_DATA);
+ }
+
+ return num_words * sizeof(rt_uint32_t);
+}
+
+static rt_err_t bcm2835_rng_init(struct bcm2835_rng *brng)
+{
+ rt_err_t err;
+ rt_uint32_t val;
+
+ if ((err = rt_clk_prepare_enable(brng->clk)))
+ {
+ LOG_E("CLK enable error = %s", rt_strerror(err));
+ return err;
+ }
+
+ if ((err = rt_reset_control_reset(brng->rstc)))
+ {
+ LOG_E("Reset error = %s", rt_strerror(err));
+ return err;
+ }
+
+ if (brng->mask_interrupts)
+ {
+ /* mask the interrupt */
+ val = rng_readl(brng, RNG_INT_MASK);
+ val |= RNG_INT_OFF;
+ rng_writel(brng, RNG_INT_MASK, val);
+ }
+
+ /* set warm-up count & enable */
+ rng_writel(brng, RNG_STATUS, RNG_WARMUP_COUNT);
+ rng_writel(brng, RNG_CTRL, RNG_RBGEN);
+
+ return RT_EOK;
+}
+
+static void bcm2835_rng_cleanup(struct bcm2835_rng *brng)
+{
+ /* Disable rng hardware */
+ rng_writel(brng, RNG_CTRL, 0);
+
+ rt_clk_disable_unprepare(brng->clk);
+}
+
+static rt_uint32_t bcm2835_rng_rand(struct hwcrypto_rng *ctx)
+{
+ rt_size_t size;
+ rt_uint32_t rand;
+ struct bcm2835_rng *brng = raw_to_bcm2835_rng(ctx->parent.device);
+
+ size = bcm2835_rng_read(brng, &rand, sizeof(rand), RT_TRUE);
+
+ if (size != sizeof(rand))
+ {
+ return 0;
+ }
+
+ return rand;
+}
+
+static const struct hwcrypto_rng_ops rng_ops =
+{
+ .update = bcm2835_rng_rand,
+};
+
+static rt_err_t bcm2835_rng_create(struct rt_hwcrypto_ctx *ctx)
+{
+ rt_err_t res = RT_EOK;
+ struct hwcrypto_rng *rng;
+
+ switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
+ {
+ case HWCRYPTO_TYPE_RNG:
+ ctx->contex = RT_NULL;
+
+ rng = rt_container_of(ctx, struct hwcrypto_rng, parent);
+ rng->ops = &rng_ops;
+ break;
+
+ default:
+ res = -RT_ENOSYS;
+ break;
+ }
+
+ return res;
+}
+
+static void bcm2835_rng_destroy(struct rt_hwcrypto_ctx *ctx)
+{
+ struct bcm2835_rng *brng = raw_to_bcm2835_rng(ctx->device);
+
+ bcm2835_rng_cleanup(brng);
+
+ rt_free(ctx->contex);
+}
+
+static rt_err_t bcm2835_rng_copy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
+{
+ rt_err_t err = RT_EOK;
+
+ switch (src->type & HWCRYPTO_MAIN_TYPE_MASK)
+ {
+ case HWCRYPTO_TYPE_RNG:
+ break;
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+
+ return err;
+}
+
+static void bcm2835_rng_reset(struct rt_hwcrypto_ctx *ctx)
+{
+ struct bcm2835_rng *brng = raw_to_bcm2835_rng(ctx->device);
+
+ bcm2835_rng_init(brng);
+}
+
+static const struct rt_hwcrypto_ops bcm2835_rng_ops =
+{
+ .create = bcm2835_rng_create,
+ .destroy = bcm2835_rng_destroy,
+ .copy = bcm2835_rng_copy,
+ .reset = bcm2835_rng_reset,
+};
+
+static void bcm2835_rng_free(struct bcm2835_rng *brng)
+{
+ if (!brng->regs)
+ {
+ rt_iounmap(brng->regs);
+ }
+
+ if (!rt_is_err_or_null(brng->rstc))
+ {
+ rt_reset_control_assert(brng->rstc);
+ rt_reset_control_put(brng->rstc);
+ }
+
+ if (!rt_is_err_or_null(brng->clk))
+ {
+ rt_clk_disable_unprepare(brng->clk);
+ rt_clk_put(brng->clk);
+ }
+
+ rt_free(brng);
+}
+
+static rt_err_t bcm2835_rng_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ struct rt_device *dev = &pdev->parent;
+ const struct bcm2835_rng_soc_data *soc_data;
+ struct bcm2835_rng *brng = rt_calloc(1, sizeof(*brng));
+
+ if (!brng)
+ {
+ return -RT_ENOMEM;
+ }
+
+ brng->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!brng->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ brng->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(brng->clk))
+ {
+ err = rt_ptr_err(brng->clk);
+ goto _fail;
+ }
+
+ brng->rstc = rt_reset_control_get_by_index(dev, 0);
+
+ if (rt_is_err(brng->rstc))
+ {
+ err = rt_ptr_err(brng->rstc);
+ goto _fail;
+ }
+
+ if ((soc_data = pdev->id->data))
+ {
+ brng->mask_interrupts = soc_data->mask_interrupts;
+ }
+
+ dev->user_data = brng;
+
+ brng->parent.ops = &bcm2835_rng_ops;
+
+ if ((err = rt_hwcrypto_register(&brng->parent, "hwrng")))
+ {
+ goto _fail;
+ }
+
+ bcm2835_rng_init(brng);
+
+ return RT_EOK;
+
+_fail:
+ bcm2835_rng_free(brng);
+
+ return err;
+}
+
+static rt_err_t bcm2835_rng_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_rng *brng = pdev->parent.user_data;
+
+ bcm2835_rng_cleanup(brng);
+
+ rt_device_unregister(&brng->parent.parent);
+
+ bcm2835_rng_free(brng);
+
+ return RT_EOK;
+}
+
+static const struct bcm2835_rng_soc_data nsp_rng_data =
+{
+ .mask_interrupts = RT_TRUE,
+};
+
+static const struct rt_ofw_node_id bcm2835_rng_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-rng" },
+ { .compatible = "brcm,bcm-nsp-rng", .data = &nsp_rng_data },
+ { .compatible = "brcm,bcm5301x-rng", .data = &nsp_rng_data },
+ { .compatible = "brcm,bcm6368-rng" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_rng_driver =
+{
+ .name = "bcm2835-rng",
+ .ids = bcm2835_rng_ofw_ids,
+
+ .probe = bcm2835_rng_probe,
+ .remove = bcm2835_rng_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_rng_driver);
diff --git a/bsp/raspberry-pi/dm/hwcrypto/hw-rng-iproc-rng200.c b/bsp/raspberry-pi/dm/hwcrypto/hw-rng-iproc-rng200.c
new file mode 100755
index 0000000000..a8feade65e
--- /dev/null
+++ b/bsp/raspberry-pi/dm/hwcrypto/hw-rng-iproc-rng200.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "rng.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define RNG_CTRL_OFFSET 0x00
+#define RNG_CTRL_RNG_RBGEN_MASK 0x00001fff
+#define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
+
+#define RNG_SOFT_RESET_OFFSET 0x04
+#define RNG_SOFT_RESET 0x00000001
+
+#define RBG_SOFT_RESET_OFFSET 0x08
+#define RBG_SOFT_RESET 0x00000001
+
+#define RNG_INT_STATUS_OFFSET 0x18
+#define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
+#define RNG_INT_STATUS_STARTUP_TRANSITIONS_MET_IRQ_MASK 0x00020000
+#define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
+#define RNG_INT_STATUS_TOTAL_BITS_COUNT_IRQ_MASK 0x00000001
+
+#define RNG_FIFO_DATA_OFFSET 0x20
+
+#define RNG_FIFO_COUNT_OFFSET 0x24
+#define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000ff
+
+#define MAX_RESETS_PER_READ 1
+#define MAX_IDLE_TIME (1 * 100)
+
+struct iproc_rng200
+{
+ struct rt_hwcrypto_device parent;
+
+ void *regs;
+};
+
+#define raw_to_iproc_rng200(raw) rt_container_of(raw, struct iproc_rng200, parent)
+
+static void iproc_rng200_enable_set(struct iproc_rng200 *rng200, rt_bool_t enable)
+{
+ rt_uint32_t val;
+
+ val = HWREG32(rng200->regs + RNG_CTRL_OFFSET);
+ val &= ~RNG_CTRL_RNG_RBGEN_MASK;
+
+ if (enable)
+ {
+ val |= RNG_CTRL_RNG_RBGEN_ENABLE;
+ }
+
+ HWREG32(rng200->regs + RNG_CTRL_OFFSET) = val;
+}
+
+static void iproc_rng200_restart(struct iproc_rng200 *rng200)
+{
+ rt_uint32_t val;
+ void *regs = rng200->regs;
+
+ iproc_rng200_enable_set(rng200, RT_FALSE);
+
+ /* Clear all interrupt status */
+ HWREG32(regs + RNG_INT_STATUS_OFFSET) = 0xffffffffUL;
+
+ /* Reset RNG and RBG */
+ val = HWREG32(regs + RBG_SOFT_RESET_OFFSET);
+ val |= RBG_SOFT_RESET;
+ HWREG32(regs + RBG_SOFT_RESET_OFFSET) = val;
+
+ val = HWREG32(regs + RNG_SOFT_RESET_OFFSET);
+ val |= RNG_SOFT_RESET;
+ HWREG32(regs + RNG_SOFT_RESET_OFFSET) = val;
+
+ val = HWREG32(regs + RNG_SOFT_RESET_OFFSET);
+ val &= ~RNG_SOFT_RESET;
+ HWREG32(regs + RNG_SOFT_RESET_OFFSET) = val;
+
+ val = HWREG32(regs + RBG_SOFT_RESET_OFFSET);
+ val &= ~RBG_SOFT_RESET;
+ HWREG32(regs + RBG_SOFT_RESET_OFFSET) = val;
+
+ iproc_rng200_enable_set(rng200, RT_TRUE);
+}
+
+static rt_uint32_t iproc_rng200_read(struct iproc_rng200 *rng200, void *buf,
+ rt_size_t max, rt_bool_t wait)
+{
+ rt_uint32_t num_remaining = max, status, num_resets = 0;
+
+ while (num_remaining > 0)
+ {
+ rt_thread_mdelay(MAX_IDLE_TIME >> 1);
+
+ /* Is RNG sane? If not, reset it. */
+ status = HWREG32(rng200->regs + RNG_INT_STATUS_OFFSET);
+ if ((status & (RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK |
+ RNG_INT_STATUS_NIST_FAIL_IRQ_MASK)) != 0)
+ {
+ if (num_resets >= MAX_RESETS_PER_READ)
+ {
+ return max - num_remaining;
+ }
+
+ iproc_rng200_restart(rng200);
+ ++num_resets;
+ }
+
+ /* Are there any random numbers available? */
+ if ((HWREG32(rng200->regs + RNG_FIFO_COUNT_OFFSET) &
+ RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK) > 0)
+ {
+ if (num_remaining >= sizeof(rt_uint32_t))
+ {
+ /* Buffer has room to store entire word */
+ *(rt_uint32_t *)buf = HWREG32(rng200->regs + RNG_FIFO_DATA_OFFSET);
+ buf += sizeof(rt_uint32_t);
+ num_remaining -= sizeof(rt_uint32_t);
+ }
+ else
+ {
+ /* Buffer can only store partial word */
+ rt_uint32_t rnd_number = HWREG32(rng200->regs + RNG_FIFO_DATA_OFFSET);
+
+ rt_memcpy(buf, &rnd_number, num_remaining);
+ buf += num_remaining;
+ num_remaining = 0;
+ }
+ }
+ else
+ {
+ if (!wait)
+ {
+ /* Cannot wait, return immediately */
+ return max - num_remaining;
+ }
+
+ /* Can wait, give others chance to run */
+ rt_hw_us_delay((rt_min(num_remaining * 10, 500U)) >> 1);
+ }
+ }
+
+ return max - num_remaining;
+}
+
+static rt_err_t iproc_rng200_init(struct iproc_rng200 *rng200)
+{
+ iproc_rng200_enable_set(rng200, RT_TRUE);
+
+ return RT_EOK;
+}
+
+static void iproc_rng200_cleanup(struct iproc_rng200 *rng200)
+{
+ iproc_rng200_enable_set(rng200, RT_FALSE);
+}
+
+static rt_uint32_t iproc_rng200_rand(struct hwcrypto_rng *ctx)
+{
+ rt_size_t size;
+ rt_uint32_t rand;
+ struct iproc_rng200 *rng200 = raw_to_iproc_rng200(ctx->parent.device);
+
+ size = iproc_rng200_read(rng200, &rand, sizeof(rand), RT_TRUE);
+
+ if (size != sizeof(rand))
+ {
+ return 0;
+ }
+
+ return rand;
+}
+
+static const struct hwcrypto_rng_ops rng_ops =
+{
+ .update = iproc_rng200_rand,
+};
+
+static rt_err_t iproc_rng200_create(struct rt_hwcrypto_ctx *ctx)
+{
+ rt_err_t res = RT_EOK;
+ struct hwcrypto_rng *rng;
+
+ switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
+ {
+ case HWCRYPTO_TYPE_RNG:
+ ctx->contex = RT_NULL;
+
+ rng = rt_container_of(ctx, struct hwcrypto_rng, parent);
+ rng->ops = &rng_ops;
+ break;
+
+ default:
+ res = -RT_ENOSYS;
+ break;
+ }
+
+ return res;
+}
+
+static void iproc_rng200_destroy(struct rt_hwcrypto_ctx *ctx)
+{
+ struct iproc_rng200 *rng200 = raw_to_iproc_rng200(ctx->device);
+
+ iproc_rng200_cleanup(rng200);
+
+ rt_free(ctx->contex);
+}
+
+static rt_err_t iproc_rng200_copy(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
+{
+ rt_err_t err = RT_EOK;
+
+ switch (src->type & HWCRYPTO_MAIN_TYPE_MASK)
+ {
+ case HWCRYPTO_TYPE_RNG:
+ break;
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+
+ return err;
+}
+
+static void iproc_rng200_reset(struct rt_hwcrypto_ctx *ctx)
+{
+ struct iproc_rng200 *rng200 = raw_to_iproc_rng200(ctx->device);
+
+ iproc_rng200_init(rng200);
+}
+
+static const struct rt_hwcrypto_ops iproc_rng200_ops =
+{
+ .create = iproc_rng200_create,
+ .destroy = iproc_rng200_destroy,
+ .copy = iproc_rng200_copy,
+ .reset = iproc_rng200_reset,
+};
+
+static rt_err_t iproc_rng200_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct iproc_rng200 *rng200 = rt_calloc(1, sizeof(*rng200));
+
+ if (!rng200)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rng200->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!rng200->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ dev->user_data = rng200;
+
+ rng200->parent.ops = &iproc_rng200_ops;
+
+ if ((err = rt_hwcrypto_register(&rng200->parent, "hwrng")))
+ {
+ goto _fail;
+ }
+
+ iproc_rng200_init(rng200);
+
+ return RT_EOK;
+
+_fail:
+ if (rng200->regs)
+ {
+ rt_iounmap(rng200->regs);
+ }
+
+ rt_free(rng200);
+
+ return err;
+}
+
+static rt_err_t iproc_rng200_remove(struct rt_platform_device *pdev)
+{
+ struct iproc_rng200 *rng200 = pdev->parent.user_data;
+
+ iproc_rng200_cleanup(rng200);
+
+ rt_device_unregister(&rng200->parent.parent);
+
+ rt_iounmap(rng200->regs);
+ rt_free(rng200);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id iproc_rng200_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2711-rng200", },
+ { .compatible = "brcm,bcm7211-rng200", },
+ { .compatible = "brcm,bcm7278-rng200", },
+ { .compatible = "brcm,iproc-rng200", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver iproc_rng200_driver =
+{
+ .name = "iproc-rng200",
+ .ids = iproc_rng200_ofw_ids,
+
+ .probe = iproc_rng200_probe,
+ .remove = iproc_rng200_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(iproc_rng200_driver);
diff --git a/bsp/raspberry-pi/dm/i2c/Kconfig b/bsp/raspberry-pi/dm/i2c/Kconfig
new file mode 100755
index 0000000000..86fe1e7115
--- /dev/null
+++ b/bsp/raspberry-pi/dm/i2c/Kconfig
@@ -0,0 +1,9 @@
+config RT_I2C_BCM2835
+ bool "Broadcom BCM2835 I2C controller"
+ depends on RT_USING_PINCTRL
+ default n
+
+config RT_I2C_BRCMSTB
+ bool "BRCM Settop/DSL I2C controller"
+ depends on RT_USING_PINCTRL
+ default n
diff --git a/bsp/raspberry-pi/dm/i2c/SConscript b/bsp/raspberry-pi/dm/i2c/SConscript
new file mode 100755
index 0000000000..ffcbb27d7d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/i2c/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_I2C_BCM2835']):
+ src += ['i2c-bcm2835.c']
+
+if GetDepend(['RT_I2C_BRCMSTB']):
+ src += ['i2c-brcmstb.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/i2c/i2c-bcm2835.c b/bsp/raspberry-pi/dm/i2c/i2c-bcm2835.c
new file mode 100755
index 0000000000..fe44841272
--- /dev/null
+++ b/bsp/raspberry-pi/dm/i2c/i2c-bcm2835.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "i2c.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <drivers/dev_i2c_dm.h>
+
+#define BCM2835_I2C_C 0x0
+#define BCM2835_I2C_S 0x4
+#define BCM2835_I2C_DLEN 0x8
+#define BCM2835_I2C_A 0xc
+#define BCM2835_I2C_FIFO 0x10
+#define BCM2835_I2C_DIV 0x14
+#define BCM2835_I2C_DEL 0x18
+/*
+ * 16-bit field for the number of SCL cycles to wait after rising SCL
+ * before deciding the slave is not responding. 0 disables the
+ * timeout detection.
+ */
+#define BCM2835_I2C_CLKT 0x1c
+
+#define BCM2835_I2C_C_READ RT_BIT(0)
+#define BCM2835_I2C_C_CLEAR RT_BIT(4) /* bits 4 and 5 both clear */
+#define BCM2835_I2C_C_ST RT_BIT(7)
+#define BCM2835_I2C_C_INTD RT_BIT(8)
+#define BCM2835_I2C_C_INTT RT_BIT(9)
+#define BCM2835_I2C_C_INTR RT_BIT(10)
+#define BCM2835_I2C_C_I2CEN RT_BIT(15)
+
+#define BCM2835_I2C_S_TA RT_BIT(0)
+#define BCM2835_I2C_S_DONE RT_BIT(1)
+#define BCM2835_I2C_S_TXW RT_BIT(2)
+#define BCM2835_I2C_S_RXR RT_BIT(3)
+#define BCM2835_I2C_S_TXD RT_BIT(4)
+#define BCM2835_I2C_S_RXD RT_BIT(5)
+#define BCM2835_I2C_S_TXE RT_BIT(6)
+#define BCM2835_I2C_S_RXF RT_BIT(7)
+#define BCM2835_I2C_S_ERR RT_BIT(8)
+#define BCM2835_I2C_S_CLKT RT_BIT(9)
+#define BCM2835_I2C_S_LEN RT_BIT(10) /* Fake bit for SW error reporting */
+
+#define BCM2835_I2C_FEDL_SHIFT 16
+#define BCM2835_I2C_REDL_SHIFT 0
+
+#define BCM2835_I2C_CDIV_MIN 0x0002
+#define BCM2835_I2C_CDIV_MAX 0xfffe
+
+#define CLK_TOUT_MS 35
+
+struct bcm2835_i2c
+{
+ struct rt_i2c_bus_device parent;
+
+ void *regs;
+ int irq;
+ struct rt_clk *clk;
+
+ struct rt_completion done;
+
+ struct rt_i2c_msg *curr_msg;
+ int num_msgs;
+ rt_err_t msg_err;
+ rt_uint8_t *msg_buf;
+ rt_size_t msg_buf_remaining;
+};
+
+#define raw_to_bcm2835_i2c(raw) rt_container_of(raw, struct bcm2835_i2c, parent)
+
+rt_inline void bcm2835_i2c_writel(struct bcm2835_i2c *i2c, int offset, rt_uint32_t val)
+{
+ HWREG32(i2c->regs + offset) = val;
+}
+
+rt_inline rt_uint32_t bcm2835_i2c_readl(struct bcm2835_i2c *i2c, int offset)
+{
+ return HWREG32(i2c->regs + offset);
+}
+
+static void bcm2835_fill_txfifo(struct bcm2835_i2c *i2c)
+{
+ while (i2c->msg_buf_remaining)
+ {
+ if (!(bcm2835_i2c_readl(i2c, BCM2835_I2C_S) & BCM2835_I2C_S_TXD))
+ {
+ break;
+ }
+
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_FIFO, *i2c->msg_buf);
+
+ ++i2c->msg_buf;
+ --i2c->msg_buf_remaining;
+ }
+}
+
+static void bcm2835_drain_rxfifo(struct bcm2835_i2c *i2c)
+{
+ while (i2c->msg_buf_remaining)
+ {
+ if (!(bcm2835_i2c_readl(i2c, BCM2835_I2C_S) & BCM2835_I2C_S_RXD))
+ {
+ break;
+ }
+
+ *i2c->msg_buf = bcm2835_i2c_readl(i2c, BCM2835_I2C_FIFO);
+
+ ++i2c->msg_buf;
+ --i2c->msg_buf_remaining;
+ }
+}
+
+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c *i2c)
+{
+ rt_uint32_t c;
+ rt_bool_t last_msg;
+ struct rt_i2c_msg *msg = i2c->curr_msg;
+
+ if (!i2c->num_msgs)
+ {
+ return;
+ }
+
+ last_msg = (i2c->num_msgs == 1);
+ c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN;
+
+ --i2c->num_msgs;
+ i2c->msg_buf = msg->buf;
+ i2c->msg_buf_remaining = msg->len;
+ rt_hw_rmb();
+
+ if (msg->flags & RT_I2C_RD)
+ {
+ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+ }
+ else
+ {
+ c |= BCM2835_I2C_C_INTT;
+ }
+
+ if (last_msg)
+ {
+ c |= BCM2835_I2C_C_INTD;
+ }
+
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_A, msg->addr);
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_DLEN, msg->len);
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_C, c);
+}
+
+static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c *i2c)
+{
+ i2c->curr_msg = RT_NULL;
+ i2c->num_msgs = 0;
+
+ i2c->msg_buf = RT_NULL;
+ i2c->msg_buf_remaining = 0;
+}
+
+static rt_ssize_t bcm2835_i2c_master_xfer(struct rt_i2c_bus_device *bus,
+ struct rt_i2c_msg msgs[], rt_uint32_t num)
+{
+ rt_err_t err;
+ rt_bool_t ignore_nak = RT_FALSE;
+ struct bcm2835_i2c *i2c = raw_to_bcm2835_i2c(bus);
+
+ for (int i = 0; i < num - 1; ++i)
+ {
+ if (msgs[i].flags & RT_I2C_RD)
+ {
+ return -RT_ENOSYS;
+ }
+
+ if (msgs[i].flags & RT_I2C_IGNORE_NACK)
+ {
+ ignore_nak = RT_TRUE;
+ }
+ }
+
+ i2c->curr_msg = msgs;
+ i2c->num_msgs = num;
+ i2c->msg_err = 0;
+
+ bcm2835_i2c_start_transfer(i2c);
+
+ err = rt_completion_wait(&i2c->done, RT_TICK_PER_SECOND);
+
+ bcm2835_i2c_finish_transfer(i2c);
+
+ if (ignore_nak)
+ {
+ i2c->msg_err &= ~BCM2835_I2C_S_ERR;
+ }
+
+ if (err)
+ {
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+
+ return -RT_ETIMEOUT;
+ }
+
+ if (!i2c->msg_err)
+ {
+ return num;
+ }
+
+ if (i2c->msg_err & BCM2835_I2C_S_ERR)
+ {
+ LOG_E("Bus error");
+ }
+
+ return -RT_EIO;
+}
+
+const static struct rt_i2c_bus_device_ops bcm2835_i2c_ops =
+{
+ .master_xfer = bcm2835_i2c_master_xfer,
+};
+
+static void bcm2835_i2c_isr(int irqno, void *param)
+{
+ rt_uint32_t val, err;
+ struct bcm2835_i2c *i2c = param;
+
+ val = bcm2835_i2c_readl(i2c, BCM2835_I2C_S);
+
+ err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+ if (err && !(val & BCM2835_I2C_S_TA))
+ {
+ i2c->msg_err = err;
+ }
+
+ if (val & BCM2835_I2C_S_DONE)
+ {
+ if (!i2c->curr_msg)
+ {
+ LOG_E("Got unexpected interrupt (from firmware?)");
+ }
+ else if (i2c->curr_msg->flags & RT_I2C_RD)
+ {
+ bcm2835_drain_rxfifo(i2c);
+ val = bcm2835_i2c_readl(i2c, BCM2835_I2C_S);
+ }
+
+ if ((val & BCM2835_I2C_S_RXD) || i2c->msg_buf_remaining)
+ {
+ i2c->msg_err = BCM2835_I2C_S_LEN;
+ }
+
+ goto _complete;
+ }
+
+ if (val & BCM2835_I2C_S_TXW)
+ {
+ if (!i2c->msg_buf_remaining)
+ {
+ i2c->msg_err = val | BCM2835_I2C_S_LEN;
+ goto _complete;
+ }
+
+ bcm2835_fill_txfifo(i2c);
+
+ if (i2c->num_msgs && !i2c->msg_buf_remaining)
+ {
+ i2c->curr_msg++;
+ bcm2835_i2c_start_transfer(i2c);
+ }
+
+ return;
+ }
+
+ if (val & BCM2835_I2C_S_RXR)
+ {
+ if (!i2c->msg_buf_remaining)
+ {
+ i2c->msg_err = val | BCM2835_I2C_S_LEN;
+ goto _complete;
+ }
+
+ bcm2835_drain_rxfifo(i2c);
+ }
+
+ return;
+
+_complete:
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_S, BCM2835_I2C_S_CLKT |
+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE);
+ rt_completion_done(&i2c->done);
+}
+
+static int clk_bcm2835_i2c_calc_divider(rt_ubase_t rate, rt_ubase_t parent_rate)
+{
+ rt_uint32_t divider = RT_DIV_ROUND_UP(parent_rate, rate);
+
+ if (divider & 1)
+ {
+ ++divider;
+ }
+
+ if (divider < BCM2835_I2C_CDIV_MIN || divider > BCM2835_I2C_CDIV_MAX)
+ {
+ return -RT_EINVAL;
+ }
+
+ return divider;
+}
+
+static rt_err_t bcm2835_i2c_clk_set_rate(struct bcm2835_i2c *i2c, rt_ubase_t rate)
+{
+ rt_uint32_t redl, fedl, clk_tout, divider;
+
+ divider = clk_bcm2835_i2c_calc_divider(rate, rt_clk_get_rate(i2c->clk));
+
+ if ((rt_int32_t)divider < 0)
+ {
+ return (rt_err_t)divider;
+ }
+
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_DIV, divider);
+
+ /*
+ * Number of core clocks to wait after falling edge before
+ * outputting the next data bit. Note that both FEDL and REDL
+ * can't be greater than CDIV/2.
+ */
+ fedl = rt_max(divider / 16, 1U);
+
+ /*
+ * Number of core clocks to wait after rising edge before
+ * sampling the next incoming data bit.
+ */
+ redl = rt_max(divider / 4, 1U);
+
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_DEL,
+ (fedl << BCM2835_I2C_FEDL_SHIFT) | (redl << BCM2835_I2C_REDL_SHIFT));
+
+ /* Set the clock stretch timeout. */
+ if (rate > 0xffff * 1000 / CLK_TOUT_MS)
+ {
+ clk_tout = 0xffff;
+ }
+ else
+ {
+ clk_tout = CLK_TOUT_MS * rate / 1000;
+ }
+
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_CLKT, clk_tout);
+
+ return RT_EOK;
+}
+
+static void bcm2835_i2c_free(struct bcm2835_i2c *i2c)
+{
+ if (i2c->regs)
+ {
+ rt_iounmap(i2c->regs);
+ }
+
+ if (!rt_is_err_or_null(i2c->clk))
+ {
+ rt_clk_disable_unprepare(i2c->clk);
+ rt_clk_put(i2c->clk);
+ }
+
+ rt_free(i2c);
+}
+
+static rt_err_t bcm2835_i2c_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ const char *dev_name;
+ rt_uint32_t bus_clk_rate;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_i2c *i2c = rt_calloc(1, sizeof(*i2c));
+
+ if (!i2c)
+ {
+ return -RT_ENOMEM;
+ }
+
+ i2c->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!i2c->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ i2c->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(i2c->clk))
+ {
+ err = rt_ptr_err(i2c->clk);
+ goto _fail;
+ }
+
+ if (rt_dm_dev_prop_read_u32(dev, "clock-frequency", &bus_clk_rate))
+ {
+ bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
+ }
+
+ if ((err = bcm2835_i2c_clk_set_rate(i2c, bus_clk_rate)))
+ {
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(i2c->clk)))
+ {
+ goto _fail;
+ }
+
+ i2c->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (i2c->irq < 0)
+ {
+ err = i2c->irq;
+ goto _fail;
+ }
+
+ /*
+ * Disable the hardware clock stretching timeout. SMBUS
+ * specifies a limit for how long the device can stretch the
+ * clock, but core I2C doesn't.
+ */
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_CLKT, 0);
+ bcm2835_i2c_writel(i2c, BCM2835_I2C_C, 0);
+
+ rt_completion_init(&i2c->done);
+
+ rt_dm_dev_set_name_auto(&i2c->parent.parent, "i2c");
+ dev_name = rt_dm_dev_get_name(&i2c->parent.parent);
+
+ rt_hw_interrupt_install(i2c->irq, bcm2835_i2c_isr, i2c, dev_name);
+ rt_hw_interrupt_umask(i2c->irq);
+
+ dev->user_data = i2c;
+
+ i2c->parent.ops = &bcm2835_i2c_ops;
+ i2c->parent.parent.ofw_node = dev->ofw_node;
+
+ if ((err = rt_i2c_bus_device_register(&i2c->parent, dev_name)))
+ {
+ goto _free_irq;
+ }
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, i2c);
+
+ return RT_EOK;
+
+_free_irq:
+ rt_hw_interrupt_mask(i2c->irq);
+ rt_pic_detach_irq(i2c->irq, i2c);
+
+_fail:
+ bcm2835_i2c_free(i2c);
+
+ return err;
+}
+
+static rt_err_t bcm2835_i2c_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_i2c *i2c = pdev->parent.user_data;
+
+ rt_hw_interrupt_mask(i2c->irq);
+ rt_pic_detach_irq(i2c->irq, i2c);
+
+ rt_device_unregister(&i2c->parent.parent);
+
+ bcm2835_i2c_free(i2c);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_i2c_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2711-i2c" },
+ { .compatible = "brcm,bcm2835-i2c" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_i2c_driver =
+{
+ .name = "bcm2835-i2c",
+ .ids = bcm2835_i2c_ofw_ids,
+
+ .probe = bcm2835_i2c_probe,
+ .remove = bcm2835_i2c_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_i2c_driver);
diff --git a/bsp/raspberry-pi/dm/i2c/i2c-brcmstb.c b/bsp/raspberry-pi/dm/i2c/i2c-brcmstb.c
new file mode 100755
index 0000000000..709d97e2fc
--- /dev/null
+++ b/bsp/raspberry-pi/dm/i2c/i2c-brcmstb.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "i2c.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <drivers/dev_i2c_dm.h>
+
+#define N_DATA_REGS 8
+
+/*
+ * PER_I2C/BSC count register mask depends on 1 byte/4 byte data register
+ * size. Cable modem and DSL SoCs with Peripheral i2c cores use 1 byte per
+ * data register whereas STB SoCs use 4 byte per data register transfer,
+ * account for this difference in total count per transaction and mask to use.
+ */
+#define BSC_CNT_REG1_MASK(nb) (nb == 1 ? RT_GENMASK(3, 0) : RT_GENMASK(5, 0))
+#define BSC_CNT_REG1_SHIFT 0
+
+/* BSC CTL register field definitions */
+#define BSC_CTL_REG_DTF_MASK 0x00000003
+#define BSC_CTL_REG_SCL_SEL_MASK 0x00000030
+#define BSC_CTL_REG_SCL_SEL_SHIFT 4
+#define BSC_CTL_REG_INT_EN_MASK 0x00000040
+#define BSC_CTL_REG_INT_EN_SHIFT 6
+#define BSC_CTL_REG_DIV_CLK_MASK 0x00000080
+
+/* BSC_IIC_ENABLE r/w enable and interrupt field definitions */
+#define BSC_IIC_EN_RESTART_MASK 0x00000040
+#define BSC_IIC_EN_NOSTART_MASK 0x00000020
+#define BSC_IIC_EN_NOSTOP_MASK 0x00000010
+#define BSC_IIC_EN_NOACK_MASK 0x00000004
+#define BSC_IIC_EN_INTRP_MASK 0x00000002
+#define BSC_IIC_EN_ENABLE_MASK 0x00000001
+
+/* BSC_CTLHI control register field definitions */
+#define BSC_CTLHI_REG_DATAREG_SIZE_MASK 0x00000040
+#define BSC_CTLHI_REG_IGNORE_ACK_MASK 0x00000002
+#define BSC_CTLHI_REG_WAIT_DIS_MASK 0x00000001
+
+#define I2C_TIMEOUT 100 /* msecs */
+
+/* Condition mask used for non combined transfer */
+#define COND_RESTART BSC_IIC_EN_RESTART_MASK
+#define COND_NOSTART BSC_IIC_EN_NOSTART_MASK
+#define COND_NOSTOP BSC_IIC_EN_NOSTOP_MASK
+#define COND_START_STOP (COND_RESTART | COND_NOSTART | COND_NOSTOP)
+
+/* BSC data transfer direction */
+#define DTF_WR_MASK 0x00000000
+#define DTF_RD_MASK 0x00000001
+/* BSC data transfer direction combined format */
+#define DTF_RD_WR_MASK 0x00000002
+#define DTF_WR_RD_MASK 0x00000003
+
+#define AUTOI2C_CTRL0 0x26c
+#define AUTOI2C_CTRL0_RELEASE_BSC RT_BIT(1)
+
+/* BSC block register map structure to cache fields to be written */
+struct bsc_regs
+{
+ rt_uint32_t chip_address; /* slave address */
+ rt_uint32_t data_in[N_DATA_REGS]; /* tx data buffer*/
+ rt_uint32_t cnt_reg; /* rx/tx data length */
+ rt_uint32_t ctl_reg; /* control register */
+ rt_uint32_t iic_enable; /* xfer enable and status */
+ rt_uint32_t data_out[N_DATA_REGS]; /* rx data buffer */
+ rt_uint32_t ctlhi_reg; /* more control fields */
+ rt_uint32_t scl_param; /* reserved */
+};
+
+struct bsc_clk_param
+{
+ rt_uint32_t hz;
+ rt_uint32_t scl_mask;
+ rt_uint32_t div_mask;
+};
+
+enum bsc_xfer_cmd
+{
+ CMD_WR,
+ CMD_RD,
+ CMD_WR_NOACK,
+ CMD_RD_NOACK,
+};
+
+enum bus_speeds
+{
+ SPD_375K,
+ SPD_390K,
+ SPD_187K,
+ SPD_200K,
+ SPD_93K,
+ SPD_97K,
+ SPD_46K,
+ SPD_50K,
+};
+
+static const struct bsc_clk_param bsc_clk[] =
+{
+ [SPD_375K] =
+ {
+ .hz = 375000,
+ .scl_mask = SPD_375K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = 0,
+ },
+ [SPD_390K] =
+ {
+ .hz = 390000,
+ .scl_mask = SPD_390K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = 0,
+ },
+ [SPD_187K] =
+ {
+ .hz = 187500,
+ .scl_mask = SPD_187K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = 0,
+ },
+ [SPD_200K] =
+ {
+ .hz = 200000,
+ .scl_mask = SPD_200K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = 0,
+ },
+ [SPD_93K] =
+ {
+ .hz = 93750,
+ .scl_mask = SPD_375K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = BSC_CTL_REG_DIV_CLK_MASK,
+ },
+ [SPD_97K] =
+ {
+ .hz = 97500,
+ .scl_mask = SPD_390K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = BSC_CTL_REG_DIV_CLK_MASK,
+ },
+ [SPD_46K] =
+ {
+ .hz = 46875,
+ .scl_mask = SPD_187K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = BSC_CTL_REG_DIV_CLK_MASK,
+ },
+ [SPD_50K] =
+ {
+ .hz = 50000,
+ .scl_mask = SPD_200K << BSC_CTL_REG_SCL_SEL_SHIFT,
+ .div_mask = BSC_CTL_REG_DIV_CLK_MASK,
+ }
+};
+
+struct brcmstb_i2c
+{
+ struct rt_i2c_bus_device parent;
+
+ int irq;
+ void *base;
+ struct bsc_regs bsc_regmap;
+
+ int data_regsz;
+ rt_uint32_t clk_freq_hz;
+ struct rt_completion done;
+};
+
+#define raw_to_brcmstb_i2c(raw) rt_container_of(raw, struct brcmstb_i2c, parent)
+
+#define bsc_readl(i2c, reg) HWREG32((i2c)->base + rt_offsetof(struct bsc_regs, reg))
+#define bsc_writel(i2c, reg, val) HWREG32((i2c)->base + rt_offsetof(struct bsc_regs, reg)) = (val)
+
+rt_inline int brcmstb_i2c_get_xfersz(struct brcmstb_i2c *i2c)
+{
+ return (N_DATA_REGS * i2c->data_regsz);
+}
+
+rt_inline int brcmstb_i2c_get_data_regsz(struct brcmstb_i2c *i2c)
+{
+ return i2c->data_regsz;
+}
+
+static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c *i2c, rt_bool_t int_en)
+{
+ if (int_en)
+ {
+ /* Enable BSC CTL interrupt line */
+ i2c->bsc_regmap.ctl_reg |= BSC_CTL_REG_INT_EN_MASK;
+ }
+ else
+ {
+ /* Disable BSC CTL interrupt line */
+ i2c->bsc_regmap.ctl_reg &= ~BSC_CTL_REG_INT_EN_MASK;
+ }
+
+ rt_hw_barrier();
+ bsc_writel(i2c, ctl_reg, i2c->bsc_regmap.ctl_reg);
+}
+
+/* Wait for device to be ready */
+static rt_err_t brcmstb_i2c_wait_if_busy(struct brcmstb_i2c *i2c)
+{
+ rt_tick_t timeout;
+
+ timeout = rt_tick_from_millisecond(I2C_TIMEOUT);
+ timeout += rt_tick_get();
+
+ while ((bsc_readl(i2c, iic_enable) & BSC_IIC_EN_INTRP_MASK))
+ {
+ if (rt_tick_get() > timeout)
+ {
+ return -RT_ETIMEOUT;
+ }
+
+ rt_hw_cpu_relax();
+ }
+
+ return RT_EOK;
+}
+
+/* i2c xfer completion function, handles both irq and polling mode */
+static rt_err_t brcmstb_i2c_wait_for_completion(struct brcmstb_i2c *i2c)
+{
+ rt_tick_t timeout;
+ rt_err_t err = RT_EOK;
+
+ timeout = rt_tick_from_millisecond(I2C_TIMEOUT);
+ timeout += rt_tick_get();
+
+ if (i2c->irq >= 0)
+ {
+ err = rt_completion_wait(&i2c->done, timeout);
+ }
+ else
+ {
+ /* Polling mode */
+ rt_uint32_t bsc_intrp;
+
+ do {
+ bsc_intrp = bsc_readl(i2c, iic_enable) & BSC_IIC_EN_INTRP_MASK;
+
+ if (rt_tick_get() > timeout)
+ {
+ err = -RT_ETIMEOUT;
+ break;
+ }
+
+ rt_hw_cpu_relax();
+ } while (!bsc_intrp);
+ }
+
+ if (i2c->irq < 0 || err == -RT_ETIMEOUT)
+ {
+ brcmstb_i2c_enable_disable_irq(i2c, RT_FALSE);
+ }
+
+ return err;
+}
+
+/* Set xfer START/STOP conditions for subsequent transfer */
+static void brcmstb_set_i2c_start_stop(struct brcmstb_i2c *i2c, rt_uint32_t cond_flag)
+{
+ rt_uint32_t regval = i2c->bsc_regmap.iic_enable;
+
+ i2c->bsc_regmap.iic_enable = (regval & ~COND_START_STOP) | cond_flag;
+}
+
+/* Send I2C request check completion */
+static rt_err_t brcmstb_send_i2c_cmd(struct brcmstb_i2c *i2c, enum bsc_xfer_cmd cmd)
+{
+ rt_err_t err;
+ struct bsc_regs *pi2creg = &i2c->bsc_regmap;
+
+ /* Make sure the hardware is ready */
+ if ((err = brcmstb_i2c_wait_if_busy(i2c)))
+ {
+ return err;
+ }
+
+ /* Enable BSC CTL interrupt line */
+ brcmstb_i2c_enable_disable_irq(i2c, RT_TRUE);
+
+ /* Initiate transfer by setting iic_enable */
+ pi2creg->iic_enable |= BSC_IIC_EN_ENABLE_MASK;
+ bsc_writel(i2c, iic_enable, pi2creg->iic_enable);
+
+ /* Wait for transaction to finish or timeout */
+ if ((err = brcmstb_i2c_wait_for_completion(i2c)))
+ {
+ goto _cmd_out;
+ }
+
+ if ((cmd == CMD_RD || cmd == CMD_WR) && bsc_readl(i2c, iic_enable) & BSC_IIC_EN_NOACK_MASK)
+ {
+ err = -RT_EIO;
+ }
+
+_cmd_out:
+ bsc_writel(i2c, cnt_reg, 0);
+ bsc_writel(i2c, iic_enable, 0);
+
+ return err;
+}
+
+/* Actual data transfer through the BSC master */
+static rt_err_t brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c *i2c,
+ rt_uint8_t *buf, rt_size_t len, struct rt_i2c_msg *msg)
+{
+ rt_err_t err;
+ int data_regsz;
+ rt_uint32_t ctl_reg;
+ enum bsc_xfer_cmd cmd;
+ struct bsc_regs *pi2creg = &i2c->bsc_regmap;
+
+ data_regsz = brcmstb_i2c_get_data_regsz(i2c);
+
+ if (msg->flags & RT_I2C_IGNORE_NACK)
+ {
+ cmd = (msg->flags & RT_I2C_RD) ? CMD_RD_NOACK : CMD_WR_NOACK;
+ pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK;
+ }
+ else
+ {
+ cmd = (msg->flags & RT_I2C_RD) ? CMD_RD : CMD_WR;
+ pi2creg->ctlhi_reg &= ~BSC_CTLHI_REG_IGNORE_ACK_MASK;
+ }
+ bsc_writel(i2c, ctlhi_reg, pi2creg->ctlhi_reg);
+
+ /* Set data transfer direction */
+ ctl_reg = pi2creg->ctl_reg & ~BSC_CTL_REG_DTF_MASK;
+
+ if (cmd == CMD_WR || cmd == CMD_WR_NOACK)
+ {
+ pi2creg->ctl_reg = ctl_reg | DTF_WR_MASK;
+ }
+ else
+ {
+ pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK;
+ }
+
+ /* Set the read/write length */
+ bsc_writel(i2c, cnt_reg, BSC_CNT_REG1_MASK(data_regsz) & (len << BSC_CNT_REG1_SHIFT));
+
+ /* Write data into data_in register */
+ if (cmd == CMD_WR || cmd == CMD_WR_NOACK)
+ {
+ for (int cnt = 0, i = 0; cnt < len; cnt += data_regsz, ++i)
+ {
+ rt_uint32_t word = 0;
+
+ for (int byte = 0; byte < data_regsz; ++byte)
+ {
+ word >>= RT_BITS_PER_BYTE;
+
+ if ((cnt + byte) < len)
+ {
+ word |= buf[cnt + byte] << (RT_BITS_PER_BYTE * (data_regsz - 1));
+ }
+ }
+
+ bsc_writel(i2c, data_in[i], word);
+ }
+ }
+
+ /* Initiate xfer, the function will return on completion */
+ if ((err = brcmstb_send_i2c_cmd(i2c, cmd)))
+ {
+ return err;
+ }
+
+ /* Read data from data_out register */
+ if (cmd == CMD_RD || cmd == CMD_RD_NOACK)
+ {
+ for (int cnt = 0, i = 0; cnt < len; cnt += data_regsz, ++i)
+ {
+ rt_uint32_t data = bsc_readl(i2c, data_out[i]);
+
+ for (int byte = 0; byte < data_regsz && byte + cnt < len; ++byte)
+ {
+ buf[cnt + byte] = data & 0xff;
+ data >>= RT_BITS_PER_BYTE;
+ }
+ }
+ }
+
+ return RT_EOK;
+}
+
+/* Write a single byte of data to the i2c bus */
+static rt_err_t brcmstb_i2c_write_data_byte(struct brcmstb_i2c *i2c,
+ rt_uint32_t *buf, rt_uint32_t nak_expected)
+{
+ enum bsc_xfer_cmd cmd = nak_expected ? CMD_WR : CMD_WR_NOACK;
+
+ bsc_writel(i2c, cnt_reg, 1);
+ bsc_writel(i2c, data_in, *buf);
+
+ return brcmstb_send_i2c_cmd(i2c, cmd);
+}
+
+/* Send i2c address */
+static rt_err_t brcmstb_i2c_do_addr(struct brcmstb_i2c *i2c, struct rt_i2c_msg *msg)
+{
+ rt_err_t err;
+ rt_uint8_t addr;
+
+ if (msg->flags & RT_I2C_ADDR_10BIT)
+ {
+ /* First byte is 11110XX0 where XX is upper 2 bits */
+ addr = 0xf0 | ((msg->addr & 0x300) >> 7);
+ bsc_writel(i2c, chip_address, addr);
+
+ /* Second byte is the remaining 8 bits */
+ addr = msg->addr & 0xff;
+ if ((err = brcmstb_i2c_write_data_byte(i2c, (void *)&addr, 0)))
+ {
+ return err;
+ }
+
+ if (msg->flags & RT_I2C_RD)
+ {
+ /* For read, send restart without stop condition */
+ brcmstb_set_i2c_start_stop(i2c, COND_RESTART | COND_NOSTOP);
+
+ /* Then re-send the first byte with the read bit set */
+ addr = 0xf0 | ((msg->addr & 0x300) >> 7) | 0x01;
+ if ((err = brcmstb_i2c_write_data_byte(i2c, (void *)&addr, 0)))
+ {
+ return err;
+ }
+ }
+ }
+ else
+ {
+ /* 8bit addr from msg */
+ addr = (msg->addr << 1) | (msg->flags & RT_I2C_RD ? 1 : 0);;
+ bsc_writel(i2c, chip_address, addr);
+ }
+
+ return RT_EOK;
+}
+
+static rt_ssize_t brcmstb_i2c_master_xfer(struct rt_i2c_bus_device *bus,
+ struct rt_i2c_msg msgs[], rt_uint32_t num)
+{
+ rt_err_t err;
+ rt_uint8_t *tmp_buf;
+ int bytes_to_xfer, xfersz, len;
+ rt_uint32_t cond, cond_per_msg;
+ struct rt_i2c_msg *pmsg;
+ struct brcmstb_i2c *i2c = raw_to_brcmstb_i2c(bus);
+
+ xfersz = brcmstb_i2c_get_xfersz(i2c);
+
+ /* Loop through all messages */
+ for (int i = 0; i < num; ++i)
+ {
+ pmsg = &msgs[i];
+ len = pmsg->len;
+ tmp_buf = pmsg->buf;
+
+ if (i < num - 1 && (msgs[i + 1].flags & RT_I2C_NO_START))
+ {
+ cond = ~COND_START_STOP;
+ }
+ else
+ {
+ cond = COND_RESTART | COND_NOSTOP;
+ }
+
+ brcmstb_set_i2c_start_stop(i2c, cond);
+
+ /* Send slave address */
+ if (!(pmsg->flags & RT_I2C_NO_START))
+ {
+ if ((err = brcmstb_i2c_do_addr(i2c, pmsg)))
+ {
+ return err;
+ }
+ }
+
+ cond_per_msg = cond;
+
+ /* Perform data transfer */
+ while (len)
+ {
+ bytes_to_xfer = rt_min(len, xfersz);
+
+ if (len <= xfersz)
+ {
+ if (i == num - 1)
+ {
+ cond_per_msg = cond_per_msg & ~(COND_RESTART | COND_NOSTOP);
+ }
+ else
+ {
+ cond_per_msg = cond;
+ }
+ }
+ else
+ {
+ cond_per_msg = (cond_per_msg & ~COND_RESTART) | COND_NOSTOP;
+ }
+
+ brcmstb_set_i2c_start_stop(i2c, cond_per_msg);
+
+ if ((err = brcmstb_i2c_xfer_bsc_data(i2c, tmp_buf, bytes_to_xfer, pmsg)))
+ {
+ return err;
+ }
+
+ len -= bytes_to_xfer;
+ tmp_buf += bytes_to_xfer;
+
+ cond_per_msg = COND_NOSTART | COND_NOSTOP;
+ }
+ }
+
+ return num;
+}
+
+const static struct rt_i2c_bus_device_ops brcmstb_i2c_ops =
+{
+ .master_xfer = brcmstb_i2c_master_xfer,
+};
+
+static void brcmstb_i2c_isr(int irq, void *param)
+{
+ rt_uint32_t status_bsc_ctl;
+ struct brcmstb_i2c *i2c = param;
+
+ status_bsc_ctl = bsc_readl(i2c, ctl_reg);
+
+ if (!(status_bsc_ctl & BSC_CTL_REG_INT_EN_MASK))
+ {
+ return;
+ }
+
+ brcmstb_i2c_enable_disable_irq(i2c, RT_FALSE);
+ rt_completion_done(&i2c->done);
+}
+
+static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c *i2c)
+{
+ int i, num_speeds = RT_ARRAY_SIZE(bsc_clk);
+ rt_uint32_t clk_freq_hz = i2c->clk_freq_hz;
+
+ if (brcmstb_i2c_get_data_regsz(i2c) == sizeof(rt_uint32_t))
+ {
+ i2c->bsc_regmap.ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK;
+ }
+ else
+ {
+ i2c->bsc_regmap.ctlhi_reg &= ~BSC_CTLHI_REG_DATAREG_SIZE_MASK;
+ }
+
+ bsc_writel(i2c, ctlhi_reg, i2c->bsc_regmap.ctlhi_reg);
+
+ /* Set bus speed */
+ for (i = 0; i < num_speeds; ++i)
+ {
+ if (bsc_clk[i].hz == clk_freq_hz)
+ {
+ i2c->bsc_regmap.ctl_reg &= ~(BSC_CTL_REG_SCL_SEL_MASK | BSC_CTL_REG_DIV_CLK_MASK);
+ i2c->bsc_regmap.ctl_reg |= bsc_clk[i].scl_mask | bsc_clk[i].div_mask;
+ bsc_writel(i2c, ctl_reg, i2c->bsc_regmap.ctl_reg);
+ break;
+ }
+ }
+
+ /* in case we did not get find a valid speed */
+ if (i == num_speeds)
+ {
+ i = (bsc_readl(i2c, ctl_reg) & BSC_CTL_REG_SCL_SEL_MASK) >> BSC_CTL_REG_SCL_SEL_SHIFT;
+ }
+}
+
+static void brcmstb_i2c_free(struct brcmstb_i2c *i2c)
+{
+ if (i2c->base)
+ {
+ rt_iounmap(i2c->base);
+ }
+
+ rt_free(i2c);
+}
+
+static rt_err_t brcmstb_i2c_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ void *autoi2c;
+ const char *dev_name;
+ struct rt_device *dev = &pdev->parent;
+ struct brcmstb_i2c *i2c = rt_calloc(1, sizeof(*i2c));
+
+ if (!i2c)
+ {
+ return -RT_ENOMEM;
+ }
+
+ i2c->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!i2c->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if (rt_dm_dev_prop_read_bool(dev, "reg-names"))
+ {
+ if (!(autoi2c = rt_dm_dev_iomap_by_name(dev, "auto-i2c")))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ HWREG32(autoi2c + AUTOI2C_CTRL0) = AUTOI2C_CTRL0_RELEASE_BSC;
+ rt_iounmap(autoi2c);
+
+ i2c->bsc_regmap.iic_enable = 0;
+ bsc_writel(i2c, iic_enable, i2c->bsc_regmap.iic_enable);
+ }
+
+ i2c->irq = rt_dm_dev_get_irq(dev, 0);
+
+ brcmstb_i2c_enable_disable_irq(i2c, RT_FALSE);
+
+ if (rt_dm_dev_prop_read_u32(dev, "clock-frequency", &i2c->clk_freq_hz))
+ {
+ i2c->clk_freq_hz = bsc_clk[0].hz;
+ }
+
+ if (rt_ofw_node_is_compatible(dev->ofw_node, "brcm,brcmper-i2c"))
+ {
+ i2c->data_regsz = sizeof(rt_uint8_t);
+ }
+ else
+ {
+ i2c->data_regsz = sizeof(rt_uint32_t);
+ }
+
+ brcmstb_i2c_set_bsc_reg_defaults(i2c);
+
+ rt_completion_init(&i2c->done);
+
+ rt_dm_dev_set_name_auto(&i2c->parent.parent, "i2c");
+ dev_name = rt_dm_dev_get_name(&i2c->parent.parent);
+
+ if (i2c->irq >= 0)
+ {
+ rt_hw_interrupt_install(i2c->irq, brcmstb_i2c_isr, i2c, dev_name);
+ rt_hw_interrupt_umask(i2c->irq);
+ }
+
+ dev->user_data = i2c;
+
+ i2c->parent.ops = &brcmstb_i2c_ops;
+ i2c->parent.parent.ofw_node = dev->ofw_node;
+
+ if ((err = rt_i2c_bus_device_register(&i2c->parent, dev_name)))
+ {
+ goto _free_irq;
+ }
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, i2c);
+
+ return RT_EOK;
+_free_irq:
+ if (i2c->irq >= 0)
+ {
+ rt_hw_interrupt_mask(i2c->irq);
+ rt_pic_detach_irq(i2c->irq, i2c);
+ }
+
+_fail:
+ brcmstb_i2c_free(i2c);
+
+ return err;
+}
+
+static rt_err_t brcmstb_i2c_remove(struct rt_platform_device *pdev)
+{
+ struct brcmstb_i2c *i2c = pdev->parent.user_data;
+
+ if (i2c->irq >= 0)
+ {
+ rt_hw_interrupt_mask(i2c->irq);
+ rt_pic_detach_irq(i2c->irq, i2c);
+ }
+
+ rt_device_unregister(&i2c->parent.parent);
+
+ brcmstb_i2c_free(i2c);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id brcmstb_i2c_ofw_ids[] =
+{
+ { .compatible = "brcm,brcmstb-i2c" },
+ { .compatible = "brcm,brcmper-i2c" },
+ { .compatible = "brcm,bcm2711-hdmi-i2c" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmstb_i2c_driver =
+{
+ .name = "brcmstb-i2c",
+ .ids = brcmstb_i2c_ofw_ids,
+
+ .probe = brcmstb_i2c_probe,
+ .remove = brcmstb_i2c_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(brcmstb_i2c_driver);
diff --git a/bsp/raspberry-pi/dm/include/bcm2835-pm.h b/bsp/raspberry-pi/dm/include/bcm2835-pm.h
new file mode 100755
index 0000000000..1cf48f9be1
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/bcm2835-pm.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#ifndef __BCM2835_PM_H__
+#define __BCM2835_PM_H__
+
+struct bcm2835_pm
+{
+ void *base;
+ void *asb;
+ void *rpivid_asb;
+
+ void *ofw_node;
+};
+
+#endif /* __BCM2835_PM_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835-aux.h b/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835-aux.h
new file mode 100755
index 0000000000..189b2b48ad
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835-aux.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BCM2835_AUX_H__
+#define __DT_BINDINGS_CLOCK_BCM2835_AUX_H__
+
+#define BCM2835_AUX_CLOCK_UART 0
+#define BCM2835_AUX_CLOCK_SPI1 1
+#define BCM2835_AUX_CLOCK_SPI2 2
+#define BCM2835_AUX_CLOCK_COUNT 3
+
+#endif /* __DT_BINDINGS_CLOCK_BCM2835_AUX_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835.h b/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835.h
new file mode 100755
index 0000000000..0182e3aac7
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/clock/bcm2835.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BCM2835_H__
+#define __DT_BINDINGS_CLOCK_BCM2835_H__
+
+#define BCM2835_PLLA 0
+#define BCM2835_PLLB 1
+#define BCM2835_PLLC 2
+#define BCM2835_PLLD 3
+#define BCM2835_PLLH 4
+
+#define BCM2835_PLLA_CORE 5
+#define BCM2835_PLLA_PER 6
+#define BCM2835_PLLB_ARM 7
+#define BCM2835_PLLC_CORE0 8
+#define BCM2835_PLLC_CORE1 9
+#define BCM2835_PLLC_CORE2 10
+#define BCM2835_PLLC_PER 11
+#define BCM2835_PLLD_CORE 12
+#define BCM2835_PLLD_PER 13
+#define BCM2835_PLLH_RCAL 14
+#define BCM2835_PLLH_AUX 15
+#define BCM2835_PLLH_PIX 16
+
+#define BCM2835_CLOCK_TIMER 17
+#define BCM2835_CLOCK_OTP 18
+#define BCM2835_CLOCK_UART 19
+#define BCM2835_CLOCK_VPU 20
+#define BCM2835_CLOCK_V3D 21
+#define BCM2835_CLOCK_ISP 22
+#define BCM2835_CLOCK_H264 23
+#define BCM2835_CLOCK_VEC 24
+#define BCM2835_CLOCK_HSM 25
+#define BCM2835_CLOCK_SDRAM 26
+#define BCM2835_CLOCK_TSENS 27
+#define BCM2835_CLOCK_EMMC 28
+#define BCM2835_CLOCK_PERI_IMAGE 29
+#define BCM2835_CLOCK_PWM 30
+#define BCM2835_CLOCK_PCM 31
+
+#define BCM2835_PLLA_DSI0 32
+#define BCM2835_PLLA_CCP2 33
+#define BCM2835_PLLD_DSI0 34
+#define BCM2835_PLLD_DSI1 35
+
+#define BCM2835_CLOCK_AVEO 36
+#define BCM2835_CLOCK_DFT 37
+#define BCM2835_CLOCK_GP0 38
+#define BCM2835_CLOCK_GP1 39
+#define BCM2835_CLOCK_GP2 40
+#define BCM2835_CLOCK_SLIM 41
+#define BCM2835_CLOCK_SMI 42
+#define BCM2835_CLOCK_TEC 43
+#define BCM2835_CLOCK_DPI 44
+#define BCM2835_CLOCK_CAM0 45
+#define BCM2835_CLOCK_CAM1 46
+#define BCM2835_CLOCK_DSI0E 47
+#define BCM2835_CLOCK_DSI1E 48
+#define BCM2835_CLOCK_DSI0P 49
+#define BCM2835_CLOCK_DSI1P 50
+
+#define BCM2711_CLOCK_EMMC2 51
+
+#endif /* __DT_BINDINGS_CLOCK_BCM2835_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/clock/rp1.h b/bsp/raspberry-pi/dm/include/dt-bindings/clock/rp1.h
new file mode 100755
index 0000000000..da56a95a90
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/clock/rp1.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_RP1_H__
+#define __DT_BINDINGS_CLOCK_RP1_H__
+
+#define RP1_PLL_SYS_CORE 0
+#define RP1_PLL_AUDIO_CORE 1
+#define RP1_PLL_VIDEO_CORE 2
+
+#define RP1_PLL_SYS 3
+#define RP1_PLL_AUDIO 4
+#define RP1_PLL_VIDEO 5
+
+#define RP1_PLL_SYS_PRI_PH 6
+#define RP1_PLL_SYS_SEC_PH 7
+#define RP1_PLL_AUDIO_PRI_PH 8
+
+#define RP1_PLL_SYS_SEC 9
+#define RP1_PLL_AUDIO_SEC 10
+#define RP1_PLL_VIDEO_SEC 11
+
+#define RP1_CLK_SYS 12
+#define RP1_CLK_SLOW_SYS 13
+#define RP1_CLK_DMA 14
+#define RP1_CLK_UART 15
+#define RP1_CLK_ETH 16
+#define RP1_CLK_PWM0 17
+#define RP1_CLK_PWM1 18
+#define RP1_CLK_AUDIO_IN 19
+#define RP1_CLK_AUDIO_OUT 20
+#define RP1_CLK_I2S 21
+#define RP1_CLK_MIPI0_CFG 22
+#define RP1_CLK_MIPI1_CFG 23
+#define RP1_CLK_PCIE_AUX 24
+#define RP1_CLK_USBH0_MICROFRAME 25
+#define RP1_CLK_USBH1_MICROFRAME 26
+#define RP1_CLK_USBH0_SUSPEND 27
+#define RP1_CLK_USBH1_SUSPEND 28
+#define RP1_CLK_ETH_TSU 29
+#define RP1_CLK_ADC 30
+#define RP1_CLK_SDIO_TIMER 31
+#define RP1_CLK_SDIO_ALT_SRC 32
+#define RP1_CLK_GP0 33
+#define RP1_CLK_GP1 34
+#define RP1_CLK_GP2 35
+#define RP1_CLK_GP3 36
+#define RP1_CLK_GP4 37
+#define RP1_CLK_GP5 38
+#define RP1_CLK_VEC 39
+#define RP1_CLK_DPI 40
+#define RP1_CLK_MIPI0_DPI 41
+#define RP1_CLK_MIPI1_DPI 42
+
+/* Extra PLL output channels - RP1B0 only */
+#define RP1_PLL_VIDEO_PRI_PH 43
+#define RP1_PLL_AUDIO_TERN 44
+
+/* MIPI clocks managed by the DSI driver */
+#define RP1_CLK_MIPI0_DSI_BYTECLOCK 45
+#define RP1_CLK_MIPI1_DSI_BYTECLOCK 46
+
+#endif /* __DT_BINDINGS_CLOCK_RP1_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/mfd/rp1.h b/bsp/raspberry-pi/dm/include/dt-bindings/mfd/rp1.h
new file mode 100755
index 0000000000..c935229840
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/mfd/rp1.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_MFD_RP1_H__
+#define __DT_BINDINGS_MFD_RP1_H__
+
+/* Address map */
+#define RP1_SYSINFO_BASE 0x000000
+#define RP1_TBMAN_BASE 0x004000
+#define RP1_SYSCFG_BASE 0x008000
+#define RP1_OTP_BASE 0x00c000
+#define RP1_POWER_BASE 0x010000
+#define RP1_RESETS_BASE 0x014000
+#define RP1_CLOCKS_BANK_DEFAULT_BASE 0x018000
+#define RP1_CLOCKS_BANK_VIDEO_BASE 0x01c000
+#define RP1_PLL_SYS_BASE 0x020000
+#define RP1_PLL_AUDIO_BASE 0x024000
+#define RP1_PLL_VIDEO_BASE 0x028000
+#define RP1_UART0_BASE 0x030000
+#define RP1_UART1_BASE 0x034000
+#define RP1_UART2_BASE 0x038000
+#define RP1_UART3_BASE 0x03c000
+#define RP1_UART4_BASE 0x040000
+#define RP1_UART5_BASE 0x044000
+#define RP1_SPI8_BASE 0x04c000
+#define RP1_SPI0_BASE 0x050000
+#define RP1_SPI1_BASE 0x054000
+#define RP1_SPI2_BASE 0x058000
+#define RP1_SPI3_BASE 0x05c000
+#define RP1_SPI4_BASE 0x060000
+#define RP1_SPI5_BASE 0x064000
+#define RP1_SPI6_BASE 0x068000
+#define RP1_SPI7_BASE 0x06c000
+#define RP1_I2C0_BASE 0x070000
+#define RP1_I2C1_BASE 0x074000
+#define RP1_I2C2_BASE 0x078000
+#define RP1_I2C3_BASE 0x07c000
+#define RP1_I2C4_BASE 0x080000
+#define RP1_I2C5_BASE 0x084000
+#define RP1_I2C6_BASE 0x088000
+#define RP1_AUDIO_IN_BASE 0x090000
+#define RP1_AUDIO_OUT_BASE 0x094000
+#define RP1_PWM0_BASE 0x098000
+#define RP1_PWM1_BASE 0x09c000
+#define RP1_I2S0_BASE 0x0a0000
+#define RP1_I2S1_BASE 0x0a4000
+#define RP1_I2S2_BASE 0x0a8000
+#define RP1_TIMER_BASE 0x0ac000
+#define RP1_SDIO0_APBS_BASE 0x0b0000
+#define RP1_SDIO1_APBS_BASE 0x0b4000
+#define RP1_BUSFABRIC_MONITOR_BASE 0x0c0000
+#define RP1_BUSFABRIC_AXISHIM_BASE 0x0c4000
+#define RP1_ADC_BASE 0x0c8000
+#define RP1_IO_BANK0_BASE 0x0d0000
+#define RP1_IO_BANK1_BASE 0x0d4000
+#define RP1_IO_BANK2_BASE 0x0d8000
+#define RP1_SYS_RIO0_BASE 0x0e0000
+#define RP1_SYS_RIO1_BASE 0x0e4000
+#define RP1_SYS_RIO2_BASE 0x0e8000
+#define RP1_PADS_BANK0_BASE 0x0f0000
+#define RP1_PADS_BANK1_BASE 0x0f4000
+#define RP1_PADS_BANK2_BASE 0x0f8000
+#define RP1_PADS_ETH_BASE 0x0fc000
+#define RP1_ETH_IP_BASE 0x100000
+#define RP1_ETH_CFG_BASE 0x104000
+#define RP1_PCIE_APBS_BASE 0x108000
+#define RP1_MIPI0_CSIDMA_BASE 0x110000
+#define RP1_MIPI0_CSIHOST_BASE 0x114000
+#define RP1_MIPI0_DSIDMA_BASE 0x118000
+#define RP1_MIPI0_DSIHOST_BASE 0x11c000
+#define RP1_MIPI0_MIPICFG_BASE 0x120000
+#define RP1_MIPI0_ISP_BASE 0x124000
+#define RP1_MIPI1_CSIDMA_BASE 0x128000
+#define RP1_MIPI1_CSIHOST_BASE 0x12c000
+#define RP1_MIPI1_DSIDMA_BASE 0x130000
+#define RP1_MIPI1_DSIHOST_BASE 0x134000
+#define RP1_MIPI1_MIPICFG_BASE 0x138000
+#define RP1_MIPI1_ISP_BASE 0x13c000
+#define RP1_VIDEO_OUT_CFG_BASE 0x140000
+#define RP1_VIDEO_OUT_VEC_BASE 0x144000
+#define RP1_VIDEO_OUT_DPI_BASE 0x148000
+#define RP1_XOSC_BASE 0x150000
+#define RP1_WATCHDOG_BASE 0x154000
+#define RP1_DMA_TICK_BASE 0x158000
+#define RP1_SDIO_CLOCKS_BASE 0x15c000
+#define RP1_USBHOST0_APBS_BASE 0x160000
+#define RP1_USBHOST1_APBS_BASE 0x164000
+#define RP1_ROSC0_BASE 0x168000
+#define RP1_ROSC1_BASE 0x16c000
+#define RP1_VBUSCTRL_BASE 0x170000
+#define RP1_TICKS_BASE 0x174000
+#define RP1_PIO_APBS_BASE 0x178000
+#define RP1_SDIO0_AHBLS_BASE 0x180000
+#define RP1_SDIO1_AHBLS_BASE 0x184000
+#define RP1_DMA_BASE 0x188000
+#define RP1_RAM_BASE 0x1c0000
+#define RP1_RAM_SIZE 0x020000
+#define RP1_USBHOST0_AXIS_BASE 0x200000
+#define RP1_USBHOST1_AXIS_BASE 0x300000
+#define RP1_EXAC_BASE 0x400000
+
+/* Interrupts */
+
+#define RP1_INT_IO_BANK0 0
+#define RP1_INT_IO_BANK1 1
+#define RP1_INT_IO_BANK2 2
+#define RP1_INT_AUDIO_IN 3
+#define RP1_INT_AUDIO_OUT 4
+#define RP1_INT_PWM0 5
+#define RP1_INT_ETH 6
+#define RP1_INT_I2C0 7
+#define RP1_INT_I2C1 8
+#define RP1_INT_I2C2 9
+#define RP1_INT_I2C3 10
+#define RP1_INT_I2C4 11
+#define RP1_INT_I2C5 12
+#define RP1_INT_I2C6 13
+#define RP1_INT_I2S0 14
+#define RP1_INT_I2S1 15
+#define RP1_INT_I2S2 16
+#define RP1_INT_SDIO0 17
+#define RP1_INT_SDIO1 18
+#define RP1_INT_SPI0 19
+#define RP1_INT_SPI1 20
+#define RP1_INT_SPI2 21
+#define RP1_INT_SPI3 22
+#define RP1_INT_SPI4 23
+#define RP1_INT_SPI5 24
+#define RP1_INT_UART0 25
+#define RP1_INT_TIMER_0 26
+#define RP1_INT_TIMER_1 27
+#define RP1_INT_TIMER_2 28
+#define RP1_INT_TIMER_3 29
+#define RP1_INT_USBHOST0 30
+#define RP1_INT_USBHOST0_0 31
+#define RP1_INT_USBHOST0_1 32
+#define RP1_INT_USBHOST0_2 33
+#define RP1_INT_USBHOST0_3 34
+#define RP1_INT_USBHOST1 35
+#define RP1_INT_USBHOST1_0 36
+#define RP1_INT_USBHOST1_1 37
+#define RP1_INT_USBHOST1_2 38
+#define RP1_INT_USBHOST1_3 39
+#define RP1_INT_DMA 40
+#define RP1_INT_PWM1 41
+#define RP1_INT_UART1 42
+#define RP1_INT_UART2 43
+#define RP1_INT_UART3 44
+#define RP1_INT_UART4 45
+#define RP1_INT_UART5 46
+#define RP1_INT_MIPI0 47
+#define RP1_INT_MIPI1 48
+#define RP1_INT_VIDEO_OUT 49
+#define RP1_INT_PIO_0 50
+#define RP1_INT_PIO_1 51
+#define RP1_INT_ADC_FIFO 52
+#define RP1_INT_PCIE_OUT 53
+#define RP1_INT_SPI6 54
+#define RP1_INT_SPI7 55
+#define RP1_INT_SPI8 56
+#define RP1_INT_SYSCFG 58
+#define RP1_INT_CLOCKS_DEFAULT 59
+#define RP1_INT_VBUSCTRL 60
+#define RP1_INT_PROC_MISC 57
+#define RP1_INT_END 61
+
+/* DMA peripherals (for pacing) */
+#define RP1_DMA_I2C0_RX 0x0
+#define RP1_DMA_I2C0_TX 0x1
+#define RP1_DMA_I2C1_RX 0x2
+#define RP1_DMA_I2C1_TX 0x3
+#define RP1_DMA_I2C2_RX 0x4
+#define RP1_DMA_I2C2_TX 0x5
+#define RP1_DMA_I2C3_RX 0x6
+#define RP1_DMA_I2C3_TX 0x7
+#define RP1_DMA_I2C4_RX 0x8
+#define RP1_DMA_I2C4_TX 0x9
+#define RP1_DMA_I2C5_RX 0xa
+#define RP1_DMA_I2C5_TX 0xb
+#define RP1_DMA_SPI0_RX 0xc
+#define RP1_DMA_SPI0_TX 0xd
+#define RP1_DMA_SPI1_RX 0xe
+#define RP1_DMA_SPI1_TX 0xf
+#define RP1_DMA_SPI2_RX 0x10
+#define RP1_DMA_SPI2_TX 0x11
+#define RP1_DMA_SPI3_RX 0x12
+#define RP1_DMA_SPI3_TX 0x13
+#define RP1_DMA_SPI4_RX 0x14
+#define RP1_DMA_SPI4_TX 0x15
+#define RP1_DMA_SPI5_RX 0x16
+#define RP1_DMA_SPI5_TX 0x17
+#define RP1_DMA_PWM0 0x18
+#define RP1_DMA_UART0_RX 0x19
+#define RP1_DMA_UART0_TX 0x1a
+#define RP1_DMA_AUDIO_IN_CH0 0x1b
+#define RP1_DMA_AUDIO_IN_CH1 0x1c
+#define RP1_DMA_AUDIO_OUT 0x1d
+#define RP1_DMA_PWM1 0x1e
+#define RP1_DMA_I2S0_RX 0x1f
+#define RP1_DMA_I2S0_TX 0x20
+#define RP1_DMA_I2S1_RX 0x21
+#define RP1_DMA_I2S1_TX 0x22
+#define RP1_DMA_I2S2_RX 0x23
+#define RP1_DMA_I2S2_TX 0x24
+#define RP1_DMA_UART1_RX 0x25
+#define RP1_DMA_UART1_TX 0x26
+#define RP1_DMA_UART2_RX 0x27
+#define RP1_DMA_UART2_TX 0x28
+#define RP1_DMA_UART3_RX 0x29
+#define RP1_DMA_UART3_TX 0x2a
+#define RP1_DMA_UART4_RX 0x2b
+#define RP1_DMA_UART4_TX 0x2c
+#define RP1_DMA_UART5_RX 0x2d
+#define RP1_DMA_UART5_TX 0x2e
+#define RP1_DMA_ADC 0x2f
+#define RP1_DMA_DMA_TICK_TICK0 0x30
+#define RP1_DMA_DMA_TICK_TICK1 0x31
+#define RP1_DMA_SPI6_RX 0x32
+#define RP1_DMA_SPI6_TX 0x33
+#define RP1_DMA_SPI7_RX 0x34
+#define RP1_DMA_SPI7_TX 0x35
+#define RP1_DMA_SPI8_RX 0x36
+#define RP1_DMA_SPI8_TX 0x37
+#define RP1_DMA_PIO_CH0_TX 0x38
+#define RP1_DMA_PIO_CH0_RX 0x39
+#define RP1_DMA_PIO_CH1_TX 0x3a
+#define RP1_DMA_PIO_CH1_RX 0x3b
+#define RP1_DMA_PIO_CH2_TX 0x3c
+#define RP1_DMA_PIO_CH2_RX 0x3d
+#define RP1_DMA_PIO_CH3_TX 0x3e
+#define RP1_DMA_PIO_CH3_RX 0x3f
+
+#endif /* __DT_BINDINGS_MFD_RP1_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/pinctrl/bcm2835.h b/bsp/raspberry-pi/dm/include/dt-bindings/pinctrl/bcm2835.h
new file mode 100755
index 0000000000..c98752b200
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/pinctrl/bcm2835.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_PINCTRL_BCM2835_H__
+#define __DT_BINDINGS_PINCTRL_BCM2835_H__
+
+/* brcm,function property */
+#define BCM2835_FSEL_GPIO_IN 0
+#define BCM2835_FSEL_GPIO_OUT 1
+#define BCM2835_FSEL_ALT5 2
+#define BCM2835_FSEL_ALT4 3
+#define BCM2835_FSEL_ALT0 4
+#define BCM2835_FSEL_ALT1 5
+#define BCM2835_FSEL_ALT2 6
+#define BCM2835_FSEL_ALT3 7
+
+/* brcm,pull property */
+#define BCM2835_PUD_OFF 0
+#define BCM2835_PUD_DOWN 1
+#define BCM2835_PUD_UP 2
+
+#endif /* __DT_BINDINGS_PINCTRL_BCM2835_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/power/bcm2835-pm.h b/bsp/raspberry-pi/dm/include/dt-bindings/power/bcm2835-pm.h
new file mode 100755
index 0000000000..5864167be0
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/power/bcm2835-pm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_POWER_BCM2835_PM_H__
+#define __DT_BINDINGS_POWER_BCM2835_PM_H__
+
+#define BCM2835_POWER_DOMAIN_GRAFX 0
+#define BCM2835_POWER_DOMAIN_GRAFX_V3D 1
+#define BCM2835_POWER_DOMAIN_IMAGE 2
+#define BCM2835_POWER_DOMAIN_IMAGE_PERI 3
+#define BCM2835_POWER_DOMAIN_IMAGE_ISP 4
+#define BCM2835_POWER_DOMAIN_IMAGE_H264 5
+#define BCM2835_POWER_DOMAIN_USB 6
+#define BCM2835_POWER_DOMAIN_DSI0 7
+#define BCM2835_POWER_DOMAIN_DSI1 8
+#define BCM2835_POWER_DOMAIN_CAM0 9
+#define BCM2835_POWER_DOMAIN_CAM1 10
+#define BCM2835_POWER_DOMAIN_CCP2TX 11
+#define BCM2835_POWER_DOMAIN_HDMI 12
+
+#define BCM2835_POWER_DOMAIN_COUNT 13
+
+#define BCM2835_RESET_V3D 0
+#define BCM2835_RESET_ISP 1
+#define BCM2835_RESET_H264 2
+
+#define BCM2835_RESET_COUNT 3
+
+#endif /* __DT_BINDINGS_POWER_BCM2835_PM_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/power/raspberrypi-power.h b/bsp/raspberry-pi/dm/include/dt-bindings/power/raspberrypi-power.h
new file mode 100755
index 0000000000..573c39206b
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/power/raspberrypi-power.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_POWER_RASPBERRYPI_POWER_H__
+#define __DT_BINDINGS_POWER_RASPBERRYPI_POWER_H__
+
+#define RPI_POWER_DOMAIN_I2C0 0
+#define RPI_POWER_DOMAIN_I2C1 1
+#define RPI_POWER_DOMAIN_I2C2 2
+#define RPI_POWER_DOMAIN_VIDEO_SCALER 3
+#define RPI_POWER_DOMAIN_VPU1 4
+#define RPI_POWER_DOMAIN_HDMI 5
+#define RPI_POWER_DOMAIN_USB 6
+#define RPI_POWER_DOMAIN_VEC 7
+#define RPI_POWER_DOMAIN_JPEG 8
+#define RPI_POWER_DOMAIN_H264 9
+#define RPI_POWER_DOMAIN_V3D 10
+#define RPI_POWER_DOMAIN_ISP 11
+#define RPI_POWER_DOMAIN_UNICAM0 12
+#define RPI_POWER_DOMAIN_UNICAM1 13
+#define RPI_POWER_DOMAIN_CCP2RX 14
+#define RPI_POWER_DOMAIN_CSI2 15
+#define RPI_POWER_DOMAIN_CPI 16
+#define RPI_POWER_DOMAIN_DSI0 17
+#define RPI_POWER_DOMAIN_DSI1 18
+#define RPI_POWER_DOMAIN_TRANSPOSER 19
+#define RPI_POWER_DOMAIN_CCP2TX 20
+#define RPI_POWER_DOMAIN_CDP 21
+#define RPI_POWER_DOMAIN_ARM 22
+
+#define RPI_POWER_DOMAIN_COUNT 23
+
+#endif /* __DT_BINDINGS_POWER_BCMRASPBERRYPI_POWERH__ */
diff --git a/bsp/raspberry-pi/dm/include/dt-bindings/reset/raspberrypi,firmware-reset.h b/bsp/raspberry-pi/dm/include/dt-bindings/reset/raspberrypi,firmware-reset.h
new file mode 100755
index 0000000000..37c6135325
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dt-bindings/reset/raspberrypi,firmware-reset.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __DT_BINDINGS_POWER_RASPBERRYPI_FIRMWARE_RESET_H__
+#define __DT_BINDINGS_POWER_RASPBERRYPI_FIRMWARE_RESET_H__
+
+#define RASPBERRYPI_FIRMWARE_RESET_ID_USB 0
+#define RASPBERRYPI_FIRMWARE_RESET_NUM_IDS 1
+
+#endif /* __DT_BINDINGS_POWER_RASPBERRYPI_FIRMWARE_RESET_H__ */
diff --git a/bsp/raspberry-pi/dm/include/dvfs-raspberrypi-cpufreq.h b/bsp/raspberry-pi/dm/include/dvfs-raspberrypi-cpufreq.h
new file mode 100644
index 0000000000..15092a7c92
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/dvfs-raspberrypi-cpufreq.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#ifndef __DVFS_RASPBERRYPI_CPUFREQ_H__
+#define __DVFS_RASPBERRYPI_CPUFREQ_H__
+
+#include <rtdevice.h>
+#include <firmware-raspberrypi.h>
+
+struct rt_clk *raspberrypi_arm_clk_get(void);
+rt_err_t raspberrypi_cpufreq_register(struct rt_clk *arm_clk, struct rt_ofw_node *cpu_np,
+ struct rpi_firmware *rpi_fw);
+
+#endif /* __DVFS_RASPBERRYPI_CPUFREQ_H__ */
diff --git a/bsp/raspberry-pi/dm/include/firmware-raspberrypi.h b/bsp/raspberry-pi/dm/include/firmware-raspberrypi.h
new file mode 100755
index 0000000000..ab949ae1aa
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/firmware-raspberrypi.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#ifndef __RASPBERRYPI_FIRMWARE_H__
+#define __RASPBERRYPI_FIRMWARE_H__
+
+#include <rtdevice.h>
+
+struct rpi_firmware;
+
+enum rpi_firmware_property_status
+{
+ RPI_FIRMWARE_STATUS_REQUEST = 0,
+ RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000,
+ RPI_FIRMWARE_STATUS_ERROR = 0x80000001,
+};
+
+struct rpi_firmware_property_tag_header
+{
+ rt_uint32_t tag;
+ rt_uint32_t buf_size;
+ rt_uint32_t req_resp_size; /* always 4 byte aligned */
+};
+
+enum rpi_firmware_property_tag
+{
+ RPI_FIRMWARE_PROPERTY_END = 0,
+ RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001,
+ RPI_FIRMWARE_GET_FIRMWARE_VARIANT = 0x00000002,
+ RPI_FIRMWARE_GET_FIRMWARE_HASH = 0x00000003,
+
+ RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010,
+ RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011,
+
+ RPI_FIRMWARE_GET_BOARD_MODEL = 0x00010001,
+ RPI_FIRMWARE_GET_BOARD_REVISION = 0x00010002,
+ RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS = 0x00010003,
+ RPI_FIRMWARE_GET_BOARD_SERIAL = 0x00010004,
+ RPI_FIRMWARE_GET_ARM_MEMORY = 0x00010005,
+ RPI_FIRMWARE_GET_VC_MEMORY = 0x00010006,
+ RPI_FIRMWARE_GET_CLOCKS = 0x00010007,
+ RPI_FIRMWARE_GET_POWER_STATE = 0x00020001,
+ RPI_FIRMWARE_GET_TIMING = 0x00020002,
+ RPI_FIRMWARE_SET_POWER_STATE = 0x00028001,
+ RPI_FIRMWARE_GET_CLOCK_STATE = 0x00030001,
+ RPI_FIRMWARE_GET_CLOCK_RATE = 0x00030002,
+ RPI_FIRMWARE_GET_VOLTAGE = 0x00030003,
+ RPI_FIRMWARE_GET_MAX_CLOCK_RATE = 0x00030004,
+ RPI_FIRMWARE_GET_MAX_VOLTAGE = 0x00030005,
+ RPI_FIRMWARE_GET_TEMPERATURE = 0x00030006,
+ RPI_FIRMWARE_GET_MIN_CLOCK_RATE = 0x00030007,
+ RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008,
+ RPI_FIRMWARE_GET_TURBO = 0x00030009,
+ RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a,
+ RPI_FIRMWARE_GET_STC = 0x0003000b,
+ RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c,
+ RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d,
+ RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e,
+ RPI_FIRMWARE_RELEASE_MEMORY = 0x0003000f,
+ RPI_FIRMWARE_EXECUTE_CODE = 0x00030010,
+ RPI_FIRMWARE_EXECUTE_QPU = 0x00030011,
+ RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012,
+ RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
+ RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020,
+ RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021,
+ RPI_FIRMWARE_GET_EDID_BLOCK_DISPLAY = 0x00030023,
+ RPI_FIRMWARE_GET_USER_OTP = 0x00030024,
+ RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030,
+ RPI_FIRMWARE_GET_THROTTLED = 0x00030046,
+ RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047,
+ RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048,
+ RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001,
+ RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002,
+ RPI_FIRMWARE_SET_VOLTAGE = 0x00038003,
+ RPI_FIRMWARE_SET_TURBO = 0x00038009,
+ RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021,
+ RPI_FIRMWARE_SET_USER_OTP = 0x00038024,
+ RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030,
+ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041,
+ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041,
+ RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042,
+ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043,
+ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043,
+ RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045,
+ RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045,
+ RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049,
+ RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00038049,
+ RPI_FIRMWARE_SET_POE_HAT_VAL_OLD = 0x00030050,
+ RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,
+ RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064,
+ RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064,
+ RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066,
+ RPI_FIRMWARE_GET_BUTTONS_PRESSED = 0x00030088,
+ RPI_FIRMWARE_GET_RTC_REG = 0x00030087,
+ RPI_FIRMWARE_SET_RTC_REG = 0x00038087,
+
+ /* Dispmanx TAGS */
+ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
+ RPI_FIRMWARE_FRAMEBUFFER_BLANK = 0x00040002,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH = 0x00040005,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH = 0x00040008,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_LAYER = 0x0004000c,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
+ RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PITCH = 0x00048008,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
+
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_LAYER = 0x0004800c,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
+
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010,
+
+ RPI_FIRMWARE_SET_PLANE = 0x00048015,
+ RPI_FIRMWARE_GET_DISPLAY_TIMING = 0x00040017,
+ RPI_FIRMWARE_SET_TIMING = 0x00048017,
+ RPI_FIRMWARE_GET_DISPLAY_CFG = 0x00040018,
+ RPI_FIRMWARE_SET_DISPLAY_POWER = 0x00048019,
+ RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001,
+ RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
+};
+
+enum rpi_firmware_clk_id
+{
+ RPI_FIRMWARE_EMMC_CLK_ID = 1,
+ RPI_FIRMWARE_UART_CLK_ID,
+ RPI_FIRMWARE_ARM_CLK_ID,
+ RPI_FIRMWARE_CORE_CLK_ID,
+ RPI_FIRMWARE_V3D_CLK_ID,
+ RPI_FIRMWARE_H264_CLK_ID,
+ RPI_FIRMWARE_ISP_CLK_ID,
+ RPI_FIRMWARE_SDRAM_CLK_ID,
+ RPI_FIRMWARE_PIXEL_CLK_ID,
+ RPI_FIRMWARE_PWM_CLK_ID,
+ RPI_FIRMWARE_HEVC_CLK_ID,
+ RPI_FIRMWARE_EMMC2_CLK_ID,
+ RPI_FIRMWARE_M2MC_CLK_ID,
+ RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
+ RPI_FIRMWARE_VEC_CLK_ID,
+ RPI_FIRMWARE_DISP_CLK_ID,
+ RPI_FIRMWARE_NUM_CLK_ID,
+};
+
+#define GET_DISPLAY_SETTINGS_PAYLOAD_SIZE 64
+
+rt_packed(struct rpi_firmware_clk_rate_request
+{
+ rt_le32_t id; /* ID of the clock being queried */
+ rt_le32_t rate; /* Rate in Hertz. Set by the firmware */
+});
+
+#define RPI_FIRMWARE_CLK_RATE_REQUEST(ID) \
+{ \
+ .id = ID, \
+}
+
+void *rpi_firmware_property_raw_alloc(struct rpi_firmware *rpi_fw,
+ rt_size_t max_header_tag_size, rt_ubase_t *out_bus_addr);
+void rpi_firmware_property_raw_free(struct rpi_firmware *rpi_fw,
+ rt_size_t max_header_tag_size, void *buf, rt_ubase_t bus_addr);
+
+rt_err_t rpi_firmware_property(struct rpi_firmware *rpi_fw,
+ rt_uint32_t tag, void *tag_data, rt_size_t buf_size);
+rt_err_t rpi_firmware_property_raw(struct rpi_firmware *rpi_fw, rt_uint32_t tag,
+ rt_ubase_t bus_addr, struct rpi_firmware_property_tag_header *header, rt_size_t req_size);
+rt_err_t rpi_firmware_property_list(struct rpi_firmware *rpi_fw,
+ void *data, rt_size_t tag_size);
+rt_err_t rpi_firmware_property_list_raw(struct rpi_firmware *rpi_fw,
+ rt_ubase_t bus_addr, void *data, rt_size_t tag_size);
+
+rt_uint32_t rpi_firmware_clk_get_max_rate(struct rpi_firmware *rpi_fw, rt_uint32_t id);
+
+struct rt_ofw_node *rpi_firmware_find_node(void);
+struct rpi_firmware *rpi_firmware_get(struct rt_ofw_node *fw_np);
+void rpi_firmware_put(struct rpi_firmware *rpi_fw);
+
+#endif /* __RASPBERRYPI_FIRMWARE_H__ */
diff --git a/bsp/raspberry-pi/dm/include/rpi-sense.h b/bsp/raspberry-pi/dm/include/rpi-sense.h
new file mode 100755
index 0000000000..1c5a9937d6
--- /dev/null
+++ b/bsp/raspberry-pi/dm/include/rpi-sense.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#ifndef __RPISENSE_H__
+#define __RPISENSE_H__
+
+#include <sys/ioctl.h>
+
+#define SENSEFB_FBIO_IOC_MAGIC 0xf1
+
+#define SENSEFB_FBIOGET_GAMMA _IO(SENSEFB_FBIO_IOC_MAGIC, 0)
+#define SENSEFB_FBIOSET_GAMMA _IO(SENSEFB_FBIO_IOC_MAGIC, 1)
+#define SENSEFB_FBIORESET_GAMMA _IO(SENSEFB_FBIO_IOC_MAGIC, 2)
+
+/*
+ * Register values.
+ */
+#define RPISENSE_FB 0x00
+#define RPISENSE_WAI 0xf0
+#define RPISENSE_VER 0xf1
+#define RPISENSE_KEYS 0xf2
+#define RPISENSE_EE_WP 0xf3
+
+#define RPISENSE_ID 's'
+
+struct rpisense
+{
+ struct rt_i2c_client *i2c_client;
+
+ struct rt_platform_device joystick_dev;
+ struct rt_platform_device framebuffer_dev;
+};
+
+rt_int32_t rpisense_reg_read(struct rpisense *rpisense, int reg);
+rt_ssize_t rpisense_block_write(struct rpisense *rpisense, const char *buf, int count);
+
+#endif /* __RPISENSE_H__ */
diff --git a/bsp/raspberry-pi/dm/input/SConscript b/bsp/raspberry-pi/dm/input/SConscript
new file mode 100755
index 0000000000..3d15055d62
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/SConscript
@@ -0,0 +1,13 @@
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+ path = os.path.join(cwd, d)
+ if os.path.isfile(os.path.join(path, 'SConscript')):
+ objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')
diff --git a/bsp/raspberry-pi/dm/input/joystick/Kconfig b/bsp/raspberry-pi/dm/input/joystick/Kconfig
new file mode 100755
index 0000000000..b5be7b9cc7
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/joystick/Kconfig
@@ -0,0 +1,5 @@
+config RT_INPUT_JOYSTICK_RPISENSE
+ bool "Raspberry Pi Sense HAT joystick"
+ depends on RT_INPUT_JOYSTICK
+ depends on RT_MFD_RPI_SENSE
+ default n
diff --git a/bsp/raspberry-pi/dm/input/joystick/SConscript b/bsp/raspberry-pi/dm/input/joystick/SConscript
new file mode 100755
index 0000000000..4061a05e44
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/joystick/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../../include']
+
+if GetDepend(['RT_INPUT_JOYSTICK_RPISENSE']):
+ src += ['js-rpisense.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/input/joystick/js-rpisense.c b/bsp/raspberry-pi/dm/input/joystick/js-rpisense.c
new file mode 100755
index 0000000000..9bfeaea847
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/joystick/js-rpisense.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <rpi-sense.h>
+
+struct rpisense_joystick
+{
+ struct rt_input_device parent;
+ struct rpisense *rpisense;
+
+ rt_base_t pin;
+ rt_uint8_t active_val;
+ rt_int32_t prev_keys;
+
+ struct rt_thread *keys_task;
+};
+
+static rt_uint8_t keymap[5] =
+{
+ KEY_DOWN, KEY_RIGHT, KEY_UP, KEY_ENTER, KEY_LEFT
+};
+
+static void rpisense_keys_task(void *param)
+{
+ rt_int32_t keys, changes;
+ struct rpisense_joystick *rpisense_js = param;
+
+ while (RT_TRUE)
+ {
+ rt_thread_suspend(rpisense_js->keys_task);
+ rt_schedule();
+
+ keys = rpisense_reg_read(rpisense_js->rpisense, RPISENSE_KEYS);
+ changes = keys ^ rpisense_js->prev_keys;
+ rpisense_js->prev_keys = keys;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(keymap); ++i)
+ {
+ if (changes & 1)
+ {
+ rt_input_report_key(&rpisense_js->parent, keymap[i], keys & 1);
+ }
+
+ changes >>= 1;
+ keys >>= 1;
+ }
+
+ rt_input_sync(&rpisense_js->parent);
+ }
+}
+
+static void rpisense_isr(void *args)
+{
+ struct rpisense_joystick *rpisense_js = args;
+
+ rt_thread_resume(rpisense_js->keys_task);
+}
+
+static rt_err_t rpisense_js_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rpisense *rpisense = pdev->priv;
+ struct rpisense_joystick *rpisense_js = rt_calloc(1, sizeof(*rpisense_js));
+
+ if (!rpisense_js)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rpisense_js->rpisense = rpisense;
+ rpisense_js->pin = rt_pin_get_named_pin(&rpisense->i2c_client->parent,
+ "keys-int", 0, RT_NULL, &rpisense_js->active_val);
+
+ if (rpisense_js->pin < 0)
+ {
+ err = rpisense_js->pin;
+ goto _fail;
+ }
+
+ rt_pin_write(rpisense_js->pin, rpisense_js->active_val);
+ rt_pin_mode(rpisense_js->pin, PIN_MODE_INPUT);
+ rt_pin_attach_irq(rpisense_js->pin, PIN_IRQ_MODE_RISING, rpisense_isr, rpisense_js);
+ rt_pin_irq_enable(rpisense_js->pin, RT_TRUE);
+
+ for (int i = 0; i < RT_ARRAY_SIZE(keymap); ++i)
+ {
+ rt_input_set_capability(&rpisense_js->parent, EV_KEY, keymap[i]);
+ }
+
+ if ((err = rt_input_device_register(&rpisense_js->parent)))
+ {
+ goto _fail;
+ }
+
+ rpisense_js->keys_task = rt_thread_create("rpisense-js", &rpisense_keys_task,
+ rpisense_js, DM_THREAD_STACK_SIZE, RT_THREAD_PRIORITY_MAX / 2, 10);
+
+ if (!rpisense_js->keys_task)
+ {
+ rt_input_device_unregister(&rpisense_js->parent);
+ goto _fail;
+ }
+
+ pdev->parent.user_data = rpisense_js;
+
+ rt_thread_startup(rpisense_js->keys_task);
+
+ return RT_EOK;
+
+_fail:
+ if (rpisense_js->pin >= 0)
+ {
+ rt_pin_detach_irq(rpisense_js->pin);
+ }
+
+ rt_free(rpisense_js);
+
+ return err;
+}
+
+static rt_err_t rpisense_js_remove(struct rt_platform_device *pdev)
+{
+ struct rpisense_joystick *rpisense_js = pdev->parent.user_data;
+
+ rt_pin_irq_enable(rpisense_js->pin, RT_FALSE);
+ rt_pin_detach_irq(rpisense_js->pin);
+
+ rt_thread_delete(rpisense_js->keys_task);
+
+ rt_input_device_unregister(&rpisense_js->parent);
+
+ rt_free(rpisense_js);
+
+ return RT_EOK;
+}
+
+static struct rt_platform_driver rpisense_js_driver =
+{
+ .name = "rpi-sense-js",
+
+ .probe = rpisense_js_probe,
+ .remove = rpisense_js_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpisense_js_driver);
diff --git a/bsp/raspberry-pi/dm/input/touchscreen/Kconfig b/bsp/raspberry-pi/dm/input/touchscreen/Kconfig
new file mode 100755
index 0000000000..9766216f38
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/touchscreen/Kconfig
@@ -0,0 +1,9 @@
+config RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW
+ bool "Raspberry Pi's firmware base touch screen support"
+ depends on RT_INPUT_TOUCHSCREEN
+ depends on RT_USING_OFW
+ depends on RT_USING_DMA
+ depends on RT_FIRMWARE_RASPBERRYPI
+ depends on RT_USING_ADT
+ depends on RT_USING_ADT_BITMAP
+ default n
diff --git a/bsp/raspberry-pi/dm/input/touchscreen/SConscript b/bsp/raspberry-pi/dm/input/touchscreen/SConscript
new file mode 100755
index 0000000000..0b95fd9d21
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/touchscreen/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../../include']
+
+if GetDepend(['RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW']):
+ src += ['ts-raspberrypi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/input/touchscreen/ts-raspberrypi.c b/bsp/raspberry-pi/dm/input/touchscreen/ts-raspberrypi.c
new file mode 100755
index 0000000000..0e2da82d4c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/input/touchscreen/ts-raspberrypi.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "input.touchscreen.rpi-ts"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+
+#define RPI_TS_DEFAULT_WIDTH 800
+#define RPI_TS_DEFAULT_HEIGHT 480
+
+#define RPI_TS_MAX_SUPPORTED_POINTS 10
+
+#define RPI_TS_FTS_TOUCH_DOWN 0
+#define RPI_TS_FTS_TOUCH_CONTACT 2
+
+#define RPI_TS_POLL_INTERVAL 17 /* 60fps */
+
+#define RPI_TS_NPOINTS_REG_INVALIDATE 99
+
+struct rpi_ts_regs
+{
+ rt_uint8_t device_mode;
+ rt_uint8_t gesture_id;
+ rt_uint8_t num_points;
+
+ struct rpi_ts_touch
+ {
+ rt_uint8_t xh;
+ rt_uint8_t xl;
+ rt_uint8_t yh;
+ rt_uint8_t yl;
+ rt_uint8_t pressure; /* Not supported */
+ rt_uint8_t area; /* Not supported */
+ } point[RPI_TS_MAX_SUPPORTED_POINTS];
+};
+
+struct rpi_ts
+{
+ struct rt_input_device parent;
+
+ void *fw_regs;
+ rt_ubase_t fw_regs_phys;
+
+ int known_ids;
+ struct rpi_ts_regs ts_regs;
+};
+
+#define raw_to_rpi_ts(raw) rt_container_of(raw, struct rpi_ts, parent)
+
+static void rpi_ts_poll(struct rt_input_device *idev)
+{
+ int touchid;
+ int event_type;
+ int modified_ids = 0;
+ int x, y, bit = 0;
+ rt_bitmap_t released_ids;
+ struct rpi_ts *rts = raw_to_rpi_ts(idev);
+ struct rpi_ts_regs *regs = &rts->ts_regs;
+
+ rt_memcpy(regs, rts->fw_regs, sizeof(*regs));
+
+ /*
+ * We poll the memory based register copy of the touchscreen chip using
+ * the number of points register to know whether the copy has been
+ * updated (we write 99 to the memory copy, the GPU will write between
+ * 0 - 10 points)
+ */
+ HWREG8(rts->fw_regs + (rt_size_t)&((struct rpi_ts_regs *)0)->num_points) =
+ RPI_TS_NPOINTS_REG_INVALIDATE;
+
+ if (regs->num_points == RPI_TS_NPOINTS_REG_INVALIDATE ||
+ (regs->num_points == 0 && rts->known_ids == 0))
+ {
+ return;
+ }
+
+ for (int i = 0; i < regs->num_points; ++i)
+ {
+ x = (((int)regs->point[i].xh & 0xf) << 8) + regs->point[i].xl;
+ y = (((int)regs->point[i].yh & 0xf) << 8) + regs->point[i].yl;
+ touchid = (regs->point[i].yh >> 4) & 0xf;
+ event_type = (regs->point[i].xh >> 6) & 0x03;
+
+ modified_ids |= RT_BIT(touchid);
+
+ if (event_type == RPI_TS_FTS_TOUCH_DOWN ||
+ event_type == RPI_TS_FTS_TOUCH_CONTACT)
+ {
+ rt_input_report_touch_slot(idev, touchid);
+ rt_input_report_touch_inactive(idev, RT_TRUE);
+ rt_input_report_touch_position(idev, x, y, RT_TRUE);
+ }
+ }
+
+ released_ids = rts->known_ids & ~modified_ids;
+ rt_bitmap_for_each_set_bit(&released_ids, bit, RPI_TS_MAX_SUPPORTED_POINTS)
+ {
+ rt_input_report_touch_slot(idev, bit);
+ rt_input_report_touch_inactive(idev, RT_FALSE);
+ modified_ids &= ~RT_BIT(bit);
+ }
+
+ rts->known_ids = modified_ids;
+ rt_input_sync(idev);
+}
+
+static rt_err_t rpi_ts_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ rt_uint32_t touchbuf;
+ struct rt_touch_info touch_info = {};
+ struct rpi_firmware *rpi_fw = RT_NULL;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_ts *rts = rt_calloc(1, sizeof(*rts));
+
+ if (!rts)
+ {
+ return -RT_ENOMEM;
+ }
+ rts->parent.parent.ofw_node = np;
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rts->fw_regs = rt_dma_alloc_coherent(dev, ARCH_PAGE_SIZE, &rts->fw_regs_phys);
+
+ if (!rts->fw_regs)
+ {
+ LOG_E("Failed to dma buffer");
+
+ goto _fail;
+ }
+
+ if (rts->fw_regs_phys > RT_UINT32_MAX)
+ {
+ LOG_E("64 bits dma buffer is not support");
+
+ goto _fail;
+ }
+
+ touchbuf = (rt_uint32_t)rts->fw_regs_phys;
+
+ if ((err = rpi_firmware_property(rpi_fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
+ &touchbuf, sizeof(touchbuf))))
+ {
+ LOG_E("Set touchbuf from firmware error = %s", rt_strerror(err));
+
+ goto _fail;
+ }
+
+ if ((err = rt_input_set_capability(&rts->parent, EV_ABS, ABS_MT_POSITION_X)) ||
+ (err = rt_input_set_capability(&rts->parent, EV_ABS, ABS_MT_POSITION_Y)))
+ {
+ goto _fail;
+ }
+
+ rt_input_set_absinfo(&rts->parent,
+ ABS_MT_POSITION_X, 0, RPI_TS_DEFAULT_WIDTH, 0, 0);
+
+ rt_input_set_absinfo(&rts->parent,
+ ABS_MT_POSITION_Y, 0, RPI_TS_DEFAULT_HEIGHT, 0, 0);
+
+ if ((err = rt_input_setup_polling(&rts->parent, rpi_ts_poll)))
+ {
+ goto _fail;
+ }
+
+ rt_input_set_poll_interval(&rts->parent, RPI_TS_POLL_INTERVAL);
+
+ touch_info.type = RT_TOUCH_TYPE_RESISTANCE;
+ touch_info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
+
+ if ((err = rt_input_setup_touch(&rts->parent,
+ RPI_TS_MAX_SUPPORTED_POINTS, &touch_info)))
+ {
+ goto _fail;
+ }
+
+ if ((err = rt_input_device_register(&rts->parent)))
+ {
+ goto _fail;
+ }
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, &rts->parent);
+ dev->user_data = rts;
+
+ return RT_EOK;
+
+_fail:
+ rt_input_remove_config(&rts->parent);
+
+ if (rts->fw_regs)
+ {
+ rt_dma_free_coherent(dev, ARCH_PAGE_SIZE, rts->fw_regs, rts->fw_regs_phys);
+ }
+
+ if (rpi_fw)
+ {
+ rpi_firmware_put(rpi_fw);
+ }
+
+ rt_free(rts);
+
+ return err;
+}
+
+static rt_err_t rpi_ts_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct rpi_ts *rts = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+ rt_input_device_unregister(&rts->parent);
+
+ rt_dma_free_coherent(dev, ARCH_PAGE_SIZE, rts->fw_regs, rts->fw_regs_phys);
+
+ rt_free(rts);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rpi_ts_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,firmware-ts" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_ts_driver =
+{
+ .name = "touchscreen-rpi",
+ .ids = rpi_ts_ofw_ids,
+
+ .probe = rpi_ts_probe,
+ .remove = rpi_ts_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpi_ts_driver);
diff --git a/bsp/raspberry-pi/dm/mailbox/Kconfig b/bsp/raspberry-pi/dm/mailbox/Kconfig
new file mode 100755
index 0000000000..64c55a6618
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mailbox/Kconfig
@@ -0,0 +1,3 @@
+config RT_MBOX_BCM2835
+ bool "BCM2835 Mailbox"
+ default n
diff --git a/bsp/raspberry-pi/dm/mailbox/SConscript b/bsp/raspberry-pi/dm/mailbox/SConscript
new file mode 100755
index 0000000000..14d2237d2a
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mailbox/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_MBOX_BCM2835']):
+ src += ['mailbox-bcm2835.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/mailbox/mailbox-bcm2835.c b/bsp/raspberry-pi/dm/mailbox/mailbox-bcm2835.c
new file mode 100755
index 0000000000..59f28e3684
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mailbox/mailbox-bcm2835.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-09-23 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+/* Mailboxes */
+#define ARM_0_MAIL0 0x00
+#define ARM_0_MAIL1 0x20
+
+/*
+ * Mailbox registers. We basically only support mailbox 0 & 1. We
+ * deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See
+ * BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about
+ * the placement of memory barriers.
+ */
+#define MAIL0_RD (ARM_0_MAIL0 + 0x00)
+#define MAIL0_POL (ARM_0_MAIL0 + 0x10)
+#define MAIL0_STA (ARM_0_MAIL0 + 0x18)
+#define MAIL0_CNF (ARM_0_MAIL0 + 0x1C)
+#define MAIL1_WRT (ARM_0_MAIL1 + 0x00)
+#define MAIL1_STA (ARM_0_MAIL1 + 0x18)
+
+/* Status register: FIFO state. */
+#define ARM_MS_FULL RT_BIT(31)
+#define ARM_MS_EMPTY RT_BIT(30)
+
+/* Configuration register: Enable interrupts. */
+#define ARM_MC_IHAVEDATAIRQEN RT_BIT(0)
+
+struct bcm2835_mbox
+{
+ struct rt_mbox_controller parent;
+
+ int irq;
+ void *regs;
+ struct rt_spinlock lock;
+};
+
+#define raw_to_bcm2835_mbox(raw) rt_container_of(raw, struct bcm2835_mbox, parent)
+
+rt_inline rt_uint32_t bcm2835_mbox_readl(struct bcm2835_mbox *bcm_mbox, int offset)
+{
+ return HWREG32(bcm_mbox->regs + offset);
+}
+
+rt_inline void bcm2835_mbox_writel(struct bcm2835_mbox *bcm_mbox, int offset,
+ rt_uint32_t value)
+{
+ HWREG32(bcm_mbox->regs + offset) = value;
+}
+
+static rt_err_t bcm2835_mbox_request(struct rt_mbox_chan *chan)
+{
+ struct bcm2835_mbox *bcm_mbox = raw_to_bcm2835_mbox(chan->ctrl);
+
+ /* Enable the interrupt on data reception */
+ bcm2835_mbox_writel(bcm_mbox, MAIL0_CNF, ARM_MC_IHAVEDATAIRQEN);
+
+ return RT_EOK;
+}
+
+static void bcm2835_mbox_release(struct rt_mbox_chan *chan)
+{
+ struct bcm2835_mbox *bcm_mbox = raw_to_bcm2835_mbox(chan->ctrl);
+
+ bcm2835_mbox_writel(bcm_mbox, MAIL0_CNF, 0);
+}
+
+static rt_err_t bcm2835_mbox_send(struct rt_mbox_chan *chan, const void *data)
+{
+ rt_err_t err = -RT_ETIMEOUT;
+ rt_int32_t timeout_us = 1000000;
+ rt_uint32_t msg = *(rt_uint32_t *)data;
+ struct bcm2835_mbox *bcm_mbox = raw_to_bcm2835_mbox(chan->ctrl);
+
+ rt_spin_lock(&bcm_mbox->lock);
+
+ /*
+ * Property channel replies are polled synchronously. Mask the mailbox
+ * interrupt while waiting so the ISR cannot consume the reply first and
+ * leave the poll loop timing out spuriously.
+ */
+ rt_hw_interrupt_mask(bcm_mbox->irq);
+
+ while (bcm2835_mbox_readl(bcm_mbox, MAIL1_STA) & ARM_MS_FULL)
+ {
+ rt_spin_unlock(&bcm_mbox->lock);
+ rt_hw_us_delay(10);
+ rt_spin_lock(&bcm_mbox->lock);
+ }
+
+ bcm2835_mbox_writel(bcm_mbox, MAIL1_WRT, msg);
+ rt_hw_wmb();
+
+ while (timeout_us > 0)
+ {
+ rt_uint32_t sta = bcm2835_mbox_readl(bcm_mbox, MAIL0_STA);
+
+ if (!(sta & ARM_MS_EMPTY))
+ {
+ rt_uint32_t reply = bcm2835_mbox_readl(bcm_mbox, MAIL0_RD);
+
+ rt_mbox_recv(chan, &reply);
+ err = RT_EOK;
+ break;
+ }
+
+ rt_hw_us_delay(10);
+ timeout_us -= 10;
+ }
+
+ rt_hw_interrupt_umask(bcm_mbox->irq);
+ rt_spin_unlock(&bcm_mbox->lock);
+
+ return err;
+}
+
+static int bcm2835_mbox_ofw_parse(struct rt_mbox_controller *ctrl,
+ struct rt_ofw_cell_args *args)
+{
+ if (args->args_count != 0)
+ {
+ return -RT_EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct rt_mbox_controller_ops bcm2835_mbox_ops =
+{
+ .request = bcm2835_mbox_request,
+ .release = bcm2835_mbox_release,
+ .send = bcm2835_mbox_send,
+ .ofw_parse = bcm2835_mbox_ofw_parse,
+};
+
+static void bcm2835_mbox_isr(int irqno, void *param)
+{
+ struct bcm2835_mbox *bcm_mbox = param;
+
+ while (!(bcm2835_mbox_readl(bcm_mbox, MAIL0_STA) & ARM_MS_EMPTY))
+ {
+ rt_uint32_t msg = bcm2835_mbox_readl(bcm_mbox, MAIL0_RD);
+
+ rt_mbox_recv(&bcm_mbox->parent.chans[0], &msg);
+ }
+}
+
+static rt_err_t bcm2835_mbox_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_mbox *bcm_mbox = rt_calloc(1, sizeof(*bcm_mbox));
+
+ if (!bcm_mbox)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bcm_mbox->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!bcm_mbox->regs)
+ {
+ err = -RT_EIO;
+
+ goto _fail;
+ }
+
+ bcm_mbox->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (bcm_mbox->irq < 0)
+ {
+ err = bcm_mbox->irq;
+
+ goto _fail;
+ }
+
+ dev->user_data = bcm_mbox;
+
+ rt_hw_interrupt_install(bcm_mbox->irq, bcm2835_mbox_isr, bcm_mbox, "bcm2835-mbox");
+ rt_hw_interrupt_umask(bcm_mbox->irq);
+
+ bcm_mbox->parent.dev = dev;
+ bcm_mbox->parent.num_chans = 1;
+ bcm_mbox->parent.ops = &bcm2835_mbox_ops;
+
+ if ((err = rt_mbox_controller_register(&bcm_mbox->parent)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (bcm_mbox->regs)
+ {
+ rt_iounmap(bcm_mbox->regs);
+ }
+
+ rt_free(bcm_mbox);
+
+ return err;
+}
+
+static rt_err_t bcm2835_mbox_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_mbox *bcm_mbox = pdev->parent.user_data;
+
+ rt_hw_interrupt_mask(bcm_mbox->irq);
+ rt_pic_detach_irq(bcm_mbox->irq, bcm_mbox);
+
+ rt_mbox_controller_unregister(&bcm_mbox->parent);
+
+ rt_iounmap(bcm_mbox->regs);
+
+ rt_free(bcm_mbox);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_mbox_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-mbox" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_mbox_driver =
+{
+ .name = "mailbox-bcm2835",
+ .ids = bcm2835_mbox_ofw_ids,
+
+ .probe = bcm2835_mbox_probe,
+ .remove = bcm2835_mbox_remove,
+};
+
+static int bcm2835_mbox_drv_register(void)
+{
+ rt_platform_driver_register(&bcm2835_mbox_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_mbox_drv_register);
diff --git a/bsp/raspberry-pi/dm/mfd/Kconfig b/bsp/raspberry-pi/dm/mfd/Kconfig
new file mode 100755
index 0000000000..3321277989
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mfd/Kconfig
@@ -0,0 +1,18 @@
+config RT_MFD_BCM2835_PM
+ bool "BCM2835 PM driver"
+ depends on RT_USING_MFD
+ default n
+
+config RT_MFD_RP1
+ bool "Raspberry Pi RP1 MFD driver"
+ depends on RT_USING_MFD
+ depends on RT_USING_PCI
+ default n
+
+config RT_MFD_RPI_SENSE
+ bool "Raspberry Pi Sense HAT core functions"
+ depends on RT_USING_MFD
+ depends on RT_USING_I2C
+ depends on RT_USING_OFW
+ depends on RT_USING_PIN
+ default n
diff --git a/bsp/raspberry-pi/dm/mfd/SConscript b/bsp/raspberry-pi/dm/mfd/SConscript
new file mode 100755
index 0000000000..a60f069e95
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mfd/SConscript
@@ -0,0 +1,19 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_MFD_BCM2835_PM']):
+ src += ['bcm2835-pm.c']
+
+if GetDepend(['RT_MFD_RP1']):
+ src += ['rp1.c']
+
+if GetDepend(['RT_MFD_RPI_SENSE']):
+ src += ['rpi-sense.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/mfd/bcm2835-pm.c b/bsp/raspberry-pi/dm/mfd/bcm2835-pm.c
new file mode 100755
index 0000000000..9bc9f35771
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mfd/bcm2835-pm.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "mfd.bcm2835-pm"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <bcm2835-pm.h>
+
+static rt_err_t bcm2835_pm_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_bool_t is_2712 = RT_FALSE;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_bus *bus = dev->bus;
+ struct bcm2835_pm *pm = rt_malloc(sizeof(*pm));
+
+ if (!pm)
+ {
+ return -RT_ENOMEM;
+ }
+
+#ifdef RT_USING_OFW
+ is_2712 = rt_ofw_node_is_compatible(dev->ofw_node, "brcm,bcm2712-pm");
+
+ if (rt_ofw_prop_read_bool(dev->ofw_node, "reg-names"))
+ {
+ if (!(pm->base = rt_dm_dev_iomap_by_name(dev, "pm")))
+ {
+ err = -RT_EIO;
+
+ goto _fail;
+ }
+
+ pm->asb = rt_dm_dev_iomap_by_name(dev, "asb");
+ pm->rpivid_asb = rt_dm_dev_iomap_by_name(dev, "rpivid_asb");
+ }
+ else
+#endif /* RT_USING_OFW */
+ {
+ if (!(pm->base = rt_dm_dev_iomap(dev, 0)))
+ {
+ err = -RT_EIO;
+
+ goto _fail;
+ }
+
+ pm->asb = rt_dm_dev_iomap(dev, 1);
+ pm->rpivid_asb = rt_dm_dev_iomap(dev, 2);
+ }
+
+ pm->ofw_node = dev->ofw_node;
+
+ pdev->name = "bcm2835-wdt";
+ pdev->priv = pm;
+ /* Ask bus to check drivers' name */
+ pdev->parent.ofw_node = RT_NULL;
+ rt_bus_remove_device(dev);
+ rt_bus_add_device(bus, dev);
+
+ if (pm->asb || is_2712)
+ {
+ pdev = rt_calloc(1, sizeof(*pdev));
+
+ if (pdev)
+ {
+ pdev->name = "bcm2835-power";
+ pdev->priv = pm;
+ rt_bus_add_device(bus, &pdev->parent);
+ }
+ else
+ {
+ LOG_W("Power will not register");
+ }
+ }
+
+ /* No Error, No success */
+ return 1;
+
+_fail:
+ rt_free(pm);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id bcm2835_pm_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-pm-wdt", },
+ { .compatible = "brcm,bcm2835-pm", },
+ { .compatible = "brcm,bcm2711-pm", },
+ { .compatible = "brcm,bcm2712-pm", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_pm_driver =
+{
+ .name = "pm-bcm2835",
+ .ids = bcm2835_pm_ofw_ids,
+
+ .probe = bcm2835_pm_probe,
+};
+
+static int bcm2835_pm_register(void)
+{
+ rt_platform_driver_register(&bcm2835_pm_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_pm_register);
diff --git a/bsp/raspberry-pi/dm/mfd/rp1.c b/bsp/raspberry-pi/dm/mfd/rp1.c
new file mode 100755
index 0000000000..e38bf258b3
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mfd/rp1.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "mfd.rp1"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <dt-bindings/mfd/rp1.h>
+
+#define PCI_DEVICE_ID_RP1_C0 0x0001
+
+#define RP1_PCI_BAR0_OFFSET 0x410000ULL
+#define RP1_PCI_BAR1_OFFSET 0x0ULL
+#define RP1_PCI_BAR2_OFFSET 0x400000ULL
+
+
+
+#define RP1_ACTUAL_IRQS RP1_INT_END
+#define RP1_IRQS RP1_ACTUAL_IRQS
+
+#define RP1_SYSCLK_RATE 200000000
+#define RP1_SYSCLK_FPGA_RATE 60000000
+
+#define REG_RW 0x000
+#define REG_SET 0x800
+#define REG_CLR 0xc00
+
+#define MSIX_CFG(x) (0x8 + (4 * (x)))
+
+#define MSIX_CFG_IACK_EN RT_BIT(3)
+#define MSIX_CFG_IACK RT_BIT(2)
+#define MSIX_CFG_TEST RT_BIT(1)
+#define MSIX_CFG_ENABLE RT_BIT(0)
+
+#define INTSTATL 0x108
+#define INTSTATH 0x10c
+
+struct rp1_device
+{
+ struct rt_pic parent;
+ struct rt_pci_device *pdev;
+
+ rt_ubase_t bar_start;
+ rt_ubase_t bar_end;
+
+ struct rt_clk *sys_clk;
+ struct rt_pci_msix_entry msix_entries[RP1_IRQS];
+ rt_bool_t rp1_level_triggered_irq[RP1_ACTUAL_IRQS];
+
+ void *msix_cfg_regs;
+ struct rt_pic *msi_pic;
+};
+
+#define raw_to_rp1(raw) rt_container_of(raw, struct rp1_device, parent)
+
+extern void brcm_pcie_reapply_maps(struct rt_pci_device *pdev);
+
+rt_inline rt_ubase_t rp1_io_to_phys(struct rp1_device *rp1, int offset)
+{
+ return rp1->bar_start + offset;
+}
+
+static void msix_cfg_set(struct rp1_device *rp1, int hwirq, rt_uint32_t value)
+{
+ HWREG32(rp1->msix_cfg_regs + REG_SET + MSIX_CFG(hwirq)) = value;
+}
+
+static void msix_cfg_clr(struct rp1_device *rp1, int hwirq, rt_uint32_t value)
+{
+ HWREG32(rp1->msix_cfg_regs + REG_CLR + MSIX_CFG(hwirq)) = value;
+}
+
+static void rp1_sync_pci_bar_config(struct rt_pci_device *pdev)
+{
+ rt_uint16_t cmd;
+ rt_uint32_t bar0, bar1, bar2;
+ static const rt_uint32_t want[] = {
+ (rt_uint32_t)RP1_PCI_BAR0_OFFSET,
+ (rt_uint32_t)RP1_PCI_BAR1_OFFSET,
+ (rt_uint32_t)RP1_PCI_BAR2_OFFSET,
+ };
+
+ rt_pci_read_config_u32(pdev, PCIR_BAR(0), &bar0);
+ rt_pci_read_config_u32(pdev, PCIR_BAR(1), &bar1);
+ rt_pci_read_config_u32(pdev, PCIR_BAR(2), &bar2);
+
+ if ((bar0 & ~0xfU) == want[0] && (bar1 & ~0xfU) == want[1] &&
+ (bar2 & ~0xfU) == want[2])
+ {
+ return;
+ }
+
+ rt_pci_read_config_u16(pdev, PCIR_COMMAND, &cmd);
+ rt_pci_write_config_u16(pdev, PCIR_COMMAND, cmd & ~PCIM_CMD_MEMEN);
+
+ rt_pci_write_config_u32(pdev, PCIR_BAR(1), want[1]);
+ rt_pci_write_config_u32(pdev, PCIR_BAR(1) + 4, 0);
+ rt_pci_write_config_u32(pdev, PCIR_BAR(2), want[2]);
+ rt_pci_write_config_u32(pdev, PCIR_BAR(2) + 4, 0);
+ rt_pci_write_config_u32(pdev, PCIR_BAR(0), want[0]);
+
+ rt_pci_write_config_u16(pdev, PCIR_COMMAND, cmd);
+}
+
+/*
+ * RP1 BAR CPU bases come from the host bridge MEM window + fixed PCI decode
+ * offsets (BAR1=0). Generic BAR assign may leave resource[1].base at the
+ * wrong anchor (e.g. win+0x400000); never use that as the window base.
+ */
+static rt_ubase_t rp1_host_mem_cpu(struct rt_pci_device *pdev)
+{
+ struct rt_pci_host_bridge *hb = rt_pci_find_host_bridge(pdev->bus);
+
+ if (!hb)
+ {
+ return 0;
+ }
+
+ for (int j = 0; j < hb->bus_regions_nr; ++j)
+ {
+ struct rt_pci_bus_region *mem = &hb->bus_regions[j];
+
+ if (mem->flags == PCI_BUS_REGION_F_MEM && mem->size > 0)
+ {
+ rt_uint64_t pci = RP1_PCI_BAR1_OFFSET;
+
+ if (pci >= mem->phy_addr &&
+ pci < mem->phy_addr + mem->size)
+ {
+ return mem->cpu_addr + (pci - mem->phy_addr);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void rp1_sync_bar_resources(struct rt_pci_device *pdev)
+{
+ rt_ubase_t win = rp1_host_mem_cpu(pdev);
+
+ if (!win)
+ {
+ LOG_W("RP1: no MEM window anchor for BAR sync");
+ return;
+ }
+
+ if (pdev->resource[0].size == 0 || (pdev->resource[0].flags & PCI_BUS_REGION_F_NONE))
+ {
+ pdev->resource[0].size = 0x4000;
+ pdev->resource[0].flags = PCI_BUS_REGION_F_MEM;
+ }
+ pdev->resource[0].base = win + RP1_PCI_BAR0_OFFSET;
+
+ if (pdev->resource[1].size == 0 || (pdev->resource[1].flags & PCI_BUS_REGION_F_NONE))
+ {
+ pdev->resource[1].size = 0x400000;
+ pdev->resource[1].flags = PCI_BUS_REGION_F_MEM;
+ }
+ pdev->resource[1].base = win;
+
+ if (pdev->resource[2].size == 0 || (pdev->resource[2].flags & PCI_BUS_REGION_F_NONE))
+ {
+ pdev->resource[2].size = 0x10000;
+ pdev->resource[2].flags = PCI_BUS_REGION_F_MEM;
+ }
+ pdev->resource[2].base = win + RP1_PCI_BAR2_OFFSET;
+}
+
+/*
+ * Reset RP1 BAR config + resource[] before MSI-X enable so generic
+ * msix_table_remap() can use resource[bir].base (BIR 0 on Pi5).
+ */
+static void rp1_prepare_msix_bars(struct rt_pci_device *pdev)
+{
+ rp1_sync_pci_bar_config(pdev);
+ rp1_sync_bar_resources(pdev);
+}
+
+static void rp1_msix_reprogram(struct rp1_device *rp1)
+{
+ struct rt_pci_device *pdev = rp1->pdev;
+ struct rt_pic *msi_pic = rp1->msi_pic;
+ struct rt_pci_msi_desc *desc;
+
+ if (!pdev || !pdev->msix_enabled || !msi_pic || !msi_pic->ops->irq_compose_msi_msg)
+ {
+ return;
+ }
+
+ rt_pci_msi_for_each_desc(pdev, desc)
+ {
+ struct rt_pic_irq *pirq = rt_pic_find_pirq(msi_pic, desc->irq);
+
+ if (!pirq)
+ {
+ continue;
+ }
+
+ msi_pic->ops->irq_compose_msi_msg(pirq, &desc->msg);
+ rt_pci_msi_write_msg(desc, &desc->msg);
+ }
+}
+
+static void rp1_irq_eoi(struct rt_pic_irq *pirq)
+{
+ int hwirq = pirq->hwirq;
+ struct rp1_device *rp1 = raw_to_rp1(pirq->pic);
+
+ /* Pulse IACK after the device ISR has cleared the level source, not before. */
+ if (rp1->rp1_level_triggered_irq[hwirq])
+ {
+ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK);
+ }
+}
+
+static void rp1_irq_mask(struct rt_pic_irq *pirq)
+{
+ struct rt_pic_irq *parent = pirq->parent;
+
+ if (parent && parent->msi_desc)
+ {
+ rt_pci_msi_mask_irq(parent);
+ }
+
+ rt_pic_irq_parent_mask(pirq);
+}
+
+static void rp1_irq_unmask(struct rt_pic_irq *pirq)
+{
+ struct rt_pic_irq *parent = pirq->parent;
+
+ /* Unmask the underlying PCI MSIX vector. */
+ if (parent && parent->msi_desc)
+ {
+ rt_pci_msi_unmask_irq(parent);
+ }
+
+ rt_pic_irq_parent_unmask(pirq);
+}
+
+static rt_err_t rp1_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode)
+{
+ int hwirq = pirq->hwirq;
+ struct rp1_device *rp1 = raw_to_rp1(pirq->pic);
+
+ switch (mode)
+ {
+ case RT_IRQ_MODE_LEVEL_HIGH:
+ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
+ rp1->rp1_level_triggered_irq[hwirq] = RT_TRUE;
+ break;
+
+ case RT_IRQ_MODE_EDGE_RISING:
+ msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
+ rp1->rp1_level_triggered_irq[hwirq] = RT_FALSE;
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static int rp1_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
+{
+ int irq;
+ struct rp1_device *rp1 = raw_to_rp1(pic);
+ struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
+
+ irq = rt_pic_config_irq(pic, hwirq, hwirq);
+
+ pirq->mode = mode;
+ rp1_irq_set_triger_mode(pirq, mode);
+
+ /* Enable RP1-side MSIX routing. */
+ msix_cfg_set(rp1, hwirq, MSIX_CFG_ENABLE);
+
+ rt_pic_cascade(pirq, rp1->msix_entries[hwirq].irq);
+
+ return irq;
+}
+
+static rt_err_t rp1_irq_parse(struct rt_pic *pic,
+ struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
+{
+ out_pirq->hwirq = args->args[0];
+ out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK;
+
+ return RT_EOK;
+}
+
+const static struct rt_pic_ops rp1_ops =
+{
+ .name = "RP1",
+ .irq_eoi = rp1_irq_eoi,
+ .irq_mask = rp1_irq_mask,
+ .irq_unmask = rp1_irq_unmask,
+ .irq_set_triger_mode = rp1_irq_set_triger_mode,
+ .irq_map = rp1_irq_map,
+ .irq_parse = rp1_irq_parse,
+ .flags = RT_PIC_F_IRQ_ROUTING,
+};
+
+static rt_err_t rp1_probe(struct rt_pci_device *pdev)
+{
+ rt_err_t err;
+ struct rp1_device *rp1;
+ struct rt_ofw_node *rp1_np, *pcie_np;
+
+ pcie_np = rt_pci_find_host_bridge(pdev->bus)->parent.ofw_node;
+
+ if (!pcie_np)
+ {
+ return -RT_EINVAL;
+ }
+
+ rp1 = rt_calloc(1, sizeof(*rp1));
+
+ if (!rp1)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rp1->pdev = pdev;
+
+ rt_pci_pme_active(pdev, RT_TRUE);
+
+ rt_pci_set_master(pdev);
+
+ /*
+ * Ensure PCIe inbound/outbound windows are active before MSIX table
+ * programming and RP1 MMIO.
+ */
+ brcm_pcie_reapply_maps(pdev);
+
+ rp1_prepare_msix_bars(pdev);
+
+ rt_pci_msix_entry_index_linear(rp1->msix_entries, RP1_IRQS);
+
+ if (rt_pci_msix_enable(pdev, rp1->msix_entries, RP1_IRQS) != RP1_IRQS)
+ {
+ err = -RT_ERROR;
+ goto _fail;
+ }
+
+ rp1->msi_pic = pdev->msi_pic;
+ rp1_msix_reprogram(rp1);
+ rp1->bar_start = pdev->resource[1].base;
+ rp1->bar_end = rp1->bar_start + pdev->resource[1].size;
+
+ rp1->msix_cfg_regs = rt_ioremap((void *)rp1_io_to_phys(rp1, RP1_PCIE_APBS_BASE), 0x1000);
+
+ if (!rp1->msix_cfg_regs)
+ {
+ err = -RT_EIO;
+ goto _free_pci;
+ }
+
+ if (!(rp1_np = rt_ofw_get_child_by_tag(pcie_np, "rp1")))
+ {
+ LOG_E("Could not find RP1 node under %s", rt_ofw_node_full_name(pcie_np));
+ err = -RT_EINVAL;
+ goto _free_msix;
+ }
+
+ rp1->parent.priv_data = rp1;
+ rp1->parent.ops = &rp1_ops;
+ rt_pic_linear_irq(&rp1->parent, RP1_IRQS);
+ rt_pic_user_extends(&rp1->parent);
+
+ rt_ofw_data(rp1_np) = &rp1->parent;
+ rt_platform_ofw_request(rp1_np);
+
+ rt_ofw_node_put(rp1_np);
+
+ return RT_EOK;
+
+_free_msix:
+ rt_iounmap(rp1->msix_cfg_regs);
+
+_free_pci:
+ rt_pci_free_vector(pdev);
+
+_fail:
+ rt_free(rp1);
+
+ return err;
+}
+
+static const struct rt_pci_device_id rp1_ids[] =
+{
+ { RT_PCI_DEVICE_ID(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RP1_C0) },
+ { /* sentinel */ }
+};
+
+static struct rt_pci_driver rp1_driver =
+{
+ .name = "rp1",
+
+ .ids = rp1_ids,
+ .probe = rp1_probe,
+};
+RT_PCI_DRIVER_EXPORT(rp1_driver);
diff --git a/bsp/raspberry-pi/dm/mfd/rpi-sense.c b/bsp/raspberry-pi/dm/mfd/rpi-sense.c
new file mode 100755
index 0000000000..236f0cd2e1
--- /dev/null
+++ b/bsp/raspberry-pi/dm/mfd/rpi-sense.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "mfd.rpi-sense"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "rpi-sense.h"
+
+static rt_int32_t i2c_smbus_read_byte_data(struct rt_i2c_client *client,
+ rt_uint8_t command)
+{
+ rt_int32_t res;
+ rt_uint8_t ret = 0;
+ struct rt_i2c_msg msg[2];
+
+ msg[0].buf = &command;
+ msg[0].addr = client->client_addr;
+ msg[0].len = 1;
+ msg[0].flags = RT_I2C_WR;
+
+ msg[1].buf = &ret;
+ msg[1].addr = client->client_addr;
+ msg[1].len = 1;
+ msg[1].flags = RT_I2C_RD;
+
+ res = rt_i2c_transfer(client->bus, msg, 2);
+
+ return res == 2 ? ret : res;
+}
+
+rt_int32_t rpisense_reg_read(struct rpisense *rpisense, int reg)
+{
+ rt_int32_t ret = i2c_smbus_read_byte_data(rpisense->i2c_client, reg);
+
+ if (ret < 0)
+ {
+ LOG_E("Read from reg(%d) error = %s", reg, rt_strerror(ret));
+ }
+
+ /*
+ * As the BCM270x I2C clock stretching bug, some values may have MSB set.
+ * Clear it to avoid incorrect values.
+ */
+ return ret & 0x7f;
+}
+
+rt_ssize_t rpisense_block_write(struct rpisense *rpisense, const char *buf, int count)
+{
+ rt_ssize_t ret;
+ struct rt_i2c_client *client = rpisense->i2c_client;
+
+ ret = rt_i2c_master_send(client->bus, client->client_addr, 0, (void *)buf, count);
+
+ if (ret < 0)
+ {
+ LOG_E("Write block(%d) error = %s", count, rt_strerror(ret));
+ }
+
+ return ret;
+}
+
+static void rpisense_client_dev_register(struct rpisense *rpisense,
+ const char *name, struct rt_platform_device *pdev)
+{
+ pdev->name = name;
+ pdev->priv = rpisense;
+
+ rt_platform_device_register(pdev);
+}
+
+static rt_err_t rpisense_probe(struct rt_i2c_client *client)
+{
+ rt_err_t err;
+ rt_int32_t value;
+ struct rt_device *dev = &client->parent;
+ struct rpisense *rpisense = rt_calloc(1, sizeof(*rpisense));
+
+ if (!rpisense)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rpisense->i2c_client = client;
+
+ value = rpisense_reg_read(rpisense, RPISENSE_WAI);
+ if (value > 0)
+ {
+ if (value != RPISENSE_ID)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+ }
+ else
+ {
+ err = value;
+ goto _fail;
+ }
+
+ value = rpisense_reg_read(rpisense, RPISENSE_VER);
+ if (value < 0)
+ {
+ err = value;
+ goto _fail;
+ }
+
+ LOG_I("Raspberry Pi Sense HAT firmware version %i", value);
+
+ dev->user_data = rpisense;
+
+ rpisense_client_dev_register(rpisense, "rpi-sense-js", &rpisense->joystick_dev);
+ rpisense_client_dev_register(rpisense, "rpi-sense-fb", &rpisense->framebuffer_dev);
+
+ return RT_EOK;
+
+_fail:
+ rt_free(rpisense);
+
+ return err;
+}
+
+static rt_err_t rpisense_remove(struct rt_i2c_client *client)
+{
+ struct rpisense *rpisense = client->parent.user_data;
+
+ rt_bus_remove_device(&rpisense->joystick_dev.parent);
+ rt_bus_remove_device(&rpisense->framebuffer_dev.parent);
+
+ rt_free(rpisense);
+
+ return RT_EOK;
+}
+
+static const struct rt_i2c_device_id rpisense_ids[] =
+{
+ { .name = "rpi-sense" },
+ { /* sentinel */ },
+};
+
+static const struct rt_ofw_node_id rpisense_ofw_ids[] =
+{
+ { .compatible = "rpi,rpi-sense" },
+ { /* sentinel */ },
+};
+
+static struct rt_i2c_driver rpisense_driver =
+{
+ .ids = rpisense_ids,
+ .ofw_ids = rpisense_ofw_ids,
+
+ .probe = rpisense_probe,
+ .remove = rpisense_remove,
+};
+RT_I2C_DRIVER_EXPORT(rpisense_driver);
diff --git a/bsp/raspberry-pi/dm/nvmem/Kconfig b/bsp/raspberry-pi/dm/nvmem/Kconfig
new file mode 100755
index 0000000000..6c5b3b8dd1
--- /dev/null
+++ b/bsp/raspberry-pi/dm/nvmem/Kconfig
@@ -0,0 +1,4 @@
+config RT_NVMEM_RASPBERRYPI_OTP
+ bool "Raspberry Pi OTP support"
+ depends on RT_USING_NVMEM
+ default n
diff --git a/bsp/raspberry-pi/dm/nvmem/SConscript b/bsp/raspberry-pi/dm/nvmem/SConscript
new file mode 100755
index 0000000000..f5635e6088
--- /dev/null
+++ b/bsp/raspberry-pi/dm/nvmem/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_NVMEM_RASPBERRYPI_OTP']):
+ src += ['raspberrypi-otp.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/nvmem/raspberrypi-otp.c b/bsp/raspberry-pi/dm/nvmem/raspberrypi-otp.c
new file mode 100755
index 0000000000..2294e736bc
--- /dev/null
+++ b/bsp/raspberry-pi/dm/nvmem/raspberrypi-otp.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "nvmem.raspberrypi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+
+#define MAX_ROWS 192
+
+struct rpi_otp
+{
+ struct rt_nvmem_device parent;
+
+ struct rpi_firmware *fw;
+ rt_uint32_t block;
+};
+
+#define raw_to_rpi_otp(raw) rt_container_of(raw, struct rpi_otp, parent)
+
+static rt_ssize_t rpi_otp_read(struct rt_nvmem_device *ndev, int offset,
+ void *val, rt_size_t bytes)
+{
+ rt_err_t err;
+ int words, index;
+ rt_uint32_t data[3 + MAX_ROWS];
+ struct rpi_otp *otp = raw_to_rpi_otp(ndev);
+
+ words = bytes / sizeof(rt_uint32_t);
+ index = offset / sizeof(rt_uint32_t);
+ data[0] = otp->block;
+ data[1] = index;
+ data[2] = words;
+
+ if (words > MAX_ROWS)
+ {
+ return -RT_EINVAL;
+ }
+
+ err = rpi_firmware_property(otp->fw, RPI_FIRMWARE_GET_USER_OTP, &data, sizeof(data));
+
+ if (!err)
+ {
+ rt_memcpy(val, data + 3, bytes);
+ }
+ else
+ {
+ rt_memset(val, 0xee, bytes);
+ }
+
+ return err ? : bytes;
+}
+
+static rt_ssize_t rpi_otp_write(struct rt_nvmem_device *ndev, int offset,
+ void *val, rt_size_t bytes)
+{
+ int words, index;
+ rt_uint32_t data[3 + MAX_ROWS];
+ struct rpi_otp *otp = raw_to_rpi_otp(ndev);
+
+ words = bytes / sizeof(rt_uint32_t);
+ index = offset / sizeof(rt_uint32_t);
+ data[0] = otp->block;
+ data[1] = index;
+ data[2] = words;
+
+ if (bytes > MAX_ROWS * sizeof(rt_uint32_t))
+ {
+ return -RT_EINVAL;
+ }
+
+ rt_memcpy(data + 3, val, bytes);
+
+ return rpi_firmware_property(otp->fw, RPI_FIRMWARE_SET_USER_OTP, &data, sizeof(data)) ? : bytes;
+}
+
+static rt_err_t rpi_otp_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t reg[2];
+ struct rt_nvmem_device *nvmem;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_otp *otp = rt_calloc(1, sizeof(*otp));
+
+ if (!otp)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ otp->fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!otp->fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (rt_dm_dev_prop_read_u32_array_index(dev, "reg", 0, RT_ARRAY_SIZE(reg), reg) <= 0)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ nvmem = &otp->parent;
+ nvmem->parent.ofw_node = np;
+ nvmem->reg_read = rpi_otp_read,
+ nvmem->reg_write = rpi_otp_write,
+ nvmem->size = reg[1] * sizeof(rt_uint32_t);
+ nvmem->read_only = !rt_dm_dev_prop_read_bool(dev, "rw");
+ nvmem->stride = sizeof(rt_uint32_t);
+ nvmem->word_size = sizeof(rt_uint32_t);
+
+ if ((err = rt_nvmem_device_register(nvmem)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (otp->fw)
+ {
+ rpi_firmware_put(otp->fw);
+ }
+
+ rt_free(otp);
+
+ return err;
+}
+
+static rt_err_t rpi_otp_remove(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rpi_otp *otp = pdev->parent.user_data;
+
+ err = rt_nvmem_device_unregister(&otp->parent);
+
+ rpi_firmware_put(otp->fw);
+
+ rt_free(otp);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rpi_top_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rpi-otp", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_top_driver =
+{
+ .name = "nvmem-raspberrypi-otp",
+ .ids = rpi_top_ofw_ids,
+
+ .probe = rpi_otp_probe,
+ .remove = rpi_otp_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpi_top_driver);
diff --git a/bsp/raspberry-pi/dm/pci/Kconfig b/bsp/raspberry-pi/dm/pci/Kconfig
new file mode 100755
index 0000000000..20e93a8622
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pci/Kconfig
@@ -0,0 +1,5 @@
+config RT_PCIE_BRCMSTB
+ bool "Broadcom Brcmstb PCIe controller"
+ depends on RT_PCI_MSI
+ depends on RT_USING_OFW
+ default n
diff --git a/bsp/raspberry-pi/dm/pci/SConscript b/bsp/raspberry-pi/dm/pci/SConscript
new file mode 100755
index 0000000000..f8b4e28c2b
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pci/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include', cwd + '/../../../../components/drivers/pci']
+
+if GetDepend(['RT_PCIE_BRCMSTB']):
+ src += ['pcie-brcmstb.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pci/pcie-brcmstb.c b/bsp/raspberry-pi/dm/pci/pcie-brcmstb.c
new file mode 100755
index 0000000000..97aa97483c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pci/pcie-brcmstb.c
@@ -0,0 +1,2669 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pcie.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <ecam.h>
+#include <mmu.h>
+#include <mm_aspace.h>
+#include <dt-bindings/size.h>
+
+/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
+#define BRCM_PCIE_CAP_REGS 0x00ac
+
+/* Broadcom STB PCIe Register Offsets */
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
+#define PCIE_RC_CFG_VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN 0x0
+
+#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
+
+#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
+#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK 0x1f0
+
+#define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8
+#define PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK 0xf8
+
+#define PCIE_RC_TL_VDM_CTL0 0x0a20
+#define PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK 0x10000
+#define PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK 0x20000
+#define PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK 0x40000
+
+#define PCIE_RC_TL_VDM_CTL1 0x0a0c
+#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID0_MASK 0x0000ffff
+#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID1_MASK 0xffff0000
+
+#define PCIE_RC_DL_MDIO_ADDR 0x1100
+#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
+#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
+
+#define PCIE_RC_PL_REG_PHY_CTL_1 0x1804
+#define PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK 0x8
+
+#define PCIE_RC_PL_PHY_CTL_15 0x184c
+#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000
+#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff
+
+#define PCIE_RC_PL_STATS_CTRL 0x1940
+#define PCIE_RC_PL_STATS_CTRL_EN_MASK 0x1
+#define PCIE_RC_PL_STATS_CTRL_LEN_MASK 0xfffffff0
+
+#define PCIE_RC_PL_STATS_TXTLP_LO 0x1944
+#define PCIE_RC_PL_STATS_TXTLP_HI 0x1948
+#define PCIE_RC_PL_STATS_TXDLLP_LO 0x194c
+#define PCIE_RC_PL_STATS_TXDLLP_HI 0x1950
+#define PCIE_RC_PL_STATS_RXTLP_LO 0x195c
+#define PCIE_RC_PL_STATS_RXTLP_HI 0x1960
+#define PCIE_RC_PL_STATS_RXDLLP_LO 0x1964
+#define PCIE_RC_PL_STATS_RXDLLP_HI 0x1968
+#define PCIE_RC_PL_STATS_RXPL_ERR 0x1974
+#define PCIE_RC_PL_STATS_RXDL_ERR 0x1978
+#define PCIE_RC_PL_STATS_RXTL_ERR 0x197c
+
+#define PCIE_RC_PL_LTSSM_STATS_3 0x19b0
+#define PCIE_RC_PL_LTSSM_STATS_3_TIME_L0S_MASK 0xffff0000
+#define PCIE_RC_PL_LTSSM_STATS_3_TIME_RECOV_MASK 0x0000ffff
+
+#define PCIE_RC_PL_LTSSM_STATS_CNT 0x19b4
+#define PCIE_RC_PL_LTSSM_STATS_CNT_L0S_FAIL_MASK 0xffff0000
+#define PCIE_RC_PL_LTSSM_STATS_CNT_RECOV_MASK 0x0000ffff
+
+#define PCIE_RC_PL_LTSSM_HIST_0 0x1cec
+#define PCIE_RC_PL_LTSSM_HIST(n) (PCIE_RC_PL_LTSSM_HIST_0 + ((n) * 4))
+
+#define PCIE_MISC_MISC_CTRL 0x4008
+#define PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK 0x80
+#define PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK 0x400
+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
+
+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
+#define PCIE_MISC_MISC_CTRL_SCB1_SIZE_MASK 0x07c00000
+#define PCIE_MISC_MISC_CTRL_SCB2_SIZE_MASK 0x0000001f
+#define SCB_SIZE_MASK(x) PCIE_MISC_MISC_CTRL_SCB ## x ## _SIZE_MASK
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
+#define PCIE_MEM_WIN0_LO(win) PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 8)
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
+#define PCIE_MEM_WIN0_HI(win) PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 8)
+
+#define PCIE_BRCM_MAX_INBOUND_WINS 16
+#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
+
+#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4
+
+#define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
+#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
+
+#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
+#define PCIE_MISC_MSI_DATA_CONFIG_VAL_32 0xffe06540
+#define PCIE_MISC_MSI_DATA_CONFIG_VAL_8 0xfff86540
+
+#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c
+
+#define PCIE_MISC_PCIE_CTRL 0x4064
+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4
+
+#define PCIE_MISC_PCIE_STATUS 0x4068
+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80
+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20
+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
+
+#define PCIE_MISC_REVISION 0x406c
+#define BRCM_PCIE_HW_REV_33 0x0303
+#define BRCM_PCIE_HW_REV_3_20 0x0320
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
+#define PCIE_MEM_WIN0_BASE_LIMIT(win) PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
+#define PCIE_MEM_WIN0_BASE_HI(win) PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
+
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
+#define PCIE_MEM_WIN0_LIMIT_HI(win) PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
+
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->soc_data->reg_offsets[PCIE_HARD_DEBUG]
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_REFCLK_OVRD_ENABLE_MASK 0x10000
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_REFCLK_OVRD_OUT_MASK 0x100000
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK 0x200000
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
+#define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000
+#define PCIE_CLKREQ_MASK \
+ (PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK | \
+ PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK)
+
+/* PCIe Link Capabilities: L0s Entry Supported (PCI Express Base Spec) */
+#ifndef PCI_EXP_LNKCAP_ASPM_L0S
+#define PCI_EXP_LNKCAP_ASPM_L0S 0x00000400
+#endif
+
+#define PCIE_MISC_CTRL_1 0x40A0
+#define PCIE_MISC_CTRL_1_OUTBOUND_TC_MASK 0xf
+#define PCIE_MISC_CTRL_1_OUTBOUND_NO_SNOOP_MASK RT_BIT(3)
+#define PCIE_MISC_CTRL_1_OUTBOUND_RO_MASK RT_BIT(4)
+#define PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK RT_BIT(5)
+
+#define PCIE_MISC_UBUS_CTRL 0x40a4
+#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK RT_BIT(13)
+#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK RT_BIT(19)
+
+#define PCIE_MISC_UBUS_TIMEOUT 0x40a8
+
+#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac
+#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK RT_BIT(0)
+#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI 0x40b0
+#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP 0x410c
+
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK RT_BIT(0)
+#define PCIE_MISC_UBUS_BAR3_CONFIG_REMAP 0x40bc
+
+/* Additional RC BARs */
+#define PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK 0x1f
+#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4
+#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8
+
+#define PCIE_MISC_RC_BAR10_CONFIG_LO 0x4104
+#define PCIE_MISC_RC_BAR10_CONFIG_HI 0x4108
+
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000
+#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff
+#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c
+#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110
+
+#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_LO 0x413c
+#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_HI 0x4140
+
+/* AXI priority forwarding - automatic level-based */
+#define PCIE_MISC_TC_QUEUE_TO_QOS_MAP(x) (0x4160 - (x) * 4)
+/* Defined in quarter-fullness */
+#define QUEUE_THRESHOLD_34_TO_QOS_MAP_SHIFT 12
+#define QUEUE_THRESHOLD_23_TO_QOS_MAP_SHIFT 8
+#define QUEUE_THRESHOLD_12_TO_QOS_MAP_SHIFT 4
+#define QUEUE_THRESHOLD_01_TO_QOS_MAP_SHIFT 0
+#define QUEUE_THRESHOLD_MASK 0xf
+
+/* VDM messages indexing TCs to AXI priorities */
+/* Indexes 8-15 */
+#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI 0x4164
+/* Indexes 0-7 */
+#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO 0x4168
+#define VDM_PRIORITY_TO_QOS_MAP_SHIFT(x) (4 * (x))
+#define VDM_PRIORITY_TO_QOS_MAP_MASK 0xf
+
+#define PCIE_MISC_AXI_INTF_CTRL 0x416c
+#define AXI_EN_RCLK_QOS_ARRAY_FIX RT_BIT(13)
+#define AXI_EN_QOS_UPDATE_TIMING_FIX RT_BIT(12)
+#define AXI_DIS_QOS_GATING_IN_MASTER RT_BIT(11)
+#define AXI_REQFIFO_EN_QOS_PROPAGATION RT_BIT(7)
+#define AXI_BRIDGE_LOW_LATENCY_MODE RT_BIT(6)
+#define AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK 0x3f
+
+#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170
+
+#define PCIE_MSI_INTR2_BASE 0x4500
+/* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
+#define MSI_INT_STATUS 0x0
+#define MSI_INT_CLR 0x8
+#define MSI_INT_MASK_SET 0x10
+#define MSI_INT_MASK_CLR 0x14
+
+#define PCIE_EXT_CFG_DATA 0x8000
+#define PCIE_EXT_CFG_INDEX 0x9000
+
+#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
+#define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0
+
+#define RGR1_SW_INIT_1_INIT_GENERIC_MASK 0x2
+#define RGR1_SW_INIT_1_INIT_GENERIC_SHIFT 0x1
+#define RGR1_SW_INIT_1_INIT_7278_MASK 0x1
+#define RGR1_SW_INIT_1_INIT_7278_SHIFT 0x0
+
+/* PCIe parameters */
+#define BRCM_NUM_PCIE_OUT_WINS 0x4
+#define BRCM_INT_PCI_MSI_NR 32
+#define BRCM_INT_PCI_MSI_LEGACY_NR 8
+#define BRCM_INT_PCI_MSI_SHIFT 0
+#define BRCM_INT_PCI_MSI_MASK RT_GENMASK(BRCM_INT_PCI_MSI_NR - 1, 0)
+#define BRCM_INT_PCI_MSI_LEGACY_MASK RT_GENMASK(31, 32 - BRCM_INT_PCI_MSI_LEGACY_NR)
+
+/* MSI target addresses */
+#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
+#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
+
+/* PCIe CEM 2.2 / PCIe r5.0 6.6.1: wait after PERST# deassertion */
+#define PCIE_RESET_CONFIG_WAIT_MS 100
+
+/* MDIO registers */
+#define MDIO_PORT0 0x0
+#define MDIO_DATA_MASK 0x7fffffff
+#define MDIO_PORT_MASK 0xf0000
+#define MDIO_PORT_EXT_MASK 0x200000
+#define MDIO_REGAD_MASK 0xffff
+#define MDIO_CMD_MASK 0x00100000
+#define MDIO_CMD_READ 0x1
+#define MDIO_CMD_WRITE 0x0
+#define MDIO_DATA_DONE_MASK 0x80000000
+#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
+#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
+#define SSC_REGS_ADDR 0x1100
+#define SET_ADDR_OFFSET 0x1f
+#define SSC_CNTL_OFFSET 0x2
+#define SSC_CNTL_OVRD_EN_MASK 0x8000
+#define SSC_CNTL_OVRD_VAL_MASK 0x4000
+#define SSC_STATUS_OFFSET 0x1
+#define SSC_STATUS_SSC_MASK 0x400
+#define SSC_STATUS_PLL_LOCK_MASK 0x800
+#define PCIE_BRCM_MAX_MEMC 3
+
+#define IDX_ADDR(pcie) (pcie->soc_data->reg_offsets[EXT_CFG_INDEX])
+#define DATA_ADDR(pcie) (pcie->soc_data->reg_offsets[EXT_CFG_DATA])
+#define HARD_DEBUG(pcie) (pcie->soc_data->reg_offsets[PCIE_HARD_DEBUG])
+#define INTR2_CPU_BASE(pcie) (pcie->soc_data->reg_offsets[PCIE_INTR2_CPU_BASE])
+#define PCIE_RGR1_SW_INIT_1(pcie) (pcie->soc_data->reg_offsets[RGR1_SW_INIT_1])
+
+/* Rescal registers */
+#define PCIE_DVT_PMU_PHY_CTRL 0xc700
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_NFLDS 0x3
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_DIG_RESET_MASK 0x4
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_DIG_RESET_SHIFT 0x2
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_RESET_MASK 0x2
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_RESET_SHIFT 0x1
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_PWRDN_MASK 0x1
+#define PCIE_DVT_PMU_PHY_CTRL_DAST_PWRDN_SHIFT 0x0
+
+enum
+{
+ RGR1_SW_INIT_1,
+ EXT_CFG_INDEX,
+ EXT_CFG_DATA,
+ PCIE_HARD_DEBUG,
+ PCIE_INTR2_CPU_BASE,
+};
+
+enum
+{
+ RGR1_SW_INIT_1_INIT_MASK,
+ RGR1_SW_INIT_1_INIT_SHIFT,
+};
+
+enum brcm_pcie_type
+{
+ GENERIC,
+ BCM2711,
+ BCM4908,
+ BCM7278,
+ BCM7425,
+ BCM7435,
+ BCM7712,
+};
+
+static const char * const supplies_prefix[] =
+{
+ "vpcie3v3",
+ "vpcie3v3aux",
+ "vpcie12v",
+};
+
+struct brcm_pcie;
+
+struct inbound_win
+{
+ rt_uint64_t size;
+ rt_uint64_t pci_offset;
+ rt_uint64_t cpu_addr;
+};
+
+struct pcie_cfg_soc_data
+{
+ const int *reg_offsets;
+ const enum brcm_pcie_type type;
+ const rt_bool_t has_phy;
+
+#define CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN RT_BIT(0)
+#define CFG_QUIRK_NO_SSC RT_BIT(1)
+ const rt_uint32_t quirks;
+ rt_uint8_t num_inbound_wins;
+
+ rt_err_t (*perst_set)(struct brcm_pcie *pcie, rt_uint32_t val);
+ rt_err_t (*bridge_sw_init_set)(struct brcm_pcie *pcie, rt_uint32_t val);
+ rt_err_t (*post_setup)(struct brcm_pcie *pcie);
+};
+
+struct brcm_msi
+{
+ int irq;
+ void *pcie_base;
+ void *intr_base;
+
+ struct rt_pic inner_pic;
+ rt_uint64_t data_address;
+
+ rt_bool_t legacy;
+ /* Some chips have MSIs in bits [31..24] of a shared register. */
+ int legacy_shift;
+
+ int msi_max_nr;
+ RT_BITMAP_DECLARE(msi_map, 64);
+ struct rt_spinlock lock;
+};
+
+/* Internal PCIe Host Controller Information. */
+struct brcm_pcie
+{
+ const struct pcie_cfg_soc_data *soc_data;
+ struct rt_device *dev;
+
+ void *base;
+
+ rt_bool_t ssc; /* Spread Spectrum Clocking */
+ rt_bool_t l1ss; /* L1 PM Substates */
+ rt_bool_t ep_wakeup_capable;
+ rt_uint32_t qos_map;
+ rt_uint32_t generation;
+ rt_uint32_t misc_revision;
+ rt_uint32_t tperst_clk_ms;
+
+ rt_size_t memc_nr;
+ rt_uint64_t memc_size[PCIE_BRCM_MAX_MEMC];
+
+ struct rt_clk *clk;
+ struct rt_reset_control *rescal_rstc;
+ struct rt_reset_control *perst_rstc;
+ struct rt_reset_control *bridge_rstc;
+ struct rt_reset_control *swinit_rstc;
+ struct rt_regulator *supplies[RT_ARRAY_SIZE(supplies_prefix)];
+
+ struct brcm_msi *msi;
+ rt_uint64_t msi_data_address;
+
+ struct rt_pci_host_bridge *bridge;
+
+ struct inbound_win inbound_wins[PCIE_BRCM_MAX_INBOUND_WINS];
+ rt_uint8_t num_inbound_wins;
+};
+
+static void brcm_pcie_reapply_7712_maps(struct brcm_pcie *pcie);
+
+rt_inline void replace_u32_bitfield(rt_uint32_t *p, rt_uint32_t val, rt_uint32_t field)
+{
+ *p = (*p & ~field) | ((val & (field / (field & -field))) * (field & -field));
+}
+
+rt_inline void replace_u16_bitfield(rt_uint16_t *p, rt_uint16_t val, rt_uint16_t field)
+{
+ *p = (*p & ~field) | ((val & (field / (field & -field))) * (field & -field));
+}
+
+rt_inline int __fls64(rt_uint64_t x)
+{
+ const rt_uint64_t bits_per_u64 = (sizeof(x) * 8);
+ int num = bits_per_u64 - 1;
+
+ if (x == 0)
+ {
+ return 0;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 32))))
+ {
+ num -= 32;
+ x <<= 32;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 16))))
+ {
+ num -= 16;
+ x <<= 16;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 8))))
+ {
+ num -= 8;
+ x <<= 8;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 4))))
+ {
+ num -= 4;
+ x <<= 4;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 2))))
+ {
+ num -= 2;
+ x <<= 2;
+ }
+
+ if (!(x & (~0ULL << (bits_per_u64 - 1))))
+ {
+ num -= 1;
+ }
+
+ return num + 1;
+}
+
+rt_uint32_t __hweight32(rt_uint32_t w)
+{
+ rt_uint32_t res = w - ((w >> 1) & 0x55555555);
+ res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+ res = (res + (res >> 4)) & 0x0f0f0f0f;
+ res = res + (res >> 8);
+ return (res + (res >> 16)) & 0x000000ff;
+}
+
+rt_inline rt_bool_t is_bmips(const struct brcm_pcie *pcie)
+{
+ const struct pcie_cfg_soc_data *soc_data = pcie->soc_data;
+
+ return soc_data->type == BCM7435 || soc_data->type == BCM7425;
+}
+
+/*
+ * This is to convert the size of the inbound "BAR" region to the
+ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
+ */
+static int brcm_pcie_encode_ibar_size(rt_uint64_t size)
+{
+ int log2_in = rt_ilog2(size);
+
+ if (log2_in >= 12 && log2_in <= 15)
+ {
+ /* Covers 4KB to 32KB (inclusive) */
+ return (log2_in - 12) + 0x1c;
+ }
+ else if (log2_in >= 16 && log2_in <= 36)
+ {
+ /* Covers 64KB to 64GB, (inclusive) */
+ return log2_in - 15;
+ }
+
+ /* Something is awry so disable */
+ return 0;
+}
+
+static rt_uint32_t brcm_pcie_mdio_form_pkt(int port, int regad, int cmd)
+{
+ rt_uint32_t pkt = 0;
+
+ pkt |= RT_FIELD_PREP(MDIO_PORT_EXT_MASK, port >> 4);
+ pkt |= RT_FIELD_PREP(MDIO_PORT_MASK, port);
+ pkt |= RT_FIELD_PREP(MDIO_REGAD_MASK, regad);
+ pkt |= RT_FIELD_PREP(MDIO_CMD_MASK, cmd);
+
+ return pkt;
+}
+
+/* Negative return value indicates error */
+static rt_err_t brcm_pcie_mdio_read(void *base,
+ rt_uint8_t port, rt_uint8_t regad, rt_uint32_t *val)
+{
+ rt_uint32_t data;
+
+ HWREG32(base + PCIE_RC_DL_MDIO_ADDR) =
+ brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_READ);
+ data = HWREG32(base + PCIE_RC_DL_MDIO_ADDR);
+
+ data = HWREG32(base + PCIE_RC_DL_MDIO_RD_DATA);
+
+ for (int tries = 0; !MDIO_RD_DONE(data) && tries < 10; ++tries)
+ {
+ rt_hw_us_delay(10);
+ data = HWREG32(base + PCIE_RC_DL_MDIO_RD_DATA);
+ }
+
+ *val = RT_FIELD_GET(MDIO_DATA_MASK, data);
+
+ return MDIO_RD_DONE(data) ? 0 : -RT_EIO;
+}
+
+/* Negative return value indicates error */
+static rt_err_t brcm_pcie_mdio_write(void *base,
+ rt_uint8_t port, rt_uint8_t regad, rt_uint16_t wrdata)
+{
+ rt_uint32_t data;
+
+ HWREG32(base + PCIE_RC_DL_MDIO_ADDR) =
+ brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_WRITE);
+ data = HWREG32(base + PCIE_RC_DL_MDIO_ADDR);
+ HWREG32(base + PCIE_RC_DL_MDIO_WR_DATA) = MDIO_DATA_DONE_MASK | wrdata;
+
+ data = HWREG32(base + PCIE_RC_DL_MDIO_WR_DATA);
+
+ for (int tries = 0; !MDIO_WT_DONE(data) && tries < 10; ++tries)
+ {
+ rt_hw_us_delay(10);
+ data = HWREG32(base + PCIE_RC_DL_MDIO_WR_DATA);
+ }
+
+ return MDIO_WT_DONE(data) ? 0 : -RT_EIO;
+}
+
+/*
+ * Configures device for Spread Spectrum Clocking (SSC) mode;
+ * a negative return value indicates error.
+ */
+static rt_err_t brcm_pcie_set_ssc(struct brcm_pcie *pcie)
+{
+ int pll, ssc;
+ rt_err_t err;
+ rt_uint32_t tmp;
+
+ if ((err = brcm_pcie_mdio_write(pcie->base,
+ MDIO_PORT0, SET_ADDR_OFFSET, SSC_REGS_ADDR)) < 0)
+ {
+ return err;
+ }
+
+ if ((err = brcm_pcie_mdio_read(pcie->base,
+ MDIO_PORT0, SSC_CNTL_OFFSET, &tmp)) < 0)
+ {
+ return err;
+ }
+
+ replace_u32_bitfield(&tmp, 1, SSC_CNTL_OVRD_EN_MASK);
+ replace_u32_bitfield(&tmp, 1, SSC_CNTL_OVRD_VAL_MASK);
+
+ if ((err = brcm_pcie_mdio_write(pcie->base,
+ MDIO_PORT0, SSC_CNTL_OFFSET, tmp)) < 0)
+ {
+ return err;
+ }
+
+ rt_hw_us_delay(1500);
+
+ if ((err = brcm_pcie_mdio_read(pcie->base,
+ MDIO_PORT0, SSC_STATUS_OFFSET, &tmp)) < 0)
+ {
+ return err;
+ }
+
+ ssc = RT_FIELD_GET(SSC_STATUS_SSC_MASK, tmp);
+ pll = RT_FIELD_GET(SSC_STATUS_PLL_LOCK_MASK, tmp);
+
+ return ssc && pll ? 0 : -RT_EIO;
+}
+
+/*
+ * SerDes MDIO refclk programming for BCM7712/2712 (54MHz xosc).
+ * Must run after SERDES_IDDQ is cleared.
+ */
+static void brcm_pcie_delay_ms(rt_uint32_t ms);
+
+static rt_err_t brcm_pcie_serdes_munge_pll(struct brcm_pcie *pcie)
+{
+ void *base = pcie->base;
+ const rt_uint16_t data[] =
+ {
+ 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007
+ };
+ const rt_uint8_t regs[] =
+ {
+ 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e
+ };
+ rt_err_t err;
+
+ if ((err = brcm_pcie_mdio_write(base, MDIO_PORT0, SET_ADDR_OFFSET, 0x1600)))
+ {
+ return err;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(regs); ++i)
+ {
+ if ((err = brcm_pcie_mdio_write(base, MDIO_PORT0, regs[i], data[i])))
+ {
+ return err;
+ }
+ }
+
+ rt_hw_us_delay(200);
+
+ return RT_EOK;
+}
+
+static void brcm_pcie_serdes_pm_clk_period(struct brcm_pcie *pcie)
+{
+ rt_uint32_t tmp;
+ void *base = pcie->base;
+
+ /*
+ * L1SS sub-state timers: PM clock period 18.52ns (1/54MHz, round down).
+ */
+ tmp = HWREG32(base + PCIE_RC_PL_PHY_CTL_15);
+ tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK;
+ tmp |= 0x12;
+ HWREG32(base + PCIE_RC_PL_PHY_CTL_15) = tmp;
+}
+
+/* Limits operation to a specific generation (1, 2, or 3) */
+static void brcm_pcie_set_generation(struct brcm_pcie *pcie, int generation)
+{
+ rt_uint16_t lnkctl2;
+ rt_uint32_t lnkcap;
+
+ lnkctl2 = HWREG16(pcie->base + BRCM_PCIE_CAP_REGS + PCIER_LINK_CTL2);
+ lnkcap = HWREG32(pcie->base + BRCM_PCIE_CAP_REGS + PCIER_LINK_CAP);
+
+ replace_u32_bitfield(&lnkcap, generation, PCIEM_LINK_CAP_MAX_SPEED);
+ HWREG32(pcie->base + BRCM_PCIE_CAP_REGS + PCIER_LINK_CAP) = lnkcap;
+
+ replace_u16_bitfield(&lnkctl2, generation, PCIEM_LNKCTL2_TLS);
+ HWREG16(pcie->base + BRCM_PCIE_CAP_REGS + PCIER_LINK_CTL2) = lnkctl2;
+}
+
+static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, rt_uint32_t win,
+ rt_uint64_t cpu_addr, rt_uint64_t pcie_addr, rt_uint64_t size)
+{
+ int high_addr_shift;
+ rt_ubase_t cpu_addr_mb, limit_addr_mb;
+ rt_uint32_t cpu_addr_mb_high, limit_addr_mb_high, tmp;
+
+ /* Set the base of the pcie_addr window */
+ HWREG32(pcie->base + PCIE_MEM_WIN0_LO(win)) = rt_lower_32_bits(pcie_addr);
+ HWREG32(pcie->base + PCIE_MEM_WIN0_HI(win)) = rt_upper_32_bits(pcie_addr);
+
+ /* Write the addr base & limit lower bits (in MBs) */
+ cpu_addr_mb = cpu_addr / SIZE_MB;
+ limit_addr_mb = (cpu_addr + size - 1) / SIZE_MB;
+
+ tmp = HWREG32(pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
+ replace_u32_bitfield(&tmp, cpu_addr_mb,
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
+ replace_u32_bitfield(&tmp, limit_addr_mb,
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK);
+ HWREG32(pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win)) = tmp;
+
+ if (is_bmips(pcie))
+ {
+ return;
+ }
+
+ /* Write the cpu & limit addr upper bits */
+ high_addr_shift = __hweight32(PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
+
+ cpu_addr_mb_high = cpu_addr_mb >> high_addr_shift;
+ tmp = HWREG32(pcie->base + PCIE_MEM_WIN0_BASE_HI(win));
+ replace_u32_bitfield(&tmp, cpu_addr_mb_high,
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK);
+ HWREG32(pcie->base + PCIE_MEM_WIN0_BASE_HI(win)) = tmp;
+
+ limit_addr_mb_high = limit_addr_mb >> high_addr_shift;
+ tmp = HWREG32(pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
+ replace_u32_bitfield(&tmp, limit_addr_mb_high,
+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK);
+ HWREG32(pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win)) = tmp;
+}
+
+static void brcm_pcie_misc_ctrl_enable_access(struct brcm_pcie *pcie)
+{
+ void *base = pcie->base;
+ rt_uint32_t tmp = HWREG32(base + PCIE_MISC_MISC_CTRL);
+ rt_uint32_t burst;
+
+ if (is_bmips(pcie))
+ {
+ burst = 0x1;
+ }
+ else if (pcie->soc_data->type == BCM2711)
+ {
+ burst = 0x0;
+ }
+ else if (pcie->soc_data->type == BCM7278)
+ {
+ burst = 0x3;
+ }
+ else
+ {
+ burst = 0x2;
+ }
+
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK);
+ replace_u32_bitfield(&tmp, burst, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK);
+ HWREG32(base + PCIE_MISC_MISC_CTRL) = tmp;
+}
+
+static void brcm_pcie_apply_outbound_wins(struct brcm_pcie *pcie)
+{
+ struct rt_pci_host_bridge *bridge = pcie->bridge;
+ int num_out_wins = 0;
+
+ for (int i = 0; i < bridge->bus_regions_nr; ++i)
+ {
+ struct rt_pci_bus_region *region = &bridge->bus_regions[i];
+
+ if (region->flags != PCI_BUS_REGION_F_MEM &&
+ region->flags != PCI_BUS_REGION_F_PREFETCH)
+ {
+ continue;
+ }
+
+ if (num_out_wins >= BRCM_NUM_PCIE_OUT_WINS)
+ {
+ LOG_E("Too many outbound wins");
+ return;
+ }
+
+ if (is_bmips(pcie))
+ {
+ rt_uint64_t start = region->cpu_addr;
+ rt_off_t offset = region->cpu_addr - region->phy_addr;
+ rt_uint32_t nwins = region->size / 128 * SIZE_MB;
+
+ if (nwins > BRCM_NUM_PCIE_OUT_WINS)
+ {
+ nwins = BRCM_NUM_PCIE_OUT_WINS;
+ }
+
+ for (int j = 0; j < nwins; ++j, start += 128 * SIZE_MB)
+ {
+ brcm_pcie_set_outbound_win(pcie, j, start, start - offset, 128 * SIZE_MB);
+ }
+ return;
+ }
+
+ brcm_pcie_set_outbound_win(pcie, num_out_wins,
+ region->cpu_addr, region->phy_addr, region->size);
+ ++num_out_wins;
+ }
+}
+
+/* The controller is capable of serving in both RC and EP roles */
+static rt_bool_t brcm_pcie_rc_mode(struct brcm_pcie *pcie)
+{
+ void *base = pcie->base;
+ rt_uint32_t val = HWREG32(base + PCIE_MISC_PCIE_STATUS);
+
+ return !!RT_FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val);
+}
+
+static rt_bool_t brcm_pcie_link_up(struct brcm_pcie *pcie)
+{
+ rt_uint32_t val = HWREG32(pcie->base + PCIE_MISC_PCIE_STATUS);
+ rt_uint32_t dla = RT_FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK, val);
+ rt_uint32_t plu = RT_FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK, val);
+
+ return dla && plu;
+}
+
+static void brcm_pcie_prep_train_clk(struct brcm_pcie *pcie)
+{
+ rt_uint32_t tmp;
+ void *base = pcie->base;
+
+ tmp = HWREG32(base + HARD_DEBUG(pcie));
+ tmp &= ~PCIE_CLKREQ_MASK;
+ HWREG32(base + HARD_DEBUG(pcie)) = tmp;
+}
+
+static void brcm_pcie_delay_ms(rt_uint32_t ms)
+{
+ if (ms == 0)
+ {
+ return;
+ }
+
+ /*
+ * Always busy-wait: link training runs during init (often before the
+ * scheduler is fully ready). mdelay can yield or mis-time here.
+ */
+ rt_hw_us_delay(ms * 1000UL);
+}
+
+static void *brcm_pcie_map(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg)
+{
+ void *base;
+ struct brcm_pcie *pcie = bus->sysdata;
+
+ base = pcie->base;
+
+ /* Accesses to the RC go right to the RC registers if !devfn */
+ if (rt_pci_is_root_bus(bus))
+ {
+ return devfn ? RT_NULL : base + PCIE_ECAM_REG(reg);
+ }
+
+ /* An access to our HW w/o link-up will cause a CPU Abort */
+ if (!brcm_pcie_link_up(pcie))
+ {
+ return RT_NULL;
+ }
+
+ /* For devices, write to the config space index register */
+ HWREG32(pcie->base + IDX_ADDR(pcie)) = PCIE_ECAM_OFFSET(bus->number, devfn, 0);
+ return base + DATA_ADDR(pcie) + PCIE_ECAM_REG(reg);
+}
+
+static void *brcm7425_pcie_map(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg)
+{
+ void *base;
+ struct brcm_pcie *pcie = bus->sysdata;
+
+ base = pcie->base;
+
+ /* Accesses to the RC go right to the RC registers if !devfn */
+ if (rt_pci_is_root_bus(bus))
+ {
+ return devfn ? RT_NULL : base + PCIE_ECAM_REG(reg);
+ }
+
+ /* An access to our HW w/o link-up will cause a CPU Abort */
+ if (!brcm_pcie_link_up(pcie))
+ {
+ return RT_NULL;
+ }
+
+ /* For devices, write to the config space index register */
+ HWREG32(base + IDX_ADDR(pcie)) = PCIE_ECAM_OFFSET(bus->number, devfn, reg);
+ return base + DATA_ADDR(pcie);
+}
+
+static rt_err_t brcm_pcie_bridge_sw_init_set_generic(struct brcm_pcie *pcie, rt_uint32_t val)
+{
+ rt_err_t err;
+ rt_uint32_t tmp, mask = RGR1_SW_INIT_1_INIT_GENERIC_MASK;
+ rt_uint32_t shift = RGR1_SW_INIT_1_INIT_GENERIC_SHIFT;
+
+ if (pcie->bridge_rstc)
+ {
+ if (val)
+ {
+ err = rt_reset_control_assert(pcie->bridge_rstc);
+ }
+ else
+ {
+ err = rt_reset_control_deassert(pcie->bridge_rstc);
+ }
+
+ return err;
+ }
+
+ tmp = HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+ tmp = (tmp & ~mask) | ((val << shift) & mask);
+ HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie)) = tmp;
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_pcie_bridge_sw_init_set_7278(struct brcm_pcie *pcie, rt_uint32_t val)
+{
+ rt_uint32_t tmp, mask = RGR1_SW_INIT_1_INIT_7278_MASK;
+ rt_uint32_t shift = RGR1_SW_INIT_1_INIT_7278_SHIFT;
+
+ tmp = HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+ tmp = (tmp & ~mask) | ((val << shift) & mask);
+ HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie)) = tmp;
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_pcie_perst_set_4908(struct brcm_pcie *pcie, rt_uint32_t val)
+{
+ rt_err_t err;
+
+ if (!pcie->perst_rstc)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (val)
+ {
+ err = rt_reset_control_assert(pcie->perst_rstc);
+ }
+ else
+ {
+ err = rt_reset_control_deassert(pcie->perst_rstc);
+ }
+
+ return err;
+}
+
+static rt_err_t brcm_pcie_perst_set_7278(struct brcm_pcie *pcie, rt_uint32_t val)
+{
+ rt_uint32_t tmp;
+
+ /* Perst bit has moved and assert value is 0 */
+ tmp = HWREG32(pcie->base + PCIE_MISC_PCIE_CTRL);
+ replace_u32_bitfield(&tmp, !val, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK);
+ HWREG32(pcie->base + PCIE_MISC_PCIE_CTRL) = tmp;
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, rt_uint32_t val)
+{
+ rt_uint32_t tmp;
+
+ tmp = HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie));
+ replace_u32_bitfield(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK);
+ HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie)) = tmp;
+
+ return RT_EOK;
+}
+
+/*
+ * access timeout may occur during L1SS sleep periods, even without the
+ * presence of a PCIe access.
+ */
+static void brcm_extend_rbus_timeout(struct brcm_pcie *pcie)
+{
+ /* 4 seconds, our setting for L1SS */
+ const rt_uint32_t timeout_us = 4000000;
+
+ /* 7712 does not have this (RGR1) timer */
+ if (pcie->soc_data->type == BCM7712)
+ {
+ return;
+ }
+
+ /* Each unit in timeout register is 1/216,000,000 seconds */
+ HWREG32(pcie->base + PCIE_RGR1_SW_INIT_1(pcie) - 8) = 216 * timeout_us;
+}
+
+static void brcm_config_clkreq(struct brcm_pcie *pcie)
+{
+ rt_err_t err;
+ void *base = pcie->base;
+ rt_uint32_t clkreq_cntl, tmp;
+ const char *mode = "default";
+
+ err = rt_dm_dev_prop_read_string(pcie->dev, "brcm,clkreq-mode", &mode);
+
+ if (err && err != -RT_EINVAL)
+ {
+ mode = "safe";
+ }
+
+ /*
+ * brcm,enable-l1ss in DT documents capability; until ASPM is fully
+ * handled in RT-Thread, force refclk on to avoid EP stuck in L1.x.
+ */
+ if (pcie->soc_data->type == BCM7712 &&
+ rt_dm_dev_prop_read_bool(pcie->dev, "brcm,enable-l1ss"))
+ {
+ mode = "safe";
+ }
+
+ /* Start out assuming safe mode (both mode bits cleared) */
+ clkreq_cntl = HWREG32(base + HARD_DEBUG(pcie));
+ clkreq_cntl &= ~PCIE_CLKREQ_MASK;
+
+ if (!rt_strcmp(mode, "no-l1ss"))
+ {
+ /*
+ * "no-l1ss" -- Provides Clock Power Management, L0s, and
+ * L1, but cannot provide L1 substate (L1SS) power
+ * savings. If the downstream device connected to the RC is
+ * L1SS capable AND the OS enables L1SS, all PCIe traffic
+ * may abruptly halt, potentially hanging the system.
+ */
+ clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
+ /*
+ * We want to un-advertise L1 substates because if the OS
+ * tries to configure the controller into using L1 substate
+ * power savings it may fail or hang when the RC HW is in
+ * "no-l1ss" mode.
+ */
+ tmp = HWREG32(base + PCIE_RC_CFG_PRIV1_ROOT_CAP);
+ replace_u32_bitfield(&tmp, 2, PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK);
+ HWREG32(base + PCIE_RC_CFG_PRIV1_ROOT_CAP) = tmp;
+ }
+ else if (!rt_strcmp(mode, "default"))
+ {
+ /*
+ * "default" -- Provides L0s, L1, and L1SS, but not
+ * compliant to provide Clock Power Management;
+ * specifically, may not be able to meet the Tclron max
+ * timing of 400ns as specified in "Dynamic Clock Control",
+ * section 3.2.5.2.2 of the PCIe spec. This situation is
+ * atypical and should happen only with older devices.
+ */
+ clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK;
+ brcm_extend_rbus_timeout(pcie);
+ }
+ else
+ {
+ /*
+ * "safe" -- No power savings; refclk is driven by RC
+ * unconditionally.
+ */
+ if (rt_strcmp(mode, "safe") != 0)
+ {
+ LOG_W("invalid 'brcm,clkreq-mode' DT string");
+ }
+ mode = "safe";
+ clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_REFCLK_OVRD_OUT_MASK;
+ clkreq_cntl |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_REFCLK_OVRD_ENABLE_MASK;
+ tmp = HWREG32(base + PCIE_RC_CFG_PRIV1_ROOT_CAP);
+ replace_u32_bitfield(&tmp, 2, PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK);
+ HWREG32(base + PCIE_RC_CFG_PRIV1_ROOT_CAP) = tmp;
+ }
+
+ HWREG32(base + HARD_DEBUG(pcie)) = clkreq_cntl;
+}
+
+
+static rt_err_t brcm_pcie_start_link(struct brcm_pcie *pcie)
+{
+ rt_err_t err;
+ rt_uint32_t tmp;
+ rt_uint16_t tmp16;
+ void *base = pcie->base;
+
+ if (pcie->generation)
+ {
+ brcm_pcie_set_generation(pcie, pcie->generation);
+ }
+
+ brcm_pcie_prep_train_clk(pcie);
+
+ if (pcie->tperst_clk_ms)
+ {
+ tmp = HWREG32(base + HARD_DEBUG(pcie));
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
+ HWREG32(base + HARD_DEBUG(pcie)) = tmp;
+
+ if ((err = pcie->soc_data->perst_set(pcie, 0)))
+ {
+ return err;
+ }
+ brcm_pcie_delay_ms(pcie->tperst_clk_ms);
+
+ tmp = HWREG32(base + HARD_DEBUG(pcie));
+ replace_u32_bitfield(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
+ HWREG32(base + HARD_DEBUG(pcie)) = tmp;
+ }
+ else
+ {
+ if ((err = pcie->soc_data->perst_set(pcie, 0)))
+ {
+ return err;
+ }
+ }
+
+ brcm_pcie_delay_ms(PCIE_RESET_CONFIG_WAIT_MS);
+
+ for (int i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
+ {
+ brcm_pcie_delay_ms(5);
+ }
+
+ if (!brcm_pcie_link_up(pcie))
+ {
+ LOG_E("%s: link down", rt_dm_dev_get_name(pcie->dev));
+ return -RT_EINVAL;
+ }
+
+ brcm_config_clkreq(pcie);
+
+ if (pcie->soc_data->post_setup)
+ {
+ /*
+ * post_setup may run before the link is up; re-apply SerDes PLL
+ * settings after training so downstream refclk is stable.
+ */
+ if ((err = brcm_pcie_serdes_munge_pll(pcie)))
+ {
+ LOG_W("post-train serdes munge failed: %s", rt_strerror(err));
+ }
+ else
+ {
+ brcm_pcie_serdes_pm_clk_period(pcie);
+ }
+ }
+
+ if (pcie->ssc)
+ {
+ if (brcm_pcie_set_ssc(pcie))
+ {
+ LOG_E("Failed attempt to enter ssc mode");
+ }
+ }
+
+ brcm_pcie_reapply_7712_maps(pcie);
+
+ tmp16 = HWREG16(base + BRCM_PCIE_CAP_REGS + PCIER_ROOT_CAP);
+ if (tmp16 & PCIEM_ROOT_CAP_CRS_VIS)
+ {
+ tmp16 = HWREG16(base + BRCM_PCIE_CAP_REGS + PCIER_ROOT_CTL);
+ replace_u16_bitfield(&tmp16, 1, PCIEM_ROOT_CTL_CRS_VIS);
+ HWREG16(base + BRCM_PCIE_CAP_REGS + PCIER_ROOT_CTL) = tmp16;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_pcie_add_bus(struct rt_pci_bus *bus)
+{
+ rt_err_t err = RT_EOK;
+ struct brcm_pcie *pcie = bus->sysdata;
+ struct rt_device *dev = &bus->host_bridge->parent;
+
+ if (!bus->parent)
+ {
+ return RT_EOK;
+ }
+
+ if (!rt_pci_is_root_bus(bus->parent))
+ {
+ return RT_EOK;
+ }
+
+ if (dev->ofw_node)
+ {
+ rt_size_t supplies = 0;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pcie->supplies); ++i)
+ {
+ pcie->supplies[i] = rt_regulator_get(dev, supplies_prefix[i]);
+
+ if (rt_is_err(pcie->supplies[i]))
+ {
+ err = rt_ptr_err(pcie->supplies[i]);
+
+ while (i --> 0)
+ {
+ rt_regulator_put(pcie->supplies[i]);
+ pcie->supplies[i] = RT_NULL;
+ }
+
+ return err;
+ }
+ else if (pcie->supplies[i])
+ {
+ ++supplies;
+ }
+ }
+
+ if (!supplies)
+ {
+ goto _no_regulators;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pcie->supplies); ++i)
+ {
+ if (pcie->supplies[i])
+ {
+ if ((err = rt_regulator_enable(pcie->supplies[i])))
+ {
+ LOG_E("Can't enable regulators for downstream device");
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pcie->supplies); ++i)
+ {
+ rt_regulator_put(pcie->supplies[i]);
+ pcie->supplies[i] = RT_NULL;
+ }
+
+ return err;
+ }
+ }
+ }
+ }
+
+_no_regulators:
+ err = brcm_pcie_start_link(pcie);
+
+ return err;
+}
+
+static rt_err_t brcm_pcie_remove_bus(struct rt_pci_bus *bus)
+{
+ struct brcm_pcie *pcie = bus->sysdata;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pcie->supplies); ++i)
+ {
+ if (!rt_is_err_or_null(pcie->supplies[i]))
+ {
+ rt_regulator_disable(pcie->supplies[i]);
+ rt_regulator_put(pcie->supplies[i]);
+ }
+ }
+
+ return RT_EOK;
+}
+
+/* L23 is a low-power PCIe link state */
+static void brcm_pcie_enter_l23(struct brcm_pcie *pcie)
+{
+ int l23;
+ rt_uint32_t tmp;
+ void *base = pcie->base;
+
+ /* Assert request for L23 */
+ tmp = HWREG32(base + PCIE_MISC_PCIE_CTRL);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
+ HWREG32(base + PCIE_MISC_PCIE_CTRL) = tmp;
+
+ /* Wait up to 36 msec for L23 */
+ tmp = HWREG32(base + PCIE_MISC_PCIE_STATUS);
+ l23 = RT_FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK, tmp);
+
+ for (int i = 0; i < 15 && !l23; ++i)
+ {
+ rt_hw_us_delay(2200);
+
+ tmp = HWREG32(base + PCIE_MISC_PCIE_STATUS);
+ l23 = RT_FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK, tmp);
+ }
+
+ if (!l23)
+ {
+ LOG_E("%s: failed to enter low-power link state", rt_dm_dev_get_name(pcie->dev));
+ }
+}
+
+static rt_err_t brcm_phy_cntl(struct brcm_pcie *pcie, const int start)
+{
+ rt_err_t err = RT_EOK;
+ void *base = pcie->base;
+ rt_uint32_t val, tmp, combined_mask = 0;
+ const int beg = start ? 0 : PCIE_DVT_PMU_PHY_CTRL_DAST_NFLDS - 1;
+ const int end = start ? PCIE_DVT_PMU_PHY_CTRL_DAST_NFLDS : -1;
+ static const rt_uint32_t shifts[PCIE_DVT_PMU_PHY_CTRL_DAST_NFLDS] =
+ {
+ PCIE_DVT_PMU_PHY_CTRL_DAST_PWRDN_SHIFT,
+ PCIE_DVT_PMU_PHY_CTRL_DAST_RESET_SHIFT,
+ PCIE_DVT_PMU_PHY_CTRL_DAST_DIG_RESET_SHIFT,
+ };
+ static const rt_uint32_t masks[PCIE_DVT_PMU_PHY_CTRL_DAST_NFLDS] =
+ {
+ PCIE_DVT_PMU_PHY_CTRL_DAST_PWRDN_MASK,
+ PCIE_DVT_PMU_PHY_CTRL_DAST_RESET_MASK,
+ PCIE_DVT_PMU_PHY_CTRL_DAST_DIG_RESET_MASK,
+ };
+
+ for (int i = beg; i != end; start ? ++i : --i)
+ {
+ val = start ? RT_BIT_MASK(shifts[i]) : 0;
+
+ tmp = HWREG32(base + PCIE_DVT_PMU_PHY_CTRL);
+ tmp = (tmp & ~masks[i]) | (val & masks[i]);
+ HWREG32(base + PCIE_DVT_PMU_PHY_CTRL) = tmp;
+
+ rt_hw_us_delay(125);
+ combined_mask |= masks[i];
+ }
+
+ tmp = HWREG32(base + PCIE_DVT_PMU_PHY_CTRL);
+ val = start ? combined_mask : 0;
+
+ if ((tmp & combined_mask) != val)
+ {
+ err = -RT_EIO;
+ LOG_E("%s: failed to %s phy", rt_dm_dev_get_name(pcie->dev), start ? "start" : "stop");
+ }
+
+ return err;
+}
+
+
+static rt_err_t brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie)
+{
+ rt_err_t err;
+ rt_uint32_t tmp;
+ rt_uint8_t qos_map[8];
+ void *base = pcie->base;
+
+ if ((err = brcm_pcie_serdes_munge_pll(pcie)))
+ {
+ return err;
+ }
+
+ rt_hw_us_delay(200);
+ brcm_pcie_serdes_pm_clk_period(pcie);
+
+ /*
+ * BCM7712/2712 uses a UBUS-AXI bridge.
+ * Suppress AXI error responses and return 1s for read failures.
+ */
+ tmp = HWREG32(base + PCIE_MISC_UBUS_CTRL);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK);
+ HWREG32(base + PCIE_MISC_UBUS_CTRL) = tmp;
+ HWREG32(base + PCIE_MISC_AXI_READ_ERROR_DATA) = 0xffffffff;
+
+ /*
+ * Adjust timeouts. The UBUS timeout also affects Configuration Request
+ * Retry responses, as the request will get terminated if
+ * either timeout expires, so both have to be a large value
+ * (in clocks of 750MHz).
+ * Set UBUS timeout to 250ms, then set RC config retry timeout
+ * to be ~240ms.
+ *
+ * If CRSSVE=1 this will stop the core from blocking on a Retry
+ * response, but does require the device to be well-behaved...
+ */
+ HWREG32(base + PCIE_MISC_UBUS_TIMEOUT) = 0xb2d0000;
+ HWREG32(base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT) = 0xaba0000;
+
+ /*
+ * BCM2712 has a configurable QoS mechanism that assigns TLP Traffic Classes
+ * to separate AXI IDs with a configurable priority scheme.
+ * Dynamic priority elevation is supported through reception of Type 1
+ * Vendor Defined Messages, but several bugs make this largely ineffective.
+ */
+
+ /* Disable broken forwarding search. Set chicken bits for 2712D0 */
+ tmp = HWREG32(base + PCIE_MISC_AXI_INTF_CTRL);
+ tmp &= ~AXI_REQFIFO_EN_QOS_PROPAGATION;
+ tmp |= AXI_EN_RCLK_QOS_ARRAY_FIX | AXI_EN_QOS_UPDATE_TIMING_FIX | AXI_DIS_QOS_GATING_IN_MASTER;
+ HWREG32(base + PCIE_MISC_AXI_INTF_CTRL) = tmp;
+
+ /*
+ * Work around spurious QoS=0 assignments to inbound traffic.
+ * If the QOS_UPDATE_TIMING_FIX bit is Reserved-0, then this is a
+ * 2712C1 chip, or a single-lane RC. Use the best-effort alternative
+ * which is to partially throttle AXI requests in-flight to SDRAM.
+ */
+ tmp = HWREG32(base + PCIE_MISC_AXI_INTF_CTRL);
+ if (!(tmp & AXI_EN_QOS_UPDATE_TIMING_FIX))
+ {
+ tmp &= ~AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK;
+ tmp |= 15;
+ HWREG32(base + PCIE_MISC_AXI_INTF_CTRL) = tmp;
+ }
+
+ /* Disable VDM reception by default */
+ tmp = HWREG32(base + PCIE_MISC_CTRL_1);
+ tmp &= ~PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK;
+ HWREG32(base + PCIE_MISC_CTRL_1) = tmp;
+
+ /*
+ * U-Boot enables BAR2 UBUS remap access for inbound EP MemWr (DMA).
+ * MIP MSIX doorbell (PCI 0xff_ffff_f000) uses inbound BAR3 on 2712.
+ */
+ tmp = HWREG32(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK);
+ HWREG32(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP) = tmp;
+
+ tmp = HWREG32(base + PCIE_MISC_UBUS_BAR3_CONFIG_REMAP);
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK);
+ HWREG32(base + PCIE_MISC_UBUS_BAR3_CONFIG_REMAP) = tmp;
+
+ if (!rt_dm_dev_prop_read_u8_array_index(pcie->dev, "brcm,fifo-qos-map", 0, 4, qos_map))
+ {
+ /*
+ * Backpressure mode - each element is QoS for each
+ * quartile of FIFO level. Each TC gets the same map, because
+ * this mode is intended for nonrealtime EPs.
+ */
+ tmp = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ /* Priorities range from 0-15 */
+ qos_map[i] &= 0x0f;
+ tmp |= qos_map[i] << (i * 4);
+ }
+
+ for (int i = 0; i < 8; i++)
+ {
+ HWREG32(base + PCIE_MISC_TC_QUEUE_TO_QOS_MAP(i)) = tmp;
+ }
+ }
+ else if (!rt_dm_dev_prop_read_u8_array_index(pcie->dev, "brcm,vdm-qos-map", 0, 8, qos_map))
+ {
+ /* Enable VDM reception */
+ tmp = HWREG32(base + PCIE_MISC_CTRL_1);
+ tmp |= PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK;
+ HWREG32(base + PCIE_MISC_CTRL_1) = tmp;
+
+ tmp = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ /* Priorities range from 0-15 */
+ qos_map[i] &= 0x0f;
+ tmp |= qos_map[i] << (i * 4);
+ }
+ /* Broken forwarding means no point separating panic priorities from normal */
+ HWREG32(base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO) = tmp;
+ HWREG32(base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI) = tmp;
+
+ /* Match Vendor ID of 0 */
+ HWREG32(base + PCIE_RC_TL_VDM_CTL1) = 0;
+
+ /*
+ * Forward VDMs to priority interface anyway -
+ * useful for debugging starvation through the received VDM count fields.
+ */
+ tmp = HWREG32(base + PCIE_RC_TL_VDM_CTL0);
+ tmp |= PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK |
+ PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK |
+ PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK;
+ HWREG32(base + PCIE_RC_TL_VDM_CTL0) = tmp;
+ }
+
+ return RT_EOK;
+}
+
+static const int pcie_offsets[] =
+{
+ [RGR1_SW_INIT_1] = 0x9210,
+ [EXT_CFG_INDEX] = 0x9000,
+ [EXT_CFG_DATA] = 0x8000,
+ [PCIE_HARD_DEBUG] = 0x4204,
+ [PCIE_INTR2_CPU_BASE] = 0x4300,
+};
+
+static const int pcie_offsets_bcm7278[] =
+{
+ [RGR1_SW_INIT_1] = 0xc010,
+ [EXT_CFG_INDEX] = 0x9000,
+ [EXT_CFG_DATA] = 0x8000,
+ [PCIE_HARD_DEBUG] = 0x4204,
+ [PCIE_INTR2_CPU_BASE] = 0x4300,
+};
+
+static const int pcie_offsets_bcm7425[] =
+{
+ [RGR1_SW_INIT_1] = 0x8010,
+ [EXT_CFG_INDEX] = 0x8300,
+ [EXT_CFG_DATA] = 0x8304,
+ [PCIE_HARD_DEBUG] = 0x4204,
+ [PCIE_INTR2_CPU_BASE] = 0x4300,
+};
+
+static const int pcie_offsets_bcm7712[] =
+{
+ [RGR1_SW_INIT_1] = 0x9210,
+ [EXT_CFG_INDEX] = 0x9000,
+ [EXT_CFG_DATA] = 0x8000,
+ [PCIE_HARD_DEBUG] = 0x4304,
+ [PCIE_INTR2_CPU_BASE] = 0x4400,
+};
+
+static const struct pcie_cfg_soc_data generic_cfg =
+{
+ .reg_offsets = pcie_offsets,
+ .type = GENERIC,
+ .perst_set = brcm_pcie_perst_set_generic,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm7425_cfg =
+{
+ .reg_offsets = pcie_offsets_bcm7425,
+ .type = BCM7425,
+ .perst_set = brcm_pcie_perst_set_generic,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm7435_cfg =
+{
+ .reg_offsets = pcie_offsets,
+ .type = BCM7435,
+ .perst_set = brcm_pcie_perst_set_generic,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm4908_cfg =
+{
+ .reg_offsets = pcie_offsets,
+ .type = BCM4908,
+ .perst_set = brcm_pcie_perst_set_4908,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm7278_cfg =
+{
+ .reg_offsets = pcie_offsets_bcm7278,
+ .type = BCM7278,
+ .perst_set = brcm_pcie_perst_set_7278,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm2711_cfg =
+{
+ .reg_offsets = pcie_offsets,
+ .type = BCM2711,
+ .perst_set = brcm_pcie_perst_set_generic,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm7216_cfg =
+{
+ .reg_offsets = pcie_offsets_bcm7278,
+ .type = BCM7278,
+ .perst_set = brcm_pcie_perst_set_7278,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278,
+ .has_phy = RT_TRUE,
+ .num_inbound_wins = 3,
+};
+
+static const struct pcie_cfg_soc_data bcm7712_cfg =
+{
+ .reg_offsets = pcie_offsets_bcm7712,
+ .type = BCM7712,
+ .perst_set = brcm_pcie_perst_set_7278,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .num_inbound_wins = 10,
+};
+
+static const struct pcie_cfg_soc_data bcm2712_cfg =
+{
+ .reg_offsets = pcie_offsets_bcm7712,
+ .type = BCM7712,
+ .perst_set = brcm_pcie_perst_set_7278,
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
+ .post_setup = brcm_pcie_post_setup_bcm2712,
+ .quirks = CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN | CFG_QUIRK_NO_SSC,
+ .num_inbound_wins = 10,
+};
+
+static const struct rt_pci_ops brcm_pcie_ops =
+{
+ .add = brcm_pcie_add_bus,
+ .remove = brcm_pcie_remove_bus,
+ .map = brcm_pcie_map,
+ .read = rt_pci_bus_read_config_uxx,
+ .write = rt_pci_bus_write_config_uxx,
+};
+
+static const struct rt_pci_ops brcm7425_pcie_ops =
+{
+ .add = brcm_pcie_add_bus,
+ .remove = brcm_pcie_remove_bus,
+ .map = brcm7425_pcie_map,
+ .read = rt_pci_bus_read_config_generic_u32,
+ .write = rt_pci_bus_write_config_generic_u32,
+};
+
+static void brcm_msi_ack_irq(struct rt_pic_irq *pirq)
+{
+ struct brcm_msi *msi = pirq->pic->priv_data;
+
+ HWREG32(msi->intr_base + MSI_INT_CLR) = 1 << (pirq->hwirq + msi->legacy_shift);
+}
+
+static void brcm_msi_compose_msi_msg(struct rt_pic_irq *pirq, struct rt_pci_msi_msg *msg)
+{
+ struct brcm_msi *msi = pirq->pic->priv_data;
+
+ msg->address_lo = rt_lower_32_bits(msi->data_address);
+ msg->address_hi = rt_upper_32_bits(msi->data_address);
+ msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | pirq->hwirq;
+}
+
+static int brcm_msi_irq_alloc(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc)
+{
+ int irq, hwirq;
+ rt_ubase_t level;
+ struct rt_pic_irq *pirq;
+ struct brcm_msi *msi = pic->priv_data;
+
+ level = rt_spin_lock_irqsave(&msi->lock);
+ hwirq = rt_bitmap_next_clear_bit(msi->msi_map, 0, msi->msi_max_nr);
+
+ if (hwirq >= msi->msi_max_nr)
+ {
+ irq = -RT_EEMPTY;
+ goto _out_lock;
+ }
+
+ rt_bitmap_set_bit(msi->msi_map, hwirq);
+
+ irq = rt_pic_config_irq(pic, hwirq, hwirq);
+ pirq = rt_pic_find_irq(pic, hwirq);
+ pirq->mode = RT_IRQ_MODE_EDGE_RISING;
+
+_out_lock:
+ rt_spin_unlock_irqrestore(&msi->lock, level);
+
+ return irq;
+}
+
+static void brcm_msi_irq_free(struct rt_pic *pic, int irq)
+{
+ rt_ubase_t level;
+ struct rt_pic_irq *pirq;
+ struct brcm_msi *msi = pic->priv_data;
+
+ pirq = rt_pic_find_pirq(pic, irq);
+
+ if (!pirq)
+ {
+ return;
+ }
+
+ level = rt_spin_lock_irqsave(&msi->lock);
+ rt_bitmap_clear_bit(msi->msi_map, pirq->hwirq);
+ rt_spin_unlock_irqrestore(&msi->lock, level);
+}
+
+const static struct rt_pic_ops brcm_msi_ops =
+{
+ .name = "BRCMSTB-MSI",
+ .irq_ack = brcm_msi_ack_irq,
+ .irq_mask = rt_pci_msi_mask_irq,
+ .irq_unmask = rt_pci_msi_unmask_irq,
+ .irq_compose_msi_msg = brcm_msi_compose_msi_msg,
+ .irq_alloc_msi = brcm_msi_irq_alloc,
+ .irq_free_msi = brcm_msi_irq_free,
+};
+
+static void brcm_pcie_msi_isr(int irqno, void *param)
+{
+ rt_uint32_t status;
+ rt_uint32_t raw_status;
+ struct rt_pic_irq *pirq;
+ struct brcm_msi *msi = param;
+
+ RT_UNUSED(irqno);
+
+ raw_status = HWREG32(msi->intr_base + MSI_INT_STATUS);
+ status = raw_status >> msi->legacy_shift;
+
+ for (int bit = 0; bit < BRCM_INT_PCI_MSI_NR && status; ++bit)
+ {
+ if (!(RT_BIT(bit) & status))
+ {
+ continue;
+ }
+
+ pirq = rt_pic_find_irq(&msi->inner_pic, bit);
+ brcm_msi_ack_irq(pirq);
+ rt_pic_handle_isr(pirq);
+
+ pirq = rt_pic_find_irq(&msi->inner_pic, bit + 32);
+ brcm_msi_ack_irq(pirq);
+ rt_pic_handle_isr(pirq);
+
+ status &= ~RT_BIT(bit);
+ }
+
+ rt_hw_interrupt_umask(msi->irq);
+}
+
+static rt_err_t brcm_pcie_enable_msi(struct brcm_pcie *pcie)
+{
+ int irq;
+ rt_uint32_t val;
+ struct brcm_msi *msi;
+ struct rt_device *dev = pcie->dev;
+
+ if ((irq = rt_dm_dev_get_irq(dev, 1)) < 0)
+ {
+ LOG_E("Read map MSI interrupt error = %s", rt_strerror(irq));
+ return irq;
+ }
+
+ if (!(msi = rt_calloc(1, sizeof(*msi))))
+ {
+ return -RT_ENOMEM;
+ }
+
+ msi->pcie_base = pcie->base;
+ msi->data_address = pcie->msi_data_address;
+ msi->irq = irq;
+ msi->legacy = pcie->misc_revision < BRCM_PCIE_HW_REV_33;
+ rt_spin_lock_init(&msi->lock);
+
+ if (msi->legacy)
+ {
+ msi->intr_base = msi->pcie_base + PCIE_INTR2_CPU_BASE;
+ msi->msi_max_nr = BRCM_INT_PCI_MSI_LEGACY_NR;
+ msi->legacy_shift = 24;
+ }
+ else
+ {
+ msi->intr_base = msi->pcie_base + PCIE_MSI_INTR2_BASE;
+ msi->msi_max_nr = 64;
+ msi->legacy_shift = 0;
+ }
+
+ msi->inner_pic.priv_data = msi;
+ msi->inner_pic.ops = &brcm_msi_ops;
+ rt_pic_linear_irq(&msi->inner_pic, msi->msi_max_nr);
+ rt_pic_user_extends(&msi->inner_pic);
+
+ rt_hw_interrupt_install(msi->irq, brcm_pcie_msi_isr, msi, "brcm-pcie-msi");
+ rt_hw_interrupt_umask(msi->irq);
+
+ val = msi->legacy ? BRCM_INT_PCI_MSI_LEGACY_MASK : BRCM_INT_PCI_MSI_MASK;
+
+ HWREG32(msi->intr_base + MSI_INT_MASK_CLR) = val;
+ HWREG32(msi->intr_base + MSI_INT_CLR) = val;
+
+ /*
+ * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI enable,
+ * which we set to 1.
+ */
+ HWREG32(msi->pcie_base + PCIE_MISC_MSI_BAR_CONFIG_LO) = rt_lower_32_bits(msi->data_address) | 0x1;
+ HWREG32(msi->pcie_base + PCIE_MISC_MSI_BAR_CONFIG_HI) = rt_upper_32_bits(msi->data_address);
+
+ val = msi->legacy ? PCIE_MISC_MSI_DATA_CONFIG_VAL_8 : PCIE_MISC_MSI_DATA_CONFIG_VAL_32;
+ HWREG32(msi->pcie_base + PCIE_MISC_MSI_DATA_CONFIG) = val;
+
+ pcie->msi = msi;
+
+ rt_ofw_data(dev->ofw_node) = &msi->inner_pic;
+ rt_ofw_node_set_flag(dev->ofw_node, RT_OFW_F_READLY);
+
+ return RT_EOK;
+}
+
+rt_inline rt_err_t brcm_phy_start(struct brcm_pcie *pcie)
+{
+ return pcie->soc_data->has_phy ? brcm_phy_cntl(pcie, 1) : RT_EOK;
+}
+
+rt_inline rt_err_t brcm_phy_stop(struct brcm_pcie *pcie)
+{
+ return pcie->soc_data->has_phy ? brcm_phy_cntl(pcie, 0) : RT_EOK;
+}
+
+static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
+{
+ rt_uint32_t tmp;
+ void *base = pcie->base;
+
+ if (brcm_pcie_link_up(pcie))
+ {
+ brcm_pcie_enter_l23(pcie);
+ }
+ /* Assert fundamental reset */
+ pcie->soc_data->perst_set(pcie, 1);
+
+ /* Deassert request for L23 in case it was asserted */
+ tmp = HWREG32(base + PCIE_MISC_PCIE_CTRL);
+ replace_u32_bitfield(&tmp, 0, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
+ HWREG32(base + PCIE_MISC_PCIE_CTRL) = tmp;
+
+ if (pcie->soc_data->type != BCM2711)
+ {
+ /* Turn off SerDes */
+ tmp = HWREG32(base + HARD_DEBUG(pcie));
+ replace_u32_bitfield(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
+ HWREG32(base + HARD_DEBUG(pcie)) = tmp;
+ }
+
+ if (!(pcie->soc_data->quirks & CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN))
+ {
+ /* Shutdown PCIe bridge */
+ pcie->soc_data->bridge_sw_init_set(pcie, 1);
+ }
+}
+
+static void add_inbound_win(struct inbound_win *b, rt_uint8_t *count,
+ rt_uint64_t size, rt_uint64_t cpu_addr, rt_uint64_t pci_offset)
+{
+ b->size = size;
+ b->cpu_addr = cpu_addr;
+ b->pci_offset = pci_offset;
+ (*count)++;
+}
+
+/*
+ * Debian DT omits the MIP doorbell dma-ranges entry present in bcm2712.dtsi.
+ * EP MSIX MemWr to brcm,msi-pci-addr must inbound-map to the MIP MMIO block.
+ */
+static void brcm_pcie_add_mip_doorbell_win(struct brcm_pcie *pcie,
+ struct inbound_win *b, rt_uint8_t *n, const struct inbound_win *begin)
+{
+ struct rt_ofw_node *np, *msi_np;
+ rt_uint32_t addr_cells[2];
+ rt_uint64_t pci_door, cpu_door, reg_size;
+ int i;
+
+ if (pcie->soc_data->type != BCM7712 || !pcie->dev)
+ {
+ return;
+ }
+
+ np = pcie->dev->ofw_node;
+ msi_np = rt_ofw_parse_phandle(np, "msi-parent", 0);
+ if (!msi_np || msi_np == np)
+ {
+ rt_ofw_node_put(msi_np);
+ return;
+ }
+
+ if (!rt_ofw_node_is_compatible(msi_np, "brcm,bcm2712-mip-intc"))
+ {
+ rt_ofw_node_put(msi_np);
+ return;
+ }
+
+ if (rt_ofw_prop_read_u32_array_index(msi_np, "brcm,msi-pci-addr", 0, 2, addr_cells) < 2 ||
+ rt_ofw_get_address(msi_np, 0, &cpu_door, &reg_size))
+ {
+ rt_ofw_node_put(msi_np);
+ return;
+ }
+
+ pci_door = ((rt_uint64_t)addr_cells[0] << 32) | addr_cells[1];
+
+ for (i = 1; i <= *n; ++i)
+ {
+ if (begin[i].pci_offset == pci_door)
+ {
+ rt_ofw_node_put(msi_np);
+ return;
+ }
+ }
+
+ if (*n >= pcie->soc_data->num_inbound_wins)
+ {
+ LOG_W("No inbound slot for MIP doorbell pci=%#llx", (unsigned long long)pci_door);
+ rt_ofw_node_put(msi_np);
+ return;
+ }
+
+ add_inbound_win(b, n, 0x1000, cpu_door, pci_door);
+
+ rt_ofw_node_put(msi_np);
+}
+
+static int brcm_pcie_get_inbound_wins(struct brcm_pcie *pcie, struct inbound_win inbound_wins[])
+{
+ rt_uint8_t n = 0;
+ rt_uint64_t lowest_pcie_addr = ~(rt_uint64_t)0;
+ rt_uint64_t pci_offset, cpu_addr, size = 0, tot_size = 0;
+ struct rt_pci_host_bridge *bridge = pcie->bridge;
+ /*
+ * The HW registers (and PCIe) use order-1 numbering for BARs. As such,
+ * we have inbound_wins[0] unused and BAR1 starts at inbound_wins[1].
+ */
+ struct inbound_win *b_begin = &inbound_wins[1], *b = b_begin;
+
+ /*
+ * STB chips beside 7712 disable the first inbound window default.
+ * Rather being mapped to system memory it is mapped to the
+ * internal registers of the SoC. This feature is deprecated, has
+ * security considerations, and is not implemented in our modern
+ * SoCs.
+ */
+ if (pcie->soc_data->type != BCM7712)
+ {
+ add_inbound_win(b++, &n, 0, 0, 0);
+ }
+
+ for (int i = 0; i < bridge->dma_regions_nr; ++i)
+ {
+ rt_uint64_t pcie_start, cpu_start;
+ struct rt_pci_bus_region *region = &bridge->dma_regions[i];
+
+ pcie_start = region->phy_addr;
+ cpu_start = region->cpu_addr;
+
+ size = region->size;
+ tot_size += size;
+
+ if (pcie_start < lowest_pcie_addr)
+ {
+ lowest_pcie_addr = pcie_start;
+ }
+
+ /*
+ * 7712 and newer chips may have many BARs, with each
+ * offering a non-overlapping viewport to system memory.
+ * That being said, each BARs size must still be a power of two.
+ */
+ if (pcie->soc_data->type == BCM7712)
+ {
+ add_inbound_win(b++, &n, size, cpu_start, pcie_start);
+ }
+
+ if (n > pcie->soc_data->num_inbound_wins)
+ {
+ break;
+ }
+ }
+
+ if (lowest_pcie_addr == ~(rt_uint64_t)0)
+ {
+ return -RT_EINVAL;
+ }
+
+ /*
+ * 7712 and newer chips do not have an internal memory mapping system
+ * that enables multiple memory controllers. As such, it can return
+ * now w/o doing special configuration.
+ */
+ if (pcie->soc_data->type == BCM7712)
+ {
+ brcm_pcie_add_mip_doorbell_win(pcie, b, &n, inbound_wins);
+
+ if (n > pcie->soc_data->num_inbound_wins)
+ {
+ LOG_E("Too many inbound windows (%u)", n);
+ return -RT_EINVAL;
+ }
+
+ return n;
+ }
+
+ pcie->memc_nr = rt_dm_dev_prop_read_u64_array_index(pcie->dev,
+ "brcm,scb-sizes", 0, PCIE_BRCM_MAX_MEMC, pcie->memc_size);
+
+ if ((rt_ssize_t)pcie->memc_nr <= 0)
+ {
+ /* Make an educated guess */
+ pcie->memc_nr = 1;
+ pcie->memc_size[0] = 1ULL << __fls64(tot_size - 1);
+ }
+
+ /* Each memc is viewed through a "port" that is a power of 2 */
+ for (int i = 0, size = 0; i < pcie->memc_nr; ++i)
+ {
+ size += pcie->memc_size[i];
+ }
+
+ /* Our HW mandates that the window size must be a power of 2 */
+ size = 1ULL << __fls64(size - 1);
+
+ /*
+ * Pi4 firmware rewrites dma-ranges before boot.
+ * Ignore bogus brcm,scb-sizes and derive the inbound aperture from the
+ * parsed dma-ranges total instead.
+ */
+ if (pcie->soc_data->type == BCM2711)
+ {
+ if (tot_size >= SIZE_MB)
+ {
+ rt_uint64_t want = 1ULL << __fls64(tot_size - 1);
+
+ if (size < want)
+ {
+ size = want;
+ }
+ }
+ else if (lowest_pcie_addr == 0x400000000ULL)
+ {
+ size = 2ULL * SIZE_GB;
+ }
+
+ }
+
+ /*
+ * For STB chips, the BAR2 cpu_addr is hardwired to the start
+ * of system memory, so we set it to 0.
+ */
+ cpu_addr = 0;
+ pci_offset = lowest_pcie_addr;
+
+ /*
+ * We validate the inbound memory view even though we should trust
+ * whatever the device-tree provides. This is because of an HW issue on
+ * early Raspberry Pi 4's revisions (bcm2711). It turns out its
+ * firmware has to dynamically edit dma-ranges due to a bug on the
+ * PCIe controller integration, which prohibits any access above the
+ * lower 3GB of memory. Given this, we decided to keep the dma-ranges
+ * in check, avoiding hard to debug device-tree related issues in the
+ * future:
+ *
+ * The PCIe host controller by design must set the inbound viewport to
+ * be a contiguous arrangement of all of the system's memory. In
+ * addition, its size mut be a power of two. To further complicate
+ * matters, the viewport must start on a pcie-address that is aligned
+ * on a multiple of its size. If a portion of the viewport does not
+ * represent system memory -- e.g. 3GB of memory requires a 4GB
+ * viewport -- we can map the outbound memory in or after 3GB and even
+ * though the viewport will overlap the outbound memory the controller
+ * will know to send outbound memory downstream and everything else
+ * upstream.
+ *
+ * For example:
+ *
+ * - The best-case scenario, memory up to 3GB, is to place the inbound
+ * region in the first 4GB of pcie-space, as some legacy devices can
+ * only address 32bits. We would also like to put the MSI under 4GB
+ * as well, since some devices require a 32bit MSI target address.
+ *
+ * - If the system memory is 4GB or larger we cannot start the inbound
+ * region at location 0 (since we have to allow some space for
+ * outbound memory @ 3GB). So instead it will start at the 1x
+ * multiple of its size
+ */
+ if (!size || (pci_offset & (size - 1)) ||
+ (pci_offset < 4UL * SIZE_GB && pci_offset > 2UL * SIZE_GB))
+ {
+ return -RT_EINVAL;
+ }
+
+ /* Enable inbound window 2, the main inbound window for STB chips */
+ add_inbound_win(b++, &n, size, cpu_addr, pci_offset);
+
+ /*
+ * Disable inbound window 3. On some chips presents the same
+ * window as #2 but the data appears in a settable endianness.
+ */
+ add_inbound_win(b++, &n, 0, 0, 0);
+
+ return n;
+}
+
+static rt_uint32_t brcm_bar_reg_offset(int bar)
+{
+ if (bar <= 3)
+ {
+ return PCIE_MISC_RC_BAR1_CONFIG_LO + 8 * (bar - 1);
+ }
+ else
+ {
+ return PCIE_MISC_RC_BAR4_CONFIG_LO + 8 * (bar - 4);
+ }
+}
+
+static rt_uint32_t brcm_ubus_reg_offset(int bar)
+{
+ if (bar <= 3)
+ {
+ return PCIE_MISC_UBUS_BAR1_CONFIG_REMAP + 8 * (bar - 1);
+ }
+ else
+ {
+ return PCIE_MISC_UBUS_BAR4_CONFIG_REMAP + 8 * (bar - 4);
+ }
+}
+
+static void set_inbound_win_registers(struct brcm_pcie *pcie,
+ const struct inbound_win *inbound_wins, rt_uint8_t num_inbound_wins)
+{
+ void *base = pcie->base;
+
+ for (int i = 1; i <= num_inbound_wins; ++i)
+ {
+ rt_uint64_t pci_offset = inbound_wins[i].pci_offset;
+ rt_uint64_t cpu_addr = inbound_wins[i].cpu_addr;
+ rt_uint64_t size = inbound_wins[i].size;
+ rt_uint32_t reg_offset = brcm_bar_reg_offset(i);
+ rt_uint32_t tmp = rt_lower_32_bits(pci_offset);
+
+ replace_u32_bitfield(&tmp, brcm_pcie_encode_ibar_size(size),
+ PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK);
+
+ /* Write low */
+ HWREG32(base + reg_offset) = tmp;
+ /* Write high */
+ HWREG32(base + reg_offset + 4) = rt_upper_32_bits(pci_offset);
+
+ /*
+ * Most STB chips:
+ * Do nothing.
+ * 7712:
+ * All of their BARs need to be set.
+ */
+ if (pcie->soc_data->type == BCM7712)
+ {
+ /* BUS remap register settings */
+ reg_offset = brcm_ubus_reg_offset(i);
+ tmp = rt_lower_32_bits(cpu_addr) & ~0xfffU;
+ tmp |= PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK;
+ HWREG32(base + reg_offset) = tmp;
+ HWREG32(base + reg_offset + 4) = rt_upper_32_bits(cpu_addr);
+ }
+ }
+}
+
+static void brcm_pcie_reapply_inbound_access(struct brcm_pcie *pcie)
+{
+ void *base = pcie->base;
+
+ if (!base || pcie->soc_data->type != BCM7712)
+ {
+ return;
+ }
+
+ brcm_pcie_misc_ctrl_enable_access(pcie);
+
+ /*
+ * MIP MSIX doorbell lands on inbound BAR3 (PCI ff_ffff_f000), not BAR2.
+ * Re-enable ACCESS on every active inbound UBUS remap after link events.
+ */
+ for (int i = 1; i <= pcie->num_inbound_wins; ++i)
+ {
+ rt_uint32_t reg = brcm_ubus_reg_offset(i);
+ rt_uint32_t tmp;
+
+ if (pcie->inbound_wins[i].size == 0)
+ {
+ continue;
+ }
+
+ tmp = HWREG32(base + reg);
+ replace_u32_bitfield(&tmp, 1,
+ PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK);
+ HWREG32(base + reg) = tmp;
+ }
+}
+
+static void brcm_pcie_reapply_7712_maps(struct brcm_pcie *pcie)
+{
+ if (pcie->soc_data->type != BCM7712 || !pcie->num_inbound_wins)
+ {
+ return;
+ }
+
+ brcm_pcie_reapply_inbound_access(pcie);
+ set_inbound_win_registers(pcie, pcie->inbound_wins, pcie->num_inbound_wins);
+ brcm_pcie_apply_outbound_wins(pcie);
+}
+
+static rt_err_t brcm_pcie_setup(struct brcm_pcie *pcie)
+{
+ rt_err_t err;
+ void *base = pcie->base;
+ int num_out_wins = 0, num_inbound_wins = 0;
+ rt_uint32_t tmp, num_lanes = 0, num_lanes_cap = 0;
+ struct rt_pci_host_bridge *bridge = pcie->bridge;
+ struct inbound_win inbound_wins[PCIE_BRCM_MAX_INBOUND_WINS];
+
+ /* Reset the bridge */
+ pcie->soc_data->bridge_sw_init_set(pcie, 1);
+
+ /* Ensure that PERST# is asserted; some bootloaders may deassert it. */
+ if (pcie->soc_data->type == BCM2711)
+ {
+ if ((err = pcie->soc_data->perst_set(pcie, 1)))
+ {
+ pcie->soc_data->bridge_sw_init_set(pcie, 0);
+ return err;
+ }
+ }
+
+ rt_hw_us_delay(150);
+
+ /* Take the bridge out of reset */
+ if ((err = pcie->soc_data->bridge_sw_init_set(pcie, 0)))
+ {
+ return err;
+ }
+
+ /*
+ * On some BCM2711 integrations this register window can raise SError
+ * immediately after bridge reset deassert; skip this write there.
+ */
+ if (pcie->soc_data->type != BCM2711)
+ {
+ tmp = HWREG32(base + HARD_DEBUG(pcie));
+ if (is_bmips(pcie))
+ {
+ tmp &= ~PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
+ }
+ else
+ {
+ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
+ }
+ HWREG32(base + HARD_DEBUG(pcie)) = tmp;
+ /* Wait for SerDes to be stable */
+ rt_hw_us_delay(150);
+ }
+
+ brcm_pcie_misc_ctrl_enable_access(pcie);
+
+ num_inbound_wins = brcm_pcie_get_inbound_wins(pcie, inbound_wins);
+ if (num_inbound_wins < 0)
+ {
+ return num_inbound_wins;
+ }
+
+ set_inbound_win_registers(pcie, inbound_wins, num_inbound_wins);
+ pcie->num_inbound_wins = (rt_uint8_t)num_inbound_wins;
+ rt_memcpy(pcie->inbound_wins, inbound_wins, sizeof(inbound_wins));
+
+ if (!brcm_pcie_rc_mode(pcie))
+ {
+ LOG_E("PCIe RC controller misconfigured as Endpoint");
+ return -RT_EINVAL;
+ }
+
+ tmp = HWREG32(base + PCIE_MISC_MISC_CTRL);
+
+ for (int memc = 0; memc < pcie->memc_nr; memc++)
+ {
+ rt_uint32_t scb_size_val = rt_ilog2(pcie->memc_size[memc]) - 15;
+
+ if (memc == 0)
+ {
+ replace_u32_bitfield(&tmp, scb_size_val, SCB_SIZE_MASK(0));
+ }
+ else if (memc == 1)
+ {
+ replace_u32_bitfield(&tmp, scb_size_val, SCB_SIZE_MASK(1));
+ }
+ else if (memc == 2)
+ {
+ replace_u32_bitfield(&tmp, scb_size_val, SCB_SIZE_MASK(2));
+ }
+ }
+
+ HWREG32(base + PCIE_MISC_MISC_CTRL) = tmp;
+
+ /*
+ * We ideally want the MSI target address to be located in the 32bit
+ * addressable memory area. Some devices might depend on it. This is
+ * possible either when the inbound window is located above the lower
+ * 4GB or when the inbound area is smaller than 4GB (taking into
+ * account the rounding-up we're forced to perform).
+ */
+ if (inbound_wins[2].pci_offset >= (4UL * SIZE_GB) ||
+ (inbound_wins[2].size + inbound_wins[2].pci_offset) < (4UL * SIZE_GB))
+ {
+ pcie->msi_data_address = BRCM_MSI_TARGET_ADDR_LT_4GB;
+ }
+ else
+ {
+ pcie->msi_data_address = BRCM_MSI_TARGET_ADDR_GT_4GB;
+ }
+
+ /* Don't advertise L0s capability if 'aspm-no-l0s' */
+ tmp = HWREG32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+ if (rt_dm_dev_prop_read_bool(pcie->dev, "aspm-no-l0s"))
+ {
+ tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S;
+ }
+ HWREG32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY) = tmp;
+
+ num_lanes_cap = (tmp & PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK) >> 4;
+
+ /*
+ * Use hardware negotiated Max Link Width value by default. If the
+ * "num-lanes" DT property is present, assume that the chip's default
+ * link width capability information is incorrect/undesired and use the
+ * specified value instead.
+ */
+ if (!rt_dm_dev_prop_read_u32(pcie->dev, "num-lanes", &num_lanes) &&
+ num_lanes && num_lanes <= 4 && num_lanes_cap != num_lanes)
+ {
+ replace_u32_bitfield(&tmp, num_lanes,
+ PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_WIDTH_MASK);
+ HWREG32(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY) = tmp;
+ tmp = HWREG32(base + PCIE_RC_PL_REG_PHY_CTL_1);
+ replace_u32_bitfield(&tmp, 1,
+ PCIE_RC_PL_REG_PHY_CTL_1_REG_P2_POWERDOWN_ENA_NOSYNC_MASK);
+ HWREG32(base + PCIE_RC_PL_REG_PHY_CTL_1) = tmp;
+ }
+
+ /*
+ * For config space accesses on the RC, show the right class for
+ * a PCIe-PCIe bridge (the default setting is to be EP mode).
+ */
+ tmp = HWREG32(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
+ replace_u32_bitfield(&tmp, 0x060400,
+ PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
+ HWREG32(base + PCIE_RC_CFG_PRIV1_ID_VAL3) = tmp;
+
+ for (int i = 0; i < bridge->bus_regions_nr; ++i)
+ {
+ struct rt_pci_bus_region *region = &bridge->bus_regions[i];
+
+ if (region->flags != PCI_BUS_REGION_F_MEM &&
+ region->flags != PCI_BUS_REGION_F_PREFETCH)
+ {
+ continue;
+ }
+
+ if (num_out_wins >= BRCM_NUM_PCIE_OUT_WINS)
+ {
+ LOG_E("Too many outbound wins");
+ return -RT_EINVAL;
+ }
+
+ if (is_bmips(pcie))
+ {
+ rt_uint64_t start = region->cpu_addr;
+ rt_off_t offset = region->cpu_addr - region->phy_addr;
+ rt_uint32_t nwins = region->size / 128 * SIZE_MB;
+
+ /* BMIPS PCIe outbound windows have a 128MB max size */
+ if (nwins > BRCM_NUM_PCIE_OUT_WINS)
+ {
+ nwins = BRCM_NUM_PCIE_OUT_WINS;
+ }
+
+ for (int j = 0; j < nwins; ++j, start += 128 * SIZE_MB)
+ {
+ brcm_pcie_set_outbound_win(pcie, j, start, start - offset, 128 * SIZE_MB);
+ }
+ break;
+ }
+
+ brcm_pcie_set_outbound_win(pcie, num_out_wins,
+ region->cpu_addr, region->phy_addr, region->size);
+ ++num_out_wins;
+ }
+
+ /* PCIe->SCB endian mode for BAR */
+ tmp = HWREG32(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
+ replace_u32_bitfield(&tmp, PCIE_RC_CFG_VENDOR_SPECIFIC_REG1_LITTLE_ENDIAN,
+ PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
+ HWREG32(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1) = tmp;
+
+ if (pcie->soc_data->post_setup)
+ {
+ if ((err = pcie->soc_data->post_setup(pcie)))
+ {
+ return err;
+ }
+ }
+
+ return RT_EOK;
+}
+
+static void brcm_pcie_free(struct brcm_pcie *pcie)
+{
+ if (pcie->bridge)
+ {
+ rt_pci_host_bridge_remove(pcie->bridge);
+ }
+
+ if (pcie->soc_data && pcie->soc_data->has_phy)
+ {
+ brcm_phy_stop(pcie);
+ }
+
+ brcm_pcie_turn_off(pcie);
+
+ if (!rt_is_err_or_null(pcie->rescal_rstc))
+ {
+ rt_reset_control_assert(pcie->rescal_rstc);
+ rt_reset_control_put(pcie->rescal_rstc);
+ }
+
+ if (!rt_is_err_or_null(pcie->perst_rstc))
+ {
+ rt_reset_control_put(pcie->perst_rstc);
+ }
+
+ if (!rt_is_err_or_null(pcie->bridge_rstc))
+ {
+ rt_reset_control_put(pcie->bridge_rstc);
+ }
+
+ if (!rt_is_err_or_null(pcie->swinit_rstc))
+ {
+ rt_reset_control_put(pcie->swinit_rstc);
+ }
+
+ if (!rt_is_err_or_null(pcie->clk))
+ {
+ rt_clk_disable_unprepare(pcie->clk);
+ }
+
+ if (pcie->base)
+ {
+ rt_iounmap(pcie->base);
+ }
+
+ rt_pci_host_bridge_free(pcie->bridge);
+}
+
+static rt_err_t brcm_pcie_get_optional_reset(struct rt_device *dev, const char *name,
+ struct rt_reset_control **rstc)
+{
+ struct rt_reset_control *rc = rt_reset_control_get_by_name(dev, name);
+
+ if (rt_is_err(rc))
+ {
+ if (rt_ptr_err(rc) == -RT_ENOENT)
+ {
+ *rstc = RT_NULL;
+ return RT_EOK;
+ }
+
+ return rt_ptr_err(rc);
+ }
+
+ *rstc = rc;
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_pcie_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct brcm_pcie *pcie;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_pci_host_bridge *bridge;
+ struct rt_ofw_node *np = dev->ofw_node, *msi_np;
+
+ bridge = rt_pci_host_bridge_alloc(sizeof(*pcie));
+
+ if (!bridge)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pcie = (void *)bridge->priv;
+ pcie->soc_data = pdev->id->data;
+ pcie->dev = dev;
+ pcie->bridge = bridge;
+
+ pcie->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!pcie->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ pcie->clk = rt_clk_get_by_name(dev, "sw_pcie");
+
+ if (rt_is_err(pcie->clk))
+ {
+ if (rt_ptr_err(pcie->clk) != -RT_ENOENT)
+ {
+ err = rt_ptr_err(pcie->clk);
+ goto _fail;
+ }
+
+ pcie->clk = RT_NULL;
+ }
+ else if ((err = rt_clk_prepare_enable(pcie->clk)))
+ {
+ LOG_E("%s: could not enable clock", rt_dm_dev_get_name(dev));
+ goto _fail;
+ }
+
+ if (rt_dm_dev_prop_read_u32(dev, "max-link-speed", &pcie->generation))
+ {
+ pcie->generation = 0;
+ }
+
+ pcie->ssc = rt_dm_dev_prop_read_bool(dev, "brcm,enable-ssc");
+ rt_dm_dev_prop_read_u32(dev, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms);
+
+ if ((err = brcm_pcie_get_optional_reset(dev, "rescal", &pcie->rescal_rstc)))
+ {
+ goto _fail;
+ }
+
+ if ((err = brcm_pcie_get_optional_reset(dev, "perst", &pcie->perst_rstc)))
+ {
+ goto _fail;
+ }
+
+ if ((err = brcm_pcie_get_optional_reset(dev, "bridge", &pcie->bridge_rstc)))
+ {
+ goto _fail;
+ }
+
+ if ((err = brcm_pcie_get_optional_reset(dev, "swinit", &pcie->swinit_rstc)))
+ {
+ goto _fail;
+ }
+
+ pcie->soc_data->bridge_sw_init_set(pcie, 0);
+
+ if (pcie->swinit_rstc)
+ {
+ if ((err = rt_reset_control_assert(pcie->swinit_rstc)))
+ {
+ goto _fail;
+ }
+
+ rt_hw_us_delay(1);
+
+ if ((err = rt_reset_control_deassert(pcie->swinit_rstc)))
+ {
+ goto _fail;
+ }
+ }
+
+ if (pcie->rescal_rstc &&
+ (err = rt_reset_control_reset(pcie->rescal_rstc)))
+ {
+ goto _fail;
+ }
+
+ if ((err = brcm_phy_start(pcie)))
+ {
+ goto _fail;
+ }
+
+ bridge->parent.ofw_node = np;
+
+ if ((err = rt_pci_host_bridge_init(bridge)))
+ {
+ goto _fail;
+ }
+
+ if ((err = brcm_pcie_setup(pcie)))
+ {
+ goto _fail;
+ }
+
+ pcie->misc_revision = HWREG32(pcie->base + PCIE_MISC_REVISION);
+
+ if (pcie->soc_data->type == BCM4908 &&
+ pcie->misc_revision >= BRCM_PCIE_HW_REV_3_20)
+ {
+ LOG_E("%s: hardware revision with unsupported PERST# setup",
+ rt_dm_dev_get_name(dev));
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ msi_np = rt_ofw_parse_phandle(np, "msi-parent", 0);
+
+ if (msi_np == np)
+ {
+ if ((err = brcm_pcie_enable_msi(pcie)))
+ {
+ LOG_E("%s: probe ofw internal MSI error = %s",
+ rt_dm_dev_get_name(dev), rt_strerror(err));
+
+ goto _fail;
+ }
+ }
+
+ rt_ofw_node_put(msi_np);
+
+ bridge->ops = pcie->soc_data->type == BCM7425 ? &brcm7425_pcie_ops : &brcm_pcie_ops;
+ bridge->sysdata = pcie;
+
+ if ((err = rt_pci_host_bridge_probe(bridge)))
+ {
+ goto _fail;
+ }
+
+ if (!brcm_pcie_link_up(pcie))
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ brcm_pcie_reapply_7712_maps(pcie);
+
+ dev->user_data = pcie;
+
+ return RT_EOK;
+
+_fail:
+ if (pcie->msi)
+ {
+ rt_pic_cancel_irq(&pcie->msi->inner_pic);
+ }
+
+ brcm_pcie_free(pcie);
+
+ return err;
+}
+
+static rt_err_t brcm_pcie_remove(struct rt_platform_device *pdev)
+{
+ struct brcm_pcie *pcie = pdev->parent.user_data;
+
+ brcm_pcie_free(pcie);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id brcm_pcie_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg },
+ { .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg },
+ { .compatible = "brcm,bcm4908-pcie", .data = &bcm4908_cfg },
+ { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg },
+ { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg },
+ { .compatible = "brcm,bcm7216-pcie", .data = &bcm7216_cfg },
+ { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
+ { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
+ { .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
+ { .compatible = "brcm,bcm7712-pcie", .data = &bcm7712_cfg },
+ { /* sentinel */ }
+};
+
+void brcm_pcie_reapply_maps(struct rt_pci_device *pdev)
+{
+ struct brcm_pcie *pcie;
+ struct rt_pci_host_bridge *host_bridge;
+
+ if (!pdev || !pdev->bus)
+ {
+ return;
+ }
+
+ if (!(host_bridge = rt_pci_find_host_bridge(pdev->bus)))
+ {
+ return;
+ }
+
+ if ((pcie = host_bridge->sysdata))
+ {
+ brcm_pcie_reapply_7712_maps(pcie);
+ }
+}
+
+static struct rt_platform_driver brcm_pcie_driver =
+{
+ .name = "pcie-brcm",
+ .ids = brcm_pcie_ofw_ids,
+
+ .probe = brcm_pcie_probe,
+ .remove = brcm_pcie_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(brcm_pcie_driver);
diff --git a/bsp/raspberry-pi/dm/phy/Kconfig b/bsp/raspberry-pi/dm/phy/Kconfig
new file mode 100755
index 0000000000..fc7d9d5e9c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/phy/Kconfig
@@ -0,0 +1,7 @@
+config RT_PHY_MDIO_BCM_UNIMAC
+ bool "Broadcom UniMAC MDIO bus controller (BCM2711 GENET)"
+ default n
+
+config RT_PHY_BCM54213
+ bool "Broadcom BCM54213PE Ethernet PHY (Pi4/Pi5 RJ45)"
+ default n
diff --git a/bsp/raspberry-pi/dm/phy/SConscript b/bsp/raspberry-pi/dm/phy/SConscript
new file mode 100755
index 0000000000..a184e201fe
--- /dev/null
+++ b/bsp/raspberry-pi/dm/phy/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_PHY_BCM54213']):
+ src += ['phy-bcm54213.c']
+
+if GetDepend(['RT_PHY_MDIO_BCM_UNIMAC']):
+ src += ['mdio-bcm-unimac.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/phy/mdio-bcm-unimac.c b/bsp/raspberry-pi/dm/phy/mdio-bcm-unimac.c
new file mode 100755
index 0000000000..3ad24f26dc
--- /dev/null
+++ b/bsp/raspberry-pi/dm/phy/mdio-bcm-unimac.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-02-25 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "phy.mdio.bcm-unimac"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define MDIO_CMD 0x00
+#define MDIO_START_BUSY (1 << 29)
+#define MDIO_READ_FAIL (1 << 28)
+#define MDIO_RD (2 << 26)
+#define MDIO_WR (1 << 26)
+#define MDIO_PMD_SHIFT 21
+#define MDIO_PMD_MASK 0x1f
+#define MDIO_REG_SHIFT 16
+#define MDIO_REG_MASK 0x1f
+
+#define MDIO_CFG 0x04
+#define MDIO_C22 (1 << 0)
+#define MDIO_C45 0
+#define MDIO_CLK_DIV_SHIFT 4
+#define MDIO_CLK_DIV_MASK 0x3f
+#define MDIO_SUPP_PREAMBLE (1 << 12)
+
+struct unimac_mdio
+{
+ struct rt_device *dev;
+ struct mii_bus *mdio;
+
+ void *base;
+
+ rt_uint32_t clk_freq;
+ struct rt_clk *clk;
+};
+
+rt_inline void unimac_mdio_start(struct unimac_mdio *umdio)
+{
+ rt_uint32_t reg;
+
+ reg = HWREG32(umdio->base + MDIO_CMD);
+ reg |= MDIO_START_BUSY;
+ HWREG32(umdio->base + MDIO_CMD) = reg;
+}
+
+static rt_err_t unimac_mdio_poll(struct unimac_mdio *umdio)
+{
+ rt_uint32_t timeout = 1000;
+
+ do {
+ if (!(HWREG32(umdio->base + MDIO_CMD) & MDIO_START_BUSY))
+ {
+ return RT_EOK;
+ }
+
+ rt_hw_us_delay(1500);
+ } while (--timeout);
+
+ return -RT_ETIMEOUT;
+}
+
+static int unimac_mdio_read(struct mii_bus *bus, int addr, int devad, int reg)
+{
+ int err;
+ rt_uint32_t cmd;
+ struct unimac_mdio *umdio = bus->priv;
+
+ cmd = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT);
+ HWREG32(umdio->base + MDIO_CMD) = cmd;
+
+ unimac_mdio_start(umdio);
+
+ if ((err = (int)unimac_mdio_poll(umdio)))
+ {
+ return err;
+ }
+
+ cmd = HWREG32(umdio->base + MDIO_CMD);
+
+ return cmd & 0xffff;
+}
+
+static int unimac_mdio_write(struct mii_bus *bus, int addr, int devad, int reg, rt_uint16_t val)
+{
+ rt_uint32_t cmd;
+ struct unimac_mdio *umdio = bus->priv;
+
+ cmd = MDIO_WR | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & val);
+ HWREG32(umdio->base + MDIO_CMD) = cmd;
+
+ unimac_mdio_start(umdio);
+
+ return (int)unimac_mdio_poll(umdio);
+}
+
+static int unimac_mdio_reset(struct mii_bus *bus)
+{
+ rt_uint32_t read_mask = 0, addr;
+ struct unimac_mdio *umdio = bus->priv;
+ struct rt_ofw_node *np = umdio->dev->ofw_node, *child;
+
+ if (!np)
+ {
+ read_mask = ~bus->phy_mask;
+ }
+ else
+ {
+ rt_ofw_foreach_available_child_node(np, child)
+ {
+ if (!rt_ofw_prop_read_u32(child, "reg", &addr) && addr < RT_PHY_MAX)
+ {
+ read_mask |= 1 << addr;
+ }
+ }
+ }
+
+ for (addr = 0; addr < RT_PHY_MAX; ++addr)
+ {
+ if (read_mask & (1 << addr))
+ {
+ unimac_mdio_read(bus, addr, 0, RT_MII_BMSR);
+ }
+ }
+
+ return 0;
+}
+
+#ifdef RT_USING_PM
+static rt_err_t unimac_mdio_pm_suspend(const struct rt_device *device, rt_uint8_t mode)
+{
+ struct unimac_mdio *umdio = device->user_data;
+
+ rt_clk_disable_unprepare(umdio->clk);
+
+ return RT_EOK;
+}
+
+static void unimac_mdio_pm_resume(const struct rt_device *device, rt_uint8_t mode)
+{
+ struct unimac_mdio *umdio = device->user_data;
+
+ rt_clk_prepare_enable(umdio->clk);
+}
+
+static const struct rt_device_pm_ops unimac_mdio_pm_ops =
+{
+ .suspend = unimac_mdio_pm_suspend,
+ .resume = unimac_mdio_pm_resume,
+};
+#endif /* RT_USING_PM */
+
+static rt_err_t unimac_mdio_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint64_t base, size, mac_base;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *pnp;
+ struct unimac_mdio *umdio = rt_calloc(1, sizeof(*umdio));
+
+ if (!umdio)
+ {
+ return -RT_ENOMEM;
+ }
+ umdio->dev = dev;
+
+ pnp = rt_ofw_get_parent(np);
+ rt_ofw_get_address(pnp, 0, &mac_base, RT_NULL);
+ rt_ofw_node_put(pnp);
+ rt_ofw_get_address(np, 0, &base, &size);
+
+ umdio->base = rt_ioremap((void *)(mac_base + base), size);
+
+ if (!umdio->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ umdio->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(umdio->clk))
+ {
+ err = rt_ptr_err(umdio->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(umdio->clk)))
+ {
+ goto _fail;
+ }
+
+ rt_dm_dev_prop_read_u32(dev, "clock-frequency", &umdio->clk_freq);
+
+ if (umdio->clk_freq)
+ {
+ rt_uint32_t reg, div;
+ rt_ubase_t rate = 250000000;
+
+ if (umdio->clk)
+ {
+ rate = rt_clk_get_rate(umdio->clk);
+ }
+
+ div = (rate / (2 * umdio->clk_freq)) - 1;
+
+ /*
+ * The MDIO clock is the reference clock (typically 250Mhz) divided by
+ * 2 x (MDIO_CLK_DIV + 1)
+ */
+ reg = HWREG32(umdio->base + MDIO_CFG);
+ reg &= ~(MDIO_CLK_DIV_MASK << MDIO_CLK_DIV_SHIFT);
+ reg |= div << MDIO_CLK_DIV_SHIFT;
+ HWREG32(umdio->base + MDIO_CFG) = reg;
+ }
+
+ umdio->mdio = rt_mdio_alloc();
+
+ if (!umdio->mdio)
+ {
+ err = -RT_ENOMEM;
+ goto _free_clk;
+ }
+
+ rt_sprintf(umdio->mdio->name, "unimac MII bus");
+ umdio->mdio->priv = umdio;
+ umdio->mdio->read = unimac_mdio_read;
+ umdio->mdio->write = unimac_mdio_write;
+ umdio->mdio->reset = unimac_mdio_reset;
+
+ dev->user_data = umdio;
+
+ if ((err = rt_mdio_register(umdio->mdio)))
+ {
+ goto _free_clk;
+ }
+
+#ifdef RT_USING_PM
+ rt_pm_device_register(dev, &unimac_mdio_pm_ops);
+#endif
+
+ return RT_EOK;
+
+_free_clk:
+ if (!rt_is_err_or_null(umdio->clk))
+ {
+ rt_clk_disable_unprepare(umdio->clk);
+ }
+
+_fail:
+ if (umdio->base)
+ {
+ rt_iounmap(umdio->base);
+ }
+
+ if (umdio->mdio)
+ {
+ rt_free(umdio->mdio);
+ }
+
+ rt_free(umdio);
+
+ return err;
+}
+
+static rt_err_t unimac_mdio_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct unimac_mdio *umdio = dev->user_data;
+
+#ifdef RT_USING_PM
+ rt_pm_device_unregister(dev);
+#endif
+
+ rt_mdio_unregister(umdio->mdio);
+
+ rt_clk_disable_unprepare(umdio->clk);
+ rt_clk_put(umdio->clk);
+
+ rt_free(umdio->mdio);
+ rt_free(umdio);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id unimac_mdio_ofw_ids[] =
+{
+ { .compatible = "brcm,asp-v2.1-mdio", },
+ { .compatible = "brcm,asp-v2.0-mdio", },
+ { .compatible = "brcm,bcm6846-mdio", },
+ { .compatible = "brcm,genet-mdio-v5", },
+ { .compatible = "brcm,genet-mdio-v4", },
+ { .compatible = "brcm,genet-mdio-v3", },
+ { .compatible = "brcm,genet-mdio-v2", },
+ { .compatible = "brcm,genet-mdio-v1", },
+ { .compatible = "brcm,unimac-mdio", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver unimac_mdio_driver =
+{
+ .name = "unimac-mdio",
+ .ids = unimac_mdio_ofw_ids,
+
+ .probe = unimac_mdio_probe,
+ .remove = unimac_mdio_remove,
+};
+
+static int unimac_mdio_drv_register(void)
+{
+ rt_platform_driver_register(&unimac_mdio_driver);
+
+ return 0;
+}
+INIT_PLATFORM_EXPORT(unimac_mdio_drv_register);
diff --git a/bsp/raspberry-pi/dm/phy/phy-bcm54213.c b/bsp/raspberry-pi/dm/phy/phy-bcm54213.c
new file mode 100644
index 0000000000..54f4e9f1ed
--- /dev/null
+++ b/bsp/raspberry-pi/dm/phy/phy-bcm54213.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-06-18 GuEe-GUI BCM54213PE PHY for BCM2711 GENET
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <drivers/phy.h>
+
+#define DBG_TAG "phy.bcm54213"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+/* BCM54213PE on Raspberry Pi 4 (BCM2711 GENET) */
+#define PHY_ID_BCM54213PE 0x600d84a2
+
+#define MII_BCM54XX_AUX_CTL 0x18
+#define MII_BCM54XX_SHD 0x1c
+
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x07
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
+#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
+#define AUXCTL_MISC_RGMII_SKEW_EN (1 << 8)
+#define AUXCTL_MISC_WREN (1 << 15)
+
+#define MII_BCM54XX_SHD_WRITE (1 << 15)
+#define MII_BCM54XX_SHD_VAL(x) (((x) & 0x1f) << 10)
+#define MII_BCM54XX_SHD_DATA(x) (((x) & 0x3ff) << 0)
+
+#define BCM54810_SHD_CLK_CTL 0x3
+#define CLK_CTL_GTXCLK_EN (1 << 9)
+
+static int bcm54xx_auxctl_read(struct rt_phy_device *phydev, rt_uint16_t regnum)
+{
+ rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_AUX_CTL,
+ MII_BCM54XX_AUXCTL_SHDWSEL_MASK |
+ (regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT));
+
+ return rt_phy_read(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_AUX_CTL);
+}
+
+static int bcm54xx_auxctl_write(struct rt_phy_device *phydev, rt_uint16_t regnum, rt_uint16_t val)
+{
+ return rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_AUX_CTL, regnum | val);
+}
+
+static int bcm_phy_read_shadow(struct rt_phy_device *phydev, rt_uint16_t shadow)
+{
+ int val;
+
+ rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
+ val = rt_phy_read(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_SHD);
+
+ return MII_BCM54XX_SHD_DATA(val);
+}
+
+static int bcm_phy_write_shadow(struct rt_phy_device *phydev, rt_uint16_t shadow, rt_uint16_t val)
+{
+ return rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, MII_BCM54XX_SHD,
+ MII_BCM54XX_SHD_WRITE | MII_BCM54XX_SHD_VAL(shadow) | MII_BCM54XX_SHD_DATA(val));
+}
+
+static int bcm54xx_config_clock_delay(struct rt_phy_device *phydev)
+{
+ int val, err;
+
+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ if (val < 0)
+ {
+ return val;
+ }
+
+ val |= AUXCTL_MISC_WREN;
+
+ if (phydev->interface == RT_PHY_INTERFACE_MODE_RGMII ||
+ phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_TXID)
+ {
+ val &= ~AUXCTL_MISC_RGMII_SKEW_EN;
+ }
+ else if (phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_RXID)
+ {
+ val |= AUXCTL_MISC_RGMII_SKEW_EN;
+ }
+
+ err = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val);
+ if (err < 0)
+ {
+ return err;
+ }
+
+ val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
+ if (val < 0)
+ {
+ return val;
+ }
+
+ if (phydev->interface == RT_PHY_INTERFACE_MODE_RGMII ||
+ phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_RXID)
+ {
+ val &= ~CLK_CTL_GTXCLK_EN;
+ }
+ else if (phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == RT_PHY_INTERFACE_MODE_RGMII_TXID)
+ {
+ val |= CLK_CTL_GTXCLK_EN;
+ }
+
+ return bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+}
+
+static int bcm54213pe_config(struct rt_phy_device *phydev)
+{
+ int err;
+
+ err = bcm54xx_config_clock_delay(phydev);
+ if (err < 0)
+ {
+ return err;
+ }
+
+ LOG_D("PHY config if=%d", phydev->interface);
+
+ return rt_genphy_config(phydev);
+}
+
+static int bcm54213pe_read_bmsr(struct rt_phy_device *phydev)
+{
+ int bmsr;
+
+ /* BMSR link status is latch-low; read twice for current value */
+ bmsr = rt_phy_read(phydev, RT_MDIO_DEVAD_NONE, RT_MII_BMSR);
+ if (bmsr < 0)
+ {
+ return bmsr;
+ }
+
+ return rt_phy_read(phydev, RT_MDIO_DEVAD_NONE, RT_MII_BMSR);
+}
+
+static int bcm54213pe_startup(struct rt_phy_device *phydev)
+{
+ int bmsr;
+
+ /*
+ * Non-blocking startup: do not wait for autoneg in init context.
+ * Link-up / retry is handled by GENET link IRQ work and periodic poll.
+ */
+ bmsr = bcm54213pe_read_bmsr(phydev);
+ if (bmsr < 0)
+ {
+ return bmsr;
+ }
+
+ if (bmsr & RT_BMSR_LSTATUS)
+ {
+ phydev->link = 1;
+ rt_genphy_parse_link(phydev);
+ LOG_I("PHY up: speed=%d duplex=%d", phydev->speed, phydev->duplex);
+ return 0;
+ }
+
+ phydev->link = 0;
+ LOG_I("PHY link down at boot, defer to link event / retry work");
+ return 0;
+}
+
+static struct rt_phy_driver bcm54213pe_driver =
+{
+ .uid = PHY_ID_BCM54213PE,
+ .mask = 0xffffffff,
+ .name = "Broadcom BCM54213PE",
+ .features = RT_PHY_GBIT_FEATURES,
+ .config = bcm54213pe_config,
+ .startup = bcm54213pe_startup,
+};
+
+static int bcm54213_phy_drv_register(void)
+{
+ rt_phy_driver_register(&bcm54213pe_driver);
+
+ return 0;
+}
+INIT_PLATFORM_EXPORT(bcm54213_phy_drv_register);
diff --git a/bsp/raspberry-pi/dm/pic/Kconfig b/bsp/raspberry-pi/dm/pic/Kconfig
new file mode 100755
index 0000000000..0d2112aa9c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/Kconfig
@@ -0,0 +1,19 @@
+config RT_PIC_BCM2712_MIP
+ bool "Broadcom 2712 MSI-X Interrupt Peripheral support" if RT_PCI_MSI
+ depends on RT_USING_OFW
+ default n
+
+config RT_PIC_BCM2835_INTC
+ bool "BCM2835 intc"
+ depends on RT_USING_OFW
+ default n
+
+config RT_PIC_BCM2836_L1_INTC
+ bool "BCM2836 L1 intc"
+ depends on RT_USING_OFW
+ default n
+
+config RT_PIC_BRCMSTB_L2_IRQ
+ bool "BRCMSTB L2 IRQ"
+ depends on RT_USING_OFW
+ default n
diff --git a/bsp/raspberry-pi/dm/pic/SConscript b/bsp/raspberry-pi/dm/pic/SConscript
new file mode 100755
index 0000000000..ab14380a57
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/SConscript
@@ -0,0 +1,22 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_PIC_BCM2712_MIP']):
+ src += ['pic-bcm2712-mip.c']
+
+if GetDepend(['RT_PIC_BCM2835_INTC']):
+ src += ['pic-bcm2835.c']
+
+if GetDepend(['RT_PIC_BCM2836_L1_INTC']):
+ src += ['pic-bcm2836.c']
+
+if GetDepend(['RT_PIC_BRCMSTB_L2_IRQ']):
+ src += ['pic-brcmstb-l2.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pic/pic-bcm2712-mip.c b/bsp/raspberry-pi/dm/pic/pic-bcm2712-mip.c
new file mode 100755
index 0000000000..52b484a52a
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/pic-bcm2712-mip.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ * 2025-06-19 GuEe-GUI support upstream brcm,bcm2712-mip DT format
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pic.mip-msi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define MIP_INT_RAISE 0x00
+#define MIP_INT_CLEARE 0x10
+#define MIP_INT_CFGL_HOST 0x20
+#define MIP_INT_CFGH_HOST 0x30
+#define MIP_INT_MASKL_HOST 0x40
+#define MIP_INT_MASKH_HOST 0x50
+#define MIP_INT_MASKL_VPU 0x60
+#define MIP_INT_MASKH_VPU 0x70
+#define MIP_INT_STATUSL_HOST 0x80
+#define MIP_INT_STATUSH_HOST 0x90
+#define MIP_INT_STATUSL_VPU 0xa0
+#define MIP_INT_STATUSH_VPU 0xb0
+
+struct mip_msi
+{
+ struct rt_pic parent;
+ struct rt_pic *ppic;
+ struct rt_ofw_node *pic_np;
+
+ void *base;
+ rt_ubase_t msg_addr;
+ rt_uint32_t msi_base; /* The SGI/SPI number that MSIs start */
+ rt_uint32_t spi_base; /* msi_base + 32, GIC INTID for MIP hwirq 0 */
+ rt_uint32_t num_msis; /* The number of SGIs for MSIs */
+ rt_uint32_t msi_offset; /* Shift the allocated msi up by N */
+ rt_ubase_t *msi_map;
+
+ struct rt_spinlock msi_map_lock;
+};
+
+#define raw_to_mip_msi(raw) rt_container_of(raw, struct mip_msi, parent)
+
+static rt_err_t mip_msi_parse_pci_addr(struct rt_ofw_node *np, rt_uint64_t *addr)
+{
+ int nr;
+ rt_uint32_t cells[2];
+
+ nr = rt_ofw_prop_read_u32_array_index(np, "brcm,msi-pci-addr", 0, 2, cells);
+
+ if (nr < 2)
+ {
+ LOG_E("brcm,msi-pci-addr needs two u32 cells, got %d", nr);
+ return -RT_EINVAL;
+ }
+
+ *addr = ((rt_uint64_t)cells[0] << 32) | cells[1];
+
+ if (rt_upper_32_bits(*addr) != 0xffU)
+ {
+ LOG_E("brcm,msi-pci-addr hi=%#x lo=%#x (expected hi=0xff)",
+ rt_upper_32_bits(*addr), rt_lower_32_bits(*addr));
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t mip_msi_parse_intc_dt(struct mip_msi *mip, struct rt_ofw_node *np)
+{
+ mip->pic_np = rt_ofw_find_irq_parent(np, RT_NULL);
+ if (!mip->pic_np)
+ {
+ LOG_E("Unable to find PIC parent");
+ return -RT_EINVAL;
+ }
+
+ if (rt_ofw_prop_read_u32(np, "brcm,msi-base-spi", &mip->msi_base))
+ {
+ LOG_E("Unable to parse MSI base");
+ return -RT_EINVAL;
+ }
+
+ if (rt_ofw_prop_read_u32(np, "brcm,msi-num-spis", &mip->num_msis))
+ {
+ LOG_E("Unable to parse MSI numbers");
+ return -RT_EINVAL;
+ }
+
+ if (rt_ofw_prop_read_u32(np, "brcm,msi-offset", &mip->msi_offset))
+ {
+ mip->msi_offset = 0;
+ }
+
+ if (mip_msi_parse_pci_addr(np, &mip->msg_addr))
+ {
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t mip_msi_parse_upstream_dt(struct mip_msi *mip, struct rt_ofw_node *np)
+{
+ rt_err_t err;
+ rt_uint64_t size;
+ struct rt_ofw_cell_args args;
+
+ if (rt_ofw_prop_read_u32(np, "brcm,msi-offset", &mip->msi_offset))
+ {
+ mip->msi_offset = 0;
+ }
+
+ err = rt_ofw_parse_phandle_cells(np, "msi-ranges", "#interrupt-cells", 0, &args);
+ if (err)
+ {
+ LOG_E("Unable to parse msi-ranges");
+ return err;
+ }
+
+ mip->pic_np = args.data;
+ if (!mip->pic_np)
+ {
+ LOG_E("Unable to find MSI parent from msi-ranges");
+ return -RT_EINVAL;
+ }
+
+ if (args.args_count < 2)
+ {
+ LOG_E("Invalid msi-ranges interrupt specifier");
+ return -RT_EINVAL;
+ }
+
+ mip->msi_base = args.args[1];
+
+ if (rt_ofw_prop_read_u32_index(np, "msi-ranges", args.args_count + 1, &mip->num_msis))
+ {
+ LOG_E("Unable to parse MSI count from msi-ranges");
+ return -RT_EINVAL;
+ }
+
+ if (rt_ofw_get_address(np, 1, &mip->msg_addr, &size))
+ {
+ LOG_E("Unable to parse MSI doorbell address");
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t mip_msi_irq_init(struct rt_pic *pic)
+{
+ struct mip_msi *mip = raw_to_mip_msi(pic);
+
+ mip->ppic = rt_ofw_data(mip->pic_np);
+
+ return mip->ppic ? RT_EOK : -RT_ENOSYS;
+}
+
+static int mip_msi_parent_hwirq(struct mip_msi *mip, int hwirq)
+{
+ return hwirq + mip->spi_base;
+}
+
+static rt_err_t mip_msi_link_parent(struct mip_msi *mip, struct rt_pic_irq *pirq)
+{
+ rt_err_t err;
+ int parent_irq;
+
+ if (!mip || !pirq || !mip->ppic)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (pirq->parent)
+ {
+ return RT_EOK;
+ }
+
+ parent_irq = mip->ppic->ops->irq_map(mip->ppic,
+ mip_msi_parent_hwirq(mip, pirq->hwirq), RT_IRQ_MODE_EDGE_RISING);
+ if (parent_irq < 0)
+ {
+ return parent_irq;
+ }
+
+ err = rt_pic_cascade(pirq, parent_irq);
+ if (err)
+ {
+ LOG_E("MIP cascade virq=%d parent_irq=%d err=%d", pirq->irq, parent_irq, err);
+ }
+
+ return err;
+}
+
+static void mip_msi_irq_mask(struct rt_pic_irq *pirq)
+{
+ rt_pci_msi_mask_irq(pirq);
+ rt_pic_irq_parent_mask(pirq);
+}
+
+static void mip_msi_irq_unmask(struct rt_pic_irq *pirq)
+{
+ struct mip_msi *mip = raw_to_mip_msi(pirq->pic);
+
+ mip_msi_link_parent(mip, pirq);
+ rt_pci_msi_unmask_irq(pirq);
+ rt_pic_irq_parent_unmask(pirq);
+}
+
+static void mip_msi_compose_msi_msg(struct rt_pic_irq *pirq, struct rt_pci_msi_msg *msg)
+{
+ struct mip_msi *mip = raw_to_mip_msi(pirq->pic);
+
+ msg->address_hi = rt_upper_32_bits(mip->msg_addr);
+ msg->address_lo = rt_lower_32_bits(mip->msg_addr);
+ msg->data = pirq->hwirq;
+}
+
+static int mip_msi_irq_alloc_msi(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc)
+{
+ rt_ubase_t level;
+ rt_err_t err;
+ int irq, hwirq, hwirq_index;
+ struct rt_pic_irq *pirq;
+ struct mip_msi *mip = raw_to_mip_msi(pic);
+
+ RT_UNUSED(msi_desc);
+
+ if (!mip->ppic)
+ {
+ LOG_E("MIP parent PIC not ready");
+ return -RT_ENOSYS;
+ }
+
+ level = rt_spin_lock_irqsave(&mip->msi_map_lock);
+ hwirq_index = rt_bitmap_next_clear_bit(mip->msi_map, 0, mip->num_msis);
+
+ if (hwirq_index >= mip->num_msis)
+ {
+ irq = -RT_EEMPTY;
+ goto _out_lock;
+ }
+
+ hwirq = hwirq_index + mip->msi_offset;
+
+ irq = rt_pic_config_irq(pic, hwirq_index, hwirq);
+ if (irq < 0)
+ {
+ goto _out_lock;
+ }
+ pirq = rt_pic_find_irq(pic, hwirq_index);
+
+ pirq->mode = RT_IRQ_MODE_EDGE_RISING;
+ err = mip_msi_link_parent(mip, pirq);
+ if (err)
+ {
+ irq = err;
+ goto _out_lock;
+ }
+
+ rt_bitmap_set_bit(mip->msi_map, hwirq_index);
+
+_out_lock:
+ rt_spin_unlock_irqrestore(&mip->msi_map_lock, level);
+
+ return irq;
+}
+
+static void mip_msi_irq_free_msi(struct rt_pic *pic, int irq)
+{
+ rt_ubase_t level;
+ struct rt_pic_irq *pirq;
+ struct mip_msi *mip = raw_to_mip_msi(pic);
+
+ pirq = rt_pic_find_pirq(pic, irq);
+
+ if (!pirq)
+ {
+ return;
+ }
+
+ rt_hw_interrupt_mask(irq);
+ rt_pic_uncascade(pirq);
+
+ level = rt_spin_lock_irqsave(&mip->msi_map_lock);
+ rt_bitmap_clear_bit(mip->msi_map, pirq->hwirq - mip->msi_offset);
+ rt_spin_unlock_irqrestore(&mip->msi_map_lock, level);
+}
+
+static rt_err_t mip_msi_irq_set_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t state)
+{
+ struct mip_msi *mip = raw_to_mip_msi(pic);
+ struct rt_pic *ppic = mip->ppic;
+
+ if (ppic->ops->irq_set_state)
+ {
+ return ppic->ops->irq_set_state(ppic, mip_msi_parent_hwirq(mip, hwirq),
+ type, state);
+ }
+
+ return -RT_ENOSYS;
+}
+
+static rt_err_t mip_msi_irq_get_state(struct rt_pic *pic, int hwirq, int type, rt_bool_t *out_state)
+{
+ struct mip_msi *mip = raw_to_mip_msi(pic);
+ struct rt_pic *ppic = mip->ppic;
+
+ if (ppic->ops->irq_get_state)
+ {
+ return ppic->ops->irq_get_state(ppic, mip_msi_parent_hwirq(mip, hwirq),
+ type, out_state);
+ }
+
+ return -RT_ENOSYS;
+}
+
+const static struct rt_pic_ops mip_msi_ops =
+{
+ .name = "MIP-MSI",
+ .irq_init = mip_msi_irq_init,
+ .irq_mask = mip_msi_irq_mask,
+ .irq_unmask = mip_msi_irq_unmask,
+ /* irq_eoi omitted: GIC root handler performs a single EOI. */
+ .irq_set_affinity = rt_pic_irq_parent_set_affinity,
+ .irq_set_triger_mode = rt_pic_irq_parent_set_triger_mode,
+ .irq_compose_msi_msg = mip_msi_compose_msi_msg,
+ .irq_alloc_msi = mip_msi_irq_alloc_msi,
+ .irq_free_msi = mip_msi_irq_free_msi,
+ .irq_set_state = mip_msi_irq_set_state,
+ .irq_get_state = mip_msi_irq_get_state,
+ .flags = RT_PIC_F_IRQ_ROUTING,
+};
+
+static rt_err_t mip_msi_ofw_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id)
+{
+ rt_err_t err;
+ struct mip_msi *mip = rt_calloc(1, sizeof(*mip));
+
+ if (!mip)
+ {
+ return -RT_ENOMEM;
+ }
+
+ if (!rt_strcmp(id->compatible, "brcm,bcm2712-mip-intc"))
+ {
+ err = mip_msi_parse_intc_dt(mip, np);
+ }
+ else
+ {
+ err = mip_msi_parse_upstream_dt(mip, np);
+ }
+
+ if (err)
+ {
+ goto _fail;
+ }
+
+ /* SPI offset from MSI base */
+ mip->spi_base = mip->msi_base + 32;
+
+ mip->base = rt_ofw_iomap(np, 0);
+
+ if (!mip->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ mip->msi_map = rt_calloc(RT_BITS_TO_LONGS(mip->num_msis), sizeof(*mip->msi_map));
+
+ if (!mip->msi_map)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ /*
+ * Begin with all MSI-Xs masked in for the host, masked out for the VPU,
+ * and edge-triggered.
+ */
+ HWREG32(mip->base + MIP_INT_MASKL_HOST) = 0;
+ HWREG32(mip->base + MIP_INT_MASKH_HOST) = 0;
+ HWREG32(mip->base + MIP_INT_MASKL_VPU) = ~0;
+ HWREG32(mip->base + MIP_INT_MASKH_VPU) = ~0;
+ HWREG32(mip->base + MIP_INT_CFGL_HOST) = ~0;
+ HWREG32(mip->base + MIP_INT_CFGH_HOST) = ~0;
+
+ LOG_D("Found %d MSIx, starting at %d (offset %d)", mip->num_msis, mip->msi_base, mip->msi_offset);
+
+ rt_spin_lock_init(&mip->msi_map_lock);
+
+ mip->parent.priv_data = mip;
+ mip->parent.ops = &mip_msi_ops;
+
+ rt_pic_linear_irq(&mip->parent, mip->num_msis);
+ rt_pic_user_extends(&mip->parent);
+
+ rt_ofw_data(np) = &mip->parent;
+ rt_ofw_node_set_flag(np, RT_OFW_F_READLY);
+
+ return RT_EOK;
+
+_fail:
+ if (mip->base)
+ {
+ rt_iounmap(mip->base);
+ }
+
+ if (mip->msi_map)
+ {
+ rt_free(mip->msi_map);
+ }
+
+ rt_free(mip);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id mip_msi_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2712-mip-intc" },
+ { .compatible = "brcm,bcm2712-mip" },
+ { /* sentinel */ }
+};
+RT_PIC_OFW_DECLARE(mip_msi, mip_msi_ofw_ids, mip_msi_ofw_init);
diff --git a/bsp/raspberry-pi/dm/pic/pic-bcm2835.c b/bsp/raspberry-pi/dm/pic/pic-bcm2835.c
new file mode 100755
index 0000000000..2851b4ea04
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/pic-bcm2835.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-03-12 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pic.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+/* Put the bank and irq (32 bits) into the hwirq */
+#define MAKE_HWIRQ(b, n) ((b << 5) | (n))
+#define HWIRQ_BANK(i) (i >> 5)
+#define HWIRQ_BIT(i) RT_BIT(i & 0x1f)
+
+#define NR_IRQS_BANK0 8
+#define BANK0_HWIRQ_MASK 0xff
+/* Shortcuts can't be disabled so any unknown new ones need to be masked */
+#define SHORTCUT1_MASK 0x00007c00
+#define SHORTCUT2_MASK 0x001f8000
+#define SHORTCUT_SHIFT 10
+#define BANK1_HWIRQ RT_BIT(8)
+#define BANK2_HWIRQ RT_BIT(9)
+#define BANK0_VALID_MASK (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ | SHORTCUT1_MASK | SHORTCUT2_MASK)
+
+#define REG_FIQ_CONTROL 0x0c
+#define FIQ_CONTROL_ENABLE RT_BIT(7)
+
+#define NR_BANKS 3
+#define IRQS_PER_BANK 32
+
+struct bcm2835_arm_intc
+{
+ struct rt_pic parent;
+
+ void *base;
+ void *pending[NR_BANKS];
+ void *enable[NR_BANKS];
+ void *disable[NR_BANKS];
+};
+
+static struct bcm2835_arm_intc intc;
+
+static const int shortcuts[] =
+{
+ 7, 9, 10, 18, 19, /* Bank 1 */
+ 21, 22, 23, 24, 25, 30 /* Bank 2 */
+};
+
+/*
+ * Handle each interrupt across the entire interrupt controller. This reads the
+ * status register before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
+ */
+
+static rt_uint32_t bcm2835_arm_intc_translate_bank(int bank)
+{
+ rt_uint32_t status = HWREG32(intc.pending[bank]);
+
+ return MAKE_HWIRQ(bank, __rt_ffs(status) - 1);
+}
+
+static rt_uint32_t bcm2835_arm_intc_translate_shortcut(int bank, rt_uint32_t status)
+{
+ return MAKE_HWIRQ(bank, shortcuts[__rt_ffs(status >> SHORTCUT_SHIFT) - 1]);
+}
+
+static rt_uint32_t bcm2835_arm_intc_get_next_armctrl_hwirq(void)
+{
+ rt_uint32_t ret;
+ rt_uint32_t status = HWREG32(intc.pending[0]) & BANK0_VALID_MASK;
+
+ if (status == 0)
+ {
+ ret = ~0;
+ }
+ else if (status & BANK0_HWIRQ_MASK)
+ {
+ ret = MAKE_HWIRQ(0, __rt_ffs(status & BANK0_HWIRQ_MASK) - 1);
+ }
+ else if (status & SHORTCUT1_MASK)
+ {
+ ret = bcm2835_arm_intc_translate_shortcut(1, status & SHORTCUT1_MASK);
+ }
+ else if (status & SHORTCUT2_MASK)
+ {
+ ret = bcm2835_arm_intc_translate_shortcut(2, status & SHORTCUT2_MASK);
+ }
+ else if (status & BANK1_HWIRQ)
+ {
+ ret = bcm2835_arm_intc_translate_bank(1);
+ }
+ else if (status & BANK2_HWIRQ)
+ {
+ ret = bcm2835_arm_intc_translate_bank(2);
+ }
+ else
+ {
+ LOG_E("IRQ status panic = %d", status);
+ RT_ASSERT(0);
+ }
+
+ return ret;
+}
+
+static void bcm2835_arm_intc_mask_irq(struct rt_pic_irq *pirq)
+{
+ int hwirq = pirq->hwirq;
+
+ HWREG32(intc.disable[HWIRQ_BANK(hwirq)]) = HWIRQ_BIT(hwirq);
+}
+
+static void bcm2835_arm_intc_unmask_irq(struct rt_pic_irq *pirq)
+{
+ int hwirq = pirq->hwirq;
+
+ HWREG32(intc.enable[HWIRQ_BANK(hwirq)]) = HWIRQ_BIT(hwirq);
+}
+
+static int bcm2835_arm_intc_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
+{
+ struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
+
+ pirq->mode = mode;
+ RT_IRQ_AFFINITY_SET(pirq->affinity, rt_hw_cpu_id());
+
+ return rt_pic_config_irq(pic, hwirq, hwirq);
+}
+
+static rt_err_t bcm2835_arm_intc_irq_parse(struct rt_pic *pic,
+ struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
+{
+ rt_err_t err = RT_EOK;
+
+ if (args->args_count == 2 &&
+ args->args[0] < NR_BANKS &&
+ args->args[1] < IRQS_PER_BANK &&
+ (args->args[0] != 0 || args->args[1]))
+ {
+ out_pirq->hwirq = MAKE_HWIRQ(args->args[0], args->args[1]);
+ out_pirq->mode = RT_IRQ_MODE_EDGE_RISING;
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+const static struct rt_pic_ops bcm2835_arm_intc_ops =
+{
+ .name = "BCM2835-ARMCTRL-level",
+ .irq_mask = bcm2835_arm_intc_mask_irq,
+ .irq_unmask = bcm2835_arm_intc_unmask_irq,
+ .irq_map = bcm2835_arm_intc_irq_map,
+ .irq_parse = bcm2835_arm_intc_irq_parse,
+};
+
+static rt_bool_t bcm2835_arm_intc_handler(void *data)
+{
+ rt_uint32_t hwirq;
+ rt_bool_t res = RT_FALSE;
+
+ while ((hwirq = bcm2835_arm_intc_get_next_armctrl_hwirq()) != ~0)
+ {
+ struct rt_pic_irq *pirq = rt_pic_find_irq(&intc.parent, hwirq);
+
+ rt_pic_handle_isr(pirq);
+
+ res = RT_TRUE;
+ }
+
+ return res;
+}
+
+static rt_err_t bcm2835_arm_ofw_intc(struct rt_ofw_node *np, const struct rt_ofw_node_id *id)
+{
+ rt_err_t err = RT_EOK;
+
+ intc.base = rt_ofw_iomap(np, 0);
+
+ if (intc.base)
+ {
+ rt_uint32_t reg;
+
+ int reg_pending[] = { 0x00, 0x04, 0x08 };
+ int reg_enable[] = { 0x18, 0x10, 0x14 };
+ int reg_disable[] = { 0x24, 0x1c, 0x20 };
+
+ for (int i = 0; i < NR_BANKS; ++i)
+ {
+ intc.pending[i] = intc.base + reg_pending[i];
+ intc.enable[i] = intc.base + reg_enable[i];
+ intc.disable[i] = intc.base + reg_disable[i];
+
+ reg = HWREG32(intc.enable[i]);
+
+ if (reg)
+ {
+ HWREG32(intc.disable[i]) = reg;
+
+ LOG_E("Bootloader left irq enabled: bank = %d irq-bitmask = %08x", i, reg);
+ }
+ }
+
+ reg = HWREG32(intc.base + REG_FIQ_CONTROL);
+
+ if (reg & FIQ_CONTROL_ENABLE)
+ {
+ HWREG32(intc.base + REG_FIQ_CONTROL) = 0;
+
+ LOG_E("Bootloader left fiq enabled");
+ }
+
+ intc.parent.priv_data = &intc;
+ intc.parent.ops = &bcm2835_arm_intc_ops;
+
+ rt_ofw_data(np) = &intc.parent;
+
+ rt_pic_linear_irq(&intc.parent, MAKE_HWIRQ(NR_BANKS, 0));
+
+ rt_pic_add_traps(bcm2835_arm_intc_handler, &intc);
+ }
+ else
+ {
+ err = -RT_ERROR;
+ }
+
+ return err;
+}
+
+static const struct rt_ofw_node_id bcm2835_arm_intc_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-armctrl-ic", },
+ { .compatible = "brcm,bcm2836-armctrl-ic", },
+ { /* sentinel */ }
+};
+RT_PIC_OFW_DECLARE(bcm2835_arm_intc, bcm2835_arm_intc_ofw_ids, bcm2835_arm_ofw_intc);
diff --git a/bsp/raspberry-pi/dm/pic/pic-bcm2836.c b/bsp/raspberry-pi/dm/pic/pic-bcm2836.c
new file mode 100755
index 0000000000..d952076f23
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/pic-bcm2836.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pic.bcm2836"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+
+#define LOCAL_CONTROL 0x00
+#define LOCAL_PRESCALER 0x08
+
+/*
+ * The low 2 bits identify the CPU that the GPU IRQ goes to, and the next 2 bits
+ * identify the CPU that the GPU FIQ goes to.
+ */
+#define LOCAL_GPU_ROUTING 0x0c
+/* When setting bits 0-3, enables PMU interrupts on that CPU. */
+#define LOCAL_PM_ROUTING_SET 0x10
+/* When setting bits 0-3, disables PMU interrupts on that CPU. */
+#define LOCAL_PM_ROUTING_CLR 0x14
+/*
+ * The low 4 bits of this are the CPU's timer IRQ enables, and the next 4 bits
+ * are the CPU's timer FIQ enables (which override the IRQ bits).
+ */
+#define LOCAL_TIMER_INT_CONTROL0 0x40
+/*
+ * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and the next 4
+ * bits are the CPU's per-mailbox FIQ enables (which override the IRQ bits).
+ */
+#define LOCAL_MAILBOX_INT_CONTROL0 0x50
+/*
+ * The CPU's interrupt status register. Bits are defined by the LOCAL_IRQ_* bits
+ * below.
+ */
+#define LOCAL_IRQ_PENDING0 0x60
+/* Same status bits as above, but for FIQ. */
+#define LOCAL_FIQ_PENDING0 0x70
+/*
+ * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and these bits
+ * are organized by mailbox number and then CPU number. We use mailbox 0 for
+ * IPIs. The mailbox's interrupt is raised while any bit is set.
+ */
+#define LOCAL_MAILBOX0_SET0 0x80
+#define LOCAL_MAILBOX3_SET0 0x8c
+/* Mailbox write-to-clear bits. */
+#define LOCAL_MAILBOX0_CLR0 0xc0
+#define LOCAL_MAILBOX3_CLR0 0xcc
+
+#define LOCAL_IRQ_CNTPSIRQ 0
+#define LOCAL_IRQ_CNTPNSIRQ 1
+#define LOCAL_IRQ_CNTHPIRQ 2
+#define LOCAL_IRQ_CNTVIRQ 3
+#define LOCAL_IRQ_MAILBOX0 4
+#define LOCAL_IRQ_MAILBOX1 5
+#define LOCAL_IRQ_MAILBOX2 6
+#define LOCAL_IRQ_MAILBOX3 7
+#define LOCAL_IRQ_GPU_FAST 8
+#define LOCAL_IRQ_PMU_FAST 9
+#define LAST_IRQ LOCAL_IRQ_PMU_FAST
+
+struct bcm2836_arm_intc
+{
+ struct rt_pic parent;
+
+ void *base;
+};
+
+static struct bcm2836_arm_intc intc;
+
+static void bcm2836_arm_irqchip_mask_ipi(rt_uint32_t reg_offset, rt_uint32_t bit, int cpu)
+{
+ void *reg = intc.base + reg_offset + 4 * cpu;
+
+ HWREG32(reg) &= ~RT_BIT(bit);
+}
+
+static void bcm2836_arm_irqchip_unmask_ipi(rt_uint32_t reg_offset, rt_uint32_t bit, int cpu)
+{
+ void *reg = intc.base + reg_offset + 4 * cpu;
+
+ HWREG32(reg) |= RT_BIT(bit);
+}
+
+static void bcm2836_arm_irqchip_mask_timer_irq(int hwirq)
+{
+ bcm2836_arm_irqchip_mask_ipi(LOCAL_TIMER_INT_CONTROL0, hwirq - LOCAL_IRQ_CNTPSIRQ, rt_hw_cpu_id());
+}
+
+static void bcm2836_arm_irqchip_unmask_timer_irq(int hwirq)
+{
+ bcm2836_arm_irqchip_unmask_ipi(LOCAL_TIMER_INT_CONTROL0, hwirq - LOCAL_IRQ_CNTPSIRQ, rt_hw_cpu_id());
+}
+
+static void bcm2836_arm_irqchip_mask_gpu_irq(void)
+{
+}
+
+static void bcm2836_arm_irqchip_unmask_gpu_irq(void)
+{
+}
+
+static void bcm2836_arm_irqchip_mask_pmu_irq(void)
+{
+ HWREG32(intc.base + LOCAL_PM_ROUTING_CLR) = 1 << rt_hw_cpu_id();
+}
+
+static void bcm2836_arm_irqchip_unmask_pmu_irq(void)
+{
+ HWREG32(intc.base + LOCAL_PM_ROUTING_SET) = 1 << rt_hw_cpu_id();
+}
+
+static void bcm2836_arm_irqchip_irq_ops(int hwirq, rt_bool_t mask)
+{
+#define CALL_OPS(name, ...) \
+ if (mask) { \
+ bcm2836_arm_irqchip_mask_##name(__VA_ARGS__); \
+ } else { \
+ bcm2836_arm_irqchip_unmask_##name(__VA_ARGS__); \
+ }
+
+ switch (hwirq)
+ {
+ case LOCAL_IRQ_MAILBOX0:
+ case LOCAL_IRQ_MAILBOX1:
+ case LOCAL_IRQ_MAILBOX2:
+ case LOCAL_IRQ_MAILBOX3:
+ CALL_OPS(ipi, LOCAL_MAILBOX_INT_CONTROL0, 0, rt_hw_cpu_id());
+ break;
+ case LOCAL_IRQ_CNTPSIRQ:
+ case LOCAL_IRQ_CNTPNSIRQ:
+ case LOCAL_IRQ_CNTHPIRQ:
+ case LOCAL_IRQ_CNTVIRQ:
+ CALL_OPS(timer_irq, hwirq);
+ break;
+ case LOCAL_IRQ_GPU_FAST:
+ CALL_OPS(gpu_irq);
+ break;
+ case LOCAL_IRQ_PMU_FAST:
+ CALL_OPS(pmu_irq);
+ break;
+ default:
+ LOG_W("Unexpected hwirq = %d", hwirq);
+ break;
+ }
+#undef CALL_OPS
+}
+
+static void bcm2836_arm_l1_intc_irq_mask(struct rt_pic_irq *pirq)
+{
+ bcm2836_arm_irqchip_irq_ops(pirq->hwirq, RT_TRUE);
+}
+
+static void bcm2836_arm_l1_intc_irq_unmask(struct rt_pic_irq *pirq)
+{
+ bcm2836_arm_irqchip_irq_ops(pirq->hwirq, RT_FALSE);
+}
+
+static void bcm2836_arm_l1_intc_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask)
+{
+ int cpu, hwirq = pirq->hwirq;
+ void *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
+
+ /*
+ * Ensure that stores to normal memory are visible to the other CPUs before
+ * issuing the IPI.
+ */
+ rt_hw_wmb();
+
+ rt_bitmap_for_each_set_bit(cpumask, cpu, RT_CPUS_NR)
+ {
+ HWREG32(mailbox0_base + 16 * cpu) = RT_BIT(hwirq);
+ }
+}
+
+static int bcm2836_arm_l1_intc_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
+{
+ struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
+
+ pirq->mode = mode;
+
+ switch (hwirq)
+ {
+ case LOCAL_IRQ_CNTPSIRQ:
+ case LOCAL_IRQ_CNTPNSIRQ:
+ case LOCAL_IRQ_CNTHPIRQ:
+ case LOCAL_IRQ_CNTVIRQ:
+ for (int cpuid = 0; cpuid < RT_CPUS_NR; ++cpuid)
+ {
+ RT_IRQ_AFFINITY_SET(pirq->affinity, cpuid);
+ }
+ break;
+
+ default:
+ RT_IRQ_AFFINITY_SET(pirq->affinity, rt_hw_cpu_id());
+ break;
+ }
+
+ return rt_pic_config_irq(pic, hwirq, hwirq);
+}
+
+static rt_err_t bcm2836_arm_l1_intc_irq_parse(struct rt_pic *pic,
+ struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
+{
+ rt_err_t err = RT_EOK;
+
+ if (args->args_count == 2)
+ {
+ out_pirq->hwirq = args->args[0];
+ out_pirq->mode = args->args[1];
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+const static struct rt_pic_ops bcm2836_arm_l1_intc_ops =
+{
+ .name = "BCM2836-ARM-L1-INTC",
+ .irq_mask = bcm2836_arm_l1_intc_irq_mask,
+ .irq_unmask = bcm2836_arm_l1_intc_irq_unmask,
+ .irq_send_ipi = bcm2836_arm_l1_intc_irq_send_ipi,
+ .irq_map = bcm2836_arm_l1_intc_irq_map,
+ .irq_parse = bcm2836_arm_l1_intc_irq_parse,
+};
+
+static rt_bool_t bcm2836_arm_l1_intc_handler(void *data)
+{
+ rt_uint32_t hwirq;
+ rt_bool_t res = RT_FALSE;
+ int cpu_id = rt_hw_cpu_id();
+ rt_uint32_t status = HWREG32(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu_id);
+
+ if (!status)
+ {
+ status = HWREG32(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu_id);
+ }
+
+ if (status)
+ {
+ struct rt_pic_irq *pirq;
+
+ hwirq = __rt_ffs(status) - 1;
+
+ if (hwirq > LOCAL_IRQ_MAILBOX3 || hwirq < LOCAL_IRQ_MAILBOX0)
+ {
+ pirq = rt_pic_find_irq(&intc.parent, hwirq);
+ }
+ else
+ {
+ HWREG32(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * rt_hw_cpu_id()) = RT_BIT(hwirq);
+
+ pirq = rt_pic_find_ipi(&intc.parent, hwirq - LOCAL_IRQ_MAILBOX0);
+ }
+
+ rt_pic_handle_isr(pirq);
+
+ res = RT_TRUE;
+ }
+
+ return res;
+}
+
+/*
+ * The LOCAL_IRQ_CNT* timer firings are based off of the external oscillator
+ * with some scaling. The firmware sets up CNTFRQ to report 19.2Mhz, but
+ * doesn't set up the scaling registers.
+ */
+static void bcm2835_init_local_timer_frequency(void)
+{
+ /*
+ * Set the timer to source from the 19.2Mhz crystal clock (bit 8 unset), and
+ * only increment by 1 instead of 2 (bit 9 unset).
+ */
+ HWREG32(intc.base + LOCAL_CONTROL) = 0;
+
+ /* Set the timer prescaler to 1:1 (timer freq = input freq * 2**31 / prescaler) */
+ HWREG32(intc.base + LOCAL_PRESCALER) = 0x80000000;
+}
+
+static rt_err_t bcm2836_arm_l1_intc_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id)
+{
+ rt_err_t err = RT_EOK;
+
+ intc.base = rt_ofw_iomap(np, 0);
+
+ if (intc.base)
+ {
+ bcm2835_init_local_timer_frequency();
+
+ intc.parent.priv_data = &intc;
+ intc.parent.ops = &bcm2836_arm_l1_intc_ops;
+ rt_ofw_data(np) = &intc.parent;
+
+ rt_pic_linear_irq(&intc.parent, LAST_IRQ + 1);
+
+ for (int ipi = 0; ipi < RT_MAX_IPI; ++ipi)
+ {
+ struct rt_pic_irq *pirq;
+
+ if (LOCAL_IRQ_MAILBOX0 + ipi > LOCAL_IRQ_MAILBOX3)
+ {
+ RT_ASSERT(0);
+ break;
+ }
+
+ rt_pic_config_ipi(&intc.parent, ipi, LOCAL_IRQ_MAILBOX0 + ipi);
+ pirq = rt_pic_find_ipi(&intc.parent, ipi);
+ pirq->mode = RT_IRQ_MODE_EDGE_RISING;
+ }
+
+ rt_pic_add_traps(bcm2836_arm_l1_intc_handler, &intc);
+ }
+ else
+ {
+ err = -RT_ERROR;
+ }
+
+ return err;
+}
+
+static const struct rt_ofw_node_id bcm2836_arm_l1_intc_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2836-l1-intc" },
+ { /* sentinel */ }
+};
+RT_PIC_OFW_DECLARE(bcm2836_arm_l1_intc, bcm2836_arm_l1_intc_ofw_ids, bcm2836_arm_l1_intc_init);
diff --git a/bsp/raspberry-pi/dm/pic/pic-brcmstb-l2.c b/bsp/raspberry-pi/dm/pic/pic-brcmstb-l2.c
new file mode 100644
index 0000000000..ded70ef69e
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pic/pic-brcmstb-l2.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pic.brcmstb_l2"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+struct brcmstb_intc_init_params
+{
+ int cpu_status;
+ int cpu_clear;
+ int cpu_mask_status;
+ int cpu_mask_set;
+ int cpu_mask_clear;
+};
+
+struct brcmstb_l2_intc
+{
+ struct rt_pic parent;
+
+ int irq;
+ void *regs;
+ rt_bool_t can_wake;
+ struct rt_ofw_node *np;
+
+ const struct brcmstb_intc_init_params *params;
+};
+
+#define raw_to_brcmstb_l2_intc(raw) rt_container_of(raw, struct brcmstb_l2_intc, parent)
+
+/* Register offsets in the L2 latched interrupt controller */
+static const struct brcmstb_intc_init_params l2_edge_intc =
+{
+ .cpu_status = 0x00,
+ .cpu_clear = 0x08,
+ .cpu_mask_status = 0x0c,
+ .cpu_mask_set = 0x10,
+ .cpu_mask_clear = 0x14
+};
+
+/* Register offsets in the L2 level interrupt controller */
+static const struct brcmstb_intc_init_params l2_lvl_intc =
+{
+ .cpu_status = 0x00,
+ .cpu_clear = -1, /* Register not present */
+ .cpu_mask_status = 0x04,
+ .cpu_mask_set = 0x08,
+ .cpu_mask_clear = 0x0c
+};
+
+/* Register offsets in the 2711 L2 level interrupt controller */
+static const struct brcmstb_intc_init_params l2_2711_lvl_intc =
+{
+ .cpu_status = 0x00,
+ .cpu_clear = 0x08,
+ .cpu_mask_status = 0x0c,
+ .cpu_mask_set = 0x10,
+ .cpu_mask_clear = 0x14
+};
+
+static void brcmstb_l2_intc_isr(int irqno, void *params);
+
+static rt_err_t brcmstb_l2_intc_irq_init(struct rt_pic *pic)
+{
+ struct brcmstb_l2_intc *bl2 = raw_to_brcmstb_l2_intc(pic);
+
+ bl2->irq = rt_ofw_get_irq(bl2->np, 0);
+
+ if (bl2->irq < 0)
+ {
+ LOG_E("Failed to find parent interrupt");
+ return -RT_EINVAL;
+ }
+
+ rt_hw_interrupt_install(bl2->irq, brcmstb_l2_intc_isr, bl2, "BRCMSTB-L2-INTC");
+ rt_hw_interrupt_umask(bl2->irq);
+
+ return RT_EOK;
+}
+
+static void brcmstb_l2_intc_irq_ack(struct rt_pic_irq *pirq)
+{
+ struct brcmstb_l2_intc *bl2 = raw_to_brcmstb_l2_intc(pirq->pic);
+
+ if (bl2->params->cpu_clear >= 0)
+ {
+ HWREG32(bl2->regs + bl2->params->cpu_clear) = RT_BIT(pirq->hwirq);
+ }
+}
+
+static void brcmstb_l2_intc_irq_mask(struct rt_pic_irq *pirq)
+{
+ struct brcmstb_l2_intc *bl2 = raw_to_brcmstb_l2_intc(pirq->pic);
+
+ HWREG32(bl2->regs + bl2->params->cpu_mask_set) = RT_BIT(pirq->hwirq);
+}
+
+static void brcmstb_l2_intc_irq_unmask(struct rt_pic_irq *pirq)
+{
+ struct brcmstb_l2_intc *bl2 = raw_to_brcmstb_l2_intc(pirq->pic);
+
+ HWREG32(bl2->regs + bl2->params->cpu_mask_clear) = RT_BIT(pirq->hwirq);
+}
+
+static int brcmstb_l2_intc_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
+{
+ struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
+
+ RT_IRQ_AFFINITY_SET(pirq->affinity, rt_hw_cpu_id());
+ pirq->mode = mode;
+
+ return rt_pic_config_irq(pic, hwirq, hwirq);
+}
+
+static rt_err_t brcmstb_l2_intc_irq_parse(struct rt_pic *pic,
+ struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
+{
+ rt_err_t err = RT_EOK;
+ struct brcmstb_l2_intc *bl2 = rt_container_of(pic, struct brcmstb_l2_intc, parent);
+
+ if (args->args_count == 1)
+ {
+ out_pirq->hwirq = args->args[0];
+
+ if (bl2->params == &l2_edge_intc)
+ {
+ out_pirq->mode = RT_IRQ_MODE_EDGE_RISING;
+ }
+ else if (bl2->params == &l2_lvl_intc || bl2->params == &l2_2711_lvl_intc)
+ {
+ out_pirq->mode = RT_IRQ_MODE_LEVEL_HIGH;
+ }
+ }
+ else
+ {
+ err = -RT_EINVAL;
+ }
+
+ return err;
+}
+
+const static struct rt_pic_ops brcmstb_l2_intc_ops =
+{
+ .name = "BRCMSTB-L2-INTC",
+ .irq_init = brcmstb_l2_intc_irq_init,
+ .irq_ack = brcmstb_l2_intc_irq_ack,
+ .irq_mask = brcmstb_l2_intc_irq_mask,
+ .irq_unmask = brcmstb_l2_intc_irq_unmask,
+ .irq_map = brcmstb_l2_intc_irq_map,
+ .irq_parse = brcmstb_l2_intc_irq_parse,
+};
+
+static void brcmstb_l2_intc_isr(int irqno, void *params)
+{
+ struct rt_pic_irq *pirq;
+ rt_uint32_t hwirq, raw_status, mask_status, status;
+ struct brcmstb_l2_intc *bl2 = params;
+
+ RT_UNUSED(irqno);
+
+ raw_status = HWREG32(bl2->regs + bl2->params->cpu_status);
+ mask_status = HWREG32(bl2->regs + bl2->params->cpu_mask_status);
+ status = raw_status & ~mask_status;
+
+ if (!status)
+ {
+ return;
+ }
+
+ do {
+ hwirq = __rt_ffs(status) - 1;
+ status &= ~RT_BIT(hwirq);
+
+ pirq = rt_pic_find_irq(&bl2->parent, hwirq);
+ if (!pirq)
+ {
+ if (bl2->params->cpu_clear >= 0)
+ {
+ HWREG32(bl2->regs + bl2->params->cpu_clear) = RT_BIT(hwirq);
+ }
+ continue;
+ }
+
+ brcmstb_l2_intc_irq_ack(pirq);
+
+ rt_pic_handle_isr(pirq);
+ } while (status);
+}
+
+static rt_err_t brcmstb_l2_intc_ofw_intc(struct rt_ofw_node *np, const struct rt_ofw_node_id *id)
+{
+ rt_err_t err;
+ const struct brcmstb_intc_init_params *params;
+ struct brcmstb_l2_intc *bl2 = rt_calloc(1, sizeof(*bl2));
+
+ if (!bl2)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bl2->regs = rt_ofw_iomap(np, 0);
+
+ if (!bl2->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ bl2->params = params = id->data;
+ bl2->irq = -RT_EEMPTY;
+
+ /* Disable all interrupts by default */
+ HWREG32(bl2->regs + params->cpu_mask_set) = 0xffffffff;
+
+ /* Wakeup interrupts may be retained from S5 (cold boot) */
+ bl2->can_wake = rt_ofw_prop_read_bool(np, "brcm,irq-can-wake");
+ if (!bl2->can_wake && params->cpu_clear >= 0)
+ {
+ HWREG32(bl2->regs + params->cpu_clear) = 0xffffffff;
+ }
+
+ bl2->parent.priv_data = bl2;
+ bl2->parent.ops = &brcmstb_l2_intc_ops;
+
+ bl2->np = np;
+ rt_ofw_data(np) = &bl2->parent;
+
+ rt_pic_linear_irq(&bl2->parent, 32);
+
+ return RT_EOK;
+
+_fail:
+ if (bl2->regs)
+ {
+ rt_iounmap(bl2->regs);
+ }
+
+ rt_free(bl2);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id brcmstb_l2_intc_ofw_ids[] =
+{
+ { .compatible = "brcm,l2-intc", .data = &l2_edge_intc },
+ { .compatible = "brcm,hif-spi-l2-intc", .data = &l2_edge_intc },
+ { .compatible = "brcm,upg-aux-aon-l2-intc", .data = &l2_edge_intc },
+ { .compatible = "brcm,bcm7271-l2-intc", .data = &l2_lvl_intc },
+ { .compatible = "brcm,bcm2711-l2-intc", .data = &l2_2711_lvl_intc },
+ { /* sentinel */ }
+};
+
+rt_err_t brcmstb_l2_intc_request_node(struct rt_ofw_node *np)
+{
+ rt_err_t err;
+ struct rt_pic *pic;
+ struct brcmstb_l2_intc *bl2;
+ struct rt_ofw_prop *compat_prop;
+ struct rt_ofw_node_id *id;
+
+ if (!np || !rt_ofw_node_is_available(np))
+ {
+ return -RT_EINVAL;
+ }
+
+ pic = rt_pic_dynamic_cast(rt_ofw_data(np));
+ if (pic)
+ {
+ bl2 = raw_to_brcmstb_l2_intc(pic);
+ if (bl2->irq < 0)
+ {
+ err = brcmstb_l2_intc_irq_init(pic);
+ if (!err)
+ {
+ rt_ofw_node_set_flag(np, RT_OFW_F_READLY);
+ }
+
+ return err;
+ }
+
+ return RT_EOK;
+ }
+
+ compat_prop = rt_ofw_get_prop(np, "compatible", RT_NULL);
+ id = rt_ofw_prop_match(compat_prop, brcmstb_l2_intc_ofw_ids);
+ if (!id)
+ {
+ return -RT_ENOSYS;
+ }
+
+ err = brcmstb_l2_intc_ofw_intc(np, id);
+ if (err)
+ {
+ return err;
+ }
+
+ pic = rt_pic_dynamic_cast(rt_ofw_data(np));
+ if (!pic)
+ {
+ return -RT_EIO;
+ }
+
+ err = brcmstb_l2_intc_irq_init(pic);
+ if (err)
+ {
+ return err;
+ }
+ rt_ofw_node_set_flag(np, RT_OFW_F_READLY);
+
+ return RT_EOK;
+}
+
+RT_PIC_OFW_DECLARE(brcmstb_l2_intc, brcmstb_l2_intc_ofw_ids, brcmstb_l2_intc_ofw_intc);
diff --git a/bsp/raspberry-pi/dm/pin/Kconfig b/bsp/raspberry-pi/dm/pin/Kconfig
new file mode 100755
index 0000000000..016fd764da
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pin/Kconfig
@@ -0,0 +1,15 @@
+config RT_PIN_BCM_VIRT
+ bool "Broadcom Virt GPIO support"
+ depends on RT_USING_PIN
+ default n
+
+config RT_PIN_BRCMSTB
+ bool "BRCMSTB GPIO support"
+ depends on RT_USING_PIN
+ default n
+
+config RT_PIN_RASPBERRYPI_EXP
+ bool "Raspberry Pi 3 GPIO Expander"
+ depends on RT_USING_PIN
+ depends on RT_FIRMWARE_RASPBERRYPI
+ default n
diff --git a/bsp/raspberry-pi/dm/pin/SConscript b/bsp/raspberry-pi/dm/pin/SConscript
new file mode 100755
index 0000000000..4f39edb52d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pin/SConscript
@@ -0,0 +1,19 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include', cwd + '/../../../../components/drivers/pin']
+
+if GetDepend(['RT_PIN_BCM_VIRT']):
+ src += ['pin-bcm-virt.c']
+
+if GetDepend(['RT_PIN_BRCMSTB']):
+ src += ['pin-brcmstb.c']
+
+if GetDepend(['RT_PIN_RASPBERRYPI_EXP']):
+ src += ['pin-raspberrypi-exp.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pin/pin-bcm-virt.c b/bsp/raspberry-pi/dm/pin/pin-bcm-virt.c
new file mode 100755
index 0000000000..69085138d2
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pin/pin-bcm-virt.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <firmware-raspberrypi.h>
+
+#include "dev_pin_dm.h"
+
+#define NUM_GPIO 2
+
+struct brcmvirt_gpio
+{
+ struct rt_device_pin parent;
+ rt_uint32_t *ts_base;
+
+ rt_uint32_t enables_disables[NUM_GPIO];
+ rt_ubase_t bus_addr;
+};
+
+#define raw_to_brcmvirt_gpio(raw) rt_container_of(raw, struct brcmvirt_gpio, parent)
+
+static void brcmvirt_gpio_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+}
+
+static void brcmvirt_gpio_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
+{
+ rt_bool_t lit;
+ rt_uint16_t enables, disables;
+ struct brcmvirt_gpio *gpio = raw_to_brcmvirt_gpio(device);
+
+ enables = gpio->enables_disables[pin] >> 16;
+ disables = gpio->enables_disables[pin] >> 0;
+ lit = (rt_int16_t)(enables - disables) > 0;
+
+ if ((value && lit) || (!value && !lit))
+ {
+ return;
+ }
+
+ if (value)
+ {
+ enables++;
+ }
+ else
+ {
+ disables++;
+ }
+
+ gpio->enables_disables[pin] = (enables << 16) | (disables << 0);
+ HWREG32(gpio->ts_base + pin) = gpio->enables_disables[pin];
+}
+
+static rt_ssize_t brcmvirt_gpio_read(struct rt_device *device, rt_base_t pin)
+{
+ rt_uint32_t value;
+ struct brcmvirt_gpio *gpio = raw_to_brcmvirt_gpio(device);
+
+ value = HWREG32(gpio->ts_base + pin);
+
+ return (rt_int16_t)((value >> 16) - value) > 0;
+}
+
+static const struct rt_pin_ops brcmvirt_gpio_ops =
+{
+ .pin_mode = brcmvirt_gpio_mode,
+ .pin_write = brcmvirt_gpio_write,
+ .pin_read = brcmvirt_gpio_read,
+};
+
+static rt_err_t brcmvirt_gpio_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ void *ts_base;
+ rt_uint32_t virtbuf;
+ struct rpi_firmware *rpi_fw = RT_NULL;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct brcmvirt_gpio *gpio = rt_calloc(1, sizeof(*gpio));
+
+ if (!gpio)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ ts_base = rt_dma_alloc_coherent(dev, ARCH_PAGE_SIZE, &gpio->bus_addr);
+
+ if (!ts_base)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ virtbuf = (rt_uint32_t)gpio->bus_addr;
+ err = rpi_firmware_property(rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF, &gpio->bus_addr, sizeof(virtbuf));
+
+ if (err)
+ {
+ goto _fail;
+ }
+
+ err = rpi_firmware_property(rpi_fw,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, &virtbuf, sizeof(virtbuf));
+
+ if (err)
+ {
+ goto _fail;
+ }
+
+ virtbuf &= ~0xc0000000;
+ gpio->ts_base = rt_ioremap((void *)(rt_ubase_t)virtbuf, ARCH_PAGE_SIZE);
+
+ if (!gpio->ts_base)
+ {
+ goto _fail;
+ }
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, &gpio->parent);
+
+ gpio->parent.ops = &brcmvirt_gpio_ops;
+ pin_api_init(&gpio->parent, NUM_GPIO);
+
+ return RT_EOK;
+
+_fail:
+ if (gpio->bus_addr)
+ {
+ rt_dma_free_coherent(dev, ARCH_PAGE_SIZE, ts_base, gpio->bus_addr);
+ }
+
+ if (rpi_fw)
+ {
+ rpi_firmware_put(rpi_fw);
+ }
+
+ rt_free(gpio);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id brcmvirt_gpio_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-virtgpio" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmvirt_gpio_driver =
+{
+ .name = "brcmvirt-gpio",
+ .ids = brcmvirt_gpio_ofw_ids,
+
+ .probe = brcmvirt_gpio_probe,
+};
+
+static int brcmvirt_gpio_drv_register(void)
+{
+ rt_platform_driver_register(&brcmvirt_gpio_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(brcmvirt_gpio_drv_register);
diff --git a/bsp/raspberry-pi/dm/pin/pin-brcmstb.c b/bsp/raspberry-pi/dm/pin/pin-brcmstb.c
new file mode 100644
index 0000000000..59a56f3483
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pin/pin-brcmstb.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pin.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <dev_pin_dm.h>
+#include <drivers/ofw_irq.h>
+
+enum gio_reg_index
+{
+ GIO_REG_ODEN = 0,
+ GIO_REG_DATA,
+ GIO_REG_IODIR,
+ GIO_REG_EC,
+ GIO_REG_EI,
+ GIO_REG_MASK,
+ GIO_REG_LEVEL,
+ GIO_REG_STAT,
+ NUMBER_OF_GIO_REGISTERS
+};
+
+#define MAX_GPIO_PER_BANK 32
+#define brcmstb_gpio_bit(pin) RT_BIT((pin) % MAX_GPIO_PER_BANK)
+
+struct brcmstb_gpio;
+
+struct brcmstb_gpio_bank
+{
+ int id;
+ struct brcmstb_gpio *gpio;
+
+ rt_uint32_t width;
+};
+
+struct brcmstb_gpio
+{
+ struct rt_device_pin parent;
+
+ void *base;
+ int irq;
+
+ struct rt_spinlock lock;
+
+ rt_uint32_t num_banks;
+ struct brcmstb_gpio_bank *banks;
+};
+
+extern rt_err_t brcmstb_l2_intc_request_node(struct rt_ofw_node *np);
+
+rt_inline struct brcmstb_gpio_bank *raw_to_brcmstb_gpio_bank(struct rt_device *raw, rt_ubase_t pin)
+{
+ struct brcmstb_gpio *gpio = rt_container_of(raw, struct brcmstb_gpio, parent);
+ rt_ubase_t bank_id = pin / MAX_GPIO_PER_BANK;
+
+ if (bank_id >= gpio->num_banks)
+ {
+ return RT_NULL;
+ }
+
+ return &gpio->banks[bank_id];
+}
+
+rt_inline rt_bool_t brcmstb_gpio_bank_is_valid(struct brcmstb_gpio_bank *bank, rt_base_t pin)
+{
+ return bank && bank->width && (pin % MAX_GPIO_PER_BANK) < bank->width;
+}
+
+rt_inline rt_uint32_t brcmstb_gpio_valid_mask(struct brcmstb_gpio_bank *bank)
+{
+ if (bank->width >= MAX_GPIO_PER_BANK)
+ {
+ return 0xffffffffU;
+ }
+
+ return RT_BIT(bank->width) - 1;
+}
+
+rt_inline rt_uint32_t brcmstb_gpio_offset(struct brcmstb_gpio_bank *bank, rt_uint32_t reg)
+{
+ return bank->id * NUMBER_OF_GIO_REGISTERS * sizeof(rt_uint32_t) + reg * sizeof(rt_uint32_t);
+}
+
+rt_inline rt_uint32_t brcmstb_gpio_readl(struct brcmstb_gpio_bank *bank, rt_uint32_t reg)
+{
+ return HWREG32(bank->gpio->base + brcmstb_gpio_offset(bank, reg));
+}
+
+rt_inline void brcmstb_gpio_writel(struct brcmstb_gpio_bank *bank, rt_uint32_t reg, rt_uint32_t value)
+{
+ HWREG32(bank->gpio->base + brcmstb_gpio_offset(bank, reg)) = value;
+}
+
+static void brcmstb_gpio_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ rt_ubase_t level;
+ rt_uint32_t oden, iodir, bit = brcmstb_gpio_bit(pin);
+ struct brcmstb_gpio_bank *bank = raw_to_brcmstb_gpio_bank(device, pin);
+
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return;
+ }
+
+ level = rt_spin_lock_irqsave(&bank->gpio->lock);
+
+ oden = brcmstb_gpio_readl(bank, GIO_REG_ODEN);
+ iodir = brcmstb_gpio_readl(bank, GIO_REG_IODIR);
+
+ switch (mode)
+ {
+ case PIN_MODE_OUTPUT:
+ brcmstb_gpio_writel(bank, GIO_REG_ODEN, oden & ~bit);
+ brcmstb_gpio_writel(bank, GIO_REG_IODIR, iodir & ~bit);
+ break;
+
+ case PIN_MODE_OUTPUT_OD:
+ brcmstb_gpio_writel(bank, GIO_REG_ODEN, oden | bit);
+ brcmstb_gpio_writel(bank, GIO_REG_IODIR, iodir & ~bit);
+ break;
+
+ case PIN_MODE_INPUT:
+ case PIN_MODE_INPUT_PULLUP:
+ case PIN_MODE_INPUT_PULLDOWN:
+ brcmstb_gpio_writel(bank, GIO_REG_IODIR, iodir | bit);
+ break;
+
+ default:
+ break;
+ }
+
+ rt_spin_unlock_irqrestore(&bank->gpio->lock, level);
+}
+
+static void brcmstb_gpio_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
+{
+ rt_ubase_t level;
+ rt_uint32_t data, bit = brcmstb_gpio_bit(pin);
+ struct brcmstb_gpio_bank *bank = raw_to_brcmstb_gpio_bank(device, pin);
+
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return;
+ }
+
+ level = rt_spin_lock_irqsave(&bank->gpio->lock);
+
+ data = brcmstb_gpio_readl(bank, GIO_REG_DATA);
+ if (value)
+ {
+ data |= bit;
+ }
+ else
+ {
+ data &= ~bit;
+ }
+ brcmstb_gpio_writel(bank, GIO_REG_DATA, data);
+
+ rt_spin_unlock_irqrestore(&bank->gpio->lock, level);
+}
+
+static rt_ssize_t brcmstb_gpio_read(struct rt_device *device, rt_base_t pin)
+{
+ struct brcmstb_gpio_bank *bank = raw_to_brcmstb_gpio_bank(device, pin);
+
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return 0;
+ }
+
+ return !!(brcmstb_gpio_readl(bank, GIO_REG_DATA) & brcmstb_gpio_bit(pin));
+}
+
+static rt_err_t brcmstb_gpio_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
+{
+ rt_ubase_t level;
+ rt_uint32_t imask, mask = brcmstb_gpio_bit(pin);
+ struct brcmstb_gpio_bank *bank = raw_to_brcmstb_gpio_bank(device, pin);
+
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return -RT_EINVAL;
+ }
+
+ level = rt_spin_lock_irqsave(&bank->gpio->lock);
+
+ imask = brcmstb_gpio_readl(bank, GIO_REG_MASK);
+ if (enabled)
+ {
+ imask |= mask;
+ }
+ else
+ {
+ imask &= ~mask;
+ }
+ brcmstb_gpio_writel(bank, GIO_REG_MASK, imask);
+
+ rt_spin_unlock_irqrestore(&bank->gpio->lock, level);
+
+ return RT_EOK;
+}
+
+static rt_err_t brcmstb_gpio_irq_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ rt_ubase_t level;
+ rt_uint32_t mask = brcmstb_gpio_bit(pin);
+ rt_uint32_t int_level, ilevel;
+ rt_uint32_t edge_config, iedge_config;
+ rt_uint32_t edge_insensitive, iedge_insensitive;
+ struct brcmstb_gpio_bank *bank = raw_to_brcmstb_gpio_bank(device, pin);
+
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return -RT_EINVAL;
+ }
+
+ switch (mode)
+ {
+ case PIN_IRQ_MODE_LOW_LEVEL:
+ int_level = mask;
+ edge_config = 0;
+ edge_insensitive = 0;
+ break;
+
+ case PIN_IRQ_MODE_HIGH_LEVEL:
+ int_level = mask;
+ edge_config = mask;
+ edge_insensitive = 0;
+ break;
+
+ case PIN_IRQ_MODE_FALLING:
+ int_level = 0;
+ edge_config = 0;
+ edge_insensitive = 0;
+ break;
+
+ case PIN_IRQ_MODE_RISING:
+ int_level = 0;
+ edge_config = mask;
+ edge_insensitive = 0;
+ break;
+
+ case PIN_IRQ_MODE_RISING_FALLING:
+ int_level = 0;
+ edge_config = 0;
+ edge_insensitive = mask;
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+
+ level = rt_spin_lock_irqsave(&bank->gpio->lock);
+
+ iedge_config = brcmstb_gpio_readl(bank, GIO_REG_EC) & ~mask;
+ iedge_insensitive = brcmstb_gpio_readl(bank, GIO_REG_EI) & ~mask;
+ ilevel = brcmstb_gpio_readl(bank, GIO_REG_LEVEL) & ~mask;
+
+ brcmstb_gpio_writel(bank, GIO_REG_EC, iedge_config | edge_config);
+ brcmstb_gpio_writel(bank, GIO_REG_EI, iedge_insensitive | edge_insensitive);
+ brcmstb_gpio_writel(bank, GIO_REG_LEVEL, ilevel | int_level);
+
+ rt_spin_unlock_irqrestore(&bank->gpio->lock, level);
+
+ return RT_EOK;
+}
+
+static rt_err_t brcmstb_gpio_attach_irq(struct rt_device *device, rt_base_t pin,
+ rt_uint8_t mode, void (*hdr)(void *args), void *args)
+{
+ rt_err_t err;
+ struct brcmstb_gpio *gpio = rt_container_of(device, struct brcmstb_gpio, parent);
+ struct rt_pin_irq_hdr *legacy_isr;
+
+ if (!brcmstb_gpio_bank_is_valid(raw_to_brcmstb_gpio_bank(device, pin), pin))
+ {
+ return -RT_EINVAL;
+ }
+
+ if (!gpio->parent.legacy_isr)
+ {
+ return -RT_ENOSYS;
+ }
+
+ err = brcmstb_gpio_irq_mode(device, pin, mode);
+ if (err)
+ {
+ return err;
+ }
+
+ legacy_isr = &gpio->parent.legacy_isr[pin];
+ legacy_isr->pin = pin;
+ legacy_isr->mode = mode;
+ legacy_isr->hdr = hdr;
+ legacy_isr->args = args;
+
+ return RT_EOK;
+}
+
+static rt_ssize_t brcmstb_gpio_parse(struct rt_device *device, struct rt_ofw_cell_args *args, rt_uint32_t *flags)
+{
+ struct brcmstb_gpio_bank *bank;
+ rt_base_t pin;
+
+ if (!args || args->args_count < 2)
+ {
+ return -RT_EINVAL;
+ }
+
+ pin = args->args[0];
+ bank = raw_to_brcmstb_gpio_bank(device, pin);
+ if (!brcmstb_gpio_bank_is_valid(bank, pin))
+ {
+ return -RT_EINVAL;
+ }
+
+ if (flags)
+ {
+ *flags = args->args[1];
+ }
+
+ return pin;
+}
+
+static const struct rt_pin_ops brcmstb_gpio_ops =
+{
+ .pin_mode = brcmstb_gpio_mode,
+ .pin_write = brcmstb_gpio_write,
+ .pin_read = brcmstb_gpio_read,
+ .pin_attach_irq = brcmstb_gpio_attach_irq,
+ .pin_irq_enable = brcmstb_gpio_irq_enable,
+ .pin_irq_mode = brcmstb_gpio_irq_mode,
+ .pin_parse = brcmstb_gpio_parse,
+};
+
+static void brcmstb_gpio_isr(int irqno, void *param)
+{
+ rt_ubase_t level;
+ rt_uint32_t mask, status;
+ struct brcmstb_gpio *gpio = param;
+
+ RT_UNUSED(irqno);
+
+ for (int i = 0; i < gpio->num_banks; ++i)
+ {
+ struct brcmstb_gpio_bank *bank = &gpio->banks[i];
+
+ while (RT_TRUE)
+ {
+ level = rt_spin_lock_irqsave(&gpio->lock);
+ status = brcmstb_gpio_readl(bank, GIO_REG_STAT);
+ status &= brcmstb_gpio_readl(bank, GIO_REG_MASK);
+ status &= brcmstb_gpio_valid_mask(bank);
+ rt_spin_unlock_irqrestore(&gpio->lock, level);
+
+ if (!status)
+ {
+ break;
+ }
+
+ for (rt_ubase_t pin = 0; pin < bank->width; ++pin)
+ {
+ mask = RT_BIT(pin);
+
+ if (mask & status)
+ {
+ brcmstb_gpio_writel(bank, GIO_REG_STAT, mask);
+ pin_pic_handle_isr(&gpio->parent, bank->id * MAX_GPIO_PER_BANK + pin);
+ }
+ }
+ }
+ }
+}
+
+static void brcmstb_gpio_apply_hogs(struct brcmstb_gpio *gpio)
+{
+ struct rt_device *dev = &gpio->parent.parent;
+ struct rt_ofw_node *child;
+
+ rt_ofw_foreach_child_node(dev->ofw_node, child)
+ {
+ rt_uint32_t cells[2];
+ rt_ssize_t nr;
+ struct brcmstb_gpio_bank *bank;
+
+ if (!rt_ofw_get_prop(child, "gpio-hog", RT_NULL))
+ {
+ continue;
+ }
+
+ nr = rt_ofw_prop_read_u32_array_index(child, "gpios", 0, 2, cells);
+ if (nr < 2)
+ {
+ continue;
+ }
+
+ bank = raw_to_brcmstb_gpio_bank(dev, cells[0]);
+ if (!brcmstb_gpio_bank_is_valid(bank, cells[0]))
+ {
+ continue;
+ }
+
+ if (rt_ofw_get_prop(child, "input", RT_NULL))
+ {
+ brcmstb_gpio_mode(dev, cells[0], PIN_MODE_INPUT);
+ }
+ else if (rt_ofw_get_prop(child, "output-high", RT_NULL))
+ {
+ brcmstb_gpio_write(dev, cells[0], 1);
+ brcmstb_gpio_mode(dev, cells[0], PIN_MODE_OUTPUT);
+ }
+ else if (rt_ofw_get_prop(child, "output-low", RT_NULL))
+ {
+ brcmstb_gpio_write(dev, cells[0], 0);
+ brcmstb_gpio_mode(dev, cells[0], PIN_MODE_OUTPUT);
+ }
+ }
+}
+
+static rt_err_t brcmstb_gpio_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = -RT_EINVAL;
+ const fdt32_t *cell;
+ rt_uint32_t num_banks, value;
+ struct rt_ofw_prop *prop;
+ struct rt_device *dev = &pdev->parent;
+ struct brcmstb_gpio_bank *bank = RT_NULL;
+ struct brcmstb_gpio *gpio = rt_calloc(1, sizeof(*gpio));
+
+ if (!gpio)
+ {
+ return -RT_ENOMEM;
+ }
+
+ gpio->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!gpio->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if (dev->ofw_node)
+ {
+ struct rt_ofw_node *irq_parent;
+
+ irq_parent = rt_ofw_find_irq_parent(dev->ofw_node, RT_NULL);
+ if (irq_parent)
+ {
+ brcmstb_l2_intc_request_node(irq_parent);
+ rt_ofw_node_put(irq_parent);
+ }
+ }
+
+ gpio->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (gpio->irq < 0 && gpio->irq != -RT_EEMPTY && gpio->irq != -RT_EIO)
+ {
+ err = gpio->irq;
+ goto _fail;
+ }
+
+ num_banks = 0;
+ rt_ofw_foreach_prop_u32(dev->ofw_node, "brcm,gpio-bank-widths", prop, cell, value)
+ {
+ struct brcmstb_gpio_bank *new_bank;
+
+ if (!(new_bank = rt_realloc(bank, sizeof(*bank) * (num_banks + 1))))
+ {
+ LOG_E("No memory for bank(%u)", num_banks + 1);
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ bank = new_bank;
+ new_bank += num_banks;
+
+ rt_memset(new_bank, 0, sizeof(*new_bank));
+ new_bank->id = num_banks;
+ new_bank->gpio = gpio;
+
+ if (value > MAX_GPIO_PER_BANK)
+ {
+ LOG_E("Invalid bank width %u", value);
+ goto _fail;
+ }
+
+ new_bank->width = value;
+ ++num_banks;
+ }
+
+ if (!num_banks)
+ {
+ LOG_E("No valid gpio banks described");
+ goto _fail;
+ }
+
+ gpio->num_banks = num_banks;
+ gpio->banks = bank;
+ rt_spin_lock_init(&gpio->lock);
+
+ gpio->parent.ops = &brcmstb_gpio_ops;
+ pin_api_init(&gpio->parent, MAX_GPIO_PER_BANK * gpio->num_banks);
+
+ if (gpio->irq >= 0)
+ {
+ for (rt_ubase_t i = 0; i < gpio->num_banks; ++i)
+ {
+ brcmstb_gpio_writel(&gpio->banks[i], GIO_REG_MASK, 0);
+ }
+
+ pin_pic_init(&gpio->parent, gpio->irq);
+ rt_hw_interrupt_install(gpio->irq, brcmstb_gpio_isr, gpio, "brcmstb-gpio");
+ rt_hw_interrupt_umask(gpio->irq);
+ }
+
+ rt_ofw_data(dev->ofw_node) = &gpio->parent;
+
+ brcmstb_gpio_apply_hogs(gpio);
+
+ return RT_EOK;
+
+_fail:
+ if (bank)
+ {
+ rt_free(bank);
+ }
+
+ if (gpio->base)
+ {
+ rt_iounmap(gpio->base);
+ }
+
+ rt_free(gpio);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id brcmstb_gpio_ofw_ids[] =
+{
+ { .compatible = "brcm,brcmstb-gpio" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmstb_gpio_driver =
+{
+ .name = "brcmstb-gpio",
+ .ids = brcmstb_gpio_ofw_ids,
+
+ .probe = brcmstb_gpio_probe,
+};
+
+static int brcmstb_gpio_register(void)
+{
+ rt_platform_driver_register(&brcmstb_gpio_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(brcmstb_gpio_register);
diff --git a/bsp/raspberry-pi/dm/pin/pin-raspberrypi-exp.c b/bsp/raspberry-pi/dm/pin/pin-raspberrypi-exp.c
new file mode 100755
index 0000000000..13e1b4e881
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pin/pin-raspberrypi-exp.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pin.raspberrypi-exp"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <dev_pin_dm.h>
+#include <firmware-raspberrypi.h>
+
+#define RPI_EXP_GPIO_BASE 128
+
+#define RPI_EXP_GPIO_DIR_IN 0
+#define RPI_EXP_GPIO_DIR_OUT 1
+
+#define RPI_EXP_GPIO_NR 8
+
+struct gpio_set_config
+{
+ struct rpi_firmware_property_tag_header hdr;
+
+ rt_uint32_t gpio;
+ rt_uint32_t direction;
+ rt_uint32_t polarity;
+ rt_uint32_t term_en;
+ rt_uint32_t term_pull_up;
+ rt_uint32_t state;
+};
+
+struct gpio_get_config
+{
+ struct rpi_firmware_property_tag_header hdr;
+
+ rt_uint32_t gpio;
+ rt_uint32_t direction;
+ rt_uint32_t polarity;
+ rt_uint32_t term_en;
+ rt_uint32_t term_pull_up;
+};
+
+struct gpio_get_set_state
+{
+ struct rpi_firmware_property_tag_header hdr;
+
+ rt_uint32_t gpio;
+ rt_uint32_t state;
+};
+
+struct rpi_exp_gpio
+{
+ struct rt_device_pin parent;
+
+ void *property;
+ rt_ubase_t property_dma;
+ struct rpi_firmware *rpi_fw;
+ struct rt_spinlock lock;
+};
+
+#define raw_to_rpi_exp_gpio(raw) rt_container_of(raw, struct rpi_exp_gpio, parent)
+
+static int rpi_exp_gpio_get_polarity(struct rpi_exp_gpio *regpio, rt_base_t pin)
+{
+ rt_err_t err;
+ struct gpio_get_config *get = regpio->property;
+
+ get->gpio = pin + RPI_EXP_GPIO_BASE;
+
+ if ((err = rpi_firmware_property_raw(regpio->rpi_fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
+ regpio->property_dma, (void *)get, sizeof(*get))) || get->gpio != 0)
+ {
+ LOG_E("Failed to get PIN %u config (%s, %x)", pin, rt_strerror(err), get->gpio);
+
+ return err ? err : -RT_EIO;
+ }
+
+ return get->polarity;
+}
+
+static void rpi_exp_gpio_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ rt_err_t err;
+ rt_int32_t polarity;
+ union
+ {
+ struct gpio_set_config in;
+ struct gpio_set_config out;
+ } *set;
+ struct rpi_exp_gpio *regpio = raw_to_rpi_exp_gpio(device);
+
+ if (pin >= RPI_EXP_GPIO_NR)
+ {
+ return;
+ }
+
+ rt_hw_spin_lock(&regpio->lock.lock);
+
+ switch (mode)
+ {
+ case PIN_MODE_OUTPUT:
+ if ((polarity = rpi_exp_gpio_get_polarity(regpio, pin)) < 0)
+ {
+ LOG_E("Failed to get PIN %u polarity error = %s", pin, rt_strerror(polarity));
+
+ break;
+ }
+ set = regpio->property;
+ set->out.gpio = pin + RPI_EXP_GPIO_BASE;
+ set->out.direction = RPI_EXP_GPIO_DIR_OUT;
+ set->out.term_en = 0; /* n/a as an output */
+ set->out.term_pull_up = 0; /* n/a as termination disabled */
+ set->out.state = 1; /* Output state */
+ set->out.polarity = polarity; /* Retain existing setting */
+
+ if ((err = rpi_firmware_property_raw(regpio->rpi_fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
+ regpio->property_dma, (void *)&set->out, sizeof(set->out))) || set->out.gpio != 0)
+ {
+ LOG_E("Failed to set PIN %u to output (%s, %x)", pin, rt_strerror(err), set->out.gpio);
+ }
+
+ break;
+
+ case PIN_MODE_INPUT:
+ if ((polarity = rpi_exp_gpio_get_polarity(regpio, pin)) < 0)
+ {
+ LOG_E("Failed to get PIN %u polarity error = %s", pin, rt_strerror(polarity));
+
+ break;
+ }
+ set = regpio->property;
+ set->in.gpio = pin + RPI_EXP_GPIO_BASE;
+ set->in.direction = RPI_EXP_GPIO_DIR_IN;
+ set->in.term_en = 0; /* Termination disabled */
+ set->in.term_pull_up = 0; /* n/a as termination disabled */
+ set->in.state = 0; /* n/a as configured as an input */
+ set->in.polarity = polarity; /* Retain existing setting */
+
+ if ((err = rpi_firmware_property_raw(regpio->rpi_fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
+ regpio->property_dma, (void *)&set->in, sizeof(set->in))) || set->in.gpio != 0)
+ {
+ LOG_E("Failed to set PIN %u to input (%s, %x)", pin, rt_strerror(err), set->in.gpio);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ rt_hw_spin_unlock(&regpio->lock.lock);
+}
+
+static void rpi_exp_gpio_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
+{
+ rt_err_t err;
+ struct gpio_get_set_state *set;
+ struct rpi_exp_gpio *regpio = raw_to_rpi_exp_gpio(device);
+
+ if (pin >= RPI_EXP_GPIO_NR)
+ {
+ return;
+ }
+
+ rt_hw_spin_lock(&regpio->lock.lock);
+
+ set = regpio->property;
+ set->gpio = pin + RPI_EXP_GPIO_BASE;
+ set->state = value;
+
+ if ((err = rpi_firmware_property_raw(regpio->rpi_fw, RPI_FIRMWARE_SET_GPIO_STATE,
+ regpio->property_dma, (void *)set, sizeof(*set))) || set->gpio != 0)
+ {
+ LOG_E("Failed to set PIN %u state (%s, %x)", pin, rt_strerror(err), set->gpio);
+ }
+
+ rt_hw_spin_unlock(&regpio->lock.lock);
+}
+
+static rt_ssize_t rpi_exp_gpio_pin_read(struct rt_device *device, rt_base_t pin)
+{
+ rt_ssize_t res;
+ struct gpio_get_set_state *get;
+ struct rpi_exp_gpio *regpio = raw_to_rpi_exp_gpio(device);
+
+ if (pin >= RPI_EXP_GPIO_NR)
+ {
+ return -RT_EINVAL;
+ }
+
+ rt_hw_spin_lock(&regpio->lock.lock);
+
+ get = regpio->property;
+ get->gpio = pin + RPI_EXP_GPIO_BASE;
+ get->state = 0;
+
+ if ((res = rpi_firmware_property_raw(regpio->rpi_fw, RPI_FIRMWARE_GET_GPIO_STATE,
+ regpio->property_dma, (void *)get, sizeof(*get))) || get->gpio != 0)
+ {
+ LOG_E("Failed to get PIN %u state (%s, %x)", pin, rt_strerror(res), get->gpio);
+
+ res = res ? : -RT_EIO;
+ }
+ else
+ {
+ res = !!get->state;
+ }
+
+ rt_hw_spin_unlock(&regpio->lock.lock);
+
+ return res;
+}
+
+static const struct rt_pin_ops rpi_exp_gpio_pin_ops =
+{
+ .pin_mode = rpi_exp_gpio_pin_mode,
+ .pin_write = rpi_exp_gpio_pin_write,
+ .pin_read = rpi_exp_gpio_pin_read,
+};
+
+static rt_err_t rpi_exp_gpio_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_size_t size;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_exp_gpio *rpi_gpio = rt_calloc(1, sizeof(*rpi_gpio));
+
+ if (!rpi_gpio)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_get_parent(np);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_gpio->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_gpio->rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ size = sizeof(struct gpio_set_config);
+ size = rt_max_t(rt_size_t, sizeof(struct gpio_get_config), size);
+ size = rt_max_t(rt_size_t, sizeof(struct gpio_get_set_state), size);
+
+ rpi_gpio->property = rpi_firmware_property_raw_alloc(rpi_gpio->rpi_fw, size,
+ &rpi_gpio->property_dma);
+
+ if (!rpi_gpio->property)
+ {
+ err = -RT_ENOMEM;
+ goto _fail;
+ }
+
+ rt_spin_lock_init(&rpi_gpio->lock);
+
+ rpi_gpio->parent.ops = &rpi_exp_gpio_pin_ops;
+ pin_api_init(&rpi_gpio->parent, RPI_EXP_GPIO_NR);
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, &rpi_gpio->parent);
+
+ return RT_EOK;
+
+_fail:
+ if (rpi_gpio->rpi_fw)
+ {
+ rpi_firmware_put(rpi_gpio->rpi_fw);
+ }
+
+ rt_free(rpi_gpio);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rpi_exp_gpio_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,firmware-gpio" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_exp_gpio_driver =
+{
+ .name = "raspberrypi-exp-gpio",
+ .ids = rpi_exp_gpio_ofw_ids,
+
+ .probe = rpi_exp_gpio_probe,
+};
+
+static int rpi_exp_gpio_register(void)
+{
+ rt_platform_driver_register(&rpi_exp_gpio_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rpi_exp_gpio_register);
diff --git a/bsp/raspberry-pi/dm/pinctrl/Kconfig b/bsp/raspberry-pi/dm/pinctrl/Kconfig
new file mode 100755
index 0000000000..6fd1174e84
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pinctrl/Kconfig
@@ -0,0 +1,14 @@
+config RT_PINCTRL_BCM2712
+ bool "Broadcom BCM2712 PINCONF driver"
+ depends on RT_USING_PINCTRL
+ default n
+
+config RT_PINCTRL_BCM2835
+ bool "Broadcom BCM2835 GPIO (with PINCONF) driver"
+ depends on RT_USING_PINCTRL
+ default n
+
+config RT_PINCTRL_RP1
+ bool "Pinctrl driver for RP1"
+ depends on RT_USING_PINCTRL
+ default n
diff --git a/bsp/raspberry-pi/dm/pinctrl/SConscript b/bsp/raspberry-pi/dm/pinctrl/SConscript
new file mode 100755
index 0000000000..b5f3f87ada
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pinctrl/SConscript
@@ -0,0 +1,19 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_PINCTRL_BCM2712']):
+ src += ['pinctrl-bcm2712.c']
+
+if GetDepend(['RT_PINCTRL_BCM2835']):
+ src += ['pinctrl-bcm2835.c']
+
+if GetDepend(['RT_PINCTRL_RP1']):
+ src += ['pinctrl-rp1.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2712.c b/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2712.c
new file mode 100755
index 0000000000..03f3ba8222
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2712.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pinctrl.bcm2712"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define BCM2712_PULL_NONE 0
+#define BCM2712_PULL_DOWN 1
+#define BCM2712_PULL_UP 2
+#define BCM2712_PULL_MASK 0x3
+
+#define BCM2712_FSEL_COUNT 9
+#define BCM2712_FSEL_MASK 0xf
+
+#define REG_BIT_INVALID 0xffff
+
+#define BIT_TO_REG(b) (((b) >> 5) << 2)
+#define BIT_TO_SHIFT(b) ((b) & 0x1f)
+
+#define GPIO_REGS(n, mr, mb, pr, pb) [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 }
+#define EMMC_REGS(n, r, b) [n] = { 0, ((r)*4)*8 + (b)*2 }
+#define AGPIO_REGS(n, mr, mb, pr, pb) [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 }
+#define SGPIO_REGS(n, mr, mb) [n+32] = { ((mr)*4)*8 + (mb)*4, REG_BIT_INVALID }
+
+#define GPIO_PIN(a) { .number = a, .name = "gpio" #a }
+#define AGPIO_PIN(a) { .number = a, .name = "aon_gpio" #a }
+#define SGPIO_PIN(a) { .number = a+32, .name = "aon_sgpio" #a }
+
+enum bcm2712_funcs
+{
+ func_gpio,
+ func_alt1,
+ func_alt2,
+ func_alt3,
+ func_alt4,
+ func_alt5,
+ func_alt6,
+ func_alt7,
+ func_alt8,
+ func_aon_cpu_standbyb,
+ func_aon_fp_4sec_resetb,
+ func_aon_gpclk,
+ func_aon_pwm,
+ func_arm_jtag,
+ func_aud_fs_clk0,
+ func_avs_pmu_bsc,
+ func_bsc_m0,
+ func_bsc_m1,
+ func_bsc_m2,
+ func_bsc_m3,
+ func_clk_observe,
+ func_ctl_hdmi_5v,
+ func_enet0,
+ func_enet0_mii,
+ func_enet0_rgmii,
+ func_ext_sc_clk,
+ func_fl0,
+ func_fl1,
+ func_gpclk0,
+ func_gpclk1,
+ func_gpclk2,
+ func_hdmi_tx0_auto_i2c,
+ func_hdmi_tx0_bsc,
+ func_hdmi_tx1_auto_i2c,
+ func_hdmi_tx1_bsc,
+ func_i2s_in,
+ func_i2s_out,
+ func_ir_in,
+ func_mtsif,
+ func_mtsif_alt,
+ func_mtsif_alt1,
+ func_pdm,
+ func_pkt,
+ func_pm_led_out,
+ func_sc0,
+ func_sd0,
+ func_sd2,
+ func_sd_card_a,
+ func_sd_card_b,
+ func_sd_card_c,
+ func_sd_card_d,
+ func_sd_card_e,
+ func_sd_card_f,
+ func_sd_card_g,
+ func_spdif_out,
+ func_spi_m,
+ func_spi_s,
+ func_sr_edm_sense,
+ func_te0,
+ func_te1,
+ func_tsio,
+ func_uart0,
+ func_uart1,
+ func_uart2,
+ func_usb_pwr,
+ func_usb_vbus,
+ func_uui,
+ func_vc_i2c0,
+ func_vc_i2c3,
+ func_vc_i2c4,
+ func_vc_i2c5,
+ func_vc_i2csl,
+ func_vc_pcm,
+ func_vc_pwm0,
+ func_vc_pwm1,
+ func_vc_spi0,
+ func_vc_spi3,
+ func_vc_spi4,
+ func_vc_spi5,
+ func_vc_uart0,
+ func_vc_uart2,
+ func_vc_uart3,
+ func_vc_uart4,
+ func__,
+ func_count = func__,
+};
+
+struct bcm2712_pin_desc
+{
+ rt_uint32_t number;
+ const char *name;
+};
+
+struct bcm2712_pin_funcs
+{
+#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \
+ [i] = { \
+ .funcs = { \
+ func_##f1, \
+ func_##f2, \
+ func_##f3, \
+ func_##f4, \
+ func_##f5, \
+ func_##f6, \
+ func_##f7, \
+ func_##f8, \
+ }, \
+ }
+ rt_uint8_t funcs[BCM2712_FSEL_COUNT - 1];
+};
+
+struct bcm2712_pin_regs
+{
+ rt_uint16_t mux_bit;
+ rt_uint16_t pad_bit;
+};
+
+struct bcm2712_pinctrl_soc_data
+{
+ rt_size_t num_pins;
+ const struct bcm2712_pin_desc *desc;
+ const struct bcm2712_pin_funcs *funcs;
+ const struct bcm2712_pin_regs *regs;
+};
+
+struct bcm2712_pinctrl
+{
+ struct rt_device_pin parent;
+ const struct bcm2712_pinctrl_soc_data *soc_data;
+
+ void *base;
+ struct rt_spinlock lock;
+};
+
+#define raw_to_bcm2712_pinctrl(raw) rt_container_of(raw, struct bcm2712_pinctrl, parent)
+
+static const char * const bcm2712_func_names[] =
+{
+#define FUNC_NAME(name) [func_##name] = #name
+ FUNC_NAME(gpio),
+ FUNC_NAME(alt1),
+ FUNC_NAME(alt2),
+ FUNC_NAME(alt3),
+ FUNC_NAME(alt4),
+ FUNC_NAME(alt5),
+ FUNC_NAME(alt6),
+ FUNC_NAME(alt7),
+ FUNC_NAME(alt8),
+ FUNC_NAME(aon_cpu_standbyb),
+ FUNC_NAME(aon_fp_4sec_resetb),
+ FUNC_NAME(aon_gpclk),
+ FUNC_NAME(aon_pwm),
+ FUNC_NAME(arm_jtag),
+ FUNC_NAME(aud_fs_clk0),
+ FUNC_NAME(avs_pmu_bsc),
+ FUNC_NAME(bsc_m0),
+ FUNC_NAME(bsc_m1),
+ FUNC_NAME(bsc_m2),
+ FUNC_NAME(bsc_m3),
+ FUNC_NAME(clk_observe),
+ FUNC_NAME(ctl_hdmi_5v),
+ FUNC_NAME(enet0),
+ FUNC_NAME(enet0_mii),
+ FUNC_NAME(enet0_rgmii),
+ FUNC_NAME(ext_sc_clk),
+ FUNC_NAME(fl0),
+ FUNC_NAME(fl1),
+ FUNC_NAME(gpclk0),
+ FUNC_NAME(gpclk1),
+ FUNC_NAME(gpclk2),
+ FUNC_NAME(hdmi_tx0_auto_i2c),
+ FUNC_NAME(hdmi_tx0_bsc),
+ FUNC_NAME(hdmi_tx1_auto_i2c),
+ FUNC_NAME(hdmi_tx1_bsc),
+ FUNC_NAME(i2s_in),
+ FUNC_NAME(i2s_out),
+ FUNC_NAME(ir_in),
+ FUNC_NAME(mtsif),
+ FUNC_NAME(mtsif_alt),
+ FUNC_NAME(mtsif_alt1),
+ FUNC_NAME(pdm),
+ FUNC_NAME(pkt),
+ FUNC_NAME(pm_led_out),
+ FUNC_NAME(sc0),
+ FUNC_NAME(sd0),
+ FUNC_NAME(sd2),
+ FUNC_NAME(sd_card_a),
+ FUNC_NAME(sd_card_b),
+ FUNC_NAME(sd_card_c),
+ FUNC_NAME(sd_card_d),
+ FUNC_NAME(sd_card_e),
+ FUNC_NAME(sd_card_f),
+ FUNC_NAME(sd_card_g),
+ FUNC_NAME(spdif_out),
+ FUNC_NAME(spi_m),
+ FUNC_NAME(spi_s),
+ FUNC_NAME(sr_edm_sense),
+ FUNC_NAME(te0),
+ FUNC_NAME(te1),
+ FUNC_NAME(tsio),
+ FUNC_NAME(uart0),
+ FUNC_NAME(uart1),
+ FUNC_NAME(uart2),
+ FUNC_NAME(usb_pwr),
+ FUNC_NAME(usb_vbus),
+ FUNC_NAME(uui),
+ FUNC_NAME(vc_i2c0),
+ FUNC_NAME(vc_i2c3),
+ FUNC_NAME(vc_i2c4),
+ FUNC_NAME(vc_i2c5),
+ FUNC_NAME(vc_i2csl),
+ FUNC_NAME(vc_pcm),
+ FUNC_NAME(vc_pwm0),
+ FUNC_NAME(vc_pwm1),
+ FUNC_NAME(vc_spi0),
+ FUNC_NAME(vc_spi3),
+ FUNC_NAME(vc_spi4),
+ FUNC_NAME(vc_spi5),
+ FUNC_NAME(vc_uart0),
+ FUNC_NAME(vc_uart2),
+ FUNC_NAME(vc_uart3),
+ FUNC_NAME(vc_uart4),
+#undef FUNC_NAME
+};
+
+rt_inline rt_uint32_t bcm2712_reg_rd(struct bcm2712_pinctrl *pc, int reg)
+{
+ return HWREG32(pc->base + reg);
+}
+
+rt_inline void bcm2712_reg_wr(struct bcm2712_pinctrl *pc, int reg, rt_uint32_t val)
+{
+ HWREG32(pc->base + reg) = val;
+}
+
+static void bcm2712_pinctrl_fsel_set(struct bcm2712_pinctrl *pc, rt_ubase_t pin,
+ enum bcm2712_funcs func)
+{
+ int fsel, cur;
+ const rt_uint8_t *pin_funcs;
+ rt_uint32_t bit = pc->soc_data->regs[pin].mux_bit, val;
+
+ if (!bit || func >= func_count)
+ {
+ return;
+ }
+
+ fsel = BCM2712_FSEL_COUNT;
+
+ if (func >= BCM2712_FSEL_COUNT)
+ {
+ /* Convert to an fsel number */
+ pin_funcs = pc->soc_data->funcs[pin].funcs;
+
+ for (int i = 1; i < BCM2712_FSEL_COUNT; ++i)
+ {
+ if (pin_funcs[i - 1] == func)
+ {
+ fsel = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ fsel = (enum bcm2712_funcs)func;
+ }
+
+ if (fsel >= BCM2712_FSEL_COUNT)
+ {
+ return;
+ }
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ cur = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK;
+
+ if (cur != fsel)
+ {
+ val &= ~(BCM2712_FSEL_MASK << BIT_TO_SHIFT(bit));
+ val |= fsel << BIT_TO_SHIFT(bit);
+
+ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val);
+ }
+}
+
+static void bcm2712_pull_config_set(struct bcm2712_pinctrl *pc, rt_ubase_t pin,
+ rt_uint32_t arg)
+{
+ rt_uint32_t bit = pc->soc_data->regs[pin].pad_bit, val;
+
+ if (bit == REG_BIT_INVALID)
+ {
+ return;
+ }
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ val &= ~(BCM2712_PULL_MASK << BIT_TO_SHIFT(bit));
+ val |= (arg << BIT_TO_SHIFT(bit));
+ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val);
+}
+
+static const struct rt_pin_ctrl_conf_params bcm2712_conf_params[] =
+{
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+};
+
+static rt_err_t bcm2712_pinctrl_confs_apply_once(struct bcm2712_pinctrl *pc,
+ struct rt_ofw_node *np)
+{
+ rt_err_t err = RT_EOK;
+ rt_ubase_t pin;
+ const char *string;
+ struct rt_ofw_prop *prop;
+ enum bcm2712_funcs func = func_count;
+ const struct rt_pin_ctrl_conf_params *conf = RT_NULL;
+
+ if (rt_ofw_prop_read_string(np, "function", &string))
+ {
+ return -RT_EINVAL;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(bcm2712_func_names); ++i)
+ {
+ if (!rt_strcmp(string, bcm2712_func_names[i]))
+ {
+ func = (enum bcm2712_funcs)i;
+ break;
+ }
+ }
+
+ if (func == func_count)
+ {
+ return -RT_EINVAL;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(bcm2712_conf_params); ++i)
+ {
+ if (rt_ofw_prop_read_bool(np, bcm2712_conf_params[i].propname))
+ {
+ conf = &bcm2712_conf_params[i];
+ break;
+ }
+ }
+
+ rt_ofw_foreach_prop_string(np, "pins", prop, string)
+ {
+ pin = pc->soc_data->num_pins;
+
+ for (int i = 0; i < pc->soc_data->num_pins; ++i)
+ {
+ if (!rt_strcmp(pc->soc_data->desc[i].name, string))
+ {
+ pin = pc->soc_data->desc[i].number;
+ break;
+ }
+ }
+
+ if (pin == pc->soc_data->num_pins)
+ {
+ err = -RT_EINVAL;
+ break;
+ }
+
+ bcm2712_pinctrl_fsel_set(pc, pin, func);
+
+ if (conf)
+ {
+ switch (conf->param)
+ {
+ case PIN_CONFIG_BIAS_DISABLE:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_NONE);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_DOWN);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_UP);
+ break;
+
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+static rt_err_t bcm2712_pinctrl_confs_apply(struct rt_device *device, void *fw_conf_np)
+{
+ rt_err_t err;
+ rt_bool_t stage2 = RT_FALSE;
+ struct rt_ofw_node *conf_np = fw_conf_np, *child;
+ struct bcm2712_pinctrl *pc = raw_to_bcm2712_pinctrl(device);
+
+ rt_hw_spin_lock(&pc->lock.lock);
+
+ rt_ofw_foreach_child_node(conf_np, child)
+ {
+ stage2 = RT_TRUE;
+
+ if ((err = bcm2712_pinctrl_confs_apply_once(pc, child)))
+ {
+ goto _unlock;
+ }
+ }
+
+ if (!stage2)
+ {
+ err = bcm2712_pinctrl_confs_apply_once(pc, conf_np);
+ }
+
+_unlock:
+ rt_hw_spin_unlock(&pc->lock.lock);
+
+ return err;
+}
+
+static const struct rt_pin_ops bcm2712_pinctrl_ops =
+{
+ .pin_ctrl_confs_apply = bcm2712_pinctrl_confs_apply,
+};
+
+static rt_err_t bcm2712_pinctrl_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2712_pinctrl *pc = rt_calloc(1, sizeof(*pc));
+
+ if (!pc)
+ {
+ return -RT_ENOMEM;
+ }
+ pc->soc_data = pdev->id->data;
+
+ if (!(pc->base = rt_dm_dev_iomap(dev, 0)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ rt_spin_lock_init(&pc->lock);
+ pc->parent.ops = &bcm2712_pinctrl_ops;
+
+ rt_ofw_data(dev->ofw_node) = &pc->parent;
+
+ return RT_EOK;
+
+_fail:
+ rt_free(pc);
+
+ return err;
+}
+
+static const struct bcm2712_pin_desc bcm2712_c0_gpio_pins[] =
+{
+ GPIO_PIN(0),
+ GPIO_PIN(1),
+ GPIO_PIN(2),
+ GPIO_PIN(3),
+ GPIO_PIN(4),
+ GPIO_PIN(5),
+ GPIO_PIN(6),
+ GPIO_PIN(7),
+ GPIO_PIN(8),
+ GPIO_PIN(9),
+ GPIO_PIN(10),
+ GPIO_PIN(11),
+ GPIO_PIN(12),
+ GPIO_PIN(13),
+ GPIO_PIN(14),
+ GPIO_PIN(15),
+ GPIO_PIN(16),
+ GPIO_PIN(17),
+ GPIO_PIN(18),
+ GPIO_PIN(19),
+ GPIO_PIN(20),
+ GPIO_PIN(21),
+ GPIO_PIN(22),
+ GPIO_PIN(23),
+ GPIO_PIN(24),
+ GPIO_PIN(25),
+ GPIO_PIN(26),
+ GPIO_PIN(27),
+ GPIO_PIN(28),
+ GPIO_PIN(29),
+ GPIO_PIN(30),
+ GPIO_PIN(31),
+ GPIO_PIN(32),
+ GPIO_PIN(33),
+ GPIO_PIN(34),
+ GPIO_PIN(35),
+ GPIO_PIN(36),
+ GPIO_PIN(37),
+ GPIO_PIN(38),
+ GPIO_PIN(39),
+ GPIO_PIN(40),
+ GPIO_PIN(41),
+ GPIO_PIN(42),
+ GPIO_PIN(43),
+ GPIO_PIN(44),
+ GPIO_PIN(45),
+ GPIO_PIN(46),
+ GPIO_PIN(47),
+ GPIO_PIN(48),
+ GPIO_PIN(49),
+ GPIO_PIN(50),
+ GPIO_PIN(51),
+ GPIO_PIN(52),
+ GPIO_PIN(53),
+ { 54, "emmc_cmd" },
+ { 55, "emmc_ds" },
+ { 56, "emmc_clk" },
+ { 57, "emmc_dat0" },
+ { 58, "emmc_dat1" },
+ { 59, "emmc_dat2" },
+ { 60, "emmc_dat3" },
+ { 61, "emmc_dat4" },
+ { 62, "emmc_dat5" },
+ { 63, "emmc_dat6" },
+ { 64, "emmc_dat7" },
+};
+
+static const struct bcm2712_pin_funcs bcm2712_c0_gpio_pin_funcs[] =
+{
+ PIN(0, bsc_m3, vc_i2c0, gpclk0, enet0, vc_pwm1, vc_spi0, ir_in, _),
+ PIN(1, bsc_m3, vc_i2c0, gpclk1, enet0, vc_pwm1, sr_edm_sense, vc_spi0, vc_uart3),
+ PIN(2, pdm, i2s_in, gpclk2, vc_spi4, pkt, vc_spi0, vc_uart3, _),
+ PIN(3, pdm, i2s_in, vc_spi4, pkt, vc_spi0, vc_uart3, _, _),
+ PIN(4, pdm, i2s_in, arm_jtag, vc_spi4, pkt, vc_spi0, vc_uart3, _),
+ PIN(5, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5),
+ PIN(6, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5),
+ PIN(7, i2s_out, spdif_out, arm_jtag, sd_card_e, vc_i2c3, enet0_rgmii, vc_pcm, vc_spi4),
+ PIN(8, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, vc_i2c3, enet0_mii, vc_pcm, vc_spi4),
+ PIN(9, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, enet0_mii, sd_card_c, vc_spi4, _),
+ PIN(10, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4),
+ PIN(11, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4),
+ PIN(12, spi_s, mtsif_alt1, i2s_in, i2s_out, vc_spi5, vc_i2csl, sd0, sd_card_d),
+ PIN(13, spi_s, mtsif_alt1, i2s_out, usb_vbus, vc_spi5, vc_i2csl, sd0, sd_card_d),
+ PIN(14, spi_s, vc_i2csl, enet0_rgmii, arm_jtag, vc_spi5, vc_pwm0, vc_i2c4, sd_card_d),
+ PIN(15, spi_s, vc_i2csl, vc_spi3, arm_jtag, vc_pwm0, vc_i2c4, gpclk0, _),
+ PIN(16, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, gpclk1, _),
+ PIN(17, sd_card_b, i2s_out, vc_spi3, i2s_in, ext_sc_clk, sd0, enet0_rgmii, gpclk2),
+ PIN(18, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, vc_pwm1, _),
+ PIN(19, sd_card_b, usb_pwr, vc_spi3, pkt, spdif_out, sd0, ir_in, vc_pwm1),
+ PIN(20, sd_card_b, uui, vc_uart0, arm_jtag, uart2, usb_pwr, vc_pcm, vc_uart4),
+ PIN(21, usb_pwr, uui, vc_uart0, arm_jtag, uart2, sd_card_b, vc_pcm, vc_uart4),
+ PIN(22, usb_pwr, enet0, vc_uart0, mtsif, uart2, usb_vbus, vc_pcm, vc_i2c5),
+ PIN(23, usb_vbus, enet0, vc_uart0, mtsif, uart2, i2s_out, vc_pcm, vc_i2c5),
+ PIN(24, mtsif, pkt, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3, _),
+ PIN(25, mtsif, pkt, sc0, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3),
+ PIN(26, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _),
+ PIN(27, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _),
+ PIN(28, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _),
+ PIN(29, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _),
+ PIN(30, mtsif, pkt, sc0, sd2, enet0_rgmii, gpclk0, vc_pwm0, _),
+ PIN(31, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_pwm0, _),
+ PIN(32, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_uart3, _),
+ PIN(33, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_uart3, _, _),
+ PIN(34, mtsif, pkt, ext_sc_clk, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _),
+ PIN(35, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _, _),
+ PIN(36, sd0, mtsif, sc0, i2s_in, vc_uart3, vc_uart2, _, _),
+ PIN(37, sd0, mtsif, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _),
+ PIN(38, sd0, mtsif_alt, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _),
+ PIN(39, sd0, mtsif_alt, sc0, vc_spi0, vc_uart3, vc_uart2, _, _),
+ PIN(40, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _),
+ PIN(41, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _),
+ PIN(42, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(43, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(44, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(45, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(46, vc_spi0, mtsif_alt, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m, _),
+ PIN(47, enet0, mtsif_alt, i2s_out, mtsif_alt1, arm_jtag, _, _, _),
+ PIN(48, sc0, usb_pwr, spdif_out, mtsif, _, _, _, _),
+ PIN(49, sc0, usb_pwr, aud_fs_clk0, mtsif, _, _, _, _),
+ PIN(50, sc0, usb_vbus, sc0, _, _, _, _, _),
+ PIN(51, sc0, enet0, sc0, sr_edm_sense, _, _, _, _),
+ PIN(52, sc0, enet0, vc_pwm1, _, _, _, _, _),
+ PIN(53, sc0, enet0_rgmii, ext_sc_clk, _, _, _, _, _),
+};
+
+static const struct bcm2712_pin_regs bcm2712_c0_gpio_pin_regs[] =
+{
+ GPIO_REGS(0, 0, 0, 7, 7),
+ GPIO_REGS(1, 0, 1, 7, 8),
+ GPIO_REGS(2, 0, 2, 7, 9),
+ GPIO_REGS(3, 0, 3, 7, 10),
+ GPIO_REGS(4, 0, 4, 7, 11),
+ GPIO_REGS(5, 0, 5, 7, 12),
+ GPIO_REGS(6, 0, 6, 7, 13),
+ GPIO_REGS(7, 0, 7, 7, 14),
+ GPIO_REGS(8, 1, 0, 8, 0),
+ GPIO_REGS(9, 1, 1, 8, 1),
+ GPIO_REGS(10, 1, 2, 8, 2),
+ GPIO_REGS(11, 1, 3, 8, 3),
+ GPIO_REGS(12, 1, 4, 8, 4),
+ GPIO_REGS(13, 1, 5, 8, 5),
+ GPIO_REGS(14, 1, 6, 8, 6),
+ GPIO_REGS(15, 1, 7, 8, 7),
+ GPIO_REGS(16, 2, 0, 8, 8),
+ GPIO_REGS(17, 2, 1, 8, 9),
+ GPIO_REGS(18, 2, 2, 8, 10),
+ GPIO_REGS(19, 2, 3, 8, 11),
+ GPIO_REGS(20, 2, 4, 8, 12),
+ GPIO_REGS(21, 2, 5, 8, 13),
+ GPIO_REGS(22, 2, 6, 8, 14),
+ GPIO_REGS(23, 2, 7, 9, 0),
+ GPIO_REGS(24, 3, 0, 9, 1),
+ GPIO_REGS(25, 3, 1, 9, 2),
+ GPIO_REGS(26, 3, 2, 9, 3),
+ GPIO_REGS(27, 3, 3, 9, 4),
+ GPIO_REGS(28, 3, 4, 9, 5),
+ GPIO_REGS(29, 3, 5, 9, 6),
+ GPIO_REGS(30, 3, 6, 9, 7),
+ GPIO_REGS(31, 3, 7, 9, 8),
+ GPIO_REGS(32, 4, 0, 9, 9),
+ GPIO_REGS(33, 4, 1, 9, 10),
+ GPIO_REGS(34, 4, 2, 9, 11),
+ GPIO_REGS(35, 4, 3, 9, 12),
+ GPIO_REGS(36, 4, 4, 9, 13),
+ GPIO_REGS(37, 4, 5, 9, 14),
+ GPIO_REGS(38, 4, 6, 10, 0),
+ GPIO_REGS(39, 4, 7, 10, 1),
+ GPIO_REGS(40, 5, 0, 10, 2),
+ GPIO_REGS(41, 5, 1, 10, 3),
+ GPIO_REGS(42, 5, 2, 10, 4),
+ GPIO_REGS(43, 5, 3, 10, 5),
+ GPIO_REGS(44, 5, 4, 10, 6),
+ GPIO_REGS(45, 5, 5, 10, 7),
+ GPIO_REGS(46, 5, 6, 10, 8),
+ GPIO_REGS(47, 5, 7, 10, 9),
+ GPIO_REGS(48, 6, 0, 10, 10),
+ GPIO_REGS(49, 6, 1, 10, 11),
+ GPIO_REGS(50, 6, 2, 10, 12),
+ GPIO_REGS(51, 6, 3, 10, 13),
+ GPIO_REGS(52, 6, 4, 10, 14),
+ GPIO_REGS(53, 6, 5, 11, 0),
+ EMMC_REGS(54, 11, 1), /* EMMC_CMD */
+ EMMC_REGS(55, 11, 2), /* EMMC_DS */
+ EMMC_REGS(56, 11, 3), /* EMMC_CLK */
+ EMMC_REGS(57, 11, 4), /* EMMC_DAT0 */
+ EMMC_REGS(58, 11, 5), /* EMMC_DAT1 */
+ EMMC_REGS(59, 11, 6), /* EMMC_DAT2 */
+ EMMC_REGS(60, 11, 7), /* EMMC_DAT3 */
+ EMMC_REGS(61, 11, 8), /* EMMC_DAT4 */
+ EMMC_REGS(62, 11, 9), /* EMMC_DAT5 */
+ EMMC_REGS(63, 11, 10), /* EMMC_DAT6 */
+ EMMC_REGS(64, 11, 11), /* EMMC_DAT7 */
+};
+
+static struct bcm2712_pinctrl_soc_data bcm2712_c0_data =
+{
+ .num_pins = RT_ARRAY_SIZE(bcm2712_c0_gpio_pins),
+ .desc = bcm2712_c0_gpio_pins,
+ .funcs = bcm2712_c0_gpio_pin_funcs,
+ .regs = bcm2712_c0_gpio_pin_regs,
+};
+
+static struct bcm2712_pin_desc bcm2712_c0_aon_gpio_pins[] =
+{
+ AGPIO_PIN(0),
+ AGPIO_PIN(1),
+ AGPIO_PIN(2),
+ AGPIO_PIN(3),
+ AGPIO_PIN(4),
+ AGPIO_PIN(5),
+ AGPIO_PIN(6),
+ AGPIO_PIN(7),
+ AGPIO_PIN(8),
+ AGPIO_PIN(9),
+ AGPIO_PIN(10),
+ AGPIO_PIN(11),
+ AGPIO_PIN(12),
+ AGPIO_PIN(13),
+ AGPIO_PIN(14),
+ AGPIO_PIN(15),
+ AGPIO_PIN(16),
+ SGPIO_PIN(0),
+ SGPIO_PIN(1),
+ SGPIO_PIN(2),
+ SGPIO_PIN(3),
+ SGPIO_PIN(4),
+ SGPIO_PIN(5),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_c0_aon_gpio_pin_funcs[] =
+{
+ PIN(0, ir_in, vc_spi0, vc_uart3, vc_i2c3, te0, vc_i2c0, _, _),
+ PIN(1, vc_pwm0, vc_spi0, vc_uart3, vc_i2c3, te1, aon_pwm, vc_i2c0, vc_pwm1),
+ PIN(2, vc_pwm0, vc_spi0, vc_uart3, ctl_hdmi_5v, fl0, aon_pwm, ir_in, vc_pwm1),
+ PIN(3, ir_in, vc_spi0, vc_uart3, aon_fp_4sec_resetb, fl1, sd_card_g, aon_gpclk, _),
+ PIN(4, gpclk0, vc_spi0, vc_i2csl, aon_gpclk, pm_led_out, aon_pwm, sd_card_g, vc_pwm0),
+ PIN(5, gpclk1, ir_in, vc_i2csl, clk_observe, aon_pwm, sd_card_g, vc_pwm0, _),
+ PIN(6, uart1, vc_uart4, gpclk2, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _),
+ PIN(7, uart1, vc_uart4, gpclk0, aon_pwm, vc_uart0, vc_spi3, _, _),
+ PIN(8, uart1, vc_uart4, vc_i2csl, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _),
+ PIN(9, uart1, vc_uart4, vc_i2csl, aon_pwm, vc_uart0, vc_spi3, _, _),
+ PIN(10, tsio, ctl_hdmi_5v, sc0, spdif_out, vc_spi5, usb_pwr, aon_gpclk, sd_card_f),
+ PIN(11, tsio, uart0, sc0, aud_fs_clk0, vc_spi5, usb_vbus, vc_uart2, sd_card_f),
+ PIN(12, tsio, uart0, vc_uart0, tsio, vc_spi5, usb_pwr, vc_uart2, sd_card_f),
+ PIN(13, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3),
+ PIN(14, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3),
+ PIN(15, ir_in, aon_fp_4sec_resetb, vc_uart0, pm_led_out, ctl_hdmi_5v, aon_pwm, aon_gpclk, _),
+ PIN(16, aon_cpu_standbyb, gpclk0, pm_led_out, ctl_hdmi_5v, vc_pwm0, usb_pwr, aud_fs_clk0, _),
+};
+
+static const struct bcm2712_pin_regs bcm2712_c0_aon_gpio_pin_regs[] =
+{
+ AGPIO_REGS(0, 3, 0, 6, 10),
+ AGPIO_REGS(1, 3, 1, 6, 11),
+ AGPIO_REGS(2, 3, 2, 6, 12),
+ AGPIO_REGS(3, 3, 3, 6, 13),
+ AGPIO_REGS(4, 3, 4, 6, 14),
+ AGPIO_REGS(5, 3, 5, 7, 0),
+ AGPIO_REGS(6, 3, 6, 7, 1),
+ AGPIO_REGS(7, 3, 7, 7, 2),
+ AGPIO_REGS(8, 4, 0, 7, 3),
+ AGPIO_REGS(9, 4, 1, 7, 4),
+ AGPIO_REGS(10, 4, 2, 7, 5),
+ AGPIO_REGS(11, 4, 3, 7, 6),
+ AGPIO_REGS(12, 4, 4, 7, 7),
+ AGPIO_REGS(13, 4, 5, 7, 8),
+ AGPIO_REGS(14, 4, 6, 7, 9),
+ AGPIO_REGS(15, 4, 7, 7, 10),
+ AGPIO_REGS(16, 5, 0, 7, 11),
+ SGPIO_REGS(0, 0, 0),
+ SGPIO_REGS(1, 0, 1),
+ SGPIO_REGS(2, 0, 2),
+ SGPIO_REGS(3, 0, 3),
+ SGPIO_REGS(4, 1, 0),
+ SGPIO_REGS(5, 2, 0),
+};
+
+static struct bcm2712_pinctrl_soc_data bcm2712_c0_aon_data =
+{
+ .num_pins = RT_ARRAY_SIZE(bcm2712_c0_aon_gpio_pins),
+ .desc = bcm2712_c0_aon_gpio_pins,
+ .funcs = bcm2712_c0_aon_gpio_pin_funcs,
+ .regs = bcm2712_c0_aon_gpio_pin_regs,
+};
+
+static const struct bcm2712_pin_desc bcm2712_d0_gpio_pins[] =
+{
+ GPIO_PIN(1),
+ GPIO_PIN(2),
+ GPIO_PIN(3),
+ GPIO_PIN(4),
+ GPIO_PIN(10),
+ GPIO_PIN(11),
+ GPIO_PIN(12),
+ GPIO_PIN(13),
+ GPIO_PIN(14),
+ GPIO_PIN(15),
+ GPIO_PIN(18),
+ GPIO_PIN(19),
+ GPIO_PIN(20),
+ GPIO_PIN(21),
+ GPIO_PIN(22),
+ GPIO_PIN(23),
+ GPIO_PIN(24),
+ GPIO_PIN(25),
+ GPIO_PIN(26),
+ GPIO_PIN(27),
+ GPIO_PIN(28),
+ GPIO_PIN(29),
+ GPIO_PIN(30),
+ GPIO_PIN(31),
+ GPIO_PIN(32),
+ GPIO_PIN(33),
+ GPIO_PIN(34),
+ GPIO_PIN(35),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_d0_gpio_pin_funcs[] =
+{
+ PIN(1, vc_i2c0, usb_pwr, gpclk0, sd_card_e, vc_spi3, sr_edm_sense, vc_spi0, vc_uart0),
+ PIN(2, vc_i2c0, usb_pwr, gpclk1, sd_card_e, vc_spi3, clk_observe, vc_spi0, vc_uart0),
+ PIN(3, vc_i2c3, usb_vbus, gpclk2, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _),
+ PIN(4, vc_i2c3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _),
+ PIN(10, bsc_m3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, gpclk0, _, _),
+ PIN(11, bsc_m3, vc_spi3, clk_observe, sd_card_c, gpclk1, _, _, _),
+ PIN(12, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _),
+ PIN(13, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _),
+ PIN(14, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, sd_card_d, _, _),
+ PIN(15, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, gpclk0, _, _),
+ PIN(18, sd_card_f, vc_pwm1, _, _, _, _, _, _),
+ PIN(19, sd_card_f, usb_pwr, vc_pwm1, _, _, _, _, _),
+ PIN(20, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _),
+ PIN(21, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _),
+ PIN(22, sd_card_f, vc_uart0, vc_i2c3, _, _, _, _, _),
+ PIN(23, vc_uart0, vc_i2c3, _, _, _, _, _, _),
+ PIN(24, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _),
+ PIN(25, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _),
+ PIN(26, sd_card_b, vc_spi0, arm_jtag, uart0, usb_vbus, vc_uart2, vc_spi0, _),
+ PIN(27, sd_card_b, vc_spi0, arm_jtag, uart0, vc_uart2, vc_spi0, _, _),
+ PIN(28, sd_card_b, vc_spi0, arm_jtag, vc_i2c0, vc_spi0, _, _, _),
+ PIN(29, arm_jtag, vc_i2c0, vc_spi0, _, _, _, _, _),
+ PIN(30, sd2, gpclk0, vc_pwm0, _, _, _, _, _),
+ PIN(31, sd2, vc_spi3, vc_pwm0, _, _, _, _, _),
+ PIN(32, sd2, vc_spi3, vc_uart3, _, _, _, _, _),
+ PIN(33, sd2, vc_spi3, vc_uart3, _, _, _, _, _),
+ PIN(34, sd2, vc_spi3, vc_i2c5, _, _, _, _, _),
+ PIN(35, sd2, vc_spi3, vc_i2c5, _, _, _, _, _),
+};
+
+static const struct bcm2712_pin_regs bcm2712_d0_gpio_pin_regs[] =
+{
+ GPIO_REGS(1, 0, 0, 4, 5),
+ GPIO_REGS(2, 0, 1, 4, 6),
+ GPIO_REGS(3, 0, 2, 4, 7),
+ GPIO_REGS(4, 0, 3, 4, 8),
+ GPIO_REGS(10, 0, 4, 4, 9),
+ GPIO_REGS(11, 0, 5, 4, 10),
+ GPIO_REGS(12, 0, 6, 4, 11),
+ GPIO_REGS(13, 0, 7, 4, 12),
+ GPIO_REGS(14, 1, 0, 4, 13),
+ GPIO_REGS(15, 1, 1, 4, 14),
+ GPIO_REGS(18, 1, 2, 5, 0),
+ GPIO_REGS(19, 1, 3, 5, 1),
+ GPIO_REGS(20, 1, 4, 5, 2),
+ GPIO_REGS(21, 1, 5, 5, 3),
+ GPIO_REGS(22, 1, 6, 5, 4),
+ GPIO_REGS(23, 1, 7, 5, 5),
+ GPIO_REGS(24, 2, 0, 5, 6),
+ GPIO_REGS(25, 2, 1, 5, 7),
+ GPIO_REGS(26, 2, 2, 5, 8),
+ GPIO_REGS(27, 2, 3, 5, 9),
+ GPIO_REGS(28, 2, 4, 5, 10),
+ GPIO_REGS(29, 2, 5, 5, 11),
+ GPIO_REGS(30, 2, 6, 5, 12),
+ GPIO_REGS(31, 2, 7, 5, 13),
+ GPIO_REGS(32, 3, 0, 5, 14),
+ GPIO_REGS(33, 3, 1, 6, 0),
+ GPIO_REGS(34, 3, 2, 6, 1),
+ GPIO_REGS(35, 3, 3, 6, 2),
+};
+
+static struct bcm2712_pinctrl_soc_data bcm2712_d0_data =
+{
+ .num_pins = RT_ARRAY_SIZE(bcm2712_d0_gpio_pins),
+ .desc = bcm2712_d0_gpio_pins,
+ .funcs = bcm2712_d0_gpio_pin_funcs,
+ .regs = bcm2712_d0_gpio_pin_regs,
+};
+
+static struct bcm2712_pin_desc bcm2712_d0_aon_gpio_pins[] =
+{
+ AGPIO_PIN(0),
+ AGPIO_PIN(1),
+ AGPIO_PIN(2),
+ AGPIO_PIN(3),
+ AGPIO_PIN(4),
+ AGPIO_PIN(5),
+ AGPIO_PIN(6),
+ AGPIO_PIN(8),
+ AGPIO_PIN(9),
+ AGPIO_PIN(12),
+ AGPIO_PIN(13),
+ AGPIO_PIN(14),
+ SGPIO_PIN(0),
+ SGPIO_PIN(1),
+ SGPIO_PIN(2),
+ SGPIO_PIN(3),
+ SGPIO_PIN(4),
+ SGPIO_PIN(5),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_d0_aon_gpio_pin_funcs[] =
+{
+ PIN(0, ir_in, vc_spi0, vc_uart0, vc_i2c3, uart0, vc_i2c0, _, _),
+ PIN(1, vc_pwm0, vc_spi0, vc_uart0, vc_i2c3, uart0, aon_pwm, vc_i2c0, vc_pwm1),
+ PIN(2, vc_pwm0, vc_spi0, vc_uart0, ctl_hdmi_5v, uart0, aon_pwm, ir_in, vc_pwm1),
+ PIN(3, ir_in, vc_spi0, vc_uart0, uart0, sd_card_g, aon_gpclk, _, _),
+ PIN(4, gpclk0, vc_spi0, pm_led_out, aon_pwm, sd_card_g, vc_pwm0, _, _),
+ PIN(5, gpclk1, ir_in, aon_pwm, sd_card_g, vc_pwm0, _, _, _),
+ PIN(6, uart1, vc_uart2, ctl_hdmi_5v, gpclk2, vc_spi3, _, _, _),
+ PIN(7, _, _, _, _, _, _, _, _),
+ PIN(8, uart1, vc_uart2, ctl_hdmi_5v, vc_spi0, vc_spi3, _, _, _),
+ PIN(9, uart1, vc_uart2, vc_uart0, aon_pwm, vc_spi0, vc_uart2, vc_spi3, _),
+ PIN(10, _, _, _, _, _, _, _, _),
+ PIN(11, _, _, _, _, _, _, _, _),
+ PIN(12, uart1, vc_uart2, vc_uart0, vc_spi0, usb_pwr, vc_uart2, vc_spi3, _),
+ PIN(13, bsc_m1, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3, _),
+ PIN(14, bsc_m1, aon_gpclk, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3),
+};
+
+static const struct bcm2712_pin_regs bcm2712_d0_aon_gpio_pin_regs[] =
+{
+ AGPIO_REGS(0, 3, 0, 5, 9),
+ AGPIO_REGS(1, 3, 1, 5, 10),
+ AGPIO_REGS(2, 3, 2, 5, 11),
+ AGPIO_REGS(3, 3, 3, 5, 12),
+ AGPIO_REGS(4, 3, 4, 5, 13),
+ AGPIO_REGS(5, 3, 5, 5, 14),
+ AGPIO_REGS(6, 3, 6, 6, 0),
+ AGPIO_REGS(8, 3, 7, 6, 1),
+ AGPIO_REGS(9, 4, 0, 6, 2),
+ AGPIO_REGS(12, 4, 1, 6, 3),
+ AGPIO_REGS(13, 4, 2, 6, 4),
+ AGPIO_REGS(14, 4, 3, 6, 5),
+ SGPIO_REGS(0, 0, 0),
+ SGPIO_REGS(1, 0, 1),
+ SGPIO_REGS(2, 0, 2),
+ SGPIO_REGS(3, 0, 3),
+ SGPIO_REGS(4, 1, 0),
+ SGPIO_REGS(5, 2, 0),
+};
+
+static struct bcm2712_pinctrl_soc_data bcm2712_d0_aon_data =
+{
+ .num_pins = RT_ARRAY_SIZE(bcm2712_d0_aon_gpio_pins),
+ .desc = bcm2712_d0_aon_gpio_pins,
+ .funcs = bcm2712_d0_aon_gpio_pin_funcs,
+ .regs = bcm2712_d0_aon_gpio_pin_regs,
+};
+
+static const struct rt_ofw_node_id bcm2712_pinctrl_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2712-pinctrl", .data = &bcm2712_c0_data },
+ { .compatible = "brcm,bcm2712-aon-pinctrl", .data = &bcm2712_c0_aon_data },
+ { .compatible = "brcm,bcm2712c0-pinctrl", .data = &bcm2712_c0_data },
+ { .compatible = "brcm,bcm2712c0-aon-pinctrl", .data = &bcm2712_c0_aon_data },
+ { .compatible = "brcm,bcm2712d0-pinctrl", .data = &bcm2712_d0_data },
+ { .compatible = "brcm,bcm2712d0-aon-pinctrl", .data = &bcm2712_d0_aon_data },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2712_pinctrl_driver =
+{
+ .name = "pinctrl-bcm2712",
+ .ids = bcm2712_pinctrl_ofw_ids,
+
+ .probe = bcm2712_pinctrl_probe,
+};
+
+static int bcm2712_pinctrl_register(void)
+{
+ rt_platform_driver_register(&bcm2712_pinctrl_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2712_pinctrl_register);
diff --git a/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2835.c b/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2835.c
new file mode 100755
index 0000000000..2e78c8d3a4
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pinctrl/pinctrl-bcm2835.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pinctrl.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <bitmap.h>
+#include <dev_pin_dm.h>
+#include <dt-bindings/pinctrl/bcm2835.h>
+
+/* GPIO register offsets */
+#define GPFSEL0 0x0 /* Function Select */
+#define GPSET0 0x1c /* Pin Output Set */
+#define GPCLR0 0x28 /* Pin Output Clear */
+#define GPLEV0 0x34 /* Pin Level */
+#define GPEDS0 0x40 /* Pin Event Detect Status */
+#define GPREN0 0x4c /* Pin Rising Edge Detect Enable */
+#define GPFEN0 0x58 /* Pin Falling Edge Detect Enable */
+#define GPHEN0 0x64 /* Pin High Detect Enable */
+#define GPLEN0 0x70 /* Pin Low Detect Enable */
+#define GPAREN0 0x7c /* Pin Async Rising Edge Detect */
+#define GPAFEN0 0x88 /* Pin Async Falling Edge Detect */
+#define GPPUD 0x94 /* Pin Pull-up/down Enable */
+#define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */
+#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
+
+#define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4))
+#define FSEL_SHIFT(p) (((p) % 10) * 3)
+#define GPIO_REG_OFFSET(p) ((p) / 32)
+#define GPIO_REG_SHIFT(p) ((p) % 32)
+
+#define PUD_2711_MASK 0x3
+#define PUD_2711_REG_OFFSET(p) ((p) / 16)
+#define PUD_2711_REG_SHIFT(p) (((p) % 16) * 2)
+
+/* argument: bcm2835_pinconf_pull */
+#define BCM2835_PINCONF_PARAM_PULL (PIN_CONFIG_END + 1)
+
+#define BCM2835_NUM_GPIOS 54
+#define BCM2711_NUM_GPIOS 58
+#define BCM2835_NUM_BANKS 2
+#define BCM2835_NUM_IRQS 3
+
+#define BCM2711_PULL_NONE 0x0
+#define BCM2711_PULL_UP 0x1
+#define BCM2711_PULL_DOWN 0x2
+
+enum
+{
+ SOC_TYPE_BCM2835,
+ SOC_TYPE_BCM2711,
+ SOC_TYPE_BCM7211,
+};
+
+enum bcm2835_fsel
+{
+ BCM2835_FSEL_COUNT = 8,
+ BCM2835_FSEL_MASK = 0x7,
+};
+
+struct bcm2835_pinctrl_soc_data
+{
+ rt_uint32_t soc_type;
+ rt_uint32_t num_gpios;
+};
+
+struct bcm2835_pinctrl
+{
+ struct rt_device_pin parent;
+ const struct bcm2835_pinctrl_soc_data *soc_data;
+
+ void *base;
+ int irqs[BCM2835_NUM_IRQS];
+
+ rt_bitmap_t enabled_irq_map[BCM2835_NUM_BANKS];
+ rt_uint8_t irq_type[BCM2711_NUM_GPIOS];
+
+ struct rt_spinlock irq_lock[BCM2835_NUM_BANKS];
+ struct rt_spinlock fsel_lock; /* Protect FSEL registers */
+};
+
+#define raw_to_bcm2835_pinctrl(raw) rt_container_of(raw, struct bcm2835_pinctrl, parent)
+
+rt_inline rt_uint32_t bcm2835_gpio_rd(struct bcm2835_pinctrl *pc, int reg)
+{
+ return HWREG32(pc->base + reg);
+}
+
+rt_inline void bcm2835_gpio_wr(struct bcm2835_pinctrl *pc, int reg, rt_uint32_t val)
+{
+ HWREG32(pc->base + reg) = val;
+}
+
+rt_inline int bcm2835_gpio_get_bit(struct bcm2835_pinctrl *pc, int reg, int bit)
+{
+ reg += GPIO_REG_OFFSET(bit) * 4;
+ return (bcm2835_gpio_rd(pc, reg) >> GPIO_REG_SHIFT(bit)) & 1;
+}
+
+/* note NOT a read/modify/write cycle */
+rt_inline void bcm2835_gpio_set_bit(struct bcm2835_pinctrl *pc, int reg, int bit)
+{
+ reg += GPIO_REG_OFFSET(bit) * 4;
+ bcm2835_gpio_wr(pc, reg, RT_BIT(GPIO_REG_SHIFT(bit)));
+}
+
+rt_inline enum bcm2835_fsel bcm2835_pinctrl_fsel_get(struct bcm2835_pinctrl *pc,
+ rt_ubase_t pin)
+{
+ rt_uint32_t val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
+
+ return (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
+}
+
+static void bcm2835_pinctrl_fsel_set(struct bcm2835_pinctrl *pc, rt_ubase_t pin,
+ enum bcm2835_fsel fsel)
+{
+ rt_uint32_t val;
+ rt_ubase_t level;
+ enum bcm2835_fsel cur;
+
+ level = rt_spin_lock_irqsave(&pc->fsel_lock);
+
+ val = bcm2835_gpio_rd(pc, FSEL_REG(pin));
+ cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK;
+
+ if (cur == fsel)
+ {
+ goto _out_lock;
+ }
+
+ if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN)
+ {
+ /* Always transition through GPIO_IN */
+ val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
+ val |= BCM2835_FSEL_GPIO_IN << FSEL_SHIFT(pin);
+
+ bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
+ }
+
+ val &= ~(BCM2835_FSEL_MASK << FSEL_SHIFT(pin));
+ val |= fsel << FSEL_SHIFT(pin);
+
+ bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
+
+_out_lock:
+ rt_spin_unlock_irqrestore(&pc->fsel_lock, level);
+}
+
+static void bcm2835_gpio_irq_config_reg(struct bcm2835_pinctrl *pc,
+ int reg, int offset, rt_bool_t enable)
+{
+ rt_uint32_t value;
+
+ reg += GPIO_REG_OFFSET(offset) * 4;
+ value = bcm2835_gpio_rd(pc, reg);
+
+ if (enable)
+ {
+ value |= RT_BIT(GPIO_REG_SHIFT(offset));
+ }
+ else
+ {
+ value &= ~(RT_BIT(GPIO_REG_SHIFT(offset)));
+ }
+
+ bcm2835_gpio_wr(pc, reg, value);
+}
+
+/* fast path for IRQ handler */
+static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, int offset, rt_bool_t enable)
+{
+ switch (pc->irq_type[offset])
+ {
+ case PIN_IRQ_MODE_RISING:
+ bcm2835_gpio_irq_config_reg(pc, GPREN0, offset, enable);
+ break;
+
+ case PIN_IRQ_MODE_FALLING:
+ bcm2835_gpio_irq_config_reg(pc, GPFEN0, offset, enable);
+ break;
+
+ case PIN_IRQ_MODE_RISING_FALLING:
+ bcm2835_gpio_irq_config_reg(pc, GPREN0, offset, enable);
+ bcm2835_gpio_irq_config_reg(pc, GPFEN0, offset, enable);
+ break;
+
+ case PIN_IRQ_MODE_HIGH_LEVEL:
+ bcm2835_gpio_irq_config_reg(pc, GPHEN0, offset, enable);
+ break;
+
+ case PIN_IRQ_MODE_LOW_LEVEL:
+ bcm2835_gpio_irq_config_reg(pc, GPLEN0, offset, enable);
+ break;
+ }
+}
+
+static rt_err_t bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
+ int offset, rt_uint8_t type)
+{
+ switch (type)
+ {
+ case PIN_IRQ_MODE_RISING:
+ if (pc->irq_type[offset] == PIN_IRQ_MODE_RISING_FALLING)
+ {
+ /* RISING already enabled, disable FALLING */
+ pc->irq_type[offset] = PIN_IRQ_MODE_FALLING;
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ }
+ else if (pc->irq_type[offset] != type)
+ {
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ }
+ break;
+
+ case PIN_IRQ_MODE_FALLING:
+ if (pc->irq_type[offset] == PIN_IRQ_MODE_RISING_FALLING)
+ {
+ /* FALLING already enabled, disable RISING */
+ pc->irq_type[offset] = PIN_IRQ_MODE_RISING;
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ }
+ else if (pc->irq_type[offset] != type)
+ {
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ }
+ break;
+
+ case PIN_IRQ_MODE_RISING_FALLING:
+ if (pc->irq_type[offset] == PIN_IRQ_MODE_RISING)
+ {
+ /* RISING already enabled, enable FALLING too */
+ pc->irq_type[offset] = PIN_IRQ_MODE_FALLING;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ pc->irq_type[offset] = type;
+ }
+ else if (pc->irq_type[offset] == PIN_IRQ_MODE_FALLING)
+ {
+ /* FALLING already enabled, enable RISING too */
+ pc->irq_type[offset] = PIN_IRQ_MODE_RISING;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ pc->irq_type[offset] = type;
+ }
+ else if (pc->irq_type[offset] != type)
+ {
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ }
+ break;
+
+ case PIN_IRQ_MODE_HIGH_LEVEL:
+ case PIN_IRQ_MODE_LOW_LEVEL:
+ if (pc->irq_type[offset] != type)
+ {
+ bcm2835_gpio_irq_config(pc, offset, RT_FALSE);
+ pc->irq_type[offset] = type;
+ bcm2835_gpio_irq_config(pc, offset, RT_TRUE);
+ }
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_gpio_irq_set_type_disabled(struct bcm2835_pinctrl *pc,
+ int offset, rt_uint8_t type)
+{
+ switch (type)
+ {
+ case PIN_IRQ_MODE_RISING:
+ case PIN_IRQ_MODE_FALLING:
+ case PIN_IRQ_MODE_RISING_FALLING:
+ case PIN_IRQ_MODE_HIGH_LEVEL:
+ case PIN_IRQ_MODE_LOW_LEVEL:
+ pc->irq_type[offset] = type;
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+
+ return RT_EOK;
+}
+
+static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc, int pin, rt_uint32_t arg)
+{
+ rt_uint32_t off, bit;
+
+ off = GPIO_REG_OFFSET(pin);
+ bit = GPIO_REG_SHIFT(pin);
+
+ bcm2835_gpio_wr(pc, GPPUD, arg & 3);
+ /*
+ * BCM2835 datasheet say to wait 150 cycles, but not of what.
+ * But the VideoCore firmware delay for this operation
+ * based nearly on the same amount of VPU cycles and this clock
+ * runs at 250 MHz.
+ */
+ rt_hw_us_delay(1);
+ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), RT_BIT(bit));
+ rt_hw_us_delay(1);
+ bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
+}
+
+static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc, int pin, rt_uint32_t arg)
+{
+ rt_uint32_t shifter, value, off;
+
+ off = PUD_2711_REG_OFFSET(pin);
+ shifter = PUD_2711_REG_SHIFT(pin);
+
+ value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4));
+ value &= ~(PUD_2711_MASK << shifter);
+ value |= (arg << shifter);
+ bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value);
+}
+
+static void bcm2835_pinctrl_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ switch (mode)
+ {
+ case PIN_MODE_OUTPUT:
+ bcm2835_pinctrl_fsel_set(pc, pin, BCM2835_FSEL_GPIO_OUT);
+ break;
+
+ case PIN_MODE_INPUT:
+ bcm2835_pinctrl_fsel_set(pc, pin, BCM2835_FSEL_GPIO_IN);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void bcm2835_pinctrl_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
+{
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, pin);
+}
+
+static rt_ssize_t bcm2835_pinctrl_read(struct rt_device *device, rt_base_t pin)
+{
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ return bcm2835_gpio_get_bit(pc, GPLEV0, pin);
+}
+
+static rt_err_t bcm2835_pinctrl_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
+{
+ rt_ubase_t level;
+ rt_uint32_t offset, bank;
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ offset = GPIO_REG_SHIFT(pin);
+ bank = GPIO_REG_OFFSET(pin);
+
+ level = rt_spin_lock_irqsave(&pc->irq_lock[bank]);
+
+ if (enabled)
+ {
+ rt_bitmap_set_bit(&pc->enabled_irq_map[bank], offset);
+ bcm2835_gpio_irq_config(pc, pin, RT_TRUE);
+ }
+ else
+ {
+ bcm2835_gpio_irq_config(pc, pin, RT_FALSE);
+ /* Clear events that were latched prior to clearing event sources */
+ bcm2835_gpio_set_bit(pc, GPEDS0, pin);
+ rt_bitmap_clear_bit(&pc->enabled_irq_map[bank], offset);
+ }
+
+ rt_spin_unlock_irqrestore(&pc->irq_lock[bank], level);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_pinctrl_irq_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ rt_err_t err;
+ rt_ubase_t level;
+ rt_uint32_t offset, bank;
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ offset = GPIO_REG_SHIFT(pin);
+ bank = GPIO_REG_OFFSET(pin);
+
+ level = rt_spin_lock_irqsave(&pc->irq_lock[bank]);
+
+ if (rt_bitmap_test_bit(&pc->enabled_irq_map[bank], offset))
+ {
+ err = bcm2835_gpio_irq_set_type_enabled(pc, pin, mode);
+ }
+ else
+ {
+ err = bcm2835_gpio_irq_set_type_disabled(pc, pin, mode);
+ }
+
+ rt_spin_unlock_irqrestore(&pc->irq_lock[bank], level);
+
+ return err;
+}
+
+static rt_err_t bcm2835_pinctrl_confs_apply(struct rt_device *device, void *fw_conf_np)
+{
+ int pin;
+ rt_err_t err;
+ const fdt32_t *cell;
+ rt_uint32_t value, idx;
+ enum bcm2835_fsel fsel;
+ struct rt_ofw_prop *prop;
+ struct rt_ofw_node *conf_np = fw_conf_np;
+ struct bcm2835_pinctrl *pc = raw_to_bcm2835_pinctrl(device);
+
+ if ((err = rt_ofw_prop_read_u32(conf_np, "brcm,function", &value)))
+ {
+ return err;
+ }
+ fsel = value;
+
+ idx = 0;
+ rt_ofw_foreach_prop_u32(conf_np, "brcm,pins", prop, cell, value)
+ {
+ if (prop->length < sizeof(*cell))
+ {
+ break;
+ }
+
+ pin = value;
+ bcm2835_pinctrl_fsel_set(pc, pin, fsel);
+
+ if (rt_ofw_prop_read_u32_index(conf_np, "brcm,pull", idx++, &value))
+ {
+ continue;
+ }
+
+ if (pc->soc_data->soc_type == SOC_TYPE_BCM2835)
+ {
+ bcm2835_pull_config_set(pc, pin, value);
+ }
+ else
+ {
+ bcm2711_pull_config_set(pc, pin, value);
+ }
+ }
+
+ return RT_EOK;
+}
+
+static const struct rt_pin_ops bcm2835_pinctrl_ops =
+{
+ .pin_mode = bcm2835_pinctrl_mode,
+ .pin_write = bcm2835_pinctrl_write,
+ .pin_read = bcm2835_pinctrl_read,
+ .pin_irq_enable = bcm2835_pinctrl_irq_enable,
+ .pin_irq_mode = bcm2835_pinctrl_irq_mode,
+ .pin_ctrl_confs_apply = bcm2835_pinctrl_confs_apply,
+};
+
+static void bcm2835_gpio_bank_isr(struct bcm2835_pinctrl *pc, int bank, rt_uint32_t mask)
+{
+ rt_ubase_t events;
+ rt_uint32_t offset, gpio, levs, levs2;
+
+ events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+ levs = bcm2835_gpio_rd(pc, GPLEV0 + bank * 4);
+ events &= mask;
+ events &= pc->enabled_irq_map[bank];
+ bcm2835_gpio_wr(pc, GPEDS0 + bank * 4, events);
+
+_retry:
+ rt_bitmap_for_each_set_bit(&events, offset, 32)
+ {
+ gpio = (32 * bank) + offset;
+
+ pin_pic_handle_isr(&pc->parent, gpio);
+ }
+
+ events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+ levs2 = bcm2835_gpio_rd(pc, GPLEV0 + bank * 4);
+
+ events |= levs2 & ~levs & bcm2835_gpio_rd(pc, GPREN0 + bank * 4);
+ events |= ~levs2 & levs & bcm2835_gpio_rd(pc, GPFEN0 + bank * 4);
+ events &= mask;
+ events &= pc->enabled_irq_map[bank];
+
+ if (events)
+ {
+ bcm2835_gpio_wr(pc, GPEDS0 + bank * 4, events);
+ levs = levs2;
+ goto _retry;
+ }
+}
+
+static void bcm2835_pinctrl_isr(int irq, void *param)
+{
+ int group = 0;
+ struct bcm2835_pinctrl *pc = param;
+
+ for (int i = 0; i < BCM2835_NUM_IRQS; ++i)
+ {
+ if (pc->irqs[i] == irq)
+ {
+ group = i;
+ break;
+ }
+ }
+
+ switch (group)
+ {
+ case 0: /* IRQ0 covers GPIOs 0-27 */
+ bcm2835_gpio_bank_isr(pc, 0, 0x0fffffff);
+ break;
+
+ case 1: /* IRQ1 covers GPIOs 28-45 */
+ bcm2835_gpio_bank_isr(pc, 0, 0xf0000000);
+ bcm2835_gpio_bank_isr(pc, 1, 0x00003fff);
+ break;
+
+ case 2: /* IRQ2 covers GPIOs 46-57 */
+ bcm2835_gpio_bank_isr(pc, 1, 0x003fc000);
+ break;
+ }
+}
+
+static rt_err_t bcm2835_pinctrl_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node;
+ const struct bcm2835_pinctrl_soc_data *soc_data;
+ struct bcm2835_pinctrl *pc = rt_calloc(1, sizeof(*pc));
+
+ if (!pc)
+ {
+ return -RT_ENOMEM;
+ }
+ soc_data = pdev->id->data;
+ pc->soc_data = soc_data;
+
+ if (!(pc->base = rt_dm_dev_iomap(dev, 0)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ rt_spin_lock_init(&pc->fsel_lock);
+
+ for (int i = 0; i < BCM2835_NUM_BANKS; ++i)
+ {
+ int offset;
+ rt_ubase_t events;
+
+ /* clear event detection flags */
+ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0);
+ bcm2835_gpio_wr(pc, GPFEN0 + i * 4, 0);
+ bcm2835_gpio_wr(pc, GPHEN0 + i * 4, 0);
+ bcm2835_gpio_wr(pc, GPLEN0 + i * 4, 0);
+ bcm2835_gpio_wr(pc, GPAREN0 + i * 4, 0);
+ bcm2835_gpio_wr(pc, GPAFEN0 + i * 4, 0);
+
+ /* clear all the events */
+ events = bcm2835_gpio_rd(pc, GPEDS0 + i * 4);
+ rt_bitmap_for_each_set_bit(&events, offset, 32)
+ {
+ bcm2835_gpio_wr(pc, GPEDS0 + i * 4, RT_BIT(offset));
+ }
+
+ rt_spin_lock_init(&pc->irq_lock[i]);
+ }
+
+ pc->parent.ops = &bcm2835_pinctrl_ops;
+ pin_api_init(&pc->parent, soc_data->num_gpios);
+ pin_pic_init(&pc->parent, pc->irqs[0]);
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pc->irqs); ++i)
+ {
+ pc->irqs[i] = rt_dm_dev_get_irq(dev, i);
+
+ if (soc_data->soc_type != SOC_TYPE_BCM7211)
+ {
+ if (pc->irqs[i] < 0)
+ {
+ break;
+ }
+
+ continue;
+ }
+ else if (pc->irqs[i] < 0)
+ {
+ err = pc->irqs[i];
+ goto _fail;
+ }
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(pc->irqs); ++i)
+ {
+ int irq = pc->irqs[i];
+
+ if (irq < 0)
+ {
+ break;
+ }
+
+ rt_hw_interrupt_install(irq, bcm2835_pinctrl_isr, pc, "bcm2835-pinctrl");
+ rt_hw_interrupt_umask(irq);
+ }
+
+ rt_ofw_data(np) = &pc->parent;
+
+ return RT_EOK;
+
+_fail:
+ rt_free(pc);
+
+ return err;
+}
+
+static struct bcm2835_pinctrl_soc_data bcm2835_data =
+{
+ .soc_type = SOC_TYPE_BCM2835,
+ .num_gpios = BCM2835_NUM_GPIOS,
+};
+
+static struct bcm2835_pinctrl_soc_data bcm2711_data =
+{
+ .soc_type = SOC_TYPE_BCM2711,
+ .num_gpios = BCM2711_NUM_GPIOS,
+};
+
+static struct bcm2835_pinctrl_soc_data bcm7211_data =
+{
+ .soc_type = SOC_TYPE_BCM7211,
+ .num_gpios = BCM2711_NUM_GPIOS,
+};
+
+static const struct rt_ofw_node_id bcm2835_pinctrl_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-gpio", .data = &bcm2835_data },
+ { .compatible = "brcm,bcm2711-gpio", .data = &bcm2711_data },
+ { .compatible = "brcm,bcm7211-gpio", .data = &bcm7211_data },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_pinctrl_driver =
+{
+ .name = "pinctrl-bcm2835",
+ .ids = bcm2835_pinctrl_ofw_ids,
+
+ .probe = bcm2835_pinctrl_probe,
+};
+
+static int bcm2835_pinctrl_register(void)
+{
+ rt_platform_driver_register(&bcm2835_pinctrl_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_pinctrl_register);
diff --git a/bsp/raspberry-pi/dm/pinctrl/pinctrl-rp1.c b/bsp/raspberry-pi/dm/pinctrl/pinctrl-rp1.c
new file mode 100755
index 0000000000..a829009de3
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pinctrl/pinctrl-rp1.c
@@ -0,0 +1,925 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pinctrl.rp1"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <bitmap.h>
+#include <dev_pin_dm.h>
+
+#define RP1_NUM_GPIOS 54
+#define RP1_NUM_BANKS 3
+
+#define RP1_RW_OFFSET 0x0000
+#define RP1_XOR_OFFSET 0x1000
+#define RP1_SET_OFFSET 0x2000
+#define RP1_CLR_OFFSET 0x3000
+
+#define RP1_GPIO_STATUS 0x0000
+#define RP1_GPIO_CTRL 0x0004
+
+#define RP1_GPIO_PCIE_INTE 0x011c
+#define RP1_GPIO_PCIE_INTS 0x0124
+
+#define RP1_GPIO_EVENTS_SHIFT_RAW 20
+#define RP1_GPIO_STATUS_FALLING RT_BIT(20)
+#define RP1_GPIO_STATUS_RISING RT_BIT(21)
+#define RP1_GPIO_STATUS_LOW RT_BIT(22)
+#define RP1_GPIO_STATUS_HIGH RT_BIT(23)
+
+#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24
+#define RP1_GPIO_STATUS_F_FALLING RT_BIT(24)
+#define RP1_GPIO_STATUS_F_RISING RT_BIT(25)
+#define RP1_GPIO_STATUS_F_LOW RT_BIT(26)
+#define RP1_GPIO_STATUS_F_HIGH RT_BIT(27)
+
+#define RP1_GPIO_CTRL_FUNCSEL_LSB 0
+#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f
+#define RP1_GPIO_CTRL_OUTOVER_LSB 12
+#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000
+#define RP1_GPIO_CTRL_OEOVER_LSB 14
+#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000
+#define RP1_GPIO_CTRL_INOVER_LSB 16
+#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000
+#define RP1_GPIO_CTRL_IRQEN_FALLING RT_BIT(20)
+#define RP1_GPIO_CTRL_IRQEN_RISING RT_BIT(21)
+#define RP1_GPIO_CTRL_IRQEN_LOW RT_BIT(22)
+#define RP1_GPIO_CTRL_IRQEN_HIGH RT_BIT(23)
+#define RP1_GPIO_CTRL_IRQEN_F_FALLING RT_BIT(24)
+#define RP1_GPIO_CTRL_IRQEN_F_RISING RT_BIT(25)
+#define RP1_GPIO_CTRL_IRQEN_F_LOW RT_BIT(26)
+#define RP1_GPIO_CTRL_IRQEN_F_HIGH RT_BIT(27)
+#define RP1_GPIO_CTRL_IRQRESET RT_BIT(28)
+#define RP1_GPIO_CTRL_IRQOVER_LSB 30
+#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000
+
+#define RP1_INT_EDGE_FALLING RT_BIT(0)
+#define RP1_INT_EDGE_RISING RT_BIT(1)
+#define RP1_INT_LEVEL_LOW RT_BIT(2)
+#define RP1_INT_LEVEL_HIGH RT_BIT(3)
+#define RP1_INT_MASK 0xf
+
+#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | RP1_INT_EDGE_RISING)
+#define RP1_PUD_OFF 0
+#define RP1_PUD_DOWN 1
+#define RP1_PUD_UP 2
+
+#define RP1_FSEL_COUNT 9
+
+#define RP1_FSEL_ALT0 0x00
+#define RP1_FSEL_GPIO 0x05
+#define RP1_FSEL_NONE 0x09
+#define RP1_FSEL_NONE_HW 0x1f
+
+#define RP1_DIR_OUTPUT 0
+#define RP1_DIR_INPUT 1
+
+#define RP1_OUTOVER_PERI 0
+#define RP1_OUTOVER_INVPERI 1
+#define RP1_OUTOVER_LOW 2
+#define RP1_OUTOVER_HIGH 3
+
+#define RP1_OEOVER_PERI 0
+#define RP1_OEOVER_INVPERI 1
+#define RP1_OEOVER_DISABLE 2
+#define RP1_OEOVER_ENABLE 3
+
+#define RP1_INOVER_PERI 0
+#define RP1_INOVER_INVPERI 1
+#define RP1_INOVER_LOW 2
+#define RP1_INOVER_HIGH 3
+
+#define RP1_RIO_OUT 0x00
+#define RP1_RIO_OE 0x04
+#define RP1_RIO_IN 0x08
+
+#define RP1_PAD_SLEWFAST_MASK 0x00000001
+#define RP1_PAD_SLEWFAST_LSB 0
+#define RP1_PAD_SCHMITT_MASK 0x00000002
+#define RP1_PAD_SCHMITT_LSB 1
+#define RP1_PAD_PULL_MASK 0x0000000c
+#define RP1_PAD_PULL_LSB 2
+#define RP1_PAD_DRIVE_MASK 0x00000030
+#define RP1_PAD_DRIVE_LSB 4
+#define RP1_PAD_IN_ENABLE_MASK 0x00000040
+#define RP1_PAD_IN_ENABLE_LSB 6
+#define RP1_PAD_OUT_DISABLE_MASK 0x00000080
+#define RP1_PAD_OUT_DISABLE_LSB 7
+
+#define RP1_PAD_DRIVE_2MA 0x00000000
+#define RP1_PAD_DRIVE_4MA 0x00000010
+#define RP1_PAD_DRIVE_8MA 0x00000020
+#define RP1_PAD_DRIVE_12MA 0x00000030
+
+#define FLD_GET(r, f) (((r) & (f ## _MASK)) >> (f ## _LSB))
+#define FLD_SET(r, f, v) r = (((r) & ~(f ## _MASK)) | ((v) << (f ## _LSB)))
+
+enum rp1_funcs
+{
+ func_alt0,
+ func_alt1,
+ func_alt2,
+ func_alt3,
+ func_alt4,
+ func_gpio,
+ func_alt6,
+ func_alt7,
+ func_alt8,
+ func_none,
+ func_aaud,
+ func_dcd0,
+ func_dpi,
+ func_dsi0_te_ext,
+ func_dsi1_te_ext,
+ func_dsr0,
+ func_dtr0,
+ func_gpclk0,
+ func_gpclk1,
+ func_gpclk2,
+ func_gpclk3,
+ func_gpclk4,
+ func_gpclk5,
+ func_i2c0,
+ func_i2c1,
+ func_i2c2,
+ func_i2c3,
+ func_i2c4,
+ func_i2c5,
+ func_i2c6,
+ func_i2s0,
+ func_i2s1,
+ func_i2s2,
+ func_ir,
+ func_mic,
+ func_pcie_clkreq_n,
+ func_pio,
+ func_proc_rio,
+ func_pwm0,
+ func_pwm1,
+ func_ri0,
+ func_sd0,
+ func_sd1,
+ func_spi0,
+ func_spi1,
+ func_spi2,
+ func_spi3,
+ func_spi4,
+ func_spi5,
+ func_spi6,
+ func_spi7,
+ func_spi8,
+ func_uart0,
+ func_uart1,
+ func_uart2,
+ func_uart3,
+ func_uart4,
+ func_uart5,
+ func_vbus0,
+ func_vbus1,
+ func_vbus2,
+ func_vbus3,
+ func__,
+ func_count = func__,
+};
+
+struct rp1_pin_funcs
+{
+#define PIN(i, f0, f1, f2, f3, f4, f5, f6, f7, f8) \
+ [i] = { \
+ .funcs = { \
+ func_##f0, \
+ func_##f1, \
+ func_##f2, \
+ func_##f3, \
+ func_##f4, \
+ func_##f5, \
+ func_##f6, \
+ func_##f7, \
+ func_##f8, \
+ }, \
+ }
+ rt_uint8_t funcs[RP1_FSEL_COUNT];
+};
+
+struct rp1_pin_desc
+{
+ rt_uint32_t number;
+ const char *name;
+};
+
+struct rp1_iobank_desc
+{
+ int min_gpio;
+ int num_gpios;
+ int gpio_offset;
+ int inte_offset;
+ int ints_offset;
+ int rio_offset;
+ int pads_offset;
+};
+
+struct rp1_pinctrl;
+
+struct rp1_pin_info
+{
+ rt_uint8_t num;
+ rt_uint8_t bank;
+ rt_uint8_t offset;
+ rt_uint8_t fsel;
+ rt_uint8_t irq_type;
+
+ void *gpio;
+ void *rio;
+ void *inte;
+ void *ints;
+ void *pad;
+};
+
+struct rp1_pinctrl
+{
+ struct rt_device_pin parent;
+
+ void *gpio_base;
+ void *rio_base;
+ void *pads_base;
+ int irqs[RP1_NUM_BANKS];
+ struct rp1_pin_info pins[RP1_NUM_GPIOS];
+ struct rt_spinlock irq_lock[RP1_NUM_BANKS];
+};
+
+#define raw_to_rp1_pinctrl(raw) rt_container_of(raw, struct rp1_pinctrl, parent)
+
+/* Pins are just named GPIO0..GPIO53 */
+static struct rp1_pin_desc rp1_gpio_pins[] =
+{
+#define RP1_GPIO_PIN(a) { a, "gpio" #a }
+ RP1_GPIO_PIN(0),
+ RP1_GPIO_PIN(1),
+ RP1_GPIO_PIN(2),
+ RP1_GPIO_PIN(3),
+ RP1_GPIO_PIN(4),
+ RP1_GPIO_PIN(5),
+ RP1_GPIO_PIN(6),
+ RP1_GPIO_PIN(7),
+ RP1_GPIO_PIN(8),
+ RP1_GPIO_PIN(9),
+ RP1_GPIO_PIN(10),
+ RP1_GPIO_PIN(11),
+ RP1_GPIO_PIN(12),
+ RP1_GPIO_PIN(13),
+ RP1_GPIO_PIN(14),
+ RP1_GPIO_PIN(15),
+ RP1_GPIO_PIN(16),
+ RP1_GPIO_PIN(17),
+ RP1_GPIO_PIN(18),
+ RP1_GPIO_PIN(19),
+ RP1_GPIO_PIN(20),
+ RP1_GPIO_PIN(21),
+ RP1_GPIO_PIN(22),
+ RP1_GPIO_PIN(23),
+ RP1_GPIO_PIN(24),
+ RP1_GPIO_PIN(25),
+ RP1_GPIO_PIN(26),
+ RP1_GPIO_PIN(27),
+ RP1_GPIO_PIN(28),
+ RP1_GPIO_PIN(29),
+ RP1_GPIO_PIN(30),
+ RP1_GPIO_PIN(31),
+ RP1_GPIO_PIN(32),
+ RP1_GPIO_PIN(33),
+ RP1_GPIO_PIN(34),
+ RP1_GPIO_PIN(35),
+ RP1_GPIO_PIN(36),
+ RP1_GPIO_PIN(37),
+ RP1_GPIO_PIN(38),
+ RP1_GPIO_PIN(39),
+ RP1_GPIO_PIN(40),
+ RP1_GPIO_PIN(41),
+ RP1_GPIO_PIN(42),
+ RP1_GPIO_PIN(43),
+ RP1_GPIO_PIN(44),
+ RP1_GPIO_PIN(45),
+ RP1_GPIO_PIN(46),
+ RP1_GPIO_PIN(47),
+ RP1_GPIO_PIN(48),
+ RP1_GPIO_PIN(49),
+ RP1_GPIO_PIN(50),
+ RP1_GPIO_PIN(51),
+ RP1_GPIO_PIN(52),
+ RP1_GPIO_PIN(53),
+#undef RP1_GPIO_PIN
+};
+
+static const char * const rp1_func_names[] =
+{
+#define FUNC_NAME(name) [func_##name] = #name
+ FUNC_NAME(alt0),
+ FUNC_NAME(alt1),
+ FUNC_NAME(alt2),
+ FUNC_NAME(alt3),
+ FUNC_NAME(alt4),
+ FUNC_NAME(gpio),
+ FUNC_NAME(alt6),
+ FUNC_NAME(alt7),
+ FUNC_NAME(alt8),
+ FUNC_NAME(none),
+ FUNC_NAME(aaud),
+ FUNC_NAME(dcd0),
+ FUNC_NAME(dpi),
+ FUNC_NAME(dsi0_te_ext),
+ FUNC_NAME(dsi1_te_ext),
+ FUNC_NAME(dsr0),
+ FUNC_NAME(dtr0),
+ FUNC_NAME(gpclk0),
+ FUNC_NAME(gpclk1),
+ FUNC_NAME(gpclk2),
+ FUNC_NAME(gpclk3),
+ FUNC_NAME(gpclk4),
+ FUNC_NAME(gpclk5),
+ FUNC_NAME(i2c0),
+ FUNC_NAME(i2c1),
+ FUNC_NAME(i2c2),
+ FUNC_NAME(i2c3),
+ FUNC_NAME(i2c4),
+ FUNC_NAME(i2c5),
+ FUNC_NAME(i2c6),
+ FUNC_NAME(i2s0),
+ FUNC_NAME(i2s1),
+ FUNC_NAME(i2s2),
+ FUNC_NAME(ir),
+ FUNC_NAME(mic),
+ FUNC_NAME(pcie_clkreq_n),
+ FUNC_NAME(pio),
+ FUNC_NAME(proc_rio),
+ FUNC_NAME(pwm0),
+ FUNC_NAME(pwm1),
+ FUNC_NAME(ri0),
+ FUNC_NAME(sd0),
+ FUNC_NAME(sd1),
+ FUNC_NAME(spi0),
+ FUNC_NAME(spi1),
+ FUNC_NAME(spi2),
+ FUNC_NAME(spi3),
+ FUNC_NAME(spi4),
+ FUNC_NAME(spi5),
+ FUNC_NAME(spi6),
+ FUNC_NAME(spi7),
+ FUNC_NAME(spi8),
+ FUNC_NAME(uart0),
+ FUNC_NAME(uart1),
+ FUNC_NAME(uart2),
+ FUNC_NAME(uart3),
+ FUNC_NAME(uart4),
+ FUNC_NAME(uart5),
+ FUNC_NAME(vbus0),
+ FUNC_NAME(vbus1),
+ FUNC_NAME(vbus2),
+ FUNC_NAME(vbus3),
+#undef FUNC_NAME
+};
+
+static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] =
+{
+ PIN(0, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2),
+ PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2),
+ PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
+ PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
+ PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3),
+ PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3),
+ PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3),
+ PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3),
+ PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
+ PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
+ PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4),
+ PIN(11, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4),
+ PIN(12, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5),
+ PIN(13, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5),
+ PIN(14, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5),
+ PIN(15, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5),
+ PIN(16, spi1, dpi, dsi0_te_ext, _, uart0, gpio, proc_rio, pio, _),
+ PIN(17, spi1, dpi, dsi1_te_ext, _, uart0, gpio, proc_rio, pio, _),
+ PIN(18, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, gpclk1),
+ PIN(19, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, _),
+ PIN(20, spi1, dpi, i2s0, gpclk0, i2s1, gpio, proc_rio, pio, _),
+ PIN(21, spi1, dpi, i2s0, gpclk1, i2s1, gpio, proc_rio, pio, _),
+ PIN(22, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _),
+ PIN(23, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _),
+ PIN(24, sd0, dpi, i2s0, _, i2s1, gpio, proc_rio, pio, spi2),
+ PIN(25, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi3),
+ PIN(26, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi5),
+ PIN(27, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi1),
+ PIN(28, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _),
+ PIN(29, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _),
+ PIN(30, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _),
+ PIN(31, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _),
+ PIN(32, sd1, gpclk3, i2s2, spi6, uart5, gpio, proc_rio, _, _),
+ PIN(33, sd1, gpclk4, i2s2, spi6, uart5, gpio, proc_rio, _, _),
+ PIN(34, pwm1, gpclk3, vbus0, i2c4, mic, gpio, proc_rio, _, _),
+ PIN(35, spi8, pwm1, vbus0, i2c4, mic, gpio, proc_rio, _, _),
+ PIN(36, spi8, uart5, pcie_clkreq_n, i2c5, mic, gpio, proc_rio, _, _),
+ PIN(37, spi8, uart5, mic, i2c5, pcie_clkreq_n, gpio, proc_rio, _, _),
+ PIN(38, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi0_te_ext, _),
+ PIN(39, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi1_te_ext, _),
+ PIN(40, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _),
+ PIN(41, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _),
+ PIN(42, gpclk5, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _),
+ PIN(43, gpclk4, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _),
+ PIN(44, gpclk5, i2c5, pwm1, spi6, i2s2, gpio, proc_rio, _, _),
+ PIN(45, pwm1, i2c5, spi7, spi6, i2s2, gpio, proc_rio, _, _),
+ PIN(46, gpclk3, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi0_te_ext, _),
+ PIN(47, gpclk5, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi1_te_ext, _),
+ PIN(48, pwm1, pcie_clkreq_n, spi7, mic, uart5, gpio, proc_rio, _, _),
+ PIN(49, spi8, spi7, i2c5, aaud, uart5, gpio, proc_rio, _, _),
+ PIN(50, spi8, spi7, i2c5, aaud, vbus2, gpio, proc_rio, _, _),
+ PIN(51, spi8, spi7, i2c6, aaud, vbus2, gpio, proc_rio, _, _),
+ PIN(52, spi8, _, i2c6, aaud, vbus3, gpio, proc_rio, _, _),
+ PIN(53, spi8, spi7, _, pcie_clkreq_n, vbus3, gpio, proc_rio, _, _),
+};
+
+static const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] =
+{
+ /* gpio inte ints rio pads */
+ { 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 },
+ { 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 },
+ { 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 },
+};
+
+static void rp1_pad_update(struct rp1_pin_info *pin, rt_uint32_t clr, rt_uint32_t set)
+{
+ rt_uint32_t padctrl = HWREG32(pin->pad);
+
+ padctrl &= ~clr;
+ padctrl |= set;
+
+ HWREG32(pin->pad) = padctrl;
+}
+
+static void rp1_input_enable(struct rp1_pin_info *pin, int value)
+{
+ rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK, value ? RP1_PAD_IN_ENABLE_MASK : 0);
+}
+
+static void rp1_output_enable(struct rp1_pin_info *pin, int value)
+{
+ rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK, value ? 0 : RP1_PAD_OUT_DISABLE_MASK);
+}
+
+static void rp1_set_fsel(struct rp1_pin_info *pin, rt_uint32_t fsel)
+{
+ rt_uint32_t ctrl = HWREG32(pin->gpio + RP1_GPIO_CTRL);
+
+ if (fsel >= RP1_FSEL_COUNT)
+ {
+ fsel = RP1_FSEL_NONE_HW;
+ }
+
+ rp1_input_enable(pin, 1);
+ rp1_output_enable(pin, 1);
+
+ if (fsel == RP1_FSEL_NONE)
+ {
+ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_DISABLE);
+ }
+ else
+ {
+ FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI);
+ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI);
+ }
+
+ FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel);
+ HWREG32(pin->gpio + RP1_GPIO_CTRL) = ctrl;
+}
+
+static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
+{
+ rt_uint32_t padctrl = HWREG32(pin->pad);
+
+ FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3);
+
+ HWREG32(pin->pad) = padctrl;
+}
+
+static const struct rt_pin_ctrl_conf_params rp1_conf_params[] =
+{
+ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+};
+
+static rt_err_t rp1_pinctrl_confs_apply_once(struct rp1_pinctrl *pc, struct rt_ofw_node *np)
+{
+ rt_err_t err = RT_EOK;
+ const char *string;
+ rt_uint32_t pin, fsel, strength, slew;
+ struct rt_ofw_prop *prop;
+ struct rp1_pin_info *pini;
+ enum rp1_funcs func = func_count;
+ const struct rt_pin_ctrl_conf_params *conf = RT_NULL;
+
+ if (rt_ofw_prop_read_string(np, "function", &string))
+ {
+ return -RT_EINVAL;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(rp1_func_names); ++i)
+ {
+ if (!rt_strcmp(string, rp1_func_names[i]))
+ {
+ func = (enum rp1_funcs)i;
+ break;
+ }
+ }
+
+ if (func == func_count)
+ {
+ return -RT_EINVAL;
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(rp1_conf_params); ++i)
+ {
+ if (rt_ofw_prop_read_bool(np, rp1_conf_params[i].propname))
+ {
+ conf = &rp1_conf_params[i];
+ break;
+ }
+ }
+
+ strength = RT_UINT32_MAX;
+ if (!rt_ofw_prop_read_u32(np, "drive-strength", &strength))
+ {
+ switch (strength)
+ {
+ case 2: strength = RP1_PAD_DRIVE_2MA; break;
+ case 4: strength = RP1_PAD_DRIVE_4MA; break;
+ case 8: strength = RP1_PAD_DRIVE_8MA; break;
+ case 12: strength = RP1_PAD_DRIVE_12MA; break;
+ default:
+ return -RT_ENOSYS;
+ }
+ }
+
+ slew = RT_UINT32_MAX;
+ rt_ofw_prop_read_u32(np, "slew-rate", &slew);
+
+ rt_ofw_foreach_prop_string(np, "pins", prop, string)
+ {
+ pini = RT_NULL;
+
+ for (int i = 0; i < RT_ARRAY_SIZE(rp1_gpio_pins); ++i)
+ {
+ if (!rt_strcmp(rp1_gpio_pins[i].name, string))
+ {
+ pin = rp1_gpio_pins[i].number;
+ pini = &pc->pins[pin];
+ break;
+ }
+ }
+
+ if (!pini)
+ {
+ err = -RT_EINVAL;
+ break;
+ }
+
+ /* IOMUX */
+ for (fsel = 0; fsel < RP1_FSEL_COUNT; ++fsel)
+ {
+ if (func == rp1_gpio_pin_funcs[pin].funcs[fsel])
+ {
+ break;
+ }
+ }
+
+ if (fsel == RP1_FSEL_COUNT)
+ {
+ err = -RT_EINVAL;
+ break;
+ }
+
+ rp1_set_fsel(pini, fsel);
+
+ /* PULL */
+ if (conf)
+ {
+ switch (conf->param)
+ {
+ case PIN_CONFIG_BIAS_DISABLE:
+ rp1_pull_config_set(pini, RP1_PUD_OFF);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ rp1_pull_config_set(pini, RP1_PUD_DOWN);
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ rp1_pull_config_set(pini, RP1_PUD_UP);
+ break;
+
+ default:
+ err = -RT_ENOSYS;
+ break;
+ }
+ }
+
+ if (strength != RT_UINT32_MAX)
+ {
+ rp1_pad_update(pini, RP1_PAD_DRIVE_MASK, strength);
+ }
+
+ if (slew != RT_UINT32_MAX)
+ {
+ rp1_pad_update(pini, RP1_PAD_SLEWFAST_MASK, slew ? RP1_PAD_SLEWFAST_MASK : 0);
+ }
+ }
+
+ return err;
+}
+
+static void rp1_pinctrl_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+ struct rp1_pin_info *pini = &pc->pins[pin];
+
+ switch (mode)
+ {
+ case PIN_MODE_OUTPUT:
+ HWREG32(pini->rio + RP1_RIO_OE + RP1_SET_OFFSET) = 1 << pini->offset;
+ rp1_set_fsel(pini, RP1_FSEL_GPIO);
+ break;
+
+ case PIN_MODE_INPUT:
+ HWREG32(pini->rio + RP1_RIO_OE + RP1_CLR_OFFSET) = 1 << pini->offset;
+ rp1_set_fsel(pini, RP1_FSEL_GPIO);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void rp1_pinctrl_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
+{
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+ struct rp1_pin_info *pini = &pc->pins[pin];
+
+ /* Assume the pin is already an output */
+ HWREG32(pini->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)) =
+ 1 << pini->offset;
+}
+
+static rt_ssize_t rp1_pinctrl_read(struct rt_device *device, rt_base_t pin)
+{
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+ struct rp1_pin_info *pini = &pc->pins[pin];
+
+ return !!(HWREG32(pini->rio + RP1_RIO_IN) & (1 << pini->offset));
+}
+
+static rt_err_t rp1_pinctrl_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
+{
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+ struct rp1_pin_info *pini = &pc->pins[pin];
+
+ HWREG32(pini->inte + (enabled ? RP1_SET_OFFSET : RP1_CLR_OFFSET)) = 1 << pini->offset;
+
+ if (!enabled)
+ {
+ /* Clear any latched events */
+ HWREG32(pini->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL) = RP1_GPIO_CTRL_IRQRESET;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_pinctrl_irq_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
+{
+ rt_ubase_t level;
+ rt_uint32_t irq_flags;
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+ struct rp1_pin_info *pini = &pc->pins[pin];
+
+ level = rt_spin_lock_irqsave(&pc->irq_lock[pini->bank]);
+
+ switch (mode)
+ {
+ case PIN_IRQ_MODE_RISING:
+ irq_flags = RP1_INT_EDGE_RISING;
+ break;
+
+ case PIN_IRQ_MODE_FALLING:
+ irq_flags = RP1_INT_EDGE_FALLING;
+ break;
+
+ case PIN_IRQ_MODE_RISING_FALLING:
+ irq_flags = RP1_INT_EDGE_RISING | RP1_INT_EDGE_FALLING;
+ break;
+
+ case PIN_IRQ_MODE_HIGH_LEVEL:
+ irq_flags = RP1_INT_LEVEL_HIGH;
+ break;
+
+ case PIN_IRQ_MODE_LOW_LEVEL:
+ irq_flags = RP1_INT_LEVEL_LOW;
+ break;
+
+ default:
+ rt_spin_unlock_irqrestore(&pc->irq_lock[pini->bank], level);
+ return -RT_EINVAL;
+ }
+
+ /* Clear them all */
+ HWREG32(pini->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL) =
+ RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW;
+
+ /* Set those that are needed */
+ HWREG32(pini->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL) =
+ irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW;
+
+ pini->irq_type = mode;
+
+ rt_spin_unlock_irqrestore(&pc->irq_lock[pini->bank], level);
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_pinctrl_confs_apply(struct rt_device *device, void *fw_conf_np)
+{
+ rt_err_t err;
+ rt_bool_t stage2 = RT_FALSE;
+ struct rt_ofw_node *conf_np = fw_conf_np, *child;
+ struct rp1_pinctrl *pc = raw_to_rp1_pinctrl(device);
+
+ rt_ofw_foreach_child_node(conf_np, child)
+ {
+ stage2 = RT_TRUE;
+
+ if ((err = rp1_pinctrl_confs_apply_once(pc, child)))
+ {
+ return err;
+ }
+ }
+
+ if (!stage2)
+ {
+ err = rp1_pinctrl_confs_apply_once(pc, conf_np);
+ }
+
+ return err;
+}
+
+static const struct rt_pin_ops rp1_pinctrl_ops =
+{
+ .pin_mode = rp1_pinctrl_mode,
+ .pin_write = rp1_pinctrl_write,
+ .pin_read = rp1_pinctrl_read,
+ .pin_irq_enable = rp1_pinctrl_irq_enable,
+ .pin_irq_mode = rp1_pinctrl_irq_mode,
+ .pin_ctrl_confs_apply = rp1_pinctrl_confs_apply,
+};
+
+static void rp1_pinctrl_isr(int irq, void *param)
+{
+ rt_ubase_t pin;
+ rt_bitmap_t ints;
+ struct rp1_pin_info *pini;
+ struct rp1_pinctrl *pc = param;
+ const struct rp1_iobank_desc *bank;
+
+ if (pc->irqs[0] == irq)
+ {
+ bank = &rp1_iobanks[0];
+ }
+ else if (pc->irqs[1] == irq)
+ {
+ bank = &rp1_iobanks[1];
+ }
+ else
+ {
+ bank = &rp1_iobanks[2];
+ }
+
+ ints = HWREG32(pc->gpio_base + bank->ints_offset);
+
+ rt_bitmap_for_each_set_bit(&ints, pin, 32)
+ {
+ pini = &pc->pins[pin];
+
+ /* Clear any latched events */
+ HWREG32(pini->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL) = RP1_GPIO_CTRL_IRQRESET;
+
+ pin_pic_handle_isr(&pc->parent, pin);
+ }
+}
+
+static rt_err_t rp1_pinctrl_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_pinctrl *pc = rt_calloc(1, sizeof(*pc));
+
+ if (!pc)
+ {
+ return -RT_ENOMEM;
+ }
+
+ if (!(pc->gpio_base = rt_dm_dev_iomap(dev, 0)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if (!(pc->rio_base = rt_dm_dev_iomap(dev, 1)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ if (!(pc->pads_base = rt_dm_dev_iomap(dev, 2)))
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ for (int i = 0; i < RP1_NUM_BANKS; ++i)
+ {
+ const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
+
+ for (int j = 0; j < bank->num_gpios; ++j)
+ {
+ struct rp1_pin_info *pini = &pc->pins[bank->min_gpio + j];
+
+ pini->num = bank->min_gpio + j;
+ pini->bank = i;
+ pini->offset = j;
+
+ pini->gpio = pc->gpio_base + bank->gpio_offset + j * sizeof(rt_uint32_t) * 2;
+ pini->inte = pc->gpio_base + bank->inte_offset;
+ pini->ints = pc->gpio_base + bank->ints_offset;
+ pini->rio = pc->rio_base + bank->rio_offset;
+ pini->pad = pc->pads_base + bank->pads_offset + j * sizeof(rt_uint32_t);
+ }
+
+ rt_spin_lock_init(&pc->irq_lock[i]);
+ }
+
+ for (int i = 0; i < RP1_NUM_BANKS; ++i)
+ {
+ int irq = rt_dm_dev_get_irq(dev, i);
+
+ pc->irqs[i] = irq;
+
+ if (irq < 0)
+ {
+ break;
+ }
+
+ rt_hw_interrupt_install(irq, rp1_pinctrl_isr, pc, "rp1-pinctrl");
+ rt_hw_interrupt_umask(irq);
+ }
+
+ pc->parent.ops = pdev->id->data;
+ pin_api_init(&pc->parent, RP1_NUM_GPIOS);
+ pin_pic_init(&pc->parent, pc->irqs[0]);
+
+ rt_ofw_data(dev->ofw_node) = &pc->parent;
+
+ return RT_EOK;
+
+_fail:
+ rt_free(pc);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rp1_pinctrl_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rp1-gpio", .data = &rp1_pinctrl_ops },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rp1_pinctrl_driver =
+{
+ .name = "pinctrl-rp1",
+ .ids = rp1_pinctrl_ofw_ids,
+
+ .probe = rp1_pinctrl_probe,
+};
+
+static int rp1_pinctrl_register(void)
+{
+ rt_platform_driver_register(&rp1_pinctrl_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rp1_pinctrl_register);
diff --git a/bsp/raspberry-pi/dm/pmdomain/Kconfig b/bsp/raspberry-pi/dm/pmdomain/Kconfig
new file mode 100755
index 0000000000..84a3539851
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pmdomain/Kconfig
@@ -0,0 +1,8 @@
+config RT_PMDOMAIN_BCM2835
+ bool "BCM2835"
+ depends on RT_USING_RESET
+ default n
+
+config RT_PMDOMAIN_RASPBERRYPI
+ bool "Raspberrypi"
+ default n
diff --git a/bsp/raspberry-pi/dm/pmdomain/SConscript b/bsp/raspberry-pi/dm/pmdomain/SConscript
new file mode 100755
index 0000000000..fdfe8e0739
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pmdomain/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_PMDOMAIN_BCM2835']):
+ src += ['pm-domain-bcm2835.c']
+
+if GetDepend(['RT_PMDOMAIN_RASPBERRYPI']):
+ src += ['pm-domain-raspberrypi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pmdomain/pm-domain-bcm2835.c b/bsp/raspberry-pi/dm/pmdomain/pm-domain-bcm2835.c
new file mode 100755
index 0000000000..a4c821b963
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pmdomain/pm-domain-bcm2835.c
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-21 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pm-domain.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+#include <bcm2835-pm.h>
+#include <dt-bindings/power/bcm2835-pm.h>
+
+#define PM_GNRIC 0x00
+#define PM_AUDIO 0x04
+#define PM_STATUS 0x18
+#define PM_RSTC 0x1c
+#define PM_RSTS 0x20
+#define PM_WDOG 0x24
+#define PM_PADS0 0x28
+#define PM_PADS2 0x2c
+#define PM_PADS3 0x30
+#define PM_PADS4 0x34
+#define PM_PADS5 0x38
+#define PM_PADS6 0x3c
+#define PM_CAM0 0x44
+#define PM_CAM0_LDOHPEN RT_BIT(2)
+#define PM_CAM0_LDOLPEN RT_BIT(1)
+#define PM_CAM0_CTRLEN RT_BIT(0)
+
+#define PM_CAM1 0x48
+#define PM_CAM1_LDOHPEN RT_BIT(2)
+#define PM_CAM1_LDOLPEN RT_BIT(1)
+#define PM_CAM1_CTRLEN RT_BIT(0)
+
+#define PM_CCP2TX 0x4c
+#define PM_CCP2TX_LDOEN RT_BIT(1)
+#define PM_CCP2TX_CTRLEN RT_BIT(0)
+
+#define PM_DSI0 0x50
+#define PM_DSI0_LDOHPEN RT_BIT(2)
+#define PM_DSI0_LDOLPEN RT_BIT(1)
+#define PM_DSI0_CTRLEN RT_BIT(0)
+
+#define PM_DSI1 0x54
+#define PM_DSI1_LDOHPEN RT_BIT(2)
+#define PM_DSI1_LDOLPEN RT_BIT(1)
+#define PM_DSI1_CTRLEN RT_BIT(0)
+
+#define PM_HDMI 0x58
+#define PM_HDMI_RSTDR RT_BIT(19)
+#define PM_HDMI_LDOPD RT_BIT(1)
+#define PM_HDMI_CTRLEN RT_BIT(0)
+
+#define PM_USB 0x5c
+/*
+ * The power gates must be enabled with this bit before enabling the LDO in the
+ * USB block.
+ */
+#define PM_USB_CTRLEN RT_BIT(0)
+
+#define PM_PXLDO 0x60
+#define PM_PXBG 0x64
+#define PM_DFT 0x68
+#define PM_SMPS 0x6c
+#define PM_XOSC 0x70
+#define PM_SPAREW 0x74
+#define PM_SPARER 0x78
+#define PM_AVS_RSTDR 0x7c
+#define PM_AVS_STAT 0x80
+#define PM_AVS_EVENT 0x84
+#define PM_AVS_INTEN 0x88
+#define PM_DUMMY 0xfc
+
+#define PM_IMAGE 0x108
+#define PM_GRAFX 0x10c
+#define PM_PROC 0x110
+#define PM_GRAFX_2712 0x304
+#define PM_ENAB RT_BIT(12)
+#define PM_ISPRSTN RT_BIT(8)
+#define PM_H264RSTN RT_BIT(7)
+#define PM_PERIRSTN RT_BIT(6)
+#define PM_V3DRSTN RT_BIT(6)
+#define PM_ISFUNC RT_BIT(5)
+#define PM_MRDONE RT_BIT(4)
+#define PM_MEMREP RT_BIT(3)
+#define PM_ISPOW RT_BIT(2)
+#define PM_POWOK RT_BIT(1)
+#define PM_POWUP RT_BIT(0)
+#define PM_INRUSH_SHIFT 13
+#define PM_INRUSH_3_5_MA 0
+#define PM_INRUSH_5_MA 1
+#define PM_INRUSH_10_MA 2
+#define PM_INRUSH_20_MA 3
+#define PM_INRUSH_MASK (3 << PM_INRUSH_SHIFT)
+
+#define PM_PASSWORD 0x5a000000
+
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define PM_READ(reg) HWREG32(power->base + (reg))
+#define PM_WRITE(reg, val) HWREG32(power->base + (reg)) = PM_PASSWORD | (val)
+
+#define ASB_BRDG_VERSION 0x00
+#define ASB_CPR_CTRL 0x04
+
+#define ASB_V3D_S_CTRL 0x08
+#define ASB_V3D_M_CTRL 0x0c
+#define ASB_ISP_S_CTRL 0x10
+#define ASB_ISP_M_CTRL 0x14
+#define ASB_H264_S_CTRL 0x18
+#define ASB_H264_M_CTRL 0x1c
+
+#define ASB_REQ_STOP RT_BIT(0)
+#define ASB_ACK RT_BIT(1)
+#define ASB_EMPTY RT_BIT(2)
+#define ASB_FULL RT_BIT(3)
+
+#define ASB_AXI_BRDG_ID 0x20
+
+#define BCM2835_BRDG_ID 0x62726467
+
+struct bcm2835_power;
+
+struct bcm2835_power_domain
+{
+ struct rt_dm_power_domain parent;
+ const char *name;
+
+ rt_uint32_t domain;
+ struct rt_clk *clk;
+ struct bcm2835_power *power;
+};
+
+#define raw_to_rpi_bcm2835_power_domain(raw) rt_container_of(raw, struct bcm2835_power_domain, parent)
+
+struct bcm2835_power
+{
+ struct rt_dm_power_domain_proxy proxy_parent;
+ struct rt_reset_controller rstc_parent;
+
+ void *base; /* PM registers. */
+ void *asb; /* AXI Async bridge registers. */
+ void *rpivid_asb; /* RPiVid bridge registers. */
+
+ struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT];
+};
+
+#define raw_to_bcm2835_power(raw) rt_container_of(raw, struct bcm2835_power, proxy_parent)
+
+static rt_err_t bcm2835_asb_control(struct bcm2835_power *power, int reg, rt_bool_t enable)
+{
+ rt_uint32_t val;
+ rt_bool_t timeout;
+ void *base = power->asb;
+
+ switch (reg)
+ {
+ case 0:
+ return RT_EOK;
+
+ case ASB_V3D_S_CTRL:
+ case ASB_V3D_M_CTRL:
+ if (power->rpivid_asb)
+ {
+ base = power->rpivid_asb;
+ }
+ break;
+
+ default:
+ return -RT_EINVAL;
+ }
+
+ timeout = RT_FALSE;
+
+ /* Enable the module's async AXI bridges. */
+ if (enable)
+ {
+ val = HWREG32(base + reg) & ~ASB_REQ_STOP;
+ }
+ else
+ {
+ val = HWREG32(base + reg) | ASB_REQ_STOP;
+ }
+
+ HWREG32(base + reg) = PM_PASSWORD | val;
+
+ while (!!(HWREG32(base + reg) & ASB_ACK) == enable)
+ {
+ if (timeout)
+ {
+ return -RT_ETIMEOUT;
+ }
+
+ rt_hw_us_delay(1);
+ timeout = RT_TRUE;
+
+ rt_hw_cpu_relax();
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_asb_enable(struct bcm2835_power *power, int reg)
+{
+ return bcm2835_asb_control(power, reg, RT_TRUE);
+}
+
+static rt_err_t bcm2835_asb_disable(struct bcm2835_power *power, int reg)
+{
+ return bcm2835_asb_control(power, reg, RT_FALSE);
+}
+
+static rt_err_t bcm2835_power_power_off(struct bcm2835_power_domain *pd, int pm_reg)
+{
+ struct bcm2835_power *power = pd->power;
+
+ /* We don't run this on BCM2711 */
+ if (power->rpivid_asb)
+ {
+ return RT_EOK;
+ }
+
+ /* Enable functional isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC);
+
+ /* Enable electrical isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+
+ /* Open the power switches. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_POWUP);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_power_power_on(struct bcm2835_power_domain *pd, rt_uint32_t pm_reg)
+{
+ rt_err_t err;
+ int inrush;
+ rt_bool_t powok, timeout;
+ struct bcm2835_power *power = pd->power;
+
+ /* We don't run this on BCM2711 */
+ if (power->rpivid_asb)
+ {
+ return RT_EOK;
+ }
+
+ /* If it was already powered on by the fw, leave it that way. */
+ if (PM_READ(pm_reg) & PM_POWUP)
+ {
+ return RT_EOK;
+ }
+
+ /*
+ * Enable power. Allowing too much current at once may result
+ * in POWOK never getting set, so start low and ramp it up as
+ * necessary to succeed.
+ */
+ powok = RT_FALSE;
+ for (inrush = PM_INRUSH_3_5_MA; inrush <= PM_INRUSH_20_MA; ++inrush)
+ {
+ PM_WRITE(pm_reg, (PM_READ(pm_reg) & ~PM_INRUSH_MASK) |
+ (inrush << PM_INRUSH_SHIFT) | PM_POWUP);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ if ((powok = !!(PM_READ(pm_reg) & PM_POWOK)))
+ {
+ break;
+ }
+
+ rt_hw_us_delay(1);
+ rt_hw_cpu_relax();
+ }
+ }
+
+ if (!powok)
+ {
+ LOG_E("Timeout waiting for %s power OK", pd->name);
+
+ err = -RT_ETIMEOUT;
+ goto _err_disable_powup;
+ }
+
+ /* Disable electrical isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISPOW);
+
+ /* Repair memory */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_MEMREP);
+
+ timeout = RT_FALSE;
+ while (!(PM_READ(pm_reg) & PM_MRDONE))
+ {
+ if (timeout)
+ {
+ LOG_E("Timeout waiting for %s memory repair", pd->name);
+
+ err = -RT_ETIMEOUT;
+ goto _err_disable_ispow;
+ }
+
+ rt_hw_us_delay(1);
+ timeout = RT_TRUE;
+
+ rt_hw_cpu_relax();
+ }
+
+ /* Disable functional isolation */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | PM_ISFUNC);
+
+ return RT_EOK;
+
+_err_disable_ispow:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISPOW);
+
+_err_disable_powup:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~(PM_POWUP | PM_INRUSH_MASK));
+
+ return err;
+}
+
+static rt_err_t bcm2835_asb_power_on(struct bcm2835_power_domain *pd,
+ rt_uint32_t pm_reg, rt_uint32_t asb_m_reg,
+ rt_uint32_t asb_s_reg, rt_uint32_t reset_flags)
+{
+ rt_err_t err;
+ struct bcm2835_power *power = pd->power;
+
+ if ((err = rt_clk_prepare_enable(pd->clk)))
+ {
+ LOG_E("Failed to enable clock for %s", pd->name);
+ return err;
+ }
+
+ /* Wait 32 clocks for reset to propagate, 1 us will be enough */
+ rt_hw_us_delay(1);
+
+ rt_clk_disable_unprepare(pd->clk);
+
+ /* Deassert the resets. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) | reset_flags);
+
+ if ((err = rt_clk_prepare_enable(pd->clk)))
+ {
+ LOG_E("Failed to enable clock for %s", pd->name);
+ goto _err_enable_resets;
+ }
+
+ if ((err = bcm2835_asb_enable(power, asb_m_reg)))
+ {
+ LOG_E("Failed to enable ASB master for %s", pd->name);
+ goto _err_disable_clk;
+ }
+
+ if ((err = bcm2835_asb_enable(power, asb_s_reg)))
+ {
+ LOG_E("Failed to enable ASB slave for %s", pd->name);
+ goto _err_disable_asb_master;
+ }
+
+ return RT_EOK;
+
+_err_disable_asb_master:
+ bcm2835_asb_disable(power, asb_m_reg);
+
+_err_disable_clk:
+ rt_clk_disable_unprepare(pd->clk);
+
+_err_enable_resets:
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+
+ return err;
+}
+
+static rt_err_t bcm2835_asb_power_off(struct bcm2835_power_domain *pd,
+ rt_uint32_t pm_reg, rt_uint32_t asb_m_reg,
+ rt_uint32_t asb_s_reg, rt_uint32_t reset_flags)
+{
+ rt_err_t err;
+ struct bcm2835_power *power = pd->power;
+
+ if ((err = bcm2835_asb_disable(power, asb_s_reg)))
+ {
+ LOG_W("Failed to disable ASB slave for %s", pd->name);
+
+ return err;
+ }
+
+ if ((err = bcm2835_asb_disable(power, asb_m_reg)))
+ {
+ LOG_W("Failed to disable ASB master for %s", pd->name);
+ bcm2835_asb_enable(power, asb_s_reg);
+
+ return err;
+ }
+
+ rt_clk_disable_unprepare(pd->clk);
+
+ /* Assert the resets. */
+ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~reset_flags);
+
+ return 0;
+}
+
+static rt_err_t bcm2835_power_pd_power_on(struct rt_dm_power_domain *domain)
+{
+ struct bcm2835_power_domain *pd = raw_to_rpi_bcm2835_power_domain(domain);
+ struct bcm2835_power *power = pd->power;
+
+ switch (pd->domain)
+ {
+ case BCM2835_POWER_DOMAIN_GRAFX:
+ return bcm2835_power_power_on(pd, PM_GRAFX);
+
+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+ if (!power->asb)
+ {
+ return bcm2835_asb_power_on(pd, PM_GRAFX_2712, 0, 0, PM_V3DRSTN);
+ }
+ return bcm2835_asb_power_on(pd, PM_GRAFX,
+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, PM_V3DRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE:
+ return bcm2835_power_power_on(pd, PM_IMAGE);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+ return bcm2835_asb_power_on(pd, PM_IMAGE, 0, 0, PM_PERIRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+ return bcm2835_asb_power_on(pd, PM_IMAGE,
+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, PM_ISPRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
+ return bcm2835_asb_power_on(pd, PM_IMAGE,
+ ASB_H264_M_CTRL, ASB_H264_S_CTRL, PM_H264RSTN);
+
+ case BCM2835_POWER_DOMAIN_USB:
+ PM_WRITE(PM_USB, PM_USB_CTRLEN);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_DSI0:
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN | PM_DSI0_LDOHPEN);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_DSI1:
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN | PM_DSI1_LDOHPEN);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_CCP2TX:
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN | PM_CCP2TX_LDOEN);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_HDMI:
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_RSTDR);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_CTRLEN);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_LDOPD);
+
+ rt_hw_us_delay(150);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_RSTDR);
+ return RT_EOK;
+
+ default:
+ LOG_E("Invalid domain %d", pd->domain);
+
+ return -RT_EINVAL;
+ }
+}
+
+static rt_err_t bcm2835_power_pd_power_off(struct rt_dm_power_domain *domain)
+{
+ struct bcm2835_power_domain *pd = raw_to_rpi_bcm2835_power_domain(domain);
+ struct bcm2835_power *power = pd->power;
+
+ switch (pd->domain)
+ {
+ case BCM2835_POWER_DOMAIN_GRAFX:
+ return bcm2835_power_power_off(pd, PM_GRAFX);
+
+ case BCM2835_POWER_DOMAIN_GRAFX_V3D:
+ if (!power->asb)
+ {
+ return bcm2835_asb_power_off(pd, PM_GRAFX_2712, 0, 0, PM_V3DRSTN);
+ }
+ return bcm2835_asb_power_off(pd, PM_GRAFX,
+ ASB_V3D_M_CTRL, ASB_V3D_S_CTRL, PM_V3DRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE:
+ return bcm2835_power_power_off(pd, PM_IMAGE);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_PERI:
+ return bcm2835_asb_power_off(pd, PM_IMAGE, 0, 0, PM_PERIRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_ISP:
+ return bcm2835_asb_power_off(pd, PM_IMAGE,
+ ASB_ISP_M_CTRL, ASB_ISP_S_CTRL, PM_ISPRSTN);
+
+ case BCM2835_POWER_DOMAIN_IMAGE_H264:
+ return bcm2835_asb_power_off(pd, PM_IMAGE,
+ ASB_H264_M_CTRL, ASB_H264_S_CTRL, PM_H264RSTN);
+
+ case BCM2835_POWER_DOMAIN_USB:
+ PM_WRITE(PM_USB, 0);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_DSI0:
+ PM_WRITE(PM_DSI0, PM_DSI0_CTRLEN);
+ PM_WRITE(PM_DSI0, 0);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_DSI1:
+ PM_WRITE(PM_DSI1, PM_DSI1_CTRLEN);
+ PM_WRITE(PM_DSI1, 0);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_CCP2TX:
+ PM_WRITE(PM_CCP2TX, PM_CCP2TX_CTRLEN);
+ PM_WRITE(PM_CCP2TX, 0);
+ return RT_EOK;
+
+ case BCM2835_POWER_DOMAIN_HDMI:
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) | PM_HDMI_LDOPD);
+ PM_WRITE(PM_HDMI, PM_READ(PM_HDMI) & ~PM_HDMI_CTRLEN);
+ return RT_EOK;
+
+ default:
+ LOG_E("Invalid domain %d", pd->domain);
+
+ return -RT_EINVAL;
+ }
+}
+
+static struct rt_dm_power_domain *bcm2835_power_domains_ofw_parse(
+ struct rt_dm_power_domain_proxy *proxy, struct rt_ofw_cell_args *args)
+{
+ struct bcm2835_power *power = raw_to_bcm2835_power(proxy);
+
+ return &power->domains[args->args[0]].parent;
+}
+
+static rt_err_t bcm2835_reset_reset(struct rt_reset_control *rstc)
+{
+ rt_err_t err;
+ struct bcm2835_power_domain *pd;
+ struct bcm2835_power *power = rstc->rstcer->priv;
+
+ switch (rstc->id)
+ {
+ case BCM2835_RESET_V3D:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_GRAFX_V3D];
+ break;
+
+ case BCM2835_RESET_H264:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_H264];
+ break;
+
+ case BCM2835_RESET_ISP:
+ pd = &power->domains[BCM2835_POWER_DOMAIN_IMAGE_ISP];
+ break;
+
+ default:
+ LOG_E("Invalid reset id %u", rstc->id);
+ return -RT_EINVAL;
+ }
+
+ if ((err = bcm2835_power_pd_power_off(&pd->parent)))
+ {
+ return err;
+ }
+
+ return bcm2835_power_pd_power_on(&pd->parent);
+}
+
+static int bcm2835_reset_status(struct rt_reset_control *rstc)
+{
+ struct bcm2835_power *power = rstc->rstcer->priv;
+
+ switch (rstc->id)
+ {
+ case BCM2835_RESET_V3D:
+ return !PM_READ(PM_GRAFX & PM_V3DRSTN);
+
+ case BCM2835_RESET_H264:
+ return !PM_READ(PM_IMAGE & PM_H264RSTN);
+
+ case BCM2835_RESET_ISP:
+ return !PM_READ(PM_IMAGE & PM_ISPRSTN);
+
+ default:
+ return -RT_EINVAL;
+ }
+}
+
+static const struct rt_reset_control_ops bcm2835_reset_ops =
+{
+ .reset = bcm2835_reset_reset,
+ .status = bcm2835_reset_status,
+};
+
+static const char *const power_domain_names[] =
+{
+ [BCM2835_POWER_DOMAIN_GRAFX] = "grafx",
+ [BCM2835_POWER_DOMAIN_GRAFX_V3D] = "v3d",
+
+ [BCM2835_POWER_DOMAIN_IMAGE] = "image",
+ [BCM2835_POWER_DOMAIN_IMAGE_PERI] = "peri_image",
+ [BCM2835_POWER_DOMAIN_IMAGE_H264] = "h264",
+ [BCM2835_POWER_DOMAIN_IMAGE_ISP] = "isp",
+
+ [BCM2835_POWER_DOMAIN_USB] = "usb",
+ [BCM2835_POWER_DOMAIN_DSI0] = "dsi0",
+ [BCM2835_POWER_DOMAIN_DSI1] = "dsi1",
+ [BCM2835_POWER_DOMAIN_CAM0] = "cam0",
+ [BCM2835_POWER_DOMAIN_CAM1] = "cam1",
+ [BCM2835_POWER_DOMAIN_CCP2TX] = "ccp2tx",
+ [BCM2835_POWER_DOMAIN_HDMI] = "hdmi",
+};
+
+static rt_err_t bcm2835_init_power_domain(struct bcm2835_power *power,
+ struct bcm2835_pm *pm, int id)
+{
+ const char *name = power_domain_names[id];
+ struct bcm2835_power_domain *dom = &power->domains[id];
+
+ dom->clk = rt_ofw_get_clk_by_name(pm->ofw_node, name);
+
+ if (rt_is_err(dom->clk))
+ {
+ return rt_ptr_err(dom->clk);
+ }
+
+ dom->power = power;
+ dom->parent.power_on = bcm2835_power_pd_power_on;
+ dom->parent.power_off = bcm2835_power_pd_power_off;
+
+ rt_dm_power_domain_register(&dom->parent);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_power_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_reset_controller *rstcer;
+ struct bcm2835_pm *pm = pdev->priv;
+ struct bcm2835_power *power = rt_calloc(1, sizeof(*power));
+
+ if (!power)
+ {
+ return -RT_ENOMEM;
+ }
+
+ power->base = pm->base;
+ power->asb = pm->asb;
+ power->rpivid_asb = pm->rpivid_asb;
+
+ if (power->asb)
+ {
+ rt_uint32_t id = HWREG32(power->asb + ASB_AXI_BRDG_ID);
+
+ /* "BRDG" */
+ if (id != BCM2835_BRDG_ID)
+ {
+ LOG_E("ASB register ID returned 0x%08x", id);
+
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ if (power->rpivid_asb)
+ {
+ id = HWREG32(power->rpivid_asb + ASB_AXI_BRDG_ID);
+ /* "BRDG" */
+ if (id != BCM2835_BRDG_ID)
+ {
+ LOG_E("RPiVid ASB register ID returned 0x%08x", id);
+
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+ }
+ }
+
+ for (int i = 0; i < RT_ARRAY_SIZE(power_domain_names); ++i)
+ {
+ if ((err = bcm2835_init_power_domain(power, pm, i)))
+ {
+ goto _free_power_domain;
+ }
+ }
+
+ power->proxy_parent.ofw_parse = bcm2835_power_domains_ofw_parse;
+ rt_dm_power_domain_proxy_ofw_bind(&power->proxy_parent, pm->ofw_node);
+
+ rstcer = &power->rstc_parent;
+ rstcer->priv = power;
+ rstcer->ofw_node = pm->ofw_node;
+ rstcer->ops = &bcm2835_reset_ops;
+
+ rt_reset_controller_register(rstcer);
+
+ return RT_EOK;
+
+_free_power_domain:
+ for (int i = 0; i < RT_ARRAY_SIZE(power_domain_names); ++i)
+ {
+ struct bcm2835_power_domain *dom = &power->domains[i];
+
+ if (!dom->power)
+ {
+ break;
+ }
+
+ rt_dm_power_domain_unregister(&dom->parent);
+ }
+
+_fail:
+ rt_free(power);
+
+ return err;
+}
+
+static struct rt_platform_driver bcm2835_power_driver =
+{
+ .name = "bcm2835-power",
+ .probe = bcm2835_power_probe,
+};
+
+static int bcm2835_power_drv_register(void)
+{
+ rt_platform_driver_register(&bcm2835_power_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(bcm2835_power_drv_register);
diff --git a/bsp/raspberry-pi/dm/pmdomain/pm-domain-raspberrypi.c b/bsp/raspberry-pi/dm/pmdomain/pm-domain-raspberrypi.c
new file mode 100755
index 0000000000..435185a215
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pmdomain/pm-domain-raspberrypi.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-21 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <firmware-raspberrypi.h>
+#include <dt-bindings/power/raspberrypi-power.h>
+
+/*
+ * Firmware indices for the old power domains interface.
+ * Only a few of them were actually implemented.
+ */
+#define RPI_OLD_POWER_DOMAIN_USB 3
+#define RPI_OLD_POWER_DOMAIN_V3D 10
+
+/*
+ * Packet definition used by RPI_FIRMWARE_SET_POWER_STATE and
+ * RPI_FIRMWARE_SET_DOMAIN_STATE.
+ */
+struct rpi_power_domain_packet
+{
+ rt_uint32_t domain;
+ rt_uint32_t state;
+};
+
+struct rpi_power_domain
+{
+ struct rt_dm_power_domain parent;
+
+ rt_uint32_t domain;
+ rt_bool_t old_interface;
+ struct rpi_firmware *rpi_fw;
+};
+
+#define raw_to_rpi_power_domain(raw) rt_container_of(raw, struct rpi_power_domain, parent)
+
+struct rpi_power_domains
+{
+ struct rt_dm_power_domain_proxy parent;
+
+ rt_bool_t has_new_interface;
+ struct rpi_firmware *rpi_fw;
+ struct rpi_power_domain domains[RPI_POWER_DOMAIN_COUNT];
+};
+
+#define raw_to_rpi_power_domains(raw) rt_container_of(raw, struct rpi_power_domains, parent)
+
+static rt_err_t rpi_firmware_set_power(struct rt_dm_power_domain *domain, rt_bool_t on)
+{
+ struct rpi_power_domain *rpi_domain = raw_to_rpi_power_domain(domain);
+ struct rpi_power_domain_packet packet;
+
+ packet.domain = rpi_domain->domain;
+ packet.state = on;
+
+ return rpi_firmware_property(rpi_domain->rpi_fw,
+ rpi_domain->old_interface ?
+ RPI_FIRMWARE_SET_POWER_STATE : RPI_FIRMWARE_SET_DOMAIN_STATE,
+ &packet, sizeof(packet));
+}
+
+static rt_err_t rpi_domain_off(struct rt_dm_power_domain *domain)
+{
+ return rpi_firmware_set_power(domain, RT_FALSE);
+}
+
+static rt_err_t rpi_domain_on(struct rt_dm_power_domain *domain)
+{
+ return rpi_firmware_set_power(domain, RT_TRUE);
+}
+
+static struct rt_dm_power_domain *rpi_power_domains_ofw_parse(
+ struct rt_dm_power_domain_proxy *proxy, struct rt_ofw_cell_args *args)
+{
+ struct rpi_power_domains *rpi_domains = raw_to_rpi_power_domains(proxy);
+
+ return &rpi_domains->domains[args->args[0]].parent;
+}
+
+static void rpi_common_init_power_domain(struct rpi_power_domains *rpi_domains, int id)
+{
+ struct rpi_power_domain *dom = &rpi_domains->domains[id];
+
+ dom->rpi_fw = rpi_domains->rpi_fw;
+
+ dom->parent.power_on = rpi_domain_on;
+ dom->parent.power_off = rpi_domain_off;
+
+ rt_dm_power_domain_register(&dom->parent);
+}
+
+static void rpi_init_power_domain(struct rpi_power_domains *rpi_domains,
+ int id, const char *name)
+{
+ struct rpi_power_domain *dom = &rpi_domains->domains[id];
+
+ if (!rpi_domains->has_new_interface)
+ {
+ return;
+ }
+
+ /* The DT binding index is the firmware's domain index minus one. */
+ dom->domain = id + 1;
+
+ rpi_common_init_power_domain(rpi_domains, id);
+ (void)name;
+}
+
+static void rpi_init_old_power_domain(struct rpi_power_domains *rpi_domains,
+ int id, int domain, const char *name)
+{
+ struct rpi_power_domain *dom = &rpi_domains->domains[id];
+
+ dom->old_interface = RT_TRUE;
+ dom->domain = domain;
+
+ rpi_common_init_power_domain(rpi_domains, id);
+ (void)name;
+}
+
+/*
+ * Detect whether the firmware supports the new power domains interface.
+ *
+ * The firmware does not return an error on an unknown tag and just skips
+ * over it, so probe by putting an unexpected value in the return field
+ * and checking if it was unchanged.
+ */
+static rt_bool_t rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
+{
+ struct rpi_power_domain_packet packet;
+
+ packet.domain = RPI_POWER_DOMAIN_ARM;
+ packet.state = ~0;
+
+ return !rpi_firmware_property(rpi_domains->rpi_fw,
+ RPI_FIRMWARE_GET_DOMAIN_STATE, &packet, sizeof(packet)) &&
+ packet.state != ~0;
+}
+
+static rt_err_t rpi_power_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node;
+ struct rt_ofw_node *fw_np;
+ struct rpi_power_domains *rpi_domains = rt_calloc(1, sizeof(*rpi_domains));
+
+ if (!rpi_domains)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_domains->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_domains->rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_domains->has_new_interface = rpi_has_new_domain_support(rpi_domains);
+
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C0, "I2C0");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C1, "I2C1");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_I2C2, "I2C2");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VIDEO_SCALER, "VIDEO_SCALER");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VPU1, "VPU1");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_HDMI, "HDMI");
+
+ /*
+ * Use the old firmware interface for USB power, so that we
+ * can turn it on even if the firmware hasn't been updated.
+ */
+ rpi_init_old_power_domain(rpi_domains, RPI_POWER_DOMAIN_USB,
+ RPI_OLD_POWER_DOMAIN_USB, "USB");
+
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_VEC, "VEC");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_JPEG, "JPEG");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_H264, "H264");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_V3D, "V3D");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ISP, "ISP");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM0, "UNICAM0");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_UNICAM1, "UNICAM1");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2RX, "CCP2RX");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CSI2, "CSI2");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CPI, "CPI");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI0, "DSI0");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_DSI1, "DSI1");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_TRANSPOSER, "TRANSPOSER");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CCP2TX, "CCP2TX");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_CDP, "CDP");
+ rpi_init_power_domain(rpi_domains, RPI_POWER_DOMAIN_ARM, "ARM");
+
+ rpi_domains->parent.ofw_parse = rpi_power_domains_ofw_parse;
+ rt_dm_power_domain_proxy_ofw_bind(&rpi_domains->parent, pdev->parent.ofw_node);
+
+ return RT_EOK;
+
+_fail:
+ rt_free(rpi_domains);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rpi_power_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,bcm2835-power" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_power_driver =
+{
+ .name = "raspberrypi-power",
+ .ids = rpi_power_ofw_ids,
+
+ .probe = rpi_power_probe,
+};
+
+static int rpi_power_drv_register(void)
+{
+ rt_platform_driver_register(&rpi_power_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rpi_power_drv_register);
diff --git a/bsp/raspberry-pi/dm/pwm/Kconfig b/bsp/raspberry-pi/dm/pwm/Kconfig
new file mode 100755
index 0000000000..1400eb66d2
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pwm/Kconfig
@@ -0,0 +1,20 @@
+config RT_PWM_BCM2835
+ bool "BCM2835 PWM support"
+ depends on RT_USING_PINCTRL
+ depends on RT_USING_DM
+ depends on RT_USING_PWM
+ default n
+
+config RT_PWM_BRCMSTB
+ bool "Broadcom STB PWM support"
+ depends on RT_USING_PINCTRL
+ depends on RT_USING_DM
+ depends on RT_USING_PWM
+ default n
+
+config RT_PWM_RP1
+ bool "RP1 PWM support"
+ depends on RT_USING_PINCTRL
+ depends on RT_USING_DM
+ depends on RT_USING_PWM
+ default n
diff --git a/bsp/raspberry-pi/dm/pwm/SConscript b/bsp/raspberry-pi/dm/pwm/SConscript
new file mode 100755
index 0000000000..4d5c0d4c5f
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pwm/SConscript
@@ -0,0 +1,19 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_PWM_BCM2835']):
+ src += ['pwm-bcm2835.c']
+
+if GetDepend(['RT_PWM_BRCMSTB']):
+ src += ['pwm-brcmstb.c']
+
+if GetDepend(['RT_PWM_RP1']):
+ src += ['pwm-rp1.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/pwm/pwm-bcm2835.c b/bsp/raspberry-pi/dm/pwm/pwm-bcm2835.c
new file mode 100755
index 0000000000..45a7693e36
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pwm/pwm-bcm2835.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pwm.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define PWM_CONTROL 0x000
+#define PWM_CONTROL_SHIFT(x) ((x) * 8)
+#define PWM_CONTROL_MASK 0xff
+#define PWM_MODE 0x80 /* Set timer in PWM mode */
+#define PWM_ENABLE (1 << 0)
+#define PWM_POLARITY (1 << 4)
+
+#define PERIOD(x) (((x) * 0x10) + 0x10)
+#define DUTY(x) (((x) * 0x10) + 0x14)
+
+#define PERIOD_MIN 0x2
+#define PWM_NUMBER 2
+
+#define NSEC_PER_SEC 1000000000L
+
+struct bcm2835_pwm
+{
+ struct rt_device_pwm parent;
+
+ void *base;
+ struct rt_clk *clk;
+};
+
+#define raw_to_bcm2835_pwm(raw) rt_container_of(raw, struct bcm2835_pwm, parent)
+
+static rt_err_t bcm2835_pwm_enable(struct bcm2835_pwm *bpwm, int channel, rt_bool_t enable)
+{
+ rt_uint32_t value;
+
+ if (channel >= PWM_NUMBER)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (enable)
+ {
+ value = HWREG32(bpwm->base + PWM_CONTROL);
+ value &= ~(PWM_CONTROL_MASK << PWM_CONTROL_SHIFT(channel));
+ value |= ((PWM_MODE | PWM_ENABLE) << PWM_CONTROL_SHIFT(channel));
+ HWREG32(bpwm->base + PWM_CONTROL) = value;
+ }
+ else
+ {
+ value = HWREG32(bpwm->base + PWM_CONTROL);
+ value &= ~((PWM_CONTROL_MASK | PWM_ENABLE) << PWM_CONTROL_SHIFT(channel));
+ HWREG32(bpwm->base + PWM_CONTROL) = value;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_pwm_config(struct bcm2835_pwm *bpwm,
+ struct rt_pwm_configuration *pwm_cfg)
+{
+ int channel;
+ rt_uint32_t val;
+ rt_uint64_t period_cycles, max_period;
+ rt_ubase_t rate = rt_clk_get_rate(bpwm->clk);
+
+ if (!rate)
+ {
+ LOG_E("Failed to get clock rate");
+
+ return -RT_EINVAL;
+ }
+
+ channel = pwm_cfg->channel;
+
+ /*
+ * period_cycles must be a 32 bit value, so period * rate / NSEC_PER_SEC
+ * must be <= RT_UINT32_MAX. As RT_UINT32_MAX * NSEC_PER_SEC < U64_MAX the
+ * multiplication period * rate doesn't overflow.
+ * To calculate the maximal possible period that guarantees the
+ * above inequality:
+ *
+ * round(period * rate / NSEC_PER_SEC) <= RT_UINT32_MAX
+ * <=> period * rate / NSEC_PER_SEC < RT_UINT32_MAX + 0.5
+ * <=> period * rate < (RT_UINT32_MAX + 0.5) * NSEC_PER_SEC
+ * <=> period < ((RT_UINT32_MAX + 0.5) * NSEC_PER_SEC) / rate
+ * <=> period < ((RT_UINT32_MAX * NSEC_PER_SEC + NSEC_PER_SEC/2) / rate
+ * <=> period <= ceil((RT_UINT32_MAX * NSEC_PER_SEC + NSEC_PER_SEC/2) / rate) - 1
+ */
+ max_period = RT_DIV_ROUND_UP_ULL(
+ (rt_uint64_t)RT_UINT32_MAX * NSEC_PER_SEC + NSEC_PER_SEC / 2, rate) - 1;
+
+ if (pwm_cfg->period > max_period)
+ {
+ return -RT_EINVAL;
+ }
+
+ /* Set period */
+ period_cycles = RT_DIV_ROUND_CLOSEST_ULL(pwm_cfg->period * rate, NSEC_PER_SEC);
+
+ /* Don't accept a period that is too small */
+ if (period_cycles < PERIOD_MIN)
+ {
+ return -RT_EINVAL;
+ }
+
+ HWREG32(bpwm->base + PERIOD(channel)) = period_cycles;
+
+ /* Set duty cycle */
+ val = RT_DIV_ROUND_CLOSEST_ULL(pwm_cfg->pulse * rate, NSEC_PER_SEC);
+ HWREG32(bpwm->base + DUTY(channel)) = val;
+
+ /* Set polarity */
+ val = HWREG32(bpwm->base + PWM_CONTROL);
+
+ if (!pwm_cfg->complementary)
+ {
+ val &= ~(PWM_POLARITY << PWM_CONTROL_SHIFT(channel));
+ }
+ else
+ {
+ val |= PWM_POLARITY << PWM_CONTROL_SHIFT(channel);
+ }
+
+ HWREG32(bpwm->base + PWM_CONTROL) = val;
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_pwm_control(struct rt_device_pwm *pwm, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct bcm2835_pwm *bpwm = raw_to_bcm2835_pwm(pwm);
+ struct rt_pwm_configuration *pwm_cfg = args;
+
+ switch (cmd)
+ {
+ case PWM_CMD_ENABLE:
+ err = bcm2835_pwm_enable(bpwm, pwm_cfg->channel, RT_TRUE);
+ break;
+
+ case PWM_CMD_DISABLE:
+ err = bcm2835_pwm_enable(bpwm, pwm_cfg->channel, RT_FALSE);
+ break;
+
+ case PWM_CMD_SET:
+ case PWM_CMD_SET_PERIOD:
+ case PWM_CMD_SET_PULSE:
+ err = bcm2835_pwm_config(bpwm, pwm_cfg);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+const static struct rt_pwm_ops bcm2835_pwm_ops =
+{
+ .control = bcm2835_pwm_control,
+};
+
+static rt_err_t bcm2835_pwm_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_pwm *bpwm = rt_calloc(1, sizeof(*bpwm));
+
+ if (!bpwm)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bpwm->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!bpwm->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ bpwm->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(bpwm->clk))
+ {
+ err = rt_ptr_err(bpwm->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(bpwm->clk)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = bpwm;
+
+ bpwm->parent.parent.ofw_node = dev->ofw_node;
+
+ rt_dm_dev_set_name_auto(&bpwm->parent.parent, "pwm");
+ rt_device_pwm_register(&bpwm->parent, rt_dm_dev_get_name(&bpwm->parent.parent), &bcm2835_pwm_ops, bpwm);
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, bpwm);
+
+ return RT_EOK;
+
+_fail:
+ if (bpwm->base)
+ {
+ rt_iounmap(bpwm->base);
+ }
+
+ if (!rt_is_err_or_null(bpwm->clk))
+ {
+ rt_clk_disable_unprepare(bpwm->clk);
+ rt_clk_put(bpwm->clk);
+ }
+
+ rt_free(bpwm);
+
+ return err;
+}
+
+static rt_err_t bcm2835_pwm_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_pwm *bpwm = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ for (int channel = 0; channel < PWM_NUMBER; ++channel)
+ {
+ bcm2835_pwm_enable(bpwm, channel, RT_FALSE);
+ }
+
+ rt_device_unregister(&bpwm->parent.parent);
+
+ rt_clk_disable_unprepare(bpwm->clk);
+ rt_clk_put(bpwm->clk);
+
+ rt_free(bpwm);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_pwm_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-pwm", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_pwm_driver =
+{
+ .name = "bcm2835-pwm",
+ .ids = bcm2835_pwm_ofw_ids,
+
+ .probe = bcm2835_pwm_probe,
+ .remove = bcm2835_pwm_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_pwm_driver);
diff --git a/bsp/raspberry-pi/dm/pwm/pwm-brcmstb.c b/bsp/raspberry-pi/dm/pwm/pwm-brcmstb.c
new file mode 100755
index 0000000000..d90d92f668
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pwm/pwm-brcmstb.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pwm.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define PWM_CTRL 0x00
+#define CTRL_START RT_BIT(0)
+#define CTRL_OEB RT_BIT(1)
+#define CTRL_FORCE_HIGH RT_BIT(2)
+#define CTRL_OPENDRAIN RT_BIT(3)
+#define CTRL_CHAN_OFFS 4
+
+#define PWM_CTRL2 0x04
+#define CTRL2_OUT_SELECT RT_BIT(0)
+
+#define PWM_CH_SIZE 0x8
+
+#define PWM_CWORD_MSB(ch) (0x08 + ((ch) * PWM_CH_SIZE))
+#define PWM_CWORD_LSB(ch) (0x0c + ((ch) * PWM_CH_SIZE))
+
+/* Number of bits for the CWORD value */
+#define CWORD_BIT_SIZE 16
+
+/*
+ * Maximum control word value allowed when variable-frequency PWM is used as a
+ * clock for the constant-frequency PMW.
+ */
+#define CONST_VAR_F_MAX 32768
+#define CONST_VAR_F_MIN 1
+
+#define PWM_ON(ch) (0x18 + ((ch) * PWM_CH_SIZE))
+#define PWM_ON_MIN 1
+#define PWM_PERIOD(ch) (0x1c + ((ch) * PWM_CH_SIZE))
+#define PWM_PERIOD_MIN 0
+
+#define PWM_ON_PERIOD_MAX 0xff
+
+#define PWM_NUMBER 2
+
+#define NSEC_PER_SEC 1000000000L
+
+struct brcmstb_pwm
+{
+ struct rt_device_pwm parent;
+
+ void *base;
+ struct rt_clk *clk;
+};
+
+#define raw_to_brcmstb_pwm(raw) rt_container_of(raw, struct brcmstb_pwm, parent)
+
+#ifndef mul_u64_u64_div_u64
+static rt_uint64_t mul_u64_u64_div_u64(rt_uint64_t a, rt_uint64_t b, rt_uint64_t c)
+{
+ /* overflow in rt-thread is unlikely */
+ return a * b / c;
+}
+#endif /* mul_u64_u64_div_u64 */
+
+static rt_err_t brcmstb_pwm_enable(struct brcmstb_pwm *bpwm, int channel, rt_bool_t enable)
+{
+ rt_uint32_t shift, value;
+
+ if (channel >= PWM_NUMBER)
+ {
+ return -RT_EINVAL;
+ }
+
+ shift = channel * CTRL_CHAN_OFFS;
+ value = HWREG32(bpwm->base + PWM_CTRL);
+
+ if (enable)
+ {
+ value &= ~(CTRL_OEB << shift);
+ value |= (CTRL_START | CTRL_OPENDRAIN) << shift;
+ }
+ else
+ {
+ value &= ~((CTRL_START | CTRL_OPENDRAIN) << shift);
+ value |= CTRL_OEB << shift;
+ }
+
+ HWREG32(bpwm->base + PWM_CTRL) = value;
+
+ return RT_EOK;
+}
+
+/*
+ * Fv is derived from the variable frequency output. The variable frequency
+ * output is configured using this formula:
+ *
+ * W = cword, if cword < 2 ^ 15 else 16-bit 2's complement of cword
+ *
+ * Fv = W x 2 ^ -16 x 27Mhz (reference clock)
+ *
+ * The period is: (period + 1) / Fv and "on" time is on / (period + 1)
+ *
+ * The PWM core framework specifies that the "duty_ns" parameter is in fact the
+ * "on" time, so this translates directly into our HW programming here.
+ */
+static rt_err_t brcmstb_pwm_config(struct brcmstb_pwm *bpwm,
+ struct rt_pwm_configuration *pwm_cfg)
+{
+ rt_ubase_t pc, dc, cword = CONST_VAR_F_MAX;
+ rt_uint32_t value, channel, period_ns, duty_ns;
+
+ channel = pwm_cfg->channel;
+ period_ns = pwm_cfg->period;
+ duty_ns = pwm_cfg->pulse;
+
+ /*
+ * If asking for a duty_ns equal to period_ns, we need to substract
+ * the period value by 1 to make it shorter than the "on" time and
+ * produce a flat 100% duty cycle signal, and max out the "on" time
+ */
+ if (duty_ns == period_ns)
+ {
+ dc = PWM_ON_PERIOD_MAX;
+ pc = PWM_ON_PERIOD_MAX - 1;
+ goto _done;
+ }
+
+ while (RT_TRUE)
+ {
+ rt_uint64_t rate;
+
+ /* Calculate the base rate from base frequency and current cword */
+ rate = (rt_uint64_t)rt_clk_get_rate(bpwm->clk) * (rt_uint64_t)cword;
+ rate >>= CWORD_BIT_SIZE;
+
+ pc = mul_u64_u64_div_u64(period_ns, rate, NSEC_PER_SEC);
+ dc = mul_u64_u64_div_u64(duty_ns + 1, rate, NSEC_PER_SEC);
+
+ /*
+ * We can be called with separate duty and period updates,
+ * so do not reject dc == 0 right away
+ */
+ if (pc == PWM_PERIOD_MIN || (dc < PWM_ON_MIN && duty_ns))
+ {
+ return -RT_EINVAL;
+ }
+
+ /* We converged on a calculation */
+ if (pc <= PWM_ON_PERIOD_MAX && dc <= PWM_ON_PERIOD_MAX)
+ {
+ break;
+ }
+
+ /*
+ * The cword needs to be a power of 2 for the variable
+ * frequency generator to output a 50% duty cycle variable
+ * frequency which is used as input clock to the fixed
+ * frequency generator.
+ */
+ cword >>= 1;
+
+ /* Desired periods are too large, we do not have a divider for them */
+ if (cword < CONST_VAR_F_MIN)
+ {
+ return -RT_EINVAL;
+ }
+ }
+
+_done:
+ /*
+ * Configure the defined "cword" value to have the variable frequency
+ * generator output a base frequency for the constant frequency
+ * generator to derive from.
+ */
+ HWREG32(bpwm->base + PWM_CWORD_MSB(channel)) = cword >> 8;
+ HWREG32(bpwm->base + PWM_CWORD_LSB(channel)) = cword & 0xff;
+
+ /* Select constant frequency signal output */
+ value = HWREG32(bpwm->base + PWM_CTRL2);
+ value |= CTRL2_OUT_SELECT << (channel * CTRL_CHAN_OFFS);
+ HWREG32(bpwm->base + PWM_CTRL2) = value;
+
+ /* Configure on and period value */
+ HWREG32(bpwm->base + PWM_PERIOD(channel)) = pc;
+ HWREG32(bpwm->base + PWM_ON(channel)) = dc;
+
+ return 0;
+}
+
+static rt_err_t brcmstb_pwm_control(struct rt_device_pwm *pwm, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct brcmstb_pwm *bpwm = raw_to_brcmstb_pwm(pwm);
+ struct rt_pwm_configuration *pwm_cfg = args;
+
+ switch (cmd)
+ {
+ case PWM_CMD_ENABLE:
+ err = brcmstb_pwm_enable(bpwm, pwm_cfg->channel, RT_TRUE);
+ break;
+
+ case PWM_CMD_DISABLE:
+ err = brcmstb_pwm_enable(bpwm, pwm_cfg->channel, RT_FALSE);
+ break;
+
+ case PWM_CMD_SET:
+ case PWM_CMD_SET_PERIOD:
+ case PWM_CMD_SET_PULSE:
+ err = brcmstb_pwm_config(bpwm, pwm_cfg);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+const static struct rt_pwm_ops brcmstb_pwm_ops =
+{
+ .control = brcmstb_pwm_control,
+};
+
+static rt_err_t brcmstb_pwm_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct brcmstb_pwm *bpwm = rt_calloc(1, sizeof(*bpwm));
+
+ if (!bpwm)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bpwm->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!bpwm->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ bpwm->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(bpwm->clk))
+ {
+ err = rt_ptr_err(bpwm->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(bpwm->clk)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = bpwm;
+
+ bpwm->parent.parent.ofw_node = dev->ofw_node;
+
+ rt_dm_dev_set_name_auto(&bpwm->parent.parent, "pwm");
+ rt_device_pwm_register(&bpwm->parent, rt_dm_dev_get_name(&bpwm->parent.parent), &brcmstb_pwm_ops, bpwm);
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, bpwm);
+
+ return RT_EOK;
+
+_fail:
+ if (bpwm->base)
+ {
+ rt_iounmap(bpwm->base);
+ }
+
+ if (!rt_is_err_or_null(bpwm->clk))
+ {
+ rt_clk_disable_unprepare(bpwm->clk);
+ rt_clk_put(bpwm->clk);
+ }
+
+ rt_free(bpwm);
+
+ return err;
+}
+
+static rt_err_t brcmstb_pwm_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct brcmstb_pwm *bpwm = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ for (int channel = 0; channel < PWM_NUMBER; ++channel)
+ {
+ brcmstb_pwm_enable(bpwm, channel, RT_FALSE);
+ }
+
+ rt_device_unregister(&bpwm->parent.parent);
+
+ rt_clk_disable_unprepare(bpwm->clk);
+ rt_clk_put(bpwm->clk);
+
+ rt_free(bpwm);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id brcmstb_pwm_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm7038-pwm", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmstb_pwm_driver =
+{
+ .name = "brcmstb-pwm",
+ .ids = brcmstb_pwm_ofw_ids,
+
+ .probe = brcmstb_pwm_probe,
+ .remove = brcmstb_pwm_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(brcmstb_pwm_driver);
diff --git a/bsp/raspberry-pi/dm/pwm/pwm-rp1.c b/bsp/raspberry-pi/dm/pwm/pwm-rp1.c
new file mode 100755
index 0000000000..27553c1b4e
--- /dev/null
+++ b/bsp/raspberry-pi/dm/pwm/pwm-rp1.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "pwm.rp1"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define PWM_GLOBAL_CTRL 0x000
+#define PWM_CHANNEL_CTRL(x) (0x014 + ((x) * 16))
+#define PWM_RANGE(x) (0x018 + ((x) * 16))
+#define PWM_DUTY(x) (0x020 + ((x) * 16))
+
+/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */
+#define PWM_CHANNEL_DEFAULT (RT_BIT(8) + RT_BIT(0))
+#define PWM_CHANNEL_ENABLE(x) RT_BIT(x)
+#define PWM_POLARITY RT_BIT(3)
+#define SET_UPDATE RT_BIT(31)
+#define PWM_MODE_MASK RT_GENMASK(1, 0)
+#define PWM_POLARITY_INVERTED RT_BIT(0)
+
+#define PWM_NUMBER 4
+
+#define NSEC_PER_SEC 1000000000L
+
+struct rp1_pwm
+{
+ struct rt_device_pwm parent;
+
+ void *base;
+ struct rt_clk *clk;
+
+ rt_bool_t inverted[PWM_NUMBER];
+ struct rt_pwm_configuration config[PWM_NUMBER];
+};
+
+#define raw_to_rp1_pwm(raw) rt_container_of(raw, struct rp1_pwm, parent)
+
+static void rp1_pwm_apply_config(struct rp1_pwm *rpwm)
+{
+ rt_uint32_t value;
+
+ value = HWREG32(rpwm->base + PWM_GLOBAL_CTRL);
+ value |= SET_UPDATE;
+ HWREG32(rpwm->base + PWM_GLOBAL_CTRL) = value;
+}
+
+static rt_err_t rp1_pwm_enable(struct rp1_pwm *rpwm, int channel, rt_bool_t enable)
+{
+ rt_uint32_t value;
+
+ if (channel >= PWM_NUMBER)
+ {
+ return -RT_EINVAL;
+ }
+
+ if (enable)
+ {
+ value = PWM_CHANNEL_DEFAULT;
+
+ if (rpwm->config[channel].complementary || rpwm->inverted[channel])
+ {
+ value |= PWM_POLARITY;
+ }
+
+ HWREG32(rpwm->base + PWM_CHANNEL_CTRL(channel)) = value;
+
+ value = HWREG32(rpwm->base + PWM_GLOBAL_CTRL);
+ value |= PWM_CHANNEL_ENABLE(channel);
+ HWREG32(rpwm->base + PWM_GLOBAL_CTRL) = value;
+ }
+ else
+ {
+ value = HWREG32(rpwm->base + PWM_GLOBAL_CTRL);
+ value &= ~PWM_CHANNEL_ENABLE(channel);
+ HWREG32(rpwm->base + PWM_GLOBAL_CTRL) = value;
+ }
+
+ rp1_pwm_apply_config(rpwm);
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_pwm_config(struct rp1_pwm *rpwm,
+ struct rt_pwm_configuration *pwm_cfg)
+{
+ int channel;
+ rt_uint32_t value;
+ rt_ubase_t clk_period, clk_rate = rt_clk_get_rate(rpwm->clk);
+
+ if (!clk_rate)
+ {
+ LOG_E("Failed to get clock rate");
+
+ return -RT_EINVAL;
+ }
+
+ channel = pwm_cfg->channel;
+
+ if (channel >= PWM_NUMBER)
+ {
+ return -RT_EINVAL;
+ }
+
+ /* Period */
+ clk_period = RT_DIV_ROUND_CLOSEST(NSEC_PER_SEC, clk_rate);
+
+ HWREG32(rpwm->base + PWM_DUTY(channel)) =
+ RT_DIV_ROUND_CLOSEST(pwm_cfg->pulse, clk_period);
+
+ /* Duty cycle */
+ HWREG32(rpwm->base + PWM_RANGE(channel)) =
+ RT_DIV_ROUND_CLOSEST(pwm_cfg->period, clk_period);
+
+ /* Polarity */
+ value = HWREG32(rpwm->base + PWM_CHANNEL_CTRL(channel));
+ if (!pwm_cfg->complementary && !rpwm->inverted[channel])
+ {
+ value &= ~PWM_POLARITY;
+ }
+ else
+ {
+ value |= PWM_POLARITY;
+ }
+ HWREG32(rpwm->base + PWM_CHANNEL_CTRL(channel)) = value;
+
+ rp1_pwm_apply_config(rpwm);
+
+ rpwm->config[channel] = *pwm_cfg;
+ rpwm->config[channel].complementary =
+ pwm_cfg->complementary || rpwm->inverted[channel];
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_pwm_get(struct rp1_pwm *rpwm,
+ struct rt_pwm_configuration *pwm_cfg)
+{
+ int channel = pwm_cfg->channel;
+
+ if (channel >= PWM_NUMBER)
+ {
+ return -RT_EINVAL;
+ }
+
+ *pwm_cfg = rpwm->config[channel];
+
+ return RT_EOK;
+}
+
+static rt_err_t rp1_pwm_control(struct rt_device_pwm *pwm, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct rp1_pwm *rpwm = raw_to_rp1_pwm(pwm);
+ struct rt_pwm_configuration *pwm_cfg = args;
+
+ switch (cmd)
+ {
+ case PWM_CMD_ENABLE:
+ err = rp1_pwm_enable(rpwm, pwm_cfg->channel, RT_TRUE);
+ break;
+
+ case PWM_CMD_DISABLE:
+ err = rp1_pwm_enable(rpwm, pwm_cfg->channel, RT_FALSE);
+ break;
+
+ case PWM_CMD_SET:
+ case PWM_CMD_SET_PERIOD:
+ case PWM_CMD_SET_PULSE:
+ err = rp1_pwm_config(rpwm, pwm_cfg);
+ break;
+
+ case PWM_CMD_GET:
+ err = rp1_pwm_get(rpwm, pwm_cfg);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+const static struct rt_pwm_ops rp1_pwm_ops =
+{
+ .control = rp1_pwm_control,
+};
+
+static void rp1_pwm_parse_dt_flags(struct rp1_pwm *rpwm,
+ struct rt_ofw_node *pwm_np)
+{
+ struct rt_ofw_node *np;
+
+ rt_ofw_foreach_allnodes(np)
+ {
+ int index = 0;
+ struct rt_ofw_cell_args args;
+
+ while (!rt_ofw_parse_phandle_cells(np, "pwms", "#pwm-cells",
+ index++, &args))
+ {
+ if (args.data == pwm_np && args.args_count >= 3 &&
+ args.args[0] < PWM_NUMBER)
+ {
+ rpwm->inverted[args.args[0]] =
+ !!(args.args[2] & PWM_POLARITY_INVERTED);
+ }
+
+ if (args.data)
+ {
+ rt_ofw_node_put(args.data);
+ }
+ }
+ }
+}
+
+static rt_err_t rp1_pwm_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_pwm *rpwm = rt_calloc(1, sizeof(*rpwm));
+
+ if (!rpwm)
+ {
+ return -RT_ENOMEM;
+ }
+
+ rpwm->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!rpwm->base)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ rpwm->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(rpwm->clk))
+ {
+ err = rt_ptr_err(rpwm->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(rpwm->clk)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = rpwm;
+
+ rpwm->parent.parent.ofw_node = dev->ofw_node;
+
+ rp1_pwm_parse_dt_flags(rpwm, dev->ofw_node);
+
+ for (int channel = 0; channel < PWM_NUMBER; ++channel)
+ {
+ rp1_pwm_enable(rpwm, channel, RT_FALSE);
+
+ HWREG32(rpwm->base + PWM_CHANNEL_CTRL(channel)) =
+ PWM_CHANNEL_DEFAULT |
+ (rpwm->inverted[channel] ? PWM_POLARITY : 0);
+ rpwm->config[channel].channel = channel;
+ rpwm->config[channel].complementary = rpwm->inverted[channel];
+ }
+
+ rp1_pwm_apply_config(rpwm);
+
+ rt_dm_dev_set_name_auto(&rpwm->parent.parent, "pwm");
+ rt_device_pwm_register(&rpwm->parent, rt_dm_dev_get_name(&rpwm->parent.parent), &rp1_pwm_ops, rpwm);
+
+ rt_dm_dev_bind_fwdata(dev, RT_NULL, rpwm);
+
+ return RT_EOK;
+
+_fail:
+ if (rpwm->base)
+ {
+ rt_iounmap(rpwm->base);
+ }
+
+ if (!rt_is_err_or_null(rpwm->clk))
+ {
+ rt_clk_disable_unprepare(rpwm->clk);
+ rt_clk_put(rpwm->clk);
+ }
+
+ rt_free(rpwm);
+
+ return err;
+}
+
+static rt_err_t rp1_pwm_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct rp1_pwm *rpwm = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ for (int channel = 0; channel < PWM_NUMBER; ++channel)
+ {
+ rp1_pwm_enable(rpwm, channel, RT_FALSE);
+ }
+
+ rt_device_unregister(&rpwm->parent.parent);
+
+ rt_clk_disable_unprepare(rpwm->clk);
+ rt_clk_put(rpwm->clk);
+
+ rt_free(rpwm);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rp1_pwm_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rp1-pwm" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rp1_pwm_driver =
+{
+ .name = "rp1-pwm",
+ .ids = rp1_pwm_ofw_ids,
+
+ .probe = rp1_pwm_probe,
+ .remove = rp1_pwm_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rp1_pwm_driver);
diff --git a/bsp/raspberry-pi/dm/reset/Kconfig b/bsp/raspberry-pi/dm/reset/Kconfig
new file mode 100755
index 0000000000..91acd93003
--- /dev/null
+++ b/bsp/raspberry-pi/dm/reset/Kconfig
@@ -0,0 +1,15 @@
+config RT_RESET_BRCMSTB_RESCAL
+ bool "Broadcom STB RESCAL reset controller"
+ depends on RT_USING_RESET
+ default n
+
+config RT_RESET_BRCMSTB
+ bool "Broadcom STB reset controller"
+ depends on RT_USING_RESET
+ default n
+
+config RT_RESET_RASPBERRYPI
+ bool "Raspberry Pi 4 Firmware Reset Driver"
+ depends on RT_USING_RESET
+ depends on RT_FIRMWARE_RASPBERRYPI
+ default n
diff --git a/bsp/raspberry-pi/dm/reset/SConscript b/bsp/raspberry-pi/dm/reset/SConscript
new file mode 100755
index 0000000000..8d8bccc20d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/reset/SConscript
@@ -0,0 +1,19 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_RESET_BRCMSTB_RESCAL']):
+ src += ['reset-brcmstb-rescal.c']
+
+if GetDepend(['RT_RESET_BRCMSTB']):
+ src += ['reset-brcmstb.c']
+
+if GetDepend(['RT_RESET_RASPBERRYPI']):
+ src += ['reset-raspberrypi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/reset/reset-brcmstb-rescal.c b/bsp/raspberry-pi/dm/reset/reset-brcmstb-rescal.c
new file mode 100755
index 0000000000..9a2e8cb254
--- /dev/null
+++ b/bsp/raspberry-pi/dm/reset/reset-brcmstb-rescal.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "reset.brcmstb-rescal"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+
+#define BRCM_RESCAL_START 0x0
+#define BRCM_RESCAL_START_BIT RT_BIT(0)
+#define BRCM_RESCAL_CTRL 0x4
+#define BRCM_RESCAL_STATUS 0x8
+#define BRCM_RESCAL_STATUS_BIT RT_BIT(0)
+
+struct brcm_rescal_reset
+{
+ struct rt_reset_controller parent;
+
+ void *regs;
+};
+
+static rt_err_t brcm_rescal_reset_ofw_parse(struct rt_reset_control *rstc, struct rt_ofw_cell_args *args)
+{
+ args->args[0] = 0;
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_rescal_reset_reset(struct rt_reset_control *rstc)
+{
+ rt_uint32_t reg;
+ struct brcm_rescal_reset *brrst = rstc->rstcer->priv;
+
+ reg = HWREG32(brrst->regs + BRCM_RESCAL_START);
+ HWREG32(brrst->regs + BRCM_RESCAL_START) = reg | BRCM_RESCAL_START_BIT;
+ reg = HWREG32(brrst->regs + BRCM_RESCAL_START);
+
+ if (!(reg & BRCM_RESCAL_START_BIT))
+ {
+ LOG_E("Failed to start SATA/PCIe rescal");
+
+ return -RT_EIO;
+ }
+
+ for (rt_uint32_t time = 0; time < 1000; time += 100)
+ {
+ reg = HWREG32(brrst->regs + BRCM_RESCAL_STATUS);
+
+ if (reg & BRCM_RESCAL_STATUS_BIT)
+ {
+ goto _status_ok;
+ }
+
+ rt_hw_us_delay(100);
+
+ rt_hw_cpu_relax();
+ }
+
+ LOG_E("Time out on SATA/PCIe rescal");
+
+ return -RT_ETIMEOUT;
+
+_status_ok:
+ reg = HWREG32(brrst->regs + BRCM_RESCAL_START);
+ HWREG32(brrst->regs + BRCM_RESCAL_START) = reg & ~BRCM_RESCAL_START_BIT;
+
+ LOG_D("SATA/PCIe rescal success");
+
+ return RT_EOK;
+}
+
+static rt_err_t brcm_rescal_reset_assert(struct rt_reset_control *rstc)
+{
+ return RT_EOK;
+}
+
+static rt_err_t brcm_rescal_reset_deassert(struct rt_reset_control *rstc)
+{
+ return brcm_rescal_reset_reset(rstc);
+}
+
+const static struct rt_reset_control_ops brcm_rescal_reset_ops =
+{
+ .ofw_parse = brcm_rescal_reset_ofw_parse,
+ .reset = brcm_rescal_reset_reset,
+ .assert = brcm_rescal_reset_assert,
+ .deassert = brcm_rescal_reset_deassert,
+};
+
+static rt_err_t brcm_rescal_reset_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_reset_controller *rstcer;
+ struct rt_device *dev = &pdev->parent;
+ struct brcm_rescal_reset *brrst = rt_calloc(1, sizeof(*brrst));
+
+ if (!brrst)
+ {
+ return -RT_ENOMEM;
+ }
+
+ brrst->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!brrst->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ rstcer = &brrst->parent;
+
+ rstcer->priv = brrst;
+ rstcer->ofw_node = dev->ofw_node;
+ rstcer->ops = &brcm_rescal_reset_ops;
+
+ if ((err = rt_reset_controller_register(rstcer)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (brrst->regs)
+ {
+ rt_iounmap(brrst->regs);
+ }
+
+ rt_free(brrst);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id brcm_rescal_reset_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm7216-pcie-sata-rescal" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcm_rescal_reset_driver =
+{
+ .name = "reset-brcm-rescal",
+ .ids = brcm_rescal_reset_ofw_ids,
+
+ .probe = brcm_rescal_reset_probe,
+};
+
+static int brcm_rescal_reset_register(void)
+{
+ rt_platform_driver_register(&brcm_rescal_reset_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(brcm_rescal_reset_register);
diff --git a/bsp/raspberry-pi/dm/reset/reset-brcmstb.c b/bsp/raspberry-pi/dm/reset/reset-brcmstb.c
new file mode 100755
index 0000000000..1c71afb47d
--- /dev/null
+++ b/bsp/raspberry-pi/dm/reset/reset-brcmstb.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "reset.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define SW_INIT_SET 0x00
+#define SW_INIT_CLEAR 0x04
+#define SW_INIT_STATUS 0x08
+
+#define SW_INIT_BIT(id) RT_BIT((id) & 0x1f)
+#define SW_INIT_BANK(id) ((id) >> 5)
+
+/*
+ * A full bank contains extra registers that we are not utilizing but still
+ * qualify as a single bank.
+ */
+#define SW_INIT_BANK_SIZE 0x18
+
+struct brcmstb_reset
+{
+ struct rt_reset_controller parent;
+
+ void *regs;
+};
+
+static rt_err_t brcmstb_reset_assert(struct rt_reset_control *rstc)
+{
+ struct brcmstb_reset *brst = rstc->rstcer->priv;
+ rt_uint32_t off = SW_INIT_BANK(rstc->id) * SW_INIT_BANK_SIZE;
+
+ HWREG32(brst->regs + off + SW_INIT_SET) = SW_INIT_BIT(rstc->id);
+
+ return RT_EOK;
+}
+
+static rt_err_t brcmstb_reset_deassert(struct rt_reset_control *rstc)
+{
+ struct brcmstb_reset *brst = rstc->rstcer->priv;
+ unsigned int off = SW_INIT_BANK(rstc->id) * SW_INIT_BANK_SIZE;
+
+ HWREG32(brst->regs + off + SW_INIT_CLEAR) = SW_INIT_BIT(rstc->id);
+
+ /*
+ * Maximum reset delay after de-asserting a line and seeing block
+ * operation is typically 14us for the worst case, build some slack here.
+ */
+ rt_hw_us_delay(150);
+
+ return RT_EOK;
+}
+
+static int brcmstb_reset_status(struct rt_reset_control *rstc)
+{
+ struct brcmstb_reset *brst = rstc->rstcer->priv;
+ rt_uint32_t off = SW_INIT_BANK(rstc->id) * SW_INIT_BANK_SIZE;
+
+ return HWREG32(brst->regs + off + SW_INIT_STATUS) & SW_INIT_BIT(rstc->id);
+}
+
+const static struct rt_reset_control_ops brcmstb_reset_ops =
+{
+ .assert = brcmstb_reset_assert,
+ .deassert = brcmstb_reset_deassert,
+ .status = brcmstb_reset_status,
+};
+
+static rt_err_t brcmstb_reset_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_reset_controller *rstcer;
+ struct rt_device *dev = &pdev->parent;
+ struct brcmstb_reset *brst = rt_calloc(1, sizeof(*brst));
+
+ if (!brst)
+ {
+ return -RT_ENOMEM;
+ }
+
+ brst->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!brst->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ rstcer = &brst->parent;
+
+ rstcer->priv = brst;
+ rstcer->ofw_node = dev->ofw_node;
+ rstcer->ops = &brcmstb_reset_ops;
+
+ if ((err = rt_reset_controller_register(rstcer)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ if (brst->regs)
+ {
+ rt_iounmap(brst->regs);
+ }
+
+ rt_free(brst);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id brcmstb_reset_ofw_ids[] =
+{
+ { .compatible = "brcm,brcmstb-reset" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmstb_reset_driver =
+{
+ .name = "reset-brcmstb",
+ .ids = brcmstb_reset_ofw_ids,
+
+ .probe = brcmstb_reset_probe,
+};
+
+static int brcmstb_reset_register(void)
+{
+ rt_platform_driver_register(&brcmstb_reset_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(brcmstb_reset_register);
diff --git a/bsp/raspberry-pi/dm/reset/reset-raspberrypi.c b/bsp/raspberry-pi/dm/reset/reset-raspberrypi.c
new file mode 100755
index 0000000000..8b2708a921
--- /dev/null
+++ b/bsp/raspberry-pi/dm/reset/reset-raspberrypi.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "reset.raspberrypi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
+
+struct rpi_reset
+{
+ struct rt_reset_controller parent;
+
+ struct rpi_firmware *rpi_fw;
+};
+
+static rt_err_t rpi_reset_reset(struct rt_reset_control *rstc)
+{
+ rt_err_t err = RT_EOK;
+ rt_uint32_t dev_addr;
+ struct rpi_reset *rrst = rstc->rstcer->priv;
+
+ switch (rstc->id)
+ {
+ case RASPBERRYPI_FIRMWARE_RESET_ID_USB:
+ /*
+ * The Raspberry Pi 4 gets its USB functionality from VL805, a
+ * PCIe chip that implements xHCI. After a PCI reset, VL805's
+ * firmware may either be loaded directly from an EEPROM or, if
+ * not present, by the SoC's co-processor, VideoCore. rpi's
+ * VideoCore OS contains both the non public firmware load
+ * logic and the VL805 firmware blob. This triggers the
+ * aforementioned process.
+ *
+ * VideoCore expects the PCI location encoded as:
+ * PCI_BUS << 20 | PCI_SLOT << 15 | PCI_FUNC << 12
+ *
+ * Pi4 wires VL805 at bus 1, slot 0, function 0, so the address
+ * passed to NOTIFY_XHCI_RESET is 0x00100000.
+ */
+ dev_addr = (1U << 20) | (0U << 15) | (0U << 12);
+
+ err = rpi_firmware_property(rrst->rpi_fw, RPI_FIRMWARE_NOTIFY_XHCI_RESET,
+ &dev_addr, sizeof(dev_addr));
+ if (err)
+ {
+ break;
+ }
+
+ /* Wait for vl805 to startup */
+ rt_hw_us_delay(500);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+const static struct rt_reset_control_ops rpi_reset_ops =
+{
+ .reset = rpi_reset_reset,
+};
+
+static rt_err_t rpi_reset_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_reset_controller *rstcer;
+ struct rt_ofw_node *np = pdev->parent.ofw_node, *fw_np;
+ struct rpi_reset *rrst = rt_calloc(1, sizeof(*rrst));
+
+ if (!rrst)
+ {
+ return -RT_ENOMEM;
+ }
+
+ if (!np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ fw_np = rt_ofw_get_parent(np);
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rrst->rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rrst->rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rstcer = &rrst->parent;
+
+ rstcer->priv = rrst;
+ rstcer->ofw_node = np;
+ rstcer->ops = &rpi_reset_ops;
+
+ if ((err = rt_reset_controller_register(rstcer)))
+ {
+ goto _fail;
+ }
+
+ return RT_EOK;
+
+_fail:
+ rt_free(rrst);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id rpi_reset_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,firmware-reset" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_reset_driver =
+{
+ .name = "reset-raspberrypi",
+ .ids = rpi_reset_ofw_ids,
+
+ .probe = rpi_reset_probe,
+};
+
+static int rpi_reset_register(void)
+{
+ rt_platform_driver_register(&rpi_reset_driver);
+
+ return 0;
+}
+INIT_SUBSYS_EXPORT(rpi_reset_register);
diff --git a/bsp/raspberry-pi/dm/rtc/Kconfig b/bsp/raspberry-pi/dm/rtc/Kconfig
new file mode 100755
index 0000000000..ed22c9eb7b
--- /dev/null
+++ b/bsp/raspberry-pi/dm/rtc/Kconfig
@@ -0,0 +1,5 @@
+config RT_RTC_RPI
+ bool "Raspberry Pi RTC"
+ depends on RT_FIRMWARE_RASPBERRYPI
+ select RT_USING_ALARM
+ default n
diff --git a/bsp/raspberry-pi/dm/rtc/SConscript b/bsp/raspberry-pi/dm/rtc/SConscript
new file mode 100755
index 0000000000..eff1275ba3
--- /dev/null
+++ b/bsp/raspberry-pi/dm/rtc/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include', cwd + '/../../../../components/drivers/rtc']
+
+if GetDepend(['RT_RTC_RPI']):
+ src += ['rtc-rpi.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/rtc/rtc-rpi.c b/bsp/raspberry-pi/dm/rtc/rtc-rpi.c
new file mode 100755
index 0000000000..f64a605738
--- /dev/null
+++ b/bsp/raspberry-pi/dm/rtc/rtc-rpi.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-26 GuEe-GUI first version
+ */
+
+#define DBG_TAG "rtc.rpi"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "rtc_dm.h"
+#include <firmware-raspberrypi.h>
+
+enum
+{
+ RTC_TIME,
+ RTC_ALARM,
+ RTC_ALARM_PENDING,
+ RTC_ALARM_ENABLE,
+ RTC_BBAT_CHG_VOLTS,
+ RTC_BBAT_CHG_VOLTS_MIN,
+ RTC_BBAT_CHG_VOLTS_MAX,
+ RTC_BBAT_VOLTS
+};
+
+struct rpi_rtc
+{
+ struct rt_device parent;
+
+ struct rpi_firmware *rpi_fw;
+ rt_uint32_t bbat_vchg_microvolts;
+
+ struct rt_mutex lock;
+ struct rt_timer alarm_mon;
+ struct rt_rtc_wkalarm wkalarm;
+};
+
+#define raw_to_rpi_rtc(raw) rt_container_of(raw, struct rpi_rtc, parent)
+
+static rt_err_t rpi_rtc_alarm_clear_pending(struct rpi_rtc *rrtc)
+{
+ rt_uint32_t data[2] = { RTC_ALARM_PENDING, 1 };
+
+ return rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_SET_RTC_REG,
+ &data, sizeof(data));
+}
+
+static rt_err_t rpi_rtc_set_charge_voltage(struct rpi_rtc *rrtc)
+{
+ rt_err_t err;
+ rt_uint32_t data[2] = { RTC_BBAT_CHG_VOLTS, rrtc->bbat_vchg_microvolts };
+
+ err = rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_SET_RTC_REG,
+ &data, sizeof(data));
+
+ if (err)
+ {
+ LOG_E("Failed to set trickle charge voltage to %uuV error = %s",
+ rrtc->bbat_vchg_microvolts, rt_strerror(err));
+ }
+ else if (rrtc->bbat_vchg_microvolts)
+ {
+ LOG_I("Trickle charging enabled at %uuV", rrtc->bbat_vchg_microvolts);
+ }
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_alarm_irq_is_enabled(struct rpi_rtc *rrtc,
+ rt_bool_t *enabled)
+{
+ rt_err_t err;
+ rt_uint32_t data[2] = { RTC_ALARM_ENABLE };
+
+ err = rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_GET_RTC_REG,
+ &data, sizeof(data));
+
+ *enabled = !!(data[1] & 0x1);
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_alarm_irq_enable(struct rpi_rtc *rrtc, rt_bool_t enabled)
+{
+ rt_uint32_t data[2] = { RTC_ALARM_ENABLE, enabled };
+
+ return rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_SET_RTC_REG,
+ &data, sizeof(data));
+}
+
+static rt_err_t rpi_rtc_read_time(struct rpi_rtc *rrtc, time_t *sec)
+{
+ rt_err_t err;
+ rt_uint32_t data[2] = { RTC_TIME };
+
+ err = rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_GET_RTC_REG,
+ &data, sizeof(data));
+
+ *sec = data[1];
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_set_time(struct rpi_rtc *rrtc, time_t *sec)
+{
+ rt_uint32_t data[2] = { RTC_TIME, (rt_uint32_t)*sec };
+
+ return rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_SET_RTC_REG,
+ &data, sizeof(data));
+}
+
+static rt_err_t rpi_rtc_read_alarm(struct rpi_rtc *rrtc,
+ struct rt_rtc_wkalarm *alarm)
+{
+ rt_err_t err;
+ rt_uint32_t data[2] = { RTC_ALARM };
+
+ if (!(err = rpi_rtc_alarm_irq_is_enabled(rrtc, &alarm->enable)))
+ {
+ err = rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_GET_RTC_REG,
+ &data, sizeof(data));
+ }
+
+ rtc_timestamp_to_wkalarm(data[1], alarm);
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_set_alarm(struct rpi_rtc *rrtc,
+ struct rt_rtc_wkalarm *alarm)
+{
+ rt_err_t err;
+ struct rt_rtc_wkalarm *wkalarm = &rrtc->wkalarm;
+ rt_uint32_t data[2] = { RTC_ALARM, (rt_uint32_t)rtc_wkalarm_to_timestamp(alarm) };
+
+ err = rpi_firmware_property(rrtc->rpi_fw, RPI_FIRMWARE_SET_RTC_REG,
+ &data, sizeof(data));
+
+ if (!err && !(err = rpi_rtc_alarm_irq_enable(rrtc, alarm->enable)))
+ {
+ rt_mutex_take(&rrtc->lock, RT_WAITING_FOREVER);
+
+ wkalarm->enable = alarm->enable;
+ wkalarm->tm_hour = alarm->tm_hour;
+ wkalarm->tm_min = alarm->tm_min;
+ wkalarm->tm_sec = alarm->tm_sec;
+
+ if (wkalarm->enable)
+ {
+ /*
+ * raspberrypi firmware rtc have an IRQ pin that is not connected
+ * to a CPU interrupt but rather directly to a PMIC or power supply.
+ * So we should poll once per second.
+ */
+ rt_tick_t tick = rt_tick_from_millisecond(1000);
+
+ rt_timer_control(&rrtc->alarm_mon, RT_TIMER_CTRL_SET_TIME, &tick);
+
+ rt_timer_start(&rrtc->alarm_mon);
+ }
+
+ rt_mutex_release(&rrtc->lock);
+ }
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct rpi_rtc *rrtc = raw_to_rpi_rtc(dev);
+
+ if (!args)
+ {
+ return -RT_EINVAL;
+ }
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_RTC_GET_TIME:
+ err = rpi_rtc_read_time(rrtc, args);
+ break;
+
+ case RT_DEVICE_CTRL_RTC_SET_TIME:
+ err = rpi_rtc_set_time(rrtc, args);
+ break;
+
+ case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
+ err = rpi_rtc_read_time(rrtc, (time_t *)&((struct timeval *)args)->tv_sec);
+ break;
+
+ case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
+ err = rpi_rtc_set_time(rrtc, (time_t *)&((struct timeval *)args)->tv_sec);
+ break;
+
+ case RT_DEVICE_CTRL_RTC_GET_ALARM:
+ err = rpi_rtc_read_alarm(rrtc, args);
+ break;
+
+ case RT_DEVICE_CTRL_RTC_SET_ALARM:
+ err = rpi_rtc_set_alarm(rrtc, args);
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops rpi_rtc_rtc_ops =
+{
+ .control = rpi_rtc_control,
+};
+#endif
+
+static void rpi_rtc_alarm_mon(void *param)
+{
+ struct rpi_rtc *rrtc = param;
+ struct rt_rtc_wkalarm alarm;
+ time_t alarm_time, next_alarm_time;
+
+ rt_mutex_take(&rrtc->lock, RT_WAITING_FOREVER);
+
+ rpi_rtc_read_alarm(rrtc, &alarm);
+ alarm_time = rtc_wkalarm_to_timestamp(&alarm);
+ next_alarm_time = rtc_wkalarm_to_timestamp(&rrtc->wkalarm);
+
+ if (alarm_time < next_alarm_time)
+ {
+ rrtc->wkalarm.enable = RT_FALSE;
+ rt_alarm_update(&rrtc->parent, 1);
+ }
+
+ rt_mutex_release(&rrtc->lock);
+}
+
+static rt_err_t rpi_rtc_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ const char *dev_name;
+ struct rpi_firmware *rpi_fw;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_ofw_node *np = dev->ofw_node, *fw_np;
+ struct rpi_rtc *rrtc = rt_calloc(1, sizeof(*rrtc));
+
+ if (!rrtc)
+ {
+ return -RT_ENOMEM;
+ }
+
+ fw_np = rt_ofw_parse_phandle(np, "firmware", 0);
+
+ if (!fw_np)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rpi_fw = rpi_firmware_get(fw_np);
+ rt_ofw_node_put(fw_np);
+
+ if (!rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ rrtc->rpi_fw = rpi_fw;
+
+ rpi_rtc_alarm_clear_pending(rrtc);
+
+ rt_ofw_prop_read_u32(np, "trickle-charge-microvolt", &rrtc->bbat_vchg_microvolts);
+ rpi_rtc_set_charge_voltage(rrtc);
+
+ dev->user_data = rrtc;
+
+ rrtc->parent.type = RT_Device_Class_RTC;
+#ifdef RT_USING_DEVICE_OPS
+ rrtc->parent.ops = &rpi_rtc_rtc_ops;
+#else
+ rrtc->parent.control = rpi_rtc_control;
+#endif
+
+ rtc_dev_set_name(&rrtc->parent);
+ dev_name = rt_dm_dev_get_name(&rrtc->parent);
+
+ rt_mutex_init(&rrtc->lock, dev_name, RT_IPC_FLAG_FIFO);
+ rt_timer_init(&rrtc->alarm_mon, dev_name, rpi_rtc_alarm_mon, rrtc,
+ 0, RT_TIMER_FLAG_PERIODIC);
+
+ rt_device_register(&rrtc->parent, dev_name, RT_DEVICE_FLAG_RDWR);
+
+ return RT_EOK;
+
+_fail:
+ rt_free(rrtc);
+
+ return err;
+}
+
+static rt_err_t rpi_rtc_remove(struct rt_platform_device *pdev)
+{
+ struct rpi_rtc *rrtc = pdev->parent.user_data;
+
+ rt_timer_detach(&rrtc->alarm_mon);
+ rt_mutex_detach(&rrtc->lock);
+ rt_device_unregister(&rrtc->parent);
+
+ rt_free(rrtc);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id rpi_rtc_ofw_ids[] =
+{
+ { .compatible = "raspberrypi,rpi-rtc" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver rpi_rtc_driver =
+{
+ .name = "rtc-rpi",
+ .ids = rpi_rtc_ofw_ids,
+
+ .probe = rpi_rtc_probe,
+ .remove = rpi_rtc_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpi_rtc_driver);
diff --git a/bsp/raspberry-pi/dm/sdio/Kconfig b/bsp/raspberry-pi/dm/sdio/Kconfig
new file mode 100755
index 0000000000..e484d3ec86
--- /dev/null
+++ b/bsp/raspberry-pi/dm/sdio/Kconfig
@@ -0,0 +1,9 @@
+config RT_SDIO_SDHCI_BRCMSTB
+ bool "Broadcom SDIO/SD/MMC"
+ depends on RT_USING_SDIO
+ select RT_USING_SDHCI
+
+config RT_SDIO_SDHCI_IPROC
+ bool "BCM2835 & iProc SD/MMC Controller"
+ depends on RT_USING_SDIO
+ select RT_USING_SDHCI
diff --git a/bsp/raspberry-pi/dm/sdio/SConscript b/bsp/raspberry-pi/dm/sdio/SConscript
new file mode 100755
index 0000000000..63915c15ae
--- /dev/null
+++ b/bsp/raspberry-pi/dm/sdio/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include', cwd + '/../../../../components/drivers/sdio']
+
+if GetDepend(['RT_SDIO_SDHCI_BRCMSTB']):
+ src += ['sdhci-brcmstb.c']
+
+if GetDepend(['RT_SDIO_SDHCI_IPROC']):
+ src += ['sdhci-iproc.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/sdio/sdhci-brcmstb.c b/bsp/raspberry-pi/dm/sdio/sdhci-brcmstb.c
new file mode 100755
index 0000000000..d77a3f781e
--- /dev/null
+++ b/bsp/raspberry-pi/dm/sdio/sdhci-brcmstb.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2025-01-01 GuEe-GUI The first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "sdhci.brcmstb"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "dev_sdio_dm.h"
+#include "dev_sdhci_dm.h"
+
+#define SDHCI_VENDOR 0x78
+#define SDHCI_VENDOR_ENHANCED_STRB 0x1
+#define SDHCI_VENDOR_GATE_SDCLK_EN 0x2
+
+#define BRCMSTB_MATCH_FLAGS_NO_64BIT RT_BIT(0)
+#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT RT_BIT(1)
+#define BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE RT_BIT(2)
+#define BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY RT_BIT(3)
+
+#define BRCMSTB_PRIV_FLAGS_HAS_CQE RT_BIT(0)
+#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK RT_BIT(1)
+#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS RT_BIT(2)
+
+#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
+
+#define SDIO_CFG_CTRL 0x0
+#define SDIO_CFG_CTRL_SDCD_N_TEST_EN RT_BIT(31)
+#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV RT_BIT(30)
+
+#define SDIO_CFG_SD_PIN_SEL 0x44
+#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
+#define SDIO_CFG_SD_PIN_SEL_MMC RT_BIT(0)
+#define SDIO_CFG_SD_PIN_SEL_SD RT_BIT(1)
+
+#define SDIO_CFG_CQ_CAPABILITY 0x4c
+#define SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT 12
+
+#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
+#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE RT_BIT(31)
+#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE RT_BIT(0)
+
+struct sdhci_brcmstb_priv
+{
+ void *cfg_regs;
+
+ struct rt_clk *base_clk;
+
+ rt_uint32_t flags;
+ rt_uint32_t base_freq_hz;
+};
+
+struct brcmstb_match_priv
+{
+ void (*hs400es)(struct rt_mmc_host *mmc, struct rt_mmcsd_io_cfg *ios);
+ void (*cfginit)(struct rt_sdhci_host *host);
+ struct rt_sdhci_ops *ops;
+ const rt_uint32_t flags;
+};
+
+rt_inline void enable_clock_gating(struct rt_sdhci_host *host)
+{
+ rt_uint32_t reg;
+
+ reg = rt_sdhci_readl(host, SDHCI_VENDOR);
+ reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
+ rt_sdhci_writel(host, reg, SDHCI_VENDOR);
+}
+
+static void brcmstb_reset(struct rt_sdhci_host *host, rt_uint8_t mask)
+{
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_brcmstb_priv *priv = rt_sdhci_pltfm_priv(pltfm_host);
+
+ /* Reset cqhci first if CQE supported */
+ rt_sdhci_reset(host, mask);
+
+ /* Reset will clear this, so re-enable it */
+ if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
+ {
+ enable_clock_gating(host);
+ }
+}
+
+static void sdhci_brcmstb_hs400es(struct rt_mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
+{
+ rt_uint32_t reg;
+ struct rt_sdhci_host *host = rt_mmc_priv(mmc);
+
+ reg = HWREG32(host->ioaddr + SDHCI_VENDOR);
+
+ if (ios->enhanced_strobe)
+ {
+ reg |= SDHCI_VENDOR_ENHANCED_STRB;
+ }
+ else
+ {
+ reg &= ~SDHCI_VENDOR_ENHANCED_STRB;
+ }
+
+ HWREG32(host->ioaddr + SDHCI_VENDOR) = reg;
+}
+
+static void sdhci_brcmstb_set_clock(struct rt_sdhci_host *host, unsigned int clock)
+{
+ rt_uint16_t clk;
+
+ host->mmc->actual_clock = 0;
+
+ clk = rt_sdhci_clk_set(host, clock, &host->mmc->actual_clock);
+ rt_sdhci_writew(host, clk, RT_SDHCI_CLOCK_CONTROL);
+
+ if (clock == 0)
+ {
+ return;
+ }
+
+ rt_sdhci_clk_enable(host, clk);
+}
+
+static void sdhci_brcmstb_set_power(struct rt_sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ if (!rt_is_err_or_null(host->mmc->rthost.supply.vmmc))
+ {
+ sdio_regulator_set_ocr(&host->mmc->rthost, host->mmc->rthost.supply.vmmc, vdd);
+ }
+
+ rt_sdhci_set_power_with_noreg(host, mode, vdd);
+}
+
+static void sdhci_bcm2712_set_clock(struct rt_sdhci_host *host, unsigned int clock)
+{
+ rt_uint16_t clk;
+ rt_uint32_t reg;
+ rt_bool_t is_emmc_rate = RT_FALSE;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_brcmstb_priv *priv = rt_sdhci_pltfm_priv(pltfm_host);
+
+ host->mmc->actual_clock = 0;
+
+ rt_sdhci_writew(host, 0, RT_SDHCI_CLOCK_CONTROL);
+
+ switch (host->mmc->ios.timing)
+ {
+ case MMC_TIMING_MMC_HS400:
+ case MMC_TIMING_MMC_HS200:
+ case MMC_TIMING_MMC_DDR52:
+ case MMC_TIMING_MMC_HS:
+ is_emmc_rate = RT_TRUE;
+ break;
+ default:
+ break;
+ }
+
+ reg = HWREG32(priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
+ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
+ if (is_emmc_rate)
+ {
+ reg |= SDIO_CFG_SD_PIN_SEL_MMC;
+ }
+ else
+ {
+ reg |= SDIO_CFG_SD_PIN_SEL_SD;
+ }
+ HWREG32(priv->cfg_regs + SDIO_CFG_SD_PIN_SEL) = reg;
+
+ if (clock == 0)
+ {
+ return;
+ }
+
+ clk = rt_sdhci_clk_set(host, clock, &host->mmc->actual_clock);
+ rt_sdhci_clk_enable(host, clk);
+}
+
+static void sdhci_bcm2712_hs400_downgrade(struct rt_mmc_host *mmc)
+{
+ struct rt_sdhci_host *host = rt_mmc_priv(mmc);
+
+ /*
+ * The eMMC PHY refuses to update if HS timings are selected while
+ * the clock is above 52MHz, so lower it before mode transitions.
+ */
+ sdhci_bcm2712_set_clock(host, 52000000);
+}
+
+static void sdhci_brcmstb_set_uhs_signaling(struct rt_sdhci_host *host,
+ unsigned int timing)
+{
+ rt_uint16_t ctrl_2;
+
+ ctrl_2 = rt_sdhci_readw(host, RT_SDHCI_HOST_CONTROL2);
+ /* Select Bus Speed Mode for host */
+ ctrl_2 &= ~RT_SDHCI_CTRL_UHS_MASK;
+
+ if (timing == MMC_TIMING_MMC_HS200 || timing == MMC_TIMING_UHS_SDR104)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_UHS_SDR104;
+ }
+ else if (timing == MMC_TIMING_UHS_SDR12)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_UHS_SDR12;
+ }
+ else if (timing == MMC_TIMING_SD_HS || timing == MMC_TIMING_MMC_HS ||
+ timing == MMC_TIMING_UHS_SDR25)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_UHS_SDR25;
+ }
+ else if (timing == MMC_TIMING_UHS_SDR50)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_UHS_SDR50;
+ }
+ else if (timing == MMC_TIMING_UHS_DDR50 || timing == MMC_TIMING_MMC_DDR52)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_UHS_DDR50;
+ }
+ else if (timing == MMC_TIMING_MMC_HS400)
+ {
+ ctrl_2 |= RT_SDHCI_CTRL_HS400; /* Non-standard */
+ }
+
+ rt_sdhci_writew(host, ctrl_2, RT_SDHCI_HOST_CONTROL2);
+}
+
+static void sdhci_brcmstb_cfginit_2712(struct rt_sdhci_host *host)
+{
+ rt_uint32_t uhs_mask, hsemmc_mask, reg, base_clk_mhz;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_brcmstb_priv *brcmstb_priv = rt_sdhci_pltfm_priv(pltfm_host);
+
+ uhs_mask = (MMCSD_SUP_SDR50 | MMCSD_SUP_SDR104);
+ hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
+ MMCSD_SUP_HS400_1V8 | MMCSD_SUP_HS400_1V2);
+
+ /*
+ * If we support a speed that requires tuning,
+ * then select the delay line PHY as the clock source.
+ */
+ if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask))
+ {
+ reg = HWREG32(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
+ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
+ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
+ HWREG32(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE) = reg;
+
+ host->mmc_host_ops.hs400_downgrade = sdhci_bcm2712_hs400_downgrade;
+ }
+
+ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
+ (host->mmc->caps & MMC_CAP_NEEDS_POLL))
+ {
+ /* Force presence */
+ reg = HWREG32(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
+ HWREG32(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL) = reg;
+ }
+
+ /* Guesstimate the timer frequency (controller base clock) */
+ base_clk_mhz = rt_clk_get_rate(pltfm_host->clk) / 1000000;
+ if (base_clk_mhz == 0)
+ {
+ base_clk_mhz = 1;
+ }
+ reg = (3 << SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT) | base_clk_mhz;
+ HWREG32(brcmstb_priv->cfg_regs + SDIO_CFG_CQ_CAPABILITY) = reg;
+}
+
+static struct rt_sdhci_ops sdhci_brcmstb_ops =
+{
+ .set_clock = rt_sdhci_set_clock,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = rt_sdhci_reset,
+ .set_uhs_signaling = rt_sdhci_set_uhs,
+};
+
+static struct rt_sdhci_ops sdhci_brcmstb_ops_2712 =
+{
+ .set_clock = sdhci_bcm2712_set_clock,
+ .set_power = sdhci_brcmstb_set_power,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = brcmstb_reset,
+ .set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
+};
+
+static struct rt_sdhci_ops sdhci_brcmstb_ops_7216 =
+{
+ .set_clock = sdhci_brcmstb_set_clock,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = brcmstb_reset,
+ .set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
+};
+
+static struct brcmstb_match_priv match_priv_7425 =
+{
+ .flags = BRCMSTB_MATCH_FLAGS_NO_64BIT | BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
+ .ops = &sdhci_brcmstb_ops,
+};
+
+static struct brcmstb_match_priv match_priv_7445 =
+{
+ .flags = BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
+ .ops = &sdhci_brcmstb_ops,
+};
+
+static const struct brcmstb_match_priv match_priv_7216 =
+{
+ .flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
+ .hs400es = sdhci_brcmstb_hs400es,
+ .ops = &sdhci_brcmstb_ops_7216,
+};
+
+static const struct brcmstb_match_priv match_priv_2712 =
+{
+ .flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY,
+ .hs400es = sdhci_brcmstb_hs400es,
+ .cfginit = sdhci_brcmstb_cfginit_2712,
+ .ops = &sdhci_brcmstb_ops_2712,
+};
+
+#ifdef RT_USING_PM
+static rt_err_t sdhci_brcmstb_pm_suspend(const struct rt_device *device, rt_uint8_t mode)
+{
+ struct rt_sdhci_host *host = device->user_data;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_brcmstb_priv *priv = rt_sdhci_pltfm_priv(pltfm_host);
+
+ rt_clk_disable_unprepare(priv->base_clk);
+
+ return rt_sdhci_pltfm_suspend(device);
+}
+
+static void sdhci_brcmstb_pm_resume(const struct rt_device *device, rt_uint8_t mode)
+{
+ struct rt_sdhci_host *host = device->user_data;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_brcmstb_priv *priv = rt_sdhci_pltfm_priv(pltfm_host);
+
+ if (!rt_sdhci_pltfm_resume(device) && priv->base_freq_hz)
+ {
+ if (!rt_clk_prepare_enable(priv->base_clk) &&
+ rt_clk_get_rate(priv->base_clk) != priv->base_freq_hz)
+ {
+ rt_clk_set_rate(priv->base_clk, priv->base_freq_hz);
+ }
+ }
+}
+
+static const struct rt_device_pm_ops sdhci_brcmstb_pm_ops =
+{
+ .suspend = sdhci_brcmstb_pm_suspend,
+ .resume = sdhci_brcmstb_pm_resume,
+};
+#endif /* RT_USING_PM */
+
+static rt_err_t sdhci_brcmstb_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t actual_clock_mhz;
+ struct rt_clk *clk, *base_clk = RT_NULL;
+ struct rt_device *dev = &pdev->parent;
+ struct rt_sdhci_host *host;
+ struct sdhci_brcmstb_priv *priv;
+ struct rt_sdhci_pltfm_host *pltfm_host;
+ struct rt_sdhci_pltfm_data brcmstb_pdata;
+ const struct brcmstb_match_priv *match_priv;
+
+ match_priv = pdev->id->data;
+
+ clk = rt_clk_get_by_index(dev, 0);
+ if (rt_is_err(clk))
+ {
+ return rt_ptr_err(clk);
+ }
+
+ if ((err = rt_clk_prepare_enable(clk)))
+ {
+ goto _free_clk;
+ }
+
+ rt_memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata));
+ brcmstb_pdata.ops = match_priv->ops;
+
+ host = rt_sdhci_pltfm_init(pdev, &brcmstb_pdata, sizeof(struct sdhci_brcmstb_priv));
+ if (!host)
+ {
+ err = -RT_ERROR;
+ goto _disable_free_clk;
+ }
+
+ pltfm_host = rt_sdhci_priv(host);
+ priv = rt_sdhci_pltfm_priv(pltfm_host);
+ pltfm_host->clk = clk;
+
+ /* Check property "supports-cqe" and set cqhci IRQ here */
+
+ /*
+ * Read ref node "sde-pcie".
+ * Init SDE regulator "sde-1v8", MMIO[1/2], pinctrl[default/sdex]
+ */
+
+ /* Map in the non-standard CFG registers */
+ priv->cfg_regs = rt_dm_dev_iomap_by_name(dev, "cfg");
+ if (!priv->cfg_regs)
+ {
+ priv->cfg_regs = rt_dm_dev_iomap(dev, 1);
+ }
+
+ if (!priv->cfg_regs)
+ {
+ err = -RT_EIO;
+ goto _free_cfg;
+ }
+
+ rt_sdhci_get_of_property(pdev);
+
+ if ((err = rt_mmc_of_parse(host->mmc)))
+ {
+ goto _free_cfg;
+ }
+
+ /*
+ * Automatic clock gating does not work for SD cards that may
+ * voltage switch so only enable it for non-removable devices.
+ */
+ if ((match_priv->flags & BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE) &&
+ (host->mmc->caps & MMC_CAP_NONREMOVABLE))
+ {
+ priv->flags |= BRCMSTB_PRIV_FLAGS_GATE_CLOCK;
+ }
+
+ /*
+ * If the chip has enhanced strobe and it's enabled, add
+ * callback
+ */
+ if (match_priv->hs400es && (host->mmc->caps2 & MMC_CAP2_HS400_ES))
+ {
+ host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
+ }
+
+ if (match_priv->cfginit)
+ {
+ match_priv->cfginit(host);
+ }
+
+ /*
+ * Supply the existing CAPS, but clear the UHS modes. This
+ * will allow these modes to be specified by device tree
+ * properties through rt_mmc_of_parse().
+ */
+ host->caps = rt_sdhci_readl(host, RT_SDHCI_CAPABILITIES);
+ if (match_priv->flags & BRCMSTB_MATCH_FLAGS_NO_64BIT)
+ {
+ host->caps &= ~RT_SDHCI_CAN_64BIT;
+ }
+ host->caps1 = rt_sdhci_readl(host, RT_SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(RT_SDHCI_SUPPORT_SDR50 | RT_SDHCI_SUPPORT_SDR104 | RT_SDHCI_SUPPORT_DDR50);
+
+ if (match_priv->flags & BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT)
+ {
+ host->quirks |= RT_SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ }
+
+ if (!(match_priv->flags & BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY))
+ {
+ host->mmc_host_ops.card_busy = RT_NULL;
+ }
+
+ /* Change the base clock frequency if the DT property exists */
+ if (rt_dm_dev_prop_read_u32(dev, "clock-frequency", &priv->base_freq_hz))
+ {
+ goto _add_host;
+ }
+
+ base_clk = rt_clk_get_by_name(dev, "sdio_freq");
+ if (rt_is_err_or_null(base_clk))
+ {
+ LOG_W("%s: Clock for \"sdio_freq\" not found", rt_dm_dev_get_name(dev));
+ goto _add_host;
+ }
+
+ if ((err = rt_clk_prepare_enable(base_clk)))
+ {
+ goto _free_base_clk;
+ }
+
+ /* set improved clock rate */
+ rt_clk_set_rate(base_clk, priv->base_freq_hz);
+ actual_clock_mhz = rt_clk_get_rate(base_clk) / 1000000;
+
+ host->caps &= ~RT_SDHCI_CLOCK_V3_BASE_MASK;
+ host->caps |= (actual_clock_mhz << RT_SDHCI_CLOCK_BASE_SHIFT);
+ /* Disable presets because they are now incorrect */
+ host->quirks2 |= RT_SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+
+ LOG_D("%s: Base Clock Frequency changed to %dMHz",
+ rt_dm_dev_get_name(dev), actual_clock_mhz);
+ priv->base_clk = base_clk;
+
+_add_host:
+ /* The CQE should be enabled before here. */
+ if ((err = rt_sdhci_set_and_add_host(host)))
+ {
+ goto _err;
+ }
+
+#ifdef RT_USING_PM
+ rt_pm_device_register(dev, &sdhci_brcmstb_pm_ops);
+#endif
+
+ return RT_EOK;
+
+_err:
+ goto _free_cfg;
+
+_free_base_clk:
+ if (base_clk && base_clk != clk)
+ {
+ rt_clk_disable_unprepare(base_clk);
+ rt_clk_put(base_clk);
+ }
+
+_free_cfg:
+ if (host)
+ {
+ rt_sdhci_pltfm_free(pdev);
+ }
+
+_disable_free_clk:
+ rt_clk_disable_unprepare(clk);
+
+_free_clk:
+ rt_clk_put(clk);
+
+ return err;
+}
+
+static rt_err_t sdhci_brcmstb_remove(struct rt_platform_device *pdev)
+{
+#ifdef RT_USING_PM
+ rt_pm_device_unregister(&pdev->parent);
+#endif
+
+ return rt_sdhci_pltfm_remove(pdev);
+}
+
+static rt_err_t sdhci_brcmstb_shutdown(struct rt_platform_device *pdev)
+{
+ return sdhci_brcmstb_remove(pdev);
+}
+
+static const struct rt_ofw_node_id sdhci_brcm_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
+ { .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
+ { .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
+ { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver sdhci_brcmstb_driver =
+{
+ .name = "sdhci-brcmstb",
+ .ids = sdhci_brcm_ofw_ids,
+
+ .probe = sdhci_brcmstb_probe,
+ .remove = sdhci_brcmstb_remove,
+ .shutdown = sdhci_brcmstb_shutdown,
+};
+RT_PLATFORM_DRIVER_EXPORT(sdhci_brcmstb_driver);
diff --git a/bsp/raspberry-pi/dm/sdio/sdhci-iproc.c b/bsp/raspberry-pi/dm/sdio/sdhci-iproc.c
new file mode 100755
index 0000000000..2341bc2d25
--- /dev/null
+++ b/bsp/raspberry-pi/dm/sdio/sdhci-iproc.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2006-2024 RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-10-28 zhujiale The first version
+ * 2025-01-01 GuEe-GUI Move to DM
+ */
+
+#include "dev_sdio_dm.h"
+#include "dev_sdhci_dm.h"
+
+struct sdhci_iproc_data
+{
+ const struct rt_sdhci_pltfm_data *pdata;
+ rt_uint32_t caps;
+ rt_uint32_t caps1;
+ rt_uint32_t mmc_caps;
+ rt_bool_t missing_caps;
+};
+
+struct sdhci_iproc_host
+{
+ const struct sdhci_iproc_data *data;
+ rt_uint32_t shadow_cmd;
+ rt_uint32_t shadow_blk;
+ rt_bool_t is_cmd_shadowed;
+ rt_bool_t is_blk_shadowed;
+};
+
+#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
+
+rt_inline rt_uint32_t sdhci_iproc_readl(struct rt_sdhci_host *host, int reg)
+{
+ return HWREG32(host->ioaddr + reg);
+}
+
+static rt_uint16_t sdhci_iproc_readw(struct rt_sdhci_host *host, int reg)
+{
+ rt_uint16_t word;
+ rt_uint32_t val;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_iproc_host *iproc_host = rt_sdhci_pltfm_priv(pltfm_host);
+
+ if ((reg == RT_SDHCI_TRANSFER_MODE) && iproc_host->is_cmd_shadowed)
+ {
+ /* Get the saved transfer mode */
+ val = iproc_host->shadow_cmd;
+ }
+ else if ((reg == RT_SDHCI_BLOCK_SIZE || reg == RT_SDHCI_BLOCK_COUNT) &&
+ iproc_host->is_blk_shadowed)
+ {
+ /* Get the saved block info */
+ val = iproc_host->shadow_blk;
+ }
+ else
+ {
+ val = sdhci_iproc_readl(host, (reg & ~3));
+ }
+
+ word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
+
+ return word;
+}
+
+static rt_uint8_t sdhci_iproc_readb(struct rt_sdhci_host *host, int reg)
+{
+ rt_uint32_t val = sdhci_iproc_readl(host, (reg & ~3));
+ rt_uint8_t byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
+
+ return byte;
+}
+
+rt_inline void sdhci_iproc_writel(struct rt_sdhci_host *host, rt_uint32_t val, int reg)
+{
+ HWREG32(host->ioaddr + reg) = val;
+
+ if (host->clock <= 400000)
+ {
+ /* Round up to micro-second four SD clock delay */
+ if (host->clock)
+ {
+ rt_hw_us_delay((4 * 1000000 + host->clock - 1) / host->clock);
+ }
+ else
+ {
+ rt_hw_us_delay(10);
+ }
+ }
+}
+
+static void sdhci_iproc_writew(struct rt_sdhci_host *host, rt_uint16_t val, int reg)
+{
+ rt_uint32_t oldval, newval;
+ rt_uint32_t word_shift = REG_OFFSET_IN_BITS(reg);
+ rt_uint32_t mask = 0xffff << word_shift;
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+ struct sdhci_iproc_host *iproc_host = rt_sdhci_pltfm_priv(pltfm_host);
+
+ if (reg == RT_SDHCI_COMMAND)
+ {
+ /* Write the block now as we are issuing a command */
+ if (iproc_host->is_blk_shadowed)
+ {
+ sdhci_iproc_writel(host, iproc_host->shadow_blk, RT_SDHCI_BLOCK_SIZE);
+ iproc_host->is_blk_shadowed = false;
+ }
+ oldval = iproc_host->shadow_cmd;
+ iproc_host->is_cmd_shadowed = false;
+ }
+ else if ((reg == RT_SDHCI_BLOCK_SIZE || reg == RT_SDHCI_BLOCK_COUNT) &&
+ iproc_host->is_blk_shadowed)
+ {
+ /* Block size and count are stored in shadow reg */
+ oldval = iproc_host->shadow_blk;
+ }
+ else
+ {
+ /* Read reg, all other registers are not shadowed */
+ oldval = sdhci_iproc_readl(host, (reg & ~3));
+ }
+ newval = (oldval & ~mask) | (val << word_shift);
+
+ if (reg == RT_SDHCI_TRANSFER_MODE)
+ {
+ /* Save the transfer mode until the command is issued */
+ iproc_host->shadow_cmd = newval;
+ iproc_host->is_cmd_shadowed = RT_TRUE;
+ }
+ else if (reg == RT_SDHCI_BLOCK_SIZE || reg == RT_SDHCI_BLOCK_COUNT)
+ {
+ /* Save the block info until the command is issued */
+ iproc_host->shadow_blk = newval;
+ iproc_host->is_blk_shadowed = RT_TRUE;
+ }
+ else
+ {
+ /* Command or other regular 32-bit write */
+ sdhci_iproc_writel(host, newval, reg & ~3);
+ }
+}
+
+static void sdhci_iproc_writeb(struct rt_sdhci_host *host, rt_uint8_t val, int reg)
+{
+ rt_uint32_t oldval = sdhci_iproc_readl(host, (reg & ~3));
+ rt_uint32_t byte_shift = REG_OFFSET_IN_BITS(reg);
+ rt_uint32_t mask = 0xff << byte_shift;
+ rt_uint32_t newval = (oldval & ~mask) | (val << byte_shift);
+
+ sdhci_iproc_writel(host, newval, reg & ~3);
+}
+
+static unsigned int sdhci_iproc_get_max_clock(struct rt_sdhci_host *host)
+{
+ struct rt_sdhci_pltfm_host *pltfm_host = rt_sdhci_priv(host);
+
+ if (pltfm_host->clk)
+ {
+ return rt_sdhci_pltfm_clk_get_max_clock(host);
+ }
+ else
+ {
+ return pltfm_host->clock;
+ }
+}
+
+static unsigned int sdhci_iproc_bcm2711_get_min_clock(struct rt_sdhci_host *host)
+{
+ return 200000;
+}
+
+static const struct rt_sdhci_ops sdhci_iproc_ops =
+{
+ .set_clock = rt_sdhci_set_clock,
+ .get_max_clock = sdhci_iproc_get_max_clock,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = rt_sdhci_reset,
+ .set_uhs_signaling = rt_sdhci_set_uhs,
+};
+
+static const struct rt_sdhci_ops sdhci_iproc_32only_ops =
+{
+ .read_l = sdhci_iproc_readl,
+ .read_w = sdhci_iproc_readw,
+ .read_b = sdhci_iproc_readb,
+ .write_l = sdhci_iproc_writel,
+ .write_w = sdhci_iproc_writew,
+ .write_b = sdhci_iproc_writeb,
+ .set_clock = rt_sdhci_set_clock,
+ .get_max_clock = sdhci_iproc_get_max_clock,
+ .set_power = rt_sdhci_set_power_and_bus_voltage,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = rt_sdhci_reset,
+ .set_uhs_signaling = rt_sdhci_set_uhs,
+};
+
+static const struct rt_sdhci_pltfm_data sdhci_iproc_cygnus_pltfm_data =
+{
+ .quirks = RT_SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | RT_SDHCI_QUIRK_NO_HISPD_BIT,
+ .quirks2 = RT_SDHCI_QUIRK2_ACMD23_BROKEN | RT_SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+ .ops = &sdhci_iproc_32only_ops,
+};
+
+static const struct sdhci_iproc_data iproc_cygnus_data =
+{
+ .pdata = &sdhci_iproc_cygnus_pltfm_data,
+ .caps = ((0x1 << RT_SDHCI_MAX_BLOCK_SHIFT) & RT_SDHCI_MAX_BLOCK_MASK) |
+ RT_SDHCI_CAN_VDD_330 | RT_SDHCI_CAN_VDD_180 | RT_SDHCI_CAN_DO_SUSPEND |
+ RT_SDHCI_CAN_DO_HISPD | RT_SDHCI_CAN_DO_ADMA2 | RT_SDHCI_CAN_DO_SDMA,
+ .caps1 = RT_SDHCI_DRIVER_TYPE_C | RT_SDHCI_DRIVER_TYPE_D | RT_SDHCI_SUPPORT_DDR50,
+ .mmc_caps = MMC_CAP_1_8V_DDR,
+};
+
+static const struct rt_sdhci_pltfm_data sdhci_iproc_pltfm_data =
+{
+ .quirks = RT_SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ RT_SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 |
+ RT_SDHCI_QUIRK_NO_HISPD_BIT,
+ .quirks2 = RT_SDHCI_QUIRK2_ACMD23_BROKEN,
+ .ops = &sdhci_iproc_ops,
+};
+
+static const struct sdhci_iproc_data iproc_data =
+{
+ .pdata = &sdhci_iproc_pltfm_data,
+ .caps = ((0x1 << RT_SDHCI_MAX_BLOCK_SHIFT) & RT_SDHCI_MAX_BLOCK_MASK) |
+ RT_SDHCI_CAN_VDD_330 |
+ RT_SDHCI_CAN_VDD_180 |
+ RT_SDHCI_CAN_DO_SUSPEND |
+ RT_SDHCI_CAN_DO_HISPD |
+ RT_SDHCI_CAN_DO_ADMA2 |
+ RT_SDHCI_CAN_DO_SDMA,
+ .caps1 = RT_SDHCI_DRIVER_TYPE_C | RT_SDHCI_DRIVER_TYPE_D | RT_SDHCI_SUPPORT_DDR50,
+};
+
+static const struct rt_sdhci_pltfm_data sdhci_bcm2835_pltfm_data =
+{
+ .quirks = RT_SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+ RT_SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ RT_SDHCI_QUIRK_NO_HISPD_BIT,
+ .quirks2 = RT_SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .ops = &sdhci_iproc_32only_ops,
+};
+
+static const struct sdhci_iproc_data bcm2835_data =
+{
+ .pdata = &sdhci_bcm2835_pltfm_data,
+ .caps = ((0x1 << RT_SDHCI_MAX_BLOCK_SHIFT) & RT_SDHCI_MAX_BLOCK_MASK) |
+ RT_SDHCI_CAN_VDD_330 | RT_SDHCI_CAN_DO_HISPD,
+ .caps1 = RT_SDHCI_DRIVER_TYPE_A | RT_SDHCI_DRIVER_TYPE_C,
+ .mmc_caps = 0x00000000,
+ .missing_caps = RT_TRUE,
+};
+
+static const struct rt_sdhci_ops sdhci_iproc_bcm2711_ops =
+{
+ .read_l = sdhci_iproc_readl,
+ .read_w = sdhci_iproc_readw,
+ .read_b = sdhci_iproc_readb,
+ .write_l = sdhci_iproc_writel,
+ .write_w = sdhci_iproc_writew,
+ .write_b = sdhci_iproc_writeb,
+ .set_clock = rt_sdhci_set_clock,
+ .set_power = rt_sdhci_set_power_and_bus_voltage,
+ .get_max_clock = sdhci_iproc_get_max_clock,
+ .get_min_clock = sdhci_iproc_bcm2711_get_min_clock,
+ .set_bus_width = rt_sdhci_set_bus_width,
+ .reset = rt_sdhci_reset,
+ .set_uhs_signaling = rt_sdhci_set_uhs,
+};
+
+static const struct rt_sdhci_pltfm_data sdhci_bcm2711_pltfm_data =
+{
+ .quirks = RT_SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+ .ops = &sdhci_iproc_bcm2711_ops,
+};
+
+static const struct sdhci_iproc_data bcm2711_data =
+{
+ .pdata = &sdhci_bcm2711_pltfm_data,
+ .mmc_caps = MMC_CAP_3_3V_DDR,
+};
+
+static const struct rt_sdhci_pltfm_data sdhci_bcm7211a0_pltfm_data =
+{
+ .quirks = RT_SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ RT_SDHCI_QUIRK_BROKEN_DMA |
+ RT_SDHCI_QUIRK_BROKEN_ADMA,
+ .ops = &sdhci_iproc_ops,
+};
+
+#define BCM7211A0_BASE_CLK_MHZ 100
+static const struct sdhci_iproc_data bcm7211a0_data =
+{
+ .pdata = &sdhci_bcm7211a0_pltfm_data,
+ .caps = ((BCM7211A0_BASE_CLK_MHZ / 2) << RT_SDHCI_TIMEOUT_CLK_SHIFT) |
+ (BCM7211A0_BASE_CLK_MHZ << RT_SDHCI_CLOCK_BASE_SHIFT) |
+ ((0x2 << RT_SDHCI_MAX_BLOCK_SHIFT) & RT_SDHCI_MAX_BLOCK_MASK) |
+ RT_SDHCI_CAN_VDD_330 |
+ RT_SDHCI_CAN_VDD_180 |
+ RT_SDHCI_CAN_DO_SUSPEND |
+ RT_SDHCI_CAN_DO_HISPD,
+ .caps1 = RT_SDHCI_DRIVER_TYPE_C | RT_SDHCI_DRIVER_TYPE_D,
+ .missing_caps = RT_TRUE,
+};
+
+static rt_err_t sdhci_iproc_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_sdhci_host *host;
+ struct sdhci_iproc_host *iproc_host;
+ struct rt_sdhci_pltfm_host *pltfm_host;
+ struct rt_device *dev = &pdev->parent;
+ const struct sdhci_iproc_data *iproc_data = RT_NULL;
+
+ iproc_data = pdev->id->data;
+ if (!iproc_data)
+ {
+ return -RT_EINVAL;
+ }
+
+ host = rt_sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host));
+ if (!host)
+ {
+ return -RT_ERROR;
+ }
+
+ pltfm_host = rt_sdhci_priv(host);
+ iproc_host = rt_sdhci_pltfm_priv(pltfm_host);
+
+ iproc_host->data = iproc_data;
+
+ err = rt_mmc_of_parse(host->mmc);
+ if (err)
+ {
+ goto _err;
+ }
+
+ rt_sdhci_get_property(pdev);
+
+ host->mmc->caps |= iproc_host->data->mmc_caps;
+
+ if (dev->ofw_node)
+ {
+ pltfm_host->clk = rt_clk_get_by_index(dev, 0);
+ if (rt_is_err(pltfm_host->clk))
+ {
+ err = rt_ptr_err(pltfm_host->clk);
+ goto _err;
+ }
+
+ err = rt_clk_prepare_enable(pltfm_host->clk);
+ if (err)
+ {
+ goto _err;
+ }
+ }
+
+ /*
+ * Controllers such as bcm2835 SDIO report unreliable/zero voltage bits in
+ * CAPABILITIES; rt_sdhci_setup_host() would otherwise overwrite software
+ * caps when calling rt_sdhci_read_caps(..., NULL, NULL). Seed caps once
+ * here so the read_caps "already done" guard keeps platform values.
+ */
+ if (iproc_host->data->missing_caps)
+ {
+ rt_sdhci_read_caps(host, RT_NULL, &iproc_host->data->caps, &iproc_host->data->caps1);
+ }
+
+ err = rt_sdhci_set_and_add_host(host);
+ if (err)
+ {
+ goto _err_clk;
+ }
+
+ return RT_EOK;
+
+_err_clk:
+ if (dev->ofw_node)
+ {
+ rt_clk_disable_unprepare(pltfm_host->clk);
+ }
+
+_err:
+ rt_sdhci_pltfm_free(pdev);
+
+ return err;
+}
+
+static const struct rt_ofw_node_id sdhci_iproc_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
+ { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data },
+ { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
+ { .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
+ { .compatible = "brcm,bcm7211a0-sdhci", .data = &bcm7211a0_data },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver sdhci_iproc_driver =
+{
+ .name = "sdhci-iproc",
+ .ids = sdhci_iproc_ofw_ids,
+
+ .probe = sdhci_iproc_probe,
+ .remove = rt_sdhci_pltfm_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(sdhci_iproc_driver);
diff --git a/bsp/raspberry-pi/dm/serial/8250-bcm2835aux.c b/bsp/raspberry-pi/dm/serial/8250-bcm2835aux.c
new file mode 100755
index 0000000000..1288c3873f
--- /dev/null
+++ b/bsp/raspberry-pi/dm/serial/8250-bcm2835aux.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-16 GuEe-GUI first version
+ */
+
+#include <rtthread.h>
+
+#include "8250.h"
+
+#define BCM2835_AUX_UART_CNTL 8
+#define BCM2835_AUX_UART_CNTL_RXEN 0x01 /* Receiver enable */
+#define BCM2835_AUX_UART_CNTL_TXEN 0x02 /* Transmitter enable */
+#define BCM2835_AUX_UART_CNTL_AUTORTS 0x04 /* RTS set by RX fill level */
+#define BCM2835_AUX_UART_CNTL_AUTOCTS 0x08 /* CTS stops transmitter */
+#define BCM2835_AUX_UART_CNTL_RTS3 0x00 /* RTS set until 3 chars left */
+#define BCM2835_AUX_UART_CNTL_RTS2 0x10 /* RTS set until 2 chars left */
+#define BCM2835_AUX_UART_CNTL_RTS1 0x20 /* RTS set until 1 chars left */
+#define BCM2835_AUX_UART_CNTL_RTS4 0x30 /* RTS set until 4 chars left */
+#define BCM2835_AUX_UART_CNTL_RTSINV 0x40 /* Invert auto RTS polarity */
+#define BCM2835_AUX_UART_CNTL_CTSINV 0x80 /* Invert auto CTS polarity */
+
+struct bcm2835aux
+{
+ struct serial8250 parent;
+ rt_uint32_t cntl;
+};
+
+#define to_bcm2835aux(serial8250) rt_container_of(serial8250, struct bcm2835aux, parent)
+
+static void bcm2835aux_free_resource(struct bcm2835aux *bcm2835aux)
+{
+ struct serial8250 *serial = &bcm2835aux->parent;
+
+ if (serial->base)
+ {
+ rt_iounmap(serial->base);
+ }
+
+ if (!rt_is_err_or_null(serial->clk))
+ {
+ rt_clk_disable_unprepare(serial->clk);
+ rt_clk_put(serial->clk);
+ }
+
+ rt_free(bcm2835aux);
+}
+
+static void bcm2835aux_serial_remove(struct serial8250 *serial)
+{
+ struct bcm2835aux *bcm2835aux = to_bcm2835aux(serial);
+
+ bcm2835aux_free_resource(bcm2835aux);
+}
+
+static rt_err_t bcm2835aux_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err = RT_EOK;
+ struct serial8250 *serial;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835aux *bcm2835aux = serial8250_alloc(bcm2835aux);
+ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+ if (!bcm2835aux)
+ {
+ return -RT_ENOMEM;
+ }
+
+ serial = &bcm2835aux->parent;
+
+ serial->base = rt_dm_dev_iomap(dev, 0);
+
+ if (!serial->base)
+ {
+ err = -RT_ERROR;
+ goto _free_res;
+ }
+
+ serial->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (serial->irq < 0)
+ {
+ err = serial->irq;
+ goto _free_res;
+ }
+
+ serial->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(serial->clk))
+ {
+ err = rt_ptr_err(serial->clk);
+ goto _free_res;
+ }
+
+ if ((err = rt_clk_enable(serial->clk)))
+ {
+ goto _free_res;
+ }
+
+ serial->freq = rt_clk_get_rate(serial->clk);
+
+ dev->user_data = serial;
+
+ rt_dm_dev_bind_fwdata(&serial->parent.parent, pdev->parent.ofw_node, &serial->parent);
+
+ serial->parent.ops = &serial8250_uart_ops;
+ serial->parent.config = config;
+ serial->regshift = 2;
+ serial->iotype = PORT_MMIO;
+ serial->remove = &bcm2835aux_serial_remove;
+ serial->data = bcm2835aux;
+
+ bcm2835aux->cntl = BCM2835_AUX_UART_CNTL_RXEN | BCM2835_AUX_UART_CNTL_TXEN;
+
+ if ((err = serial8250_setup(serial)))
+ {
+ goto _free_res;
+ }
+
+ return RT_EOK;
+
+_free_res:
+ bcm2835aux_free_resource(bcm2835aux);
+
+ return err;
+}
+
+static rt_err_t bcm2835aux_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct serial8250 *serial = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ return serial8250_remove(serial);
+}
+
+static const struct rt_ofw_node_id bcm2835aux_ofw_ids[] =
+{
+ { .type = "ttyS", .compatible = "brcm,bcm2835-aux-uart" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835aux_driver =
+{
+ .name = "bcm2835-aux-uart",
+ .ids = bcm2835aux_ofw_ids,
+
+ .probe = bcm2835aux_probe,
+ .remove = bcm2835aux_remove,
+};
+
+static int bcm2835aux_drv_register(void)
+{
+ rt_platform_driver_register(&bcm2835aux_driver);
+
+ return 0;
+}
+INIT_PLATFORM_EXPORT(bcm2835aux_drv_register);
diff --git a/bsp/raspberry-pi/dm/serial/8250-bcm7271.c b/bsp/raspberry-pi/dm/serial/8250-bcm7271.c
new file mode 100755
index 0000000000..792e8001a2
--- /dev/null
+++ b/bsp/raspberry-pi/dm/serial/8250-bcm7271.c
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rtthread.h>
+
+#define DBG_TAG "serial.8250.bcm7271"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include "8250.h"
+
+/* Register definitions for UART DMA block. Version 1.1 or later. */
+#define UDMA_ARB_RX 0x00
+#define UDMA_ARB_TX 0x04
+#define UDMA_ARB_REQ 0x00000001
+#define UDMA_ARB_GRANT 0x00000002
+
+#define UDMA_RX_REVISION 0x00
+#define UDMA_RX_REVISION_REQUIRED 0x00000101
+#define UDMA_RX_CTRL 0x04
+#define UDMA_RX_CTRL_BUF_CLOSE_MODE 0x00010000
+#define UDMA_RX_CTRL_MASK_WR_DONE 0x00008000
+#define UDMA_RX_CTRL_ENDIAN_OVERRIDE 0x00004000
+#define UDMA_RX_CTRL_ENDIAN 0x00002000
+#define UDMA_RX_CTRL_OE_IS_ERR 0x00001000
+#define UDMA_RX_CTRL_PE_IS_ERR 0x00000800
+#define UDMA_RX_CTRL_FE_IS_ERR 0x00000400
+#define UDMA_RX_CTRL_NUM_BUF_USED_MASK 0x000003c0
+#define UDMA_RX_CTRL_NUM_BUF_USED_SHIFT 6
+#define UDMA_RX_CTRL_BUF_CLOSE_CLK_SEL_SYS 0x00000020
+#define UDMA_RX_CTRL_BUF_CLOSE_ENA 0x00000010
+#define UDMA_RX_CTRL_TIMEOUT_CLK_SEL_SYS 0x00000008
+#define UDMA_RX_CTRL_TIMEOUT_ENA 0x00000004
+#define UDMA_RX_CTRL_ABORT 0x00000002
+#define UDMA_RX_CTRL_ENA 0x00000001
+#define UDMA_RX_STATUS 0x08
+#define UDMA_RX_STATUS_ACTIVE_BUF_MASK 0x0000000f
+#define UDMA_RX_TRANSFER_LEN 0x0c
+#define UDMA_RX_TRANSFER_TOTAL 0x10
+#define UDMA_RX_BUFFER_SIZE 0x14
+#define UDMA_RX_SRC_ADDR 0x18
+#define UDMA_RX_TIMEOUT 0x1c
+#define UDMA_RX_BUFFER_CLOSE 0x20
+#define UDMA_RX_BLOCKOUT_COUNTER 0x24
+#define UDMA_RX_BUF0_PTR_LO 0x28
+#define UDMA_RX_BUF0_PTR_HI 0x2c
+#define UDMA_RX_BUF0_STATUS 0x30
+#define UDMA_RX_BUFX_STATUS_OVERRUN_ERR 0x00000010
+#define UDMA_RX_BUFX_STATUS_FRAME_ERR 0x00000008
+#define UDMA_RX_BUFX_STATUS_PARITY_ERR 0x00000004
+#define UDMA_RX_BUFX_STATUS_CLOSE_EXPIRED 0x00000002
+#define UDMA_RX_BUFX_STATUS_DATA_RDY 0x00000001
+#define UDMA_RX_BUF0_DATA_LEN 0x34
+#define UDMA_RX_BUF1_PTR_LO 0x38
+#define UDMA_RX_BUF1_PTR_HI 0x3c
+#define UDMA_RX_BUF1_STATUS 0x40
+#define UDMA_RX_BUF1_DATA_LEN 0x44
+
+#define UDMA_TX_REVISION 0x00
+#define UDMA_TX_REVISION_REQUIRED 0x00000101
+#define UDMA_TX_CTRL 0x04
+#define UDMA_TX_CTRL_ENDIAN_OVERRIDE 0x00000080
+#define UDMA_TX_CTRL_ENDIAN 0x00000040
+#define UDMA_TX_CTRL_NUM_BUF_USED_MASK 0x00000030
+#define UDMA_TX_CTRL_NUM_BUF_USED_1 0x00000010
+#define UDMA_TX_CTRL_ABORT 0x00000002
+#define UDMA_TX_CTRL_ENA 0x00000001
+#define UDMA_TX_DST_ADDR 0x08
+#define UDMA_TX_BLOCKOUT_COUNTER 0x10
+#define UDMA_TX_TRANSFER_LEN 0x14
+#define UDMA_TX_TRANSFER_TOTAL 0x18
+#define UDMA_TX_STATUS 0x20
+#define UDMA_TX_BUF0_PTR_LO 0x24
+#define UDMA_TX_BUF0_PTR_HI 0x28
+#define UDMA_TX_BUF0_STATUS 0x2c
+#define UDMA_TX_BUFX_LAST 0x00000002
+#define UDMA_TX_BUFX_EMPTY 0x00000001
+#define UDMA_TX_BUF0_DATA_LEN 0x30
+#define UDMA_TX_BUF0_DATA_SENT 0x34
+#define UDMA_TX_BUF1_PTR_LO 0x38
+
+#define UDMA_INTR_STATUS 0x00
+#define UDMA_INTR_ARB_TX_GRANT 0x00040000
+#define UDMA_INTR_ARB_RX_GRANT 0x00020000
+#define UDMA_INTR_TX_ALL_EMPTY 0x00010000
+#define UDMA_INTR_TX_EMPTY_BUF1 0x00008000
+#define UDMA_INTR_TX_EMPTY_BUF0 0x00004000
+#define UDMA_INTR_TX_ABORT 0x00002000
+#define UDMA_INTR_TX_DONE 0x00001000
+#define UDMA_INTR_RX_ERROR 0x00000800
+#define UDMA_INTR_RX_TIMEOUT 0x00000400
+#define UDMA_INTR_RX_READY_BUF7 0x00000200
+#define UDMA_INTR_RX_READY_BUF6 0x00000100
+#define UDMA_INTR_RX_READY_BUF5 0x00000080
+#define UDMA_INTR_RX_READY_BUF4 0x00000040
+#define UDMA_INTR_RX_READY_BUF3 0x00000020
+#define UDMA_INTR_RX_READY_BUF2 0x00000010
+#define UDMA_INTR_RX_READY_BUF1 0x00000008
+#define UDMA_INTR_RX_READY_BUF0 0x00000004
+#define UDMA_INTR_RX_READY_MASK 0x000003fc
+#define UDMA_INTR_RX_READY_SHIFT 2
+#define UDMA_INTR_RX_ABORT 0x00000002
+#define UDMA_INTR_RX_DONE 0x00000001
+#define UDMA_INTR_SET 0x04
+#define UDMA_INTR_CLEAR 0x08
+#define UDMA_INTR_MASK_STATUS 0x0c
+#define UDMA_INTR_MASK_SET 0x10
+#define UDMA_INTR_MASK_CLEAR 0x14
+
+#define UDMA_RX_INTERRUPTS ( \
+ UDMA_INTR_RX_ERROR | \
+ UDMA_INTR_RX_TIMEOUT | \
+ UDMA_INTR_RX_READY_BUF0 | \
+ UDMA_INTR_RX_READY_BUF1 | \
+ UDMA_INTR_RX_READY_BUF2 | \
+ UDMA_INTR_RX_READY_BUF3 | \
+ UDMA_INTR_RX_READY_BUF4 | \
+ UDMA_INTR_RX_READY_BUF5 | \
+ UDMA_INTR_RX_READY_BUF6 | \
+ UDMA_INTR_RX_READY_BUF7 | \
+ UDMA_INTR_RX_ABORT | \
+ UDMA_INTR_RX_DONE)
+
+#define UDMA_RX_ERR_INTERRUPTS ( \
+ UDMA_INTR_RX_ERROR | \
+ UDMA_INTR_RX_TIMEOUT | \
+ UDMA_INTR_RX_ABORT | \
+ UDMA_INTR_RX_DONE)
+
+#define UDMA_TX_INTERRUPTS ( \
+ UDMA_INTR_TX_ABORT | \
+ UDMA_INTR_TX_DONE)
+
+#define UDMA_IS_RX_INTERRUPT(status) ((status) & UDMA_RX_INTERRUPTS)
+#define UDMA_IS_TX_INTERRUPT(status) ((status) & UDMA_TX_INTERRUPTS)
+
+
+/* Current devices have 8 sets of RX buffer registers */
+#define UDMA_RX_BUFS_COUNT 8
+#define UDMA_RX_BUFS_REG_OFFSET (UDMA_RX_BUF1_PTR_LO - UDMA_RX_BUF0_PTR_LO)
+#define UDMA_RX_BUFx_PTR_LO(x) (UDMA_RX_BUF0_PTR_LO + ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_PTR_HI(x) (UDMA_RX_BUF0_PTR_HI + ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_STATUS(x) (UDMA_RX_BUF0_STATUS + ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_DATA_LEN(x) (UDMA_RX_BUF0_DATA_LEN + ((x) * UDMA_RX_BUFS_REG_OFFSET))
+
+/* Current devices have 2 sets of TX buffer registers */
+#define UDMA_TX_BUFS_COUNT 2
+#define UDMA_TX_BUFS_REG_OFFSET (UDMA_TX_BUF1_PTR_LO - UDMA_TX_BUF0_PTR_LO)
+#define UDMA_TX_BUFx_PTR_LO(x) (UDMA_TX_BUF0_PTR_LO + ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_PTR_HI(x) (UDMA_TX_BUF0_PTR_HI + ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_STATUS(x) (UDMA_TX_BUF0_STATUS + ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_DATA_LEN(x) (UDMA_TX_BUF0_DATA_LEN + ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_DATA_SENT(x) (UDMA_TX_BUF0_DATA_SENT + ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define REGS_8250 0
+#define REGS_DMA_RX 1
+#define REGS_DMA_TX 2
+#define REGS_DMA_ISR 3
+#define REGS_DMA_ARB 4
+#define REGS_MAX 5
+
+#define TX_BUF_SIZE 4096
+#define RX_BUF_SIZE 4096
+#define RX_BUFS_COUNT 2
+#define UART_XMIT_SIZE RT_DMA_PAGE_SIZE
+#define KHZ 1000
+#define MHZ(x) ((x) * KHZ * KHZ)
+#define NSEC_PER_SEC 1000000000L
+#define NSEC_PER_MSEC 1000000L
+
+static const rt_uint32_t brcmstb_rate_table[] =
+{
+ MHZ(81),
+ MHZ(108),
+ MHZ(64), /* Actually 64285715 for some chips */
+ MHZ(48),
+};
+
+static const rt_uint32_t brcmstb_rate_table_7278[] =
+{
+ MHZ(81),
+ MHZ(108),
+ 0,
+ MHZ(48),
+};
+
+struct brcmuart
+{
+ struct serial8250 parent;
+
+ int dma_irq;
+ void *regs[REGS_MAX];
+ struct rt_device *dev;
+
+ rt_ubase_t default_mux_rate;
+ rt_uint32_t real_rates[RT_ARRAY_SIZE(brcmstb_rate_table)];
+ const rt_uint32_t *rate_table;
+
+ rt_uint32_t char_wait_ms;
+ struct rt_timer char_wait_work;
+
+ rt_bool_t dma_enabled;
+
+ void *rx_bufs;
+ int rx_index;
+ int rx_next_buf;
+ rt_ubase_t rx_addr;
+ rt_size_t rx_size;
+ rt_bool_t rx_running;
+
+ void *tx_buf;
+ rt_ubase_t tx_addr;
+ rt_size_t tx_size;
+ rt_bool_t tx_running;
+};
+
+#define to_brcmuart(serial8250) rt_container_of(serial8250, struct brcmuart, parent)
+
+static rt_uint32_t udma_readl(struct brcmuart *brcmuart, int reg_type, int offset)
+{
+ return HWREG32(brcmuart->regs[reg_type] + offset);
+}
+
+static void udma_writel(struct brcmuart *brcmuart, int reg_type, int offset, rt_uint32_t value)
+{
+ HWREG32(brcmuart->regs[reg_type] + offset) = value;
+}
+
+static void udma_set(struct brcmuart *brcmuart, int reg_type, int offset, rt_uint32_t bits)
+{
+ rt_uint32_t value;
+ void *reg = brcmuart->regs[reg_type] + offset;
+
+ value = HWREG32(reg);
+ value |= bits;
+ HWREG32(reg) = value;
+}
+
+static void udma_unset(struct brcmuart *brcmuart, int reg_type, int offset, rt_uint32_t bits)
+{
+ rt_uint32_t value;
+ void *reg = brcmuart->regs[reg_type] + offset;
+
+ value = HWREG32(reg);
+ value &= ~bits;
+ HWREG32(reg) = value;
+}
+
+/*
+ * The UART DMA engine hardware can be used by multiple UARTS, but
+ * only one at a time. Sharing is not currently supported so
+ * the first UART to request the DMA engine will get it and any
+ * subsequent requests by other UARTS will fail.
+ */
+static int brcmuart_arbitration(struct brcmuart *brcmuart, rt_bool_t acquire)
+{
+ int ret = 0;
+ rt_uint32_t rx_grant, tx_grant;
+
+ if (acquire)
+ {
+ int waits = 1;
+
+ udma_set(brcmuart, REGS_DMA_ARB, UDMA_ARB_RX, UDMA_ARB_REQ);
+ udma_set(brcmuart, REGS_DMA_ARB, UDMA_ARB_TX, UDMA_ARB_REQ);
+
+ while (RT_TRUE)
+ {
+ rx_grant = udma_readl(brcmuart, REGS_DMA_ARB, UDMA_ARB_RX);
+ tx_grant = udma_readl(brcmuart, REGS_DMA_ARB, UDMA_ARB_TX);
+
+ if (rx_grant & tx_grant & UDMA_ARB_GRANT)
+ {
+ return 0;
+ }
+
+ if (waits-- == 0)
+ {
+ break;
+ }
+
+ rt_thread_mdelay(1);
+ }
+
+ ret = 1;
+ }
+
+ udma_unset(brcmuart, REGS_DMA_ARB, UDMA_ARB_RX, UDMA_ARB_REQ);
+ udma_unset(brcmuart, REGS_DMA_ARB, UDMA_ARB_TX, UDMA_ARB_REQ);
+
+ return ret;
+}
+
+static void brcmuart_init_dma_hardware(struct brcmuart *brcmuart)
+{
+ rt_uint32_t daddr, value;
+
+ /* Start with all interrupts disabled */
+ udma_writel(brcmuart, REGS_DMA_ISR, UDMA_INTR_MASK_SET, 0xffffffff);
+
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_BUFFER_SIZE, RX_BUF_SIZE);
+
+ /*
+ * Setup buffer close to happen when 32 character times have
+ * elapsed since the last character was received.
+ */
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_BUFFER_CLOSE, 16 * 10 *32);
+ value = (RX_BUFS_COUNT << UDMA_RX_CTRL_NUM_BUF_USED_SHIFT)
+ | UDMA_RX_CTRL_BUF_CLOSE_MODE
+ | UDMA_RX_CTRL_BUF_CLOSE_ENA;
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_CTRL, value);
+
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_BLOCKOUT_COUNTER, 0);
+ daddr = brcmuart->rx_addr;
+
+ for (int i = 0; i < RX_BUFS_COUNT; ++i)
+ {
+ /* Set RX transfer length to 0 for unknown */
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_TRANSFER_LEN, 0);
+
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_BUFx_PTR_LO(i),
+ rt_lower_32_bits(daddr));
+ udma_writel(brcmuart, REGS_DMA_RX, UDMA_RX_BUFx_PTR_HI(i),
+ rt_upper_32_bits(daddr));
+ daddr += RX_BUF_SIZE;
+ }
+
+ daddr = brcmuart->tx_addr;
+ udma_writel(brcmuart, REGS_DMA_TX, UDMA_TX_BUFx_PTR_LO(0),
+ rt_lower_32_bits(daddr));
+ udma_writel(brcmuart, REGS_DMA_TX, UDMA_TX_BUFx_PTR_HI(0),
+ rt_upper_32_bits(daddr));
+ udma_writel(brcmuart, REGS_DMA_TX, UDMA_TX_CTRL,
+ UDMA_TX_CTRL_NUM_BUF_USED_1);
+
+ /* Clear all interrupts then enable them */
+ udma_writel(brcmuart, REGS_DMA_ISR, UDMA_INTR_CLEAR, 0xffffffff);
+ udma_writel(brcmuart, REGS_DMA_ISR, UDMA_INTR_MASK_CLEAR,
+ UDMA_RX_INTERRUPTS | UDMA_TX_INTERRUPTS);
+}
+
+static void start_rx_dma(struct brcmuart *brcmuart)
+{
+ udma_unset(brcmuart, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ENA);
+
+ /* Clear the RX ready bit for all buffers */
+ for (int i = 0; i < RX_BUFS_COUNT; ++i)
+ {
+ udma_unset(brcmuart, REGS_DMA_RX, UDMA_RX_BUFx_STATUS(i),
+ UDMA_RX_BUFX_STATUS_DATA_RDY);
+ }
+
+ /* Always start with buffer 0 */
+ udma_unset(brcmuart, REGS_DMA_RX, UDMA_RX_STATUS,
+ UDMA_RX_STATUS_ACTIVE_BUF_MASK);
+ brcmuart->rx_next_buf = 0;
+
+ udma_set(brcmuart, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ENA);
+ brcmuart->rx_running = RT_TRUE;
+}
+
+static void stop_rx_dma(struct brcmuart *brcmuart)
+{
+ /* If RX is running, set the RX ABORT */
+ if (brcmuart->rx_running)
+ {
+ udma_set(brcmuart, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ABORT);
+ }
+}
+
+static int stop_tx_dma(struct brcmuart *brcmuart)
+{
+ rt_uint32_t value;
+
+ /* If TX is running, set the TX ABORT */
+ value = udma_readl(brcmuart, REGS_DMA_TX, UDMA_TX_CTRL);
+
+ if (value & UDMA_TX_CTRL_ENA)
+ {
+ udma_set(brcmuart, REGS_DMA_TX, UDMA_TX_CTRL, UDMA_TX_CTRL_ABORT);
+ }
+
+ brcmuart->tx_running = RT_FALSE;
+ return 0;
+}
+
+static void brcmuart_rx_buf_done(struct brcmuart *brcmuart, int index)
+{
+ rt_uint32_t status, length;
+
+ /* Make sure we're still in sync with the hardware */
+ status = udma_readl(brcmuart, REGS_DMA_RX, UDMA_RX_BUFx_STATUS(index));
+ length = udma_readl(brcmuart, REGS_DMA_RX, UDMA_RX_BUFx_DATA_LEN(index));
+
+ if ((status & UDMA_RX_BUFX_STATUS_DATA_RDY) == 0)
+ {
+ LOG_E("RX done interrupt but DATA_RDY not found");
+ return;
+ }
+
+ if (status & (UDMA_RX_BUFX_STATUS_OVERRUN_ERR |
+ UDMA_RX_BUFX_STATUS_FRAME_ERR |
+ UDMA_RX_BUFX_STATUS_PARITY_ERR))
+ {
+ if (status & UDMA_RX_BUFX_STATUS_OVERRUN_ERR)
+ {
+ LOG_W("RX Overrun");
+ }
+ if (status & UDMA_RX_BUFX_STATUS_FRAME_ERR)
+ {
+ LOG_W("RX Framing");
+ }
+ if (status & UDMA_RX_BUFX_STATUS_PARITY_ERR)
+ {
+ LOG_W("RX Parity");
+ }
+ }
+
+ brcmuart->rx_index = index * RX_BUF_SIZE;
+ serial8250_dma_rx_done(&brcmuart->parent, length);
+}
+
+static void brcmuart_rx_work(struct brcmuart *brcmuart, rt_uint32_t rx_isr)
+{
+ rt_uint32_t rx_done_isr, check_isr;
+
+ rx_done_isr = (rx_isr & UDMA_INTR_RX_READY_MASK);
+
+ while (rx_done_isr)
+ {
+ check_isr = UDMA_INTR_RX_READY_BUF0 << brcmuart->rx_next_buf;
+
+ if (check_isr & rx_done_isr)
+ {
+ brcmuart_rx_buf_done(brcmuart, brcmuart->rx_next_buf);
+ }
+ else
+ {
+ LOG_E("RX buffer ready out of sequence, restarting RX DMA");
+ start_rx_dma(brcmuart);
+
+ break;
+ }
+ if (rx_isr & UDMA_RX_ERR_INTERRUPTS)
+ {
+ if (rx_isr & UDMA_INTR_RX_ERROR)
+ {
+ LOG_D("RX Error");
+ }
+ if (rx_isr & UDMA_INTR_RX_TIMEOUT)
+ {
+ LOG_E("RX Timeout");
+ }
+ if (rx_isr & UDMA_INTR_RX_ABORT)
+ {
+ LOG_D("RX Abort");
+ }
+
+ brcmuart->rx_running = RT_FALSE;
+ }
+ /* If not ABORT, re-enable RX buffer */
+ if (!(rx_isr & UDMA_INTR_RX_ABORT))
+ {
+ udma_unset(brcmuart, REGS_DMA_RX,
+ UDMA_RX_BUFx_STATUS(brcmuart->rx_next_buf), UDMA_RX_BUFX_STATUS_DATA_RDY);
+ }
+
+ rx_done_isr &= ~check_isr;
+ brcmuart->rx_next_buf++;
+
+ if (brcmuart->rx_next_buf == RX_BUFS_COUNT)
+ {
+ brcmuart->rx_next_buf = 0;
+ }
+ }
+}
+
+static void set_clock_mux(struct brcmuart *brcmuart, rt_uint32_t baud)
+{
+ rt_tick_t tick;
+ int best_index = -1, real_baud, i;
+ rt_uint64_t hires_rate, hires_baud, hires_err;
+ rt_uint32_t percent, best_percent = RT_UINT32_MAX, quot, best_quot = 1, rate;
+
+ /* Find the closest match for specified baud */
+ for (i = 0; i < RT_ARRAY_SIZE(brcmuart->real_rates); ++i)
+ {
+ if (brcmuart->real_rates[i] == 0)
+ {
+ continue;
+ }
+
+ rate = brcmuart->real_rates[i] / 16;
+ quot = RT_DIV_ROUND_CLOSEST(rate, baud);
+ if (!quot)
+ {
+ continue;
+ }
+
+ /* increase resolution to get xx.xx percent */
+ hires_rate = (rt_uint64_t)rate * 10000;
+ hires_baud = (rt_uint64_t)baud * 10000;
+
+ hires_err = rt_div_u64(hires_rate, (rt_uint64_t)quot);
+
+ /* get the delta */
+ if (hires_err > hires_baud)
+ {
+ hires_err = hires_err - hires_baud;
+ }
+ else
+ {
+ hires_err = hires_baud - hires_err;
+ }
+
+ percent = (rt_ubase_t)RT_DIV_ROUND_CLOSEST_ULL(hires_err, baud);
+
+ LOG_D("Baud rate: %u, MUX Clk: %u, Error: %u.%u%%",
+ baud, brcmuart->real_rates[i], percent / 100, percent % 100);
+
+ if (percent < best_percent)
+ {
+ best_percent = percent;
+ best_index = i;
+ best_quot = quot;
+ }
+ }
+
+ if (best_index == -1)
+ {
+ LOG_E("%d BAUD rate is too fast", baud);
+ return;
+ }
+
+ rate = brcmuart->real_rates[best_index];
+
+ if (rt_clk_set_rate(brcmuart->parent.clk, rate))
+ {
+ LOG_E("Selecting BAUD MUX clock");
+ }
+
+ /* Error over 3 percent will cause data errors */
+ if (best_percent > 300)
+ {
+ LOG_E("Baud: %d has %u.%u%% error", baud, percent / 100, percent % 100);
+ }
+
+ real_baud = rate / 16 / best_quot;
+ LOG_D("Selecting BAUD MUX rate: %u", rate);
+ LOG_D("Requested baud: %u, Actual baud: %u", baud, real_baud);
+
+ /* calc nanoseconds for 1.5 characters time at the given baud rate */
+ i = NSEC_PER_SEC / real_baud / 10;
+ i += (i / 2);
+ brcmuart->char_wait_ms = NSEC_PER_MSEC / i;
+
+ tick = rt_tick_from_millisecond(brcmuart->char_wait_ms);
+ rt_timer_control(&brcmuart->char_wait_work, RT_TIMER_CTRL_SET_TIME, &tick);
+
+ brcmuart->parent.freq = rate;
+}
+
+static rt_err_t brcmstb_serial_ios(struct serial8250 *serial, struct serial_configure *ios)
+{
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ if (brcmuart->dma_enabled)
+ {
+ stop_rx_dma(brcmuart);
+ }
+
+ if (!rt_is_err_or_null(serial->clk))
+ {
+ set_clock_mux(brcmuart, ios->baud_rate);
+ }
+
+ serial8250_ios(serial, ios);
+
+ if (brcmuart->dma_enabled)
+ {
+ start_rx_dma(brcmuart);
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t brcmuart_serial_dma_enable(struct serial8250 *serial, rt_bool_t enabled)
+{
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ if (!brcmuart->dma_enabled)
+ {
+ return RT_EOK;
+ }
+
+ if (enabled)
+ {
+ rt_uint32_t ier;
+
+ ier = serial->serial_in(serial, UART_IER);
+ serial->serial_out(serial, UART_IER, ier & ~UART_IER_RDI);
+
+ brcmuart_init_dma_hardware(brcmuart);
+ start_rx_dma(brcmuart);
+ }
+ else
+ {
+ rt_ubase_t level = rt_spin_lock_irqsave(&serial->spinlock);
+
+ stop_rx_dma(brcmuart);
+ stop_tx_dma(brcmuart);
+
+ /* Disable all interrupts */
+ udma_writel(brcmuart, REGS_DMA_ISR, UDMA_INTR_MASK_SET,
+ UDMA_RX_INTERRUPTS | UDMA_TX_INTERRUPTS);
+
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+ }
+
+ return RT_EOK;
+}
+
+static rt_ssize_t brcmuart_serial_dma_tx(struct serial8250 *serial,
+ const rt_uint8_t *buf, rt_size_t size)
+{
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ if (brcmuart->tx_running)
+ {
+ return 0;
+ }
+
+ size = rt_min_t(rt_size_t, size, brcmuart->tx_size);
+ rt_memcpy(brcmuart->tx_buf, buf, size);
+
+ udma_writel(brcmuart, REGS_DMA_TX, UDMA_TX_TRANSFER_LEN, size);
+ udma_writel(brcmuart, REGS_DMA_TX, UDMA_TX_BUF0_DATA_LEN, size);
+ udma_unset(brcmuart, REGS_DMA_TX, UDMA_TX_BUF0_STATUS, UDMA_TX_BUFX_EMPTY);
+ udma_set(brcmuart, REGS_DMA_TX, UDMA_TX_CTRL, UDMA_TX_CTRL_ENA);
+ brcmuart->tx_running = RT_TRUE;
+
+ return size;
+}
+
+static rt_ssize_t brcmuart_serial_dma_rx(struct serial8250 *serial,
+ rt_uint8_t *buf, rt_size_t size)
+{
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ size = rt_min_t(rt_size_t, size, brcmuart->rx_size - brcmuart->rx_index);
+ rt_memcpy(buf, brcmuart->rx_bufs + brcmuart->rx_index, size);
+
+ return size;
+}
+
+static rt_err_t brcmuart_serial_isr(struct serial8250 *serial, int irq)
+{
+ rt_ubase_t level;
+ rt_uint32_t iir, ier, mcr, status;
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ iir = serial->serial_in(serial, UART_LSR);
+
+ /*
+ * There's a bug in some 8250 cores where we get a timeout
+ * interrupt but there is no data ready.
+ */
+ if (((iir & UART_IIR_ID) == UART_IIR_RX_TIMEOUT))
+ {
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+
+ status = serial->serial_in(serial, UART_LSR);
+
+ if ((status & UART_LSR_DR) == 0)
+ {
+ ier = serial->serial_in(serial, UART_IER);
+ mcr = serial->serial_in(serial, UART_MCR);
+
+ /*
+ * if Receive Data Interrupt is enabled and
+ * we're uing hardware flow control, deassert
+ * RTS and wait for any chars in the pipline to
+ * arrive and then check for DR again.
+ */
+ if ((ier & UART_IER_RDI) && (mcr & UART_MCR_AFE))
+ {
+ ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ serial->serial_out(serial, UART_IER, ier);
+
+ mcr = serial->serial_in(serial, UART_MCR);
+ mcr &= ~UART_MCR_RTS;
+ serial->serial_out(serial, UART_MCR, mcr);
+
+ rt_timer_start(&brcmuart->char_wait_work);
+ }
+ else
+ {
+ serial->serial_in(serial, UART_RX);
+ }
+ }
+
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+ }
+
+ return RT_EOK;
+}
+
+static void brcmuart_dma_isr(int irqno, void *param)
+{
+ rt_ubase_t level;
+ rt_uint32_t interrupts, rval, tval;
+ struct brcmuart *brcmuart = param;
+ struct serial8250 *serial = &brcmuart->parent;
+
+ interrupts = udma_readl(brcmuart, REGS_DMA_ISR, UDMA_INTR_STATUS);
+
+ if (!interrupts)
+ {
+ return;
+ }
+
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+
+ /* Clear all interrupts */
+ udma_writel(brcmuart, REGS_DMA_ISR, UDMA_INTR_CLEAR, interrupts);
+
+ if ((rval = UDMA_IS_RX_INTERRUPT(interrupts)))
+ {
+ brcmuart_rx_work(brcmuart, rval);
+ }
+
+ if ((tval = UDMA_IS_TX_INTERRUPT(interrupts)))
+ {
+ if (tval & UDMA_INTR_TX_ABORT)
+ {
+ if (brcmuart->tx_running)
+ {
+ LOG_E("Unexpected TX_ABORT interrupt");
+ }
+ }
+ else
+ {
+ brcmuart->tx_running = RT_FALSE;
+ serial8250_dma_tx_done(serial);
+ }
+ }
+
+ if ((rval | tval) == 0)
+ {
+ LOG_W("Spurious interrupt: 0x%x", interrupts);
+ }
+
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+}
+
+static void brcmuart_char_wait_work(void *param)
+{
+ rt_ubase_t level;
+ rt_uint32_t ier, status;
+ struct brcmuart *brcmuart = param;
+ struct serial8250 *serial = &brcmuart->parent;
+
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+
+ status = serial->serial_in(serial, UART_LSR);
+
+ /*
+ * If a character did not arrive after the timeout, clear the false
+ * receive timeout.
+ */
+ if ((status & UART_LSR_DR) == 0)
+ {
+ serial->serial_in(serial, UART_RX);
+ }
+ ier = serial->serial_in(serial, UART_IER);
+
+ /* re-enable receive unless upper layer has disabled it */
+ if ((ier & (UART_IER_RLSI | UART_IER_RDI)) == (UART_IER_RLSI | UART_IER_RDI))
+ {
+ status = serial->serial_in(serial, UART_IER);
+ status |= (UART_IER_RLSI | UART_IER_RDI);
+ serial->serial_out(serial, UART_IER, status);
+ status = serial->serial_in(serial, UART_MCR);
+ status |= UART_MCR_RTS;
+ serial->serial_out(serial, UART_MCR, status);
+ }
+
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+}
+
+static void brcmuart_free_resource(struct brcmuart *brcmuart)
+{
+ struct serial8250 *serial = &brcmuart->parent;
+
+ if (serial->base)
+ {
+ rt_iounmap(serial->base);
+ }
+
+ if (!rt_is_err_or_null(serial->clk))
+ {
+ rt_clk_disable_unprepare(serial->clk);
+ rt_clk_put(serial->clk);
+ }
+
+ if (brcmuart->rx_bufs)
+ {
+ rt_dma_free_coherent(brcmuart->dev, brcmuart->rx_size,
+ brcmuart->rx_bufs, brcmuart->rx_addr);
+ }
+ if (brcmuart->tx_buf)
+ {
+ rt_dma_free_coherent(brcmuart->dev, brcmuart->tx_size,
+ brcmuart->tx_buf, brcmuart->tx_addr);
+ }
+
+ if (brcmuart->dma_enabled)
+ {
+ brcmuart_arbitration(brcmuart, 0);
+ }
+
+ rt_free(brcmuart);
+}
+
+static void brcmuart_serial_remove(struct serial8250 *serial)
+{
+ struct brcmuart *brcmuart = to_brcmuart(serial);
+
+ brcmuart_free_resource(brcmuart);
+
+ rt_timer_detach(&brcmuart->char_wait_work);
+}
+
+static rt_err_t brcmuart_probe(struct rt_platform_device *pdev)
+{
+ int ridx;
+ rt_err_t err;
+ const char *dev_name;
+ static const char * const reg_names[REGS_MAX] =
+ {
+ "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb"
+ };
+ struct serial8250 *serial;
+ struct rt_device *dev = &pdev->parent;
+ struct brcmuart *brcmuart = rt_calloc(1, sizeof(*brcmuart));
+ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+ if (!brcmuart)
+ {
+ return -RT_EINVAL;
+ }
+
+ brcmuart->dev = dev;
+
+ if (pdev->id)
+ {
+ brcmuart->rate_table = pdev->id->data;
+ }
+ else
+ {
+ brcmuart->rate_table = brcmstb_rate_table;
+ }
+
+ serial = &brcmuart->parent;
+
+ serial->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (serial->irq < 0)
+ {
+ err = serial->irq;
+
+ goto _free_res;
+ }
+
+ for (ridx = 0; ridx < REGS_MAX; ++ridx)
+ {
+ brcmuart->regs[ridx] = rt_dm_dev_iomap_by_name(dev, reg_names[ridx]);
+
+ if (!brcmuart->regs[ridx])
+ {
+ if (rt_dm_dev_prop_index_of_string(dev, "reg-names", reg_names[ridx]) < 0)
+ {
+ break;
+ }
+
+ err = -RT_EIO;
+ goto _free_res;
+ }
+
+ if (ridx == REGS_8250)
+ {
+ serial->base = brcmuart->regs[ridx];
+ }
+ }
+
+ if (ridx != 1 && ridx != REGS_MAX)
+ {
+ LOG_E("Registers %s not specified", reg_names[ridx]);
+ err = -RT_EINVAL;
+ goto _free_res;
+ }
+
+ if (ridx > REGS_DMA_RX)
+ {
+ if (brcmuart_arbitration(brcmuart, 1) == 0)
+ {
+ rt_uint32_t txrev = 0, rxrev = 0;
+
+ txrev = udma_readl(brcmuart, REGS_DMA_RX, UDMA_RX_REVISION);
+ rxrev = udma_readl(brcmuart, REGS_DMA_TX, UDMA_TX_REVISION);
+
+ if (txrev >= UDMA_TX_REVISION_REQUIRED &&
+ rxrev >= UDMA_RX_REVISION_REQUIRED)
+ {
+ /* Enable the use of the DMA hardware */
+ brcmuart->dma_enabled = RT_TRUE;
+ }
+ else
+ {
+ brcmuart_arbitration(brcmuart, 0);
+
+ LOG_E("Unsupported DMA Hardware Revision");
+ }
+ }
+ else
+ {
+ LOG_E("Timeout arbitrating for UART DMA hardware");
+ }
+ }
+
+ if (brcmuart->dma_enabled)
+ {
+ brcmuart->dma_irq = rt_dm_dev_get_irq_by_name(dev, "dma");
+
+ if (brcmuart->dma_irq < 0)
+ {
+ err = brcmuart->dma_irq;
+ LOG_E("Get DMA IRQ error = %s", rt_strerror(err));
+
+ goto _free_res;
+ }
+
+ brcmuart->rx_size = RX_BUF_SIZE * RX_BUFS_COUNT;
+ brcmuart->rx_bufs = rt_dma_alloc_coherent(dev, brcmuart->rx_size, &brcmuart->rx_addr);
+
+ if (!brcmuart->rx_bufs)
+ {
+ err = -RT_ENOMEM;
+ goto _free_res;
+ }
+
+ brcmuart->tx_size = UART_XMIT_SIZE;
+ brcmuart->tx_buf = rt_dma_alloc_coherent(dev, brcmuart->tx_size, &brcmuart->tx_addr);
+
+ if (!brcmuart->tx_buf)
+ {
+ err = -RT_ENOMEM;
+ goto _free_res;
+ }
+ }
+
+ rt_dm_dev_prop_read_u32(dev, "clock-frequency", &serial->freq);
+
+ serial->clk = rt_clk_get_by_name(dev, "sw_baud");
+
+ if (rt_is_err(serial->clk))
+ {
+ err = rt_ptr_err(serial->clk);
+
+ goto _free_res;
+ }
+ else if (serial->clk)
+ {
+ if ((err = rt_clk_prepare_enable(serial->clk)))
+ {
+ goto _free_res;
+ }
+
+ brcmuart->default_mux_rate = rt_clk_get_rate(serial->clk);
+
+ for (int i = 0; i < RT_ARRAY_SIZE(brcmuart->real_rates); ++i)
+ {
+ if (!brcmuart->rate_table[i])
+ {
+ brcmuart->real_rates[i] = 0;
+
+ continue;
+ }
+
+ if (rt_clk_set_rate(serial->clk, brcmuart->rate_table[i]))
+ {
+ LOG_E("Error selecting BAUD MUX clock for %u", brcmuart->rate_table[i]);
+ brcmuart->real_rates[i] = brcmuart->rate_table[i];
+ }
+ else
+ {
+ brcmuart->real_rates[i] = rt_clk_get_rate(serial->clk);
+ }
+ }
+
+ rt_clk_set_rate(serial->clk, brcmuart->default_mux_rate);
+
+ serial->freq = brcmuart->default_mux_rate;
+ }
+
+ if (!serial->freq)
+ {
+ LOG_E("clock-frequency or clk not defined");
+
+ err = -RT_EINVAL;
+ goto _free_res;
+ }
+
+ serial->iotype = rt_dm_dev_prop_read_bool(dev, "big-endian") ?
+ PORT_MMIO32BE : PORT_MMIO32;
+
+ serial->parent.ops = &serial8250_uart_ops;
+ serial->parent.config = config;
+
+ serial->serial_ios = brcmstb_serial_ios;
+ if (brcmuart->dma_enabled)
+ {
+ serial->serial_dma_enable = brcmuart_serial_dma_enable;
+ serial->serial_dma_tx = brcmuart_serial_dma_tx;
+ serial->serial_dma_rx = brcmuart_serial_dma_rx;
+ }
+ serial->handle_irq = &brcmuart_serial_isr;
+ serial->remove = &brcmuart_serial_remove;
+ serial->data = brcmuart;
+
+ pdev->parent.user_data = serial;
+
+ if ((err = serial8250_setup(serial)))
+ {
+ goto _free_res;
+ }
+
+ dev_name = rt_dm_dev_get_name(&serial->parent.parent);
+
+ rt_timer_init(&brcmuart->char_wait_work, dev_name, brcmuart_char_wait_work, brcmuart,
+ 0, RT_TIMER_FLAG_PERIODIC);
+
+ if (brcmuart->dma_enabled)
+ {
+ rt_hw_interrupt_install(brcmuart->dma_irq, brcmuart_dma_isr, brcmuart, dev_name);
+ rt_hw_interrupt_umask(brcmuart->dma_irq);
+ }
+
+ return RT_EOK;
+
+_free_res:
+ brcmuart_free_resource(brcmuart);
+
+ return err;
+}
+
+static rt_err_t brcmuart_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct serial8250 *serial = dev->user_data;
+
+ rt_dm_dev_unbind_fwdata(dev, RT_NULL);
+
+ return serial8250_remove(serial);
+}
+
+static const struct rt_ofw_node_id brcmuart_ofw_ids[] =
+{
+ { .type = "ttyS", .compatible = "brcm,bcm7278-uart", .data = brcmstb_rate_table_7278 },
+ { .type = "ttyS", .compatible = "brcm,bcm7271-uart", .data = brcmstb_rate_table },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver brcmuart_driver =
+{
+ .name = "bcm7271-uart",
+ .ids = brcmuart_ofw_ids,
+
+ .probe = brcmuart_probe,
+ .remove = brcmuart_remove,
+};
+
+static int brcmuart_drv_register(void)
+{
+ rt_platform_driver_register(&brcmuart_driver);
+
+ return 0;
+}
+INIT_PLATFORM_EXPORT(brcmuart_drv_register);
diff --git a/bsp/raspberry-pi/dm/serial/Kconfig b/bsp/raspberry-pi/dm/serial/Kconfig
new file mode 100755
index 0000000000..bb5e0ee2d6
--- /dev/null
+++ b/bsp/raspberry-pi/dm/serial/Kconfig
@@ -0,0 +1,11 @@
+config RT_SERIAL_8250_BCM2835AUX
+ bool "BCM2835 auxiliar mini UART"
+ depends on RT_SERIAL_8250
+ default n
+
+config RT_SERIAL_8250_BCM7271
+ bool "Broadcom 8250 based serial port"
+ depends on RT_SERIAL_8250
+ depends on RT_USING_DMA
+ depends on RT_SERIAL_USING_DMA
+ default n
diff --git a/bsp/raspberry-pi/dm/serial/SConscript b/bsp/raspberry-pi/dm/serial/SConscript
new file mode 100755
index 0000000000..d78e788b4b
--- /dev/null
+++ b/bsp/raspberry-pi/dm/serial/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include', cwd + '/../../../../components/drivers/serial/device/8250']
+
+if GetDepend(['RT_SERIAL_8250_BCM2835AUX']):
+ src += ['8250-bcm2835aux.c']
+
+if GetDepend(['RT_SERIAL_8250_BCM7271']):
+ src += ['8250-bcm7271.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/soc/Kconfig b/bsp/raspberry-pi/dm/soc/Kconfig
new file mode 100755
index 0000000000..e1fa03e329
--- /dev/null
+++ b/bsp/raspberry-pi/dm/soc/Kconfig
@@ -0,0 +1,6 @@
+config RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR
+ bool "Raspberry Pi voltage monitor"
+ depends on RT_FIRMWARE_RASPBERRYPI
+ select RT_USING_DEVICE_IPC
+ select RT_USING_SYSTEM_WORKQUEUE
+ default y
diff --git a/bsp/raspberry-pi/dm/soc/SConscript b/bsp/raspberry-pi/dm/soc/SConscript
new file mode 100755
index 0000000000..63a0379401
--- /dev/null
+++ b/bsp/raspberry-pi/dm/soc/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR']):
+ src += ['raspberrypi-voltage-monitor.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/soc/raspberrypi-voltage-monitor.c b/bsp/raspberry-pi/dm/soc/raspberrypi-voltage-monitor.c
new file mode 100755
index 0000000000..56001c5fce
--- /dev/null
+++ b/bsp/raspberry-pi/dm/soc/raspberrypi-voltage-monitor.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-24 GuEe-GUI first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "soc.raspberrypi-voltage-monitor"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <firmware-raspberrypi.h>
+
+#define UNDERVOLTAGE_STICKY_BIT RT_BIT(16)
+
+struct rpi_voltage_monitor
+{
+ struct rt_device_notify alarm;
+
+ rt_uint32_t last_throttled;
+ struct rpi_firmware *rpi_fw;
+ struct rt_work delayed_work;
+};
+
+static rt_err_t rpi_voltage_monitor_open(rt_device_t dev, rt_uint16_t oflag)
+{
+ if (dev->ref_count)
+ {
+ return -RT_EBUSY;
+ }
+
+ return RT_EOK;
+}
+
+static rt_err_t rpi_voltage_monitor_close(rt_device_t dev)
+{
+ struct rpi_voltage_monitor *mon = dev->user_data;
+
+ mon->alarm.notify = RT_NULL;
+
+ return RT_EOK;
+}
+
+static rt_ssize_t rpi_voltage_monitor_read(rt_device_t dev, rt_off_t pos,
+ void *buffer, rt_size_t size)
+{
+ struct rpi_voltage_monitor *mon = dev->user_data;
+
+ if (size <= sizeof(mon->last_throttled))
+ {
+ return -RT_ENOSPC;
+ }
+
+ *(rt_uint32_t *)buffer = !!(mon->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+
+ return sizeof(mon->last_throttled);
+}
+
+static rt_err_t rpi_voltage_monitor_control(rt_device_t dev, int cmd, void *args)
+{
+ rt_err_t err = RT_EOK;
+ struct rpi_voltage_monitor *mon = dev->user_data;
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_NOTIFY_SET:
+ if (!args)
+ {
+ err = -RT_EINVAL;
+ break;
+ }
+ rt_memcpy(&mon->alarm, args, sizeof(mon->alarm));
+ break;
+
+ default:
+ err = -RT_EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops rpi_voltage_monitor_ops =
+{
+ .open = rpi_voltage_monitor_open,
+ .close = rpi_voltage_monitor_close,
+ .read = rpi_voltage_monitor_read,
+ .control = rpi_voltage_monitor_control,
+};
+#endif
+
+static void rpi_voltage_monitor_delayed_work(struct rt_work *work, void *work_data)
+{
+ rt_err_t err;
+ rt_uint32_t new_uv, old_uv, value;
+ struct rpi_voltage_monitor *mon = work_data;
+
+ /* Request firmware to clear sticky bits */
+ value = 0xffff;
+
+ if ((err = rpi_firmware_property(mon->rpi_fw, RPI_FIRMWARE_GET_THROTTLED,
+ &value, sizeof(value))))
+ {
+ LOG_E("Failed to get throttled error = %s", rt_strerror(err));
+ return;
+ }
+
+ new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+ old_uv = mon->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+ mon->last_throttled = value;
+
+ if (new_uv == old_uv)
+ {
+ return;
+ }
+
+ LOG_D(new_uv ? "Undervoltage detected" : "Voltage normalised");
+
+ if (mon->alarm.notify)
+ {
+ mon->alarm.notify(mon->alarm.dev);
+ }
+
+ rt_work_submit(&mon->delayed_work, rt_tick_from_millisecond(200));
+}
+
+static rt_err_t rpi_voltage_monitor_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ const char *dev_name;
+ struct rt_device *dev = &pdev->parent, *fw_dev = pdev->priv;
+ struct rpi_voltage_monitor *mon = rt_calloc(1, sizeof(*mon));
+
+ if (!mon)
+ {
+ return -RT_ENOMEM;
+ }
+
+ mon->rpi_fw = rpi_firmware_get(fw_dev->ofw_node);
+
+ if (!mon->rpi_fw)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ dev->user_data = mon;
+
+ dev->type = RT_Device_Class_Char;
+#ifdef RT_USING_DEVICE_OPS
+ dev->ops = &rpi_voltage_monitor_ops;
+#else
+ dev->open = rpi_voltage_monitor_open,
+ dev->close = rpi_voltage_monitor_close,
+ dev->read = rpi_voltage_monitor_read,
+ dev->control = rpi_voltage_monitor_control,
+#endif
+
+ rt_dm_dev_set_name(dev, "rpi_volt");
+ dev_name = rt_dm_dev_get_name(dev);
+ rt_device_register(dev, dev_name, RT_DEVICE_FLAG_RDONLY);
+
+ rt_work_init(&mon->delayed_work, rpi_voltage_monitor_delayed_work, mon);
+ rt_work_submit(&mon->delayed_work, rt_tick_from_millisecond(200));
+
+ return RT_EOK;
+
+_fail:
+ rt_free(mon);
+
+ return err;
+}
+
+static rt_err_t rpi_voltage_monitor_remove(struct rt_platform_device *pdev)
+{
+ struct rt_device *dev = &pdev->parent;
+ struct rpi_voltage_monitor *mon = dev->user_data;
+
+ rt_work_cancel(&mon->delayed_work);
+
+ rt_device_unregister(dev);
+
+ rpi_firmware_put(mon->rpi_fw);
+ rt_free(mon);
+
+ return RT_EOK;
+}
+
+static struct rt_platform_driver rpi_voltage_monitor_driver =
+{
+ .name = "raspberrypi-voltage-monitor",
+
+ .probe = rpi_voltage_monitor_probe,
+ .remove = rpi_voltage_monitor_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(rpi_voltage_monitor_driver);
diff --git a/bsp/raspberry-pi/dm/spi/Kconfig b/bsp/raspberry-pi/dm/spi/Kconfig
new file mode 100755
index 0000000000..9dfe16a375
--- /dev/null
+++ b/bsp/raspberry-pi/dm/spi/Kconfig
@@ -0,0 +1,15 @@
+config RT_SPI_BCM2835
+ bool "BCM2835 SPI controller"
+ depends on RT_USING_DM
+ depends on RT_USING_SPI
+ depends on RT_USING_PIN
+ depends on RT_USING_PINCTRL
+ default n
+
+config RT_SPI_BCM2835AUX
+ bool "BCM2835 SPI auxiliary controller"
+ depends on RT_USING_DM
+ depends on RT_USING_SPI
+ depends on RT_USING_PIN
+ depends on RT_USING_PINCTRL
+ default n
diff --git a/bsp/raspberry-pi/dm/spi/SConscript b/bsp/raspberry-pi/dm/spi/SConscript
new file mode 100755
index 0000000000..cbde02fa56
--- /dev/null
+++ b/bsp/raspberry-pi/dm/spi/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend('RT_SPI_BCM2835'):
+ src += ['spi-bcm2835.c']
+
+if GetDepend('RT_SPI_BCM2835AUX'):
+ src += ['spi-bcm2835aux.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/spi/spi-bcm2835.c b/bsp/raspberry-pi/dm/spi/spi-bcm2835.c
new file mode 100755
index 0000000000..00ed169758
--- /dev/null
+++ b/bsp/raspberry-pi/dm/spi/spi-bcm2835.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "spi.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#include <cpuport.h>
+
+/* SPI register offsets */
+#define BCM2835_SPI_CS 0x00
+#define BCM2835_SPI_FIFO 0x04
+#define BCM2835_SPI_CLK 0x08
+#define BCM2835_SPI_DLEN 0x0c
+#define BCM2835_SPI_LTOH 0x10
+#define BCM2835_SPI_DC 0x14
+
+/* Bitfields in CS */
+#define BCM2835_SPI_CS_LEN_LONG 0x02000000
+#define BCM2835_SPI_CS_DMA_LEN 0x01000000
+#define BCM2835_SPI_CS_CSPOL2 0x00800000
+#define BCM2835_SPI_CS_CSPOL1 0x00400000
+#define BCM2835_SPI_CS_CSPOL0 0x00200000
+#define BCM2835_SPI_CS_RXF 0x00100000
+#define BCM2835_SPI_CS_RXR 0x00080000
+#define BCM2835_SPI_CS_TXD 0x00040000
+#define BCM2835_SPI_CS_RXD 0x00020000
+#define BCM2835_SPI_CS_DONE 0x00010000
+#define BCM2835_SPI_CS_LEN 0x00002000
+#define BCM2835_SPI_CS_REN 0x00001000
+#define BCM2835_SPI_CS_ADCS 0x00000800
+#define BCM2835_SPI_CS_INTR 0x00000400
+#define BCM2835_SPI_CS_INTD 0x00000200
+#define BCM2835_SPI_CS_DMAEN 0x00000100
+#define BCM2835_SPI_CS_TA 0x00000080
+#define BCM2835_SPI_CS_CSPOL 0x00000040
+#define BCM2835_SPI_CS_CLEAR_RX 0x00000020
+#define BCM2835_SPI_CS_CLEAR_TX 0x00000010
+#define BCM2835_SPI_CS_CPOL 0x00000008
+#define BCM2835_SPI_CS_CPHA 0x00000004
+#define BCM2835_SPI_CS_CS_10 0x00000002
+#define BCM2835_SPI_CS_CS_01 0x00000001
+
+#define BCM2835_SPI_FIFO_SIZE 64
+#define BCM2835_SPI_FIFO_SIZE_3_4 48
+#define BCM2835_SPI_DMA_MIN_LENGTH 96
+#define BCM2835_SPI_POLLING_LIMIT_US 30
+
+struct bcm2835_spi
+{
+ struct rt_spi_bus parent;
+
+ rt_uint8_t mode;
+ rt_ubase_t max_speed_hz;
+
+ int irq;
+ void *regs;
+
+ rt_ubase_t clk_hz;
+ struct rt_clk *clk;
+ struct rt_spi_message *msg;
+
+ const rt_uint8_t *tx_buf;
+ rt_uint8_t *rx_buf;
+ int tx_len;
+ int rx_len;
+ int tx_prologue;
+ int rx_prologue;
+ rt_uint32_t tx_spillover;
+
+ rt_uint32_t prepare_cs;
+ rt_uint32_t clear_rx_cs;
+
+ struct rt_completion done;
+};
+
+#define raw_to_bcm2835_spi(raw) rt_container_of(raw, struct bcm2835_spi, parent)
+
+rt_inline rt_uint32_t bcm2835_rd(struct bcm2835_spi *bs, int reg)
+{
+ return HWREG32(bs->regs + reg);
+}
+
+rt_inline void bcm2835_wr(struct bcm2835_spi *bs, int reg, rt_uint32_t val)
+{
+ HWREG32(bs->regs + reg) = val;
+}
+
+rt_inline void bcm2835_rd_fifo(struct bcm2835_spi *bs)
+{
+ rt_uint8_t byte;
+
+ while (bs->rx_len && (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD))
+ {
+ /* Read flush */
+ byte = bcm2835_rd(bs, BCM2835_SPI_FIFO);
+
+ if (bs->rx_buf)
+ {
+ *bs->rx_buf++ = byte;
+ }
+
+ --bs->rx_len;
+ }
+}
+
+rt_inline void bcm2835_wr_fifo(struct bcm2835_spi *bs)
+{
+ rt_uint8_t byte;
+
+ while (bs->tx_len && (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD))
+ {
+ byte = bs->tx_buf ? *bs->tx_buf++ : 0;
+ bcm2835_wr(bs, BCM2835_SPI_FIFO, byte);
+ --bs->tx_len;
+ }
+}
+
+rt_inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count)
+{
+ int len;
+ rt_uint32_t val;
+
+ bs->rx_len -= count;
+
+ do {
+ val = bcm2835_rd(bs, BCM2835_SPI_FIFO);
+ len = rt_min(count, 4);
+ rt_memcpy(bs->rx_buf, &val, len);
+ bs->rx_buf += len;
+ count -= 4;
+ } while (count > 0);
+}
+
+rt_inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count)
+{
+ int len;
+ rt_uint32_t val;
+
+ bs->tx_len -= count;
+
+ do {
+ if (bs->tx_buf)
+ {
+ len = rt_min(count, 4);
+ rt_memcpy(&val, bs->tx_buf, len);
+ bs->tx_buf += len;
+ }
+ else
+ {
+ val = 0;
+ }
+
+ bcm2835_wr(bs, BCM2835_SPI_FIFO, val);
+ count -= 4;
+ } while (count > 0);
+}
+
+rt_inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs)
+{
+ while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE))
+ {
+ rt_hw_cpu_relax();
+ }
+}
+
+rt_inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count)
+{
+ rt_uint8_t val;
+
+ count = rt_min(count, bs->rx_len);
+ bs->rx_len -= count;
+
+ do {
+ val = bcm2835_rd(bs, BCM2835_SPI_FIFO);
+
+ if (bs->rx_buf)
+ {
+ *bs->rx_buf++ = val;
+ }
+ } while (--count);
+}
+
+rt_inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count)
+{
+ rt_uint8_t val;
+
+ count = rt_min(count, bs->tx_len);
+ bs->tx_len -= count;
+
+ do {
+ val = bs->tx_buf ? *bs->tx_buf++ : 0;
+ bcm2835_wr(bs, BCM2835_SPI_FIFO, val);
+ } while (--count);
+}
+
+static void bcm2835_spi_reset_hw(struct bcm2835_spi *bs)
+{
+ rt_uint32_t cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+ /* Disable SPI interrupts and transfer */
+ cs &= ~(BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_DMAEN | BCM2835_SPI_CS_TA);
+
+ /*
+ * Transmission sometimes breaks unless the DONE bit is written at the
+ * end of every transfer. The spec says it's a RO bit. Either the
+ * spec is wrong and the bit is actually of type RW1C, or it's a
+ * hardware erratum.
+ */
+ cs |= BCM2835_SPI_CS_DONE;
+ /* Reset RX/TX FIFOS */
+ cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX;
+
+ /* Reset the SPI_HW */
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+ /* Reset the DLEN */
+ bcm2835_wr(bs, BCM2835_SPI_DLEN, 0);
+}
+
+static void bcm2835_spi_transfer_one_irq(struct bcm2835_spi *bs,
+ rt_uint32_t cs, rt_bool_t fifo_empty)
+{
+ /*
+ * Enable HW block, but with interrupts still disabled.
+ * Otherwise the empty TX FIFO would immediately trigger an interrupt.
+ */
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
+
+ /* Fill TX FIFO as much as possible */
+ if (fifo_empty)
+ {
+ bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE);
+ }
+ bcm2835_wr_fifo(bs);
+
+ /* Enable interrupts */
+ cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA;
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+}
+
+static rt_err_t bcm2835_spi_configure(struct rt_spi_device *device,
+ struct rt_spi_configuration *conf)
+{
+ rt_uint32_t prepare_cs;
+ struct bcm2835_spi *bs = raw_to_bcm2835_spi(device->bus);
+
+ prepare_cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01;
+
+ if (conf->mode & RT_SPI_CPOL)
+ {
+ prepare_cs |= BCM2835_SPI_CS_CPOL;
+ }
+ if (conf->mode & RT_SPI_CPHA)
+ {
+ prepare_cs |= BCM2835_SPI_CS_CPHA;
+ }
+ device->user_data = (void *)(rt_ubase_t)prepare_cs;
+
+ if (conf->mode & RT_SPI_NO_CS)
+ {
+ return RT_EOK;
+ }
+
+ bcm2835_wr(bs, BCM2835_SPI_CS, prepare_cs);
+
+ return RT_EOK;
+}
+
+static rt_ssize_t bcm2835_spi_xfer(struct rt_spi_device *device,
+ struct rt_spi_message *msg)
+{
+ rt_bool_t fifo_empty = RT_TRUE;
+ rt_ubase_t spi_hz, cdiv, hz_per_byte, byte_limit, effective_speed_hz;
+ rt_uint32_t cs = (rt_ubase_t)device->user_data;
+ struct bcm2835_spi *bs = raw_to_bcm2835_spi(device->bus);
+
+ spi_hz = device->config.max_hz;
+
+ if (spi_hz >= bs->clk_hz / 2)
+ {
+ cdiv = 2;
+ }
+ else if (spi_hz)
+ {
+ cdiv = RT_DIV_ROUND_UP(bs->clk_hz, spi_hz);
+ cdiv += (cdiv % 2);
+
+ if (cdiv >= 65536)
+ {
+ cdiv = 0;
+ }
+ }
+ else
+ {
+ cdiv = 0;
+ }
+ effective_speed_hz = cdiv ? (bs->clk_hz / cdiv) : (bs->clk_hz / 65536);
+ bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
+
+ /* Handle all the 3-wire mode */
+ if (device->config.mode & RT_SPI_3WIRE && msg->recv_buf)
+ {
+ cs |= BCM2835_SPI_CS_REN;
+ }
+
+ /* Set transmit buffers and length */
+ bs->tx_buf = msg->send_buf;
+ bs->rx_buf = msg->recv_buf;
+ bs->tx_len = msg->length;
+ bs->rx_len = msg->length;
+
+ /*
+ * Calculate the estimated time in us the transfer runs. Note that
+ * there is 1 idle clocks cycles after each byte getting transferred
+ * so we have 9 cycles/byte. This is used to find the number of Hz
+ * per byte per polling limit. E.g., we can transfer 1 byte in 30 us
+ * per 300,000 Hz of bus clock.
+ */
+ hz_per_byte = BCM2835_SPI_POLLING_LIMIT_US ? (9 * 1000000) / BCM2835_SPI_POLLING_LIMIT_US : 0;
+ byte_limit = hz_per_byte ? effective_speed_hz / hz_per_byte : 1;
+
+ /* Run in polling mode for short transfers */
+ if (msg->length < byte_limit)
+ {
+ rt_tick_t timeout;
+
+ /* Enable HW block without interrupts */
+ bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
+
+ /*
+ * Fill in the fifo before timeout calculations
+ * if we are interrupted here, then the data is
+ * getting transferred by the HW while we are interrupted
+ */
+ bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE);
+
+ /* Set the timeout to at least 2 jiffies */
+ timeout = 2 + RT_TICK_PER_SECOND * BCM2835_SPI_POLLING_LIMIT_US / 1000000;
+ timeout += rt_tick_get();
+
+ while (bs->rx_len)
+ {
+ /* Fill in tx fifo with remaining data */
+ bcm2835_wr_fifo(bs);
+
+ /* Read from fifo as much as possible */
+ bcm2835_rd_fifo(bs);
+
+ if (bs->rx_len && rt_tick_get() > timeout)
+ {
+ LOG_E("%s: Timeout for poll mode", rt_dm_dev_get_name(&bs->parent.parent));
+
+ fifo_empty = RT_FALSE;
+ goto _irq_mode;
+ }
+ }
+
+ /* Transfer complete - reset SPI HW */
+ bcm2835_spi_reset_hw(bs);
+ goto _end;
+ }
+
+_irq_mode:
+ bcm2835_spi_transfer_one_irq(bs, cs, fifo_empty);
+
+ rt_completion_wait(&bs->done, RT_WAITING_FOREVER);
+
+_end:
+ return msg->length;
+}
+
+static struct rt_spi_ops bcm2835_spi_ops =
+{
+ .configure = bcm2835_spi_configure,
+ .xfer = bcm2835_spi_xfer,
+};
+
+static void bcm2835_spi_isr(int irq, void *param)
+{
+ rt_uint32_t cs;
+ struct bcm2835_spi *bs = param;
+
+ cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+ /* Bail out early if interrupts are not enabled */
+ if (!(cs & BCM2835_SPI_CS_INTR))
+ {
+ return;
+ }
+
+ /*
+ * An interrupt is signaled either if DONE is set (TX FIFO empty)
+ * or if RXR is set (RX FIFO >= 3/4 full).
+ */
+ if (cs & BCM2835_SPI_CS_RXF)
+ {
+ bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE);
+ }
+ else if (cs & BCM2835_SPI_CS_RXR)
+ {
+ bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE_3_4);
+ }
+
+ if (bs->tx_len && cs & BCM2835_SPI_CS_DONE)
+ {
+ bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE);
+ }
+
+ /* Read as many bytes as possible from FIFO */
+ bcm2835_rd_fifo(bs);
+ /* Write as many bytes as possible to FIFO */
+ bcm2835_wr_fifo(bs);
+
+ if (!bs->rx_len)
+ {
+ /* Transfer complete - reset SPI HW */
+ bcm2835_spi_reset_hw(bs);
+ rt_completion_done(&bs->done);
+ }
+}
+
+static void bcm2835_spi_free(struct bcm2835_spi *bs)
+{
+ if (!rt_is_err_or_null(bs->clk))
+ {
+ rt_clk_disable_unprepare(bs->clk);
+ }
+}
+
+static rt_err_t bcm2835_spi_probe(struct rt_platform_device *pdev)
+{
+ int id;
+ rt_err_t err;
+ const char *bus_name;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_spi *bs = rt_calloc(1, sizeof(*bs));
+
+ if (!bs)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bs->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!bs->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ bs->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (bs->irq < 0)
+ {
+ err = bs->irq;
+ goto _fail;
+ }
+
+ bs->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(bs->clk))
+ {
+ err = rt_ptr_err(bs->clk);
+ goto _fail;
+ }
+
+ rt_clk_prepare_enable(bs->clk);
+ bs->max_speed_hz = rt_clk_get_rate(bs->clk);
+
+ bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
+ bs->mode = RT_SPI_CPOL | RT_SPI_CPHA | RT_SPI_CS_HIGH | RT_SPI_NO_CS | RT_SPI_3WIRE;
+ bs->parent.num_chipselect = 3;
+ rt_completion_init(&bs->done);
+
+ dev->user_data = bs;
+
+ bs->parent.parent.ofw_node = dev->ofw_node;
+
+ if ((id = pdev->dev_id) >= 0)
+ {
+ rt_dm_dev_set_name(&bs->parent.parent, "spi%u", id);
+ }
+ else
+ {
+ rt_dm_dev_set_name_auto(&bs->parent.parent, "spi");
+ }
+ bus_name = rt_dm_dev_get_name(&bs->parent.parent);
+
+ rt_hw_interrupt_install(bs->irq, bcm2835_spi_isr, bs, bus_name);
+ rt_hw_interrupt_umask(bs->irq);
+
+ if ((err = rt_spi_bus_register(&bs->parent, bus_name, &bcm2835_spi_ops)))
+ {
+ goto _free_irq;
+ }
+
+ return RT_EOK;
+
+_free_irq:
+ rt_hw_interrupt_mask(bs->irq);
+ rt_pic_detach_irq(bs->irq, bs);
+
+_fail:
+ bcm2835_spi_free(bs);
+
+ return err;
+}
+
+static rt_err_t bcm2835_spi_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_spi *bs = pdev->parent.user_data;
+
+ rt_hw_interrupt_mask(bs->irq);
+ rt_pic_detach_irq(bs->irq, bs);
+
+ rt_device_unregister(&bs->parent.parent);
+
+ /* Clear FIFOs, and disable the HW block */
+ bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
+ bcm2835_spi_free(bs);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_spi_shutdown(struct rt_platform_device *pdev)
+{
+ return bcm2835_spi_remove(pdev);
+}
+
+static const struct rt_ofw_node_id bcm2835_spi_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-spi", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_spi_driver =
+{
+ .name = "bcm2835-spi",
+ .ids = bcm2835_spi_ofw_ids,
+
+ .probe = bcm2835_spi_probe,
+ .remove = bcm2835_spi_remove,
+ .shutdown = bcm2835_spi_shutdown,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_spi_driver);
diff --git a/bsp/raspberry-pi/dm/spi/spi-bcm2835aux.c b/bsp/raspberry-pi/dm/spi/spi-bcm2835aux.c
new file mode 100755
index 0000000000..5f1d8de87c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/spi/spi-bcm2835aux.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "spi.bcm2835.aux"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+/* SPI register offsets */
+#define BCM2835_AUX_SPI_CNTL0 0x00
+#define BCM2835_AUX_SPI_CNTL1 0x04
+#define BCM2835_AUX_SPI_STAT 0x08
+#define BCM2835_AUX_SPI_PEEK 0x0c
+#define BCM2835_AUX_SPI_IO 0x20
+#define BCM2835_AUX_SPI_TXHOLD 0x30
+
+/* Bitfields in CNTL0 */
+#define BCM2835_AUX_SPI_CNTL0_SPEED 0xfff00000
+#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX 0xfff
+#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT 20
+#define BCM2835_AUX_SPI_CNTL0_CS 0x000e0000
+#define BCM2835_AUX_SPI_CNTL0_POSTINPUT 0x00010000
+#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000
+#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
+#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
+#define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400
+#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
+#define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100
+#define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080
+#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
+#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003f
+
+/* Bitfields in CNTL1 */
+#define BCM2835_AUX_SPI_CNTL1_CSHIGH 0x00000700
+#define BCM2835_AUX_SPI_CNTL1_TXEMPTY 0x00000080
+#define BCM2835_AUX_SPI_CNTL1_IDLE 0x00000040
+#define BCM2835_AUX_SPI_CNTL1_MSBF_IN 0x00000002
+#define BCM2835_AUX_SPI_CNTL1_KEEP_IN 0x00000001
+
+/* Bitfields in STAT */
+#define BCM2835_AUX_SPI_STAT_TX_LVL 0xff000000
+#define BCM2835_AUX_SPI_STAT_RX_LVL 0x00ff0000
+#define BCM2835_AUX_SPI_STAT_TX_FULL 0x00000400
+#define BCM2835_AUX_SPI_STAT_TX_EMPTY 0x00000200
+#define BCM2835_AUX_SPI_STAT_RX_FULL 0x00000100
+#define BCM2835_AUX_SPI_STAT_RX_EMPTY 0x00000080
+#define BCM2835_AUX_SPI_STAT_BUSY 0x00000040
+#define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003f
+
+#define POLLING_LIMIT_US 30
+
+struct bcm2835aux_spi
+{
+ struct rt_spi_bus parent;
+
+ void *regs;
+ int irq;
+ struct rt_clk *clk;
+
+ rt_uint8_t mode;
+
+ rt_uint32_t cntl[2];
+ rt_uint8_t *rx_buf;
+ const rt_uint8_t *tx_buf;
+ int tx_len;
+ int rx_len;
+ int pending;
+
+ struct rt_completion done;
+};
+
+#define raw_to_bcm2835aux_spi(raw) rt_container_of(raw, struct bcm2835aux_spi, parent)
+
+rt_inline rt_uint32_t bcm2835aux_rd(struct bcm2835aux_spi *bs, int reg)
+{
+ return HWREG32(bs->regs + reg);
+}
+
+rt_inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, int reg, rt_uint32_t val)
+{
+ HWREG32(bs->regs + reg) = val;
+}
+
+rt_inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
+{
+ rt_uint32_t data;
+ int count = rt_min(bs->rx_len, 3);
+
+ data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
+
+ if (bs->rx_buf)
+ {
+ switch (count)
+ {
+ case 3:
+ *bs->rx_buf++ = (data >> 16) & 0xff;
+ /* fallthrough */;
+ case 2:
+ *bs->rx_buf++ = (data >> 8) & 0xff;
+ /* fallthrough */;
+ case 1:
+ *bs->rx_buf++ = (data >> 0) & 0xff;
+ /* fallthrough - no default */
+ }
+ }
+
+ bs->rx_len -= count;
+ bs->pending -= count;
+}
+
+rt_inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
+{
+ int count;
+ rt_uint8_t byte;
+ rt_uint32_t data = 0;
+
+ /* Gather up to 3 bytes to write to the FIFO */
+ count = rt_min(bs->tx_len, 3);
+ for (int i = 0; i < count; ++i)
+ {
+ byte = bs->tx_buf ? *bs->tx_buf++ : 0;
+ data |= byte << (8 * (2 - i));
+ }
+
+ /* and set the variable bit-length */
+ data |= (count * 8) << 24;
+
+ /* and decrement length */
+ bs->tx_len -= count;
+ bs->pending += count;
+
+ /* write to the correct TX-register */
+ if (bs->tx_len)
+ {
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data);
+ }
+ else
+ {
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data);
+ }
+}
+
+static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
+{
+ /* disable spi clearing fifo and interrupts */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
+}
+
+static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
+{
+ rt_uint32_t stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
+
+ /* Check if we have data to read */
+ for (; bs->rx_len && (stat & BCM2835_AUX_SPI_STAT_RX_LVL);
+ stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT))
+ {
+ bcm2835aux_rd_fifo(bs);
+ }
+
+ /* Check if we have data to write */
+ while (bs->tx_len && bs->pending < 12 &&
+ !(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & BCM2835_AUX_SPI_STAT_TX_FULL))
+ {
+ bcm2835aux_wr_fifo(bs);
+ }
+}
+
+rt_inline void bcm2835aux_spi_enable_irq(struct bcm2835aux_spi *bs)
+{
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
+ BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE);
+}
+
+static rt_err_t bcm2835aux_spi_configure(struct rt_spi_device *device,
+ struct rt_spi_configuration *conf)
+{
+ struct bcm2835aux_spi *bs = raw_to_bcm2835aux_spi(device->bus);
+
+ if (!(conf->mode & RT_SPI_NO_CS))
+ {
+ return -RT_EINVAL;
+ }
+
+ /* Prepare message */
+ bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
+ BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
+ BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
+ bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
+
+ /* Handle all the modes */
+ if (conf->mode & RT_SPI_CPOL)
+ {
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
+ }
+ else
+ {
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
+ }
+
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+ return RT_EOK;
+}
+
+static rt_ssize_t bcm2835aux_spi_xfer(struct rt_spi_device *device,
+ struct rt_spi_message *msg)
+{
+ rt_ubase_t effective_speed_hz, spi_hz, clk_hz, speed, hz_per_byte, byte_limit;
+ struct bcm2835aux_spi *bs = raw_to_bcm2835aux_spi(device->bus);
+
+ spi_hz = device->config.max_hz;
+ clk_hz = rt_clk_get_rate(bs->clk);
+
+ if (spi_hz >= clk_hz / 2)
+ {
+ speed = 0;
+ }
+ else if (spi_hz)
+ {
+ speed = RT_DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
+
+ if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
+ {
+ speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+ }
+ }
+ else
+ {
+ speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+ }
+ /* Mask out old speed from previous spi_transfer */
+ bs->cntl[0] &= ~BCM2835_AUX_SPI_CNTL0_SPEED;
+ /* set the new speed */
+ bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
+
+ effective_speed_hz = clk_hz / (2 * (speed + 1));
+
+ /* set transmit buffers and length */
+ bs->tx_buf = msg->send_buf;
+ bs->rx_buf = msg->recv_buf;
+ bs->tx_len = msg->length;
+ bs->rx_len = msg->length;
+ bs->pending = 0;
+
+ /*
+ * Calculate the estimated time in us the transfer runs.
+ * Note that there are 2 idle clocks cycles after each chunk getting
+ * transferred - in our case the chunk size is 3 bytes, so we
+ * approximate this by 9 cycles/byte.
+ * This is used to find the number of Hz per byte per polling limit.
+ * E.g., we can transfer 1 byte in 30 us per 300,000 Hz of bus clock.
+ */
+ hz_per_byte = POLLING_LIMIT_US ? (9 * 1000000) / POLLING_LIMIT_US : 0;
+ byte_limit = hz_per_byte ? effective_speed_hz / hz_per_byte : 1;
+
+ /* Polling mode for short transfers */
+ if (msg->length < byte_limit)
+ {
+ rt_tick_t timeout;
+
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+ timeout = 2 + RT_TICK_PER_SECOND * POLLING_LIMIT_US / 1000000;
+ timeout += rt_tick_get();
+
+ while (bs->rx_len)
+ {
+ bcm2835aux_spi_transfer_helper(bs);
+
+ if (bs->rx_len && rt_tick_get() > timeout)
+ {
+ LOG_E("%s: Timeout for poll mode", rt_dm_dev_get_name(&bs->parent.parent));
+ goto _enable_irq;
+ }
+ }
+
+ goto _out_unprepare;
+ }
+
+ /* IRQ mode */
+
+ /* Fill in registers and fifos before enabling interrupts */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+ /* Fill in tx fifo with data before enabling interrupts */
+ while (bs->tx_len && bs->pending < 12 &&
+ !(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) & BCM2835_AUX_SPI_STAT_TX_FULL))
+ {
+ bcm2835aux_wr_fifo(bs);
+ }
+
+_enable_irq:
+ bcm2835aux_spi_enable_irq(bs);
+
+ rt_completion_wait(&bs->done, RT_WAITING_FOREVER);
+
+_out_unprepare:
+ /* Unprepare message */
+ bcm2835aux_spi_reset_hw(bs);
+
+ return msg->length;
+}
+
+static struct rt_spi_ops bcm2835aux_spi_ops =
+{
+ .configure = bcm2835aux_spi_configure,
+ .xfer = bcm2835aux_spi_xfer,
+};
+
+static void bcm2835aux_spi_isr(int irq, void *param)
+{
+ struct bcm2835aux_spi *bs = param;
+
+ if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+ (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+ {
+ return;
+ }
+
+ bcm2835aux_spi_transfer_helper(bs);
+
+ if (!bs->tx_len)
+ {
+ /* Disable tx fifo empty interrupt */
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | BCM2835_AUX_SPI_CNTL1_IDLE);
+ }
+
+ if (!bs->rx_len)
+ {
+ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+ rt_completion_done(&bs->done);
+
+ /* Unprepare message */
+ bcm2835aux_spi_reset_hw(bs);
+ }
+}
+
+static void bcm2835aux_spi_free(struct bcm2835aux_spi *bs)
+{
+ if (bs->regs)
+ {
+ rt_iounmap(bs->regs);
+ }
+
+ if (!rt_is_err_or_null(bs->clk))
+ {
+ rt_clk_disable_unprepare(bs->clk);
+ }
+
+ rt_free(bs);
+}
+
+static rt_err_t bcm2835aux_spi_probe(struct rt_platform_device *pdev)
+{
+ int id;
+ rt_err_t err;
+ rt_ubase_t clk_hz;
+ const char *bus_name;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835aux_spi *bs = rt_calloc(1, sizeof(*bs));
+
+ if (!bs)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bs->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!bs->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ bs->irq = rt_dm_dev_get_irq(dev, 0);
+
+ if (bs->irq < 0)
+ {
+ err = bs->irq;
+ goto _fail;
+ }
+
+ bs->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(bs->clk))
+ {
+ err = rt_ptr_err(bs->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(bs->clk)))
+ {
+ goto _fail;
+ }
+
+ if (!(clk_hz = rt_clk_get_rate(bs->clk)))
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ /* Reset SPI-HW block */
+ bcm2835aux_spi_reset_hw(bs);
+
+ bs->mode = RT_SPI_CPOL | RT_SPI_CS_HIGH | RT_SPI_NO_CS;
+ bs->parent.num_chipselect = 1;
+ rt_completion_init(&bs->done);
+
+ dev->user_data = bs;
+
+ bs->parent.parent.ofw_node = dev->ofw_node;
+
+ if ((id = pdev->dev_id) >= 0)
+ {
+ rt_dm_dev_set_name(&bs->parent.parent, "spi%u", id);
+ }
+ else
+ {
+ rt_dm_dev_set_name_auto(&bs->parent.parent, "spi");
+ }
+ bus_name = rt_dm_dev_get_name(&bs->parent.parent);
+
+ rt_hw_interrupt_install(bs->irq, bcm2835aux_spi_isr, bs, bus_name);
+ rt_hw_interrupt_umask(bs->irq);
+
+ if ((err = rt_spi_bus_register(&bs->parent, bus_name, &bcm2835aux_spi_ops)))
+ {
+ goto _free_irq;
+ }
+
+ return RT_EOK;
+
+_free_irq:
+ rt_hw_interrupt_mask(bs->irq);
+ rt_pic_detach_irq(bs->irq, bs);
+
+_fail:
+ bcm2835aux_spi_free(bs);
+
+ return err;
+}
+
+static rt_err_t bcm2835aux_spi_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835aux_spi *bs = pdev->parent.user_data;
+
+ rt_hw_interrupt_mask(bs->irq);
+ rt_pic_detach_irq(bs->irq, bs);
+
+ rt_device_unregister(&bs->parent.parent);
+
+ bcm2835aux_spi_reset_hw(bs);
+
+ bcm2835aux_spi_free(bs);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835aux_spi_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-aux-spi", },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835aux_spi_driver =
+{
+ .name = "bcm2835-aux-spi",
+ .ids = bcm2835aux_spi_ofw_ids,
+
+ .probe = bcm2835aux_spi_probe,
+ .remove = bcm2835aux_spi_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835aux_spi_driver);
diff --git a/bsp/raspberry-pi/dm/thermal/Kconfig b/bsp/raspberry-pi/dm/thermal/Kconfig
new file mode 100755
index 0000000000..081d92f606
--- /dev/null
+++ b/bsp/raspberry-pi/dm/thermal/Kconfig
@@ -0,0 +1,9 @@
+config RT_THERMAL_BCM2835
+ bool "BCM2835"
+ default n
+
+config RT_THERMAL_BCM2711
+ bool "BCM2711"
+ depends on RT_MFD_SYSCON
+ depends on RT_USING_RESET
+ default n
diff --git a/bsp/raspberry-pi/dm/thermal/SConscript b/bsp/raspberry-pi/dm/thermal/SConscript
new file mode 100755
index 0000000000..ea923cb3cd
--- /dev/null
+++ b/bsp/raspberry-pi/dm/thermal/SConscript
@@ -0,0 +1,16 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_THERMAL_BCM2711']):
+ src += ['thermal-bcm2711.c']
+
+if GetDepend(['RT_THERMAL_BCM2835']):
+ src += ['thermal-bcm2835.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/thermal/thermal-bcm2711.c b/bsp/raspberry-pi/dm/thermal/thermal-bcm2711.c
new file mode 100755
index 0000000000..009ddaeb4c
--- /dev/null
+++ b/bsp/raspberry-pi/dm/thermal/thermal-bcm2711.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "thermal.bcm2711"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define AVS_RO_TEMP_STATUS 0x200
+#define AVS_RO_TEMP_STATUS_VALID_MSK (RT_BIT(16) | RT_BIT(10))
+#define AVS_RO_TEMP_STATUS_DATA_MSK RT_GENMASK(9, 0)
+
+struct bcm2711_thermal
+{
+ struct rt_thermal_zone_device parent;
+
+ struct rt_syscon *regmap;
+};
+
+#define raw_to_bcm2711_thermal(raw) rt_container_of(raw, struct bcm2711_thermal, parent)
+
+static rt_err_t bcm2711_thermal_zone_get_temp(struct rt_thermal_zone_device *zdev,
+ int *out_temp)
+{
+ rt_err_t err;
+ rt_uint32_t val;
+ struct rt_thermal_zone_params *tz_params;
+ struct bcm2711_thermal *btz = raw_to_bcm2711_thermal(zdev);
+
+ if ((err = rt_syscon_read(btz->regmap, AVS_RO_TEMP_STATUS, &val)))
+ {
+ return err;
+ }
+
+ if (!(val & AVS_RO_TEMP_STATUS_VALID_MSK))
+ {
+ return -RT_EIO;
+ }
+
+ val &= AVS_RO_TEMP_STATUS_DATA_MSK;
+ tz_params = &btz->parent.params;
+
+ /* Convert a HW code to a temperature reading (millidegree celsius) */
+ *out_temp = tz_params->slope * val + tz_params->offset;
+
+ return RT_EOK;
+}
+
+const static struct rt_thermal_zone_ops bcm2711_thermal_zone_ops =
+{
+ .get_temp = bcm2711_thermal_zone_get_temp,
+};
+
+static rt_err_t bcm2711_thermal_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ struct rt_ofw_node *pnp;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2711_thermal *btz = rt_calloc(1, sizeof(*btz));
+
+ if (!btz)
+ {
+ return -RT_ENOMEM;
+ }
+
+ pnp = rt_ofw_get_parent(dev->ofw_node);
+
+ if (!pnp)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ btz->regmap = rt_syscon_find_by_ofw_node(pnp);
+ rt_ofw_node_put(pnp);
+
+ if (!btz->regmap)
+ {
+ err = -RT_EINVAL;
+ goto _fail;
+ }
+
+ btz->parent.parent.ofw_node = dev->ofw_node;
+ btz->parent.ops = &bcm2711_thermal_zone_ops;
+
+ rt_dm_dev_set_name(&btz->parent.parent, "bcm2711");
+
+ if ((err = rt_thermal_zone_device_register(&btz->parent)))
+ {
+ goto _fail;
+ }
+
+ dev->user_data = btz;
+
+ return RT_EOK;
+
+_fail:
+ rt_free(btz);
+
+ return err;
+}
+
+static rt_err_t bcm2711_thermal_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2711_thermal *btz = pdev->parent.user_data;
+
+ rt_thermal_zone_device_unregister(&btz->parent);
+
+ rt_free(btz);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2711_thermal_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2711-thermal" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2711_thermal_driver =
+{
+ .name = "bcm2711-thermal",
+ .ids = bcm2711_thermal_ofw_ids,
+
+ .probe = bcm2711_thermal_probe,
+ .remove = bcm2711_thermal_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2711_thermal_driver);
diff --git a/bsp/raspberry-pi/dm/thermal/thermal-bcm2835.c b/bsp/raspberry-pi/dm/thermal/thermal-bcm2835.c
new file mode 100755
index 0000000000..3c4d7e8a24
--- /dev/null
+++ b/bsp/raspberry-pi/dm/thermal/thermal-bcm2835.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+/*
+ * Note: as per Raspberry Foundation FAQ
+ * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
+ * the recommended temperature range for the SoC -40C to +85C
+ * so the trip limit is set to 80C.
+ * this applies to all the BCM283X SoC
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_TAG "thermal.bcm2835"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#define BCM2835_TS_TSENSCTL 0x00
+#define BCM2835_TS_TSENSSTAT 0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW RT_BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB RT_BIT(1)
+
+/*
+ * bandgap reference voltage in 6 mV increments
+ * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
+ */
+#define BCM2835_TS_TSENSCTL_CTRL_BITS 3
+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
+#define BCM2835_TS_TSENSCTL_CTRL_MASK \
+ RT_GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
+ BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
+ BCM2835_TS_TSENSCTL_CTRL_SHIFT)
+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
+#define BCM2835_TS_TSENSCTL_EN_INT RT_BIT(5)
+#define BCM2835_TS_TSENSCTL_DIRECT RT_BIT(6)
+#define BCM2835_TS_TSENSCTL_CLR_INT RT_BIT(7)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS 10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK \
+ RT_GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
+ BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+ BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+/*
+ * time how long the block to be asserted in reset
+ * which based on a clock counter (TSENS clock assumed)
+ */
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
+#define BCM2835_TS_TSENSCTL_REGULEN RT_BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS 10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK \
+ RT_GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
+ BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+ BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID RT_BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT RT_BIT(11)
+
+struct bcm2835_thermal
+{
+ struct rt_thermal_zone_device parent;
+
+ void *regs;
+ struct rt_clk *clk;
+};
+
+#define raw_to_bcm2835_thermal(raw) rt_container_of(raw, struct bcm2835_thermal, parent)
+
+static int bcm2835_thermal_adc2temp(rt_uint32_t adc, int offset, int slope)
+{
+ return offset + slope * adc;
+}
+
+static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
+{
+ temp -= offset;
+ temp /= slope;
+
+ if (temp < 0)
+ {
+ temp = 0;
+ }
+
+ if (temp >= RT_BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
+ {
+ temp = RT_BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
+ }
+
+ return temp;
+}
+
+static rt_err_t bcm2835_thermal_zone_get_temp(struct rt_thermal_zone_device *zdev,
+ int *out_temp)
+{
+ rt_uint32_t val;
+ struct rt_thermal_zone_params *tz_params;
+ struct bcm2835_thermal *btz = raw_to_bcm2835_thermal(zdev);
+
+ val = HWREG32(btz->regs + BCM2835_TS_TSENSSTAT);
+
+ if (!(val & BCM2835_TS_TSENSSTAT_VALID))
+ {
+ return -RT_EIO;
+ }
+
+ val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+ tz_params = &btz->parent.params;
+
+ *out_temp = bcm2835_thermal_adc2temp(val, tz_params->offset, tz_params->slope);
+
+ return RT_EOK;
+}
+
+const static struct rt_thermal_zone_ops bcm2835_thermal_zone_ops =
+{
+ .get_temp = bcm2835_thermal_zone_get_temp,
+};
+
+static rt_err_t bcm2835_thermal_probe(struct rt_platform_device *pdev)
+{
+ rt_err_t err;
+ rt_uint32_t val;
+ rt_ubase_t rate;
+ struct rt_device *dev = &pdev->parent;
+ struct bcm2835_thermal *btz = rt_calloc(1, sizeof(*btz));
+
+ if (!btz)
+ {
+ return -RT_ENOMEM;
+ }
+
+ btz->regs = rt_dm_dev_iomap(dev, 0);
+
+ if (!btz->regs)
+ {
+ err = -RT_EIO;
+ goto _fail;
+ }
+
+ btz->clk = rt_clk_get_by_index(dev, 0);
+
+ if (rt_is_err(btz->clk))
+ {
+ err = rt_ptr_err(btz->clk);
+ goto _fail;
+ }
+
+ if ((err = rt_clk_prepare_enable(btz->clk)))
+ {
+ goto _fail;
+ }
+
+ rate = rt_clk_get_rate(btz->clk);
+
+ if (rate < 1920000 || rate > 5000000)
+ {
+ LOG_W("Clock running at %u Hz is outside of the recommended range: 1.92 to 5MHz", rate);
+ }
+
+ btz->parent.parent.ofw_node = dev->ofw_node;
+ btz->parent.ops = &bcm2835_thermal_zone_ops;
+
+ rt_dm_dev_set_name(&btz->parent.parent, "bcm2835");
+
+ if ((err = rt_thermal_zone_device_register(&btz->parent)))
+ {
+ goto _fail;
+ }
+
+ /*
+ * right now the FW does set up the HW-block, so we are not
+ * touching the configuration registers.
+ * But if the HW is not enabled, then set it up
+ * using "sane" values used by the firmware right now.
+ */
+ val = HWREG32(btz->regs + BCM2835_TS_TSENSCTL);
+
+ if (!(val & BCM2835_TS_TSENSCTL_RSTB))
+ {
+ int offset, slope;
+ struct rt_thermal_trip trip;
+ struct rt_thermal_zone_device *tz = &btz->parent;
+ struct rt_thermal_zone_params *tz_params = &tz->params;
+
+ slope = tz_params->slope;
+ offset = tz_params->offset;
+
+ if ((err = rt_thermal_zone_get_trip(tz, 0, &trip)))
+ {
+ rt_thermal_zone_device_unregister(tz);
+
+ LOG_E("Read trip error = %s", rt_strerror(err));
+ goto _fail;
+ }
+
+ /* set bandgap reference voltage and enable voltage regulator */
+ val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
+ BCM2835_TS_TSENSCTL_CTRL_SHIFT) | BCM2835_TS_TSENSCTL_REGULEN;
+
+ /* use the recommended reset duration */
+ val |= 0xfe << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT;
+
+ /* trip_adc value from info */
+ val |= bcm2835_thermal_temp2adc(trip.temperature, offset, slope)
+ << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+ /* write the value back to the register as 2 steps */
+ HWREG32(btz->regs + BCM2835_TS_TSENSCTL) = val;
+ val |= BCM2835_TS_TSENSCTL_RSTB;
+ HWREG32(btz->regs + BCM2835_TS_TSENSCTL) = val;
+ }
+
+ dev->user_data = btz;
+
+ return RT_EOK;
+
+_fail:
+ if (!rt_is_err_or_null(btz->clk))
+ {
+ rt_clk_disable_unprepare(btz->clk);
+ rt_clk_put(btz->clk);
+ }
+
+ rt_free(btz);
+
+ return err;
+}
+
+static rt_err_t bcm2835_thermal_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_thermal *btz = pdev->parent.user_data;
+
+ rt_thermal_zone_device_unregister(&btz->parent);
+
+ rt_clk_disable_unprepare(btz->clk);
+ rt_clk_put(btz->clk);
+
+ rt_free(btz);
+
+ return RT_EOK;
+}
+
+static const struct rt_ofw_node_id bcm2835_thermal_ofw_ids[] =
+{
+ { .compatible = "brcm,bcm2835-thermal" },
+ { .compatible = "brcm,bcm2836-thermal" },
+ { .compatible = "brcm,bcm2837-thermal" },
+ { /* sentinel */ }
+};
+
+static struct rt_platform_driver bcm2835_thermal_driver =
+{
+ .name = "bcm2835-thermal",
+ .ids = bcm2835_thermal_ofw_ids,
+
+ .probe = bcm2835_thermal_probe,
+ .remove = bcm2835_thermal_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_thermal_driver);
diff --git a/bsp/raspberry-pi/dm/watchdog/Kconfig b/bsp/raspberry-pi/dm/watchdog/Kconfig
new file mode 100755
index 0000000000..cca2dd892a
--- /dev/null
+++ b/bsp/raspberry-pi/dm/watchdog/Kconfig
@@ -0,0 +1,5 @@
+config RT_WDT_BCM2835
+ bool "Broadcom BCM2835 hardware watchdog"
+ depends on RT_USING_DM
+ depends on RT_USING_WDT
+ default n
diff --git a/bsp/raspberry-pi/dm/watchdog/SConscript b/bsp/raspberry-pi/dm/watchdog/SConscript
new file mode 100755
index 0000000000..a17da19515
--- /dev/null
+++ b/bsp/raspberry-pi/dm/watchdog/SConscript
@@ -0,0 +1,13 @@
+from building import *
+
+group = []
+src = []
+cwd = GetCurrentDir()
+CPPPATH = [cwd + '/../include']
+
+if GetDepend(['RT_WDT_BCM2835']):
+ src += ['watchdog-bcm2835.c']
+
+group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/dm/watchdog/watchdog-bcm2835.c b/bsp/raspberry-pi/dm/watchdog/watchdog-bcm2835.c
new file mode 100755
index 0000000000..50ee2c7765
--- /dev/null
+++ b/bsp/raspberry-pi/dm/watchdog/watchdog-bcm2835.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-3-08 GuEe-GUI the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <bcm2835-pm.h>
+
+#define PM_RSTC 0x1c
+#define PM_RSTS 0x20
+#define PM_WDOG 0x24
+
+#define PM_PASSWORD 0x5a000000
+
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+/*
+ * The Raspberry Pi firmware uses the RSTS register to know which partition
+ * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10.
+ * Partition 63 is a special partition used by the firmware to indicate halt.
+ */
+#define PM_RSTS_RASPBERRYPI_HALT 0x555
+
+#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
+#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
+
+#define USEC_PER_SEC 1000000L
+
+struct bcm2835_wdt
+{
+ rt_watchdog_t parent;
+
+ void *base;
+ rt_uint32_t timeout;
+ struct rt_spinlock lock;
+};
+
+#define raw_to_bcm2835_wdt(raw) rt_container_of(raw, struct bcm2835_wdt, parent)
+
+static struct bcm2835_wdt *bcm2835_power_off_wdt;
+
+static void bcm2835_wdt_start(struct bcm2835_wdt *bcm2835_wdt)
+{
+ rt_uint32_t cur;
+ rt_ubase_t level = rt_spin_lock_irqsave(&bcm2835_wdt->lock);
+
+ HWREG32(bcm2835_wdt->base + PM_WDOG) = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm2835_wdt->timeout) & PM_WDOG_TIME_SET);
+ cur = HWREG32(bcm2835_wdt->base + PM_RSTC);
+ HWREG32(bcm2835_wdt->base + PM_RSTC) = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
+
+ rt_spin_unlock_irqrestore(&bcm2835_wdt->lock, level);
+}
+
+static void bcm2835_wdt_stop(struct bcm2835_wdt *bcm2835_wdt)
+{
+ HWREG32(bcm2835_wdt->base + PM_RSTC) = PM_PASSWORD | PM_RSTC_RESET;
+}
+
+static rt_uint32_t bcm2835_wdt_get_timeleft(struct bcm2835_wdt *bcm2835_wdt)
+{
+ rt_uint32_t value = HWREG32(bcm2835_wdt->base + PM_WDOG);
+
+ return WDOG_TICKS_TO_SECS(value & PM_WDOG_TIME_SET);
+}
+
+static void bcm2835_restart(struct bcm2835_wdt *bcm2835_wdt)
+{
+ rt_uint32_t val;
+
+ /* Use a timeout of 10 ticks (~150us) */
+ HWREG32(bcm2835_wdt->base + PM_WDOG) = 10 | PM_PASSWORD;
+ val = HWREG32(bcm2835_wdt->base + PM_RSTC);
+ val &= PM_RSTC_WRCFG_CLR;
+ val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
+ HWREG32(bcm2835_wdt->base + PM_RSTC) = val;
+
+ /* No sleeping, possibly atomic. */
+ rt_thread_mdelay(1);
+}
+
+static rt_err_t bcm2835_wdt_init(rt_watchdog_t *wdt)
+{
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_wdt_control(rt_watchdog_t *wdt, int cmd, void *args)
+{
+ rt_err_t status = RT_EOK;
+ struct bcm2835_wdt *bcm2835_wdt = raw_to_bcm2835_wdt(wdt);
+
+ switch (cmd)
+ {
+ case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
+ *(rt_uint32_t *)args = bcm2835_wdt->timeout / USEC_PER_SEC;
+ break;
+
+ case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
+ bcm2835_wdt->timeout = *(rt_uint32_t *)args * USEC_PER_SEC;
+ break;
+
+ case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
+ *(rt_uint32_t *)args = bcm2835_wdt_get_timeleft(bcm2835_wdt) / USEC_PER_SEC;
+ break;
+
+ case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+ bcm2835_wdt->timeout = 0;
+ break;
+
+ case RT_DEVICE_CTRL_WDT_START:
+ bcm2835_wdt_start(bcm2835_wdt);
+ break;
+
+ case RT_DEVICE_CTRL_WDT_STOP:
+ bcm2835_wdt_stop(bcm2835_wdt);
+ break;
+
+ default:
+ status = -RT_EINVAL;
+ }
+
+ return status;
+}
+
+static const struct rt_watchdog_ops bcm2835_wdt_ops =
+{
+ .init = bcm2835_wdt_init,
+ .control = bcm2835_wdt_control,
+};
+
+static void bcm2835_wdt_power_off(void)
+{
+ rt_uint32_t val;
+ struct bcm2835_wdt *bcm2835_wdt = bcm2835_power_off_wdt;
+
+ /*
+ * We set the watchdog hard reset bit here to distinguish this reset from
+ * the normal (full) reset. bootcode.bin will not reboot after a hard reset.
+ */
+ val = HWREG32(bcm2835_wdt->base + PM_RSTS);
+ val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT;
+ HWREG32(bcm2835_wdt->base + PM_RSTS) = val;
+
+ /* Continue with normal reset mechanism */
+ bcm2835_restart(bcm2835_wdt);
+}
+
+static void bcm2835_wdt_power_reboot(void)
+{
+ struct bcm2835_wdt *bcm2835_wdt = bcm2835_power_off_wdt;
+
+ /* Continue with normal reset mechanism */
+ bcm2835_restart(bcm2835_wdt);
+}
+
+static rt_err_t bcm2835_wdt_probe(struct rt_platform_device *pdev)
+{
+ const char *dev_name;
+ struct bcm2835_pm *pm = pdev->priv;
+ struct rt_ofw_node *np = pm->ofw_node;
+ struct bcm2835_wdt *bcm2835_wdt = rt_calloc(1, sizeof(*bcm2835_wdt));
+
+ if (!bcm2835_wdt)
+ {
+ return -RT_ENOMEM;
+ }
+
+ bcm2835_wdt->base = pm->base;
+ rt_spin_lock_init(&bcm2835_wdt->lock);
+
+ bcm2835_power_off_wdt = bcm2835_wdt;
+
+ if (rt_ofw_prop_read_bool(np, "system-power-controller"))
+ {
+ if (!rt_dm_machine_shutdown)
+ {
+ rt_dm_machine_shutdown = bcm2835_wdt_power_off;
+ }
+ }
+
+ if (!rt_dm_machine_reset)
+ {
+ rt_dm_machine_reset = bcm2835_wdt_power_reboot;
+ }
+
+ pdev->parent.user_data = bcm2835_wdt;
+
+ bcm2835_wdt->parent.ops = &bcm2835_wdt_ops;
+
+ rt_dm_dev_set_name_auto(&bcm2835_wdt->parent.parent, "wdt");
+ dev_name = rt_dm_dev_get_name(&bcm2835_wdt->parent.parent);
+ rt_hw_watchdog_register(&bcm2835_wdt->parent, dev_name, 0, bcm2835_wdt);
+
+ return RT_EOK;
+}
+
+static rt_err_t bcm2835_wdt_remove(struct rt_platform_device *pdev)
+{
+ struct bcm2835_wdt *bcm2835_wdt = pdev->parent.user_data;
+
+ bcm2835_wdt_stop(bcm2835_wdt);
+
+ rt_device_unregister(&bcm2835_wdt->parent.parent);
+
+ if (rt_dm_machine_shutdown == bcm2835_wdt_power_off)
+ {
+ rt_dm_machine_shutdown = RT_NULL;
+ }
+
+ if (rt_dm_machine_reset == bcm2835_wdt_power_reboot)
+ {
+ rt_dm_machine_reset = RT_NULL;
+ }
+
+ bcm2835_power_off_wdt = RT_NULL;
+
+ rt_free(bcm2835_wdt);
+
+ return RT_EOK;
+}
+
+static struct rt_platform_driver bcm2835_wdt_driver =
+{
+ .name = "bcm2835-wdt",
+ .probe = bcm2835_wdt_probe,
+ .remove = bcm2835_wdt_remove,
+};
+RT_PLATFORM_DRIVER_EXPORT(bcm2835_wdt_driver);
diff --git a/bsp/raspberry-pi/raspi-dm2.0/README.md b/bsp/raspberry-pi/raspi-dm2.0/README.md
deleted file mode 100644
index 9b16c4f3e8..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Raspberry PI 4-dm2.0BSP说明
-
-## 1. 简介
-
-树莓派4B的核心处理器为博通BCM2711(四核1.5GHz,Cortex A72架构,树莓派3是四核A53)。LPDDR4内存,由5V/3A USB-C供电或GPIO 5V。
-
-外设支持上,引入了双频Wi-Fi,蓝牙5.0,千兆网卡,MIPI CSI相机接口,两个USB口,40个扩展帧。
-
-这份RT-Thread BSP是针对 Raspberry Pi 4的一份移植,树莓派价格便宜, 使用者甚众,是研究和运行RT-Thread的可选平台之一。
-
-
-## 2. 编译说明
-
-推荐使用[env工具](https://www.rt-thread.org/download.html#download-rt-thread-env-tool),可以在console下进入到`bsp\raspberry-pi\raspi4-64`目录中,运行以下命令:
-
-```
-scons
-```
-
-来编译这个板级支持包。如果编译正确无误,会产生 `rtthread.elf`, `rtthread.bin` 文件。
-
-## 3. 支持情况
-
-| 驱动 | 支持情况 | 备注 |
-| ------ | ---- | :------: |
-| UART | 支持 | pl011驱动 |
-| GPIO | 尚未支持 | 等待dm2.0相关代码合入主线 |
-| SPI | 尚未支持 | 等待gpio合入主线 |
-| WATCHDOG | 尚未支持 | 等待gpio合入主线 |
-| HDMI | 尚未支持 | 等待gpio合入主线 |
-| SDIO | 支持 | 能够正常运行在qemu,但是qemu对于raspi目前只支持pio传输,后续需要硬件进行详细测试 |
-| ETH | 尚未支持 | 等待gpio合入主线 |
-
diff --git a/bsp/raspberry-pi/raspi-dm2.0/applications/SConscript b/bsp/raspberry-pi/raspi-dm2.0/applications/SConscript
deleted file mode 100644
index bda7b8b585..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/applications/SConscript
+++ /dev/null
@@ -1,14 +0,0 @@
-from building import *
-
-cwd = GetCurrentDir()
-src = Glob('*.c') + Glob('*.cpp')
-CPPPATH = [cwd, str(Dir('#'))]
-
-group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
-
-list = os.listdir(cwd)
-for item in list:
- if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
- group = group + SConscript(os.path.join(item, 'SConscript'))
-
-Return('group')
diff --git a/bsp/raspberry-pi/raspi-dm2.0/applications/main.c b/bsp/raspberry-pi/raspi-dm2.0/applications/main.c
deleted file mode 100644
index 882e458d93..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/applications/main.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <board.h>
-
-int main(int argc, char** argv)
-{
- rt_kprintf("Hi, this is RT-Thread!!\n");
- return 0;
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb b/bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb
deleted file mode 100644
index 759c21568f..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/bcm2711-rpi-4-b.dtb
+++ /dev/null
Binary files differ
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig b/bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig
deleted file mode 100644
index 34d491f587..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-menu "Hardware Drivers Config"
- config BSP_USING_PL011
- bool "Enable pl011 for uart"
- default n
-
- config BSP_USING_SDHCI
- bool "Enable sdhci driver"
- select RT_USING_SDHCI
- default y
- rsource sdhci/Kconfig
-endmenu
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript b/bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript
deleted file mode 100644
index 1a8ce83b72..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/SConscript
+++ /dev/null
@@ -1,25 +0,0 @@
-from building import *
-
-cwd = GetCurrentDir()
-src = ["board.c"]
-CPPPATH = [cwd, str(Dir('#'))]
-
-if GetDepend(['BSP_USING_PL011']):
- src = src + ['drv_uart.c']
-
-if GetDepend(['BSP_USING_SDHCI']):
- src = src + ['drv_sd.c']
-
-group = DefineGroup('driver', src, depend = [''], CPPPATH = CPPPATH)
-
-# build for sub-directory
-list = os.listdir(cwd)
-objs = []
-
-for d in list:
- path = os.path.join(cwd, d)
- if os.path.isfile(os.path.join(path, 'SConscript')):
- objs = objs + SConscript(os.path.join(d, 'SConscript'))
-group = group + objs
-
-Return('group')
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/board.c
deleted file mode 100644
index 7261199d46..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-10-28 zhujiale The first version
- */
-
-#define DBG_TAG "board"
-#define DBG_LVL DBG_INFO
-#include <rtdbg.h>
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <mm_aspace.h>
-#include <setup.h>
-#include "board.h"
-#include "drv_uart.h"
-
-#include "cp15.h"
-#include "mmu.h"
-#include <mm_page.h>
-
-#ifdef RT_USING_SMART
-#include <lwp_arch.h>
-#endif
-void rt_hw_board_init(void)
-{
- rt_hw_common_setup();
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/board.h
deleted file mode 100644
index 88e8269855..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/board.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-10-28 zhujiale The first version
- */
-
-#ifndef BOARD_H__
-#define BOARD_H__
-
-#include <stdint.h>
-#include "mmu.h"
-#include "ioremap.h"
-
-extern int __bss_end;
-#define HEAP_BEGIN ((void*)&__bss_end)
-
-#ifdef RT_USING_SMART
-#define HEAP_END ((size_t)KERNEL_VADDR_START + 32 * 1024 * 1024)
-#define PAGE_START HEAP_END
-#define PAGE_END ((size_t)KERNEL_VADDR_START + 128 * 1024 * 1024)
-#else
-#define KERNEL_VADDR_START 0x0
-
-#define HEAP_END (KERNEL_VADDR_START + 32 * 1024 * 1024)
-#define PAGE_START HEAP_END
-#define PAGE_END ((size_t)PAGE_START + 128 * 1024 * 1024)
-#endif
-
-void rt_hw_board_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c
deleted file mode 100644
index 2e8103c995..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-10-28 zhujiale The first version
- */
-
-#include <sdhci.h>
-#include <rtdevice.h>
-#include "drv_sd.h"
-#define DBG_TAG "SDHCI"
-#ifdef DRV_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* DRV_DEBUG */
-#include <rtdbg.h>
-#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
-struct sdhci_iproc_data {
- const struct sdhci_pltfm_data *pdata;
- rt_uint32_t caps;
- rt_uint32_t caps1;
- rt_uint32_t mmc_caps;
- rt_bool_t missing_caps;
-};
-
-struct sdhci_iproc_host {
- const struct sdhci_iproc_data *data;
- rt_uint32_t shadow_cmd;
- rt_uint32_t shadow_blk;
- rt_bool_t is_cmd_shadowed;
- rt_bool_t is_blk_shadowed;
-};
-
-static inline rt_uint32_t sdhci_iproc_readl(struct sdhci_host *host, int reg)
-{
- rt_uint32_t val = readl(host->ioaddr + reg);
-
- return val;
-}
-
-static rt_uint16_t sdhci_iproc_readw(struct sdhci_host *host, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
- rt_uint32_t val;
- rt_uint16_t word;
-
- if ((reg == SDHCI_TRANSFER_MODE) && iproc_host->is_cmd_shadowed)
- {
- /* Get the saved transfer mode */
- val = iproc_host->shadow_cmd;
- } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
- iproc_host->is_blk_shadowed)
- {
- /* Get the saved block info */
- val = iproc_host->shadow_blk;
- } else {
- val = sdhci_iproc_readl(host, (reg & ~3));
- }
- word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
- return word;
-}
-
-static rt_uint8_t sdhci_iproc_readb(struct sdhci_host *host, int reg)
-{
- rt_uint32_t val = sdhci_iproc_readl(host, (reg & ~3));
- rt_uint8_t byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
- return byte;
-}
-
-static inline void sdhci_iproc_writel(struct sdhci_host *host, rt_uint32_t val, int reg)
-{
- LOG_D("%s: writel [0x%02x] 0x%08x\n",
- mmc_hostname(host->mmc), reg, val);
- writel(val, host->ioaddr + reg);
- if (host->clock <= 400000)
- {
- /* Round up to micro-second four SD clock delay */
- if (host->clock)
- rt_hw_us_delay((4 * 1000000 + host->clock - 1) / host->clock);
- else
- rt_hw_us_delay(10);
- }
-}
-
-static void sdhci_iproc_writew(struct sdhci_host *host, rt_uint16_t val, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_iproc_host *iproc_host = sdhci_pltfm_priv(pltfm_host);
- rt_uint32_t word_shift = REG_OFFSET_IN_BITS(reg);
- rt_uint32_t mask = 0xffff << word_shift;
- rt_uint32_t oldval, newval;
-
- if (reg == SDHCI_COMMAND)
- {
- /* Write the block now as we are issuing a command */
- if (iproc_host->is_blk_shadowed)
- {
- sdhci_iproc_writel(host, iproc_host->shadow_blk,
- SDHCI_BLOCK_SIZE);
- iproc_host->is_blk_shadowed = false;
- }
- oldval = iproc_host->shadow_cmd;
- iproc_host->is_cmd_shadowed = false;
- } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
- iproc_host->is_blk_shadowed)
- {
- /* Block size and count are stored in shadow reg */
- oldval = iproc_host->shadow_blk;
- } else {
- /* Read reg, all other registers are not shadowed */
- oldval = sdhci_iproc_readl(host, (reg & ~3));
- }
- newval = (oldval & ~mask) | (val << word_shift);
-
- if (reg == SDHCI_TRANSFER_MODE)
- {
- /* Save the transfer mode until the command is issued */
- iproc_host->shadow_cmd = newval;
- iproc_host->is_cmd_shadowed = true;
- } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT)
- {
- /* Save the block info until the command is issued */
- iproc_host->shadow_blk = newval;
- iproc_host->is_blk_shadowed = true;
- } else {
- /* Command or other regular 32-bit write */
- sdhci_iproc_writel(host, newval, reg & ~3);
- }
-}
-
-static void sdhci_iproc_writeb(struct sdhci_host *host, rt_uint8_t val, int reg)
-{
- rt_uint32_t oldval = sdhci_iproc_readl(host, (reg & ~3));
- rt_uint32_t byte_shift = REG_OFFSET_IN_BITS(reg);
- rt_uint32_t mask = 0xff << byte_shift;
- rt_uint32_t newval = (oldval & ~mask) | (val << byte_shift);
-
- sdhci_iproc_writel(host, newval, reg & ~3);
-}
-
-static const struct sdhci_ops sdhci_iproc_bcm2711_ops = {
- .read_l = sdhci_iproc_readl,
- .read_w = sdhci_iproc_readw,
- .read_b = sdhci_iproc_readb,
- .write_l = sdhci_iproc_writel,
- .write_w = sdhci_iproc_writew,
- .write_b = sdhci_iproc_writeb,
- .set_clock = sdhci_set_clock,
- .set_bus_width = sdhci_set_bus_width,
- .reset = sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
-};
-
-static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = {
- .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
- .ops = &sdhci_iproc_bcm2711_ops,
-};
-
-static const struct sdhci_iproc_data bcm2711_data = {
- .pdata = &sdhci_bcm2711_pltfm_data,
- .mmc_caps = MMC_CAP_3_3V_DDR,
-};
-
-rt_err_t bcm2835_probe(struct rt_platform_device *pdev)
-{
- struct sdhci_iproc_host *iproc_host;
- const struct sdhci_iproc_data *iproc_data = NULL;
- struct sdhci_host *host;
- struct sdhci_pltfm_host *pltfm_host;
- int ret;
- iproc_data = &bcm2711_data;
- host = sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host));
- pltfm_host = sdhci_priv(host);
- iproc_host = sdhci_pltfm_priv(pltfm_host);
-
- iproc_host->data = iproc_data;
-
- ret = mmc_of_parse(host->mmc);
- if (ret)
- goto err;
-
- sdhci_get_property(pdev);
-
- host->mmc->caps |= iproc_host->data->mmc_caps;
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err;
-
- return 0;
-err:
- return ret;
-}
-
-static const struct rt_ofw_node_id bcm2835_ofw_ids[] =
-{
- /* { .compatible = "brcm,bcm2711-emmc2"},*/
- { .compatible = "brcm,bcm2835-mmc"},
- { /* sentinel */ }
-};
-
-static struct rt_platform_driver bcm2835_driver =
-{
- .name = "bcm2835",
- .ids = bcm2835_ofw_ids,
-
- .probe = bcm2835_probe,
- /* .remove = pl011_remove,*/
-};
-
-
-RT_PLATFORM_DRIVER_EXPORT(bcm2835_driver);
-
-
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h
deleted file mode 100644
index 506b1fafd9..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_sd.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-10-28 zhujiale The first version
- */
-
-#ifndef __DRV_SD_BCM2835_H_
-#define __DRV_SD_BCM2835_H_
-#include <drivers/dev_mmcsd_core.h>
-#include <rtthread.h>
-#include <drivers/mmcsd_cmd.h>
-#include <drivers/mmcsd_host.h>
-struct sdhci_bcm2835 {
- struct sdhci_host *host;
- struct rt_platform_device *pdev;
- struct rt_mmcsd_req *mrq;
-
- void *ioaddr;
- rt_mutex_t mutex;
-};
-#define SDCMD 0x00 /* Command to SD card - 16 R/W */
-#define SDARG 0x04 /* Argument to SD card - 32 R/W */
-#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
-#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
-#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */
-#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */
-#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */
-#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */
-#define SDHSTS 0x20 /* SD host status - 11 R/W */
-#define SDVDD 0x30 /* SD card power control - 1 R/W */
-#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
-#define SDHCFG 0x38 /* Host configuration - 2 R/W */
-#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
-#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
-#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
-
-#define SDCMD_NEW_FLAG 0x8000
-#define SDCMD_FAIL_FLAG 0x4000
-#define SDCMD_BUSYWAIT 0x800
-#define SDCMD_NO_RESPONSE 0x400
-#define SDCMD_LONG_RESPONSE 0x200
-#define SDCMD_WRITE_CMD 0x80
-#define SDCMD_READ_CMD 0x40
-#define SDCMD_CMD_MASK 0x3f
-
-#define SDCDIV_MAX_CDIV 0x7ff
-
-#define SDHSTS_BUSY_IRPT 0x400
-#define SDHSTS_BLOCK_IRPT 0x200
-#define SDHSTS_SDIO_IRPT 0x100
-#define SDHSTS_REW_TIME_OUT 0x80
-#define SDHSTS_CMD_TIME_OUT 0x40
-#define SDHSTS_CRC16_ERROR 0x20
-#define SDHSTS_CRC7_ERROR 0x10
-#define SDHSTS_FIFO_ERROR 0x08
-/* Reserved */
-/* Reserved */
-#define SDHSTS_DATA_FLAG 0x01
-
-#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR | \
- SDHSTS_CRC16_ERROR | \
- SDHSTS_REW_TIME_OUT | \
- SDHSTS_FIFO_ERROR)
-
-#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT | \
- SDHSTS_TRANSFER_ERROR_MASK)
-
-#define SDHCFG_BUSY_IRPT_EN BIT(10)
-#define SDHCFG_BLOCK_IRPT_EN BIT(8)
-#define SDHCFG_SDIO_IRPT_EN BIT(5)
-#define SDHCFG_DATA_IRPT_EN BIT(4)
-#define SDHCFG_SLOW_CARD BIT(3)
-#define SDHCFG_WIDE_EXT_BUS BIT(2)
-#define SDHCFG_WIDE_INT_BUS BIT(1)
-#define SDHCFG_REL_CMD_LINE BIT(0)
-
-#define SDVDD_POWER_OFF 0
-#define SDVDD_POWER_ON 1
-
-#define SDEDM_FORCE_DATA_MODE BIT(19)
-#define SDEDM_CLOCK_PULSE BIT(20)
-#define SDEDM_BYPASS BIT(21)
-
-#define SDEDM_WRITE_THRESHOLD_SHIFT 9
-#define SDEDM_READ_THRESHOLD_SHIFT 14
-#define SDEDM_THRESHOLD_MASK 0x1f
-
-#define SDEDM_FSM_MASK 0xf
-#define SDEDM_FSM_IDENTMODE 0x0
-#define SDEDM_FSM_DATAMODE 0x1
-#define SDEDM_FSM_READDATA 0x2
-#define SDEDM_FSM_WRITEDATA 0x3
-#define SDEDM_FSM_READWAIT 0x4
-#define SDEDM_FSM_READCRC 0x5
-#define SDEDM_FSM_WRITECRC 0x6
-#define SDEDM_FSM_WRITEWAIT1 0x7
-#define SDEDM_FSM_POWERDOWN 0x8
-#define SDEDM_FSM_POWERUP 0x9
-#define SDEDM_FSM_WRITESTART1 0xa
-#define SDEDM_FSM_WRITESTART2 0xb
-#define SDEDM_FSM_GENPULSES 0xc
-#define SDEDM_FSM_WRITEWAIT2 0xd
-#define SDEDM_FSM_STARTPOWDOWN 0xf
-
-#define SDDATA_FIFO_WORDS 16
-
-#define FIFO_READ_THRESHOLD 4
-#define FIFO_WRITE_THRESHOLD 4
-#define SDDATA_FIFO_PIO_BURST 8
-
-#define PIO_THRESHOLD 1 /* Maximum block count for PIO (0 = always DMA) */
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c
deleted file mode 100644
index a72bbcd6e8..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-05-05 Bernard The first version
- * 2022-08-24 GuEe-GUI add OFW support
- */
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include <cpuport.h>
-
-#include <ioremap.h>
-
-#include <drivers/serial_dm.h>
-
-#define PL011_OEIM RT_BIT(10) /* overrun error interrupt mask */
-#define PL011_BEIM RT_BIT(9) /* break error interrupt mask */
-#define PL011_PEIM RT_BIT(8) /* parity error interrupt mask */
-#define PL011_FEIM RT_BIT(7) /* framing error interrupt mask */
-#define PL011_RTIM RT_BIT(6) /* receive timeout interrupt mask */
-#define PL011_TXIM RT_BIT(5) /* transmit interrupt mask */
-#define PL011_RXIM RT_BIT(4) /* receive interrupt mask */
-#define PL011_DSRMIM RT_BIT(3) /* DSR interrupt mask */
-#define PL011_DCDMIM RT_BIT(2) /* DCD interrupt mask */
-#define PL011_CTSMIM RT_BIT(1) /* CTS interrupt mask */
-#define PL011_RIMIM RT_BIT(0) /* RI interrupt mask */
-
-#define PL011_DR 0x000
-#define PL011_FR 0x018
-#define PL011_IBRD 0x024
-#define PL011_FBRD 0x028
-#define PL011_LCR 0x02c
-#define PL011_CR 0x030
-#define PL011_IMSC 0x038
-#define PL011_RIS 0x03c
-#define PL011_DMACR 0x048
-
-#define PL011_LCRH_SPS (1 << 7)
-#define PL011_LCRH_WLEN_8 (3 << 5)
-#define PL011_LCRH_WLEN_7 (2 << 5)
-#define PL011_LCRH_WLEN_6 (1 << 5)
-#define PL011_LCRH_WLEN_5 (0 << 5)
-#define PL011_LCRH_FEN (1 << 4)
-#define PL011_LCRH_STP2 (1 << 3)
-#define PL011_LCRH_EPS (1 << 2)
-#define PL011_LCRH_PEN (1 << 1)
-#define PL011_LCRH_BRK (1 << 0)
-
-#define PL011_LCRH_WLEN(n) ((n - 5) << 5)
-
-#define PL011_CR_CTSEN RT_BIT(15)
-#define PL011_CR_RTSEN RT_BIT(14)
-#define PL011_CR_RTS RT_BIT(11)
-#define PL011_CR_DTR RT_BIT(10)
-#define PL011_CR_RXE RT_BIT(9)
-#define PL011_CR_TXE RT_BIT(8)
-#define PL011_CR_LBE RT_BIT(7)
-#define PL011_CR_SIRLP RT_BIT(2)
-#define PL011_CR_SIREN RT_BIT(1)
-#define PL011_CR_UARTEN RT_BIT(0)
-
-struct pl011
-{
- struct rt_serial_device parent;
-
- int irq;
- void *base;
- rt_ubase_t freq;
- struct rt_clk *clk;
- struct rt_clk *pclk;
-
- struct rt_spinlock spinlock;
-};
-
-#define raw_to_pl011(raw) rt_container_of(raw, struct pl011, parent)
-
-rt_inline rt_uint32_t pl011_read(struct pl011 *pl011, int offset)
-{
- return HWREG32(pl011->base + offset);
-}
-
-rt_inline void pl011_write(struct pl011 *pl011, int offset, rt_uint32_t value)
-{
- HWREG32(pl011->base + offset) = value;
-}
-
-static void pl011_isr(int irqno, void *param)
-{
- struct pl011 *pl011 = param;
-
- /* Check irq */
- if (pl011_read(pl011, PL011_RIS) & PL011_RXIM)
- {
- rt_base_t level = rt_spin_lock_irqsave(&pl011->spinlock);
-
- rt_hw_serial_isr(&pl011->parent, RT_SERIAL_EVENT_RX_IND);
-
- rt_spin_unlock_irqrestore(&pl011->spinlock, level);
- }
-}
-
-static rt_err_t pl011_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
-{
- rt_ubase_t quot;
- struct pl011 *pl011 = raw_to_pl011(serial);
-
- /* Clear UART setting */
- pl011_write(pl011, PL011_CR, 0);
- /* Disable FIFO */
- pl011_write(pl011, PL011_LCR, 0);
-
- if (cfg->baud_rate > pl011->freq / 16)
- {
- quot = RT_DIV_ROUND_CLOSEST(pl011->freq * 8, cfg->baud_rate);
- }
- else
- {
- quot = RT_DIV_ROUND_CLOSEST(pl011->freq * 4, cfg->baud_rate);
- }
-
- pl011_write(pl011, PL011_IBRD, quot >> 6);
- pl011_write(pl011, PL011_FBRD, quot & 0x3f);
- /* FIFO */
- pl011_write(pl011, PL011_LCR, PL011_LCRH_WLEN(cfg->data_bits));
-
- /* Art enable, TX/RX enable */
- pl011_write(pl011, PL011_CR, PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE);
-
- return RT_EOK;
-}
-
-static rt_err_t pl011_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
-{
- struct pl011 *pl011 = raw_to_pl011(serial);
-
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- /* Disable rx irq */
- pl011_write(pl011, PL011_IMSC, pl011_read(pl011, PL011_IMSC) & ~PL011_RXIM);
-
- rt_hw_interrupt_mask(pl011->irq);
-
- break;
-
- case RT_DEVICE_CTRL_SET_INT:
- /* Enable rx irq */
- pl011_write(pl011, PL011_IMSC, pl011_read(pl011, PL011_IMSC) | PL011_RXIM);
-
- rt_hw_interrupt_umask(pl011->irq);
-
- break;
- }
-
- return RT_EOK;
-}
-
-static int pl011_uart_putc(struct rt_serial_device *serial, char c)
-{
- struct pl011 *pl011 = raw_to_pl011(serial);
-
- while (pl011_read(pl011, PL011_FR) & PL011_TXIM)
- {
- rt_hw_cpu_relax();
- }
-
- pl011_write(pl011, PL011_DR, c);
-
- return 1;
-}
-
-static int pl011_uart_getc(struct rt_serial_device *serial)
-{
- int ch = -1;
- struct pl011 *pl011 = raw_to_pl011(serial);
-
- if (!(pl011_read(pl011, PL011_FR) & PL011_RXIM))
- {
- ch = pl011_read(pl011, PL011_DR);
- }
-
- return ch;
-}
-
-static const struct rt_uart_ops pl011_uart_ops =
-{
- .configure = pl011_uart_configure,
- .control = pl011_uart_control,
- .putc = pl011_uart_putc,
- .getc = pl011_uart_getc,
-};
-
-static void pl011_early_kick(struct rt_fdt_earlycon *con, int why)
-{
- struct pl011 *pl011 = raw_to_pl011(con->data);
-
- switch (why)
- {
- case FDT_EARLYCON_KICK_UPDATE:
- pl011->base = rt_ioremap((void *)con->mmio, con->size);
- break;
-
- case FDT_EARLYCON_KICK_COMPLETED:
- rt_iounmap(pl011->base);
- break;
-
- default:
- break;
- }
-}
-
-static rt_err_t pl011_early_setup(struct rt_fdt_earlycon *con, const char *options)
-{
- rt_err_t err = RT_EOK;
- static struct pl011 pl011 = { };
-
- if (options && !con->mmio)
- {
- char *arg;
-
- con->mmio = RT_NULL;
-
- /*
- * The pl011 serial port must already be setup and configured in early.
- * Options are not yet supported.
- * pl011,<addr>
- * pl011,mmio32,<addr>
- */
- serial_for_each_args(arg, options)
- {
- if (!rt_strcmp(arg, "pl011") || !rt_strcmp(arg, "mmio32"))
- {
- continue;
- }
- if (!con->mmio)
- {
- con->mmio = (rt_ubase_t)serial_base_from_args(arg);
- break;
- }
- }
- }
-
- if (!con->size)
- {
- con->size = 0x1000;
- }
-
- if (con->mmio)
- {
- pl011.base = rt_ioremap_early((void *)con->mmio, con->size);
- }
-
- if (pl011.base)
- {
- con->console_putc = (typeof(con->console_putc))&pl011_uart_putc;
- con->console_kick = pl011_early_kick;
- con->data = &pl011.parent;
- pl011.parent.config = (typeof(pl011.parent.config))RT_SERIAL_CONFIG_DEFAULT;
- }
- else
- {
- err = -RT_ERROR;
- }
-
- return err;
-}
-RT_FDT_EARLYCON_EXPORT(pl011, "pl011", "arm,pl011", pl011_early_setup);
-
-static void pl011_free(struct pl011 *pl011)
-{
- if (pl011->base)
- {
- rt_iounmap(pl011->base);
- }
-
- /* if (!rt_is_err_or_null(pl011->clk))*/
- /* {*/
- /* rt_clk_disable(pl011->clk);*/
- /* rt_clk_put(pl011->clk);*/
- /* }*/
-
- /* if (!rt_is_err_or_null(pl011->pclk))*/
- /* {*/
- /* rt_clk_disable_unprepare(pl011->pclk);*/
- /* rt_clk_put(pl011->pclk);*/
- /* }*/
-
- rt_free(pl011);
-}
-
-static rt_err_t pl011_probe(struct rt_platform_device *pdev)
-{
- rt_err_t err;
- const char *name;
- char isr_name[RT_NAME_MAX];
- struct rt_device *dev = &pdev->parent;
- struct pl011 *pl011 = rt_calloc(1, sizeof(*pl011));
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
-
- if (!pl011)
- {
- return -RT_ENOMEM;
- }
-
- pl011->base = rt_dm_dev_iomap(dev, 0);
-
- if (!pl011->base)
- {
- err = -RT_EIO;
-
- goto _fail;
- }
-
- pl011->irq = rt_dm_dev_get_irq(dev, 0);
-
- if (pl011->irq < 0)
- {
- err = pl011->irq;
-
- goto _fail;
- }
-
- /* pl011->clk = rt_clk_get_by_index(dev, 0);*/
-
- /* if (rt_is_err(pl011->clk))*/
- /* {*/
- /* err = rt_ptr_err(pl011->clk);*/
-
- /* goto _fail;*/
- /* }*/
-
- /* pl011->pclk = rt_clk_get_by_name(dev, "apb_pclk");*/
-
- /* if (rt_is_err(pl011->pclk))*/
- /* {*/
- /* err = rt_ptr_err(pl011->pclk);*/
-
- /* goto _fail;*/
- /* }*/
-
- /* if ((err = rt_clk_prepare_enable(pl011->pclk)))*/
- /* {*/
- /* goto _fail;*/
- /* }*/
-
- rt_dm_dev_bind_fwdata(&pl011->parent.parent, dev->ofw_node, &pl011->parent);
-
- /* rt_clk_enable(pl011->clk);*/
- /* pl011->freq = rt_clk_get_rate(pl011->clk);*/
-
- dev->user_data = pl011;
-
- pl011->parent.ops = &pl011_uart_ops;
- pl011->parent.config = config;
-
- rt_spin_lock_init(&pl011->spinlock);
-
- serial_dev_set_name(&pl011->parent);
- name = rt_dm_dev_get_name(&pl011->parent.parent);
-
- rt_hw_serial_register(&pl011->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, pl011);
- rt_snprintf(isr_name, RT_NAME_MAX, "%s-pl011", name);
- rt_hw_interrupt_install(pl011->irq, pl011_isr, pl011, isr_name);
-
- return RT_EOK;
-
-_fail:
- pl011_free(pl011);
-
- return err;
-}
-
-static rt_err_t pl011_remove(struct rt_platform_device *pdev)
-{
- struct rt_device *dev = &pdev->parent;
- struct pl011 *pl011 = dev->user_data;
-
- rt_dm_dev_unbind_fwdata(dev, RT_NULL);
-
- rt_hw_interrupt_mask(pl011->irq);
- rt_pic_detach_irq(pl011->irq, pl011);
-
- rt_device_unregister(&pl011->parent.parent);
-
- pl011_free(pl011);
-
- return RT_EOK;
-}
-
-static const struct rt_ofw_node_id pl011_ofw_ids[] =
-{
- { .type = "ttyAMA", .compatible = "arm,pl011" },
- { .type = "ttyAMA", .compatible = "arm,pl011-axi" },
- { /* sentinel */ }
-};
-
-static struct rt_platform_driver pl011_driver =
-{
- .name = "serial-pl011",
- .ids = pl011_ofw_ids,
-
- .probe = pl011_probe,
- .remove = pl011_remove,
-};
-
-static int pl011_drv_register(void)
-{
- rt_platform_driver_register(&pl011_driver);
-
- return 0;
-}
-INIT_DRIVER_EARLY_EXPORT(pl011_drv_register);
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h
deleted file mode 100644
index b47afcce14..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/drv_uart.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- */
-
-#ifndef DRV_UART_H__
-#define DRV_UART_H__
-
-/* register's bit*/
-#define PL011_FR_RI (1 << 8)
-#define PL011_FR_TXFE (1 << 7)
-#define PL011_FR_RXFF (1 << 6)
-#define PL011_FR_TXFF (1 << 5)
-#define PL011_FR_RXFE (1 << 4)
-#define PL011_FR_BUSY (1 << 3)
-#define PL011_FR_DCD (1 << 2)
-#define PL011_FR_DSR (1 << 1)
-#define PL011_FR_CTS (1 << 0)
-
-#define PL011_LCRH_SPS (1 << 7)
-#define PL011_LCRH_WLEN_8 (3 << 5)
-#define PL011_LCRH_WLEN_7 (2 << 5)
-#define PL011_LCRH_WLEN_6 (1 << 5)
-#define PL011_LCRH_WLEN_5 (0 << 5)
-#define PL011_LCRH_FEN (1 << 4)
-#define PL011_LCRH_STP2 (1 << 3)
-#define PL011_LCRH_EPS (1 << 2)
-#define PL011_LCRH_PEN (1 << 1)
-#define PL011_LCRH_BRK (1 << 0)
-
-#define PL011_CR_CTSEN (1 << 15)
-#define PL011_CR_RTSEN (1 << 14)
-#define PL011_CR_RTS (1 << 11)
-#define PL011_CR_DTR (1 << 10)
-#define PL011_CR_RXE (1 << 9)
-#define PL011_CR_TXE (1 << 8)
-#define PL011_CR_LBE (1 << 7)
-#define PL011_CR_SIRLP (1 << 2)
-#define PL011_CR_SIREN (1 << 1)
-#define PL011_CR_UARTEN (1 << 0)
-
-#define PL011_IMSC_TXIM (1 << 5)
-#define PL011_IMSC_RXIM (1 << 4)
-
-#define PL011_INTERRUPT_OVERRUN_ERROR (1 << 10)
-#define PL011_INTERRUPT_BREAK_ERROR (1 << 9)
-#define PL011_INTERRUPT_PARITY_ERROR (1 << 8)
-#define PL011_INTERRUPT_FRAMING_ERROR (1 << 7)
-#define PL011_INTERRUPT_RECEIVE_TIMEOUT (1 << 6)
-#define PL011_INTERRUPT_TRANSMIT (1 << 5)
-#define PL011_INTERRUPT_RECEIVE (1 << 4)
-#define PL011_INTERRUPT_nUARTCTS (1 << 1)
-
-#define PL011_REG_DR(BASE) HWREG32(BASE + 0x00)
-#define PL011_REG_RSRECR(BASE) HWREG32(BASE + 0x04)
-#define PL011_REG_RESERVED0(BASE) HWREG32(BASE + 0x08)
-#define PL011_REG_FR(BASE) HWREG32(BASE + 0x18)
-#define PL011_REG_RESERVED1(BASE) HWREG32(BASE + 0x1C)
-#define PL011_REG_ILPR(BASE) HWREG32(BASE + 0x20)
-#define PL011_REG_IBRD(BASE) HWREG32(BASE + 0x24)
-#define PL011_REG_FBRD(BASE) HWREG32(BASE + 0x28)
-#define PL011_REG_LCRH(BASE) HWREG32(BASE + 0x2C)
-#define PL011_REG_CR(BASE) HWREG32(BASE + 0x30)
-#define PL011_REG_IFLS(BASE) HWREG32(BASE + 0x34)
-#define PL011_REG_IMSC(BASE) HWREG32(BASE + 0x38)
-#define PL011_REG_RIS(BASE) HWREG32(BASE + 0x3C)
-#define PL011_REG_MIS(BASE) HWREG32(BASE + 0x40)
-#define PL011_REG_ICR(BASE) HWREG32(BASE + 0x44)
-#define PL011_REG_DMACR(BASE) HWREG32(BASE + 0x48)
-#define PL011_REG_RESERVED2(BASE) HWREG32(BASE + 0x4C)
-#define PL011_REG_ITCR(BASE) HWREG32(BASE + 0x80)
-#define PL011_REG_ITIP(BASE) HWREG32(BASE + 0x84)
-#define PL011_REG_ITOP(BASE) HWREG32(BASE + 0x88)
-#define PL011_REG_TDR(BASE) HWREG32(BASE + 0x8C)
-
-/*
- * Auxiliary
- */
-#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */
-#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */
-#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */
-#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */
-#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */
-#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */
-#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */
-#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */
-#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */
-#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */
-#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */
-#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */
-#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */
-#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */
-#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */
-#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */
-#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */
-#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */
-#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */
-#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */
-
-int rt_hw_uart_init(void);
-void rt_hw_earlycon_ioremap_early(void);
-
-#endif /* DRV_UART_H__ */
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig
deleted file mode 100644
index ab101b8be5..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-menuconfig RT_USING_SDHCI
- bool "Using sdhci for sd/mmc drivers"
- default n
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript
deleted file mode 100644
index 3eab8df97a..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/SConscript
+++ /dev/null
@@ -1,18 +0,0 @@
-from building import *
-
-group = []
-
-if not GetDepend(['RT_USING_SDHCI']):
- Return('group')
-
-cwd = GetCurrentDir()
-CPPPATH = [cwd + '/include']
-
-src = []
-src += Glob('*.c')
-src += Glob('src/*.c')
-src += Glob('sdhci-platform/*.c')
-
-group = DefineGroup('sdhci-drivers', src, depend = [''], CPPPATH = CPPPATH)
-
-Return('group')
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h
deleted file mode 100644
index bc5c7dab2a..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci-platform.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-
-#ifndef _DRIVERS_MMC_SDHCI_PLTFM_H
-#define _DRIVERS_MMC_SDHCI_PLTFM_H
-#include <rtthread.h>
-#include <drivers/core/dm.h>
-#include <drivers/ofw.h>
-#include <drivers/platform.h>
-#include <drivers/clk.h>
-#include "sdhci.h"
-
-struct sdhci_pltfm_data
-{
- const struct sdhci_ops *ops;
- unsigned int quirks;
- unsigned int quirks2;
-};
-
-struct sdhci_pltfm_host
-{
- struct rt_clk *clk;
-
- /* migrate from sdhci_of_host */
- unsigned int clock;
- rt_uint64_t xfer_mode_shadow;
-
- unsigned long private[];
-};
-
-void sdhci_get_property(struct rt_platform_device *pdev);
-
-static inline void sdhci_get_of_property(struct rt_platform_device *pdev)
-{
- return sdhci_get_property(pdev);
-}
-
-
-extern struct sdhci_host *sdhci_pltfm_init(struct rt_platform_device *pdev,
- const struct sdhci_pltfm_data *pdata,
- size_t priv_size);
-extern void sdhci_pltfm_free(struct rt_platform_device *pdev);
-
-extern int sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
- const struct sdhci_pltfm_data *pdata,
- size_t priv_size);
-extern void sdhci_pltfm_remove(struct rt_platform_device *pdev);
-
-extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
-
-static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
-{
- return host->private;
-}
-
-extern const struct dev_pm_ops sdhci_pltfm_pmops;
-static inline int sdhci_pltfm_suspend(struct rt_device *dev)
-{
- return 0;
-}
-static inline int sdhci_pltfm_resume(struct rt_device *dev)
-{
- return 0;
-}
-
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h
deleted file mode 100644
index e58517d394..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci.h
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#ifndef __SDHCI_HW_H
-#define __SDHCI_HW_H
-
-#include "sdhci_host.h"
-#include "sdhci_misc.h"
-#include "sdhci_dma.h"
-#include "sdhci-platform.h"
-#include <drivers/mmcsd_cmd.h>
-#include <drivers/mmcsd_host.h>
-#include <rtdevice.h>
-/*
- * Controller registers
- */
-#define lower_32_bits(n) ((rt_uint32_t)((n) & 0xffffffff))
-#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
-
-#define MAX_TUNING_LOOP 40
-
-#define SDHCI_DMA_ADDRESS 0x00
-#define SDHCI_ARGUMENT2 SDHCI_DMA_ADDRESS
-#define SDHCI_32BIT_BLK_CNT SDHCI_DMA_ADDRESS
-
-#define SDHCI_BLOCK_SIZE 0x04
-#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
-
-#define SDHCI_BLOCK_COUNT 0x06
-
-#define SDHCI_ARGUMENT 0x08
-
-#define SDHCI_TRANSFER_MODE 0x0C
-#define SDHCI_TRNS_DMA 0x01
-#define SDHCI_TRNS_BLK_CNT_EN 0x02
-#define SDHCI_TRNS_AUTO_CMD12 0x04
-#define SDHCI_TRNS_AUTO_CMD23 0x08
-#define SDHCI_TRNS_AUTO_SEL 0x0C
-#define SDHCI_TRNS_READ 0x10
-#define SDHCI_TRNS_MULTI 0x20
-
-#define SDHCI_COMMAND 0x0E
-#define SDHCI_CMD_RESP_MASK 0x03
-#define SDHCI_CMD_CRC 0x08
-#define SDHCI_CMD_INDEX 0x10
-#define SDHCI_CMD_DATA 0x20
-#define SDHCI_CMD_ABORTCMD 0xC0
-
-#define SDHCI_CMD_RESP_NONE 0x00
-#define SDHCI_CMD_RESP_LONG 0x01
-#define SDHCI_CMD_RESP_SHORT 0x02
-#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
-
-#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
-#define SDHCI_GET_CMD(c) ((c >> 8) & 0x3f)
-
-#define SDHCI_RESPONSE 0x10
-
-#define SDHCI_BUFFER 0x20
-
-#define SDHCI_PRESENT_STATE 0x24
-#define SDHCI_CMD_INHIBIT 0x00000001
-#define SDHCI_DATA_INHIBIT 0x00000002
-#define SDHCI_DOING_WRITE 0x00000100
-#define SDHCI_DOING_READ 0x00000200
-#define SDHCI_SPACE_AVAILABLE 0x00000400
-#define SDHCI_DATA_AVAILABLE 0x00000800
-#define SDHCI_CARD_PRESENT 0x00010000
-#define SDHCI_CARD_PRES_SHIFT 16
-#define SDHCI_CD_STABLE 0x00020000
-#define SDHCI_CD_LVL 0x00040000
-#define SDHCI_CD_LVL_SHIFT 18
-#define SDHCI_WRITE_PROTECT 0x00080000
-#define SDHCI_DATA_LVL_MASK 0x00F00000
-#define SDHCI_DATA_LVL_SHIFT 20
-#define SDHCI_DATA_0_LVL_MASK 0x00100000
-#define SDHCI_CMD_LVL 0x01000000
-
-#define SDHCI_HOST_CONTROL 0x28
-#define SDHCI_CTRL_LED 0x01
-#define SDHCI_CTRL_4BITBUS 0x02
-#define SDHCI_CTRL_HISPD 0x04
-#define SDHCI_CTRL_DMA_MASK 0x18
-#define SDHCI_CTRL_SDMA 0x00
-#define SDHCI_CTRL_ADMA1 0x08
-#define SDHCI_CTRL_ADMA32 0x10
-#define SDHCI_CTRL_ADMA64 0x18
-#define SDHCI_CTRL_ADMA3 0x18
-#define SDHCI_CTRL_8BITBUS 0x20
-#define SDHCI_CTRL_CDTEST_INS 0x40
-#define SDHCI_CTRL_CDTEST_EN 0x80
-
-#define SDHCI_POWER_CONTROL 0x29
-#define SDHCI_POWER_ON 0x01
-#define SDHCI_POWER_180 0x0A
-#define SDHCI_POWER_300 0x0C
-#define SDHCI_POWER_330 0x0E
-/*
- * VDD2 - UHS2 or PCIe/NVMe
- * VDD2 power on/off and voltage select
- */
-#define SDHCI_VDD2_POWER_ON 0x10
-#define SDHCI_VDD2_POWER_120 0x80
-#define SDHCI_VDD2_POWER_180 0xA0
-
-#define SDHCI_BLOCK_GAP_CONTROL 0x2A
-
-#define SDHCI_WAKE_UP_CONTROL 0x2B
-#define SDHCI_WAKE_ON_INT 0x01
-#define SDHCI_WAKE_ON_INSERT 0x02
-#define SDHCI_WAKE_ON_REMOVE 0x04
-
-#define SDHCI_CLOCK_CONTROL 0x2C
-#define SDHCI_DIVIDER_SHIFT 8
-#define SDHCI_DIVIDER_HI_SHIFT 6
-#define SDHCI_DIV_MASK 0xFF
-#define SDHCI_DIV_MASK_LEN 8
-#define SDHCI_DIV_HI_MASK 0x300
-#define SDHCI_PROG_CLOCK_MODE 0x0020
-#define SDHCI_CLOCK_CARD_EN 0x0004
-#define SDHCI_CLOCK_PLL_EN 0x0008
-#define SDHCI_CLOCK_INT_STABLE 0x0002
-#define SDHCI_CLOCK_INT_EN 0x0001
-
-#define SDHCI_TIMEOUT_CONTROL 0x2E
-
-#define SDHCI_SOFTWARE_RESET 0x2F
-#define SDHCI_RESET_ALL 0x01
-#define SDHCI_RESET_CMD 0x02
-#define SDHCI_RESET_DATA 0x04
-
-#define SDHCI_INT_STATUS 0x30
-#define SDHCI_INT_ENABLE 0x34
-#define SDHCI_SIGNAL_ENABLE 0x38
-#define SDHCI_INT_RESPONSE 0x00000001
-#define SDHCI_INT_DATA_END 0x00000002
-#define SDHCI_INT_BLK_GAP 0x00000004
-#define SDHCI_INT_DMA_END 0x00000008
-#define SDHCI_INT_SPACE_AVAIL 0x00000010
-#define SDHCI_INT_DATA_AVAIL 0x00000020
-#define SDHCI_INT_CARD_INSERT 0x00000040
-#define SDHCI_INT_CARD_REMOVE 0x00000080
-#define SDHCI_INT_CARD_INT 0x00000100
-#define SDHCI_INT_RETUNE 0x00001000
-#define SDHCI_INT_CQE 0x00004000
-#define SDHCI_INT_ERROR 0x00008000
-#define SDHCI_INT_TIMEOUT 0x00010000
-#define SDHCI_INT_CRC 0x00020000
-#define SDHCI_INT_END_BIT 0x00040000
-#define SDHCI_INT_INDEX 0x00080000
-#define SDHCI_INT_DATA_TIMEOUT 0x00100000
-#define SDHCI_INT_DATA_CRC 0x00200000
-#define SDHCI_INT_DATA_END_BIT 0x00400000
-#define SDHCI_INT_BUS_POWER 0x00800000
-#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
-#define SDHCI_INT_ADMA_ERROR 0x02000000
-
-#define SDHCI_INT_NORMAL_MASK 0x00007FFF
-#define SDHCI_INT_ERROR_MASK 0xFFFF8000
-
-#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_AUTO_CMD_ERR)
-#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | SDHCI_INT_BLK_GAP)
-#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
-
-#define SDHCI_CQE_INT_ERR_MASK ( \
- SDHCI_INT_ADMA_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)
-
-#define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE)
-
-#define SDHCI_AUTO_CMD_STATUS 0x3C
-#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002
-#define SDHCI_AUTO_CMD_CRC 0x00000004
-#define SDHCI_AUTO_CMD_END_BIT 0x00000008
-#define SDHCI_AUTO_CMD_INDEX 0x00000010
-
-#define SDHCI_HOST_CONTROL2 0x3E
-#define SDHCI_CTRL_UHS_MASK 0x0007
-#define SDHCI_CTRL_UHS_SDR12 0x0000
-#define SDHCI_CTRL_UHS_SDR25 0x0001
-#define SDHCI_CTRL_UHS_SDR50 0x0002
-#define SDHCI_CTRL_UHS_SDR104 0x0003
-#define SDHCI_CTRL_UHS_DDR50 0x0004
-#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
-#define SDHCI_CTRL_VDD_180 0x0008
-#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
-#define SDHCI_CTRL_DRV_TYPE_B 0x0000
-#define SDHCI_CTRL_DRV_TYPE_A 0x0010
-#define SDHCI_CTRL_DRV_TYPE_C 0x0020
-#define SDHCI_CTRL_DRV_TYPE_D 0x0030
-#define SDHCI_CTRL_EXEC_TUNING 0x0040
-#define SDHCI_CTRL_TUNED_CLK 0x0080
-#define SDHCI_CMD23_ENABLE 0x0800
-#define SDHCI_CTRL_V4_MODE 0x1000
-#define SDHCI_CTRL_64BIT_ADDR 0x2000
-#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
-
-#define SDHCI_CAPABILITIES 0x40
-#define SDHCI_TIMEOUT_CLK_MASK RT_GENMASK(5, 0)
-#define SDHCI_TIMEOUT_CLK_SHIFT 0
-#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
-#define SDHCI_CLOCK_BASE_MASK RT_GENMASK(13, 8)
-#define SDHCI_CLOCK_BASE_SHIFT 8
-#define SDHCI_CLOCK_V3_BASE_MASK RT_GENMASK(15, 8)
-#define SDHCI_MAX_BLOCK_MASK 0x00030000
-#define SDHCI_MAX_BLOCK_SHIFT 16
-#define SDHCI_CAN_DO_8BIT 0x00040000
-#define SDHCI_CAN_DO_ADMA2 0x00080000
-#define SDHCI_CAN_DO_ADMA1 0x00100000
-#define SDHCI_CAN_DO_HISPD 0x00200000
-#define SDHCI_CAN_DO_SDMA 0x00400000
-#define SDHCI_CAN_DO_SUSPEND 0x00800000
-#define SDHCI_CAN_VDD_330 0x01000000
-#define SDHCI_CAN_VDD_300 0x02000000
-#define SDHCI_CAN_VDD_180 0x04000000
-#define SDHCI_CAN_64BIT_V4 0x08000000
-#define SDHCI_CAN_64BIT 0x10000000
-
-#define SDHCI_CAPABILITIES_1 0x44
-#define SDHCI_SUPPORT_SDR50 0x00000001
-#define SDHCI_SUPPORT_SDR104 0x00000002
-#define SDHCI_SUPPORT_DDR50 0x00000004
-#define SDHCI_DRIVER_TYPE_A 0x00000010
-#define SDHCI_DRIVER_TYPE_C 0x00000020
-#define SDHCI_DRIVER_TYPE_D 0x00000040
-#define SDHCI_RETUNING_TIMER_COUNT_MASK RT_GENMASK(11, 8)
-#define SDHCI_USE_SDR50_TUNING 0x00002000
-#define SDHCI_RETUNING_MODE_MASK RT_GENMASK(15, 14)
-#define SDHCI_CLOCK_MUL_MASK RT_GENMASK(23, 16)
-#define SDHCI_CAN_DO_ADMA3 0x08000000
-#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
-
-#define SDHCI_MAX_CURRENT 0x48
-#define SDHCI_MAX_CURRENT_LIMIT RT_GENMASK(7, 0)
-#define SDHCI_MAX_CURRENT_330_MASK RT_GENMASK(7, 0)
-#define SDHCI_MAX_CURRENT_300_MASK RT_GENMASK(15, 8)
-#define SDHCI_MAX_CURRENT_180_MASK RT_GENMASK(23, 16)
-#define SDHCI_MAX_CURRENT_MULTIPLIER 4
-
-/* 4C-4F reserved for more max current */
-
-#define SDHCI_SET_ACMD12_ERROR 0x50
-#define SDHCI_SET_INT_ERROR 0x52
-
-#define SDHCI_ADMA_ERROR 0x54
-
-/* 55-57 reserved */
-
-#define SDHCI_ADMA_ADDRESS 0x58
-#define SDHCI_ADMA_ADDRESS_HI 0x5C
-
-/* 60-FB reserved */
-
-#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
-#define SDHCI_PRESET_FOR_SDR12 0x66
-#define SDHCI_PRESET_FOR_SDR25 0x68
-#define SDHCI_PRESET_FOR_SDR50 0x6A
-#define SDHCI_PRESET_FOR_SDR104 0x6C
-#define SDHCI_PRESET_FOR_DDR50 0x6E
-#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
-#define SDHCI_PRESET_DRV_MASK RT_GENMASK(15, 14)
-#define BIT(nr) ((1) << (nr))
-
-#define SDHCI_PRESET_CLKGEN_SEL BIT(10)
-#define SDHCI_PRESET_SDCLK_FREQ_MASK RT_GENMASK(9, 0)
-
-#define SDHCI_SLOT_INT_STATUS 0xFC
-
-#define SDHCI_HOST_VERSION 0xFE
-#define SDHCI_VENDOR_VER_MASK 0xFF00
-#define SDHCI_VENDOR_VER_SHIFT 8
-#define SDHCI_SPEC_VER_MASK 0x00FF
-#define SDHCI_SPEC_VER_SHIFT 0
-#define SDHCI_SPEC_100 0
-#define SDHCI_SPEC_200 1
-#define SDHCI_SPEC_300 2
-#define SDHCI_SPEC_400 3
-#define SDHCI_SPEC_410 4
-#define SDHCI_SPEC_420 5
-
-/*
- * End of controller registers.
- */
-
-#define SDHCI_MAX_DIV_SPEC_200 256
-#define SDHCI_MAX_DIV_SPEC_300 2046
-
-/*
- * Host SDMA buffer boundary. Valid values from 4K to 512K in powers of 2.
- */
-#define SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024)
-#define ilog2(v) __rt_ffs(v)
-#define SDHCI_DEFAULT_BOUNDARY_ARG (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12)
-
-/* ADMA2 32-bit DMA descriptor size */
-#define SDHCI_ADMA2_32_DESC_SZ 8
-
-/* ADMA2 32-bit descriptor */
-struct sdhci_adma2_32_desc
-{
- rt_uint16_t cmd;
- rt_uint16_t len;
- rt_uint16_t addr;
-} rt_align(4);
-/* ADMA2 data alignment */
-#define SDHCI_ADMA2_ALIGN 4
-#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1)
-
-/*
- * ADMA2 descriptor alignment. Some controllers (e.g. Intel) require 8 byte
- * alignment for the descriptor table even in 32-bit DMA mode. Memory
- * allocation is at least 8 byte aligned anyway, so just stipulate 8 always.
- */
-#define SDHCI_ADMA2_DESC_ALIGN 8
-
-/*
- * ADMA2 64-bit DMA descriptor size
- * According to SD Host Controller spec v4.10, there are two kinds of
- * descriptors for 64-bit addressing mode: 96-bit Descriptor and 128-bit
- * Descriptor, if Host Version 4 Enable is set in the Host Control 2
- * register, 128-bit Descriptor will be selected.
- */
-#define SDHCI_ADMA2_64_DESC_SZ(host) ((host)->v4_mode ? 16 : 12)
-
-/*
- * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
- * aligned.
- */
-struct sdhci_adma2_64_desc
-{
- rt_uint16_t cmd;
- rt_uint16_t len;
- rt_uint16_t addr_lo;
- rt_uint16_t addr_hi;
-};
-
-#define ADMA2_TRAN_VALID 0x21
-#define ADMA2_NOP_END_VALID 0x3
-#define ADMA2_END 0x2
-
-/*
- * Maximum segments assuming a 512KiB maximum requisition size and a minimum
- * 4KiB page size. Note this also allows enough for multiple descriptors in
- * case of PAGE_SIZE >= 64KiB.
- */
-#define SDHCI_MAX_SEGS 128
-
-/* Allow for a command request and a data request at the same time */
-#define SDHCI_MAX_MRQS 2
-
-/*
- * 48bit command and 136 bit response in 100KHz clock could take upto 2.48ms.
- * However since the start time of the command, the time between
- * command and response, and the time between response and start of data is
- * not known, set the command transfer time to 10ms.
- */
-#define MMC_CMD_TRANSFER_TIME (10 * 1000000L) /* max 10 ms */
-
-
-enum sdhci_cookie
-{
- COOKIE_UNMAPPED,
- COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */
- COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */
-};
-
-struct sdhci_host
-{
- /* Data set by hardware interface driver */
- const char *hw_name; /* Hardware bus name */
-
- unsigned int quirks; /* Deviations from spec. */
-
- void *data_buf;
-/* Controller doesn't honor resets unless we touch the clock register */
-#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0)
-/* Controller has bad caps bits, but really supports DMA */
-#define SDHCI_QUIRK_FORCE_DMA (1 << 1)
-/* Controller doesn't like to be reset when there is no card inserted. */
-#define SDHCI_QUIRK_NO_CARD_NO_RESET (1 << 2)
-/* Controller doesn't like clearing the power reg before a change */
-#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1 << 3)
-/* Controller has an unusable DMA engine */
-#define SDHCI_QUIRK_BROKEN_DMA (1 << 5)
-/* Controller has an unusable ADMA engine */
-#define SDHCI_QUIRK_BROKEN_ADMA (1 << 6)
-/* Controller can only DMA from 32-bit aligned addresses */
-#define SDHCI_QUIRK_32BIT_DMA_ADDR (1 << 7)
-/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
-#define SDHCI_QUIRK_32BIT_DMA_SIZE (1 << 8)
-/* Controller can only ADMA chunks that are a multiple of 32 bits */
-#define SDHCI_QUIRK_32BIT_ADMA_SIZE (1 << 9)
-/* Controller needs to be reset after each request to stay stable */
-#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1 << 10)
-/* Controller needs voltage and power writes to happen separately */
-#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 11)
-/* Controller provides an incorrect timeout value for transfers */
-#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1 << 12)
-/* Controller has an issue with buffer bits for small transfers */
-#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1 << 13)
-/* Controller does not provide transfer-complete interrupt when not busy */
-#define SDHCI_QUIRK_NO_BUSY_IRQ (1 << 14)
-/* Controller has unreliable card detection */
-#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1 << 15)
-/* Controller reports inverted write-protect state */
-#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1 << 16)
-/* Controller has unusable command queue engine */
-#define SDHCI_QUIRK_BROKEN_CQE (1 << 17)
-/* Controller does not like fast PIO transfers */
-#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1 << 18)
-/* Controller does not have a LED */
-#define SDHCI_QUIRK_NO_LED (1 << 19)
-/* Controller has to be forced to use block size of 2048 bytes */
-#define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1 << 20)
-/* Controller cannot do multi-block transfers */
-#define SDHCI_QUIRK_NO_MULTIBLOCK (1 << 21)
-/* Controller can only handle 1-bit data transfers */
-#define SDHCI_QUIRK_FORCE_1_BIT_DATA (1 << 22)
-/* Controller needs 10ms delay between applying power and clock */
-#define SDHCI_QUIRK_DELAY_AFTER_POWER (1 << 23)
-/* Controller uses SDCLK instead of TMCLK for data timeouts */
-#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1 << 24)
-/* Controller reports wrong base clock capability */
-#define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1 << 25)
-/* Controller cannot support End Attribute in NOP ADMA descriptor */
-#define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1 << 26)
-/* Controller uses Auto CMD12 command to stop the transfer */
-#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1 << 28)
-/* Controller doesn't have HISPD bit field in HI-SPEED SD card */
-#define SDHCI_QUIRK_NO_HISPD_BIT (1 << 29)
-/* Controller treats ADMA descriptors with length 0000h incorrectly */
-#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1 << 30)
-/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
-#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1 << 31)
-
- unsigned int quirks2; /* More deviations from spec. */
-
-#define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1 << 0)
-#define SDHCI_QUIRK2_HOST_NO_CMD23 (1 << 1)
-/* The system physically doesn't support 1.8v, even if the host does */
-#define SDHCI_QUIRK2_NO_1_8_V (1 << 2)
-#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1 << 3)
-#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1 << 4)
-/* Controller has a non-standard host control register */
-#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1 << 5)
-/* Controller does not support HS200 */
-#define SDHCI_QUIRK2_BROKEN_HS200 (1 << 6)
-/* Controller does not support DDR50 */
-#define SDHCI_QUIRK2_BROKEN_DDR50 (1 << 7)
-/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */
-#define SDHCI_QUIRK2_STOP_WITH_TC (1 << 8)
-/* Controller does not support 64-bit DMA */
-#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1 << 9)
-/* need clear transfer mode register before send cmd */
-#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1 << 10)
-/* Capability register bit-63 indicates HS400 support */
-#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1 << 11)
-/* forced tuned clock */
-#define SDHCI_QUIRK2_TUNING_WORK_AROUND (1 << 12)
-/* disable the block count for single block transactions */
-#define SDHCI_QUIRK2_SUPPORT_SINGLE (1 << 13)
-/* Controller broken with using ACMD23 */
-#define SDHCI_QUIRK2_ACMD23_BROKEN (1 << 14)
-/* Broken Clock divider zero in controller */
-#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1 << 15)
-/* Controller has CRC in 136 bit Command Response */
-#define SDHCI_QUIRK2_RSP_136_HAS_CRC (1 << 16)
-/*
- * Disable HW timeout if the requested timeout is more than the maximum
- * obtainable timeout.
- */
-#define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT (1 << 17)
-/*
- * 32-bit block count may not support eMMC where upper bits of CMD23 are used
- * for other purposes. Consequently we support 16-bit block count by default.
- * Otherwise, SDHCI_QUIRK2_USE_32BIT_BLK_CNT can be selected to use 32-bit
- * block count.
- */
-#define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1 << 18)
-/* Issue CMD and DATA reset together */
-#define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1 << 19)
-
- int irq; /* Device IRQ */
- void *ioaddr; /* Mapped address */
- char *bounce_buffer; /* For packing SDMA reads/writes */
- rt_uint64_t bounce_addr;
- unsigned int bounce_buffer_size;
-
- const struct sdhci_ops *ops; /* Low level hw interface */
-
- /* Internal data */
- struct mmc_host *mmc; /* MMC structure */
- struct mmc_host_ops mmc_host_ops; /* MMC host ops */
- rt_uint64_t dma_mask; /* custom DMA mask */
-
- rt_spinlock_t lock;
- int flags; /* Host attributes */
-#define SDHCI_USE_SDMA (1 << 0) /* Host is SDMA capable */
-#define SDHCI_USE_ADMA (1 << 1) /* Host is ADMA capable */
-#define SDHCI_REQ_USE_DMA (1 << 2) /* Use DMA for this req. */
-#define SDHCI_DEVICE_DEAD (1 << 3) /* Device unresponsive */
-#define SDHCI_SDR50_NEEDS_TUNING (1 << 4) /* SDR50 needs tuning */
-#define SDHCI_AUTO_CMD12 (1 << 6) /* Auto CMD12 support */
-#define SDHCI_AUTO_CMD23 (1 << 7) /* Auto CMD23 support */
-#define SDHCI_PV_ENABLED (1 << 8) /* Preset value enabled */
-#define SDHCI_USE_64_BIT_DMA (1 << 12) /* Use 64-bit DMA */
-#define SDHCI_HS400_TUNING (1 << 13) /* Tuning for HS400 */
-#define SDHCI_SIGNALING_330 (1 << 14) /* Host is capable of 3.3V signaling */
-#define SDHCI_SIGNALING_180 (1 << 15) /* Host is capable of 1.8V signaling */
-#define SDHCI_SIGNALING_120 (1 << 16) /* Host is capable of 1.2V signaling */
-
- unsigned int version; /* SDHCI spec. version */
-
- unsigned int max_clk; /* Max possible freq (MHz) */
- unsigned int timeout_clk; /* Timeout freq (KHz) */
- rt_uint8_t max_timeout_count; /* Vendor specific max timeout count */
- unsigned int clk_mul; /* Clock Muliplier value */
-
- unsigned int clock; /* Current clock (MHz) */
- rt_uint8_t pwr; /* Current voltage */
- rt_uint8_t drv_type; /* Current UHS-I driver type */
- rt_bool_t reinit_uhs; /* Force UHS-related re-initialization */
-
- rt_bool_t runtime_suspended; /* Host is runtime suspended */
- rt_bool_t bus_on; /* Bus power prevents runtime suspend */
- rt_bool_t preset_enabled; /* Preset is enabled */
- rt_bool_t pending_reset; /* Cmd/data reset is pending */
- rt_bool_t irq_wake_enabled; /* IRQ wakeup is enabled */
- rt_bool_t v4_mode; /* Host Version 4 Enable */
- rt_bool_t use_external_dma; /* Host selects to use external DMA */
- rt_bool_t always_defer_done; /* Always defer to complete requests */
-
- struct rt_mmcsd_req *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */
- struct rt_mmcsd_cmd *cmd; /* Current command */
- struct rt_mmcsd_cmd *data_cmd; /* Current data command */
- struct rt_mmcsd_cmd *deferred_cmd; /* Deferred command */
- struct rt_mmcsd_data *data; /* Current data request */
- unsigned int data_early : 1; /* Data finished before cmd */
-
- unsigned int blocks; /* remaining PIO blocks */
-
- int sg_count; /* Mapped sg entries */
- int max_adma; /* Max. length in ADMA descriptor */
-
- void *adma_table; /* ADMA descriptor table */
- void *align_buffer; /* Bounce buffer */
-
- size_t adma_table_sz; /* ADMA descriptor table size */
- size_t align_buffer_sz; /* Bounce buffer size */
-
- rt_uint64_t adma_addr; /* Mapped ADMA descr. table */
- rt_uint64_t align_addr; /* Mapped bounce buffer */
-
- unsigned int desc_sz; /* ADMA current descriptor size */
- unsigned int alloc_desc_sz; /* ADMA descr. max size host supports */
-
- struct rt_workqueue *complete_wq; /* Request completion wq */
- struct rt_work complete_work; /* Request completion work */
-
- struct rt_workqueue *irq_wq;
- struct rt_work irq_work;
-
- struct rt_timer timer; /* Timer for timeouts */
- struct rt_timer data_timer; /* Timer for data timeouts */
-
- rt_uint32_t caps; /* CAPABILITY_0 */
- rt_uint32_t caps1; /* CAPABILITY_1 */
- rt_bool_t read_caps; /* Capability flags have been read */
-
- rt_bool_t sdhci_core_to_disable_vqmmc; /* sdhci core can disable vqmmc */
- unsigned int ocr_avail_sdio; /* OCR bit masks */
- unsigned int ocr_avail_sd;
- unsigned int ocr_avail_mmc;
- rt_uint32_t ocr_mask; /* available voltages */
-
- unsigned timing; /* Current timing */
-
- rt_uint32_t thread_isr;
-
- /* cached registers */
- rt_uint32_t ier;
-
- rt_bool_t cqe_on; /* CQE is operating */
- rt_uint32_t cqe_ier; /* CQE interrupt mask */
- rt_uint32_t cqe_err_ier; /* CQE error interrupt mask */
-
- rt_wqueue_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
- unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
-
- unsigned int tuning_count; /* Timer count for re-tuning */
- unsigned int tuning_mode; /* Re-tuning mode supported by host */
- unsigned int tuning_err; /* Error code for re-tuning */
-#define SDHCI_TUNING_MODE_1 0
-#define SDHCI_TUNING_MODE_2 1
-#define SDHCI_TUNING_MODE_3 2
- /* Delay (ms) between tuning commands */
- int tuning_delay;
- int tuning_loop_count;
-
- /* Host SDMA buffer boundary. */
- rt_uint32_t sdma_boundary;
-
- /* Host ADMA table count */
- rt_uint32_t adma_table_cnt;
- rt_uint64_t data_timeout;
-
- unsigned long private[];
-};
-
-struct sdhci_ops
-{
- rt_uint32_t (*read_l)(struct sdhci_host *host, int reg);
- rt_uint16_t (*read_w)(struct sdhci_host *host, int reg);
- rt_uint8_t (*read_b)(struct sdhci_host *host, int reg);
- void (*write_l)(struct sdhci_host *host, rt_uint32_t val, int reg);
- void (*write_w)(struct sdhci_host *host, rt_uint16_t val, int reg);
- void (*write_b)(struct sdhci_host *host, rt_uint8_t val, int reg);
- void (*set_clock)(struct sdhci_host *host, unsigned int clock);
- void (*set_power)(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd);
-
- rt_uint32_t (*irq)(struct sdhci_host *host, rt_uint32_t intmask);
-
- int (*set_dma_mask)(struct sdhci_host *host);
- int (*enable_dma)(struct sdhci_host *host);
- unsigned int (*get_max_clock)(struct sdhci_host *host);
- unsigned int (*get_min_clock)(struct sdhci_host *host);
- /* get_timeout_clock should return clk rate in unit of Hz */
- unsigned int (*get_timeout_clock)(struct sdhci_host *host);
- unsigned int (*get_max_timeout_count)(struct sdhci_host *host);
- void (*set_timeout)(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd);
- void (*set_bus_width)(struct sdhci_host *host, int width);
- void (*platform_send_init_74_clocks)(struct sdhci_host *host,
- rt_uint8_t power_mode);
- unsigned int (*get_ro)(struct sdhci_host *host);
- void (*reset)(struct sdhci_host *host, rt_uint8_t mask);
- int (*platform_execute_tuning)(struct sdhci_host *host, rt_uint32_t opcode);
- void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
- void (*hw_reset)(struct sdhci_host *host);
- void (*adma_workaround)(struct sdhci_host *host, rt_uint32_t intmask);
- void (*card_event)(struct sdhci_host *host);
- void (*voltage_switch)(struct sdhci_host *host);
- void (*adma_write_desc)(struct sdhci_host *host, void **desc,
- rt_uint64_t addr, int len, unsigned int cmd);
- void (*copy_to_bounce_buffer)(struct sdhci_host *host,
- struct rt_mmcsd_data *data,
- unsigned int length);
- void (*request_done)(struct sdhci_host *host,
- struct rt_mmcsd_req *mrq);
- void (*dump_vendor_regs)(struct sdhci_host *host);
-};
-
-static inline rt_uint8_t rt_uint8_t_read(const volatile void *addr)
-{
- return *(const volatile rt_uint8_t *)addr;
-}
-
-static inline rt_uint16_t rt_uint16_t_read(const volatile void *addr)
-{
- return *(const volatile rt_uint16_t *)addr;
-}
-
-static inline rt_uint32_t rt_uint32_t_read(const volatile void *addr)
-{
- return *(const volatile rt_uint32_t *)addr;
-}
-
-static inline void rt_uint8_t_write(rt_uint8_t value, volatile void *addr)
-{
- *(volatile rt_uint8_t *)addr = value;
-}
-
-static inline void rt_uint16_t_write(rt_uint16_t value, volatile void *addr)
-{
- *(volatile rt_uint16_t *)addr = value;
-}
-
-static inline void rt_uint32_t_write(rt_uint32_t value, volatile void *addr)
-{
- *(volatile rt_uint32_t *)addr = value;
-}
-
-#define readb(c) rt_uint8_t_read(c)
-#define readw(c) rt_uint16_t_read(c)
-#define readl(c) rt_uint32_t_read(c)
-#define readsb(p, d, l) ({ __raw_readsb(p,d,l); __iormb(); })
-#define readsw(p, d, l) ({ __raw_readsw(p,d,l); __iormb(); })
-#define readsl(p, d, l) ({ __raw_readsl(p,d,l); __iormb(); })
-
-#define writeb(v, c) rt_uint8_t_write(v, c)
-#define writew(v, c) rt_uint16_t_write(v, c)
-#define writel(v, c) rt_uint32_t_write(v, c)
-#define writesb(p, d, l) ({ __iowmb(); __raw_writesb(p,d,l); })
-#define writesw(p, d, l) ({ __iowmb(); __raw_writesw(p,d,l); })
-#define writesl(p, d, l) ({ __iowmb(); __raw_writesl(p,d,l); })
-
-static inline void sdhci_writel(struct sdhci_host *host, rt_uint32_t val, int reg)
-{
- if (host->ops->write_l)
- host->ops->write_l(host, val, reg);
- else
- writel(val, host->ioaddr + reg);
-}
-
-static inline void sdhci_writew(struct sdhci_host *host, rt_uint16_t val, int reg)
-{
- if (host->ops->write_w)
- host->ops->write_w(host, val, reg);
- else
- writew(val, host->ioaddr + reg);
-}
-
-static inline void sdhci_writeb(struct sdhci_host *host, rt_uint8_t val, int reg)
-{
- if (host->ops->write_b)
- host->ops->write_b(host, val, reg);
- else
- writeb(val, host->ioaddr + reg);
-}
-
-static inline rt_uint32_t sdhci_readl(struct sdhci_host *host, int reg)
-{
- if (host->ops->read_l)
- return host->ops->read_l(host, reg);
- else
- return readl(host->ioaddr + reg);
-}
-
-static inline rt_uint16_t sdhci_readw(struct sdhci_host *host, int reg)
-{
- if (host->ops->read_w)
- return host->ops->read_w(host, reg);
- else
- return readw(host->ioaddr + reg);
-}
-
-static inline rt_uint8_t sdhci_readb(struct sdhci_host *host, int reg)
-{
- if (host->ops->read_b)
- return host->ops->read_b(host, reg);
- else
- return readb(host->ioaddr + reg);
-}
-
-struct sdhci_host *sdhci_alloc_host(struct rt_device *dev, size_t priv_size);
-void sdhci_free_host(struct sdhci_host *host);
-
-static inline void *sdhci_priv(struct sdhci_host *host)
-{
- return host->private;
-}
-
-void __sdhci_read_caps(struct sdhci_host *host, const rt_uint16_t *ver,
- const rt_uint32_t *caps, const rt_uint32_t *caps1);
-int sdhci_setup_host(struct sdhci_host *host);
-void sdhci_cleanup_host(struct sdhci_host *host);
-int __sdhci_add_host(struct sdhci_host *host);
-int sdhci_add_host(struct sdhci_host *host);
-void sdhci_remove_host(struct sdhci_host *host, int dead);
-
-static inline void sdhci_read_caps(struct sdhci_host *host)
-{
- __sdhci_read_caps(host, NULL, NULL, NULL);
-}
-
-rt_uint16_t sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
- unsigned int *actual_clock);
-void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
-void sdhci_enable_clk(struct sdhci_host *host, rt_uint16_t clk);
-void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd);
-void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
- unsigned char mode,
- unsigned short vdd);
-void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd);
-int sdhci_get_cd_nogpio(struct mmc_host *mmc);
-void sdhci_request(struct mmc_host *mmc, struct rt_mmcsd_req *mrq);
-int sdhci_request_atomic(struct mmc_host *mmc, struct rt_mmcsd_req *mrq);
-void sdhci_set_bus_width(struct sdhci_host *host, int width);
-void sdhci_reset(struct sdhci_host *host, rt_uint8_t mask);
-void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
-int sdhci_execute_tuning(struct mmc_host *mmc, rt_uint32_t opcode);
-int __sdhci_execute_tuning(struct sdhci_host *host, rt_uint32_t opcode);
-void sdhci_set_ios(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios);
-int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- struct rt_mmcsd_io_cfg *ios);
-void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable);
-void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
- rt_uint64_t addr, int len, unsigned int cmd);
-
-void sdhci_cqe_enable(struct mmc_host *mmc);
-void sdhci_cqe_disable(struct mmc_host *mmc, rt_bool_t recovery);
-rt_bool_t sdhci_cqe_irq(struct sdhci_host *host, rt_uint32_t intmask, int *cmd_error,
- int *data_error);
-
-void sdhci_dumpregs(struct sdhci_host *host);
-void sdhci_enable_v4_mode(struct sdhci_host *host);
-
-void sdhci_start_tuning(struct sdhci_host *host);
-void sdhci_end_tuning(struct sdhci_host *host);
-void sdhci_reset_tuning(struct sdhci_host *host);
-void sdhci_send_tuning(struct sdhci_host *host, rt_uint32_t opcode);
-void sdhci_abort_tuning(struct sdhci_host *host, rt_uint32_t opcode);
-void sdhci_switch_external_dma(struct sdhci_host *host, rt_bool_t en);
-void sdhci_set_data_timeout_irq(struct sdhci_host *host, rt_bool_t enable);
-void __sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd);
-
-#endif /* __SDHCI_HW_H */
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h
deleted file mode 100644
index 934e5c5bb1..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_dma.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#ifndef __SDHCI_DMA_H__
-#define __SDHCI_DMA_H__
-
-#include "ioremap.h"
-#include <mm_aspace.h>
-enum dma_data_direction
-{
- DMA_BIDIRECTIONAL = 0,
- DMA_TO_DEVICE = 1,
- DMA_FROM_DEVICE = 2,
- DMA_NONE = 3,
-};
-#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
-
-int dma_set_mask_and_coherent(struct rt_device *dev, rt_uint64_t mask);
-unsigned long virt_to_phys(volatile void *address);
-void *dma_alloc_coherent(struct rt_device *dev, size_t size,
- rt_uint64_t *dma_handle);
-void dma_free_coherent(struct rt_device *dev, size_t size,
- void *cpu_addr, unsigned long dma_handle);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h
deleted file mode 100644
index 23d3a1fc65..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_host.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#ifndef __SDHCI_MMC_H__
-#define __SDHCI_MMC_H__
-
-#include <rtthread.h>
-#include <drivers/mmcsd_cmd.h>
-#include <drivers/dev_mmcsd_core.h>
-#include <drivers/mmcsd_host.h>
-#include "sdhci_dma.h"
-#define mmc_dev(x) ((x)->parent)
-
-#define MMC_SEND_TUNING_BLOCK_HS200 SEND_TUNING_BLOCK_HS200
-#define MMC_SEND_TUNING_BLOCK SEND_TUNING_BLOCK
-#define MMC_STOP_TRANSMISSION STOP_TRANSMISSION
-#define MMC_BUS_TEST_R 14 /* adtc R1 */
-#define MMC_WRITE_MULTIPLE_BLOCK WRITE_MULTIPLE_BLOCK
-#define MMC_READ_MULTIPLE_BLOCK READ_MULTIPLE_BLOCK
-
-#define MMC_TIMING_UHS_DDR50 MMCSD_TIMING_UHS_DDR50
-#define MMC_TIMING_UHS_SDR50 MMCSD_TIMING_UHS_SDR50
-#define MMC_TIMING_MMC_HS200 MMCSD_TIMING_MMC_HS200
-#define MMC_TIMING_MMC_HS400 MMCSD_TIMING_MMC_HS400
-#define MMC_TIMING_UHS_SDR104 MMCSD_TIMING_UHS_SDR104
-#define MMC_TIMING_UHS_SDR25 MMCSD_TIMING_UHS_SDR25
-#define MMC_TIMING_MMC_DDR52 MMCSD_TIMING_MMC_DDR52
-#define MMC_TIMING_UHS_SDR12 MMCSD_TIMING_UHS_SDR12
-#define MMC_TIMING_SD_HS MMCSD_TIMING_SD_HS
-#define MMC_TIMING_MMC_HS MMCSD_TIMING_MMC_HS
-
-#define MMC_POWER_OFF MMCSD_POWER_OFF
-#define MMC_POWER_UP MMCSD_POWER_UP
-#define MMC_POWER_ON MMCSD_POWER_ON
-#define MMC_POWER_UNDEFINED 3
-
-#define MMC_SET_DRIVER_TYPE_B 0
-#define MMC_SET_DRIVER_TYPE_A 1
-#define MMC_SET_DRIVER_TYPE_C 2
-#define MMC_SET_DRIVER_TYPE_D 3
-
-#define MMC_SIGNAL_VOLTAGE_330 0
-#define MMC_SIGNAL_VOLTAGE_180 1
-#define MMC_SIGNAL_VOLTAGE_120 2
-
-#define MMC_RSP_PRESENT (1 << 16)
-#define MMC_RSP_136 (1 << 17) /* 136 bit response */
-#define MMC_RSP_CRC (1 << 18) /* expect valid crc */
-#define MMC_RSP_BUSY (1 << 19) /* card may send busy */
-#define MMC_RSP_OPCODE (1 << 20) /* response contains opcode */
-
-/*
- * These are the native response types, and correspond to valid bit
- * patterns of the above flags. One additional valid pattern
- * is all zeros, which means we don't expect a response.
- */
-#define MMC_RSP_NONE (0)
-#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
-#define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
-#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
-#define MMC_RSP_R3 (MMC_RSP_PRESENT)
-#define MMC_RSP_R4 (MMC_RSP_PRESENT)
-#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
-#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
-#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
-
-#define MMC_CMD_ADTC CMD_ADTC
-
-#define MMC_BUS_WIDTH_8 MMCSD_BUS_WIDTH_8
-#define MMC_BUS_WIDTH_4 MMCSD_BUS_WIDTH_4
-#define MMC_BUS_WIDTH_1 MMCSD_BUS_WIDTH_1
-
-#define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */
-#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */
-enum mmc_blk_status
-{
- MMC_BLK_SUCCESS = 0,
- MMC_BLK_PARTIAL,
- MMC_BLK_CMD_ERR,
- MMC_BLK_RETRY,
- MMC_BLK_ABORT,
- MMC_BLK_DATA_ERR,
- MMC_BLK_ECC_ERR,
- MMC_BLK_NOMEDIUM,
- MMC_BLK_NEW_REQUEST,
-};
-
-/************************************************************************************************ */
-
-#define MMC_NUM_CLK_PHASES (MMC_TIMING_MMC_HS400 + 1)
-
-struct mmc_host;
-
-struct mmc_host_ops
-{
- /*
- * It is optional for the host to implement pre_req and post_req in
- * order to support double buffering of requests (prepare one
- * request while another request is active).
- * pre_req() must always be followed by a post_req().
- * To undo a call made to pre_req(), call post_req() with
- * a nonzero err condition.
- */
- void (*post_req)(struct mmc_host *host, struct rt_mmcsd_req *req,
- int err);
- void (*pre_req)(struct mmc_host *host, struct rt_mmcsd_req *req);
- void (*request)(struct mmc_host *host, struct rt_mmcsd_req *req);
-
- /*
- * Avoid calling the next three functions too often or in a "fast
- * path", since underlaying controller might implement them in an
- * expensive and/or slow way. Also note that these functions might
- * sleep, so don't call them in the atomic contexts!
- */
-
- /*
- * Notes to the set_ios callback:
- * ios->clock might be 0. For some controllers, setting 0Hz
- * as any other frequency works. However, some controllers
- * explicitly need to disable the clock. Otherwise e.g. voltage
- * switching might fail because the SDCLK is not really quiet.
- */
- void (*set_ios)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
-
- /*
- * Return values for the get_ro callback should be:
- * 0 for a read/write card
- * 1 for a read-only card
- * -ENOSYS when not supported (equal to NULL callback)
- * or a negative errno value when something bad happened
- */
- int (*get_ro)(struct mmc_host *host);
-
- /*
- * Return values for the get_cd callback should be:
- * 0 for a absent card
- * 1 for a present card
- * -ENOSYS when not supported (equal to NULL callback)
- * or a negative errno value when something bad happened
- */
- int (*get_cd)(struct mmc_host *host);
-
- void (*enable_sdio_irq)(struct mmc_host *host, int enable);
- /* Mandatory callback when using MMC_CAP2_SDIO_IRQ_NOTHREAD. */
- void (*ack_sdio_irq)(struct mmc_host *host);
-
- int (*start_signal_voltage_switch)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
-
- /* Check if the card is pulling dat[0:3] low */
- int (*card_busy)(struct mmc_host *host);
-
- /* The tuning command opcode value is different for SD and eMMC cards */
- int (*execute_tuning)(struct mmc_host *host, unsigned opcode);
-
- /* Prepare HS400 target operating frequency depending host driver */
- int (*prepare_hs400_tuning)(struct mmc_host *host, struct rt_mmcsd_io_cfg *ios);
-
- /* Prepare switch to DDR during the HS400 init sequence */
- int (*hs400_prepare_ddr)(struct mmc_host *host);
-
- /* Prepare for switching from HS400 to HS200 */
- void (*hs400_downgrade)(struct mmc_host *host);
-
- /* Complete selection of HS400 */
- void (*hs400_complete)(struct mmc_host *host);
-
- /* Prepare enhanced strobe depending host driver */
- void (*hs400_enhanced_strobe)(struct mmc_host *host,
- struct rt_mmcsd_io_cfg *ios);
-
- /* Reset the eMMC card via RST_n */
- void (*hw_reset)(struct mmc_host *host);
- void (*card_event)(struct mmc_host *host);
-};
-
-struct regulator;
-struct mmc_pwrseq;
-
-struct mmc_supply
-{
- struct regulator *vmmc; /* Card power supply */
- struct regulator *vqmmc; /* Optional Vccq supply */
-};
-
-struct mmc_ctx
-{
- struct task_struct *task;
-};
-
-/* VDD voltage 3.3 ~ 3.4 */
-#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
-#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
-
-#define MMC_CAP2_HS200_1_8V_SDR MMCSD_SUP_HS200_1V8
-#define MMC_CAP_4_BIT_DATA MMCSD_BUSWIDTH_4
-#define MMC_CAP_8_BIT_DATA MMCSD_BUSWIDTH_8
-#define MMC_CAP2_HS200 MMCSD_SUP_HS200
-#define MMC_CAP_MMC_HIGHSPEED MMCSD_SUP_HIGHSPEED
-#define MMC_CAP_SD_HIGHSPEED MMCSD_SUP_HIGHSPEED
-#define MMC_CAP_1_8V_DDR MMCSD_SUP_DDR_1V8
-#define MMC_CAP_3_3V_DDR MMCSD_SUP_DDR_3V3
-#define MMC_CAP_1_2V_DDR MMCSD_SUP_DDR_1V2
-#define MMC_CAP_NONREMOVABLE MMCSD_SUP_NONREMOVABLE
-
-
-#define MMC_CAP_UHS_DDR50 0
-#define MMC_CAP2_HS400 0
-#define MMC_CAP_UHS_SDR50 0
-#define MMC_CAP_UHS_SDR25 0
-#define MMC_CAP_UHS_SDR12 0
-#define MMC_CAP_UHS_SDR104 0
-#define MMC_CAP_UHS 0
-#define MMC_CAP2_HSX00_1_8V 0
-#define MMC_CAP2_HS400_ES 0
-#define MMC_CAP_NEEDS_POLL 0
-#define MMC_CAP2_HSX00_1_2V 0
-#define MMC_CAP2_HS400_1_8V 0
-#define MMC_CAP_DRIVER_TYPE_D 0
-#define MMC_CAP_DRIVER_TYPE_C 0
-#define MMC_SET_DRIVER_TYPE_B 0
-#define MMC_CAP_DRIVER_TYPE_A 0
-#define MMC_CAP2_SDIO_IRQ_NOTHREAD 0
-#define MMC_CAP_CMD23 0
-#define MMC_CAP_SDIO_IRQ 0
-
-#define MMC_CAP2_NO_SDIO (1 << 19)
-#define MMC_CAP2_NO_SD (1 << 21)
-#define MMC_CAP2_NO_MMC (1 << 22)
-#define MMC_CAP2_CQE (1 << 23)
-
-#define MMC_VDD_165_195 VDD_165_195
-#define MMC_VDD_20_21 VDD_20_21
-#define MMC_VDD_29_30 VDD_29_30
-#define MMC_VDD_30_31 VDD_30_31
-#define MMC_VDD_32_33 VDD_32_33
-#define MMC_VDD_33_34 VDD_33_34
-
-
-struct mmc_host
-{
- struct rt_mmcsd_host rthost;
- struct rt_device *parent;
- int index;
- const struct mmc_host_ops *ops;
- unsigned int f_min;
- unsigned int f_max;
- unsigned int f_init;
- rt_uint32_t ocr_avail;
- rt_uint32_t ocr_avail_sdio; /* SDIO-specific OCR */
- rt_uint32_t ocr_avail_sd; /* SD-specific OCR */
- rt_uint32_t ocr_avail_mmc; /* MMC-specific OCR */
- struct wakeup_source *ws; /* Enable consume of uevents */
- rt_uint32_t max_current_330;
- rt_uint32_t max_current_300;
- rt_uint32_t max_current_180;
- rt_uint32_t caps; /* Host capabilities */
-
- rt_uint32_t caps2; /* More host capabilities */
-
-
- /* host specific block data */
- unsigned int max_seg_size; /* see blk_queue_max_segment_size */
- unsigned short max_segs; /* see blk_queue_max_segments */
- unsigned short unused;
- unsigned int max_req_size; /* maximum number of bytes in one req */
- unsigned int max_blk_size; /* maximum size of one mmc block */
- unsigned int max_blk_count; /* maximum number of blocks in one req */
- unsigned int max_busy_timeout; /* max busy timeout in ms */
- struct rt_mmcsd_io_cfg ios; /* current io bus settings */
- unsigned int retune_period;
- /* group bitfields together to minimize padding */
- unsigned int use_spi_crc : 1;
- unsigned int claimed : 1; /* host exclusively claimed */
- unsigned int doing_init_tune : 1; /* initial tuning in progress */
- unsigned int can_retune : 1; /* re-tuning can be used */
- unsigned int doing_retune : 1; /* re-tuning in progress */
- unsigned int retune_now : 1; /* do re-tuning at next req */
- unsigned int retune_paused : 1; /* re-tuning is temporarily disabled */
- unsigned int retune_crc_disable : 1; /* don't trigger retune upon crc */
- unsigned int can_dma_map_merge : 1; /* merging can be used */
- unsigned int vqmmc_enabled : 1; /* vqmmc regulator is enabled */
-
- int need_retune; /* re-tuning is needed */
- int hold_retune; /* hold off re-tuning */
- rt_bool_t trigger_card_event; /* card_event necessary */
- unsigned int sdio_irqs;
- rt_bool_t sdio_irq_pending;
-
- struct led_trigger *led; /* activity led */
-
- struct mmc_supply supply;
-
-
- /* Ongoing data transfer that allows commands during transfer */
- struct rt_mmcsd_req *ongoing_mrq;
-
-
- unsigned int actual_clock; /* Actual HC clock rate */
- rt_uint32_t pm_caps;
- unsigned long private[];
-};
-
-
-static inline int mmc_card_is_removable(struct mmc_host *host)
-{
- return !(host->caps & MMC_CAP_NONREMOVABLE);
-}
-
-struct device_node;
-
-struct mmc_host *mmc_alloc_host(int extra, struct rt_device *);
-int mmc_add_host(struct mmc_host *);
-void mmc_remove_host(struct mmc_host *);
-void mmc_free_host(struct mmc_host *);
-int mmc_of_parse(struct mmc_host *host);
-int mmc_of_parse_voltage(struct mmc_host *host, rt_uint32_t *mask);
-
-static inline void *mmc_priv(struct mmc_host *host)
-{
- return (void *)host->private;
-}
-
-
-#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI)
-
-#define mmc_dev(x) ((x)->parent)
-#define mmc_classdev(x) (&(x)->class_dev)
-#define mmc_hostname(x) (x->parent->parent.name)
-
-void mmc_detect_change(struct mmc_host *, unsigned long delay);
-void mmc_request_done(struct mmc_host *, struct rt_mmcsd_req *);
-void mmc_command_done(struct mmc_host *host, struct rt_mmcsd_req *mrq);
-
-void mmc_cqe_request_done(struct mmc_host *host, struct rt_mmcsd_req *mrq);
-
-/*
- * May be called from host driver's system/runtime suspend/resume callbacks,
- * to know if SDIO IRQs has been claimed.
- */
-static inline rt_bool_t sdio_irq_claimed(struct mmc_host *host)
-{
- return host->sdio_irqs > 0;
-}
-
-static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
- struct regulator *supply,
- unsigned short vdd_bit)
-{
- return 0;
-}
-
-int mmc_regulator_get_supply(struct mmc_host *mmc);
-int mmc_regulator_enable_vqmmc(struct mmc_host *mmc);
-void mmc_regulator_disable_vqmmc(struct mmc_host *mmc);
-
-void mmc_retune_timer_stop(struct mmc_host *host);
-
-static inline void mmc_retune_needed(struct mmc_host *host)
-{
- if (host->can_retune)
- host->need_retune = 1;
-}
-
-static inline rt_bool_t mmc_can_retune(struct mmc_host *host)
-{
- return host->can_retune == 1;
-}
-
-static inline rt_bool_t mmc_doing_retune(struct mmc_host *host)
-{
- return host->doing_retune == 1;
-}
-
-static inline rt_bool_t mmc_doing_tune(struct mmc_host *host)
-{
- return host->doing_retune == 1 || host->doing_init_tune == 1;
-}
-
-static inline int mmc_get_dma_dir(struct rt_mmcsd_data *data)
-{
- return data->flags & DATA_DIR_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-}
-
-static inline rt_bool_t mmc_op_multi(rt_uint32_t opcode)
-{
- return opcode == MMC_WRITE_MULTIPLE_BLOCK || opcode == MMC_READ_MULTIPLE_BLOCK;
-}
-
-static inline rt_bool_t mmc_op_tuning(rt_uint32_t opcode)
-{
- return opcode == MMC_SEND_TUNING_BLOCK || opcode == MMC_SEND_TUNING_BLOCK_HS200;
-}
-
-int mmc_gpio_get_cd(struct mmc_host *host);
-void mmc_detect_change(struct mmc_host *host, unsigned long delay);
-int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios);
-rt_bool_t mmc_can_gpio_ro(struct mmc_host *host);
-int mmc_gpio_get_ro(struct mmc_host *host);
-
-int mmc_send_tuning(struct mmc_host *host, rt_uint32_t opcode, int *cmd_error);
-int mmc_send_abort_tuning(struct mmc_host *host, rt_uint32_t opcode);
-int mmc_of_parse(struct mmc_host *host);
-
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h
deleted file mode 100644
index 2205b1bac3..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/include/sdhci_misc.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#ifndef __SDHCI_MISC_H__
-#define __SDHCI_MISC_H__
-
-#include "sdhci_host.h"
-
-#define __BF_FIELD_CHECK(...)
-#define __bf_shf(x) (__builtin_ffsll(x) - 1)
-#define FIELD_GET(_mask, _reg) \
- ({ \
- __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \
- (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
- })
-
-#define FIELD_PREP(_mask, _val) \
- ({ \
- __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \
- ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \
- })
-
-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-
-#define min_t(type, x, y) (((type)x < (type)y) ? x : y)
-#define max_t(type, x, y) (((type)x > (type)y) ? x : y)
-#define min(x, y) ((x) < (y) ? (x) : (y))
-
-#define from_timer(var, callback_timer, timer_fieldname) \
- container_of(callback_timer, typeof(*var), timer_fieldname)
-
-
-#define le32_to_cpu(x) (x)
-#define le16_to_cpu(x) (x)
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define lower_32_bits(n) ((rt_uint32_t)((n) & 0xffffffff))
-#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
-
-#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-
-#define do_div(n, base) ({ \
- uint32_t __base = (base); \
- uint32_t __rem; \
- __rem = ((uint64_t)(n)) % __base; \
- (n) = ((uint64_t)(n)) / __base; \
- __rem; \
-})
-
-#define fallthrough \
- do { \
- } while (0)
-
-int regulator_is_supported_voltage(struct regulator *regulator,
- int min_uV, int max_uV);
-int regulator_enable(struct regulator *regulator);
-rt_bool_t mmc_can_gpio_cd(struct mmc_host *host);
-
-struct regulator
-{
- const char *supply_name;
-};
-
-int regulator_get_current_limit(struct regulator *regulator);
-
-int regulator_enable(struct regulator *regulator);
-
-void regulator_disable(struct regulator *regulator);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c
deleted file mode 100644
index 4272b24dea..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci-platform/sdhci-platform.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#include "sdhci-platform.h"
-
-static const struct sdhci_ops sdhci_pltfm_ops = {
- .set_clock = sdhci_set_clock,
- .set_bus_width = sdhci_set_bus_width,
- .reset = sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
-};
-
-void sdhci_get_property(struct rt_platform_device *pdev)
-{
- struct rt_device *dev = &pdev->parent;
- struct sdhci_host *host = pdev->priv;
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- rt_uint32_t bus_width;
-
- if (rt_dm_dev_prop_read_bool(dev, "sdhci,auto-cmd12"))
- host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
-
- if (rt_dm_dev_prop_read_bool(dev, "sdhci,1-bit-only") || (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) == 0 && bus_width == 1))
- host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-
- if (rt_dm_dev_prop_read_bool(dev, "broken-cd"))
- host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-
- if (rt_dm_dev_prop_read_bool(dev, "no-1-8-v"))
- host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
-
- rt_dm_dev_prop_read_u32(dev, "clock-frequency", &pltfm_host->clock);
-
- if (rt_dm_dev_prop_read_bool(dev, "keep-power-in-suspend"))
- host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
-
- if (rt_dm_dev_prop_read_bool(dev, "wakeup-source") || rt_dm_dev_prop_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
- host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
-}
-
-struct sdhci_host *sdhci_pltfm_init(struct rt_platform_device *pdev,
- const struct sdhci_pltfm_data *pdata,
- size_t priv_size)
-{
- struct sdhci_host *host;
- struct rt_device *dev = &pdev->parent;
- void *ioaddr;
- int irq;
-
- ioaddr = rt_dm_dev_iomap(dev, 0);
- if (!ioaddr)
- {
- return RT_NULL;
- }
-
- irq = rt_dm_dev_get_irq(dev, 0);
- if (irq < 0)
- {
- return RT_NULL;
- }
- host = sdhci_alloc_host(dev, priv_size);
- if (!host)
- {
- return RT_NULL;
- }
- host->irq = irq;
- host->ioaddr = ioaddr;
- host->hw_name = rt_dm_dev_get_name(dev);
-
- if (pdata && pdata->ops)
- host->ops = pdata->ops;
- else
- host->ops = &sdhci_pltfm_ops;
- if (pdata)
- {
- host->quirks = pdata->quirks;
- host->quirks2 = pdata->quirks2;
- }
-
- pdev->priv = host;
-
- return host;
-}
-
-int sdhci_pltfm_init_and_add_host(struct rt_platform_device *pdev,
- const struct sdhci_pltfm_data *pdata,
- size_t priv_size)
-{
- struct sdhci_host *host;
- int ret = 0;
-
- host = sdhci_pltfm_init(pdev, pdata, priv_size);
- if (!host)
- return -RT_ERROR;
-
- sdhci_get_property(pdev);
-
- ret = sdhci_add_host(host);
- if (ret)
- sdhci_pltfm_free(pdev);
-
- return ret;
-}
-
-void sdhci_pltfm_free(struct rt_platform_device *pdev)
-{
- struct sdhci_host *host = pdev->priv;
-
- sdhci_free_host(host);
-}
-
-void sdhci_pltfm_remove(struct rt_platform_device *pdev)
-{
- struct sdhci_host *host = pdev->priv;
- int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
-
- sdhci_remove_host(host, dead);
- sdhci_pltfm_free(pdev);
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c
deleted file mode 100644
index 7d5d85f50f..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/sdhci.c
+++ /dev/null
@@ -1,3606 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-
-#include <rtthread.h>
-#include "sdhci.h"
-#include <string.h>
-#define DBG_TAG "SDHCI"
-#ifdef DRV_DEBUG
-#define DBG_LVL DBG_LOG
-#else
-#define DBG_LVL DBG_INFO
-#endif /* DRV_DEBUG */
-#include <rtdbg.h>
-static unsigned int debug_quirks = 0;
-static unsigned int debug_quirks2;
-/********************************************************* */
-/* cmd */
-/********************************************************* */
-
-
-void read_reg(struct sdhci_host *host)
-{
- rt_kprintf("0x00 addddddddddddd = %x \n", sdhci_readl(host, 0x00));
- rt_kprintf("0x04 EMMC_BLOCKSIZE = %x \n", sdhci_readw(host, 0x04));
- rt_kprintf("0x06 EMMC_BLOCKCOUNT = %x \n", sdhci_readw(host, 0x06));
- rt_kprintf("0x08 SDHCI_ARGUMENT = %x \n", sdhci_readl(host, 0x08));
- rt_kprintf("0x0c EMMC_XFER_MODE = %x \n", sdhci_readw(host, 0x0c));
- rt_kprintf("0x0e SDHCI_COMMAND = %x \n", sdhci_readw(host, 0x0e));
- rt_kprintf("0x24 SDHCI_PRESENT_STATE = %x \n", sdhci_readl(host, 0x24));
- rt_kprintf("0x28 SDHCI_HOST_CONTROL = %x \n", sdhci_readb(host, 0x28));
- rt_kprintf("0x29 SDHCI_POWER_CONTROL = %x \n", sdhci_readb(host, 0x29));
- rt_kprintf("0x2a EMMC_BGAP_CTRL = %x \n", sdhci_readb(host, 0x2a));
- rt_kprintf("0x2c EMMC_CLK_CTRL = %x \n", sdhci_readw(host, 0x2c));
- rt_kprintf("0x2e EMMC_TOUT_CTRL = %x \n", sdhci_readb(host, 0x2e));
- rt_kprintf("0x2f EMMC_SW_RST = %x \n", sdhci_readb(host, 0x2f));
- rt_kprintf("0x30 SDHCI_INT_STATUS = %x \n", sdhci_readw(host, 0x30));
- rt_kprintf("0x32 SDHCI_ERR_INT_STATUS = %x \n", sdhci_readw(host, 0x32));
- rt_kprintf("0x34 SDHCI_INT_ENABLE = %x \n", sdhci_readw(host, 0x34));
- rt_kprintf("0x36 EMMC ERROR INT STATEN = %x \n", sdhci_readw(host, 0x36));
- rt_kprintf("0x38 EMMC NORMAL INT SIGNAL EN= %x \n", sdhci_readw(host, 0x38));
- rt_kprintf("0x3a EMMC ERROR INT SIGNAL EN = %x \n", sdhci_readw(host, 0x3a));
- rt_kprintf("0x3c EMMC_AUTO_CMD_STAT = %x \n", sdhci_readw(host, 0x3c));
- rt_kprintf("0x3e EMMC_HOST_CTRL2 = %x \n", sdhci_readw(host, 0x3e));
- rt_kprintf("0x40 EMMC_CAPABILITIES1 = %x \n", sdhci_readl(host, 0x40));
- rt_kprintf("0x44 EMMC_CAPABILITIES2 = %x \n", sdhci_readl(host, 0x44));
- rt_kprintf("0x52 EMMC_FORC_ERR_INT_STAT = %x \n", sdhci_readw(host, 0x52));
- rt_kprintf("0x54 EMMC_ADMA_ERR_STAT = %x \n", sdhci_readb(host, 0x54));
- rt_kprintf("0x58 EMMC_ADMA_SA = %x \n", sdhci_readl(host, 0x58));
- rt_kprintf("0x66 EMMC_PRESET_SDR12 = %x \n", sdhci_readw(host, 0x66));
- rt_kprintf("0x68 EMMC_PRESET_SDR25 = %x \n", sdhci_readw(host, 0x68));
- rt_kprintf("0x6a EMMC_PRESET_SDR50 = %x \n", sdhci_readw(host, 0x6a));
- rt_kprintf("0x6c EMMC_PRESET_SDR104 = %x \n", sdhci_readw(host, 0x6c));
- rt_kprintf("0x6e EMMC_PRESET_DDR50 = %x \n", sdhci_readw(host, 0x6e));
- rt_kprintf("0x78 EMMC_ADMA_ID = %x \n", sdhci_readl(host, 0x78));
- rt_kprintf("0xfe EMMC_HOST_CNTRL_VERS = %x \n", sdhci_readw(host, 0xfe));
-
-}
-static inline rt_bool_t sdhci_has_requests(struct sdhci_host *host)
-{
- return host->cmd || host->data_cmd;
-}
-
-static inline rt_bool_t sdhci_auto_cmd23(struct sdhci_host *host,
- struct rt_mmcsd_req *mrq)
-{
- return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);
-}
-
-static inline rt_bool_t sdhci_auto_cmd12(struct sdhci_host *host,
- struct rt_mmcsd_req *mrq)
-{
- return !mrq->sbc && (host->flags & SDHCI_AUTO_CMD12) && !mrq->cap_cmd_during_tfr;
-}
-
-static inline rt_bool_t sdhci_manual_cmd23(struct sdhci_host *host,
- struct rt_mmcsd_req *mrq)
-{
- return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23);
-}
-
-static inline rt_bool_t sdhci_data_line_cmd(struct rt_mmcsd_cmd *cmd)
-{
- return cmd->data || cmd->flags & MMC_RSP_BUSY;
-}
-
-void sdhci_set_data_timeout_irq(struct sdhci_host *host, rt_bool_t enable)
-{
- if (enable)
- host->ier |= SDHCI_INT_DATA_TIMEOUT;
- else
- host->ier &= ~SDHCI_INT_DATA_TIMEOUT;
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-}
-
-void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
-{
- rt_uint16_t ctrl_2;
-
- ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- /* Select Bus Speed Mode for host */
- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- if ((timing == MMC_TIMING_MMC_HS200) || (timing == MMC_TIMING_UHS_SDR104))
- ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
- else if (timing == MMC_TIMING_UHS_SDR12)
- ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
- else if (timing == MMC_TIMING_UHS_SDR25)
- ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
- else if (timing == MMC_TIMING_UHS_SDR50)
- ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
- else if ((timing == MMC_TIMING_UHS_DDR50) || (timing == MMC_TIMING_MMC_DDR52))
- ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
- else if (timing == MMC_TIMING_MMC_HS400)
- ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */
- sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-}
-
-void sdhci_set_bus_width(struct sdhci_host *host, int width)
-{
- rt_uint8_t ctrl;
-
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
- if (width == MMC_BUS_WIDTH_8)
- {
- ctrl &= ~SDHCI_CTRL_4BITBUS;
- ctrl |= SDHCI_CTRL_8BITBUS;
- }
- else
- {
- if (host->mmc->caps & MMC_CAP_8_BIT_DATA)
- ctrl &= ~SDHCI_CTRL_8BITBUS;
- if (width == MMC_BUS_WIDTH_4)
- ctrl |= SDHCI_CTRL_4BITBUS;
- else
- ctrl &= ~SDHCI_CTRL_4BITBUS;
- }
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-}
-
-static inline rt_bool_t sdhci_can_64bit_dma(struct sdhci_host *host)
-{
- /*
- * According to SD Host Controller spec v4.10, bit[27] added from
- * version 4.10 in Capabilities Register is used as 64-bit System
- * Address support for V4 mode.
- */
- if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
- return host->caps & SDHCI_CAN_64BIT_V4;
-
- return host->caps & SDHCI_CAN_64BIT;
-}
-
-static void sdhci_do_enable_v4_mode(struct sdhci_host *host)
-{
- rt_uint16_t ctrl2;
-
- ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (ctrl2 & SDHCI_CTRL_V4_MODE)
- return;
-
- ctrl2 |= SDHCI_CTRL_V4_MODE;
- sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
-}
-
-void sdhci_cleanup_host(struct sdhci_host *host)
-{
- struct mmc_host *mmc = host->mmc;
-
- if (host->sdhci_core_to_disable_vqmmc)
- regulator_disable(mmc->supply.vqmmc);
-
- if (host->align_buffer)
- dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + host->adma_table_sz, host->align_buffer,
- host->align_addr);
-
- host->adma_table = NULL;
- host->align_buffer = NULL;
-}
-
-static void sdhci_set_default_irqs(struct sdhci_host *host)
-{
- host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
-
- if (host->tuning_mode == SDHCI_TUNING_MODE_2 || host->tuning_mode == SDHCI_TUNING_MODE_3)
- host->ier |= SDHCI_INT_RETUNE;
-
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-}
-
-
-static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd,
- rt_uint16_t *mode)
-{
- rt_bool_t use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && (cmd->cmd_code != SD_IO_RW_EXTENDED);
- rt_bool_t use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq);
- rt_uint16_t ctrl2;
-
- /*
- * In case of Version 4.10 or later, use of 'Auto CMD Auto
- * Select' is recommended rather than use of 'Auto CMD12
- * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
- * here because some controllers (e.g sdhci-of-dwmshc) expect it.
- */
- if (host->version >= SDHCI_SPEC_410 && host->v4_mode && (use_cmd12 || use_cmd23))
- {
- *mode |= SDHCI_TRNS_AUTO_SEL;
-
- ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (use_cmd23)
- ctrl2 |= SDHCI_CMD23_ENABLE;
- else
- ctrl2 &= ~SDHCI_CMD23_ENABLE;
- sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
-
- return;
- }
-
- /*
- * If we are sending CMD23, CMD12 never gets sent
- * on successful completion (so no Auto-CMD12).
- */
- if (use_cmd12)
- *mode |= SDHCI_TRNS_AUTO_CMD12;
- else if (use_cmd23)
- *mode |= SDHCI_TRNS_AUTO_CMD23;
-}
-
-
-static rt_bool_t sdhci_present_error(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd, rt_bool_t present)
-{
- if (!present || host->flags & SDHCI_DEVICE_DEAD)
- {
- cmd->err = -ENOMEDIUM;
- return RT_TRUE;
- }
-
- return RT_FALSE;
-}
-
-static rt_uint16_t sdhci_get_preset_value(struct sdhci_host *host)
-{
- rt_uint16_t preset = 0;
-
- switch (host->timing)
- {
- case MMC_TIMING_MMC_HS:
- case MMC_TIMING_SD_HS:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
- break;
- case MMC_TIMING_UHS_SDR12:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
- break;
- case MMC_TIMING_UHS_SDR25:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
- break;
- case MMC_TIMING_UHS_SDR50:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
- break;
- case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_MMC_HS200:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
- break;
- case MMC_TIMING_UHS_DDR50:
- case MMC_TIMING_MMC_DDR52:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
- break;
- case MMC_TIMING_MMC_HS400:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400);
- break;
- default:
- preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
- break;
- }
- return preset;
-}
-
-static void sdhci_set_card_detection(struct sdhci_host *host, rt_bool_t enable)
-{
- rt_uint32_t present;
-
- if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || !mmc_card_is_removable(host->mmc))
- return;
-
- if (enable)
- {
- present = sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT;
-
- host->ier |= present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
- }
- else
- {
- host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
- }
-
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-}
-
-static void sdhci_enable_card_detection(struct sdhci_host *host)
-{
- sdhci_set_card_detection(host, RT_TRUE);
-}
-
-static inline int sdhci_external_dma_init(struct sdhci_host *host)
-{
- return -EOPNOTSUPP;
-}
-
-static inline void sdhci_external_dma_release(struct sdhci_host *host)
-{
-}
-
-static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd)
-{
- /* This should never happen */
-}
-
-static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd)
-{
-}
-
-static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host,
- struct rt_mmcsd_data *data)
-{
- return NULL;
-}
-
-/********************************************************* */
-/* reset */
-/********************************************************* */
-enum sdhci_reset_reason
-{
- SDHCI_RESET_FOR_INIT,
- SDHCI_RESET_FOR_REQUEST_ERROR,
- SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY,
- SDHCI_RESET_FOR_TUNING_ABORT,
- SDHCI_RESET_FOR_CARD_REMOVED,
- SDHCI_RESET_FOR_CQE_RECOVERY,
-};
-
-static rt_bool_t sdhci_needs_reset(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
-{
- return (!(host->flags & SDHCI_DEVICE_DEAD) && ((mrq->cmd && mrq->cmd->err) || (mrq->sbc && mrq->sbc->err) || (mrq->data && mrq->data->stop && mrq->data->stop->err) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));
-}
-
-static rt_bool_t sdhci_do_reset(struct sdhci_host *host, rt_uint8_t mask)
-{
- if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET)
- {
- struct mmc_host *mmc = host->mmc;
-
- if (!mmc->ops->get_cd(mmc))
- return RT_FALSE;
- }
- if (host->ops->reset)
- {
- host->ops->reset(host, mask);
- }
- return RT_TRUE;
-}
-
-static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
-{
- if (host->quirks2 & SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER)
- {
- sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- return;
- }
-
- switch (reason)
- {
- case SDHCI_RESET_FOR_INIT:
- sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- break;
- case SDHCI_RESET_FOR_REQUEST_ERROR:
- case SDHCI_RESET_FOR_TUNING_ABORT:
- case SDHCI_RESET_FOR_CARD_REMOVED:
- case SDHCI_RESET_FOR_CQE_RECOVERY:
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
- break;
- case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY:
- sdhci_do_reset(host, SDHCI_RESET_DATA);
- break;
- }
-}
-
-#define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r)
-
-static void sdhci_reset_for_all(struct sdhci_host *host)
-{
- if (sdhci_do_reset(host, SDHCI_RESET_ALL))
- {
- if (host->flags & (SDHCI_USE_SDMA))
- {
- if (host->ops->enable_dma)
- host->ops->enable_dma(host);
- }
- /* Resetting the controller clears many */
- host->preset_enabled = RT_FALSE;
- }
-}
-
-
-static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
-{
- if (host->bus_on)
- return;
- host->bus_on = RT_TRUE;
-}
-
-static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
-{
- if (!host->bus_on)
- return;
- host->bus_on = RT_FALSE;
-}
-
-void sdhci_reset(struct sdhci_host *host, rt_uint8_t mask)
-{
- ssize_t timeout;
-
- sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
-
- if (mask & SDHCI_RESET_ALL)
- {
- host->clock = 0;
- /* Reset-all turns off SD Bus Power */
- if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- sdhci_runtime_pm_bus_off(host);
- }
-
- timeout = rt_tick_from_millisecond(150);
- while (1)
- {
- timeout = timeout - rt_tick_get();
-
-
- if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
- break;
- if (timeout < 0)
- {
- rt_kprintf("%s: Reset 0x%x never completed.\n",
- mmc_hostname(host->mmc), (int)mask);
- sdhci_dumpregs(host);
- return;
- }
- rt_hw_us_delay(10);
- }
-}
-
-/********************************************************* */
-/* data */
-/********************************************************* */
-static void sdhci_initialize_data(struct sdhci_host *host,
- struct rt_mmcsd_data *data)
-{
- /* Sanity checks */
- LOG_D(data->blksize * data->blks > 524288);
- LOG_D(data->blksize > host->mmc->max_blk_size);
- LOG_D(data->blks > 65535);
-
- host->data = data;
- host->data_early = 0;
- host->data->bytes_xfered = 0;
-}
-
-static rt_ubase_t sdhci_sdma_address(struct sdhci_host *host)
-{
- return (rt_ubase_t)rt_kmem_v2p(host->data->buf);
-}
-
-static void sdhci_set_adma_addr(struct sdhci_host *host, rt_uint32_t addr)
-{
- sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS);
- if (host->flags & SDHCI_USE_64_BIT_DMA)
- sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI);
-}
-
-static void sdhci_set_sdma_addr(struct sdhci_host *host, rt_uint32_t addr)
-{
- if (host->v4_mode)
- sdhci_set_adma_addr(host, addr);
- else
- sdhci_writel(host, addr, SDHCI_DMA_ADDRESS);
-}
-
-static void sdhci_config_dma(struct sdhci_host *host)
-{
- rt_uint8_t ctrl;
- rt_uint16_t ctrl2;
-
- if (host->version < SDHCI_SPEC_200)
- return;
-
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
- /*
- * Always adjust the DMA selection as some controllers
- * (e.g. JMicron) can't do PIO properly when the selection
- * is ADMA.
- */
- ctrl &= ~SDHCI_CTRL_DMA_MASK;
- if (!(host->flags & SDHCI_REQ_USE_DMA))
- goto out;
-
- /* Note if DMA Select is zero then SDMA is selected */
- if (host->flags & SDHCI_USE_64_BIT_DMA)
- {
- /*
- * If v4 mode, all supported DMA can be 64-bit addressing if
- * controller supports 64-bit system address, otherwise only
- * ADMA can support 64-bit addressing.
- */
- if (host->v4_mode)
- {
- ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl2 |= SDHCI_CTRL_64BIT_ADDR;
- sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
- }
- }
-
-out:
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-}
-
-static inline void sdhci_set_block_info(struct sdhci_host *host,
- struct rt_mmcsd_data *data)
-{
- /* Set the DMA boundary value and block size */
- sdhci_writew(host,
- SDHCI_MAKE_BLKSZ(7, data->blksize),
- SDHCI_BLOCK_SIZE);
- /*
- * For Version 4.10 onwards, if v4 mode is enabled, 32-bit Block Count
- * can be supported, in that case 16-bit block count register must be 0.
- */
- if (host->version >= SDHCI_SPEC_410 && host->v4_mode && (host->quirks2 & SDHCI_QUIRK2_USE_32BIT_BLK_CNT))
- {
- if (sdhci_readw(host, SDHCI_BLOCK_COUNT))
- sdhci_writew(host, 0, SDHCI_BLOCK_COUNT);
- sdhci_writew(host, data->blks, SDHCI_32BIT_BLK_CNT);
- }
- else
- {
- sdhci_writew(host, data->blks, SDHCI_BLOCK_COUNT);
- }
-}
-
-static void sdhci_set_transfer_irqs(struct sdhci_host *host)
-{
- rt_uint32_t pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
- rt_uint32_t dma_irqs = SDHCI_INT_DMA_END;
-
- if (host->flags & SDHCI_REQ_USE_DMA)
- host->ier = (host->ier & ~pio_irqs) | dma_irqs;
- else
- host->ier = (host->ier & ~dma_irqs) | pio_irqs;
-
- if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12))
- host->ier |= SDHCI_INT_AUTO_CMD_ERR;
- else
- host->ier &= ~SDHCI_INT_AUTO_CMD_ERR;
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-}
-
-static void sdhci_prepare_data(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
-{
- struct rt_mmcsd_data *data = cmd->data;
-
- sdhci_initialize_data(host, data);
-
- if (host->flags & SDHCI_USE_SDMA)
- {
- unsigned int length_mask, offset_mask;
-
- host->flags |= SDHCI_REQ_USE_DMA;
-
- /*
- * FIXME: This doesn't account for merging when mapping the
- * scatterlist.
- *
- * The assumption here being that alignment and lengths are
- * the same after DMA mapping to device address space.
- */
- length_mask = 0;
- offset_mask = 0;
- if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
- length_mask = 3;
- if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
- offset_mask = 3;
-
-
- if (length_mask | offset_mask)
- {
- host->flags &= ~SDHCI_REQ_USE_DMA;
- }
- }
-
- sdhci_config_dma(host);
-
- if (host->flags & SDHCI_REQ_USE_DMA)
- {
- if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE)
- rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, data->buf, data->blks * data->blksize);
- else
- rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, data->buf, data->blks * data->blksize);
-
- sdhci_set_sdma_addr(host, sdhci_sdma_address(host));
- }
-
- if (!(host->flags & SDHCI_REQ_USE_DMA))
- {
- host->blocks = data->blks;
- }
-
- sdhci_set_transfer_irqs(host);
-
- sdhci_set_block_info(host, data);
-}
-
-static void sdhci_set_mrq_done(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
-{
- int i;
-
- for (i = 0; i < SDHCI_MAX_MRQS; i++)
- {
- if (host->mrqs_done[i] == mrq)
- {
- LOG_D(1);
- return;
- }
- }
-
- for (i = 0; i < SDHCI_MAX_MRQS; i++)
- {
- if (!host->mrqs_done[i])
- {
- host->mrqs_done[i] = mrq;
- break;
- }
- }
-
- LOG_D(i >= SDHCI_MAX_MRQS);
-}
-
-static inline rt_bool_t sdhci_defer_done(struct sdhci_host *host,
- struct rt_mmcsd_req *mrq)
-{
- struct rt_mmcsd_data *data = mrq->data;
-
- return host->pending_reset || host->always_defer_done || ((host->flags & SDHCI_REQ_USE_DMA) && data && data->host_cookie == COOKIE_MAPPED);
-}
-
-
-/********************************************************* */
-/* pio */
-/********************************************************* */
-
-static void sdhci_read_block_pio(struct sdhci_host *host,void **buf)
-{
- rt_uint32_t scratch;
- size_t len;
- rt_uint32_t blksize = host->data->blksize;
- while (blksize)
- {
- len = min(4U, blksize);
-
- scratch = sdhci_readl(host, SDHCI_BUFFER);
- rt_memcpy(*buf, &scratch, len);
-
- *buf += len;
- blksize -= len;
- }
-}
-
-static void sdhci_write_block_pio(struct sdhci_host *host,void **buf)
-{
- size_t blksize, len;
- rt_uint32_t scratch;
- LOG_D("PIO writing\n");
-
- blksize = host->data->blksize;
- scratch = 0;
- while (blksize)
- {
- len = min(4U, blksize);
- rt_memcpy(&scratch, *buf, len);
- *buf += len;
- blksize -= len;
- sdhci_writel(host, scratch, SDHCI_BUFFER);
- }
-}
-
-static void sdhci_transfer_pio(struct sdhci_host *host)
-{
- rt_uint32_t mask;
-
- if (host->blocks == 0)
- return;
-
- if (host->data->flags & DATA_DIR_READ)
- mask = SDHCI_DATA_AVAILABLE;
- else
- mask = SDHCI_SPACE_AVAILABLE;
-
- /*
- * Some controllers (JMicron JMB38x) mess up the buffer bits
- * for transfers < 4 bytes. As long as it is just one block,
- * we can ignore the bits.
- */
- if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && (host->data->blks == 1))
- {
- mask = ~0;
- }
- void *buf = (void *)host->data->buf;
- while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
- {
- if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY)
- rt_hw_us_delay(100);
-
- if (host->data->flags & DATA_DIR_READ)
- sdhci_read_block_pio(host,&buf);
- else
- sdhci_write_block_pio(host,&buf);
-
- host->data->blks--;
- if (host->data->blks == 0)
- break;
-
- /* host->data->buf += host->data->blksize;*/
- }
-}
-
-/********************************************************* */
-/* config */
-/********************************************************* */
-
-
-static rt_bool_t sdhci_timing_has_preset(unsigned char timing)
-{
- switch (timing)
- {
- case MMC_TIMING_UHS_SDR12:
- case MMC_TIMING_UHS_SDR25:
- case MMC_TIMING_UHS_SDR50:
- case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_UHS_DDR50:
- case MMC_TIMING_MMC_DDR52:
- return RT_TRUE;
- }
- return RT_FALSE;
-}
-
-static rt_bool_t sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
-{
- return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && sdhci_timing_has_preset(timing);
-}
-
-static rt_bool_t sdhci_presetable_values_change(struct sdhci_host *host, struct rt_mmcsd_io_cfg *ios)
-{
- /*
- * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
- * Frequency. Check if preset values need to be enabled, or the Driver
- * Strength needs updating. Note, clock changes are handled separately.
- */
- return !host->preset_enabled && (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
-}
-
-
-static void sdhci_enable_preset_value(struct sdhci_host *host, rt_bool_t enable)
-{
- /* Host Controller v3.00 defines preset value registers */
- if (host->version < SDHCI_SPEC_300)
- return;
-
- /*
- * We only enable or disable Preset Value if they are not already
- * enabled or disabled respectively. Otherwise, we bail out.
- */
- if (host->preset_enabled != enable)
- {
- rt_uint16_t ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
- if (enable)
- ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
- else
- ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
-
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- if (enable)
- host->flags |= SDHCI_PV_ENABLED;
- else
- host->flags &= ~SDHCI_PV_ENABLED;
-
- host->preset_enabled = enable;
- }
-}
-
-static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd)
-{
- struct mmc_host *mmc = host->mmc;
-
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
-
- if (mode != MMC_POWER_OFF)
- sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
- else
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-}
-
-void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd)
-{
- rt_uint8_t pwr = 0;
-
- if (mode != MMC_POWER_OFF)
- {
- switch (1 << vdd)
- {
- case MMC_VDD_165_195:
- /*
- * Without a regulator, SDHCI does not support 2.0v
- * so we only get here if the driver deliberately
- * added the 2.0v range to ocr_avail. Map it to 1.8v
- * for the purpose of turning on the power.
- */
- case MMC_VDD_20_21:
- pwr = SDHCI_POWER_180;
- break;
- case MMC_VDD_29_30:
- case MMC_VDD_30_31:
- pwr = SDHCI_POWER_300;
- break;
- case MMC_VDD_32_33:
- case MMC_VDD_33_34:
- /*
- * 3.4 ~ 3.6V are valid only for those platforms where it's
- * known that the voltage range is supported by hardware.
- */
- case MMC_VDD_34_35:
- case MMC_VDD_35_36:
- pwr = SDHCI_POWER_330;
- break;
- default:
- break;
- }
- }
-
- if (host->pwr == pwr)
- return;
-
- host->pwr = pwr;
-
- if (pwr == 0)
- {
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- sdhci_runtime_pm_bus_off(host);
- }
- else
- {
- /*
- * Spec says that we should clear the power reg before setting
- * a new value. Some controllers don't seem to like this though.
- */
- if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-
- /*
- * At least the Marvell CaFe chip gets confused if we set the
- * voltage and set turn on power at the same time, so set the
- * voltage first.
- */
- if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-
- pwr |= SDHCI_POWER_ON;
-
- sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-
- if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- sdhci_runtime_pm_bus_on(host);
-
- /*
- * Some controllers need an extra 10ms delay of 10ms before
- * they can apply clock after applying power
- */
- if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
- rt_thread_mdelay(10);
- }
-}
-
-void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
- unsigned short vdd)
-{
- if (!host->mmc->supply.vmmc)
- sdhci_set_power_noreg(host, mode, vdd);
- else
- sdhci_set_power_reg(host, mode, vdd);
-}
-
-
-int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- struct rt_mmcsd_io_cfg *ios)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_uint16_t ctrl;
- int ret;
-
- /*
- * Signal Voltage Switching is only applicable for Host Controllers
- * v3.00 and above.
- */
- if (host->version < SDHCI_SPEC_300)
- return 0;
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
- switch (ios->signal_voltage)
- {
- case MMC_SIGNAL_VOLTAGE_330:
- if (!(host->flags & SDHCI_SIGNALING_330))
- return -EINVAL;
- /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
- ctrl &= ~SDHCI_CTRL_VDD_180;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- if (!mmc->supply.vqmmc)
- {
- ret = mmc_regulator_set_vqmmc(mmc, ios);
- if (ret < 0)
- {
- return -EIO;
- }
- }
- /* Wait for 5ms */
- rt_thread_mdelay(5);
- /* 3.3V regulator output should be stable within 5 ms */
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (!(ctrl & SDHCI_CTRL_VDD_180))
- return 0;
- return -EAGAIN;
- case MMC_SIGNAL_VOLTAGE_180:
- if (!(host->flags & SDHCI_SIGNALING_180))
- return -EINVAL;
- if (!mmc->supply.vqmmc)
- {
- ret = mmc_regulator_set_vqmmc(mmc, ios);
- if (ret < 0)
- {
- LOG_D("%s: Switching to 1.8V signalling voltage failed\n",
- mmc_hostname(mmc));
- return -EIO;
- }
- }
-
- /*
- * Enable 1.8V Signal Enable in the Host Control2
- * register
- */
- ctrl |= SDHCI_CTRL_VDD_180;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- /* Some controller need to do more when switching */
- if (host->ops->voltage_switch)
- host->ops->voltage_switch(host);
-
- /* 1.8V regulator output should be stable within 5 ms */
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (ctrl & SDHCI_CTRL_VDD_180)
- return 0;
-
- LOG_D("%s: 1.8V regulator output did not become stable\n",
- mmc_hostname(mmc));
-
- return -EAGAIN;
- case MMC_SIGNAL_VOLTAGE_120:
- if (!(host->flags & SDHCI_SIGNALING_120))
- return -EINVAL;
- if (!mmc->supply.vqmmc)
- {
- ret = mmc_regulator_set_vqmmc(mmc, ios);
- if (ret < 0)
- {
- LOG_D("%s: Switching to 1.2V signalling voltage failed\n",
- mmc_hostname(mmc));
- return -EIO;
- }
- }
- return 0;
- default:
- /* No signal voltage switch required */
- return 0;
- }
-}
-
-
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- int gpio_cd = mmc_gpio_get_cd(mmc);
-
- if (host->flags & SDHCI_DEVICE_DEAD)
- return 0;
-
- /* If nonremovable, assume that the card is always present. */
- if (!mmc_card_is_removable(mmc))
- return 1;
-
- /*
- * Try slot gpio detect, if defined it take precedence
- * over build in controller functionality
- */
- if (gpio_cd >= 0)
- return !!gpio_cd;
-
- /* If polling, assume that the card is always present. */
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- return 1;
-
- /* Host native card detect */
- return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
-}
-
-static int sdhci_check_ro(struct sdhci_host *host)
-{
- int is_readonly;
- rt_base_t flags;
- flags = rt_spin_lock_irqsave(&host->lock);
-
- if (host->flags & SDHCI_DEVICE_DEAD)
- is_readonly = 0;
- else if (host->ops->get_ro)
- is_readonly = host->ops->get_ro(host);
- else if (mmc_can_gpio_ro(host->mmc))
- is_readonly = mmc_gpio_get_ro(host->mmc);
- else
- is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
- & SDHCI_WRITE_PROTECT);
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- /* This quirk needs to be replaced by a callback-function later */
- return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? !is_readonly : is_readonly;
-}
-
-#define SAMPLE_COUNT 5
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- int i, ro_count;
-
- if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
- return sdhci_check_ro(host);
-
- ro_count = 0;
- for (i = 0; i < SAMPLE_COUNT; i++)
- {
- if (sdhci_check_ro(host))
- {
- if (++ro_count > SAMPLE_COUNT / 2)
- return 1;
- }
- rt_thread_mdelay(30);
- }
- return 0;
-}
-
-static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
-{
- if (!(host->flags & SDHCI_DEVICE_DEAD))
- {
- if (enable)
- host->ier |= SDHCI_INT_CARD_INT;
- else
- host->ier &= ~SDHCI_INT_CARD_INT;
-
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
-}
-
-static void sdhci_ack_sdio_irq(struct mmc_host *mmc)
-{
- rt_base_t flags;
- struct sdhci_host *host = mmc_priv(mmc);
- flags = rt_spin_lock_irqsave(&host->lock);
- sdhci_enable_sdio_irq_nolock(host, RT_TRUE);
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void sdhci_del_timer(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
-{
- if (sdhci_data_line_cmd(mrq->cmd))
- rt_timer_stop(&host->data_timer);
- else
- rt_timer_stop(&host->timer);
-}
-
-static unsigned int sdhci_target_timeout(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd,
- struct rt_mmcsd_data *data)
-{
- unsigned int target_timeout;
-
- /* timeout in us */
- if (!data)
- {
- target_timeout = cmd->busy_timeout * 1000;
- }
- else
- {
- target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000);
- if (host->clock && data->timeout_clks)
- {
- rt_uint32_t val;
-
- /*
- * data->timeout_clks is in units of clock cycles.
- * host->clock is in Hz. target_timeout is in us.
- * Hence, us = 1000000 * cycles / Hz. Round up.
- */
- val = 1000000ULL * data->timeout_clks;
- if (do_div(val, host->clock))
- target_timeout++;
- target_timeout += val;
- }
- }
-
- return target_timeout;
-}
-
-static rt_uint8_t sdhci_calc_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd,
- rt_bool_t *too_big)
-{
- rt_uint8_t count;
- struct rt_mmcsd_data *data;
- unsigned target_timeout, current_timeout;
-
- *too_big = RT_FALSE;
-
- /*
- * If the host controller provides us with an incorrect timeout
- * value, just skip the check and use the maximum. The hardware may take
- * longer to time out, but that's much better than having a too-short
- * timeout value.
- */
- if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
- return host->max_timeout_count;
-
- /* Unspecified command, assume max */
- if (cmd == NULL)
- return host->max_timeout_count;
-
- data = cmd->data;
- /* Unspecified timeout, assume max */
- if (!data && !cmd->busy_timeout)
- return host->max_timeout_count;
-
- /* timeout in us */
- target_timeout = sdhci_target_timeout(host, cmd, data);
-
- /*
- * Figure out needed cycles.
- * We do this in steps in order to fit inside a 32 bit int.
- * The first step is the minimum timeout, which will have a
- * minimum resolution of 6 bits:
- * (1) 2^13*1000 > 2^22,
- * (2) host->timeout_clk < 2^16
- * =>
- * (1) / (2) > 2^6
- */
- count = 0;
- current_timeout = (1 << 13) * 1000 / host->timeout_clk;
- while (current_timeout < target_timeout)
- {
- count++;
- current_timeout <<= 1;
- if (count > host->max_timeout_count)
- {
- if (!(host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT))
- LOG_D("Too large timeout 0x%x requested for CMD%d!\n",
- count, cmd->cmd_code);
- count = host->max_timeout_count;
- *too_big = RT_TRUE;
- break;
- }
- }
-
- return count;
-}
-
-static void sdhci_calc_sw_timeout(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd)
-{
- struct rt_mmcsd_data *data = cmd->data;
- struct mmc_host *mmc = host->mmc;
- struct rt_mmcsd_io_cfg *ios = &mmc->ios;
- unsigned char bus_width = 1 << ios->bus_width;
- unsigned int blksz;
- unsigned int freq;
- rt_uint64_t target_timeout;
- rt_uint64_t transfer_time;
-
- target_timeout = sdhci_target_timeout(host, cmd, data);
- target_timeout *= 1000L;
-
- if (data)
- {
- blksz = data->blksize;
- freq = mmc->actual_clock ?: host->clock;
- transfer_time = (rt_uint64_t)blksz * 1000000000L * (8 / bus_width);
- do_div(transfer_time, freq);
- /* multiply by '2' to account for any unknowns */
- transfer_time = transfer_time * 2;
- /* calculate timeout for the entire data */
- host->data_timeout = data->blks * target_timeout + transfer_time;
- }
- else
- {
- host->data_timeout = target_timeout;
- }
-
- if (host->data_timeout)
- host->data_timeout += MMC_CMD_TRANSFER_TIME;
-}
-
-
-void __sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
-{
- rt_bool_t too_big = RT_FALSE;
- rt_uint8_t count = sdhci_calc_timeout(host, cmd, &too_big);
-
- if (too_big && host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT)
- {
- sdhci_calc_sw_timeout(host, cmd);
- sdhci_set_data_timeout_irq(host, RT_FALSE);
- }
- else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT))
- {
- sdhci_set_data_timeout_irq(host, RT_FALSE);
- }
-
- sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
-}
-
-static void sdhci_set_timeout(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
-{
- if (host->ops->set_timeout)
- host->ops->set_timeout(host, cmd);
- else
- __sdhci_set_timeout(host, cmd);
-}
-
-static void sdhci_mod_timer(struct sdhci_host *host, struct rt_mmcsd_req *mrq,
- unsigned long timeout)
-{
- if (sdhci_data_line_cmd(mrq->cmd))
- {
- rt_tick_t tick = rt_tick_get();
-
- if (timeout < tick)
- {
- timeout = tick;
- }
- tick = timeout - tick;
-
- rt_timer_stop(&host->data_timer);
- rt_timer_control(&host->data_timer, RT_TIMER_CTRL_SET_TIME, &tick);
- rt_timer_start(&host->data_timer);
- }
- else
- {
- rt_tick_t tick = rt_tick_get();
-
- if (timeout < tick)
- {
- timeout = tick;
- }
- tick = timeout - tick;
-
- rt_timer_stop(&host->timer);
- rt_timer_control(&host->timer, RT_TIMER_CTRL_SET_TIME, &tick);
- rt_timer_start(&host->timer);
- }
-}
-
-static void __sdhci_finish_mrq(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
-{
- if (host->cmd && host->cmd->mrq == mrq)
- host->cmd = NULL;
-
- if (host->data_cmd && host->data_cmd->mrq == mrq)
- host->data_cmd = NULL;
-
- if (host->deferred_cmd && host->deferred_cmd->mrq == mrq)
- host->deferred_cmd = NULL;
-
- if (host->data && host->data->mrq == mrq)
- host->data = NULL;
-
- if (sdhci_needs_reset(host, mrq))
- host->pending_reset = RT_TRUE;
-
- sdhci_set_mrq_done(host, mrq);
-
- sdhci_del_timer(host, mrq);
-}
-
-static void sdhci_finish_mrq(struct sdhci_host *host, struct rt_mmcsd_req *mrq)
-{
- __sdhci_finish_mrq(host, mrq);
-
- rt_workqueue_submit_work(host->complete_wq, &host->complete_work, 0);
-}
-
-static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
-{
- if (host->data_cmd)
- {
- host->data_cmd->err = err;
- sdhci_finish_mrq(host, host->data_cmd->mrq);
- }
-
- if (host->cmd)
- {
- host->cmd->err = err;
- sdhci_finish_mrq(host, host->cmd->mrq);
- }
-}
-
-static void sdhci_card_event(struct mmc_host *mmc)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_uint32_t flags;
- int present;
-
- /* First check if client has provided their own card event */
- if (host->ops->card_event)
- host->ops->card_event(host);
-
- present = mmc->ops->get_cd(mmc);
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- /* Check sdhci_has_requests() first in case we are runtime suspended */
- if (sdhci_has_requests(host) && !present)
- {
- rt_kprintf("%s: Card removed during transfer!\n",
- mmc_hostname(mmc));
- rt_kprintf("%s: Resetting controller.\n",
- mmc_hostname(mmc));
-
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
- sdhci_error_out_mrqs(host, -ENOMEDIUM);
- }
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static int sdhci_card_busy(struct mmc_host *mmc)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_uint32_t present_state;
-
- /* Check whether DAT[0] is 0 */
- present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
-
- return !(present_state & SDHCI_DATA_0_LVL_MASK);
-}
-
-
-static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_uint32_t flags;
-
- flags = rt_spin_lock_irqsave(&host->lock);
- host->flags |= SDHCI_HS400_TUNING;
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- return 0;
-}
-
-
-static void sdhci_set_transfer_mode(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd)
-{
- rt_uint16_t mode = 0;
- struct rt_mmcsd_data *data = cmd->data;
-
- if (data == NULL)
- {
- if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD)
- {
- /* must not clear SDHCI_TRANSFER_MODE when tuning */
- if (!mmc_op_tuning(cmd->cmd_code))
- sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
- }
- else
- {
- /* clear Auto CMD settings for no data CMDs */
- mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
- sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
- }
- return;
- }
-
-
- if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE))
- mode = SDHCI_TRNS_BLK_CNT_EN;
-
- if (mmc_op_multi(cmd->cmd_code) || data->blks > 1)
- {
- mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;
- sdhci_auto_cmd_select(host, cmd, &mode);
- if (sdhci_auto_cmd23(host, cmd->mrq))
- sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);
- }
-
- if (data->flags & DATA_DIR_READ)
- mode |= SDHCI_TRNS_READ;
- if (host->flags & SDHCI_REQ_USE_DMA)
- mode |= SDHCI_TRNS_DMA;
-
- sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
-}
-
-static rt_bool_t sdhci_send_command(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
-{
- int flags;
- rt_uint32_t mask;
- unsigned long timeout;
- /* Initially, a command has no error */
- cmd->err = 0;
-
- if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && cmd->cmd_code == MMC_STOP_TRANSMISSION)
- cmd->flags |= MMC_RSP_BUSY;
-
- mask = SDHCI_CMD_INHIBIT;
- if (sdhci_data_line_cmd(cmd))
- mask |= SDHCI_DATA_INHIBIT;
-
- /* We shouldn't wait for data inihibit for stop commands, even
- though they might use busy signaling */
- if (cmd->mrq->data && (cmd == cmd->mrq->data->stop))
- mask &= ~SDHCI_DATA_INHIBIT;
-
- if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)
- return RT_FALSE;
-
- host->cmd = cmd;
- host->data_timeout = 0;
- if (sdhci_data_line_cmd(cmd))
- {
- host->data_cmd = cmd;
- sdhci_set_timeout(host, cmd);
- }
-
- if (cmd->data)
- {
- if (host->use_external_dma)
- sdhci_external_dma_prepare_data(host, cmd);
- else
- sdhci_prepare_data(host, cmd);
- }
- sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
-
- sdhci_set_transfer_mode(host, cmd);
-
- if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY))
- {
- /*
- * This does not happen in practice because 136-bit response
- * commands never have busy waiting, so rather than complicate
- * the error path, just remove busy waiting and continue.
- */
- cmd->flags &= ~MMC_RSP_BUSY;
- }
-
- if (!(cmd->flags & MMC_RSP_PRESENT))
- flags = SDHCI_CMD_RESP_NONE;
- else if (cmd->flags & MMC_RSP_136)
- flags = SDHCI_CMD_RESP_LONG;
- else if (cmd->flags & MMC_RSP_BUSY)
- flags = SDHCI_CMD_RESP_SHORT_BUSY;
- else
- flags = SDHCI_CMD_RESP_SHORT;
-
- if (cmd->flags & MMC_RSP_CRC)
- flags |= SDHCI_CMD_CRC;
- if (cmd->flags & MMC_RSP_OPCODE)
- flags |= SDHCI_CMD_INDEX;
-
- /* CMD19 is special in that the Data Present Select should be set */
- if (cmd->data || mmc_op_tuning(cmd->cmd_code))
- flags |= SDHCI_CMD_DATA;
-
- timeout = rt_tick_get();
- if (host->data_timeout)
- timeout += rt_tick_from_millisecond(host->data_timeout * 1000);
- else if (!cmd->data && cmd->busy_timeout > 9000)
- timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * RT_TICK_PER_SECOND + RT_TICK_PER_SECOND;
- else
- timeout += 10 * RT_TICK_PER_SECOND;
- sdhci_mod_timer(host, cmd->mrq, timeout);
-
- if (host->use_external_dma)
- sdhci_external_dma_pre_transfer(host, cmd);
-
- sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmd_code, flags), SDHCI_COMMAND);
- return RT_TRUE;
-}
-
-/********************************************************* */
-/* dma */
-/********************************************************* */
-static void __sdhci_finish_data(struct sdhci_host *host, rt_bool_t sw_data_timeout)
-{
- struct rt_mmcsd_cmd *data_cmd = host->data_cmd;
- struct rt_mmcsd_data *data = host->data;
-
- host->data = NULL;
- host->data_cmd = NULL;
-
- /*
- * The controller needs a reset of internal state machines upon error
- * conditions.
- */
- if (data->err)
- {
- if (!host->cmd || host->cmd == data_cmd)
- sdhci_reset_for(host, REQUEST_ERROR);
- else
- sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
- }
-
- /*
- * The specification states that the block count register must
- * be updated, but it does not specify at what point in the
- * data flow. That makes the register entirely useless to read
- * back so we have to assume that nothing made it to the card
- * in the event of an error.
- */
- if (data->err)
- {
- data->bytes_xfered = 0;
- }
- else
- {
- data->bytes_xfered = data->blksize * data->blks;
- }
- /*
- * Need to send CMD12 if -
- * a) open-ended multiblock transfer not using auto CMD12 (no CMD23)
- * b) error in multiblock transfer
- */
- if (data->stop && ((!data->mrq->sbc && !sdhci_auto_cmd12(host, data->mrq)) || data->err))
- {
- /*
- * 'cap_cmd_during_tfr' request must not use the command line
- * after mmc_command_done() has been called. It is upper layer's
- * responsibility to send the stop command if required.
- */
- if (data->mrq->cap_cmd_during_tfr)
- {
- __sdhci_finish_mrq(host, data->mrq);
- }
- else
- {
- /* Avoid triggering warning in sdhci_send_command() */
- host->cmd = NULL;
- if (!sdhci_send_command(host, data->stop))
- {
- if (sw_data_timeout)
- {
- /*
- * This is anyway a sw data timeout, so
- * give up now.
- */
- data->stop->err = -EIO;
- __sdhci_finish_mrq(host, data->mrq);
- }
- else
- {
- host->deferred_cmd = data->stop;
- }
- }
- }
- }
- else
- {
- __sdhci_finish_mrq(host, data->mrq);
- }
-}
-
-static void sdhci_finish_data(struct sdhci_host *host)
-{
- __sdhci_finish_data(host, RT_FALSE);
-}
-
-
-/********************************************************* */
-/* irq */
-/********************************************************* */
-static void sdhci_data_irq(struct sdhci_host *host, rt_uint32_t intmask)
-{
- rt_uint32_t command;
- /*
- * CMD19 generates _only_ Buffer Read Ready interrupt if
- * use sdhci_send_tuning.
- * Need to exclude this case: PIO mode and use mmc_send_tuning,
- * If not, sdhci_transfer_pio will never be called, make the
- * SDHCI_INT_DATA_AVAIL always there, stuck in irq storm.
- */
- if (intmask & SDHCI_INT_DATA_AVAIL && !host->data)
- {
- command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
- if (command == MMC_SEND_TUNING_BLOCK || command == MMC_SEND_TUNING_BLOCK_HS200)
- {
- host->tuning_done = 1;
- rt_wqueue_wakeup(&host->buf_ready_int, 0);
- return;
- }
- }
-
- if (!host->data)
- {
- struct rt_mmcsd_cmd *data_cmd = host->data_cmd;
-
- /*
- * The "data complete" interrupt is also used to
- * indicate that a busy state has ended. See comment
- * above in sdhci_cmd_irq().
- */
- if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY))
- {
- if (intmask & SDHCI_INT_DATA_TIMEOUT)
- {
- host->data_cmd = NULL;
- data_cmd->err = -ETIMEDOUT;
- __sdhci_finish_mrq(host, data_cmd->mrq);
- return;
- }
- if (intmask & SDHCI_INT_DATA_END)
- {
- host->data_cmd = NULL;
- /*
- * Some cards handle busy-end interrupt
- * before the command completed, so make
- * sure we do things in the proper order.
- */
- if (host->cmd == data_cmd)
- return;
-
- __sdhci_finish_mrq(host, data_cmd->mrq);
- return;
- }
- }
-
- /*
- * SDHCI recovers from errors by resetting the cmd and data
- * circuits. Until that is done, there very well might be more
- * interrupts, so ignore them in that case.
- */
- if (host->pending_reset)
- return;
- rt_kprintf("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
- mmc_hostname(host->mmc), (unsigned)intmask);
- sdhci_dumpregs(host);
-
- return;
- }
-
- if (intmask & SDHCI_INT_DATA_TIMEOUT)
- host->data->err = -ETIMEDOUT;
- else if (intmask & SDHCI_INT_DATA_END_BIT)
- host->data->err = -EILSEQ;
- else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R)
- {
- host->data->err = -EILSEQ;
- }
- if (host->data->err)
- {
- sdhci_finish_data(host);
- }
- else
- {
- if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
- sdhci_transfer_pio(host);
-
- /*
- * We currently don't do anything fancy with DMA
- * boundaries, but as we can't disable the feature
- * we need to at least restart the transfer.
- *
- * According to the spec sdhci_readl(host, SDHCI_DMA_ADDRESS)
- * should return a valid address to continue from, but as
- * some controllers are faulty, don't trust them.
- */
- if (intmask & SDHCI_INT_DMA_END)
- {
- rt_uint32_t dmastart, dmanow;
-
- dmastart = sdhci_sdma_address(host);
- dmanow = dmastart + host->data->bytes_xfered;
- /*
- * Force update to the next DMA block boundary.
- */
- dmanow = (dmanow & ~((rt_uint32_t)SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + SDHCI_DEFAULT_BOUNDARY_SIZE;
- host->data->bytes_xfered = dmanow - dmastart;
- LOG_D("DMA base %pad, transferred 0x%06x bytes, next %pad\n",
- &dmastart, host->data->bytes_xfered, &dmanow);
- sdhci_set_sdma_addr(host, dmanow);
- }
-
- if (intmask & SDHCI_INT_DATA_END)
- {
- if (host->cmd == host->data_cmd)
- {
- /*
- * Data managed to finish before the
- * command completed. Make sure we do
- * things in the proper order.
- */
- host->data_early = 1;
- }
- else
- {
- sdhci_finish_data(host);
- }
- }
- }
-}
-
-static void sdhci_read_rsp_136(struct sdhci_host *host, struct rt_mmcsd_cmd *cmd)
-{
- int i, reg;
-
- for (i = 0; i < 4; i++)
- {
- reg = SDHCI_RESPONSE + (3 - i) * 4;
- cmd->resp[i] = sdhci_readl(host, reg);
- }
-
- if (host->quirks2 & SDHCI_QUIRK2_RSP_136_HAS_CRC)
- return;
-
- /* CRC is stripped so we need to do some shifting */
- for (i = 0; i < 4; i++)
- {
- cmd->resp[i] <<= 8;
- if (i != 3)
- cmd->resp[i] |= cmd->resp[i + 1] >> 24;
- }
-}
-
-static void sdhci_finish_command(struct sdhci_host *host)
-{
- struct rt_mmcsd_cmd *cmd = host->cmd;
-
- host->cmd = NULL;
-
- if (cmd->flags & MMC_RSP_PRESENT)
- {
- if (cmd->flags & MMC_RSP_136)
- {
- sdhci_read_rsp_136(host, cmd);
- }
- else
- {
- cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
- }
- }
- /*
- * The host can send and interrupt when the busy state has
- * ended, allowing us to wait without wasting CPU cycles.
- * The busy signal uses DAT0 so this is similar to waiting
- * for data to complete.
- *
- * Note: The 1.0 specification is a bit ambiguous about this
- * feature so there might be some problems with older
- * controllers.
- */
- if (cmd->flags & MMC_RSP_BUSY)
- {
- if (cmd->data)
- {
- LOG_D("Cannot wait for busy signal when also doing a data transfer");
- }
- else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && cmd == host->data_cmd)
- {
- /* Command complete before busy is ended */
- return;
- }
- }
-
- /* Finished CMD23, now send actual command. */
- if (cmd == cmd->mrq->sbc)
- {
- if (!sdhci_send_command(host, cmd->mrq->cmd))
- {
- host->deferred_cmd = cmd->mrq->cmd;
- }
- }
- else
- {
- /* Processed actual command. */
- if (host->data && host->data_early)
- sdhci_finish_data(host);
-
- if (!cmd->data)
- __sdhci_finish_mrq(host, cmd->mrq);
- }
-}
-
-
-static void sdhci_cmd_irq(struct sdhci_host *host, rt_uint32_t intmask, rt_uint32_t *intmask_p)
-{
- /* Handle auto-CMD12 error */
- if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd)
- {
- struct rt_mmcsd_req *mrq = host->data_cmd->mrq;
- rt_uint16_t auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
- int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? SDHCI_INT_DATA_TIMEOUT : SDHCI_INT_DATA_CRC;
-
- /* Treat auto-CMD12 error the same as data error */
- if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
- {
- *intmask_p |= data_err_bit;
- return;
- }
- }
-
- if (!host->cmd)
- {
- /*
- * SDHCI recovers from errors by resetting the cmd and data
- * circuits. Until that is done, there very well might be more
- * interrupts, so ignore them in that case.
- */
- if (host->pending_reset)
- return;
- rt_kprintf("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
- mmc_hostname(host->mmc), (unsigned)intmask);
- sdhci_dumpregs(host);
- return;
- }
- if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX))
- {
- if (intmask & SDHCI_INT_TIMEOUT)
- host->cmd->err = -ETIMEDOUT;
- else
- host->cmd->err = -EILSEQ;
-
- /* Treat data command CRC error the same as data CRC error */
- if (host->cmd->data && (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == SDHCI_INT_CRC)
- {
- host->cmd = NULL;
- *intmask_p |= SDHCI_INT_DATA_CRC;
- return;
- }
-
- __sdhci_finish_mrq(host, host->cmd->mrq);
- return;
- }
-
- /* Handle auto-CMD23 error */
- if (intmask & SDHCI_INT_AUTO_CMD_ERR)
- {
- struct rt_mmcsd_req *mrq = host->cmd->mrq;
- rt_uint16_t auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS);
- int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? -ETIMEDOUT : -EILSEQ;
-
- if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23))
- {
- mrq->sbc->err = err;
- __sdhci_finish_mrq(host, mrq);
- return;
- }
- }
-
- if (intmask & SDHCI_INT_RESPONSE)
- sdhci_finish_command(host);
-}
-
-static void sdhci_irq(int irq, void *dev_id)
-{
- struct rt_mmcsd_req *mrqs_done[SDHCI_MAX_MRQS] = {0};
- struct sdhci_host *host = dev_id;
- rt_uint32_t intmask, mask, unexpected = 0;
- int max_loops = 16;
- int i, result;
- rt_spin_lock(&host->lock);
-
- if (host->runtime_suspended)
- {
- rt_spin_unlock(&host->lock);
- }
-
- intmask = sdhci_readl(host, SDHCI_INT_STATUS);
- if (!intmask || intmask == 0xffffffff)
- {
- result = 0;
- goto out;
- }
-
- do {
- LOG_D("IRQ status 0x%08x\n", intmask);
-
- if (host->ops->irq)
- {
- intmask = host->ops->irq(host, intmask);
- if (!intmask)
- goto cont;
- }
-
- /* Clear selected interrupts. */
- mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_BUS_POWER);
- sdhci_writel(host, mask, SDHCI_INT_STATUS);
-
- if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
- {
- rt_uint32_t present = sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT;
-
- /*
- * There is a observation on i.mx esdhc. INSERT
- * bit will be immediately set again when it gets
- * cleared, if a card is inserted. We have to mask
- * the irq to prevent interrupt storm which will
- * freeze the system. And the REMOVE gets the
- * same situation.
- *
- * More testing are needed here to ensure it works
- * for other platforms though.
- */
- host->ier &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
- host->ier |= present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-
- sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-
- host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
- result = RT_EOK;
- }
-
- if (intmask & SDHCI_INT_CMD_MASK)
- sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
-
- if (intmask & SDHCI_INT_DATA_MASK)
- sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-
- if (intmask & SDHCI_INT_BUS_POWER)
- rt_kprintf("%s: Card is consuming too much power!\n",
- mmc_hostname(host->mmc));
-
- intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);
-
- if (intmask)
- {
- unexpected |= intmask;
- sdhci_writel(host, intmask, SDHCI_INT_STATUS);
- }
- cont:
- intmask = sdhci_readl(host, SDHCI_INT_STATUS);
- } while (intmask && --max_loops);
-
- /* Determine if mrqs can be completed immediately */
- for (i = 0; i < SDHCI_MAX_MRQS; i++)
- {
- struct rt_mmcsd_req *mrq = host->mrqs_done[i];
-
- if (!mrq)
- continue;
-
- if (sdhci_defer_done(host, mrq))
- {
- result = RT_EOK;
- }
- else
- {
- mrqs_done[i] = mrq;
- host->mrqs_done[i] = NULL;
- }
- }
-out:
- if (host->deferred_cmd)
- result = RT_EOK;
-
- rt_spin_unlock(&host->lock);
-
- /* Process mrqs ready for immediate completion */
- for (i = 0; i < SDHCI_MAX_MRQS; i++)
- {
- if (!mrqs_done[i])
- continue;
-
- if (host->ops->request_done)
- host->ops->request_done(host, mrqs_done[i]);
- else
- mmc_request_done(host->mmc, mrqs_done[i]);
- }
-
- if (unexpected)
- {
- sdhci_dumpregs(host);
- }
-
- if (result == RT_EOK)
- {
- rt_workqueue_submit_work(host->irq_wq, &host->irq_work, 0);
- }
-}
-
-static rt_bool_t sdhci_send_command_retry(struct sdhci_host *host,
- struct rt_mmcsd_cmd *cmd,
- unsigned long flags)
-{
- struct rt_mmcsd_cmd *deferred_cmd = host->deferred_cmd;
- int timeout = 10; /* Approx. 10 ms */
- rt_bool_t present;
- while (!sdhci_send_command(host, cmd))
- {
- if (!timeout--)
- {
- rt_kprintf("%s: Controller never released inhibit bit(s).\n",
- mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
- cmd->err = -EIO;
- return RT_FALSE;
- }
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- rt_thread_mdelay(1);
-
- present = host->mmc->ops->get_cd(host->mmc);
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- /* A deferred command might disappear, handle that */
- if (cmd == deferred_cmd && cmd != host->deferred_cmd)
- return RT_TRUE;
-
- if (sdhci_present_error(host, cmd, present))
- return RT_FALSE;
- }
-
- if (cmd == host->deferred_cmd)
- host->deferred_cmd = NULL;
-
- return RT_TRUE;
-}
-
-static rt_bool_t sdhci_request_done(struct sdhci_host *host)
-{
- rt_base_t flags;
- struct rt_mmcsd_req *mrq;
- int i;
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- for (i = 0; i < SDHCI_MAX_MRQS; i++)
- {
- mrq = host->mrqs_done[i];
- if (mrq)
- break;
- }
-
- if (!mrq)
- {
- rt_spin_unlock_irqrestore(&host->lock, flags);
- return RT_TRUE;
- }
-
- /*
- * The controller needs a reset of internal state machines
- * upon error conditions.
- */
- if (sdhci_needs_reset(host, mrq))
- {
- /*
- * Do not finish until command and data lines are available for
- * reset. Note there can only be one other mrq, so it cannot
- * also be in mrqs_done, otherwise host->cmd and host->data_cmd
- * would both be null.
- */
- if (host->cmd || host->data_cmd)
- {
- rt_spin_unlock_irqrestore(&host->lock, flags);
- return RT_TRUE;
- }
-
- /* Some controllers need this kick or reset won't work here */
- if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
- /* This is to force an update */
- host->ops->set_clock(host, host->clock);
-
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
-
- host->pending_reset = RT_FALSE;
- }
-
- /*
- * Always unmap the data buffers if they were mapped by
- * sdhci_prepare_data() whenever we finish with a request.
- * This avoids leaking DMA mappings on error.
- */
- if (host->flags & SDHCI_REQ_USE_DMA)
- {
- struct rt_mmcsd_data *data = mrq->data;
-
- if (host->use_external_dma && data && (mrq->cmd->err || data->err))
- {
- host->mrqs_done[i] = NULL;
- sdhci_set_mrq_done(host, mrq);
- }
- }
-
- host->mrqs_done[i] = NULL;
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- if (host->ops->request_done)
- host->ops->request_done(host, mrq);
- else
- mmc_request_done(host->mmc, mrq);
-
- return RT_FALSE;
-}
-
-
-static void sdhci_thread_irq(struct rt_work *work, void *work_data)
-{
- struct sdhci_host *host = work_data;
- struct rt_mmcsd_cmd *cmd;
- rt_base_t flags;
- rt_uint32_t isr;
-
- while (!sdhci_request_done(host));
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- isr = host->thread_isr;
- host->thread_isr = 0;
-
- cmd = host->deferred_cmd;
- if (cmd && !sdhci_send_command_retry(host, cmd, flags))
- sdhci_finish_mrq(host, cmd->mrq);
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
- {
- struct mmc_host *mmc = host->mmc;
-
- mmc->ops->card_event(mmc);
- }
-}
-
-
-void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_uint32_t flags;
-
- flags = rt_spin_lock_irqsave(&host->lock);
- sdhci_enable_sdio_irq_nolock(host, enable);
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-
-/********************************************************* */
-/* request */
-/********************************************************* */
-
-void sdhci_request(struct mmc_host *mmc, struct rt_mmcsd_req *mrq)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- struct rt_mmcsd_cmd *cmd;
- rt_base_t flags;
- rt_bool_t present;
-
- /* Firstly check card presence */
- present = mmc->ops->get_cd(mmc);
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- if (sdhci_present_error(host, mrq->cmd, present))
- goto out_finish;
-
- cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd;
-
- if (!sdhci_send_command_retry(host, cmd, flags))
- goto out_finish;
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- return;
-
-out_finish:
- sdhci_finish_mrq(host, mrq);
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-
-static void sdhci_complete_work(struct rt_work *work, void *work_data)
-{
- struct sdhci_host *host = work_data;
-
- while (!sdhci_request_done(host));
-}
-
-
-/********************************************************* */
-/* timer */
-/********************************************************* */
-static void sdhci_timeout_timer(void *parameter)
-{
- struct sdhci_host *host = parameter;
- rt_base_t flags;
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- if (host->cmd && !sdhci_data_line_cmd(host->cmd))
- {
- rt_kprintf("%s: Timeout waiting for hardware cmd interrupt.\n",
- mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
-
- host->cmd->err = -ETIMEDOUT;
- sdhci_finish_mrq(host, host->cmd->mrq);
- }
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void sdhci_timeout_data_timer(void *parameter)
-{
- struct sdhci_host *host = parameter;
- rt_base_t flags;
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- if (host->data || host->data_cmd || (host->cmd && sdhci_data_line_cmd(host->cmd)))
- {
- rt_kprintf("%s: Timeout waiting for hardware interrupt.\n",
- mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
-
- if (host->data)
- {
- host->data->err = -ETIMEDOUT;
- __sdhci_finish_data(host, RT_TRUE);
- rt_workqueue_submit_work(host->complete_wq, &host->complete_work, 0);
- }
- else if (host->data_cmd)
- {
- host->data_cmd->err = -ETIMEDOUT;
- sdhci_finish_mrq(host, host->data_cmd->mrq);
- }
- else
- {
- host->cmd->err = -ETIMEDOUT;
- sdhci_finish_mrq(host, host->cmd->mrq);
- }
- }
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-
-/********************************************************* */
-/* tuning */
-/********************************************************* */
-int sdhci_execute_tuning(struct mmc_host *mmc, rt_uint32_t opcode)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- int err = 0;
- unsigned int tuning_count = 0;
- rt_bool_t hs400_tuning;
-
- hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-
- if (host->tuning_mode == SDHCI_TUNING_MODE_1)
- tuning_count = host->tuning_count;
-
- /*
- * The Host Controller needs tuning in case of SDR104 and DDR50
- * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
- * the Capabilities register.
- * If the Host Controller supports the HS200 mode then the
- * tuning function has to be executed.
- */
- switch (host->timing)
- {
- /* HS400 tuning is done in HS200 mode */
- case MMC_TIMING_MMC_HS400:
- err = -EINVAL;
- goto out;
-
- case MMC_TIMING_MMC_HS200:
- /*
- * Periodic re-tuning for HS400 is not expected to be needed, so
- * disable it here.
- */
- if (hs400_tuning)
- tuning_count = 0;
- break;
-
- case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_UHS_DDR50:
- break;
-
- case MMC_TIMING_UHS_SDR50:
- if (host->flags & SDHCI_SDR50_NEEDS_TUNING)
- break;
- fallthrough;
-
- default:
- goto out;
- }
-
- if (host->ops->platform_execute_tuning)
- {
- err = host->ops->platform_execute_tuning(host, opcode);
- goto out;
- }
-
- mmc->retune_period = tuning_count;
-
- if (host->tuning_delay < 0)
- host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK;
-
- sdhci_start_tuning(host);
-
- host->tuning_err = __sdhci_execute_tuning(host, opcode);
-
- sdhci_end_tuning(host);
-out:
- host->flags &= ~SDHCI_HS400_TUNING;
-
- return err;
-}
-
-int __sdhci_execute_tuning(struct sdhci_host *host, rt_uint32_t opcode)
-{
- int i;
-
- /*
- * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
- * of loops reaches tuning loop count.
- */
- for (i = 0; i < host->tuning_loop_count; i++)
- {
- rt_uint16_t ctrl;
-
- sdhci_send_tuning(host, opcode);
-
- if (!host->tuning_done)
- {
- sdhci_abort_tuning(host, opcode);
- return -ETIMEDOUT;
- }
-
- /* Spec does not require a delay between tuning cycles */
- if (host->tuning_delay > 0)
- rt_thread_mdelay(host->tuning_delay);
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- if (!(ctrl & SDHCI_CTRL_EXEC_TUNING))
- {
- if (ctrl & SDHCI_CTRL_TUNED_CLK)
- return 0; /* Success! */
- break;
- }
- }
-
- LOG_D("%s: Tuning failed, falling back to fixed sampling clock\n",
- mmc_hostname(host->mmc));
- sdhci_reset_tuning(host);
- return -EAGAIN;
-}
-
-void sdhci_start_tuning(struct sdhci_host *host)
-{
- rt_uint16_t ctrl;
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl |= SDHCI_CTRL_EXEC_TUNING;
- if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
- ctrl |= SDHCI_CTRL_TUNED_CLK;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
- /*
- * As per the Host Controller spec v3.00, tuning command
- * generates Buffer Read Ready interrupt, so enable that.
- *
- * Note: The spec clearly says that when tuning sequence
- * is being performed, the controller does not generate
- * interrupts other than Buffer Read Ready interrupt. But
- * to make sure we don't hit a controller bug, we _only_
- * enable Buffer Read Ready interrupt here.
- */
- sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
- sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
-}
-
-void sdhci_end_tuning(struct sdhci_host *host)
-{
- sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
- sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-}
-
-void sdhci_abort_tuning(struct sdhci_host *host, rt_uint32_t opcode)
-{
- sdhci_reset_tuning(host);
-
- sdhci_reset_for(host, TUNING_ABORT);
-
- sdhci_end_tuning(host);
-}
-
-void sdhci_send_tuning(struct sdhci_host *host, rt_uint32_t opcode)
-{
- struct mmc_host *mmc = host->mmc;
- struct rt_mmcsd_cmd cmd = {};
- struct rt_mmcsd_req mrq = {};
- unsigned long flags;
- rt_uint32_t b = host->sdma_boundary;
-
- flags = rt_spin_lock_irqsave(&host->lock);
-
- cmd.cmd_code = opcode;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
- cmd.mrq = &mrq;
-
- mrq.cmd = &cmd;
- /*
- * In response to CMD19, the card sends 64 bytes of tuning
- * block to the Host Controller. So we set the block size
- * to 64 here.
- */
- if (cmd.cmd_code == MMC_SEND_TUNING_BLOCK_HS200 && mmc->ios.bus_width == MMC_BUS_WIDTH_8)
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 128), SDHCI_BLOCK_SIZE);
- else
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(b, 64), SDHCI_BLOCK_SIZE);
-
- /*
- * The tuning block is sent by the card to the host controller.
- * So we set the TRNS_READ bit in the Transfer Mode register.
- * This also takes care of setting DMA Enable and Multi Block
- * Select in the same register to 0.
- */
- sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
-
- if (!sdhci_send_command_retry(host, &cmd, flags))
- {
- rt_spin_unlock_irqrestore(&host->lock, flags);
- host->tuning_done = 0;
- return;
- }
-
- host->cmd = NULL;
-
- sdhci_del_timer(host, &mrq);
-
- host->tuning_done = 0;
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
-}
-
-void sdhci_reset_tuning(struct sdhci_host *host)
-{
- rt_uint16_t ctrl;
-
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl &= ~SDHCI_CTRL_TUNED_CLK;
- ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-}
-
-
-/********************************************************* */
-/* error */
-/********************************************************* */
-
-void sdhci_dumpregs(struct sdhci_host *host)
-{
-#define SDHCI_DUMP rt_kprintf
- SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n");
-
- SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n",
- sdhci_readl(host, SDHCI_DMA_ADDRESS),
- sdhci_readw(host, SDHCI_HOST_VERSION));
- SDHCI_DUMP("Blk size: 0x%08x | Blk cnt: 0x%08x\n",
- sdhci_readw(host, SDHCI_BLOCK_SIZE),
- sdhci_readw(host, SDHCI_BLOCK_COUNT));
- SDHCI_DUMP("Argument: 0x%08x | Trn mode: 0x%08x\n",
- sdhci_readl(host, SDHCI_ARGUMENT),
- sdhci_readw(host, SDHCI_TRANSFER_MODE));
- SDHCI_DUMP("Present: 0x%08x | Host ctl: 0x%08x\n",
- sdhci_readl(host, SDHCI_PRESENT_STATE),
- sdhci_readb(host, SDHCI_HOST_CONTROL));
- SDHCI_DUMP("Power: 0x%08x | Blk gap: 0x%08x\n",
- sdhci_readb(host, SDHCI_POWER_CONTROL),
- sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
- SDHCI_DUMP("Wake-up: 0x%08x | Clock: 0x%08x\n",
- sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
- sdhci_readw(host, SDHCI_CLOCK_CONTROL));
- SDHCI_DUMP("Timeout: 0x%08x | Int stat: 0x%08x\n",
- sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
- sdhci_readl(host, SDHCI_INT_STATUS));
- SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n",
- sdhci_readl(host, SDHCI_INT_ENABLE),
- sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
- SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n",
- sdhci_readw(host, SDHCI_AUTO_CMD_STATUS),
- sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
- SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n",
- sdhci_readl(host, SDHCI_CAPABILITIES),
- sdhci_readl(host, SDHCI_CAPABILITIES_1));
- SDHCI_DUMP("Cmd: 0x%08x | Max curr: 0x%08x\n",
- sdhci_readw(host, SDHCI_COMMAND),
- sdhci_readl(host, SDHCI_MAX_CURRENT));
- SDHCI_DUMP("Resp[0]: 0x%08x | Resp[1]: 0x%08x\n",
- sdhci_readl(host, SDHCI_RESPONSE),
- sdhci_readl(host, SDHCI_RESPONSE + 4));
- SDHCI_DUMP("Resp[2]: 0x%08x | Resp[3]: 0x%08x\n",
- sdhci_readl(host, SDHCI_RESPONSE + 8),
- sdhci_readl(host, SDHCI_RESPONSE + 12));
- SDHCI_DUMP("Host ctl2: 0x%08x\n",
- sdhci_readw(host, SDHCI_HOST_CONTROL2));
-
-
- if (host->ops->dump_vendor_regs)
- host->ops->dump_vendor_regs(host);
-
- SDHCI_DUMP("============================================\n");
-}
-
-
-static const struct mmc_host_ops sdhci_ops = {
- .request = sdhci_request,
- .set_ios = sdhci_set_ios,
- .get_cd = sdhci_get_cd,
- .get_ro = sdhci_get_ro,
- .enable_sdio_irq = sdhci_enable_sdio_irq,
- .ack_sdio_irq = sdhci_ack_sdio_irq,
- .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
- .prepare_hs400_tuning = sdhci_prepare_hs400_tuning,
- .execute_tuning = sdhci_execute_tuning,
- .card_event = sdhci_card_event,
- .card_busy = sdhci_card_busy,
-};
-
-
-void sdhci_remove_host(struct sdhci_host *host, int dead)
-{
- struct mmc_host *mmc = host->mmc;
- unsigned long flags;
-
- if (dead)
- {
- flags = rt_spin_lock_irqsave(&host->lock);
-
- host->flags |= SDHCI_DEVICE_DEAD;
-
- if (sdhci_has_requests(host))
- {
- rt_kprintf("%s: Controller removed during "
- " transfer!\n",
- mmc_hostname(mmc));
- sdhci_error_out_mrqs(host, -ENOMEDIUM);
- }
-
- rt_spin_unlock_irqrestore(&host->lock, flags);
- }
-
- sdhci_set_card_detection(host, RT_FALSE);
-
- mmc_remove_host(mmc);
-
-
- if (!dead)
- sdhci_reset_for_all(host);
-
- sdhci_writel(host, 0, SDHCI_INT_ENABLE);
- sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
-
- rt_timer_delete(&host->timer);
- rt_timer_delete(&host->data_timer);
-
- rt_workqueue_destroy(host->complete_wq);
-
- if (host->use_external_dma)
- sdhci_external_dma_release(host);
-
- host->align_buffer = NULL;
-}
-
-rt_uint16_t sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
- unsigned int *actual_clock)
-{
- int div = 0; /* Initialized for compiler warning */
- int real_div = div, clk_mul = 1;
- rt_uint16_t clk = 0;
- rt_bool_t switch_base_clk = RT_FALSE;
-
- if (host->version >= SDHCI_SPEC_300)
- {
- if (host->preset_enabled)
- {
- rt_uint16_t pre_val;
-
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- pre_val = sdhci_get_preset_value(host);
- div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
- if (host->clk_mul && (pre_val & SDHCI_PRESET_CLKGEN_SEL))
- {
- clk = SDHCI_PROG_CLOCK_MODE;
- real_div = div + 1;
- clk_mul = host->clk_mul;
- }
- else
- {
- real_div = max_t(int, 1, div << 1);
- }
- goto clock_set;
- }
-
- /*
- * Check if the Host Controller supports Programmable Clock
- * Mode.
- */
- if (host->clk_mul)
- {
- for (div = 1; div <= 1024; div++)
- {
- if ((host->max_clk * host->clk_mul / div)
- <= clock)
- break;
- }
- if ((host->max_clk * host->clk_mul / div) <= clock)
- {
- /*
- * Set Programmable Clock Mode in the Clock
- * Control register.
- */
- clk = SDHCI_PROG_CLOCK_MODE;
- real_div = div;
- clk_mul = host->clk_mul;
- div--;
- }
- else
- {
- /*
- * Divisor can be too small to reach clock
- * speed requirement. Then use the base clock.
- */
- switch_base_clk = RT_TRUE;
- }
- }
-
- if (!host->clk_mul || switch_base_clk)
- {
- /* Version 3.00 divisors must be a multiple of 2. */
- if (host->max_clk <= clock)
- div = 1;
- else
- {
- for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
- div += 2)
- {
- if ((host->max_clk / div) <= clock)
- break;
- }
- }
- real_div = div;
- div >>= 1;
- if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN)
- && !div && host->max_clk <= 25000000)
- div = 1;
- }
- }
- else
- {
- /* Version 2.00 divisors must be a power of 2. */
- for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2)
- {
- if ((host->max_clk / div) <= clock)
- break;
- }
- real_div = div;
- div >>= 1;
- }
-
-clock_set:
- if (real_div)
- *actual_clock = (host->max_clk * clk_mul) / real_div;
- clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
- clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
- << SDHCI_DIVIDER_HI_SHIFT;
-
- return clk;
-}
-
-void sdhci_enable_clk(struct sdhci_host *host, rt_uint16_t clk)
-{
- long timeout;
-
- clk |= SDHCI_CLOCK_INT_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
- /* Wait max 150 ms */
- timeout = rt_tick_from_millisecond(150);
- while (1)
- {
- timeout = timeout - rt_tick_get();
-
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- if (clk & SDHCI_CLOCK_INT_STABLE)
- break;
- if (timeout < 0)
- {
- rt_kprintf("%s: Internal clock never stabilised.\n",
- mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
- return;
- }
- rt_hw_us_delay(10);
- }
-
- if (host->version >= SDHCI_SPEC_410 && host->v4_mode)
- {
- clk |= SDHCI_CLOCK_PLL_EN;
- clk &= ~SDHCI_CLOCK_INT_STABLE;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
- /* Wait max 150 ms */
- timeout = rt_tick_from_millisecond(150);
- while (1)
- {
- timeout = timeout - rt_tick_get();
-
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- if (clk & SDHCI_CLOCK_INT_STABLE)
- break;
- if (timeout < 0)
- {
- rt_kprintf("%s: PLL clock never stabilised.\n",
- mmc_hostname(host->mmc));
- sdhci_dumpregs(host);
- return;
- }
- rt_hw_us_delay(10);
- }
- }
-
- clk |= SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-}
-
-void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
-{
- rt_uint16_t clk;
-
- host->mmc->actual_clock = 0;
-
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-
- if (clock == 0)
- return;
-
- clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
- sdhci_enable_clk(host, clk);
-}
-
-void __sdhci_read_caps(struct sdhci_host *host, const rt_uint16_t *ver,
- const rt_uint32_t *caps, const rt_uint32_t *caps1)
-{
- rt_uint16_t v;
- rt_uint64_t dt_caps_mask = 0;
- rt_uint64_t dt_caps = 0;
-
- if (host->read_caps)
- return;
-
- host->read_caps = RT_TRUE;
-
- if (debug_quirks)
- host->quirks = debug_quirks;
-
- if (debug_quirks2)
- host->quirks2 = debug_quirks2;
-
- sdhci_reset_for_all(host);
-
- if (host->v4_mode)
- sdhci_do_enable_v4_mode(host);
-#ifdef RT_USING_OFW
- rt_ofw_prop_read_u64(mmc_dev(host->mmc)->ofw_node,
- "sdhci-caps-mask", &dt_caps_mask);
- rt_ofw_prop_read_u64(mmc_dev(host->mmc)->ofw_node,
- "sdhci-caps", &dt_caps);
-#endif
- v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
- host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
-
- if (caps)
- {
- host->caps = *caps;
- }
- else
- {
- host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
- host->caps &= ~lower_32_bits(dt_caps_mask);
- host->caps |= lower_32_bits(dt_caps);
- }
-
- if (host->version < SDHCI_SPEC_300)
- return;
-
- if (caps1)
- {
- host->caps1 = *caps1;
- }
- else
- {
- host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
- host->caps1 &= ~upper_32_bits(dt_caps_mask);
- host->caps1 |= upper_32_bits(dt_caps);
- }
-}
-
-struct sdhci_host *sdhci_alloc_host(struct rt_device *dev,
- size_t priv_size)
-{
- struct mmc_host *mmc;
- struct sdhci_host *host;
-
- mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);
- if (!mmc)
- return NULL;
-
- host = mmc_priv(mmc);
- host->mmc = mmc;
- host->mmc_host_ops = sdhci_ops;
- mmc->ops = &host->mmc_host_ops;
-
- host->flags = SDHCI_SIGNALING_330;
-
- host->cqe_ier = SDHCI_CQE_INT_MASK;
- host->cqe_err_ier = SDHCI_CQE_INT_ERR_MASK;
-
- host->tuning_delay = -1;
- host->tuning_loop_count = MAX_TUNING_LOOP;
-
- host->sdma_boundary = SDHCI_DEFAULT_BOUNDARY_ARG;
-
- /*
- * The DMA table descriptor count is calculated as the maximum
- * number of segments times 2, to allow for an alignment
- * descriptor for each segment, plus 1 for a nop end descriptor.
- */
-
- host->max_timeout_count = 0xE;
-
- return host;
-}
-
-int sdhci_setup_host(struct sdhci_host *host)
-{
- struct mmc_host *mmc;
- size_t max_current_caps;
- unsigned int ocr_avail;
- unsigned int override_timeout_clk;
- size_t max_clk;
- int ret = 0;
- bool enable_vqmmc = RT_FALSE;
-
- RT_ASSERT(host != NULL);
-
-
- mmc = host->mmc;
-
- /*
- * If there are external regulators, get them. Note this must be done
- * early before resetting the host and reading the capabilities so that
- * the host can take the appropriate action if regulators are not
- * available.
- */
- if (!mmc->supply.vqmmc)
- {
- if (ret)
- return ret;
- enable_vqmmc = RT_TRUE;
- }
-
- LOG_D("Version: 0x%08x | Present: 0x%08x\n",
- sdhci_readw(host, SDHCI_HOST_VERSION),
- sdhci_readl(host, SDHCI_PRESENT_STATE));
- LOG_D("Caps: 0x%08x | Caps_1: 0x%08x\n",
- sdhci_readl(host, SDHCI_CAPABILITIES),
- sdhci_readl(host, SDHCI_CAPABILITIES_1));
-
- sdhci_read_caps(host);
-
- override_timeout_clk = host->timeout_clk;
-
- if (host->version > SDHCI_SPEC_420)
- {
- rt_kprintf("%s: Unknown controller version (%d). You may experience problems.\n",
- mmc_hostname(mmc), host->version);
- }
-
- if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
- host->flags |= SDHCI_USE_SDMA;
- else if (!(host->caps & SDHCI_CAN_DO_SDMA))
- LOG_D("Controller doesn't have SDMA capability\n");
- else
- host->flags |= SDHCI_USE_SDMA;
-
- if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && (host->flags & SDHCI_USE_SDMA))
- {
- LOG_D("Disabling DMA as it is marked broken\n");
- host->flags &= ~SDHCI_USE_SDMA;
- }
-
- if (sdhci_can_64bit_dma(host))
- host->flags |= SDHCI_USE_64_BIT_DMA;
-
- if (host->flags & SDHCI_USE_SDMA)
- {
- if (host->ops->set_dma_mask)
- ret = host->ops->set_dma_mask(host);
-
- if (!ret && host->ops->enable_dma)
- ret = host->ops->enable_dma(host);
-
- if (ret)
- {
- rt_kprintf("%s: No suitable DMA available - falling back to PIO\n",
- mmc_hostname(mmc));
- host->flags &= ~SDHCI_USE_SDMA;
-
- ret = 0;
- }
- }
-
- /* SDMA does not support 64-bit DMA if v4 mode not set */
- if ((host->flags & SDHCI_USE_64_BIT_DMA) && !host->v4_mode)
- host->flags &= ~SDHCI_USE_SDMA;
- /*
- * If we use DMA, then it's up to the caller to set the DMA
- * mask, but PIO does not need the hw shim so we set a new
- * mask here in that case.
- */
-
- if (!(host->flags & SDHCI_USE_SDMA))
- {
- host->dma_mask = DMA_BIT_MASK(64);
- }
- if (host->version >= SDHCI_SPEC_300)
- host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps);
- else
- host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps);
-
- host->max_clk *= 1000000;
- if (host->max_clk == 0 || host->quirks & SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN)
- {
- if (!host->ops->get_max_clock)
- {
- rt_kprintf("%s: Hardware doesn't specify base clock frequency. %p \n",
- mmc_hostname(mmc), host->ops->get_max_clock);
- ret = -ENODEV;
- goto undma;
- }
- host->max_clk = host->ops->get_max_clock(host);
- }
-
- /*
- * In case of Host Controller v3.00, find out whether clock
- * multiplier is supported.
- */
- host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1);
-
- /*
- * In case the value in Clock Multiplier is 0, then programmable
- * clock mode is not supported, otherwise the actual clock
- * multiplier is one more than the value of Clock Multiplier
- * in the Capabilities Register.
- */
- if (host->clk_mul)
- host->clk_mul += 1;
-
- /*
- * Set host parameters.
- */
- max_clk = host->max_clk;
-
- if (host->ops->get_min_clock)
- mmc->f_min = host->ops->get_min_clock(host);
- else if (host->version >= SDHCI_SPEC_300)
- {
- if (host->clk_mul)
- max_clk = host->max_clk * host->clk_mul;
- /*
- * Divided Clock Mode minimum clock rate is always less than
- * Programmable Clock Mode minimum clock rate.
- */
- mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
- }
- else
- mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
-
- if (!mmc->f_max || mmc->f_max > max_clk)
- mmc->f_max = max_clk;
-
- if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK))
- {
- host->timeout_clk = FIELD_GET(SDHCI_TIMEOUT_CLK_MASK, host->caps);
-
- if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
- host->timeout_clk *= 1000;
-
- if (host->timeout_clk == 0)
- {
- if (!host->ops->get_timeout_clock)
- {
- rt_kprintf("%s: Hardware doesn't specify timeout clock frequency.\n",
- mmc_hostname(mmc));
- ret = -ENODEV;
- goto undma;
- }
-
- host->timeout_clk =
- DIV_ROUND_UP(host->ops->get_timeout_clock(host),
- 1000);
- }
-
- if (override_timeout_clk)
- host->timeout_clk = override_timeout_clk;
-
- mmc->max_busy_timeout = host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27;
- mmc->max_busy_timeout /= host->timeout_clk;
- }
-
- if (host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT && !host->ops->get_max_timeout_count)
- mmc->max_busy_timeout = 0;
-
- mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;
- mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
-
- if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
- host->flags |= SDHCI_AUTO_CMD12;
-
- /*
- * For v3 mode, Auto-CMD23 stuff only works in ADMA or PIO.
- * For v4 mode, SDMA may use Auto-CMD23 as well.
- */
- if ((host->version >= SDHCI_SPEC_300) && (!(host->flags & SDHCI_USE_SDMA) || host->v4_mode) && !(host->quirks2 & SDHCI_QUIRK2_ACMD23_BROKEN))
- {
- host->flags |= SDHCI_AUTO_CMD23;
- LOG_D("Auto-CMD23 available\n");
- }
- else
- {
- LOG_D("Auto-CMD23 unavailable\n");
- }
-
- /*
- * A controller may support 8-bit width, but the board itself
- * might not have the pins brought out. Boards that support
- * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
- * their platform code before calling sdhci_add_host(), and we
- * won't assume 8-bit width for hosts without that CAP.
- */
- if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-
- if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
- mmc->caps &= ~MMC_CAP_CMD23;
-
- if (host->caps & SDHCI_CAN_DO_HISPD)
- mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
- if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && mmc_card_is_removable(mmc) && mmc_gpio_get_cd(mmc) < 0)
- mmc->caps |= MMC_CAP_NEEDS_POLL;
-
- if (mmc->supply.vqmmc)
- {
- if (enable_vqmmc)
- {
- host->sdhci_core_to_disable_vqmmc = !ret;
- }
-
- /* If vqmmc provides no 1.8V signalling, then there's no UHS */
- if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
- 1950000))
- host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
-
- /* In eMMC case vqmmc might be a fixed 1.8V regulator */
- if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000,
- 3600000))
- host->flags &= ~SDHCI_SIGNALING_330;
-
- if (ret)
- {
- rt_kprintf("%s: Failed to enable vqmmc regulator: %d\n",
- mmc_hostname(mmc), ret);
- mmc->supply.vqmmc = (void *)-EINVAL;
- }
- }
- if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
- {
- host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
- /*
- * The SDHCI controller in a SoC might support HS200/HS400
- * (indicated using mmc-hs200-1_8v/mmc-hs400-1_8v dt property),
- * but if the board is modeled such that the IO lines are not
- * connected to 1.8v then HS200/HS400 cannot be supported.
- * Disable HS200/HS400 if the board does not have 1.8v connected
- * to the IO lines. (Applicable for other modes in 1.8v)
- */
- mmc->caps2 &= ~(MMC_CAP2_HSX00_1_8V | MMC_CAP2_HS400_ES);
- mmc->caps &= ~(MMC_CAP_1_8V_DDR | MMC_CAP_UHS);
- }
-
- /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
- if (host->caps1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50))
- mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
-
- /* SDR104 supports also implies SDR50 support */
- if (host->caps1 & SDHCI_SUPPORT_SDR104)
- {
- mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50;
- /* SD3.0: SDR104 is supported so (for eMMC) the caps2
- * field can be promoted to support HS200.
- */
- if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200))
- mmc->caps2 |= MMC_CAP2_HS200;
- }
- else if (host->caps1 & SDHCI_SUPPORT_SDR50)
- {
- mmc->caps |= MMC_CAP_UHS_SDR50;
- }
-
- if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 && (host->caps1 & SDHCI_SUPPORT_HS400))
- mmc->caps2 |= MMC_CAP2_HS400;
- if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) && (!mmc->supply.vqmmc || !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000, 1300000)))
- mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V;
- if ((host->caps1 & SDHCI_SUPPORT_DDR50) && !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
- mmc->caps |= MMC_CAP_UHS_DDR50;
-
- /* Does the host need tuning for SDR50? */
- if (host->caps1 & SDHCI_USE_SDR50_TUNING)
- host->flags |= SDHCI_SDR50_NEEDS_TUNING;
-
- /* Driver Type(s) (A, C, D) supported by the host */
- if (host->caps1 & SDHCI_DRIVER_TYPE_A)
- mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
- if (host->caps1 & SDHCI_DRIVER_TYPE_C)
- mmc->caps |= MMC_CAP_DRIVER_TYPE_C;
- if (host->caps1 & SDHCI_DRIVER_TYPE_D)
- mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
-
- /* Initial value for re-tuning timer count */
- host->tuning_count = FIELD_GET(SDHCI_RETUNING_TIMER_COUNT_MASK,
- host->caps1);
-
- /*
- * In case Re-tuning Timer is not disabled, the actual value of
- * re-tuning timer will be 2 ^ (n - 1).
- */
- if (host->tuning_count)
- host->tuning_count = 1 << (host->tuning_count - 1);
-
- /* Re-tuning mode supported by the Host Controller */
- host->tuning_mode = FIELD_GET(SDHCI_RETUNING_MODE_MASK, host->caps1);
-
- ocr_avail = 0;
-
- /*
- * According to SD Host Controller spec v3.00, if the Host System
- * can afford more than 150mA, Host Driver should set XPC to 1. Also
- * the value is meaningful only if Voltage Support in the Capabilities
- * register is set. The actual current value is 4 times the register
- * value.
- */
- max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
-
- if (!max_current_caps && mmc->supply.vmmc)
- {
- int curr = regulator_get_current_limit(mmc->supply.vmmc);
- if (curr > 0)
- {
- /* convert to SDHCI_MAX_CURRENT format */
- curr = curr / 1000; /* convert to mA */
- curr = curr / SDHCI_MAX_CURRENT_MULTIPLIER;
-
- curr = min_t(rt_uint32_t, curr, SDHCI_MAX_CURRENT_LIMIT);
- max_current_caps =
- FIELD_PREP(SDHCI_MAX_CURRENT_330_MASK, curr) | FIELD_PREP(SDHCI_MAX_CURRENT_300_MASK, curr) | FIELD_PREP(SDHCI_MAX_CURRENT_180_MASK, curr);
- }
- }
-
- if (host->caps & SDHCI_CAN_VDD_330)
- {
- ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
-
- mmc->max_current_330 = FIELD_GET(SDHCI_MAX_CURRENT_330_MASK,
- max_current_caps)
- * SDHCI_MAX_CURRENT_MULTIPLIER;
- }
- if (host->caps & SDHCI_CAN_VDD_300)
- {
- ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
-
- mmc->max_current_300 = FIELD_GET(SDHCI_MAX_CURRENT_300_MASK,
- max_current_caps)
- * SDHCI_MAX_CURRENT_MULTIPLIER;
- }
- if (host->caps & SDHCI_CAN_VDD_180)
- {
- ocr_avail |= MMC_VDD_165_195;
-
- mmc->max_current_180 = FIELD_GET(SDHCI_MAX_CURRENT_180_MASK,
- max_current_caps)
- * SDHCI_MAX_CURRENT_MULTIPLIER;
- }
-
- /* If OCR set by host, use it instead. */
- if (host->ocr_mask)
- ocr_avail = host->ocr_mask;
-
- /* If OCR set by external regulators, give it highest prio. */
- if (mmc->ocr_avail)
- ocr_avail = mmc->ocr_avail;
-
- mmc->ocr_avail = ocr_avail;
- mmc->ocr_avail_sdio = ocr_avail;
- if (host->ocr_avail_sdio)
- mmc->ocr_avail_sdio &= host->ocr_avail_sdio;
- mmc->ocr_avail_sd = ocr_avail;
- if (host->ocr_avail_sd)
- mmc->ocr_avail_sd &= host->ocr_avail_sd;
- else /* normal SD controllers don't support 1.8V */
- mmc->ocr_avail_sd &= ~MMC_VDD_165_195;
- mmc->ocr_avail_mmc = ocr_avail;
- if (host->ocr_avail_mmc)
- mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
-
- if (mmc->ocr_avail == 0)
- {
- rt_kprintf("%s: Hardware doesn't report any support voltages.\n",
- mmc_hostname(mmc));
- ret = -ENODEV;
- goto unreg;
- }
-
- if ((mmc->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR)) || (mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)))
- host->flags |= SDHCI_SIGNALING_180;
-
- if (mmc->caps2 & MMC_CAP2_HSX00_1_2V)
- host->flags |= SDHCI_SIGNALING_120;
-
- rt_spin_lock_init(&host->lock);
-
- /*
- * Maximum number of sectors in one transfer. Limited by SDMA boundary
- * size (512KiB). Note some tuning modes impose a 4MiB limit, but this
- * is less anyway.
- */
- mmc->max_req_size = 524288;
-
- /*
- * Maximum number of segments. Depends on if the hardware
- * can do scatter/gather or not.
- */
- if (host->flags & SDHCI_USE_SDMA)
- {
- mmc->max_segs = 1;
- }
- else
- { /* PIO */
- mmc->max_segs = SDHCI_MAX_SEGS;
- }
- /*
- * Maximum segment size. Could be one segment with the maximum number
- * of bytes. When doing hardware scatter/gather, each entry cannot
- * be larger than 64 KiB though.
- */
- mmc->max_seg_size = mmc->max_req_size;
-
- /*
- * Maximum block size. This varies from controller to controller and
- * is specified in the capabilities register.
- */
- if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048)
- {
- mmc->max_blk_size = 2;
- }
- else
- {
- mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
- if (mmc->max_blk_size >= 3)
- {
- rt_kprintf("%s: Invalid maximum block size, assuming 512 bytes\n",
- mmc_hostname(mmc));
- mmc->max_blk_size = 0;
- }
- }
-
- mmc->max_blk_size = 512 << mmc->max_blk_size;
-
- /*
- * Maximum block count.
- */
- mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
- return 0;
-
-unreg:
-undma:
- return ret;
-}
-
-static void sdhci_init(struct sdhci_host *host, int soft)
-{
- struct mmc_host *mmc = host->mmc;
- rt_base_t flags;
-
- if (soft)
- {
- sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- }
- else
- {
- sdhci_do_reset(host, SDHCI_RESET_ALL);
- }
- if (host->v4_mode)
- {
- sdhci_do_enable_v4_mode(host);
- }
- flags = rt_spin_lock_irqsave(&host->lock);
- sdhci_set_default_irqs(host);
- rt_spin_unlock_irqrestore(&host->lock, flags);
-
- host->cqe_on = RT_FALSE;
-
- if (soft)
- {
- /* force clock reconfiguration */
- host->clock = 0;
- host->reinit_uhs = RT_TRUE;
- mmc->ops->set_ios(mmc, &mmc->ios);
- }
-}
-
-static void sdhci_reinit(struct sdhci_host *host)
-{
- rt_uint32_t cd = host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
-
- sdhci_init(host, 0);
- sdhci_enable_card_detection(host);
-
- /*
- * A change to the card detect bits indicates a change in present state,
- * refer sdhci_set_card_detection(). A card detect interrupt might have
- * been missed while the host controller was being reset, so trigger a
- * rescan to check.
- */
- if (cd != (host->ier & (SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT)))
- mmc_detect_change(host->mmc, rt_tick_from_millisecond(200));
-}
-
-int __sdhci_add_host(struct sdhci_host *host)
-{
- struct mmc_host *mmc = host->mmc;
- int ret;
-
- if ((mmc->caps2 & MMC_CAP2_CQE) && (host->quirks & SDHCI_QUIRK_BROKEN_CQE))
- {
- mmc->caps2 &= ~MMC_CAP2_CQE;
- }
-
- host->complete_wq = rt_workqueue_create("sdhci", 4096, 20);
- if (!host->complete_wq)
- return -ENOMEM;
-
- rt_work_init(&host->complete_work, sdhci_complete_work, host);
-
- rt_timer_init(&host->timer, "sdhci_timer", sdhci_timeout_timer, host, 0, RT_TIMER_FLAG_SOFT_TIMER);
- rt_timer_init(&host->data_timer, "sdhci_data_timer", sdhci_timeout_data_timer, host, 0, RT_TIMER_FLAG_SOFT_TIMER);
-
- rt_wqueue_init(&host->buf_ready_int);
-
- sdhci_init(host, 0);
-
- host->irq_wq = rt_workqueue_create("sdhci_irq", 8192, 1);
- rt_work_init(&host->irq_work, sdhci_thread_irq, host);
- rt_hw_interrupt_install(host->irq, sdhci_irq, host, mmc_hostname(mmc));
- rt_pic_irq_unmask(host->irq);
- ret = mmc_add_host(mmc);
- if (ret)
- goto unirq;
-
- rt_kprintf("%s: SDHCI controller on %s [%s] using %s\n",
- mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->parent.name,
- (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
-
- sdhci_enable_card_detection(host);
-
- return 0;
-
-unirq:
- sdhci_reset_for_all(host);
- sdhci_writel(host, 0, SDHCI_INT_ENABLE);
- sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
-
- return ret;
-}
-
-int sdhci_add_host(struct sdhci_host *host)
-{
- int ret;
- ret = sdhci_setup_host(host);
- if (ret)
- return ret;
-
- ret = __sdhci_add_host(host);
- if (ret)
- goto cleanup;
-
- return 0;
-
-cleanup:
- sdhci_cleanup_host(host);
-
- return ret;
-}
-
-void sdhci_set_ios(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
-{
- struct sdhci_host *host = mmc_priv(mmc);
- rt_bool_t reinit_uhs = host->reinit_uhs;
- rt_bool_t turning_on_clk = RT_FALSE;
- rt_uint8_t ctrl;
-
- host->reinit_uhs = RT_FALSE;
-
- if (ios->power_mode == MMC_POWER_UNDEFINED)
- return;
-
- if (host->flags & SDHCI_DEVICE_DEAD)
- {
- if (mmc->supply.vmmc && ios->power_mode == MMC_POWER_OFF)
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
- return;
- }
-
- /*
- * Reset the chip on each power off.
- * Should clear out any weird states.
- */
- if (ios->power_mode == MMC_POWER_OFF)
- {
- sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- sdhci_reinit(host);
- }
-
- if (host->version >= SDHCI_SPEC_300 && (ios->power_mode == MMC_POWER_UP) && !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
- sdhci_enable_preset_value(host, RT_FALSE);
-
- if (!ios->clock || ios->clock != host->clock)
- {
- turning_on_clk = ios->clock && !host->clock;
-
- host->ops->set_clock(host, ios->clock);
- host->clock = ios->clock;
-
- if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && host->clock)
- {
- host->timeout_clk = mmc->actual_clock ? mmc->actual_clock / 1000 : host->clock / 1000;
- mmc->max_busy_timeout =
- host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27;
- mmc->max_busy_timeout /= host->timeout_clk;
- }
- }
-
- if (host->ops->set_power)
- host->ops->set_power(host, ios->power_mode, ios->vdd);
- else
- sdhci_set_power(host, ios->power_mode, ios->vdd);
-
- if (host->ops->platform_send_init_74_clocks)
- host->ops->platform_send_init_74_clocks(host, ios->power_mode);
-
- host->ops->set_bus_width(host, ios->bus_width);
-
- /*
- * Special case to avoid multiple clock changes during voltage
- * switching.
- */
- if (!reinit_uhs && turning_on_clk && host->timing == ios->timing && host->version >= SDHCI_SPEC_300 && !sdhci_presetable_values_change(host, ios))
- return;
-
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
- if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
- {
- if (ios->timing == MMC_TIMING_SD_HS || ios->timing == MMC_TIMING_MMC_HS || ios->timing == MMC_TIMING_MMC_HS400 || ios->timing == MMC_TIMING_MMC_HS200 || ios->timing == MMC_TIMING_MMC_DDR52 || ios->timing == MMC_TIMING_UHS_SDR50 || ios->timing == MMC_TIMING_UHS_SDR104 || ios->timing == MMC_TIMING_UHS_DDR50 || ios->timing == MMC_TIMING_UHS_SDR25)
- ctrl |= SDHCI_CTRL_HISPD;
- else
- ctrl &= ~SDHCI_CTRL_HISPD;
- }
-
- if (host->version >= SDHCI_SPEC_300)
- {
- rt_uint16_t clk, ctrl_2;
-
- /*
- * According to SDHCI Spec v3.00, if the Preset Value
- * Enable in the Host Control 2 register is set, we
- * need to reset SD Clock Enable before changing High
- * Speed Enable to avoid generating clock glitches.
- */
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- if (clk & SDHCI_CLOCK_CARD_EN)
- {
- clk &= ~SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- }
-
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
- if (!host->preset_enabled)
- {
- /*
- * We only need to set Driver Strength if the
- * preset value enable is not set.
- */
- ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
- if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
- else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B)
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
- else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
- else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
- else
- {
- LOG_D("%s: invalid driver type, default to driver type B\n",
- mmc_hostname(mmc));
- ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
- }
-
- sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
- host->drv_type = ios->drv_type;
- }
-
- host->ops->set_uhs_signaling(host, ios->timing);
- host->timing = ios->timing;
-
- if (sdhci_preset_needed(host, ios->timing))
- {
- rt_uint16_t preset;
-
- sdhci_enable_preset_value(host, RT_TRUE);
- preset = sdhci_get_preset_value(host);
- ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK,
- preset);
- host->drv_type = ios->drv_type;
- }
-
- /* Re-enable SD Clock */
- host->ops->set_clock(host, host->clock);
- }
- else
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-}
-void sdhci_free_host(struct sdhci_host *host)
-{
- sdhci_cleanup_host(host);
- rt_free(host);
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c
deleted file mode 100644
index 7c9eea3ba5..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/fit-mmc.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#include <rtthread.h>
-#include "sdhci.h"
-#include <rtdbg.h>
-#include <mmu.h>
-#include <drivers/core/dm.h>
-
-
-static void plat_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
-{
- struct mmc_host *mmc = (struct mmc_host *)host;
- rt_uint32_t flags = req->cmd->flags;
-
- switch (flags & RESP_MASK)
- {
- case RESP_NONE:
- flags |= MMC_RSP_NONE;
- break;
- case RESP_R1:
- flags |= MMC_RSP_R1;
- break;
- case RESP_R1B:
- flags |= MMC_RSP_R1B;
- break;
- case RESP_R2:
- flags |= MMC_RSP_R2;
- break;
- case RESP_R3:
- flags |= MMC_RSP_R3;
- break;
- case RESP_R4:
- flags |= MMC_RSP_R4;
- break;
- case RESP_R5:
- flags |= MMC_RSP_R5;
- break;
- case RESP_R6:
- flags |= MMC_RSP_R6;
- break;
- case RESP_R7:
- flags |= MMC_RSP_R7;
- break;
- }
- if (req->data)
- {
- if ((rt_uint64_t)rt_kmem_v2p(req->data->buf) > 0xffffffff)
- {
- void *dma_buffer = rt_malloc(ARCH_PAGE_SIZE);
- void *req_buf = NULL;
-
- if (req->data->blks * req->data->blksize > ARCH_PAGE_SIZE)
- {
- dma_buffer = rt_realloc(dma_buffer, req->data->blks * req->data->blksize);
- }
-
- if (req->data->flags & DATA_DIR_WRITE)
- {
- rt_memcpy(dma_buffer, req->data->buf, req->data->blks * req->data->blksize);
- req->data->buf = dma_buffer;
- }
- else if (req->data->flags & DATA_DIR_READ)
- {
- req_buf = req->data->buf;
- req->data->buf = dma_buffer;
- }
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
-
- rt_sem_take(&host->sem_ack, RT_WAITING_FOREVER);
-
- if (req->data->flags & DATA_DIR_READ)
- {
- rt_memcpy(req_buf, dma_buffer, req->data->blksize * req->data->blks);
- req->data->buf = req_buf;
- }
-
- rt_free(dma_buffer);
- rt_sem_release(&host->sem_ack);
- }
- else
- {
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
- }
- }
- else
- {
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
- }
-}
-
-static void plat_set_ioconfig(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *iocfg)
-{
- struct mmc_host *mmc = (struct mmc_host *)host;
-
- LOG_D("clock:%d,width:%d,power:%d,vdd:%d,timing:%d\n",
- iocfg->clock, iocfg->bus_width,
- iocfg->power_mode, iocfg->vdd, iocfg->timing);
-
- mmc->ops->set_ios(mmc, iocfg);
-}
-
-static rt_int32_t plat_get_card_status(struct rt_mmcsd_host *host)
-{
- struct mmc_host *mmc = (struct mmc_host *)host;
-
- return mmc->ops->get_cd(mmc);
-}
-
-static rt_int32_t plat_execute_tuning(struct rt_mmcsd_host *host, rt_int32_t opcode)
-{
- struct mmc_host *mmc = (struct mmc_host *)host;
-
- return mmc->ops->execute_tuning(mmc, opcode);
-}
-
-static void plat_enable_sdio_irq(struct rt_mmcsd_host *host, rt_int32_t en)
-{
- struct mmc_host *mmc = (struct mmc_host *)host;
-
- return mmc->ops->enable_sdio_irq(mmc, en);
-}
-
-
-static const struct rt_mmcsd_host_ops rt_mmcsd_ops = {
- .request = plat_request,
- .set_iocfg = plat_set_ioconfig,
- .get_card_status = plat_get_card_status,
- .enable_sdio_irq = plat_enable_sdio_irq,
- .execute_tuning = plat_execute_tuning,
-};
-
-
-void mmc_request_done(struct mmc_host *host, struct rt_mmcsd_req *mrq)
-{
- mmcsd_req_complete(&host->rthost);
-}
-
-/*add host in rtt while sdhci complete*/
-int mmc_add_host(struct mmc_host *mmc)
-{
- mmc->rthost.ops = &rt_mmcsd_ops;
- mmc->rthost.flags = mmc->caps;
- mmc->rthost.freq_max = mmc->f_max;
- mmc->rthost.freq_min = 400000;
- mmc->rthost.max_dma_segs = mmc->max_segs;
- mmc->rthost.max_seg_size = mmc->max_seg_size;
- mmc->rthost.max_blk_size = mmc->max_blk_size;
- mmc->rthost.max_blk_count = mmc->max_blk_count;
- mmc->rthost.valid_ocr = VDD_33_34 | VDD_32_33 | VDD_31_32 | VDD_30_31 | VDD_165_195 | VDD_20_21;
-
-
- mmcsd_change(&mmc->rthost);
- return 0;
-}
-
-struct mmc_host *mmc_alloc_host(int extra, struct rt_device *dev)
-{
- struct mmc_host *mmc;
-
- mmc = rt_malloc(sizeof(*mmc) + extra);
- if (mmc)
- {
- rt_memset(mmc, 0, sizeof(*mmc) + extra);
- mmc->parent = dev;
- mmcsd_host_init(&mmc->rthost);
- }
-
- return mmc;
-}
-
-void mmc_remove_host(struct mmc_host *host)
-{
- rt_free(host);
-}
-
-int mmc_abort_tuning(struct mmc_host *host, rt_uint32_t opcode)
-{
- return 0;
-}
-
-
-int mmc_gpio_get_cd(struct mmc_host *host)
-{
- return -ENOSYS;
-}
-
-void mmc_detect_change(struct mmc_host *host, unsigned long delay)
-{
-}
-
-
-int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
-{
- return 0;
-}
-
-rt_bool_t mmc_can_gpio_ro(struct mmc_host *host)
-{
- return RT_FALSE;
-}
-
-int mmc_gpio_get_ro(struct mmc_host *host)
-{
- return 0;
-}
-
-int mmc_send_abort_tuning(struct mmc_host *host, rt_uint32_t opcode)
-{
- return 0;
-}
-int mmc_of_parse(struct mmc_host *host)
-{
- struct rt_device *dev = host->parent;
- rt_uint32_t bus_width;
-
- if (!dev || !dev->ofw_node)
- return 0;
-
- /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
- if (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) < 0)
- {
- bus_width = 1;
- }
-
- switch (bus_width)
- {
- case 8:
- host->caps |= MMC_CAP_8_BIT_DATA;
- break; /* Hosts capable of 8-bit can also do 4 bits */
- case 4:
- host->caps |= MMC_CAP_4_BIT_DATA;
- break;
- case 1:
- break;
- default:
- return -EINVAL;
- }
-
- /* f_max is obtained from the optional "max-frequency" property */
- rt_dm_dev_prop_read_u32(dev, "max-frequency", &host->f_max);
-
- if (rt_dm_dev_prop_read_bool(dev, "cap-mmc-highspeed"))
- {
- host->caps |= MMC_CAP_MMC_HIGHSPEED;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "mmc-hs200-1_8v"))
- {
- host->caps |= MMC_CAP2_HS200_1_8V_SDR;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "non-removable"))
- {
- host->caps |= MMC_CAP_NONREMOVABLE;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "no-sdio"))
- {
- host->caps2 |= MMC_CAP2_NO_SDIO;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "no-sd"))
- {
- host->caps2 |= MMC_CAP2_NO_SD;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-3_3v"))
- {
- host->caps |= MMC_CAP_3_3V_DDR;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_8v"))
- {
- host->caps |= MMC_CAP_1_8V_DDR;
- }
-
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_2v"))
- {
- host->caps |= MMC_CAP_1_2V_DDR;
- }
-
- return 0;
-}
-
-
-void mmc_free_host(struct mmc_host *host)
-{
-}
-
-rt_bool_t mmc_can_gpio_cd(struct mmc_host *host)
-{
- return RT_FALSE;
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c
deleted file mode 100644
index 29d296f9de..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_dma.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#include "sdhci.h"
-#include <rtthread.h>
-
-
-int dma_set_mask_and_coherent(struct rt_device *dev, rt_uint64_t mask)
-{
- return 0;
-}
-
-unsigned long virt_to_phys(volatile void *address)
-{
- return (unsigned long)((rt_uint64_t)address + PV_OFFSET);
-}
-void *dma_alloc_coherent(struct rt_device *dev, size_t size,
- rt_uint64_t *dma_handle)
-{
- void *v;
-
- v = rt_malloc_align(size, 2048);
- rt_kprintf("v = %p \n", v);
- if (v)
- {
- *dma_handle = virt_to_phys(v);
- v = rt_ioremap((void *)*dma_handle, size);
- rt_kprintf("v = %p *dma_handle = %p \n", v, *dma_handle);
- }
-
- return v;
-}
-
-void dma_free_coherent(struct rt_device *dev, size_t size,
- void *cpu_addr, unsigned long dma_handle)
-{
- rt_free(cpu_addr);
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c b/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c
deleted file mode 100644
index 44ed683db9..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/drivers/sdhci/src/sdhci_voltage.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
-#include "sdhci.h"
-
-int mmc_regulator_get_supply(struct mmc_host *mmc)
-{
- mmc->supply.vmmc = -RT_NULL;
- mmc->supply.vqmmc = -RT_NULL;
-
- return 0;
-}
-int regulator_get_current_limit(struct regulator *regulator)
-{
- return 0;
-}
-
-int regulator_is_supported_voltage(struct regulator *regulator,
-
- int min_uV, int max_uV)
-{
- return 0;
-}
-
-int regulator_enable(struct regulator *regulator)
-{
- return 0;
-}
-void regulator_disable(struct regulator *regulator)
-{
-}
diff --git a/bsp/raspberry-pi/raspi-dm2.0/qemu.sh b/bsp/raspberry-pi/raspi-dm2.0/qemu.sh
deleted file mode 100644
index b795a9bcb5..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/qemu.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-if [ ! -f "sd.bin" ]; then
- dd if=/dev/zero of=sd.bin bs=1024 count=65536
-fi
-
-qemu-system-aarch64 -M raspi4b -serial stdio \
- -kernel rtthread.bin \
- -drive if=sd,file=sd.bin \
- -dtb bcm2711-rpi-4-b.dtb \
- -append 'printk.time=0 earlycon=pl011,0xfe201000 console=ttyAMA0 root=ram0 rw'
diff --git a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.py b/bsp/raspberry-pi/raspi-dm2.0/rtconfig.py
deleted file mode 100644
index 106618e010..0000000000
--- a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import os
-
-# toolchains options
-ARCH ='aarch64'
-CPU ='cortex-a'
-CROSS_TOOL ='gcc'
-
-if os.getenv('RTT_ROOT'):
- RTT_ROOT = os.getenv('RTT_ROOT')
-else:
- RTT_ROOT = r'../../..'
-
-if os.getenv('RTT_CC'):
- CROSS_TOOL = os.getenv('RTT_CC')
-
-PLATFORM = 'gcc'
-EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/'
-
-if os.getenv('RTT_EXEC_PATH'):
- EXEC_PATH = os.getenv('RTT_EXEC_PATH')
-
-BUILD = 'debug'
-
-if PLATFORM == 'gcc':
- # toolchains
- PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
- CC = PREFIX + 'gcc'
- CPP = PREFIX + 'g++'
- AS = PREFIX + 'gcc'
- AR = PREFIX + 'ar'
- LINK = PREFIX + 'gcc'
- TARGET_EXT = 'elf'
- SIZE = PREFIX + 'size'
- OBJDUMP = PREFIX + 'objdump'
- OBJCPY = PREFIX + 'objcopy'
-
- DEVICE = ' -march=armv8-a -mtune=cortex-a72 -fdiagnostics-color=always'
- CPPFLAGS = ' -E -P -x assembler-with-cpp'
- CFLAGS = DEVICE + ' -Wall -Wno-cpp -D_POSIX_SOURCE'
- AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
- LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
- CPATH = ''
- LPATH = ''
-
- if BUILD == 'debug':
- CFLAGS += ' -O0 -ggdb'
- AFLAGS += ' -ggdb'
- else:
- CFLAGS += ' -O2'
-
- CXXFLAGS = CFLAGS
-
-DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
-POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
diff --git a/bsp/raspberry-pi/raspi3-64/.config b/bsp/raspberry-pi/raspi3-64/.config
index 7c75cd4eea..909cdedd1b 100644
--- a/bsp/raspberry-pi/raspi3-64/.config
+++ b/bsp/raspberry-pi/raspi3-64/.config
@@ -11,18 +11,8 @@
# rt_vsnprintf options
#
# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set
-CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y
-# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set
-CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6
-CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9
-CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
+# CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG is not set
+# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set
# end of rt_vsnprintf options
#
@@ -116,13 +106,13 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
# end of rt_strnlen options
# end of klibc options
-CONFIG_RT_NAME_MAX=12
+CONFIG_RT_NAME_MAX=24
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_NANO is not set
# CONFIG_RT_USING_SMART is not set
# CONFIG_RT_USING_AMP is not set
-# CONFIG_RT_USING_SMP is not set
-CONFIG_RT_CPUS_NR=1
+CONFIG_RT_USING_SMP=y
+CONFIG_RT_CPUS_NR=4
CONFIG_RT_ALIGN_SIZE=8
# CONFIG_RT_THREAD_PRIORITY_8 is not set
CONFIG_RT_THREAD_PRIORITY_32=y
@@ -136,11 +126,13 @@ CONFIG_RT_HOOK_USING_FUNC_PTR=y
CONFIG_RT_USING_IDLE_HOOK=y
CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
CONFIG_IDLE_THREAD_STACK_SIZE=8192
+CONFIG_SYSTEM_THREAD_STACK_SIZE=8192
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
-CONFIG_RT_TIMER_THREAD_STACK_SIZE=4096
+CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192
# CONFIG_RT_USING_TIMER_ALL_SOFT is not set
-# CONFIG_RT_USING_CPU_USAGE_TRACER is not set
+CONFIG_RT_USING_CPU_USAGE_TRACER=y
+CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200
#
# kservice options
@@ -153,6 +145,8 @@ CONFIG_RT_DEBUGING_ASSERT=y
CONFIG_RT_DEBUGING_COLOR=y
CONFIG_RT_DEBUGING_CONTEXT=y
# CONFIG_RT_DEBUGING_AUTO_INIT is not set
+# CONFIG_RT_DEBUGING_SPINLOCK is not set
+# CONFIG_RT_DEBUGING_CRITICAL is not set
# CONFIG_RT_USING_CI_ACTION is not set
#
@@ -188,14 +182,14 @@ CONFIG_RT_USING_HEAP=y
CONFIG_RT_USING_DEVICE=y
CONFIG_RT_USING_DEVICE_OPS=y
-# CONFIG_RT_USING_INTERRUPT_INFO is not set
+CONFIG_RT_USING_INTERRUPT_INFO=y
# CONFIG_RT_USING_THREADSAFE_PRINTF is not set
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=512
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y
CONFIG_RT_VER_NUM=0x50300
-# CONFIG_RT_USING_STDC_ATOMIC is not set
+CONFIG_RT_USING_STDC_ATOMIC=y
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
# end of RT-Thread Kernel
@@ -206,7 +200,7 @@ CONFIG_ARCH_TEXT_OFFSET=0x200000
CONFIG_ARCH_RAM_OFFSET=0
CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=4096
CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-# CONFIG_ARCH_USING_GENERIC_CPUID is not set
+CONFIG_ARCH_USING_GENERIC_CPUID=y
CONFIG_ARCH_HEAP_SIZE=0x4000000
CONFIG_ARCH_INIT_PAGE_SIZE=0x200000
# end of AArch64 Architecture Configuration
@@ -219,6 +213,7 @@ CONFIG_ARCH_ARM=y
CONFIG_ARCH_ARM_MMU=y
CONFIG_ARCH_ARMV8=y
CONFIG_ARCH_USING_ASID=y
+CONFIG_ARCH_USING_HW_THREAD_SELF=y
CONFIG_ARCH_USING_IRQ_CTX_LIST=y
#
@@ -226,7 +221,7 @@ CONFIG_ARCH_USING_IRQ_CTX_LIST=y
#
CONFIG_RT_USING_COMPONENTS_INIT=y
CONFIG_RT_USING_USER_MAIN=y
-CONFIG_RT_MAIN_THREAD_STACK_SIZE=4096
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
CONFIG_RT_MAIN_THREAD_PRIORITY=10
# CONFIG_RT_USING_LEGACY is not set
CONFIG_RT_USING_MSH=y
@@ -234,7 +229,7 @@ CONFIG_RT_USING_FINSH=y
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_THREAD_NAME="tshell"
CONFIG_FINSH_THREAD_PRIORITY=20
-CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_THREAD_STACK_SIZE=8192
CONFIG_FINSH_USING_HISTORY=y
CONFIG_FINSH_HISTORY_LINES=5
# CONFIG_FINSH_USING_WORD_OPERATION is not set
@@ -254,12 +249,9 @@ CONFIG_FINSH_USING_OPTION_COMPLETION=y
CONFIG_RT_USING_DFS=y
CONFIG_DFS_USING_POSIX=y
CONFIG_DFS_USING_WORKDIR=y
-# CONFIG_RT_USING_DFS_MNTTABLE is not set
CONFIG_DFS_FD_MAX=16
-CONFIG_RT_USING_DFS_V1=y
-# CONFIG_RT_USING_DFS_V2 is not set
-CONFIG_DFS_FILESYSTEMS_MAX=2
-CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
+# CONFIG_RT_USING_DFS_V1 is not set
+CONFIG_RT_USING_DFS_V2=y
CONFIG_RT_USING_DFS_ELMFAT=y
#
@@ -287,11 +279,8 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000
# end of elm-chan's FatFs, Generic FAT Filesystem Module
CONFIG_RT_USING_DFS_DEVFS=y
-# CONFIG_RT_USING_DFS_9PFS is not set
-# CONFIG_RT_USING_DFS_ISO9660 is not set
# CONFIG_RT_USING_DFS_ROMFS is not set
# CONFIG_RT_USING_DFS_CROMFS is not set
-# CONFIG_RT_USING_DFS_RAMFS is not set
# CONFIG_RT_USING_DFS_TMPFS is not set
# CONFIG_RT_USING_DFS_MQUEUE is not set
# end of DFS: device virtual file system
@@ -301,62 +290,154 @@ CONFIG_RT_USING_DFS_DEVFS=y
#
# Device Drivers
#
-# CONFIG_RT_USING_DM is not set
+CONFIG_RT_USING_DM=y
# CONFIG_RT_USING_DEV_BUS is not set
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_UNAMED_PIPE_NUMBER=64
-# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
+CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=8192
+CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
# CONFIG_RT_SERIAL_USING_DMA is not set
CONFIG_RT_SERIAL_RB_BUFSZ=64
-# CONFIG_RT_USING_SERIAL_BYPASS is not set
+CONFIG_RT_USING_SERIAL_BYPASS=y
+# CONFIG_RT_SERIAL_EARLY_HVC is not set
+CONFIG_RT_SERIAL_PL011=y
+CONFIG_RT_SERIAL_8250=y
+# CONFIG_RT_SERIAL_8250_DW is not set
+CONFIG_RT_SERIAL_8250_BCM2835AUX=y
# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_ADC is not set
CONFIG_RT_USING_CLOCK_TIME=y
+# CONFIG_RT_USING_CLOCK_TIMER_TRIGGER is not set
+CONFIG_RT_CLOCK_TIME_ARM_ARCH=y
+CONFIG_RT_CLOCK_TIME_BCM2835=y
+# CONFIG_RT_USING_ETHERNET is not set
CONFIG_RT_USING_I2C=y
CONFIG_RT_I2C_DEBUG=y
-CONFIG_RT_USING_I2C_BITOPS=y
-# CONFIG_RT_I2C_BITOPS_DEBUG is not set
+# CONFIG_RT_USING_I2C_BITOPS is not set
# CONFIG_RT_USING_SOFT_I2C is not set
+CONFIG_RT_I2C_BCM2835=y
+# CONFIG_RT_I2C_BRCMSTB is not set
# CONFIG_RT_USING_PHY is not set
# CONFIG_RT_USING_PHY_V2 is not set
-# CONFIG_RT_USING_ADC is not set
# CONFIG_RT_USING_DAC is not set
-# CONFIG_RT_USING_NULL is not set
-# CONFIG_RT_USING_ZERO is not set
-# CONFIG_RT_USING_RANDOM is not set
-# CONFIG_RT_USING_PWM is not set
+CONFIG_RT_USING_NULL=y
+CONFIG_RT_USING_ZERO=y
+CONFIG_RT_USING_RANDOM=y
+CONFIG_RT_USING_PWM=y
+CONFIG_RT_PWM_BCM2835=y
+# CONFIG_RT_PWM_BRCMSTB is not set
+# CONFIG_RT_PWM_RP1 is not set
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
-# CONFIG_RT_USING_MTD_NOR is not set
+CONFIG_RT_USING_MTD_NOR=y
+# CONFIG_RT_USING_MTD_NOR_CFI is not set
+CONFIG_RT_USING_MTD_NOR_SPI=y
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
-# CONFIG_RT_USING_RTC is not set
+CONFIG_RT_USING_RTC=y
+CONFIG_RT_USING_ALARM=y
+CONFIG_RT_ALARM_STACK_SIZE=8192
+CONFIG_RT_ALARM_TIMESLICE=5
+CONFIG_RT_ALARM_PRIORITY=10
+# CONFIG_RT_ALARM_USING_LOCAL_TIME is not set
+# CONFIG_RT_USING_SOFT_RTC is not set
+# CONFIG_RT_RTC_DS1302 is not set
+CONFIG_RT_RTC_DS1307=y
+# CONFIG_RT_RTC_GOLDFISH is not set
+# CONFIG_RT_RTC_HYM8563 is not set
+# CONFIG_RT_RTC_PCF8523 is not set
+# CONFIG_RT_RTC_PCF8563 is not set
+# CONFIG_RT_RTC_PL031 is not set
+# CONFIG_RT_RTC_RX8010 is not set
+# CONFIG_RT_RTC_RPI is not set
CONFIG_RT_USING_SDIO=y
-CONFIG_RT_SDIO_STACK_SIZE=2048
+CONFIG_RT_SDIO_STACK_SIZE=8192
CONFIG_RT_SDIO_THREAD_PRIORITY=15
-CONFIG_RT_MMCSD_STACK_SIZE=4096
+CONFIG_RT_MMCSD_STACK_SIZE=8192
CONFIG_RT_MMCSD_THREAD_PRIORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
-CONFIG_RT_SDIO_DEBUG=y
-# CONFIG_RT_USING_SDHCI is not set
+# CONFIG_RT_SDIO_DEBUG is not set
+CONFIG_RT_USING_SDHCI=y
+# CONFIG_RT_SDIO_DW_MMC is not set
+# CONFIG_RT_SDIO_SDHCI_DWCMSHC is not set
+# CONFIG_RT_SDIO_SDHCI_BRCMSTB is not set
+CONFIG_RT_SDIO_SDHCI_IPROC=y
CONFIG_RT_USING_SPI=y
CONFIG_RT_USING_SPI_ISR=y
# CONFIG_RT_USING_SPI_BITOPS is not set
# CONFIG_RT_USING_SOFT_SPI is not set
# CONFIG_RT_USING_QSPI is not set
# CONFIG_RT_USING_SPI_MSD is not set
-# CONFIG_RT_USING_SFUD is not set
+CONFIG_RT_USING_SFUD=y
+CONFIG_RT_SFUD_USING_SFDP=y
+CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y
+# CONFIG_RT_SFUD_USING_QSPI is not set
+CONFIG_RT_SFUD_SPI_MAX_HZ=50000000
+# CONFIG_RT_DEBUG_SFUD is not set
# CONFIG_RT_USING_ENC28J60 is not set
# CONFIG_RT_USING_SPI_WIFI is not set
+CONFIG_RT_SPI_BCM2835=y
+# CONFIG_RT_SPI_BCM2835AUX is not set
CONFIG_RT_USING_WDT=y
-# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_WDT_DW is not set
+CONFIG_RT_WDT_BCM2835=y
+CONFIG_RT_USING_AUDIO=y
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2
+CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048
+CONFIG_RT_AUDIO_BCM2835_I2S=y
# CONFIG_RT_USING_SENSOR is not set
# CONFIG_RT_USING_TOUCH is not set
-# CONFIG_RT_USING_LCD is not set
-# CONFIG_RT_USING_HWCRYPTO is not set
+CONFIG_RT_USING_LCD=y
+CONFIG_RT_USING_GRAPHIC=y
+# CONFIG_RT_GRAPHIC_BACKLIGHT is not set
+CONFIG_RT_GRAPHIC_FB=y
+# CONFIG_RT_GRAPHIC_FB_ILI9486 is not set
+# CONFIG_RT_GRAPHIC_FB_SIMPLE is not set
+CONFIG_RT_GRAPHIC_FB_BCM2708=y
+CONFIG_RT_GRAPHIC_LOGO=y
+# CONFIG_RT_GRAPHIC_LOGO_NONE is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_CLUT224 is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_WHITE_CLUT224 is not set
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224=y
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH="../dm/graphic/logo/logo-raspi-clut224.ppm"
+CONFIG_RT_USING_HWCRYPTO=y
+CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto"
+CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16
+CONFIG_RT_HWCRYPTO_KEYBIT_MAX_SIZE=256
+# CONFIG_RT_HWCRYPTO_USING_GCM is not set
+# CONFIG_RT_HWCRYPTO_USING_AES is not set
+# CONFIG_RT_HWCRYPTO_USING_DES is not set
+# CONFIG_RT_HWCRYPTO_USING_3DES is not set
+# CONFIG_RT_HWCRYPTO_USING_RC4 is not set
+# CONFIG_RT_HWCRYPTO_USING_MD5 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA1 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA2 is not set
+CONFIG_RT_HWCRYPTO_USING_RNG=y
+# CONFIG_RT_HWCRYPTO_USING_CRC is not set
+# CONFIG_RT_HWCRYPTO_USING_BIGNUM is not set
+CONFIG_RT_HWCRYPTO_RNG_BCM2835=y
+# CONFIG_RT_HWCRYPTO_RNG_IPROC_RNG200 is not set
# CONFIG_RT_USING_WIFI is not set
+# CONFIG_RT_USING_PTP is not set
+CONFIG_RT_USING_LED=y
+CONFIG_RT_LED_GPIO=y
+# CONFIG_RT_LED_PWM is not set
+# CONFIG_RT_LED_SYSCON is not set
+# CONFIG_RT_USING_INPUT is not set
+CONFIG_RT_USING_MBOX=y
+# CONFIG_RT_MBOX_PIC is not set
+CONFIG_RT_MBOX_BCM2835=y
+# CONFIG_RT_USING_HWSPINLOCK is not set
+# CONFIG_RT_USING_RPMSG is not set
+CONFIG_RT_USING_PHYE=y
+CONFIG_RT_PHYE_GENERIC_USB=y
+# CONFIG_RT_USING_ATA is not set
+# CONFIG_RT_USING_NVME is not set
CONFIG_RT_USING_BLK=y
#
@@ -366,11 +447,93 @@ CONFIG_RT_BLK_PARTITION_DFS=y
CONFIG_RT_BLK_PARTITION_EFI=y
# end of Partition Types
-# CONFIG_RT_USING_REGULATOR is not set
+# CONFIG_RT_USING_SCSI is not set
+CONFIG_RT_USING_FIRMWARE=y
+# CONFIG_RT_FIRMWARE_QEMU_FW_CFG is not set
+# CONFIG_RT_FIRMWARE_ARM_SCMI is not set
+CONFIG_RT_FIRMWARE_RASPBERRYPI=y
+# CONFIG_RT_USING_TEE is not set
+# CONFIG_RT_USING_HWCACHE is not set
+# CONFIG_RT_USING_DVFS is not set
+CONFIG_RT_USING_REGULATOR=y
+# CONFIG_RT_REGULATOR_FAN53555 is not set
+CONFIG_RT_REGULATOR_FIXED=y
+CONFIG_RT_REGULATOR_GPIO=y
+# CONFIG_RT_REGULATOR_PWM is not set
+CONFIG_RT_USING_RESET=y
+# CONFIG_RT_RESET_SIMPLE is not set
+# CONFIG_RT_RESET_BRCMSTB_RESCAL is not set
+# CONFIG_RT_RESET_BRCMSTB is not set
+# CONFIG_RT_RESET_RASPBERRYPI is not set
+
+#
+# Power Management (PM) Domains device drivers
+#
+CONFIG_RT_PMDOMAIN_BCM2835=y
+CONFIG_RT_PMDOMAIN_RASPBERRYPI=y
+# end of Power Management (PM) Domains device drivers
+
+# CONFIG_RT_USING_POWER_RESET is not set
# CONFIG_RT_USING_POWER_SUPPLY is not set
+CONFIG_RT_USING_THERMAL=y
+
+#
+# Thermal Sensors Drivers
+#
+CONFIG_RT_THERMAL_BCM2835=y
+# CONFIG_RT_THERMAL_BCM2711 is not set
+
+#
+# Thermal Cool Drivers
+#
+# CONFIG_RT_THERMAL_COOL_GPIO_FAN is not set
+# CONFIG_RT_THERMAL_COOL_PWM_FAN is not set
# CONFIG_RT_USING_VIRTIO is not set
+CONFIG_RT_USING_NVMEM=y
+CONFIG_RT_NVMEM_RASPBERRYPI_OTP=y
+CONFIG_RT_USING_DMA=y
+# CONFIG_RT_DMA_PL330 is not set
+# CONFIG_RT_DMA_DW_AXI_DMAC is not set
+CONFIG_RT_DMA_BCM2835=y
+CONFIG_RT_USING_MFD=y
+CONFIG_RT_MFD_SYSCON=y
+CONFIG_RT_MFD_BCM2835_PM=y
+# CONFIG_RT_MFD_RPI_SENSE is not set
+CONFIG_RT_USING_OFW=y
+# CONFIG_RT_USING_BUILTIN_FDT is not set
+CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128
+CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8
+# CONFIG_RT_USING_PCI is not set
+CONFIG_RT_USING_PIC=y
+# CONFIG_RT_USING_PIC_STATISTICS is not set
+CONFIG_MAX_HANDLERS=256
+# CONFIG_RT_PIC_ARM_GIC is not set
+# CONFIG_RT_PIC_ARM_GIC_V3 is not set
+CONFIG_RT_PIC_BCM2835_INTC=y
+CONFIG_RT_PIC_BCM2836_L1_INTC=y
+# CONFIG_RT_PIC_BRCMSTB_L2_IRQ is not set
CONFIG_RT_USING_PIN=y
+# CONFIG_RT_PIN_PL061 is not set
+CONFIG_RT_PIN_BCM_VIRT=y
+# CONFIG_RT_PIN_BRCMSTB is not set
+CONFIG_RT_PIN_RASPBERRYPI_EXP=y
+CONFIG_RT_USING_PINCTRL=y
+# CONFIG_RT_PINCTRL_SINGLE is not set
+# CONFIG_RT_PINCTRL_BCM2712 is not set
+CONFIG_RT_PINCTRL_BCM2835=y
+# CONFIG_RT_PINCTRL_RP1 is not set
+CONFIG_RT_USING_CLK=y
+# CONFIG_RT_CLK_BCM2711_DVP is not set
+CONFIG_RT_CLK_BCM2835=y
+CONFIG_RT_CLK_RASPBERRYPI=y
+# CONFIG_RT_CLK_RP1 is not set
# CONFIG_RT_USING_CHERRYUSB is not set
+
+#
+# SoC (System on Chip) Drivers
+#
+CONFIG_RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR=y
+# end of SoC (System on Chip) Drivers
# end of Device Drivers
#
@@ -395,10 +558,20 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
#
# POSIX (Portable Operating System Interface) layer
#
-# CONFIG_RT_USING_POSIX_FS is not set
-# CONFIG_RT_USING_POSIX_DELAY is not set
-# CONFIG_RT_USING_POSIX_CLOCK is not set
-# CONFIG_RT_USING_POSIX_TIMER is not set
+CONFIG_RT_USING_POSIX_FS=y
+CONFIG_RT_USING_POSIX_DEVIO=y
+CONFIG_RT_USING_POSIX_STDIO=y
+CONFIG_RT_USING_POSIX_POLL=y
+# CONFIG_RT_USING_POSIX_SELECT is not set
+# CONFIG_RT_USING_POSIX_EVENTFD is not set
+# CONFIG_RT_USING_POSIX_TIMERFD is not set
+# CONFIG_RT_USING_POSIX_SOCKET is not set
+CONFIG_RT_USING_POSIX_TERMIOS=y
+# CONFIG_RT_USING_POSIX_AIO is not set
+# CONFIG_RT_USING_POSIX_MMAN is not set
+CONFIG_RT_USING_POSIX_DELAY=y
+CONFIG_RT_USING_POSIX_CLOCK=y
+CONFIG_RT_USING_POSIX_TIMER=y
# CONFIG_RT_USING_PTHREADS is not set
# CONFIG_RT_USING_MODULE is not set
@@ -421,9 +594,90 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
#
# Network
#
-# CONFIG_RT_USING_SAL is not set
-# CONFIG_RT_USING_NETDEV is not set
-# CONFIG_RT_USING_LWIP is not set
+CONFIG_RT_USING_SAL=y
+CONFIG_SAL_INTERNET_CHECK=y
+CONFIG_SOCKET_TABLE_STEP_LEN=4
+
+#
+# Docking with protocol stacks
+#
+CONFIG_SAL_USING_LWIP=y
+# CONFIG_SAL_USING_AT is not set
+# CONFIG_SAL_USING_TLS is not set
+# end of Docking with protocol stacks
+
+CONFIG_SAL_USING_POSIX=y
+CONFIG_RT_USING_NETDEV=y
+CONFIG_NETDEV_USING_IFCONFIG=y
+CONFIG_NETDEV_USING_PING=y
+CONFIG_NETDEV_USING_NETSTAT=y
+CONFIG_NETDEV_USING_AUTO_DEFAULT=y
+# CONFIG_NETDEV_USING_LINK_STATUS_CALLBACK is not set
+# CONFIG_NETDEV_USING_IPV6 is not set
+CONFIG_NETDEV_IPV4=1
+CONFIG_NETDEV_IPV6=0
+CONFIG_RT_USING_LWIP=y
+# CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set
+# CONFIG_RT_USING_LWIP141 is not set
+# CONFIG_RT_USING_LWIP203 is not set
+CONFIG_RT_USING_LWIP212=y
+# CONFIG_RT_USING_LWIP_LATEST is not set
+CONFIG_RT_USING_LWIP_VER_NUM=0x20102
+# CONFIG_RT_USING_LWIP_IPV6 is not set
+CONFIG_RT_LWIP_MEM_ALIGNMENT=8
+CONFIG_RT_LWIP_IGMP=y
+CONFIG_RT_LWIP_ICMP=y
+# CONFIG_RT_LWIP_SNMP is not set
+CONFIG_RT_LWIP_DNS=y
+CONFIG_RT_LWIP_DHCP=y
+CONFIG_IP_SOF_BROADCAST=1
+CONFIG_IP_SOF_BROADCAST_RECV=1
+
+#
+# Static IPv4 Address
+#
+CONFIG_RT_LWIP_IPADDR="192.168.1.30"
+CONFIG_RT_LWIP_GWADDR="192.168.1.1"
+CONFIG_RT_LWIP_MSKADDR="255.255.255.0"
+# end of Static IPv4 Address
+
+CONFIG_RT_LWIP_UDP=y
+CONFIG_RT_LWIP_TCP=y
+CONFIG_RT_LWIP_RAW=y
+# CONFIG_RT_LWIP_PPP is not set
+CONFIG_RT_MEMP_NUM_NETCONN=8
+CONFIG_RT_LWIP_PBUF_NUM=16
+CONFIG_RT_LWIP_RAW_PCB_NUM=4
+CONFIG_RT_LWIP_UDP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_SEG_NUM=40
+CONFIG_RT_LWIP_TCP_SND_BUF=8196
+CONFIG_RT_LWIP_TCP_WND=8196
+CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
+CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=16384
+CONFIG_LWIP_NO_RX_THREAD=y
+CONFIG_LWIP_NO_TX_THREAD=y
+CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=8192
+CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
+# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
+CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
+CONFIG_LWIP_NETIF_LINK_CALLBACK=1
+CONFIG_RT_LWIP_NETIF_NAMESIZE=6
+CONFIG_SO_REUSE=1
+CONFIG_LWIP_SO_RCVTIMEO=1
+CONFIG_LWIP_SO_SNDTIMEO=1
+CONFIG_LWIP_SO_RCVBUF=1
+CONFIG_LWIP_SO_LINGER=0
+# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set
+CONFIG_LWIP_NETIF_LOOPBACK=0
+# CONFIG_RT_LWIP_STATS is not set
+# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
+CONFIG_RT_LWIP_USING_PING=y
+# CONFIG_LWIP_USING_DHCPD is not set
+# CONFIG_RT_LWIP_ENABLE_USER_HOOKS is not set
+# CONFIG_RT_LWIP_DEBUG is not set
# CONFIG_RT_USING_AT is not set
# end of Network
@@ -441,7 +695,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0
# CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_VAR_EXPORT is not set
-# CONFIG_RT_USING_RESOURCE_ID is not set
+CONFIG_RT_USING_RESOURCE_ID=y
CONFIG_RT_USING_ADT=y
CONFIG_RT_USING_ADT_AVL=y
CONFIG_RT_USING_ADT_BITMAP=y
@@ -456,7 +710,8 @@ CONFIG_RT_USING_ADT_REF=y
# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set
CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000
CONFIG_RT_PAGE_MAX_ORDER=11
-# CONFIG_RT_USING_MEMBLOCK is not set
+CONFIG_RT_USING_MEMBLOCK=y
+CONFIG_RT_INIT_MEMORY_REGIONS=128
#
# Debugging
@@ -475,6 +730,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# end of Using USB legacy version
# CONFIG_RT_USING_FDT is not set
+# CONFIG_RT_USING_LEGACY_VIRTIO is not set
# CONFIG_RT_USING_RUST is not set
# end of RT-Thread Components
@@ -677,7 +933,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_U8G2 is not set
# end of u8g2: a monochrome graphic library
-# CONFIG_PKG_USING_NES_SIMULATOR is not set
# CONFIG_PKG_USING_OPENMV is not set
# CONFIG_PKG_USING_MUPDF is not set
# CONFIG_PKG_USING_STEMWIN is not set
@@ -702,9 +957,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# tools packages
#
-# CONFIG_PKG_USING_VECTOR is not set
-# CONFIG_PKG_USING_SORCH is not set
-# CONFIG_PKG_USING_DICT is not set
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_MCOREDUMP is not set
# CONFIG_PKG_USING_EASYFLASH is not set
@@ -753,9 +1005,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_RVBACKTRACE is not set
# CONFIG_PKG_USING_HPATCHLITE is not set
# CONFIG_PKG_USING_THREAD_METRIC is not set
-# CONFIG_PKG_USING_UORB is not set
-# CONFIG_PKG_USING_RT_TUNNEL is not set
-# CONFIG_PKG_USING_VIRTUAL_TERMINAL is not set
# end of tools packages
#
@@ -850,9 +1099,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_R_RHEALSTONE is not set
# CONFIG_PKG_USING_HEARTBEAT is not set
# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set
-# CONFIG_PKG_USING_CHERRYECAT is not set
-# CONFIG_PKG_USING_EVENT_LOOP is not set
-# CONFIG_PKG_USING_THREAD_MANAGER is not set
# end of system packages
#
@@ -998,7 +1244,9 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# NUVOTON Drivers
#
+# CONFIG_PKG_USING_NUVOTON_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_NUVOTON_SERIES_DRIVER is not set
+# CONFIG_PKG_USING_NUVOTON_ARM926_LIB is not set
# end of NUVOTON Drivers
#
@@ -1006,24 +1254,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32_RISCV_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32VW55X_WIFI is not set
# end of GD32 Drivers
-
-#
-# HPMicro SDK
-#
-# CONFIG_PKG_USING_HPM_SDK is not set
-# end of HPMicro SDK
-
-#
-# FT32 HAL & SDK Drivers
-#
-# CONFIG_PKG_USING_FT32F0_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F0_CMSIS_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_CMSIS_DRIVER is not set
-# end of FT32 HAL & SDK Drivers
# end of HAL & SDK Drivers
#
@@ -1069,11 +1300,9 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_RT3020 is not set
# CONFIG_PKG_USING_MLX90632 is not set
# CONFIG_PKG_USING_MLX90382 is not set
-# CONFIG_PKG_USING_MLX90384 is not set
# CONFIG_PKG_USING_MLX90393 is not set
# CONFIG_PKG_USING_MLX90392 is not set
# CONFIG_PKG_USING_MLX90394 is not set
-# CONFIG_PKG_USING_MLX90396 is not set
# CONFIG_PKG_USING_MLX90397 is not set
# CONFIG_PKG_USING_MS5611 is not set
# CONFIG_PKG_USING_MAX31865 is not set
@@ -1102,7 +1331,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_P3T1755 is not set
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
-# CONFIG_PKG_USING_SCD4X is not set
# end of sensors drivers
#
@@ -1120,7 +1348,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_CST812T is not set
# end of touch drivers
-# CONFIG_PKG_USING_LCD_SPI_DRIVER is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_BUTTON is not set
# CONFIG_PKG_USING_PCF8574 is not set
@@ -1200,13 +1427,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_IC74HC165 is not set
# CONFIG_PKG_USING_IST8310 is not set
# CONFIG_PKG_USING_ST7789_SPI is not set
-# CONFIG_PKG_USING_CAN_UDS is not set
-# CONFIG_PKG_USING_ISOTP_C is not set
-# CONFIG_PKG_USING_IKUNLED is not set
-# CONFIG_PKG_USING_INS5T8025 is not set
-# CONFIG_PKG_USING_IRUART is not set
-# CONFIG_PKG_USING_ST7305 is not set
-# CONFIG_PKG_USING_TM1668 is not set
# CONFIG_PKG_USING_SPI_TOOLS is not set
# end of peripheral libraries and drivers
@@ -1546,41 +1766,4 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# end of Arduino libraries
# end of RT-Thread online packages
-CONFIG_BCM2836_SOC=y
CONFIG_SOC_BCM283x=y
-
-#
-# Hardware Drivers Config
-#
-
-#
-# BCM Peripheral Drivers
-#
-CONFIG_BSP_USING_UART=y
-# CONFIG_RT_USING_UART0 is not set
-CONFIG_RT_USING_UART1=y
-CONFIG_BSP_USING_PIN=y
-CONFIG_BSP_USING_CORETIMER=y
-CONFIG_BSP_USING_SYSTIMER=y
-CONFIG_RT_USING_SYSTIMER1=y
-CONFIG_RT_USING_SYSTIMER3=y
-CONFIG_BSP_USING_I2C=y
-# CONFIG_BSP_USING_I2C0 is not set
-CONFIG_BSP_USING_I2C1=y
-CONFIG_BSP_USING_SPI=y
-CONFIG_BSP_USING_SPI0_BUS=y
-CONFIG_BSP_USING_SPI0_DEVICE0=y
-# CONFIG_BSP_USING_SPI0_DEVICE1 is not set
-CONFIG_BSP_USING_WDT=y
-# CONFIG_BSP_USING_RTC is not set
-CONFIG_BSP_USING_SDIO=y
-CONFIG_BSP_USING_SDIO0=y
-# end of BCM Peripheral Drivers
-
-#
-# Board Peripheral Drivers
-#
-CONFIG_BSP_USING_HDMI=y
-CONFIG_BSP_USING_HDMI_DISPLAY=y
-# end of Board Peripheral Drivers
-# end of Hardware Drivers Config
diff --git a/bsp/raspberry-pi/raspi3-64/Kconfig b/bsp/raspberry-pi/raspi3-64/Kconfig
index 7a1dfd12f0..7e344d89b9 100644
--- a/bsp/raspberry-pi/raspi3-64/Kconfig
+++ b/bsp/raspberry-pi/raspi3-64/Kconfig
@@ -6,21 +6,18 @@ RTT_DIR := ../../..
PKGS_DIR := packages
+SOC_DM_DIR := $BSP_DIR/../dm/
+
+source "$(SOC_DM_DIR)/Kconfig"
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
-config BCM2836_SOC
+config SOC_BCM283x
bool
select ARCH_ARMV8
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select ARCH_CPU_64BIT
select RT_USING_CACHE
- select SOC_BCM283x
+ select RT_USING_STDC_ATOMIC
default y
-
-config SOC_BCM283x
- bool
- default y
-
-rsource "driver/Kconfig"
diff --git a/bsp/raspberry-pi/raspi3-64/SConscript b/bsp/raspberry-pi/raspi3-64/SConscript
index c7ef7659ec..40e1864cf6 100644
--- a/bsp/raspberry-pi/raspi3-64/SConscript
+++ b/bsp/raspberry-pi/raspi3-64/SConscript
@@ -11,4 +11,6 @@ for d in list:
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
+objs = objs + SConscript(cwd + '/../dm/SConscript', variant_dir = 'dm', duplicate = 0)
+
Return('objs')
diff --git a/bsp/raspberry-pi/raspi3-64/SConstruct b/bsp/raspberry-pi/raspi3-64/SConstruct
index 33f65e4109..ec6fe0187f 100644
--- a/bsp/raspberry-pi/raspi3-64/SConstruct
+++ b/bsp/raspberry-pi/raspi3-64/SConstruct
@@ -27,4 +27,3 @@ objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
# make a building
DoBuilding(TARGET, objs)
-
diff --git a/bsp/raspberry-pi/raspi3-64/applications/SConscript b/bsp/raspberry-pi/raspi3-64/applications/SConscript
index fdf93d4235..c583d3016e 100644..100755
--- a/bsp/raspberry-pi/raspi3-64/applications/SConscript
+++ b/bsp/raspberry-pi/raspi3-64/applications/SConscript
@@ -1,7 +1,7 @@
from building import *
cwd = GetCurrentDir()
-src = Glob('*.c') + Glob('*.cpp') + Glob('test/*.c')
+src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
diff --git a/bsp/raspberry-pi/raspi3-64/applications/main.c b/bsp/raspberry-pi/raspi3-64/applications/main.c
index bd7c917e64..77d2df96c0 100644
--- a/bsp/raspberry-pi/raspi3-64/applications/main.c
+++ b/bsp/raspberry-pi/raspi3-64/applications/main.c
@@ -9,53 +9,10 @@
*/
#include <rtthread.h>
-#include <rtdevice.h>
-#include <board.h>
-#include "mbox.h"
-
-void set_led(int state) //set state LED nyala atau mati
-{
- if (state==1) //LED nyala
- {
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = 0x00038041; // get serial number command
- mbox[3] = 8; // buffer size
- mbox[4] = 0;
- mbox[5] = 130; // clear output buffer
- mbox[6] = 1;
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- }
- else if (state==0) //LED mati
- {
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = 0x00038041; // get serial number command
- mbox[3] = 8; // buffer size
- mbox[4] = 0;
- mbox[5] = 130; // clear output buffer
- mbox[6] = 0;
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- }
-}
int main(int argc, char** argv)
{
- int count = 1;
-
rt_kprintf("Hi, this is RT-Thread!!\n");
- while (count++)
- {
- set_led(1);
- rt_thread_mdelay(500);
- set_led(0);
- rt_thread_mdelay(500);
- }
-
return RT_EOK;
}
diff --git a/bsp/raspberry-pi/raspi3-64/applications/mnt.c b/bsp/raspberry-pi/raspi3-64/applications/mnt.c
deleted file mode 100644
index 01e97b325b..0000000000
--- a/bsp/raspberry-pi/raspi3-64/applications/mnt.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2017-5-30 bernard the first version
- */
-
-#include <rtthread.h>
-
-#ifdef BSP_USING_SDIO0
-#include <dfs_fs.h>
-
-int mnt_init(void)
-{
- rt_thread_delay(RT_TICK_PER_SECOND);
- if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
- {
- rt_kprintf("file system initialization done!\n");
- }
-
- return 0;
-}
-INIT_ENV_EXPORT(mnt_init);
-#endif
-
diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h b/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h
deleted file mode 100644
index 52fa671d0f..0000000000
--- a/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 bzt (bztsrc@github)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#define MMIO_BASE 0x3F000000
-
-#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000))
-#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004))
-#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008))
-#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C))
-#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010))
-#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014))
-#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C))
-#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020))
-#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028))
-#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034))
-#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038))
-#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040))
-#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044))
-#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064))
-#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068))
-#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094))
-#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098))
-#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C))
diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/uart.c b/bsp/raspberry-pi/raspi3-64/applications/test/uart.c
deleted file mode 100644
index b3dd4da7ea..0000000000
--- a/bsp/raspberry-pi/raspi3-64/applications/test/uart.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018 bzt (bztsrc@github)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "gpio.h"
-
-/* Auxilary mini UART registers */
-#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004))
-#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040))
-#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044))
-#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048))
-#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C))
-#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050))
-#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054))
-#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058))
-#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C))
-#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060))
-#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064))
-#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068))
-
-/**
- * Set baud rate and characteristics (115200 8N1) and map to GPIO
- */
-void uart_init()
-{
- register unsigned int r;
-
- /* initialize UART */
- *AUX_ENABLE |=1; // enable UART1, AUX mini uart
- *AUX_MU_CNTL = 0;
- *AUX_MU_LCR = 3; // 8 bits
- *AUX_MU_MCR = 0;
- *AUX_MU_IER = 0;
- *AUX_MU_IIR = 0xc6; // disable interrupts
- *AUX_MU_BAUD = 270; // 115200 baud
- /* map UART1 to GPIO pins */
- r=*GPFSEL1;
- r&=~((7<<12)|(7<<15)); // gpio14, gpio15
- r|=(2<<12)|(2<<15); // alt5
- *GPFSEL1 = r;
- *GPPUD = 0; // enable pins 14 and 15
- r=150; while(r--) { asm volatile("nop"); }
- *GPPUDCLK0 = (1<<14)|(1<<15);
- r=150; while(r--) { asm volatile("nop"); }
- *GPPUDCLK0 = 0; // flush GPIO setup
- *AUX_MU_CNTL = 3; // enable Tx, Rx
-}
-
-/**
- * Send a character
- */
-void uart_send(unsigned int c) {
- /* wait until we can send */
- do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20));
- /* write the character to the buffer */
- *AUX_MU_IO=c;
-}
-
-/**
- * Receive a character
- */
-char uart_getc() {
- char r;
- /* wait until something is in the buffer */
- do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01));
- /* read it and return */
- r=(char)(*AUX_MU_IO);
- /* convert carrige return to newline */
- return r=='\r'?'\n':r;
-}
-
-/**
- * Display a string
- */
-void uart_puts(char *s) {
- while(*s) {
- /* convert newline to carrige return + newline */
- if(*s=='\n')
- uart_send('\r');
- uart_send(*s++);
- }
-}
diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/uart.h b/bsp/raspberry-pi/raspi3-64/applications/test/uart.h
deleted file mode 100644
index 72f8e3151f..0000000000
--- a/bsp/raspberry-pi/raspi3-64/applications/test/uart.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2018 bzt (bztsrc@github)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-void uart_init();
-void uart_send(unsigned int c);
-char uart_getc();
-void uart_puts(char *s);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/Kconfig b/bsp/raspberry-pi/raspi3-64/driver/Kconfig
deleted file mode 100644
index 5632f72462..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/Kconfig
+++ /dev/null
@@ -1,116 +0,0 @@
-menu "Hardware Drivers Config"
- menu "BCM Peripheral Drivers"
- menuconfig BSP_USING_UART
- bool "Using UART"
- select RT_USING_SERIAL
- default y
-
- if BSP_USING_UART
- config RT_USING_UART0
- bool "Enabel UART 0"
- default y
-
- config RT_USING_UART1
- bool "Enabel UART 1"
- default n
- endif
-
- config BSP_USING_PIN
- bool "Using PIN"
- select RT_USING_PIN
- default y
-
- config BSP_USING_CORETIMER
- bool "Using core timer"
- select RT_USING_CORETIMER
- default y
-
- menuconfig BSP_USING_SYSTIMER
- bool "Enable SYSTIMER"
- select RT_USING_CLOCK_TIME
- default n
-
- if BSP_USING_SYSTIMER
- config RT_USING_SYSTIMER1
- bool "Enable sys timer1"
- default n
- config RT_USING_SYSTIMER3
- bool "Enable sys timer3"
- default n
- endif
-
- menuconfig BSP_USING_I2C
- bool "Enable I2C"
- select RT_USING_I2C
- default n
-
- if BSP_USING_I2C
- config BSP_USING_I2C0
- bool "Enable I2C0"
- default n
- config BSP_USING_I2C1
- bool "Enable I2C1"
- default n
- endif
-
- menuconfig BSP_USING_SPI
- bool "Enable SPI"
- select RT_USING_SPI
- default n
-
- if BSP_USING_SPI
- config BSP_USING_SPI0_BUS
- bool "Enable SPI0 BUS"
- default n
- config BSP_USING_SPI0_DEVICE0
- bool "Enable SPI0 DEVICE0"
- select BSP_USING_SPI0_BUS
- default n
- config BSP_USING_SPI0_DEVICE1
- bool "Enable SPI0 DEVICE1"
- select BSP_USING_SPI0_BUS
- default n
- endif
-
- config BSP_USING_WDT
- bool "Enable WDT"
- select RT_USING_WDT
- default n
-
- menuconfig BSP_USING_RTC
- bool "Enable RTC"
- select RT_USING_RTC
- default n
-
- if BSP_USING_RTC
- config BSP_USING_ALARM
- bool "Enable Alarm"
- select RT_USING_ALARM
- default n
- endif
-
- menuconfig BSP_USING_SDIO
- bool "Enable SDIO"
- select RT_USING_SDIO
- default n
-
- if BSP_USING_SDIO
- config BSP_USING_SDIO0
- bool "Enable SDIO0"
- select RT_USING_SDIO
- default n
- endif
- endmenu
-
- menu "Board Peripheral Drivers"
- menuconfig BSP_USING_HDMI
- bool "Enable HDMI"
- default n
-
- if BSP_USING_HDMI
- config BSP_USING_HDMI_DISPLAY
- bool "HDMI DISPLAY"
- default n
- endif
- endmenu
-endmenu
diff --git a/bsp/raspberry-pi/raspi3-64/driver/SConscript b/bsp/raspberry-pi/raspi3-64/driver/SConscript
index c51b2c42bf..f7e8f47ce8 100644
--- a/bsp/raspberry-pi/raspi3-64/driver/SConscript
+++ b/bsp/raspberry-pi/raspi3-64/driver/SConscript
@@ -3,29 +3,10 @@
from building import *
cwd = GetCurrentDir()
-src = Split('''
-board.c
-drv_uart.c
-mbox.c
-''')
+src = Glob('*.c')
CPPPATH = [cwd]
+objs = []
-if GetDepend('BSP_USING_SYSTIMER'):
- src += ['drv_timer.c']
-if GetDepend('BSP_USING_PIN'):
- src += ['drv_gpio.c']
-if GetDepend('BSP_USING_I2C'):
- src += ['drv_i2c.c']
-if GetDepend('BSP_USING_WDT'):
- src += ['drv_wdt.c']
-if GetDepend('BSP_USING_SPI'):
- src += ['drv_spi.c']
-if GetDepend('BSP_USING_SDIO'):
- src += ['drv_sdio.c']
-if GetDepend('BSP_USING_RTC'):
- src += ['drv_rtc.c']
-if GetDepend('BSP_USING_HDMI'):
- src += ['drv_fb.c']
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
diff --git a/bsp/raspberry-pi/raspi3-64/driver/board.c b/bsp/raspberry-pi/raspi3-64/driver/board.c
index 614a349973..2519d7ddc2 100644
--- a/bsp/raspberry-pi/raspi3-64/driver/board.c
+++ b/bsp/raspberry-pi/raspi3-64/driver/board.c
@@ -9,175 +9,10 @@
* 2021-12-28 GuEe-GUI add smp support
*/
-#include <rthw.h>
-#include <rtthread.h>
+#include <setup.h>
+#include <board.h>
-#include "board.h"
-#include "drv_uart.h"
-#include "drv_timer.h"
-
-#include "gtimer.h"
-#include "cpuport.h"
-#include "interrupt.h"
-#include "mmu.h"
-#include "raspi.h"
-
-struct mem_desc platform_mem_desc[] =
-{
- {0, 0x6400000, 0, NORMAL_MEM},
- {0xc00000, 0xc01000, 0xc00000, DEVICE_MEM}, /* mbox */
- {0x3f000000, 0x3f200000, 0x3f000000, DEVICE_MEM}, /* timer */
- {0x3f200000, 0x3f216000, 0x3f200000, DEVICE_MEM}, /* uart */
- {0x40000000, 0x40200000, 0x40000000, DEVICE_MEM}, /* core timer */
- {0x3F300000, 0x3F301000, 0x3F300000, DEVICE_MEM}, /* sdio */
- {0x3f804000, 0x3f805000, 0x3f804000, DEVICE_MEM}, /* i2c0 */
- {0x3f205000, 0x3f206000, 0x3f205000, DEVICE_MEM}, /* i2c1 */
-};
-
-const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
-
-#if defined(BSP_USING_CORETIMER) || defined(RT_USING_SMP)
-static volatile rt_uint64_t timer_step;
-#define BSP_USING_CORETIMER
-#endif
-
-void rt_hw_timer_isr(int vector, void *parameter)
-{
-#ifdef BSP_USING_CORETIMER
- rt_hw_set_gtimer_val(timer_step);
-#else
- ARM_TIMER_IRQCLR = 0;
-#endif
- rt_tick_increase();
-}
-
-rt_uint8_t core_timer_flag;
-
-void rt_hw_timer_init(void)
-{
- rt_hw_interrupt_install(IRQ_ARM_TIMER, rt_hw_timer_isr, RT_NULL, "tick");
- rt_hw_interrupt_umask(IRQ_ARM_TIMER);
-#ifdef BSP_USING_CORETIMER
- rt_hw_isb();
- timer_step = rt_hw_get_gtimer_frq();
- rt_hw_dsb();
- timer_step /= RT_TICK_PER_SECOND;
-
- rt_hw_gtimer_enable();
- rt_hw_set_gtimer_val(timer_step);
-#ifdef RT_USING_SMP
- core_timer_enable(rt_hw_cpu_id());
-#else
- core_timer_enable(0);
-#endif
-#else
- __DSB();
- /* timer_clock = apb_clock/(pre_divider + 1) */
- ARM_TIMER_PREDIV = (250 - 1);
-
- ARM_TIMER_RELOAD = 0;
- ARM_TIMER_LOAD = 0;
- ARM_TIMER_IRQCLR = 0;
- ARM_TIMER_CTRL = 0;
-
- ARM_TIMER_RELOAD = 10000;
- ARM_TIMER_LOAD = 10000;
-
- /* 23-bit counter, enable interrupt, enable timer */
- ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7);
-#endif
-}
-
-void idle_wfi(void)
-{
- asm volatile ("wfi");
-}
-
-/**
- * Initialize the Hardware related stuffs. Called from rtthread_startup()
- * after interrupt disabled.
- */
void rt_hw_board_init(void)
{
- extern void *MMUTable;
- rt_hw_mmu_map_init(&rt_kernel_space, (void*)0x80000000, 0x10000000, MMUTable, 0);
- rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, platform_mem_desc_size);
-
- /* initialize hardware interrupt */
- rt_hw_interrupt_init(); // in libcpu/interrupt.c. Set some data structures, no operation on device
-
- /* initialize uart */
- rt_hw_uart_init(); // driver/drv_uart.c
- /* initialize timer for os tick */
- rt_hw_timer_init();
- rt_thread_idle_sethook(idle_wfi);
-
-#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
- /* set console device */
- rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
-#endif
-
-#ifdef RT_USING_HEAP
- /* initialize memory system */
- rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
- rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
-#endif
-
-#ifdef RT_USING_COMPONENTS_INIT
- rt_components_board_init();
-#endif
-
-#ifdef RT_USING_SMP
- /* install IPI handle */
- rt_hw_ipi_handler_install(IRQ_ARM_MAILBOX, rt_scheduler_ipi_handler);
- rt_hw_interrupt_umask(IRQ_ARM_MAILBOX);
- enable_cpu_ipi_intr(0);
-#endif
-}
-
-#ifdef RT_USING_SMP
-static unsigned long cpu_release_paddr[] =
-{
- [0] = 0xd8,
- [1] = 0xe0,
- [2] = 0xe8,
- [3] = 0xf0,
- [4] = 0
-};
-
-void rt_hw_secondary_cpu_up(void)
-{
- int i;
- extern void secondary_cpu_start(void);
-
- for (i = 1; i < RT_CPUS_NR && cpu_release_paddr[i]; ++i)
- {
- __asm__ volatile ("str %0, [%1]"::"rZ"((unsigned long)secondary_cpu_start), "r"(cpu_release_paddr[i]));
- rt_hw_dcache_flush_range(cpu_release_paddr[i], sizeof(cpu_release_paddr[i]));
- __DSB();
- __SEV();
- }
-}
-
-void secondary_cpu_c_start(void)
-{
- int id = rt_hw_cpu_id();
-
- rt_hw_mmu_init();
- rt_hw_spin_lock(&_cpus_lock);
-
- rt_hw_vector_init();
- rt_hw_timer_init();
- enable_cpu_ipi_intr(id);
-
- rt_kprintf("\rcall cpu %d on success\n", id);
-
- rt_system_scheduler_start();
+ rt_hw_common_setup();
}
-
-void rt_hw_secondary_cpu_idle_exec(void)
-{
- __WFE();
-}
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/board.h b/bsp/raspberry-pi/raspi3-64/driver/board.h
index ad5d0007ce..08b8be3396 100644
--- a/bsp/raspberry-pi/raspi3-64/driver/board.h
+++ b/bsp/raspberry-pi/raspi3-64/driver/board.h
@@ -11,21 +11,6 @@
#ifndef BOARD_H__
#define BOARD_H__
-#include <stdint.h>
-#include "raspi.h"
-
-extern unsigned char __bss_start;
-extern unsigned char __bss_end;
-
-#define RT_HW_HEAP_BEGIN (void*)&__bss_end
-#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
-
-#ifndef RT_USING_SMART
-#define PV_OFFSET 0
-#define KERNEL_VADDR_START 0
-#endif
-
void rt_hw_board_init(void);
-#endif
-
+#endif /* BOARD_H__ */
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c
deleted file mode 100644
index 06056bf7c1..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-08-29 zdzn first version
- */
-
-#include <rthw.h>
-#include <stdint.h>
-#include <rtthread.h>
-#include <rtdevice.h>
-#include "mbox.h"
-#include "drv_fb.h"
-#include "mmu.h"
-#include "cache.h"
-
-#define LCD_WIDTH (800)
-#define LCD_HEIGHT (480)
-#define LCD_DEPTH (32)
-#define LCD_BPP (32)
-
-#define TAG_ALLOCATE_BUFFER 0x00040001
-#define TAG_SET_PHYS_WIDTH_HEIGHT 0x00048003
-#define TAG_SET_VIRT_WIDTH_HEIGHT 0x00048004
-#define TAG_SET_DEPTH 0x00048005
-#define TAG_SET_PIXEL_ORDER 0x00048006
-#define TAG_GET_PITCH 0x00040008
-#define TAG_SET_VIRT_OFFSET 0x00048009
-#define TAG_END 0x00000000
-
-
-enum {
- MBOX_TAG_FB_GET_GPIOVIRT = 0x00040010,
- MBOX_TAG_FB_ALLOCATE_BUFFER = 0x00040001,
- MBOX_TAG_FB_RELEASE_BUFFER = 0x00048001,
- MBOX_TAG_FB_BLANK_SCREEN = 0x00040002,
- MBOX_TAG_FB_GET_PHYS_WH = 0x00040003,
- MBOX_TAG_FB_TEST_PHYS_WH = 0x00044003,
- MBOX_TAG_FB_SET_PHYS_WH = 0x00048003,
- MBOX_TAG_FB_GET_VIRT_WH = 0x00040004,
- MBOX_TAG_FB_TEST_VIRT_WH = 0x00044004,
- MBOX_TAG_FB_SET_VIRT_WH = 0x00048004,
- MBOX_TAG_FB_GET_DEPTH = 0x00040005,
- MBOX_TAG_FB_TEST_DEPTH = 0x00044005,
- MBOX_TAG_FB_SET_DEPTH = 0x00048005,
- MBOX_TAG_FB_GET_PIXEL_ORDER = 0x00040006,
- MBOX_TAG_FB_TEST_PIXEL_ORDER = 0x00044006,
- MBOX_TAG_FB_SET_PIXEL_ORDER = 0x00048006,
- MBOX_TAG_FB_GET_ALPHA_MODE = 0x00040007,
- MBOX_TAG_FB_TEST_ALPHA_MODE = 0x00044007,
- MBOX_TAG_FB_SET_ALPHA_MODE = 0x00048007,
- MBOX_TAG_FB_GET_PITCH = 0x00040008,
- MBOX_TAG_FB_GET_VIRT_OFFSET = 0x00040009,
- MBOX_TAG_FB_TEST_VIRT_OFFSET = 0x00044009,
- MBOX_TAG_FB_SET_VIRT_OFFSET = 0x00048009,
- MBOX_TAG_FB_GET_OVERSCAN = 0x0004000a,
- MBOX_TAG_FB_TEST_OVERSCAN = 0x0004400a,
- MBOX_TAG_FB_SET_OVERSCAN = 0x0004800a,
- MBOX_TAG_FB_GET_PALETTE = 0x0004000b,
- MBOX_TAG_FB_TEST_PALETTE = 0x0004400b,
- MBOX_TAG_FB_SET_PALETTE = 0x0004800b,
-};
-
-#define LCD_DEVICE(dev) (struct rt_hdmi_fb_device*)(dev)
-
-static struct rt_hdmi_fb_device _hdmi;
-
-typedef rt_uint16_t color_t;
-
-rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
-{
- return RT_EOK;
-}
-
-rt_err_t hdmi_fb_close(rt_device_t dev)
-{
- return RT_EOK;
-}
-
-rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
-{
- return 0;
-}
-
-rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
- return size;
-}
-
-rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
-{
- struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev);
- switch (cmd)
- {
- case RTGRAPHIC_CTRL_RECT_UPDATE:
- {
- struct rt_device_rect_info *info = (struct rt_device_rect_info*)args;
- info = info;
- }
- break;
-
- case RTGRAPHIC_CTRL_GET_INFO:
- {
- struct rt_device_graphic_info* info = (struct rt_device_graphic_info*)args;
-
- RT_ASSERT(info != RT_NULL);
- info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
- info->bits_per_pixel= LCD_DEPTH;
- info->width = lcd->width;
- info->height = lcd->height;
- info->framebuffer = lcd->fb;
- }
- break;
- }
- return RT_EOK;
-}
-
-const static struct rt_device_ops hdmi_fb_ops =
-{
- RT_NULL,
- hdmi_fb_open,
- hdmi_fb_close,
- hdmi_fb_read,
- hdmi_fb_write,
- hdmi_fb_control
-};
-
-rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
-{
- struct rt_device *device;
- RT_ASSERT(hdmi_fb != RT_NULL);
-
- device = &hdmi_fb->parent;
-
- /* set device type */
- device->type = RT_Device_Class_Graphic;
- /* initialize device interface */
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &hdmi_fb_ops;
-#else
- device->init = RT_NULL;
- device->open = hdmi_fb_open;
- device->close = hdmi_fb_close;
- device->read = hdmi_fb_read;
- device->write = hdmi_fb_write;
- device->control = hdmi_fb_control;
-#endif
-
- /* register to device manager */
- rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
-
- return RT_EOK;
-}
-
-rt_uint32_t bcm283x_mbox_fb_get_gpiovirt(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return (mbox[5] & 0x3fffffff);
-}
-
-rt_uint32_t bcm283x_mbox_fb_get_pitch(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_GET_PITCH;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return mbox[5];
-}
-
-void bcm283x_mbox_fb_set_porder(int rgb)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER;
- mbox[3] = 4; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = rgb; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-void bcm283x_mbox_fb_setoffset(int xoffset, int yoffset)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = xoffset; // id
- mbox[6] = yoffset;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-
-void bcm283x_mbox_fb_setalpha(int alpha)
-{
-
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE;
- mbox[3] = 4; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = alpha; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-void *bcm283x_mbox_fb_alloc(int width, int height, int bpp, int nrender)
-{
- mbox[0] = 4 * 35;
- mbox[1] = MBOX_REQUEST;
-
- mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request
- mbox[3] = 8; //size
- mbox[4] = 4; //len
- mbox[5] = 4096; //The design of MBOX driver forces us to give the virtual address 0x3C100000
- mbox[6] = 0; //FrameBufferInfo.size
-
- mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT;
- mbox[8] = 8;
- mbox[9] = 8;
- mbox[10] = width;
- mbox[11] = height;
-
- mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT;
- mbox[13] = 8;
- mbox[14] = 8;
- mbox[15] = width;
- mbox[16] = height * nrender;
-
- mbox[17] = TAG_SET_DEPTH;
- mbox[18] = 4;
- mbox[19] = 4;
- mbox[20] = bpp;
-
- mbox[21] = TAG_SET_PIXEL_ORDER;
- mbox[22] = 4;
- mbox[23] = 0;
- mbox[24] = 0; //RGB, not BGR preferably
-
- mbox[25] = TAG_GET_PITCH;
- mbox[26] = 4;
- mbox[27] = 0;
- mbox[28] = 0;
-
- mbox[29] = TAG_SET_VIRT_OFFSET;
- mbox[30] = 8;
- mbox[31] = 8;
- mbox[32] = 0;
- mbox[33] = 0;
-
- mbox[34] = TAG_END;
-
- mbox_call(MBOX_CH_PROP, MMU_DISABLE);
-
- return (void *)((rt_uint64_t)(mbox[5] & 0x3fffffff));
-}
-
-int hdmi_fb_init(void)
-{
- _hdmi.fb = (rt_uint8_t *)bcm283x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1);
- bcm283x_mbox_fb_setoffset(0, 0);
- bcm283x_mbox_fb_set_porder(0);
- _hdmi.width = LCD_WIDTH;
- _hdmi.height = LCD_HEIGHT;
- _hdmi.depth = LCD_DEPTH;
- _hdmi.pitch = 0;
- _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
-
- // rt_hw_mmu_map(&mmu_info, (unsigned long)_hdmi.fb, (void *)0x200000, DEVICE_MEM);
-
- rt_hw_cpu_dcache_invalidate((unsigned long)_hdmi.fb,LCD_WIDTH * LCD_HEIGHT * 3);
-
- //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb);
- rt_hdmi_fb_device_init(&_hdmi, "lcd");
-
- return 0;
-}
-
-INIT_DEVICE_EXPORT(hdmi_fb_init);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h
deleted file mode 100644
index 1074dc79c7..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-08-29 zdzn first version
- */
-#ifndef __DRV_FB_H__
-#define __DRV_FB_H__
-
-#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b)))
-struct rt_hdmi_fb_device
-{
- struct rt_device parent;
-
- rt_uint32_t width;
- rt_uint32_t height;
- rt_uint32_t depth;
- rt_uint32_t pitch;
- rt_uint32_t pixel_format;
-
- rt_uint8_t *fb;
-};
-#endif/* __DRV_FB_H__ */
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c
deleted file mode 100644
index 728f1514b6..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-#include "raspi.h"
-#include "drv_gpio.h"
-
-
-#ifdef BSP_USING_PIN
-/*
- * gpio_int[0] for BANK0 (pins 0-27)
- * gpio_int[1] for BANK1 (pins 28-45)
- * gpio_int[2] for BANK2 (pins 46-53)
- */
-static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_IRQ_NUM];
-
-void gpio_set_pud(rt_uint8_t pin, rt_uint8_t pud)
-{
- rt_uint8_t num = pin / 32;
- rt_uint8_t shift = pin % 32;
- BCM283X_GPIO_GPPUD = pud;
- DELAY_MICROS(10);
- BCM283X_GPIO_GPPUDCLK(num) = 1 << shift;
- DELAY_MICROS(10);
- BCM283X_GPIO_GPPUD = BCM283X_GPIO_PUD_OFF;
- BCM283X_GPIO_GPPUDCLK(num) = 0 << shift;
-}
-
-static void gpio_ack_irq(int irq, bcm_gpio_pin pin)
-{
- rt_uint32_t data;
- data = IRQ_PEND2;
- data &= (0x0 << (irq - 32));
- IRQ_PEND2 = data;
-
- data = IRQ_DISABLE2;
- data |= (0x1 << (irq - 32));
- IRQ_DISABLE2 = data;
-}
-
-void gpio_irq_disable(rt_uint8_t index, bcm_gpio_pin pin)
-{
- int irq = 0;
- rt_uint32_t reg_value;
- rt_uint8_t irq_type;
- irq = IRQ_GPIO0 + index;
-
- gpio_ack_irq(irq, pin);
-
- irq_type = _g_gpio_irq_tbl[index].irq_type[pin];
- rt_uint8_t shift = pin % 32;
- rt_uint32_t mask = 1 << shift;
-
- switch (irq_type)
- {
- case PIN_IRQ_MODE_RISING:
- reg_value = BCM283X_GPIO_GPREN(pin /32);
- BCM283X_GPIO_GPREN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- break;
- case PIN_IRQ_MODE_FALLING:
- reg_value = BCM283X_GPIO_GPFEN(pin /32);
- BCM283X_GPIO_GPFEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- break;
- case PIN_IRQ_MODE_RISING_FALLING:
- reg_value = BCM283X_GPIO_GPAREN(pin /32);
- BCM283X_GPIO_GPAREN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- reg_value = BCM283X_GPIO_GPAFEN(pin /32);
- BCM283X_GPIO_GPAFEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- reg_value = BCM283X_GPIO_GPHEN(pin /32);
- BCM283X_GPIO_GPHEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- reg_value = BCM283X_GPIO_GPLEN(pin /32);
- BCM283X_GPIO_GPLEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask);
- break;
- }
-}
-
-void gpio_irq_enable(rt_uint8_t index, bcm_gpio_pin pin)
-{
- rt_uint32_t offset;
- rt_uint32_t data;
-
- offset = pin;
- if (index == 0)
- offset = IRQ_GPIO0 - 32;
- else if (index == 1)
- offset = IRQ_GPIO1 - 32;
- else
- offset = IRQ_GPIO2 - 32;
-
- data = IRQ_ENABLE2;
- data |= 0x1 << offset;
- IRQ_ENABLE2 = data;
-
-}
-
-static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_uint8_t mode)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
- RT_ASSERT(!(mode & 0x8));
-
- switch (mode)
- {
- case PIN_MODE_OUTPUT:
- GPIO_FSEL(pin, BCM283X_GPIO_FSEL_OUTP);
- break;
- case PIN_MODE_INPUT:
- GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT);
- break;
- case PIN_MODE_INPUT_PULLUP:
- gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
- GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT);
- break;
- case PIN_MODE_INPUT_PULLDOWN:
- gpio_set_pud(pin, BCM283X_GPIO_PUD_DOWN);
- GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT);
- break;
- case PIN_MODE_OUTPUT_OD:
- gpio_set_pud(pin, BCM283X_GPIO_PUD_OFF);
- GPIO_FSEL(pin, BCM283X_GPIO_FSEL_OUTP);
- break;
- }
-}
-
-static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_uint8_t value)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
- RT_ASSERT(!(value & 0xE));
-
- if (value)
- BCM283X_GPIO_GPSET(pin / 32) |= (1 << (pin %32));
- else
- BCM283X_GPIO_GPCLR(pin / 32) |= (1 << (pin %32));
-
-}
-
-static rt_ssize_t raspi_pin_read(struct rt_device *device, rt_base_t pin)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
- return (BCM2835_GPIO_GPLEV(pin / 32) & (1 << (pin % 32)))? PIN_HIGH : PIN_LOW;
-}
-
-static rt_err_t raspi_pin_attach_irq(struct rt_device *device, rt_base_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
-
- rt_uint8_t index;
- rt_uint32_t reg_value;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
- _g_gpio_irq_tbl[index].irq_cb[pin] = hdr;
- _g_gpio_irq_tbl[index].irq_arg[pin] = args;
- _g_gpio_irq_tbl[index].irq_type[pin] = mode;
-
- rt_uint8_t shift = pin % 32;
- rt_uint32_t mask = 1 << shift;
-
- switch (mode)
- {
- case PIN_IRQ_MODE_RISING:
- reg_value = BCM283X_GPIO_GPREN(pin /32);
- BCM283X_GPIO_GPREN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- break;
- case PIN_IRQ_MODE_FALLING:
- reg_value = BCM283X_GPIO_GPFEN(pin /32);
- BCM283X_GPIO_GPFEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- break;
- case PIN_IRQ_MODE_RISING_FALLING:
- reg_value = BCM283X_GPIO_GPAREN(pin /32);
- BCM283X_GPIO_GPAREN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- reg_value = BCM283X_GPIO_GPAFEN(pin /32);
- BCM283X_GPIO_GPAFEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- reg_value = BCM283X_GPIO_GPHEN(pin /32);
- BCM283X_GPIO_GPHEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- reg_value = BCM283X_GPIO_GPLEN(pin /32);
- BCM283X_GPIO_GPLEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask);
- break;
- }
- return RT_EOK;
-}
-
-static rt_err_t raspi_pin_detach_irq(struct rt_device *device, rt_base_t pin)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
-
- rt_uint8_t index;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
-
- gpio_irq_disable(index, pin);
-
- _g_gpio_irq_tbl[index].irq_cb[pin] = RT_NULL;
- _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL;
- _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL;
-
- return RT_EOK;
-}
-
-rt_err_t raspi_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
-{
- RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL));
-
- rt_uint8_t index;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
-
- if (enabled)
- gpio_irq_enable(index, pin);
- else
- gpio_irq_disable(index, pin);
-
- return RT_EOK;
-}
-
-static void gpio_irq_handler(int irq, void *param)
-{
- struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param;
- rt_uint32_t pin;
- rt_uint32_t value;
- rt_uint32_t tmpvalue;
-
- if (irq == IRQ_GPIO0)
- {
- /* 0~27 */
-
- value = BCM283X_GPIO_GPEDS(0);
- value &= 0x0fffffff;
- pin = 0;
- BCM283X_GPIO_GPEDS(0) = 0;
- }
- else if (irq == IRQ_GPIO1)
- {
- /* 28-45 */
- tmpvalue = BCM283X_GPIO_GPEDS(0);
- tmpvalue &= (~0x0fffffff);
-
- value = BCM283X_GPIO_GPEDS(1);
- value &= 0x3fff;
- value = (value<<4) | tmpvalue;
- pin = 28;
- BCM283X_GPIO_GPEDS(0) = 0;
- BCM283X_GPIO_GPEDS(1) = 0;
- }
- else if (irq == IRQ_GPIO2)
- {
- /* 46-53 */
- value = BCM283X_GPIO_GPEDS(1);
- value &= (~0x3fff);
- value &= 0xff600000;
- pin = 46;
- BCM283X_GPIO_GPEDS(1) = 0;
- }
-
- while (value)
- {
- if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL))
- {
- irq_def->irq_cb[pin](irq_def->irq_arg[pin]);
- gpio_ack_irq(irq,pin);
- }
- pin++;
- value = value >> 1;
- }
-}
-
-static const struct rt_pin_ops ops =
-{
- raspi_pin_mode,
- raspi_pin_write,
- raspi_pin_read,
- raspi_pin_attach_irq,
- raspi_pin_detach_irq,
- raspi_pin_irq_enable,
- RT_NULL,
-};
-#endif
-
-int rt_hw_gpio_init(void)
-{
-#ifdef BSP_USING_PIN
- rt_device_pin_register("gpio", &ops, RT_NULL);
-
- /* install ISR */
- rt_hw_interrupt_install(IRQ_GPIO0, gpio_irq_handler, &_g_gpio_irq_tbl[0], "gpio0_irq");
- rt_hw_interrupt_umask(IRQ_GPIO0);
-
- rt_hw_interrupt_install(IRQ_GPIO1, gpio_irq_handler, &_g_gpio_irq_tbl[1], "gpio1_irq");
- rt_hw_interrupt_umask(IRQ_GPIO1);
-
- rt_hw_interrupt_install(IRQ_GPIO2, gpio_irq_handler, &_g_gpio_irq_tbl[2], "gpio2_irq");
- rt_hw_interrupt_umask(IRQ_GPIO2);
-#endif
-
- return 0;
-}
-INIT_DEVICE_EXPORT(rt_hw_gpio_init);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h
deleted file mode 100644
index 009f4e3edc..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_GPIO_H__
-#define __DRV_GPIO_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "board.h"
-#include "interrupt.h"
-
-
-#define GPIO_IRQ_NUM 3
-
-#define IRQ_GPIO0 49
-#define IRQ_GPIO1 50
-#define IRQ_GPIO2 51
-#define IRQ_GPIO3 52
-
-struct gpio_irq_def
-{
- void *irq_arg[32];
- void (*irq_cb[32])(void *param);
- rt_uint8_t irq_type[32];
-};
-
-enum gpio_irq_clock
-{
- GPIO_IRQ_LOSC_32KHZ = 0,
- GPIO_IRQ_HOSC_24MHZ
-};
-
-int rt_hw_gpio_init(void);
-
-#endif /* __DRV_GPIO_H__ */
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c
deleted file mode 100644
index 4648f880e7..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#include "raspi.h"
-#include "drv_i2c.h"
-
-//Maybe redefined
-typedef unsigned long rt_ubase_t;
-typedef rt_ubase_t rt_size_t;
-
-rt_uint8_t i2c_read_or_write(volatile rt_uint32_t base, rt_uint8_t* buf, rt_uint32_t len, rt_uint8_t flag)
-{
- rt_uint32_t status;
- rt_uint32_t remaining = len;
- rt_uint32_t i = 0;
- rt_uint8_t reason = BCM283X_I2C_REASON_OK;
-
- /* Clear FIFO */
- BCM283X_BSC_C(base) |= (BSC_C_CLEAR_1 & BSC_C_CLEAR_1);
- /* Clear Status */
- BCM283X_BSC_S(base) = BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE;
- /* Set Data Length */
- BCM283X_BSC_DLEN(base) = len;
- if (flag)
- {
- /* Start read */
- BCM283X_BSC_C(base) = BSC_C_I2CEN | BSC_C_ST | BSC_C_READ;
- /* wait for transfer to complete */
- while (!(BCM283X_BSC_S(base) & BSC_S_DONE))
- {
- /* we must empty the FIFO as it is populated and not use any delay */
- while (remaining && (BCM283X_BSC_S(base) & BSC_S_RXD))
- {
- /* Read from FIFO, no barrier */
- buf[i] = BCM283X_BSC_FIFO(base);
- i++;
- remaining--;
- }
- }
- /* transfer has finished - grab any remaining stuff in FIFO */
- while (remaining && (BCM283X_BSC_S(base) & BSC_S_RXD))
- {
- /* Read from FIFO, no barrier */
- buf[i] = BCM283X_BSC_FIFO(base);
- i++;
- remaining--;
- }
- }
- else
- {
- /* pre populate FIFO with max buffer */
- while (remaining && (i < BSC_FIFO_SIZE))
- {
- BCM283X_BSC_FIFO(base) = buf[i];
- i++;
- remaining--;
- }
-
- /* Enable device and start transfer */
- BCM283X_BSC_C(base) = BSC_C_I2CEN | BSC_C_ST;
-
- /* Transfer is over when BCM2835_BSC_S_DONE */
- while (!(BCM283X_BSC_S(base) & BSC_S_DONE))
- {
- while (remaining && (BCM283X_BSC_S(base) & BSC_S_TXD))
- {
- /* Write to FIFO */
- BCM283X_BSC_FIFO(base) = buf[i];
- i++;
- remaining--;
- }
- }
- }
-
- status = BCM283X_BSC_S(base);
- if (status & BSC_S_ERR)
- {
- reason = BCM283X_I2C_REASON_ERROR_NACK;
- }
- else if (status & BSC_S_CLKT)
- {
- reason = BCM283X_I2C_REASON_ERROR_CLKT;
- }
- else if (remaining)
- {
- reason = BCM283X_I2C_REASON_ERROR_DATA;
- }
- BCM283X_BSC_C(base) |= (BSC_S_DONE & BSC_S_DONE);
-
- return reason;
-}
-
-struct raspi_i2c_hw_config
-{
- rt_uint8_t bsc_num;
- rt_uint8_t sdl_pin;
- rt_uint8_t scl_pin;
- rt_uint8_t sdl_mode;
- rt_uint8_t scl_mode;
-};
-
-#if (defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1))
-
-static rt_ssize_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num);
-static rt_ssize_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num);
-static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus,
- int cmd,
- void *args);
-
-static rt_uint32_t i2c_byte_wait_us = 0;
-static rt_ssize_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num)
-{
- rt_size_t i;
- rt_uint8_t reason;
- RT_ASSERT(bus != RT_NULL);
-
- volatile rt_base_t base = (volatile rt_base_t)(bus->parent.user_data);
-
- if (bus->parent.user_data == 0)
- base = BCM283X_BSC0_BASE;
- else
- base = BCM283X_BSC1_BASE;
-
- BCM283X_BSC_A(base) = msgs->addr;
-
- for (i = 0; i < num; i++)
- {
- if (msgs[i].flags & RT_I2C_RD)
- reason = i2c_read_or_write(base, msgs->buf, msgs->len, 1);
- else
- reason = i2c_read_or_write(base, msgs->buf, msgs->len, 0);
- }
- return (reason == 0)? i : 0;
-}
-
-static rt_ssize_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus,
- struct rt_i2c_msg msgs[],
- rt_uint32_t num)
-{
- return 0;
-}
-static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus,
- int cmd,
- void *args)
-{
- return RT_EOK;
-}
-
-static const struct rt_i2c_bus_device_ops raspi_i2c_ops =
-{
- .master_xfer = raspi_i2c_mst_xfer,
- .slave_xfer = raspi_i2c_slv_xfer,
- .i2c_bus_control = raspi_i2c_bus_control,
-};
-
-
-static rt_err_t raspi_i2c_configure(struct raspi_i2c_hw_config *cfg)
-{
- RT_ASSERT(cfg != RT_NULL);
-
- volatile rt_uint32_t base = cfg->scl_mode ? BCM283X_BSC1_BASE : BCM283X_BSC0_BASE;
-
- GPIO_FSEL(cfg->sdl_pin, cfg->sdl_mode); /* SDA */
- GPIO_FSEL(cfg->scl_pin, cfg->scl_mode); /* SCL */
- /* use 0xFFFE mask to limit a max value and round down any odd number */
- rt_uint32_t divider = (BCM283X_CORE_CLK_HZ / 10000) & 0xFFFE;
- BCM283X_BSC_DIV(base) = (rt_uint16_t) divider;
- i2c_byte_wait_us = (divider * 1000000 * 9 / BCM283X_CORE_CLK_HZ);
-
- return RT_EOK;
-}
-#endif
-
-#if defined (BSP_USING_I2C0)
-#define I2C0_BUS_NAME "i2c0"
-static struct raspi_i2c_hw_config hw_device0 =
-{
- .bsc_num = 0,
- .sdl_pin = RPI_GPIO_P1_27,
- .scl_pin = RPI_GPIO_P1_28,
- .sdl_mode = BCM283X_GPIO_FSEL_ALT0,
- .scl_mode = BCM283X_GPIO_FSEL_ALT0,
-};
-
-struct rt_i2c_bus_device device0 =
-{
- .ops = &raspi_i2c_ops,
-};
-
-#endif
-
-#if defined (BSP_USING_I2C1)
-#define I2C1_BUS_NAME "i2c1"
-static struct raspi_i2c_hw_config hw_device1 =
-{
- .bsc_num = 1,
- .sdl_pin = RPI_GPIO_P1_03,
- .scl_pin = RPI_GPIO_P1_05,
- .sdl_mode = BCM283X_GPIO_FSEL_ALT0,
- .scl_mode = BCM283X_GPIO_FSEL_ALT0,
-};
-struct rt_i2c_bus_device device1 =
-{
- .ops = &raspi_i2c_ops,
-};
-
-#endif
-
-int rt_hw_i2c_init(void)
-{
-#if defined(BSP_USING_I2C0)
- device0.parent.user_data = (void *)0;
- raspi_i2c_configure(&hw_device0);
- rt_i2c_bus_device_register(&device0, I2C0_BUS_NAME);
-#endif
-
-#if defined(BSP_USING_I2C1)
- device1.parent.user_data = (void *)1;
- raspi_i2c_configure(&hw_device1);
- rt_i2c_bus_device_register(&device1, I2C1_BUS_NAME);
-#endif
-
- return 0;
-}
-INIT_DEVICE_EXPORT(rt_hw_i2c_init);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h
deleted file mode 100644
index 2412631852..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_I2C_H__
-#define __DRV_I2C_H__
-
-#include <rtdevice.h>
-#include <rtthread.h>
-
-#include "board.h"
-
-struct raspi_master_config_t
-{
- rt_uint8_t sdl_pin;
- rt_uint8_t scl_pin;
- rt_uint8_t sdl_pin_mode;
- rt_uint8_t scl_pin_mode;
- rt_uint8_t slave_address;
- rt_uint32_t bsc_base;
- rt_uint16_t clk_div;
-};
-
-struct raspi_i2c_bus
-{
- struct rt_i2c_bus_device device;
- struct rt_i2c_msg *msg;
- rt_uint32_t msg_cnt;
- volatile rt_uint32_t msg_ptr;
- volatile rt_uint32_t dptr;
- char *device_name;
- struct raspi_master_config_t *cfg;
-};
-
-int rt_hw_i2c_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c
deleted file mode 100644
index d68596ed57..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <sys/time.h>
-#include "drv_rtc.h"
-
-#ifdef BSP_USING_RTC
-
-static struct rt_rtc_device rtc_device;
-
-rt_uint8_t buf[]=
-{
- 0x00, 0x00, 0x43, 0x15, 0x05, 0x01, 0x03, 0x19
-};
-
-static time_t raspi_get_timestamp(void)
-{
- struct tm tm_new = {0};
- buf[0] = 0;
- bcm283x_i2c_write_read_rs((char*)buf, 1, (char*)buf, 7);
-
- tm_new.tm_year = ((buf[6] / 16) + 0x30) * 10 + (buf[6] % 16) + 0x30;
- tm_new.tm_mon = ((buf[5] & 0x1F) / 16 + 0x30) + (buf[5] & 0x1F) % 16+ 0x30;
- tm_new.tm_mday = ((buf[4] & 0x3F) / 16 + 0x30) + (buf[4] & 0x3F) % 16+ 0x30;
- tm_new.tm_hour = ((buf[2] & 0x3F) / 16 + 0x30) + (buf[2] & 0x3F) % 16+ 0x30;
- tm_new.tm_min = ((buf[1] & 0x7F) / 16 + 0x30) + (buf[1] & 0x7F) % 16+ 0x30;
- tm_new.tm_sec = ((buf[0] & 0x7F) / 16 + 0x30) + (buf[0] & 0x7F) % 16+ 0x30;
-
- return timegm(&tm_new);
-}
-
-static int raspi_set_timestamp(time_t timestamp)
-{
- struct tm tblock;
- gmtime_r(&timestamp, &tblock);
- buf[0] = 0;
- buf[1] = tblock.tm_sec;
- buf[2] = tblock.tm_min;
- buf[3] = tblock.tm_hour;
- buf[4] = tblock.tm_wday;
- buf[5] = tblock.tm_mday;
- buf[6] = tblock.tm_mon;
- buf[7] = tblock.tm_year;
- bcm283x_i2c_write((PER_BASE + BCM283X_BSC0_BASE) ,buf, 8);
- return RT_EOK;
-}
-
-static rt_err_t raspi_rtc_init(rt_device_t dev)
-{
- bcm283x_i2c_setSlaveAddress(0, 0x68);
- bcm283x_i2c_set_baudrate(0, 10000);
- raspi_set_timestamp(0);
- return RT_EOK;
-}
-
-static rt_err_t raspi_rtc_open(rt_device_t dev, rt_uint16_t oflag)
-{
- bcm283x_i2c_begin(0);
- return RT_EOK;
-}
-
-static rt_err_t raspi_rtc_close(rt_device_t dev)
-{
- bcm283x_i2c_end(0);
- return RT_EOK;
-}
-
-static rt_err_t raspi_rtc_control(rt_device_t dev, int cmd, void *args)
-{
-
- RT_ASSERT(dev != RT_NULL);
-
- switch (cmd)
- {
- case RT_DEVICE_CTRL_RTC_GET_TIME:
- *(time_t *)args = raspi_get_timestamp();
- break;
- case RT_DEVICE_CTRL_RTC_SET_TIME:
- raspi_set_timestamp(*(time_t *)args);
- break;
- default:
- return -RT_EINVAL;
- }
- return RT_EOK;
-}
-
-static rt_ssize_t raspi_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
-{
- raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
- return size;
-}
-
-static rt_ssize_t raspi_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
- raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
- return size;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops raspi_rtc_ops =
-{
- .init = raspi_rtc_init,
- .open = raspi_rtc_open,
- .close = raspi_rtc_close,
- .read = raspi_rtc_read,
- .write = raspi_rtc_write,
- .control = raspi_rtc_control
-};
-#endif
-
-int rt_hw_rtc_init(void)
-{
- rt_memset(&rtc_device, 0, sizeof(rtc_device));
-
- rtc_device.device.type = RT_Device_Class_RTC;
- rtc_device.device.rx_indicate = RT_NULL;
- rtc_device.device.tx_complete = RT_NULL;
- rtc_device.device.ops = &raspi_rtc_ops;
- rtc_device.device.user_data = RT_NULL;
-
- /* register a rtc device */
- rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR);
-
- return 0;
-}
-INIT_DEVICE_EXPORT(rt_hw_rtc_init);
-#endif /* BSP_USING_RTC */
-
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h
deleted file mode 100644
index 35ccaf39d5..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_RTC_H__
-#define __DRV_RTC_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <sys/time.h>
-#include "bcm283x.h"
-
-struct rt_rtc_device
-{
- struct rt_device device;
-};
-
-int rt_hw_rtc_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c
deleted file mode 100644
index 1e7b72b985..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * File : drv_sdio.c
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#include "drv_sdio.h"
-#include "raspi.h"
-
-static rt_uint32_t sdCommandTable[] = {
- SD_CMD_INDEX(0),
- SD_CMD_RESERVED(1),
- SD_CMD_INDEX(2) | SD_RESP_R2,
- SD_CMD_INDEX(3) | SD_RESP_R1,
- SD_CMD_INDEX(4),
- SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
- SD_CMD_INDEX(6) | SD_RESP_R1,
- SD_CMD_INDEX(7) | SD_RESP_R1b,
- SD_CMD_INDEX(8) | SD_RESP_R1,
- SD_CMD_INDEX(9) | SD_RESP_R2,
- SD_CMD_INDEX(10) | SD_RESP_R2,
- SD_CMD_INDEX(11) | SD_RESP_R1,
- SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
- SD_CMD_INDEX(13) | SD_RESP_R1,
- SD_CMD_RESERVED(14),
- SD_CMD_INDEX(15),
- SD_CMD_INDEX(16) | SD_RESP_R1,
- SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(20) | SD_RESP_R1b,
- SD_CMD_RESERVED(21),
- SD_CMD_RESERVED(22),
- SD_CMD_INDEX(23) | SD_RESP_R1,
- SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
- SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(28) | SD_RESP_R1b,
- SD_CMD_INDEX(29) | SD_RESP_R1b,
- SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(31),
- SD_CMD_INDEX(32) | SD_RESP_R1,
- SD_CMD_INDEX(33) | SD_RESP_R1,
- SD_CMD_RESERVED(34),
- SD_CMD_INDEX(35) | SD_RESP_R1, //add
- SD_CMD_INDEX(36) | SD_RESP_R1, //add
- SD_CMD_RESERVED(37),
- SD_CMD_INDEX(38) | SD_RESP_R1b,
- SD_CMD_INDEX(39) | SD_RESP_R4, //add
- SD_CMD_INDEX(40) | SD_RESP_R5, //add
- SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
- SD_CMD_RESERVED(42) | SD_RESP_R1,
- SD_CMD_RESERVED(43),
- SD_CMD_RESERVED(44),
- SD_CMD_RESERVED(45),
- SD_CMD_RESERVED(46),
- SD_CMD_RESERVED(47),
- SD_CMD_RESERVED(48),
- SD_CMD_RESERVED(49),
- SD_CMD_RESERVED(50),
- SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(52),
- SD_CMD_RESERVED(53),
- SD_CMD_RESERVED(54),
- SD_CMD_INDEX(55) | SD_RESP_R3,
- SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
- SD_CMD_RESERVED(57),
- SD_CMD_RESERVED(58),
- SD_CMD_RESERVED(59),
- SD_CMD_RESERVED(60),
- SD_CMD_RESERVED(61),
- SD_CMD_RESERVED(62),
- SD_CMD_RESERVED(63)
-};
-
-static inline rt_uint32_t read32(rt_uint32_t addr)
-{
- return (*((volatile unsigned int*)((rt_uint64_t)addr)));
- //return (*((volatile rt_uint64_t *)(((long))addr)));
-}
-
-static inline void write32(rt_uint32_t addr, rt_uint32_t value)
-{
- (*((volatile unsigned int*)((rt_uint64_t)addr))) = value;
- //*((volatile rt_uint64_t *)(((long))addr)) = value;
-}
-
-rt_err_t sd_int(struct sdhci_pdata_t * pdat, unsigned int mask)
-{
- unsigned int r;
- unsigned int m = mask | INT_ERROR_MASK;
- int cnt = 1000000;
- while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
- DELAY_MICROS(1);
- r = read32(pdat->virt + EMMC_INTERRUPT);
- if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
- {
- write32(pdat->virt + EMMC_INTERRUPT, r);
- //qemu maybe can not use sdcard
- //rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
- //return -RT_ETIMEOUT;
- }
- else if (r & INT_ERROR_MASK)
- {
- write32(pdat->virt + EMMC_INTERRUPT, r);
- rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
- return -RT_ERROR;
- }
- write32(pdat->virt + EMMC_INTERRUPT, mask);
- return RT_EOK;
-}
-
-rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
-{
- int cnt = 500000;
- while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
- DELAY_MICROS(1);
- if (cnt <= 0)
- {
- return -RT_ETIMEOUT;
- }
- else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
- {
- return -RT_ERROR;
- }
-
- return RT_EOK;
-}
-
-static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
-{
- rt_uint32_t cmdidx;
- rt_err_t ret = RT_EOK;
- ret = sd_status(pdat, SR_CMD_INHIBIT);
- if (ret)
- {
- rt_kprintf("ERROR: EMMC busy %d\n", ret);
- return ret;
- }
-
- cmdidx = sdCommandTable[cmd->cmdidx];
- if (cmdidx == 0xFFFFFFFF)
- return -RT_EINVAL;
- if (cmd->datarw == DATA_READ)
- cmdidx |= SD_DATA_READ;
- if (cmd->datarw == DATA_WRITE)
- cmdidx |= SD_DATA_WRITE;
- mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
- write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
- write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
- write32(pdat->virt + EMMC_CMDTM, cmdidx);
- if (cmd->cmdidx == SD_APP_OP_COND)
- DELAY_MICROS(1000);
- else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
- DELAY_MICROS(100);
- ret = sd_int(pdat, INT_CMD_DONE);
- if (ret)
- {
- return ret;
- }
- if (cmd->resptype & RESP_MASK)
- {
-
- if (cmd->resptype & RESP_R2)
- {
- rt_uint32_t resp[4];
- resp[0] = read32(pdat->virt + EMMC_RESP0);
- resp[1] = read32(pdat->virt + EMMC_RESP1);
- resp[2] = read32(pdat->virt + EMMC_RESP2);
- resp[3] = read32(pdat->virt + EMMC_RESP3);
- if (cmd->resptype == RESP_R2)
- {
- cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
- cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
- cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
- cmd->response[3] = resp[0]<<8 ;
- }
- else
- {
- cmd->response[0] = resp[0];
- cmd->response[1] = resp[1];
- cmd->response[2] = resp[2];
- cmd->response[3] = resp[3];
- }
- }
- else
- cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
- }
- mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
- return ret;
-}
-
-static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
-{
- int c = 0;
- rt_err_t ret;
- int d;
- while (c < blkcount)
- {
- if ((ret = sd_int(pdat, INT_READ_RDY)))
- {
- rt_kprintf("timeout happens when reading block %d\n",c);
- return ret;
- }
- for (d=0; d < blksize / 4; d++)
- if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
- buf[d] = read32(pdat->virt + EMMC_DATA);
- c++;
- buf += blksize / 4;
- }
- return RT_EOK;
-}
-
-static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
-{
- int c = 0;
- rt_err_t ret;
- int d;
- while (c < blkcount)
- {
- if ((ret = sd_int(pdat, INT_WRITE_RDY)))
- {
- return ret;
- }
- for (d=0; d < blksize / 4; d++)
- write32(pdat->virt + EMMC_DATA, buf[d]);
- c++;
- buf += blksize / 4;
- }
- if ((ret = sd_int(pdat, INT_DATA_DONE)))
- {
- return ret;
- }
- return RT_EOK;
-}
-
-static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
-{
- rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
- rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
- if (ret)
- {
- rt_kprintf("ERROR: EMMC busy\n");
- return ret;
- }
- if (dat->blkcnt > 1)
- {
- struct sdhci_cmd_t newcmd;
- newcmd.cmdidx = SET_BLOCK_COUNT;
- newcmd.cmdarg = dat->blkcnt;
- newcmd.resptype = RESP_R1;
- ret = raspi_transfer_command(pdat, &newcmd);
- if (ret) return ret;
- }
-
- if(dlen < 512)
- {
- write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
- }
- else
- {
- write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
- }
- if (dat->flag & DATA_DIR_READ)
- {
- cmd->datarw = DATA_READ;
- ret = raspi_transfer_command(pdat, cmd);
- if (ret) return ret;
- mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
- ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
- }
- else if (dat->flag & DATA_DIR_WRITE)
- {
- cmd->datarw = DATA_WRITE;
- ret = raspi_transfer_command(pdat, cmd);
- if (ret) return ret;
- mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
- ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
- }
- return ret;
-}
-
-static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
-{
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
- if (!dat)
- return raspi_transfer_command(pdat, cmd);
-
- return raspi_transfer_data(pdat, cmd, dat);
-}
-
-static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
-{
- struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
- struct sdhci_cmd_t cmd;
- struct sdhci_cmd_t stop;
- struct sdhci_data_t dat;
- rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
- rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
- rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
-
- cmd.cmdidx = req->cmd->cmd_code;
- cmd.cmdarg = req->cmd->arg;
- cmd.resptype =resp_type(req->cmd);
- if (req->data)
- {
- dat.buf = (rt_uint8_t *)req->data->buf;
- dat.flag = req->data->flags;
- dat.blksz = req->data->blksize;
- dat.blkcnt = req->data->blks;
-
- req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
- }
- else
- {
- req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
- }
-
- req->cmd->resp[3] = cmd.response[3];
- req->cmd->resp[2] = cmd.response[2];
- req->cmd->resp[1] = cmd.response[1];
- req->cmd->resp[0] = cmd.response[0];
-
- if (req->stop)
- {
- stop.cmdidx = req->stop->cmd_code;
- stop.cmdarg = req->stop->arg;
- cmd.resptype =resp_type(req->stop);
- req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
- }
-
- mmcsd_req_complete(host);
-}
-
-rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
-{
- return 0;
-}
-
-void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en)
-{
-
-}
-
-static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
-{
- return RT_EOK;
-}
-
-static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
-{
- rt_uint32_t temp = 0;
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
- if (width == MMCSD_BUS_WIDTH_4)
- {
- temp = read32((pdat->virt + EMMC_CONTROL0));
- temp |= C0_HCTL_HS_EN;
- temp |= C0_HCTL_DWITDH; // always use 4 data lines:
- write32((pdat->virt + EMMC_CONTROL0), temp);
- }
- return RT_EOK;
-}
-
-static rt_uint32_t sdhci_getdivider(rt_uint32_t sdHostVer, rt_uint32_t freq)
-{
- rt_uint32_t divisor;
- rt_uint32_t closest = 41666666 / freq;
- rt_uint32_t shiftcount = __rt_fls(closest - 1);
-
-
- if (shiftcount > 0) shiftcount--;
- if (shiftcount > 7) shiftcount = 7;
- if (sdHostVer > HOST_SPEC_V2)
- divisor = closest;
- else
- divisor = (1 << shiftcount);
-
- if (divisor <= 2)
- {
- divisor = 2;
- shiftcount = 0;
- }
-
- rt_uint32_t hi = 0;
- if (sdHostVer > HOST_SPEC_V2)
- hi = (divisor & 0x300) >> 2;
- rt_uint32_t lo = (divisor & 0x0ff);
- rt_uint32_t cdiv = (lo << 8) + hi;
- return cdiv;
-}
-
-static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
-{
- rt_uint32_t temp = 0;
- rt_uint32_t sdHostVer = 0;
- int count = 100000;
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
-
- while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
- DELAY_MICROS(1);
- if (count <= 0)
- {
- rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
- return -RT_ERROR;
- }
-
- // Switch clock off.
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp &= ~C1_CLK_EN;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
- // Request the new clock setting and enable the clock
- temp = read32(pdat->virt + EMMC_SLOTISR_VER);
- sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
- int cdiv = sdhci_getdivider(sdHostVer, clock);
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp = (temp & 0xffff003f) | cdiv;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
-
- // Enable the clock.
- temp = read32(pdat->virt + EMMC_CONTROL1);
- temp |= C1_CLK_EN;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
- // Wait for clock to be stable.
- count = 10000;
- while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
- DELAY_MICROS(10);
- if (count <= 0)
- {
- rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
- return -RT_ERROR;
- }
- mmcsd_dbg("set stable clock %d.\n", clock);
- return RT_EOK;
-}
-
-static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
-{
- struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
- sdhci_setclock(sdhci, io_cfg->clock);
- sdhci_setwidth(sdhci, io_cfg->bus_width);
-}
-
-static const struct rt_mmcsd_host_ops ops =
-{
- mmc_request_send,
- mmc_set_iocfg,
- RT_NULL,
- RT_NULL,
-};
-
-static void sdmmc_gpio_init()
-{
-// int pin;
-// bcm283x_gpio_fsel(47,BCM283X_GPIO_FSEL_INPT);
-// bcm283x_gpio_set_pud(47, BCM283X_GPIO_PUD_UP);
-// bcm283x_peri_set_bits(BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN1, 1<<15, 1<<15);
-// for (pin = 53; pin >= 48; pin--)
-// {
-// bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3);
-// bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
-// }
-}
-
-static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat){
- rt_uint32_t temp;
- int cnt;
- write32((pdat->virt + EMMC_CONTROL0),0);
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp |= C1_SRST_HC;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- cnt = 10000;
- do
- {
- DELAY_MICROS(10);
- }
- while ((read32((pdat->virt + EMMC_CONTROL1)) & C1_SRST_HC) && cnt--);
- if (cnt <= 0)
- {
- rt_kprintf("ERROR: failed to reset EMMC\n");
- return -RT_ERROR;
- }
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
- return RT_EOK;
-}
-
-#ifdef RT_MMCSD_DBG
-void dump_registers(struct sdhci_pdata_t * pdat){
- rt_kprintf("EMMC registers:");
- int i = EMMC_ARG2;
- for (; i <= EMMC_CONTROL2; i += 4)
- rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
- rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
- rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
- rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
- rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
- rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
- rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
- rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
- rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
- rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
- rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
-}
-#endif
-
-int raspi_sdmmc_init(void)
-{
- rt_uint32_t virt;
- struct rt_mmcsd_host * host = RT_NULL;
- struct sdhci_pdata_t * pdat = RT_NULL;
- struct sdhci_t * sdhci = RT_NULL;
-#ifdef BSP_USING_SDIO0
- host = mmcsd_alloc_host();
- if (!host)
- {
- rt_kprintf("alloc host failed");
- goto err;
- }
-
- sdhci = rt_malloc(sizeof(struct sdhci_t));
- if (!sdhci)
- {
- rt_kprintf("alloc sdhci failed");
- goto err;
- }
- rt_memset(sdhci, 0, sizeof(struct sdhci_t));
-
- sdmmc_gpio_init();
- virt = MMC0_BASE_ADDR;
-
- pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
- RT_ASSERT(pdat != RT_NULL);
-
- pdat->virt = (rt_uint32_t)virt;
- reset_emmc(pdat);
-
- sdhci->name = "sd0";
- sdhci->voltages = VDD_33_34;
- sdhci->width = MMCSD_BUSWIDTH_4;
- sdhci->clock = 200 * 1000 * 1000;
- sdhci->removeable = RT_TRUE;
-
- sdhci->detect = sdhci_detect;
- sdhci->setwidth = sdhci_setwidth;
- sdhci->setclock = sdhci_setclock;
- sdhci->transfer = sdhci_transfer;
- sdhci->priv = pdat;
-
- host->ops = &ops;
- host->freq_min = 400000;
- host->freq_max = 50000000;
- host->valid_ocr = VDD_32_33 | VDD_33_34;
- host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
- host->max_seg_size = 2048;
- host->max_dma_segs = 10;
- host->max_blk_size = 512;
- host->max_blk_count = 4096;
-
- host->private_data = sdhci;
-
- write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
- write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
-#ifdef RT_MMCSD_DBG
- dump_registers(pdat);
-#endif
- mmcsd_change(host);
-#endif
- return RT_EOK;
-
-err:
- if (host) rt_free(host);
- if (sdhci) rt_free(sdhci);
-
- return -RT_EIO;
-}
-
-INIT_DEVICE_EXPORT(raspi_sdmmc_init);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h
deleted file mode 100644
index 726cf51cf5..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * File : drv_sdio.h
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_SDIO_H__
-#define __DRV_SDIO_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <drivers/dev_mmcsd_core.h>
-
-#include "board.h"
-
-#define MMC0_BASE_ADDR 0x3F300000
-
-/* Struct for Intrrrupt Information */
-#define SDXC_CmdDone BIT(0)
-#define SDXC_DataDone BIT(1)
-#define SDXC_BlockGap BIT(2)
-#define SDXC_WriteRdy BIT(4)
-#define SDXC_ReadRdy BIT(5)
-#define SDXC_Card BIT(8)
-#define SDXC_Retune BIT(12)
-#define SDXC_BootAck BIT(13)
-#define SDXC_EndBoot BIT(14)
-#define SDXC_Err BIT(15)
-#define SDXC_CTOErr BIT(16)
-#define SDXC_CCRCErr BIT(17)
-#define SDXC_CENDErr BIT(18)
-#define SDXC_CBADErr BIT(19)
-#define SDXC_DTOErr BIT(20)
-#define SDXC_DCRCErr BIT(21)
-#define SDXC_DENDErr BIT(22)
-#define SDXC_ACMDErr BIT(24)
-
-#define SDXC_BLKCNT_EN BIT(1)
-#define SDXC_AUTO_CMD12_EN BIT(2)
-#define SDXC_AUTO_CMD23_EN BIT(3)
-#define SDXC_DAT_DIR BIT(4) //from card to host
-#define SDXC_MULTI_BLOCK BIT(5)
-#define SDXC_CMD_RSPNS_136 BIT(16)
-#define SDXC_CMD_RSPNS_48 BIT(17)
-#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17)
-#define SDXC_CHECK_CRC_CMD BIT(19)
-#define SDXC_CMD_IXCHK_EN BIT(20)
-#define SDXC_CMD_ISDATA BIT(21)
-#define SDXC_CMD_SUSPEND BIT(22)
-#define SDXC_CMD_RESUME BIT(23)
-#define SDXC_CMD_ABORT BIT(23)|BIT(22)
-
-#define SDXC_CMD_INHIBIT BIT(0)
-#define SDXC_DAT_INHIBIT BIT(1)
-#define SDXC_DAT_ACTIVE BIT(2)
-#define SDXC_WRITE_TRANSFER BIT(8)
-#define SDXC_READ_TRANSFER BIT(9)
-
-struct sdhci_cmd_t
-{
- rt_uint32_t cmdidx;
- rt_uint32_t cmdarg;
- rt_uint32_t resptype;
- rt_uint32_t datarw;
-#define DATA_READ 1
-#define DATA_WRITE 2
- rt_uint32_t response[4];
-};
-
-struct sdhci_data_t
-{
- rt_uint8_t * buf;
- rt_uint32_t flag;
- rt_uint32_t blksz;
- rt_uint32_t blkcnt;
-};
-
-struct sdhci_t
-{
- char * name;
- rt_uint32_t voltages;
- rt_uint32_t width;
- rt_uint32_t clock;
- rt_err_t removeable;
- void * sdcard;
-
- rt_err_t (*detect)(struct sdhci_t * sdhci);
- rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width);
- rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock);
- rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat);
- void * priv;
-};
-
-struct sdhci_pdata_t
-{
- rt_uint32_t virt;
-};
-
-// EMMC command flags
-#define CMD_TYPE_NORMAL 0x00000000
-#define CMD_TYPE_SUSPEND 0x00400000
-#define CMD_TYPE_RESUME 0x00800000
-#define CMD_TYPE_ABORT 0x00c00000
-#define CMD_IS_DATA 0x00200000
-#define CMD_IXCHK_EN 0x00100000
-#define CMD_CRCCHK_EN 0x00080000
-#define CMD_RSPNS_NO 0x00000000
-#define CMD_RSPNS_136 0x00010000
-#define CMD_RSPNS_48 0x00020000
-#define CMD_RSPNS_48B 0x00030000
-#define TM_MULTI_BLOCK 0x00000020
-#define TM_DAT_DIR_HC 0x00000000
-#define TM_DAT_DIR_CH 0x00000010
-#define TM_AUTO_CMD23 0x00000008
-#define TM_AUTO_CMD12 0x00000004
-#define TM_BLKCNT_EN 0x00000002
-#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN)
-
-#define RCA_NO 1
-#define RCA_YES 2
-
-// INTERRUPT register settings
-#define INT_AUTO_ERROR 0x01000000
-#define INT_DATA_END_ERR 0x00400000
-#define INT_DATA_CRC_ERR 0x00200000
-#define INT_DATA_TIMEOUT 0x00100000
-#define INT_INDEX_ERROR 0x00080000
-#define INT_END_ERROR 0x00040000
-#define INT_CRC_ERROR 0x00020000
-#define INT_CMD_TIMEOUT 0x00010000
-#define INT_ERR 0x00008000
-#define INT_ENDBOOT 0x00004000
-#define INT_BOOTACK 0x00002000
-#define INT_RETUNE 0x00001000
-#define INT_CARD 0x00000100
-#define INT_READ_RDY 0x00000020
-#define INT_WRITE_RDY 0x00000010
-#define INT_BLOCK_GAP 0x00000004
-#define INT_DATA_DONE 0x00000002
-#define INT_CMD_DONE 0x00000001
-#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \
- INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \
- INT_ERR|INT_AUTO_ERROR)
-#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK)
-
-#define EMMC_ARG2 (0x00)
-#define EMMC_BLKSIZECNT (0x04)
-#define EMMC_ARG1 (0x08)
-#define EMMC_CMDTM (0x0c)
-#define EMMC_RESP0 (0x10)
-#define EMMC_RESP1 (0x14)
-#define EMMC_RESP2 (0x18)
-#define EMMC_RESP3 (0x1c)
-#define EMMC_DATA (0x20)
-#define EMMC_STATUS (0x24)
-#define EMMC_CONTROL0 (0x28)
-#define EMMC_CONTROL1 (0x2c)
-#define EMMC_INTERRUPT (0x30)
-#define EMMC_IRPT_MASK (0x34)
-#define EMMC_IRPT_EN (0x38)
-#define EMMC_CONTROL2 (0x3c)
-#define EMMC_BOOT_TIMEOUT (0x70)
-#define EMMC_EXRDFIFO_EN (0x84)
-#define EMMC_SPI_INT_SPT (0xf0)
-#define EMMC_SLOTISR_VER (0xfc)
-
-// CONTROL register settings
-#define C0_SPI_MODE_EN 0x00100000
-#define C0_HCTL_HS_EN 0x00000004
-#define C0_HCTL_DWITDH 0x00000002
-
-#define C1_SRST_DATA 0x04000000
-#define C1_SRST_CMD 0x02000000
-#define C1_SRST_HC 0x01000000
-#define C1_TOUNIT_DIS 0x000f0000
-#define C1_TOUNIT_MAX 0x000e0000
-#define C1_CLK_GENSEL 0x00000020
-#define C1_CLK_EN 0x00000004
-#define C1_CLK_STABLE 0x00000002
-#define C1_CLK_INTLEN 0x00000001
-
-#define FREQ_SETUP 400000 // 400 Khz
-#define FREQ_NORMAL 25000000 // 25 Mhz
-
-// SLOTISR_VER values
-#define HOST_SPEC_NUM 0x00ff0000
-#define HOST_SPEC_NUM_SHIFT 16
-#define HOST_SPEC_V3 2
-#define HOST_SPEC_V2 1
-#define HOST_SPEC_V1 0
-
-// STATUS register settings
-#define SR_DAT_LEVEL1 0x1e000000
-#define SR_CMD_LEVEL 0x01000000
-#define SR_DAT_LEVEL0 0x00f00000
-#define SR_DAT3 0x00800000
-#define SR_DAT2 0x00400000
-#define SR_DAT1 0x00200000
-#define SR_DAT0 0x00100000
-#define SR_WRITE_PROT 0x00080000 // From SDHC spec v2, BCM says reserved
-#define SR_READ_AVAILABLE 0x00000800 // ???? undocumented
-#define SR_WRITE_AVAILABLE 0x00000400 // ???? undocumented
-#define SR_READ_TRANSFER 0x00000200
-#define SR_WRITE_TRANSFER 0x00000100
-#define SR_DAT_ACTIVE 0x00000004
-#define SR_DAT_INHIBIT 0x00000002
-#define SR_CMD_INHIBIT 0x00000001
-
-#define CONFIG_MMC_USE_DMA
-#define DMA_ALIGN (32U)
-
-#define SD_CMD_INDEX(a) ((a) << 24)
-#define SD_CMD_RESERVED(a) 0xffffffff
-#define SD_CMD_INDEX(a) ((a) << 24)
-#define SD_CMD_TYPE_NORMAL 0x0
-#define SD_CMD_TYPE_SUSPEND (1 << 22)
-#define SD_CMD_TYPE_RESUME (2 << 22)
-#define SD_CMD_TYPE_ABORT (3 << 22)
-#define SD_CMD_TYPE_MASK (3 << 22)
-#define SD_CMD_ISDATA (1 << 21)
-#define SD_CMD_IXCHK_EN (1 << 20)
-#define SD_CMD_CRCCHK_EN (1 << 19)
-#define SD_CMD_RSPNS_TYPE_NONE 0 // For no response
-#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC)
-#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC)
-#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC)
-#define SD_CMD_RSPNS_TYPE_MASK (3 << 16)
-#define SD_CMD_MULTI_BLOCK (1 << 5)
-#define SD_CMD_DAT_DIR_HC 0
-#define SD_CMD_DAT_DIR_CH (1 << 4)
-#define SD_CMD_AUTO_CMD_EN_NONE 0
-#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2)
-#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2)
-#define SD_CMD_BLKCNT_EN (1 << 1)
-#define SD_CMD_DMA 1
-#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE
-#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) // | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B) // | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136) //| SD_CMD_CRCCHK_EN)
-#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48
-#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136
-#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
-#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c
deleted file mode 100644
index bb3c7479c6..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-#include "drv_spi.h"
-#include "raspi.h"
-
-#ifdef RT_USING_SPI
-
-#define RPI_CORE_CLK_HZ 250000000
-#define BSP_SPI_MAX_HZ (30* 1000 *1000)
-#define SPITIMEOUT 0x0FFF
-
-void spi_gpio_write(rt_uint8_t pin, rt_uint8_t val)
-{
- if (val)
- BCM283X_GPIO_GPSET((pin / 32)) = 1 << (pin % 32);
- else
- BCM283X_GPIO_GPCLR((pin / 32)) = 1 << (pin % 32);
-}
-
-struct raspi_spi_hw_config
-{
- rt_uint8_t spi_num;
- raspi_gpio_pin sclk_pin;
- raspi_pin_select sclk_mode;
- raspi_gpio_pin mosi_pin;
- raspi_pin_select mosi_mode;
- raspi_gpio_pin miso_pin;
- raspi_pin_select miso_mode;
-#if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0)
- raspi_gpio_pin ce0_pin;
- raspi_pin_select ce0_mode;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1)
- raspi_gpio_pin ce1_pin;
- raspi_pin_select ce1_mode;
-#endif
-
-#if defined (BSP_USING_SPI1_DEVICE2)
- raspi_gpio_pin ce2_pin;
- raspi_pin_select ce2_mode;
-#endif
-};
-
-struct raspi_spi_device
-{
- char *device_name;
- struct rt_spi_bus *spi_bus;
- struct rt_spi_device *spi_device;
- raspi_gpio_pin cs_pin;
-};
-
-static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
-{
- RT_ASSERT(cfg != RT_NULL);
- RT_ASSERT(device != RT_NULL);
- rt_uint16_t divider;
-
- // spi clear fifo
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CLEAR;
-
- if (cfg->mode & RT_SPI_CPOL)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPOL;
-
- if (cfg->mode & RT_SPI_CPHA)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPHA;
-
- if (cfg->mode & RT_SPI_CS_HIGH)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CSPOL;
-
- //set clk
- if (cfg->max_hz > BSP_SPI_MAX_HZ)
- cfg->max_hz = BSP_SPI_MAX_HZ;
-
- divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz);
- divider &= 0xFFFE;
-
- BCM283X_SPI0_CLK(BCM283X_SPI0_BASE) = divider;
-
- return RT_EOK;
-}
-
-rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag)
-{
- if (flag)
- return raspi_byte_reverse_table[b];
- else
- return b;
-}
-
-static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag)
-{
- rt_uint32_t TXCnt=0;
- rt_uint32_t RXCnt=0;
-
- /* Clear TX and RX fifos */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_CLEAR & BCM283X_SPI0_CS_CLEAR);
-
- /* Set TA = 1 */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_TA & BCM283X_SPI0_CS_TA);
-
-
- /* Use the FIFO's to reduce the interbyte times */
- while ((TXCnt < len) || (RXCnt < len))
- {
- /* TX fifo not full, so add some more bytes */
- while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len))
- {
- BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE) = correct_order(tbuf[TXCnt],flag);
- TXCnt++;
- }
- /* Rx fifo not empty, so get the next received bytes */
- while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len))
- {
- rbuf[RXCnt] = correct_order(BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE),flag);
- RXCnt++;
- }
- }
- /* Wait for DONE to be set */
- while (!(BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_DONE));
-
- /* Set TA = 0, and also set the barrier */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (0 & BCM283X_SPI0_CS_TA);
- return RT_EOK;
-}
-
-static rt_ssize_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
-{
-
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(device->parent.user_data != RT_NULL);
- RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);
-
- rt_err_t res;
- rt_uint8_t flag;
- struct rt_spi_configuration config = device->config;
- raspi_gpio_pin cs_pin = (raspi_gpio_pin)device->parent.user_data;
-
- if (config.mode & RT_SPI_MSB)
- flag = 0;
- else
- flag = 1;
- if (message->cs_take);
- // (config.mode & RT_SPI_CS_HIGH)?
- // spi_gpio_write(cs_pin, 1):
- // spi_gpio_write(cs_pin, 0);
-
- /* deal data */
- res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
- (rt_int32_t)message->length, flag);
-
- if (message->cs_release)
- (config.mode & RT_SPI_CS_HIGH)?
- spi_gpio_write(cs_pin, 0):
- spi_gpio_write(cs_pin, 1);
-
- if (res != RT_EOK)
- return res;
-
- return message->length;
-}
-
-rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device)
-{
- rt_err_t ret;
- RT_ASSERT(device != RT_NULL);
- ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device->cs_pin));
- return ret;
-}
-
-rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg)
-{
- GPIO_FSEL(hwcfg->sclk_pin, hwcfg->sclk_mode);
- GPIO_FSEL(hwcfg->miso_pin, hwcfg->miso_mode);
- GPIO_FSEL(hwcfg->mosi_pin, hwcfg->mosi_mode);
-
-#if defined (BSP_USING_SPI0_DEVICE0)
- GPIO_FSEL(hwcfg->ce0_pin, hwcfg->ce0_mode);
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- GPIO_FSEL(hwcfg->ce1_pin, hwcfg->ce1_mode);
-#endif
-
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = 0;
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = BCM283X_SPI0_CS_CLEAR;
-
- //enable chip select
-#if defined (BSP_USING_SPI0_DEVICE0)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0x2;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CS;
-#endif
- return RT_EOK;
-}
-
-static struct rt_spi_ops raspi_spi_ops =
-{
- .configure = raspi_spi_configure,
- .xfer = raspi_spi_xfer
-};
-
-#if defined (BSP_USING_SPI0_BUS)
-#define SPI0_BUS_NAME "spi0"
-#define SPI0_DEVICE0_NAME "spi0.0"
-#define SPI0_DEVICE1_NAME "spi0.1"
-
-struct rt_spi_bus spi0_bus;
-
-#if defined (BSP_USING_SPI0_DEVICE0)
-struct rt_spi_device spi0_device0;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
-static struct rt_spi_device spi0_device1;
-#endif
-
-struct raspi_spi_hw_config raspi_spi0_hw =
-{
- .spi_num = 0,
- .sclk_pin = RPI_GPIO_P1_23,
- .sclk_mode = BCM283X_GPIO_FSEL_ALT0,
- .mosi_pin = RPI_GPIO_P1_19,
- .mosi_mode = BCM283X_GPIO_FSEL_ALT0,
- .miso_pin = RPI_GPIO_P1_21,
- .miso_mode = BCM283X_GPIO_FSEL_ALT0,
-
-#if defined (BSP_USING_SPI0_DEVICE0)
- .ce0_pin = RPI_GPIO_P1_24,
- .ce0_mode = BCM283X_GPIO_FSEL_ALT0,
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- .ce1_pin = RPI_GPIO_P1_26,
- .ce1_mode = BCM283X_GPIO_FSEL_ALT0,
-#endif
-};
-#endif
-
-int rt_hw_spi_init(void)
-{
-
-#if defined (BSP_USING_SPI0_BUS)
- raspi_spi_hw_init(&raspi_spi0_hw);
- rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops);
-
-#if defined (BSP_USING_SPI0_DEVICE0)
- struct raspi_spi_device raspi_spi0_device0 =
- {
- .device_name = SPI0_DEVICE0_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device0,
- .cs_pin = raspi_spi0_hw.ce0_pin,
- };
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0);
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- struct raspi_spi_device raspi_spi0_device1 =
- {
- .device_name = SPI0_DEVICE1_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device1,
- .cs_pin = raspi_spi0_hw.ce1_pin,
- };
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1);
-#endif
-#endif
- return RT_EOK;
-}
-INIT_DEVICE_EXPORT(rt_hw_spi_init);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h
deleted file mode 100644
index 219afab8e7..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_SPI_H__
-#define __DRV_SPI_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-//#include "drivers/dev_spi.h"
-#include "board.h"
-
-#define SPI0_BASE_ADDR (PER_BASE + BCM283X_SPI0_BASE)
-
-static rt_uint8_t raspi_byte_reverse_table[] =
-{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-#define SPI_CORE_CLK 250000000U
-#define SPI_CS 0x00
-#define SPI_CS_LEN_LONG (1 << 25)
-#define SPI_CS_DMA_LEN (1 << 24)
-#define SPI_CS_CSPOL2 (1 << 23)
-#define SPI_CS_CSPOL1 (1 << 22)
-#define SPI_CS_CSPOL0 (1 << 21)
-#define SPI_CS_RXF (1 << 20)
-#define SPI_CS_RXR (1 << 19)
-#define SPI_CS_TXD (1 << 18)
-#define SPI_CS_RXD (1 << 17)
-#define SPI_CS_DONE (1 << 16)
-#define SPI_CS_LEN (1 << 13)
-#define SPI_CS_REN (1 << 12)
-#define SPI_CS_ADCS (1 << 11)
-#define SPI_CS_INTR (1 << 10)
-#define SPI_CS_INTD (1 << 9)
-#define SPI_CS_DMAEN (1 << 8)
-#define SPI_CS_TA (1 << 7)
-#define SPI_CS_CSPOL (1 << 6)
-#define SPI_CS_CLEAR_RXFIFO (1 << 5)
-#define SPI_CS_CLEAR_TXFIFO (1 << 4)
-#define SPI_CS_CPOL (1 << 3)
-#define SPI_CS_CPHA (1 << 2)
-#define SPI_CS_MASK 0x3
-#define SPI_FIFO 0x04
-#define SPI_CLK 0x08
-#define SPI_CLK_MASK 0xffff
-#define SPI_DLEN 0x0c
-#define SPI_DLEN_MASK 0xffff
-#define SPI_LTOH 0x10
-#define SPI_LTOH_MASK 0xf
-#define SPI_DC 0x14
-#define SPI_DC_RPANIC_SHIFT 24
-#define SPI_DC_RPANIC_MASK (0xff << SPI_DC_RPANIC_SHIFT)
-#define SPI_DC_RDREQ_SHIFT 16
-#define SPI_DC_RDREQ_MASK (0xff << SPI_DC_RDREQ_SHIFT)
-#define SPI_DC_TPANIC_SHIFT 8
-#define SPI_DC_TPANIC_MASK (0xff << SPI_DC_TPANIC_SHIFT)
-#define SPI_DC_TDREQ_SHIFT 0
-#define SPI_DC_TDREQ_MASK 0xff
-
-int rt_hw_spi_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c
deleted file mode 100644
index eff6fe5417..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#include "drv_timer.h"
-#include "interrupt.h"
-#include "raspi.h"
-
-#ifdef BSP_USING_SYSTIMER
-
-static void raspi_systimer_init(rt_clock_timer_t *clock_timer, rt_uint32_t state)
-{
- if (state == 0)
- clock_timer->ops->stop(clock_timer);
-}
-
-static rt_err_t raspi_systimer_start(rt_clock_timer_t *clock_timer, rt_uint32_t cnt, rt_clock_timer_mode_t mode)
-{
- rt_err_t result = RT_EOK;
- rt_systimer_t *timer = (rt_systimer_t *)clock_timer->parent.user_data;
- int timer_id = timer->timer_id;
-
- if (mode == CLOCK_TIMER_MODE_PERIOD)
- timer->cnt = cnt;
- else
- timer->cnt = 0;
-
- __sync_synchronize();
- if (timer_id == 1)
- {
- rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1);
- STIMER_C1 = STIMER_CLO + cnt;
- }
- else if (timer_id == 3)
- {
- rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3);
- STIMER_C3 = STIMER_CLO + cnt;
- }
- else
- result = -RT_ERROR;
-
- __sync_synchronize();
-
- return result;
-}
-
-static void raspi_systimer_stop(rt_clock_timer_t *clock_timer)
-{
- rt_systimer_t *timer = (rt_systimer_t *)clock_timer->parent.user_data;
- int timer_id = timer->timer_id;
- if (timer_id == 1)
- rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_1);
- else if (timer_id == 3)
- rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_3);
-
-}
-
-static rt_err_t raspi_systimer_ctrl(rt_clock_timer_t *timer, rt_uint32_t cmd, void *arg)
-{
- /* The frequency value is an immutable value. */
- if (cmd == CLOCK_TIMER_CTRL_FREQ_SET)
- {
- return RT_EOK;
- }
- else
- {
- return -RT_ENOSYS;
- }
-}
-
-
-void rt_device_systimer_isr(int vector, void *param)
-{
-
- rt_clock_timer_t *clock_timer = (rt_clock_timer_t *) param;
- rt_systimer_t *timer = (rt_systimer_t *)clock_timer->parent.user_data;
- RT_ASSERT(timer != RT_NULL);
-
- int timer_id = timer->timer_id;
-
- __sync_synchronize();
- if (timer_id == 1)
- {
- STIMER_CS = 0x2;
- STIMER_C1 = STIMER_CLO + timer->cnt;
- }
- else if (timer_id == 3)
- {
- STIMER_CS = 0x8;
- STIMER_C3 = STIMER_CLO + timer->cnt;
- }
- __sync_synchronize();
-
- rt_clock_timer_isr(clock_timer);
-}
-
-#ifdef RT_USING_SYSTIMER1
-static struct rt_clock_timer_device _clock_timer1;
-static rt_systimer_t _systimer1;
-#endif
-
-#ifdef RT_USING_SYSTIMER3
-static struct rt_clock_timer_device _clock_timer3;
-static rt_systimer_t _systimer3;
-#endif
-
-const static struct rt_clock_timer_ops systimer_ops =
-{
- raspi_systimer_init,
- raspi_systimer_start,
- raspi_systimer_stop,
- RT_NULL,
- raspi_systimer_ctrl
-};
-
-static const struct rt_clock_timer_info _info =
-{
- 1000000, /* the maxinum count frequency can be set */
- 1000000, /* the maxinum count frequency can be set */
- 0xFFFFFFFF, /* the maximum counter value */
- CLOCK_TIMER_CNTMODE_UP /* count mode (inc/dec) */
-};
-
-#endif
-
-int rt_hw_systimer_init(void)
-{
-
-#ifdef BSP_USING_SYSTIMER
-
-#ifdef RT_USING_SYSTIMER1
- _systimer1.timer_id =1;
- _clock_timer1.ops = &systimer_ops;
- _clock_timer1.info = &_info;
- rt_clock_timer_register(&_clock_timer1, "timer1",&_systimer1);
- rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_1, rt_device_systimer_isr, &_clock_timer1, "systimer1");
- rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1);
-#endif
-
-#ifdef RT_USING_SYSTIMER3
- _systimer3.timer_id =3;
- _clock_timer3.ops = &systimer_ops;
- _clock_timer3.info = &_info;
- rt_clock_timer_register(&_clock_timer3, "timer3",&_systimer3);
- rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_3, rt_device_systimer_isr, &_clock_timer3, "systimer3");
- rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3);
-#endif
-
-#endif
-
- return 0;
-}
-INIT_DEVICE_EXPORT(rt_hw_systimer_init);
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h
deleted file mode 100644
index ebe5536fa5..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-#ifndef __DRV_TIMER_H__
-#define __DRV_TIMER_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-typedef struct rt_systimer_device
-{
- int timer_id;
- rt_uint32_t cnt;
-} rt_systimer_t;
-
-int rt_hw_systimer_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c
deleted file mode 100644
index 6eb7a46f10..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018/5/5 Bernard The first version
- */
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "raspi.h"
-#include "board.h"
-#include "drv_uart.h"
-
-#define AUX_BASE (0x3F000000 + 0x215000)
-
-struct hw_uart_device
-{
- rt_ubase_t hw_base;
- rt_uint32_t irqno;
-};
-
-static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
-{
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- if (uart->hw_base == AUX_BASE)
- {
- rt_uint32_t value;
-
- /* GPIO function set */
- value = BCM283X_GPIO_GPFSEL(1);
- value &= ~(7 << 12); /* GPIO14 */
- value |= 2 << 12 ; /* ALT5 */
- value &= ~(7 << 15); /* GPIO15 */
- value |= 2 << 15 ; /* ALT5 */
- BCM283X_GPIO_GPFSEL(1) = value;
-
- BCM283X_GPIO_GPPUD = 0;
- BCM283X_GPIO_GPPUDCLK(0) = (1 << 14) | (1 << 15);
- BCM283X_GPIO_GPPUDCLK(0) = 0;
-
- AUX_ENABLES(uart->hw_base) = 1; /* Enable UART1 */
- AUX_MU_IER_REG(uart->hw_base) = 0; /* Disable interrupt */
- AUX_MU_CNTL_REG(uart->hw_base) = 0; /* Disable Transmitter and Receiver */
- AUX_MU_LCR_REG(uart->hw_base) = 3; /* Works in 8-bit mode */
- AUX_MU_MCR_REG(uart->hw_base) = 0; /* Disable RTS */
- AUX_MU_IIR_REG(uart->hw_base) = 0xC6; /* Enable FIFO, Clear FIFO */
- AUX_MU_BAUD_REG(uart->hw_base) = 270; /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */
- AUX_MU_CNTL_REG(uart->hw_base) = 3; /* Enable Transmitter and Receiver */
- }
-
- return RT_EOK;
-}
-
-static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
-{
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- /* disable rx irq */
- AUX_MU_IER_REG(uart->hw_base) = 0x0;
- rt_hw_interrupt_mask(uart->irqno);
- break;
-
- case RT_DEVICE_CTRL_SET_INT:
- /* enable rx irq */
- AUX_MU_IER_REG(uart->hw_base) = 0x1;
- rt_hw_interrupt_umask(uart->irqno);
- break;
- }
-
- return RT_EOK;
-}
-
-static int uart_putc(struct rt_serial_device *serial, char c)
-{
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20));
- AUX_MU_IO_REG(uart->hw_base) = c;
-
- return 1;
-}
-
-static int uart_getc(struct rt_serial_device *serial)
-{
- int ch = -1;
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01))
- {
- ch = AUX_MU_IO_REG(uart->hw_base) & 0xff;
- }
-
- return ch;
-}
-
-static const struct rt_uart_ops _uart_ops =
-{
- uart_configure,
- uart_control,
- uart_putc,
- uart_getc,
-};
-
-static void rt_hw_uart_isr(int irqno, void *param)
-{
- struct rt_serial_device *serial = (struct rt_serial_device*)param;
- rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
-}
-
-#ifdef RT_USING_UART0
-/* UART device driver structure */
-static struct hw_uart_device _uart0_device =
-{
- RPI_UART0_BASE,
- IRQ_PBA8_UART0,
-};
-static struct rt_serial_device _serial0;
-#endif
-
-#ifdef RT_USING_UART1
-/* UART1 device driver structure */
-static struct hw_uart_device _uart1_device =
-{
- AUX_BASE,
- IRQ_AUX,
-};
-static struct rt_serial_device _serial1;
-#endif
-
-int rt_hw_uart_init(void)
-{
- struct hw_uart_device *uart;
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
-
-#ifdef RT_USING_UART0
- uart = &_uart0_device;
-
- _serial0.ops = &_uart_ops;
- _serial0.config = config;
-
- /* register UART1 device */
- rt_hw_serial_register(&_serial0, "uart0",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart);
- rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart0");
-#endif
-
-#ifdef RT_USING_UART1
- uart = &_uart1_device;
- _serial1.ops = &_uart_ops;
- _serial1.config = config;
-
- /* register UART1 device */
- rt_hw_serial_register(&_serial1, "uart1",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart);
- /* enable Rx and Tx of UART */
- rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial1, "uart1");
-#endif
-
- return 0;
-}
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h
deleted file mode 100644
index 76072f938e..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2017-5-30 Bernard the first version
- */
-
-
-#ifndef DRV_UART_H__
-#define DRV_UART_H__
-
-/*
- * Auxiliary
- */
-#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */
-#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */
-#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */
-#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */
-#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */
-#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */
-#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */
-#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */
-#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */
-#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */
-#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */
-#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */
-#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */
-#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */
-#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */
-#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */
-#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */
-#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */
-#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */
-#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */
-
-int rt_hw_uart_init(void);
-
-#endif /* DRV_UART_H__ */
-
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c
deleted file mode 100644
index ccf8ca6cff..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-#include "drv_wdt.h"
-#include "raspi.h"
-
-#ifdef BSP_USING_WDT
-
-#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
-#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
-
-static struct raspi_wdt_driver bcm_wdt;
-
-void raspi_watchdog_init(rt_uint32_t time_init)
-{
- bcm_wdt.timeout = time_init;
-}
-
-void raspi_watchdog_start()
-{
- volatile rt_uint32_t cur;
- PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
- cur = PM_RSTC;
- PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
-}
-
-void raspi_watchdog_stop()
-{
- PM_RSTC = PM_PASSWORD | PM_RSTC_RESET;
-}
-
-void raspi_watchdog_clr()
-{
- bcm_wdt.timeout = 0;
-}
-
-void raspi_watchdog_set_timeout(rt_uint32_t timeout_us)
-{
- bcm_wdt.timeout = timeout_us;
-}
-
-rt_uint64_t raspi_watchdog_get_timeout()
-{
- return bcm_wdt.timeout;
-}
-
-rt_uint64_t raspi_watchdog_get_timeleft()
-{
- rt_uint32_t ret = PM_WDOG;
- return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
-}
-
-static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
-{
- /*init for 10S*/
- raspi_watchdog_init(1000000);
- raspi_watchdog_start();
- raspi_watchdog_stop();
- return RT_EOK;
-}
-
-static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
-{
- rt_uint64_t timeout_us = 0;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
- timeout_us = *((rt_uint32_t *)arg) * 1000000;
- if (timeout_us >= 0xFFFFFFFF)
- timeout_us = 0xFFFFFFFF;
- raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
- break;
- case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
- timeout_us = raspi_watchdog_get_timeout();
- *((rt_uint32_t *)arg) = timeout_us / 1000000;
- break;
- case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
- timeout_us = raspi_watchdog_get_timeleft();
- *((rt_uint32_t *)arg) = timeout_us / 1000000;
- break;
- case RT_DEVICE_CTRL_WDT_KEEPALIVE:
- raspi_watchdog_clr();
- break;
- case RT_DEVICE_CTRL_WDT_START:
- raspi_watchdog_start();
- break;
- case RT_DEVICE_CTRL_WDT_STOP:
- raspi_watchdog_stop();
- break;
- default:
- return -RT_EIO;
- }
- return RT_EOK;
-}
-
-static const struct rt_watchdog_ops raspi_wdg_pos =
-{
- raspi_wdg_init,
- raspi_wdg_control,
-};
-
-static rt_watchdog_t raspi_wdg;
-
-int rt_hw_wdt_init(void)
-{
- raspi_wdg.ops = &raspi_wdg_pos;
- rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
- return RT_EOK;
-}
-
-INIT_DEVICE_EXPORT(rt_hw_wdt_init);
-
-/**
- * Reboot
- */
-int reboot(void)
-{
- unsigned int r;
-
- rt_kprintf("reboot system...\n");
- rt_thread_mdelay(100);
- // trigger a restart by instructing the GPU to boot from partition 0
- r = PM_RSTS; r &= ~0xfffffaaa;
- PM_RSTS = PM_PASSWORD | r; // boot from partition 0
- PM_WDOG = PM_PASSWORD | 10;
- PM_RSTC = PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
-
- while (1);
-
- return 0;
-}
-MSH_CMD_EXPORT(reboot,reboot system...);
-#endif /*BSP_USING_WDT */
-
diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h
deleted file mode 100644
index ffb07ff5da..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __DRV_WDT_H__
-#define __DRV_WDT_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "board.h"
-
-struct raspi_wdt_driver
-{
- rt_uint32_t timeout;
-};
-
-int rt_hw_wdt_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/mbox.c b/bsp/raspberry-pi/raspi3-64/driver/mbox.c
deleted file mode 100644
index 6a8bb0633d..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/mbox.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * File : mbox.c
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-08-29 zdzn first version
- */
-
-/* mailbox message buffer */
-#include "mbox.h"
-#include "mmu.h"
-//volatile unsigned int __attribute__((aligned(16))) mbox[36];
-volatile unsigned int *mbox = (volatile unsigned int *) MBOX_ADDR;
-#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000)
-
-/**
- * Make a mailbox call. Returns 0 on failure, non-zero on success
- */
-int mbox_call(unsigned char ch, int mmu_enable)
-{
- unsigned int r = (((MBOX_ADDR)&~0xF) | (ch&0xF));
- if(mmu_enable)
- r = BUS_ADDRESS(r);
- /* wait until we can write to the mailbox */
- do
- {
- asm volatile("nop");
- } while (*MBOX_STATUS & MBOX_FULL);
- /* write the address of our message to the mailbox with channel identifier */
- *MBOX_WRITE = r;
- /* now wait for the response */
- // rt_kprintf("mailbox request %x\n",r);
- while(1)
- {
- /* is there a response? */
- do
- {
- asm volatile("nop");
- } while (*MBOX_STATUS & MBOX_EMPTY);
- /* is it a response to our message? */
- if (r == *MBOX_READ){
- /* is it a valid successful response? */
- // rt_kprintf("mbox: %x, %x, %x, %x, %x, %x, %x, %x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4], mbox[5], mbox[6], mbox[7]);
- return mbox[1] == MBOX_RESPONSE;
- }
- }
- return 0;
-}
-
-int bcm283x_mbox_hardware_get_model(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_MODEL;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- return mbox[5];
-}
-
-int bcm283x_mbox_hardware_get_revison(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_REV;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- return mbox[5];
-}
-
-int bcm283x_mbox_hardware_get_mac_address(uint8_t * mac)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_MAC_ADDRESS;
- mbox[3] = 6; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- char * mac_str = (char *)&mbox[5];
- mac[0] = mac_str[0];
- mac[1] = mac_str[1];
- mac[2] = mac_str[2];
- mac[3] = mac_str[3];
- mac[4] = mac_str[4];
- mac[5] = mac_str[5];
- return 0;
-}
-
-
-int bcm283x_mbox_hardware_get_serial(rt_uint64_t* sn)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_SERIAL;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- sn = (rt_uint64_t *)&mbox[5];
-
- return 0;
-}
-
-int bcm283x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_ARM_MEMORY;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- *base = mbox[5];
- *size = mbox[6];
-
- return 0;
-
-}
-
-int bcm283x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_VC_MEMORY;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- *base = mbox[5];
- *size = mbox[6];
-
- return 0;
-}
-
-int bcm283x_mbox_clock_get_turbo(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_TURBO;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0; // val
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_clock_set_turbo(int level)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_TURBO;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = 0; // id
- mbox[6] = level ? 1 : 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_clock_get_state(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm283x_mbox_clock_set_state(int id, int state)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = state & 0x3;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm283x_mbox_clock_get_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_clock_set_rate(int id, int rate)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = rate;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_clock_get_max_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_MAX_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_clock_get_min_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_MIN_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_power_get_state(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_POWER_GET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm283x_mbox_power_set_state(int id, int state)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_POWER_SET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = state & 0x3;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm283x_mbox_temp_get(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_TEMP_GET;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; //id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm283x_mbox_temp_get_max(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_TEMP_GET_MAX;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
diff --git a/bsp/raspberry-pi/raspi3-64/driver/mbox.h b/bsp/raspberry-pi/raspi3-64/driver/mbox.h
deleted file mode 100644
index c30a818803..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/mbox.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * File : mbox.h
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-08-29 zdzn first version
- */
-
-#ifndef __MBOX_H__
-#define __MBOX_H__
-
-#include <rtthread.h>
-#include <stdint.h>
-/* a properly aligned buffer */
-extern volatile unsigned int* mbox;
-
-#define MBOX_REQUEST 0
-
-/* channels */
-#define MBOX_CH_POWER 0
-#define MBOX_CH_FB 1
-#define MBOX_CH_VUART 2
-#define MBOX_CH_VCHIQ 3
-#define MBOX_CH_LEDS 4
-#define MBOX_CH_BTNS 5
-#define MBOX_CH_TOUCH 6
-#define MBOX_CH_COUNT 7
-#define MBOX_CH_PROP 8
-
-/* tags */
-#define MBOX_TAG_SETPOWER 0x28001
-#define MBOX_TAG_SETCLKRATE 0x38002
-#define MBOX_GET_MAC_ADDRESS 0x10003
-#define MBOX_TAG_LAST 0
-
-#define MMIO_BASE 0x3F000000
-#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
-#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
-#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10))
-#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14))
-#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18))
-#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C))
-#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20))
-#define MBOX_RESPONSE 0x80000000
-#define MBOX_FULL 0x80000000
-#define MBOX_EMPTY 0x40000000
-
-#define DEVICE_ID_SD_CARD 0
-#define DEVICE_ID_USB_HCD 3
-#define POWER_STATE_OFF (0 << 0)
-#define POWER_STATE_ON (1 << 0)
-#define POWER_STATE_WAIT (1 << 1)
-#define POWER_STATE_NO_DEVICE (1 << 1) // in response
-#define MMU_ENABLE 1
-#define MMU_DISABLE 0
-
-/*
- * raspi hardware info
- */
-enum {
- MBOX_TAG_HARDWARE_GET_MODEL = 0x00010001,
- MBOX_TAG_HARDWARE_GET_REV = 0x00010002,
- MBOX_TAG_HARDWARE_GET_MAC_ADDRESS = 0x00010003,
- MBOX_TAG_HARDWARE_GET_SERIAL = 0x00010004,
- MBOX_TAG_HARDWARE_GET_ARM_MEMORY = 0x00010005,
- MBOX_TAG_HARDWARE_GET_VC_MEMORY = 0x00010006,
- MBOX_TAG_HARDWARE_GET_CLOCKS = 0x00010007,
-};
-
-/*
- * raspi clock
- */
-enum {
- MBOX_TAG_CLOCK_GET_TURBO = 0x00030009,
- MBOX_TAG_CLOCK_SET_TURBO = 0x00038009,
- MBOX_TAG_CLOCK_GET_STATE = 0x00030001,
- MBOX_TAG_CLOCK_SET_STATE = 0x00038001,
- MBOX_TAG_CLOCK_GET_RATE = 0x00030002,
- MBOX_TAG_CLOCK_SET_RATE = 0x00038002,
- MBOX_TAG_CLOCK_GET_MAX_RATE = 0x00030004,
- MBOX_TAG_CLOCK_GET_MIN_RATE = 0x00030007,
-};
-
-/*
- * raspi power
- */
-enum {
- MBOX_TAG_POWER_GET_STATE = 0x00020001,
- MBOX_TAG_POWER_SET_STATE = 0x00028001,
-};
-
-/*
- * raspi temperature
- */
-enum {
- MBOX_TAG_TEMP_GET = 0x00030006,
- MBOX_TAG_TEMP_GET_MAX = 0x0003000A,
-};
-
-#define MBOX_ADDR 0xc00000
-
-int mbox_call(unsigned char ch, int mmu_enable);
-int bcm283x_mbox_hardware_get_model(void);
-int bcm283x_mbox_hardware_get_revison(void);
-int bcm283x_mbox_hardware_get_mac_address(uint8_t * mac);
-int bcm283x_mbox_hardware_get_serial(rt_uint64_t* sn);
-int bcm283x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size);
-int bcm283x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size);
-int bcm283x_mbox_clock_get_turbo(void);
-int bcm283x_mbox_clock_set_turbo(int level);
-int bcm283x_mbox_clock_get_state(int id);
-int bcm283x_mbox_clock_set_state(int id, int state);
-int bcm283x_mbox_clock_get_rate(int id);
-int bcm283x_mbox_clock_set_rate(int id, int rate);
-int bcm283x_mbox_clock_get_max_rate(int id);
-int bcm283x_mbox_clock_get_min_rate(int id);
-int bcm283x_mbox_power_get_state(int id);
-int bcm283x_mbox_power_set_state(int id, int state);
-int bcm283x_mbox_temp_get(void);
-int bcm283x_mbox_temp_get_max(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/driver/raspi.h b/bsp/raspberry-pi/raspi3-64/driver/raspi.h
deleted file mode 100644
index e8979b54f1..0000000000
--- a/bsp/raspberry-pi/raspi3-64/driver/raspi.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * File : rsapi.h
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
-
-#ifndef __RASPI_H__
-#define __RASPI_H__
-
-#include <rthw.h>
-
-#define __REG32(x) (*((volatile unsigned int*)((rt_uint64_t)x)))
-
-typedef enum
-{
- BCM_GPIO_PIN_0 = 0,
- BCM_GPIO_PIN_1,
- BCM_GPIO_PIN_2,
- BCM_GPIO_PIN_3,
- BCM_GPIO_PIN_4,
- BCM_GPIO_PIN_5,
- BCM_GPIO_PIN_6,
- BCM_GPIO_PIN_7,
- BCM_GPIO_PIN_8,
- BCM_GPIO_PIN_9,
- BCM_GPIO_PIN_10,
- BCM_GPIO_PIN_11,
- BCM_GPIO_PIN_12,
- BCM_GPIO_PIN_13,
- BCM_GPIO_PIN_14,
- BCM_GPIO_PIN_15,
- BCM_GPIO_PIN_16,
- BCM_GPIO_PIN_17,
- BCM_GPIO_PIN_18,
- BCM_GPIO_PIN_19,
- BCM_GPIO_PIN_20,
- BCM_GPIO_PIN_21,
- BCM_GPIO_PIN_22,
- BCM_GPIO_PIN_23,
- BCM_GPIO_PIN_24,
- BCM_GPIO_PIN_25,
- BCM_GPIO_PIN_26,
- BCM_GPIO_PIN_27,
- BCM_GPIO_PIN_28,
- BCM_GPIO_PIN_29,
- BCM_GPIO_PIN_30,
- BCM_GPIO_PIN_31,
- BCM_GPIO_PIN_32,
- BCM_GPIO_PIN_33,
- BCM_GPIO_PIN_34,
- BCM_GPIO_PIN_35,
- BCM_GPIO_PIN_36,
- BCM_GPIO_PIN_37,
- BCM_GPIO_PIN_38,
- BCM_GPIO_PIN_39,
- BCM_GPIO_PIN_40,
- BCM_GPIO_PIN_41,
- BCM_GPIO_PIN_42,
- BCM_GPIO_PIN_43,
- BCM_GPIO_PIN_44,
- BCM_GPIO_PIN_45,
- BCM_GPIO_PIN_46,
- BCM_GPIO_PIN_47,
- BCM_GPIO_PIN_48,
- BCM_GPIO_PIN_49,
- BCM_GPIO_PIN_50,
- BCM_GPIO_PIN_51,
- BCM_GPIO_PIN_52,
- BCM_GPIO_PIN_53,
- BCM_GPIO_PIN_NULL,
-} bcm_gpio_pin;
-
-typedef enum
-{
- BCM283X_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */
- BCM283X_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */
- BCM283X_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */
- BCM283X_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */
- BCM283X_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */
- BCM283X_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */
- BCM283X_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */
- BCM283X_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */
- BCM283X_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */
-} gpio_function_select;
-
-typedef enum
-{
- BCM283X_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */
- BCM283X_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */
- BCM283X_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */
-} gpio_pud_mode;
-
-#define BCM283X_CORE_CLK_HZ 250000000 /* 50 MHz */
-
-/* Base Address */
-#define PER_BASE (0x3F000000)
-#define PER_BASE_40000000 (0x40000000)
-//#define BCM283X_PERI_BASE (0x3F000000)
-//#define BCM283X_PER_BASE_40000000 (0x40000000)
-
-/* Base Address Registers Offset */
-#define ST_BASE_OFFSET (0x003000)
-#define GPIO_PAD_OFFSET (0x100000)
-#define CLOCK_BASE_OFFSET (0x101000)
-#define GPIO_BASE_OFFSET (0x200000)
-#define SPI0_BASE_OFFSET (0x204000)
-#define BSC0_BASE_OFFSET (0x205000)
-#define GPIO_PWM_OFFSET (0x20C000)
-#define AUX_BASE_OFFSET (0x215000)
-#define SPI1_BASE_OFFSET (0x215080)
-#define SPI2_BASE_OFFSET (0x2150C0)
-#define BSC1_BASE_OFFSET (0x804000)
-#define BSC2_BASE_OFFSET (0x805000)
-
-/* IRQ */
-#define MAX_HANDLERS 72
-#define IRQ_SYSTEM_TIMER_0 0
-#define IRQ_SYSTEM_TIMER_1 1
-#define IRQ_SYSTEM_TIMER_2 2
-#define IRQ_SYSTEM_TIMER_3 3
-#define IRQ_USB 9
-#define IRQ_AUX 29
-#define IRQ_PCM 55
-#define IRQ_ARM_TIMER 64
-#define IRQ_ARM_MAILBOX 65
-
-/* Interrupt Controler */
-#define IRQ_BASE (PER_BASE + 0xB200)
-#define IRQ_PEND_BASIC __REG32(IRQ_BASE + 0x0000)
-#define IRQ_PEND1 __REG32(IRQ_BASE + 0x0004)
-#define IRQ_PEND2 __REG32(IRQ_BASE + 0x0008)
-#define IRQ_FIQ_CONTROL __REG32(IRQ_BASE + 0x000C)
-#define IRQ_ENABLE1 __REG32(IRQ_BASE + 0x0010)
-#define IRQ_ENABLE2 __REG32(IRQ_BASE + 0x0014)
-#define IRQ_ENABLE_BASIC __REG32(IRQ_BASE + 0x0018)
-#define IRQ_DISABLE1 __REG32(IRQ_BASE + 0x001C)
-#define IRQ_DISABLE2 __REG32(IRQ_BASE + 0x0020)
-#define IRQ_DISABLE_BASIC __REG32(IRQ_BASE + 0x0024)
-
-
-/* Defines for WDT*/
-#define PM_BASE (PER_BASE + GPIO_PAD_OFFSET)
-#define PM_RSTC __REG32(PM_BASE + 0x001C)
-#define PM_RSTS __REG32(PM_BASE + 0x0020)
-#define PM_WDOG __REG32(PM_BASE + 0x0024)
-
-#define PM_PASSWORD 0x5a000000
-#define PM_WDOG_TIME_SET 0x000fffff
-#define PM_RSTC_WRCFG_CLR 0xffffffcf
-#define PM_RSTS_HADWRH_SET 0x00000040
-#define PM_RSTC_WRCFG_SET 0x00000030
-#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
-#define PM_RSTC_RESET 0x00000102
-#define PM_RSTS_PARTITION_CLR 0xfffffaaa
-
-/* Defines for System Timer */
-#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET)
-#define STIMER_CS __REG32(STIMER_BASE + 0x0000)
-#define STIMER_CLO __REG32(STIMER_BASE + 0x0004)
-#define STIMER_CHI __REG32(STIMER_BASE + 0x0008)
-#define STIMER_C0 __REG32(STIMER_BASE + 0x000C)
-#define STIMER_C1 __REG32(STIMER_BASE + 0x0010)
-#define STIMER_C2 __REG32(STIMER_BASE + 0x0014)
-#define STIMER_C3 __REG32(STIMER_BASE + 0x0018)
-
-#define DELAY_MICROS(micros) \
- do{ \
- rt_uint32_t compare = STIMER_CLO + micros * 25; \
- while (STIMER_CLO < compare); \
- } while (0) \
-
-/* Defines for GPIO */
-#define BCM283X_GPIO_BASE (PER_BASE + GPIO_BASE_OFFSET)
-#define BCM283X_GPIO_GPFSEL(n) __REG32(BCM283X_GPIO_BASE + 0x0000 + 0x4 * (n)) /* GPIO Function Select 32bit R/W */
-#define BCM283X_GPIO_GPSET(n) __REG32(BCM283X_GPIO_BASE + 0x001C + 0x4 * (n)) /* GPIO Pin Output Set */
-#define BCM283X_GPIO_GPCLR(n) __REG32(BCM283X_GPIO_BASE + 0x0028 + 0x4 * (n)) /* GPIO Pin Output Clear */
-#define BCM2835_GPIO_GPLEV(n) __REG32(BCM283X_GPIO_BASE + 0x0034 + 0x4 * (n)) /* GPIO Pin Level */
-#define BCM283X_GPIO_GPEDS(n) __REG32(BCM283X_GPIO_BASE + 0x0040 + 0x4 * (n)) /* GPIO Pin Event Detect Status */
-#define BCM283X_GPIO_GPREN(n) __REG32(BCM283X_GPIO_BASE + 0x004c + 0x4 * (n)) /* GPIO Pin Rising Edge Detect Enable */
-#define BCM283X_GPIO_GPFEN(n) __REG32(BCM283X_GPIO_BASE + 0x0058 + 0x4 * (n)) /* GPIO Pin Falling Edge Detect Enable */
-#define BCM283X_GPIO_GPHEN(n) __REG32(BCM283X_GPIO_BASE + 0x0064 + 0x4 * (n)) /* GPIO Pin High Detect Enable */
-#define BCM283X_GPIO_GPLEN(n) __REG32(BCM283X_GPIO_BASE + 0x0070 + 0x4 * (n)) /* GPIO Pin Low Detect Enable */
-#define BCM283X_GPIO_GPAREN(n) __REG32(BCM283X_GPIO_BASE + 0x007C + 0x4 * (n)) /* GPIO Pin Async. Rising Edge Detect */
-#define BCM283X_GPIO_GPAFEN(n) __REG32(BCM283X_GPIO_BASE + 0x0088 + 0x4 * (n)) /* GPIO Pin Async. Falling Edge Detect */
-#define BCM283X_GPIO_GPPUD __REG32(BCM283X_GPIO_BASE + 0x0094) /* GPIO Pin Pull-up/down Enable */
-#define BCM283X_GPIO_GPPUDCLK(n) __REG32(BCM283X_GPIO_BASE + 0x0098 + 0x4 * (n)) /* GPIO Pin Pull-up/down Enable Clock */
-
-#define GPIO_FSEL_NUM(pin) (pin/10)
-#define GPIO_FSEL_SHIFT(pin) ((pin%10)*3)
-#define GPIO_FSEL(pin, mode) \
- do{ \
- __sync_synchronize(); \
- BCM283X_GPIO_GPFSEL(GPIO_FSEL_NUM(pin)) |= ((mode & BCM283X_GPIO_FSEL_MASK) << GPIO_FSEL_SHIFT(pin)); \
- } while (0) \
-
-/* Defines for I2C */
-#define BCM283X_BSC0_BASE (PER_BASE + BSC0_BASE_OFFSET) //for i2c0
-#define BCM283X_BSC1_BASE (PER_BASE + BSC1_BASE_OFFSET) //for i2c1
-#define BCM283X_BSC2_BASE (PER_BASE + BSC2_BASE_OFFSET) //for hdmi i2c not use
-
-#define BCM283X_BSC_C(BASE) __REG32(BASE + 0x0000) /* BSC Master Control */
-#define BCM283X_BSC_S(BASE) __REG32(BASE + 0x0004) /* BSC Master Status */
-#define BCM283X_BSC_DLEN(BASE) __REG32(BASE + 0x0008) /* BSC Master Data Length */
-#define BCM283X_BSC_A(BASE) __REG32(BASE + 0x000c) /* BSC Master Slave Address */
-#define BCM283X_BSC_FIFO(BASE) __REG32(BASE + 0x0010) /* BSC Master Data FIFO */
-#define BCM283X_BSC_DIV(BASE) __REG32(BASE + 0x0014) /* BSC Master Clock Divider */
-#define BCM283X_BSC_DEL(BASE) __REG32(BASE + 0x0018) /* BSC Master Data Delay */
-#define BCM283X_BSC_CLKT(BASE) __REG32(BASE + 0x001c) /* BSC Master Clock Stretch Timeout */
-
-/* Register masks for C Register */
-#define BSC_C_I2CEN 0x00008000 /* I2C Enable, 0 = disabled, 1 = enabled */
-#define BSC_C_INTR 0x00000400 /* Interrupt on RX */
-#define BSC_C_INTT 0x00000200 /* Interrupt on TX */
-#define BSC_C_INTD 0x00000100 /* Interrupt on DONE */
-#define BSC_C_ST 0x00000080 /* Start transfer, 1 = Start a new transfer */
-#define BSC_C_CLEAR_1 0x00000020 /* Clear FIFO Clear */
-#define BSC_C_CLEAR_2 0x00000010 /* Clear FIFO Clear */
-#define BSC_C_READ 0x00000001 /* Read transfer */
-
-/* Register masks for S Register */
-#define BSC_S_CLKT 0x00000200 /* Clock stretch timeout */
-#define BSC_S_ERR 0x00000100 /* ACK error */
-#define BSC_S_RXF 0x00000080 /* RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */
-#define BSC_S_TXE 0x00000040 /* TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */
-#define BSC_S_RXD 0x00000020 /* RXD FIFO contains data */
-#define BSC_S_TXD 0x00000010 /* TXD FIFO can accept data */
-#define BSC_S_RXR 0x00000008 /* RXR FIFO needs reading (full) */
-#define BSC_S_TXW 0x00000004 /* TXW FIFO needs writing (full) */
-#define BSC_S_DONE 0x00000002 /* Transfer DONE */
-#define BSC_S_TA 0x00000001 /* Transfer Active */
-
-#define BSC_FIFO_SIZE (16) /* BSC FIFO size */
-
-/* Defines for SPI */
-#define BCM283X_SPI0_BASE (PER_BASE + SPI0_BASE_OFFSET)
-#define BCM283X_SPI1_BASE (PER_BASE + SPI1_BASE_OFFSET)
-#define BCM283X_SPI2_BASE (PER_BASE + SPI2_BASE_OFFSET)
-
-#define BCM283X_SPI0_CS(BASE) __REG32(BASE + 0x0000) /* SPI Master Control and Status */
-#define BCM283X_SPI0_FIFO(BASE) __REG32(BASE + 0x0004) /* SPI Master TX and RX FIFOs */
-#define BCM283X_SPI0_CLK(BASE) __REG32(BASE + 0x0008) /* SPI Master Clock Divider */
-#define BCM283X_SPI0_DLEN(BASE) __REG32(BASE + 0x000c) /* SPI Master Data Length */
-#define BCM283X_SPI0_LTOH(BASE) __REG32(BASE + 0x0010) /* SPI LOSSI mode TOH */
-#define BCM283X_SPI0_DC(BASE) __REG32(BASE + 0x0014) /* SPI DMA DREQ Controls */
-
-/* Register masks for SPI0_CS */
-#define BCM283X_SPI0_CS_LEN_LONG 0x02000000 /* Enable Long data word in Lossi mode if DMA_LEN is set */
-#define BCM283X_SPI0_CS_DMA_LEN 0x01000000 /* Enable DMA mode in Lossi mode */
-#define BCM283X_SPI0_CS_CSPOL2 0x00800000 /* Chip Select 2 Polarity */
-#define BCM283X_SPI0_CS_CSPOL1 0x00400000 /* Chip Select 1 Polarity */
-#define BCM283X_SPI0_CS_CSPOL0 0x00200000 /* Chip Select 0 Polarity */
-#define BCM283X_SPI0_CS_RXF 0x00100000 /* RXF - RX FIFO Full */
-#define BCM283X_SPI0_CS_RXR 0x00080000 /* RXR RX FIFO needs Reading (full) */
-#define BCM283X_SPI0_CS_TXD 0x00040000 /* TXD TX FIFO can accept Data */
-#define BCM283X_SPI0_CS_RXD 0x00020000 /* RXD RX FIFO contains Data */
-#define BCM283X_SPI0_CS_DONE 0x00010000 /* Done transfer Done */
-#define BCM283X_SPI0_CS_TE_EN 0x00008000 /* Unused */
-#define BCM283X_SPI0_CS_LMONO 0x00004000 /* Unused */
-#define BCM283X_SPI0_CS_LEN 0x00002000 /* LEN LoSSI enable */
-#define BCM283X_SPI0_CS_REN 0x00001000 /* REN Read Enable */
-#define BCM283X_SPI0_CS_ADCS 0x00000800 /* ADCS Automatically Deassert Chip Select */
-#define BCM283X_SPI0_CS_INTR 0x00000400 /* INTR Interrupt on RXR */
-#define BCM283X_SPI0_CS_INTD 0x00000200 /* INTD Interrupt on Done */
-#define BCM283X_SPI0_CS_DMAEN 0x00000100 /* DMAEN DMA Enable */
-#define BCM283X_SPI0_CS_TA 0x00000080 /* Transfer Active */
-#define BCM283X_SPI0_CS_CSPOL 0x00000040 /* Chip Select Polarity */
-#define BCM283X_SPI0_CS_CLEAR 0x00000030 /* Clear FIFO Clear RX and TX */
-#define BCM283X_SPI0_CS_CLEAR_RX 0x00000020 /* Clear FIFO Clear RX */
-#define BCM283X_SPI0_CS_CLEAR_TX 0x00000010 /* Clear FIFO Clear TX */
-#define BCM283X_SPI0_CS_CPOL 0x00000008 /* Clock Polarity */
-#define BCM283X_SPI0_CS_CPHA 0x00000004 /* Clock Phase */
-#define BCM283X_SPI0_CS_CS 0x00000003 /* Chip Select */
-
-/* ARM Timer */
-#define ARM_TIMER_BASE (PER_BASE + 0xB000)
-#define ARM_TIMER_LOAD __REG32(ARM_TIMER_BASE + 0x400)
-#define ARM_TIMER_VALUE __REG32(ARM_TIMER_BASE + 0x404)
-#define ARM_TIMER_CTRL __REG32(ARM_TIMER_BASE + 0x408)
-#define ARM_TIMER_IRQCLR __REG32(ARM_TIMER_BASE + 0x40C)
-#define ARM_TIMER_RAWIRQ __REG32(ARM_TIMER_BASE + 0x410)
-#define ARM_TIMER_MASKIRQ __REG32(ARM_TIMER_BASE + 0x414)
-#define ARM_TIMER_RELOAD __REG32(ARM_TIMER_BASE + 0x418)
-#define ARM_TIMER_PREDIV __REG32(ARM_TIMER_BASE + 0x41C)
-#define ARM_TIMER_CNTR __REG32(ARM_TIMER_BASE + 0x420)
-
-/* ARM Core Timer */
-#define C0TIMER_INTCTL __REG32(PER_BASE_40000000 + 0x40) /* Core0 timers Interrupt control */
-#define C1TIMER_INTCTL __REG32(PER_BASE_40000000 + 0x44) /* Core1 timers Interrupt control */
-#define C2TIMER_INTCTL __REG32(PER_BASE_40000000 + 0x48) /* Core2 timers Interrupt control */
-#define C3TIMER_INTCTL __REG32(PER_BASE_40000000 + 0x4C) /* Core3 timers Interrupt control */
-#define CORETIMER_INTCTL(n) __REG32(PER_BASE_40000000 + 0x40 + n*4) /* Coren timers Interrupt control */
-
-/*
- * Gtimer IRQ flag
- */
-#define SYSTEM_TIMER_IRQ_0 (1 << 0)
-#define SYSTEM_TIMER_IRQ_1 (1 << 1)
-#define SYSTEM_TIMER_IRQ_2 (1 << 2)
-#define SYSTEM_TIMER_IRQ_3 (1 << 3)
-
-#define NON_SECURE_TIMER_IRQ (1 << 1)
-rt_inline void core_timer_enable(int cpu_id)
-{
- CORETIMER_INTCTL(cpu_id) |= NON_SECURE_TIMER_IRQ;
-}
-
-/* ARM Core Mailbox interrupt */
-#define C0MB_INTCTL __REG32(PER_BASE_40000000 + 0x50) /* Core0 Mailboxes Interrupt control */
-#define C1MB_INTCTL __REG32(PER_BASE_40000000 + 0x54) /* Core1 Mailboxes Interrupt control */
-#define C2MB_INTCTL __REG32(PER_BASE_40000000 + 0x58) /* Core2 Mailboxes Interrupt control */
-#define C3MB_INTCTL __REG32(PER_BASE_40000000 + 0x5C) /* Core3 Mailboxes Interrupt control */
-#define COREMB_INTCTL(n) __REG32(PER_BASE_40000000 + 0x50 + 4*n) /* Coren Mailboxes Interrupt control */
-
-/* ARM Core IRQ/FIQ status */
-#define C0_IRQSOURCE __REG32(PER_BASE_40000000 + 0x60) /* Core0 IRQ Source */
-#define C1_IRQSOURCE __REG32(PER_BASE_40000000 + 0x64) /* Core1 IRQ Source */
-#define C2_IRQSOURCE __REG32(PER_BASE_40000000 + 0x68) /* Core2 IRQ Source */
-#define C3_IRQSOURCE __REG32(PER_BASE_40000000 + 0x6C) /* Core3 IRQ Source */
-#define C0_FIQSOURCE __REG32(PER_BASE_40000000 + 0x70) /* Core0 FIQ Source */
-#define C1_FIQSOURCE __REG32(PER_BASE_40000000 + 0x74) /* Core1 FIQ Source */
-#define C2_FIQSOURCE __REG32(PER_BASE_40000000 + 0x78) /* Core2 FIQ Source */
-#define C3_FIQSOURCE __REG32(PER_BASE_40000000 + 0x7C) /* Core3 FIQ Source */
-#define CORE_IRQSOURCE(n) __REG32(PER_BASE_40000000 + 0x60+ n*0x4)
-#define CORE_FIQSOURCE(n) __REG32(PER_BASE_40000000 + 0x70+ n*0x4)
-
-#define CORE_MAILBOX3_SET(n) __REG32(PER_BASE_40000000 + 0x8C + n*0x10)
-#define CORE_MAILBOX3_CLEAR(n) __REG32(PER_BASE_40000000 + 0xCC + n*0x10)
-#define CORE_MAILBOX2_SET(n) __REG32(PER_BASE_40000000 + 0x88 + n*0x10)
-#define CORE_MAILBOX2_CLEAR(n) __REG32(PER_BASE_40000000 + 0xC8 + n*0x10)
-#define CORE_MAILBOX1_SET(n) __REG32(PER_BASE_40000000 + 0x84 + n*0x10)
-#define CORE_MAILBOX1_CLEAR(n) __REG32(PER_BASE_40000000 + 0xC4 + n*0x10)
-#define CORE_MAILBOX0_SET(n) __REG32(PER_BASE_40000000 + 0x80 + n*0x10)
-#define CORE_MAILBOX0_CLEAR(n) __REG32(PER_BASE_40000000 + 0xC0 + n*0x10)
-
-/* For SMP IPI use MailBox0 */
-#define IPI_MAILBOX_SET CORE_MAILBOX0_SET
-#define IPI_MAILBOX_CLEAR CORE_MAILBOX0_CLEAR
-#define IPI_MAILBOX_INT_MASK (0x01)
-rt_inline void enable_cpu_ipi_intr(int cpu_id)
-{
- COREMB_INTCTL(cpu_id) = IPI_MAILBOX_INT_MASK;
-}
-
-enum spi_bit_order
-{
- BCM283X_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */
- BCM283X_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */
-};
-
-enum spi_mode
-{
- BCM283X_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */
- BCM283X_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */
- BCM283X_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */
- BCM283X_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */
-};
-
-enum spi_chip_select
-{
- BCM283X_SPI_CS0 = 0, /*!< Chip Select 0 */
- BCM283X_SPI_CS1 = 1, /*!< Chip Select 1 */
- BCM283X_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */
- BCM283X_SPI_CS_NONE = 3 /*!< No CS, control it yourself */
-};
-
-enum spi_clock_divider
-{
- BCM283X_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */
- BCM283X_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */
- BCM283X_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/
- BCM283X_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */
-};
-
-/*redefine for raspi*/
-typedef gpio_function_select raspi_pin_select;
-typedef enum
-{
- RPI_GPIO_P1_01 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_02 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_03 = BCM_GPIO_PIN_2,
- RPI_GPIO_P1_04 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_05 = BCM_GPIO_PIN_3,
- RPI_GPIO_P1_06 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_07 = BCM_GPIO_PIN_4,
- RPI_GPIO_P1_08 = BCM_GPIO_PIN_14,
- RPI_GPIO_P1_09 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_10 = BCM_GPIO_PIN_15,
- RPI_GPIO_P1_11 = BCM_GPIO_PIN_17,
- RPI_GPIO_P1_12 = BCM_GPIO_PIN_18,
- RPI_GPIO_P1_13 = BCM_GPIO_PIN_27,
- RPI_GPIO_P1_14 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_15 = BCM_GPIO_PIN_22,
- RPI_GPIO_P1_16 = BCM_GPIO_PIN_23,
- RPI_GPIO_P1_17 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_18 = BCM_GPIO_PIN_24,
- RPI_GPIO_P1_19 = BCM_GPIO_PIN_10,
- RPI_GPIO_P1_20 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_21 = BCM_GPIO_PIN_9,
- RPI_GPIO_P1_22 = BCM_GPIO_PIN_25,
- RPI_GPIO_P1_23 = BCM_GPIO_PIN_11,
- RPI_GPIO_P1_24 = BCM_GPIO_PIN_8,
- RPI_GPIO_P1_25 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_26 = BCM_GPIO_PIN_7,
- RPI_GPIO_P1_27 = BCM_GPIO_PIN_0,
- RPI_GPIO_P1_28 = BCM_GPIO_PIN_1,
- RPI_GPIO_P1_29 = BCM_GPIO_PIN_5,
- RPI_GPIO_P1_30 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_31 = BCM_GPIO_PIN_6,
- RPI_GPIO_P1_32 = BCM_GPIO_PIN_12,
- RPI_GPIO_P1_33 = BCM_GPIO_PIN_13,
- RPI_GPIO_P1_34 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_35 = BCM_GPIO_PIN_19,
- RPI_GPIO_P1_36 = BCM_GPIO_PIN_16,
- RPI_GPIO_P1_37 = BCM_GPIO_PIN_26,
- RPI_GPIO_P1_38 = BCM_GPIO_PIN_20,
- RPI_GPIO_P1_39 = BCM_GPIO_PIN_NULL,
- RPI_GPIO_P1_40 = BCM_GPIO_PIN_21,
-} raspi_gpio_pin;
-
-typedef enum
-{
- BCM283X_I2C_CLOCK_DIVIDER_2500 = 2500, /* 2500 = 10us = 100 kHz */
- BCM283X_I2C_CLOCK_DIVIDER_626 = 626, /* 622 = 2.504us = 399.3610 kHz */
- BCM283X_I2C_CLOCK_DIVIDER_150 = 150, /* 150 = 60ns = 1.666 MHz (default at reset) */
- BCM283X_I2C_CLOCK_DIVIDER_148 = 148 /* 148 = 59ns = 1.689 MHz */
-} i2c_clock_divider;
-
-typedef enum
-{
- BCM283X_I2C_REASON_OK = 0x00, /* Success */
- BCM283X_I2C_REASON_ERROR_NACK = 0x01, /* Received a NACK */
- BCM283X_I2C_REASON_ERROR_CLKT = 0x02, /* Received Clock Stretch Timeout */
- BCM283X_I2C_REASON_ERROR_DATA = 0x04 /* Not all data is sent / received */
-} i2c_reason_codes;
-
-#endif
diff --git a/bsp/raspberry-pi/raspi3-64/link.lds b/bsp/raspberry-pi/raspi3-64/link.lds
deleted file mode 100644
index 953be4c28b..0000000000
--- a/bsp/raspberry-pi/raspi3-64/link.lds
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * 2017-5-30 bernard first version
- */
-
-/* _EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 0x20000; */
-
-SECTIONS
-{
- . = 0x80000;
- . = ALIGN(4096);
- .text :
- {
- KEEP(*(.text.entrypoint)) /* The entry point */
- *(.vectors)
- *(.text) /* remaining code */
- *(.text.*) /* remaining code */
-
- *(.rodata) /* read-only data (constants) */
- *(.rodata*)
- *(.glue_7)
- *(.glue_7t)
- *(.gnu.linkonce.t*)
-
- *(COMMON)
-
- /* section information for finsh shell */
- . = ALIGN(16);
- __fsymtab_start = .;
- KEEP(*(FSymTab))
- __fsymtab_end = .;
- . = ALIGN(16);
- __vsymtab_start = .;
- KEEP(*(VSymTab))
- __vsymtab_end = .;
- . = ALIGN(16);
-
- /* section information for initial. */
- . = ALIGN(16);
- __rt_init_start = .;
- KEEP(*(SORT(.rti_fn*)))
- __rt_init_end = .;
- . = ALIGN(16);
-
- . = ALIGN(16);
- _etext = .;
- }
-
- .eh_frame_hdr :
- {
- *(.eh_frame_hdr)
- *(.eh_frame_entry)
- }
- .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
-
- . = ALIGN(16);
- .data :
- {
- *(.data)
- *(.data.*)
-
- *(.data1)
- *(.data1.*)
-
- . = ALIGN(16);
- _gp = ABSOLUTE(.); /* Base of small data */
-
- *(.sdata)
- *(.sdata.*)
- }
-
- . = ALIGN(16);
- .ctors :
- {
- PROVIDE(__ctors_start__ = .);
- /* new GCC version uses .init_array */
- KEEP(*(SORT(.init_array.*)))
- KEEP(*(.init_array))
- PROVIDE(__ctors_end__ = .);
- }
-
- .dtors :
- {
- PROVIDE(__dtors_start__ = .);
- KEEP(*(SORT(.dtors.*)))
- KEEP(*(.dtors))
- PROVIDE(__dtors_end__ = .);
- }
-
- . = ALIGN(16);
- .bss :
- {
- PROVIDE(__bss_start = .);
- *(.bss)
- *(.bss.*)
- *(.dynbss)
-
- PROVIDE(__bss_end = .);
- }
- _end = .;
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- * Symbols in the DWARF debugging sections are relative to the beginning
- * of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
-}
-
-__bss_size = SIZEOF(.bss);
diff --git a/bsp/raspberry-pi/raspi3-64/qemu-64.bat b/bsp/raspberry-pi/raspi3-64/qemu-64.bat
deleted file mode 100755
index b57c8a5b5b..0000000000
--- a/bsp/raspberry-pi/raspi3-64/qemu-64.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-@echo off
-if exist sd.bin goto run
-qemu-img create -f raw sd.bin 64M
-
-:run
-qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -sd sd.bin \ No newline at end of file
diff --git a/bsp/raspberry-pi/raspi3-64/qemu-64.sh b/bsp/raspberry-pi/raspi3-64/qemu-64.sh
deleted file mode 100644
index db14a102df..0000000000
--- a/bsp/raspberry-pi/raspi3-64/qemu-64.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-if [ ! -f "sd.bin" ]; then
-dd if=/dev/zero of=sd.bin bs=1024 count=65536
-fi
-qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -sd sd.bin -nographic -monitor pty \ No newline at end of file
diff --git a/bsp/raspberry-pi/raspi3-64/qemu.py b/bsp/raspberry-pi/raspi3-64/qemu.py
new file mode 100755
index 0000000000..01326e54c3
--- /dev/null
+++ b/bsp/raspberry-pi/raspi3-64/qemu.py
@@ -0,0 +1,74 @@
+#!/bin/python
+# -*- coding: utf-8 -*-
+import os, sys, re, shutil
+
+with open('rtconfig.h', 'r') as file:
+ rtconfig_header = file.read()
+
+if os.getenv('RTT_QEMU_ROOT'):
+ RTT_QEMU_ROOT = os.getenv('RTT_QEMU_ROOT')
+else:
+ RTT_QEMU_ROOT = ""
+
+if os.getenv('RTT_ROOT'):
+ RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+ RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
+
+sys.path.append(RTT_ROOT + '/tools')
+
+from building import *
+import dtc
+
+dts_name = "bcm283x-rpi-3-b"
+
+dtc.dts_to_dtb(RTT_ROOT, ["../dm/dts/" + dts_name + ".dts"], include_paths = [os.getcwd() + '/../dm/include'],
+ ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property", "unique_unit_address"])
+try:
+ shutil.move("../dm/dts/" + dts_name + ".dtb", dts_name + ".dtb")
+except:
+ exit(-1)
+
+opt = sys.argv
+
+q_graphic = "-nographic"
+q_debug = ""
+
+def is_opt(key, inkey):
+ if str("-" + key) == inkey:
+ return True
+ return False
+
+for i in range(len(opt)):
+ if i == 0:
+ continue
+ inkey = opt[i]
+
+ if is_opt("debug", inkey): q_debug = "-S -s"
+ if is_opt("graphic", inkey): q_graphic = "-device usb-kbd,port=1.2 -device usb-mouse,port=1.3"
+
+disk = "sd.qcow2"
+if not os.path.exists(disk):
+ os.system("qemu-img create -f qcow2 {} 64M".format(disk))
+
+flash = "flash.bin"
+if not os.path.exists(flash):
+ os.system("qemu-img create -f raw {} 1M".format(flash))
+
+os.system("""
+{}qemu-system-aarch64 \
+ -M raspi3b \
+ -m 1G \
+ -kernel kernel8.img \
+ -dtb {}.dtb \
+ -append "console=ttyAMA0 earlycon=pl011,0x3f201000 cma=8M coherent_pool=2M root=sd0p0 rootfstype=elm rootwait rw" \
+ -serial mon:stdio \
+ -drive if=sd,file={},format=qcow2 \
+ -device ds1338,address=0x68,bus=i2c-bus.0 \
+ -device m25p80,write-enable=true,drive=flash0,bus=spi \
+ -blockdev node-name=flash0,driver=file,filename={} \
+ -device usb-hub,port=1 \
+ -device usb-net,netdev=net0,port=1.1 -netdev user,id=net0 \
+ {} \
+ {}
+""".format(RTT_QEMU_ROOT, dts_name, disk, flash, q_graphic, q_debug))
diff --git a/bsp/raspberry-pi/raspi3-64/rtconfig.h b/bsp/raspberry-pi/raspi3-64/rtconfig.h
index 07be2b0c7c..70bb92ce6a 100644
--- a/bsp/raspberry-pi/raspi3-64/rtconfig.h
+++ b/bsp/raspberry-pi/raspi3-64/rtconfig.h
@@ -7,17 +7,6 @@
/* rt_vsnprintf options */
-#define RT_KLIBC_USING_VSNPRINTF_LONGLONG
-#define RT_KLIBC_USING_VSNPRINTF_STANDARD
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6
-#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
-#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4
/* end of rt_vsnprintf options */
/* rt_vsscanf options */
@@ -72,8 +61,9 @@
/* end of rt_strnlen options */
/* end of klibc options */
-#define RT_NAME_MAX 12
-#define RT_CPUS_NR 1
+#define RT_NAME_MAX 24
+#define RT_USING_SMP
+#define RT_CPUS_NR 4
#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
@@ -84,9 +74,12 @@
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 8192
+#define SYSTEM_THREAD_STACK_SIZE 8192
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
-#define RT_TIMER_THREAD_STACK_SIZE 4096
+#define RT_TIMER_THREAD_STACK_SIZE 8192
+#define RT_USING_CPU_USAGE_TRACER
+#define RT_CPU_USAGE_CALC_INTERVAL_MS 200
/* kservice options */
@@ -117,11 +110,13 @@
/* end of Memory Management */
#define RT_USING_DEVICE
#define RT_USING_DEVICE_OPS
+#define RT_USING_INTERRUPT_INFO
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 512
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_USING_CONSOLE_OUTPUT_CTL
#define RT_VER_NUM 0x50300
+#define RT_USING_STDC_ATOMIC
#define RT_BACKTRACE_LEVEL_MAX_NR 32
/* end of RT-Thread Kernel */
@@ -131,6 +126,7 @@
#define ARCH_RAM_OFFSET 0
#define ARCH_SECONDARY_CPU_STACK_SIZE 4096
#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#define ARCH_USING_GENERIC_CPUID
#define ARCH_HEAP_SIZE 0x4000000
#define ARCH_INIT_PAGE_SIZE 0x200000
/* end of AArch64 Architecture Configuration */
@@ -142,20 +138,21 @@
#define ARCH_ARM_MMU
#define ARCH_ARMV8
#define ARCH_USING_ASID
+#define ARCH_USING_HW_THREAD_SELF
#define ARCH_USING_IRQ_CTX_LIST
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
-#define RT_MAIN_THREAD_STACK_SIZE 4096
+#define RT_MAIN_THREAD_STACK_SIZE 8192
#define RT_MAIN_THREAD_PRIORITY 10
#define RT_USING_MSH
#define RT_USING_FINSH
#define FINSH_USING_MSH
#define FINSH_THREAD_NAME "tshell"
#define FINSH_THREAD_PRIORITY 20
-#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_THREAD_STACK_SIZE 8192
#define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5
#define FINSH_USING_SYMTAB
@@ -171,9 +168,7 @@
#define DFS_USING_POSIX
#define DFS_USING_WORKDIR
#define DFS_FD_MAX 16
-#define RT_USING_DFS_V1
-#define DFS_FILESYSTEMS_MAX 2
-#define DFS_FILESYSTEM_TYPES_MAX 2
+#define RT_USING_DFS_V2
#define RT_USING_DFS_ELMFAT
/* elm-chan's FatFs, Generic FAT Filesystem Module */
@@ -195,25 +190,79 @@
/* Device Drivers */
+#define RT_USING_DM
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
+#define RT_USING_SYSTEM_WORKQUEUE
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 8192
+#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_SERIAL_BYPASS
+#define RT_SERIAL_PL011
+#define RT_SERIAL_8250
+#define RT_SERIAL_8250_BCM2835AUX
#define RT_USING_CLOCK_TIME
+#define RT_CLOCK_TIME_ARM_ARCH
+#define RT_CLOCK_TIME_BCM2835
#define RT_USING_I2C
#define RT_I2C_DEBUG
-#define RT_USING_I2C_BITOPS
+#define RT_I2C_BCM2835
+#define RT_USING_NULL
+#define RT_USING_ZERO
+#define RT_USING_RANDOM
+#define RT_USING_PWM
+#define RT_PWM_BCM2835
+#define RT_USING_MTD_NOR
+#define RT_USING_MTD_NOR_SPI
+#define RT_USING_RTC
+#define RT_USING_ALARM
+#define RT_ALARM_STACK_SIZE 8192
+#define RT_ALARM_TIMESLICE 5
+#define RT_ALARM_PRIORITY 10
+#define RT_RTC_DS1307
#define RT_USING_SDIO
-#define RT_SDIO_STACK_SIZE 2048
+#define RT_SDIO_STACK_SIZE 8192
#define RT_SDIO_THREAD_PRIORITY 15
-#define RT_MMCSD_STACK_SIZE 4096
+#define RT_MMCSD_STACK_SIZE 8192
#define RT_MMCSD_THREAD_PRIORITY 22
#define RT_MMCSD_MAX_PARTITION 16
-#define RT_SDIO_DEBUG
+#define RT_USING_SDHCI
+#define RT_SDIO_SDHCI_IPROC
#define RT_USING_SPI
#define RT_USING_SPI_ISR
+#define RT_USING_SFUD
+#define RT_SFUD_USING_SFDP
+#define RT_SFUD_USING_FLASH_INFO_TABLE
+#define RT_SFUD_SPI_MAX_HZ 50000000
+#define RT_SPI_BCM2835
#define RT_USING_WDT
+#define RT_WDT_BCM2835
+#define RT_USING_AUDIO
+#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096
+#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2
+#define RT_AUDIO_RECORD_PIPE_SIZE 2048
+#define RT_AUDIO_BCM2835_I2S
+#define RT_USING_LCD
+#define RT_USING_GRAPHIC
+#define RT_GRAPHIC_FB
+#define RT_GRAPHIC_FB_BCM2708
+#define RT_GRAPHIC_LOGO
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH "../dm/graphic/logo/logo-raspi-clut224.ppm"
+#define RT_USING_HWCRYPTO
+#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto"
+#define RT_HWCRYPTO_IV_MAX_SIZE 16
+#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256
+#define RT_HWCRYPTO_USING_RNG
+#define RT_HWCRYPTO_RNG_BCM2835
+#define RT_USING_LED
+#define RT_LED_GPIO
+#define RT_USING_MBOX
+#define RT_MBOX_BCM2835
+#define RT_USING_PHYE
+#define RT_PHYE_GENERIC_USB
#define RT_USING_BLK
/* Partition Types */
@@ -221,7 +270,53 @@
#define RT_BLK_PARTITION_DFS
#define RT_BLK_PARTITION_EFI
/* end of Partition Types */
+#define RT_USING_FIRMWARE
+#define RT_FIRMWARE_RASPBERRYPI
+#define RT_USING_REGULATOR
+#define RT_REGULATOR_FIXED
+#define RT_REGULATOR_GPIO
+#define RT_USING_RESET
+
+/* Power Management (PM) Domains device drivers */
+
+#define RT_PMDOMAIN_BCM2835
+#define RT_PMDOMAIN_RASPBERRYPI
+/* end of Power Management (PM) Domains device drivers */
+#define RT_USING_THERMAL
+
+/* Thermal Sensors Drivers */
+
+#define RT_THERMAL_BCM2835
+
+/* Thermal Cool Drivers */
+
+#define RT_USING_NVMEM
+#define RT_NVMEM_RASPBERRYPI_OTP
+#define RT_USING_DMA
+#define RT_DMA_BCM2835
+#define RT_USING_MFD
+#define RT_MFD_SYSCON
+#define RT_MFD_BCM2835_PM
+#define RT_USING_OFW
+#define RT_FDT_EARLYCON_MSG_SIZE 128
+#define RT_USING_OFW_BUS_RANGES_NUMBER 8
+#define RT_USING_PIC
+#define MAX_HANDLERS 256
+#define RT_PIC_BCM2835_INTC
+#define RT_PIC_BCM2836_L1_INTC
#define RT_USING_PIN
+#define RT_PIN_BCM_VIRT
+#define RT_PIN_RASPBERRYPI_EXP
+#define RT_USING_PINCTRL
+#define RT_PINCTRL_BCM2835
+#define RT_USING_CLK
+#define RT_CLK_BCM2835
+#define RT_CLK_RASPBERRYPI
+
+/* SoC (System on Chip) Drivers */
+
+#define RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR
+/* end of SoC (System on Chip) Drivers */
/* end of Device Drivers */
/* C/C++ and POSIX layer */
@@ -239,6 +334,14 @@
/* POSIX (Portable Operating System Interface) layer */
+#define RT_USING_POSIX_FS
+#define RT_USING_POSIX_DEVIO
+#define RT_USING_POSIX_STDIO
+#define RT_USING_POSIX_POLL
+#define RT_USING_POSIX_TERMIOS
+#define RT_USING_POSIX_DELAY
+#define RT_USING_POSIX_CLOCK
+#define RT_USING_POSIX_TIMER
/* Interprocess Communication (IPC) */
@@ -251,6 +354,68 @@
/* Network */
+#define RT_USING_SAL
+#define SAL_INTERNET_CHECK
+#define SOCKET_TABLE_STEP_LEN 4
+
+/* Docking with protocol stacks */
+
+#define SAL_USING_LWIP
+/* end of Docking with protocol stacks */
+#define SAL_USING_POSIX
+#define RT_USING_NETDEV
+#define NETDEV_USING_IFCONFIG
+#define NETDEV_USING_PING
+#define NETDEV_USING_NETSTAT
+#define NETDEV_USING_AUTO_DEFAULT
+#define NETDEV_IPV4 1
+#define NETDEV_IPV6 0
+#define RT_USING_LWIP
+#define RT_USING_LWIP212
+#define RT_USING_LWIP_VER_NUM 0x20102
+#define RT_LWIP_MEM_ALIGNMENT 8
+#define RT_LWIP_IGMP
+#define RT_LWIP_ICMP
+#define RT_LWIP_DNS
+#define RT_LWIP_DHCP
+#define IP_SOF_BROADCAST 1
+#define IP_SOF_BROADCAST_RECV 1
+
+/* Static IPv4 Address */
+
+#define RT_LWIP_IPADDR "192.168.1.30"
+#define RT_LWIP_GWADDR "192.168.1.1"
+#define RT_LWIP_MSKADDR "255.255.255.0"
+/* end of Static IPv4 Address */
+#define RT_LWIP_UDP
+#define RT_LWIP_TCP
+#define RT_LWIP_RAW
+#define RT_MEMP_NUM_NETCONN 8
+#define RT_LWIP_PBUF_NUM 16
+#define RT_LWIP_RAW_PCB_NUM 4
+#define RT_LWIP_UDP_PCB_NUM 4
+#define RT_LWIP_TCP_PCB_NUM 4
+#define RT_LWIP_TCP_SEG_NUM 40
+#define RT_LWIP_TCP_SND_BUF 8196
+#define RT_LWIP_TCP_WND 8196
+#define RT_LWIP_TCPTHREAD_PRIORITY 10
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
+#define RT_LWIP_TCPTHREAD_STACKSIZE 16384
+#define LWIP_NO_RX_THREAD
+#define LWIP_NO_TX_THREAD
+#define RT_LWIP_ETHTHREAD_PRIORITY 12
+#define RT_LWIP_ETHTHREAD_STACKSIZE 8192
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
+#define LWIP_NETIF_STATUS_CALLBACK 1
+#define LWIP_NETIF_LINK_CALLBACK 1
+#define RT_LWIP_NETIF_NAMESIZE 6
+#define SO_REUSE 1
+#define LWIP_SO_RCVTIMEO 1
+#define LWIP_SO_SNDTIMEO 1
+#define LWIP_SO_RCVBUF 1
+#define LWIP_SO_LINGER 0
+#define LWIP_NETIF_LOOPBACK 0
+#define RT_LWIP_USING_PING
/* end of Network */
/* Memory protection */
@@ -259,6 +424,7 @@
/* Utilities */
+#define RT_USING_RESOURCE_ID
#define RT_USING_ADT
#define RT_USING_ADT_AVL
#define RT_USING_ADT_BITMAP
@@ -270,6 +436,8 @@
#define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000
#define RT_PAGE_MAX_ORDER 11
+#define RT_USING_MEMBLOCK
+#define RT_INIT_MEMORY_REGIONS 128
/* Debugging */
@@ -406,14 +574,6 @@
/* GD32 Drivers */
/* end of GD32 Drivers */
-
-/* HPMicro SDK */
-
-/* end of HPMicro SDK */
-
-/* FT32 HAL & SDK Drivers */
-
-/* end of FT32 HAL & SDK Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
@@ -493,35 +653,6 @@
/* end of Arduino libraries */
/* end of RT-Thread online packages */
-#define BCM2836_SOC
#define SOC_BCM283x
-/* Hardware Drivers Config */
-
-/* BCM Peripheral Drivers */
-
-#define BSP_USING_UART
-#define RT_USING_UART1
-#define BSP_USING_PIN
-#define BSP_USING_CORETIMER
-#define BSP_USING_SYSTIMER
-#define RT_USING_SYSTIMER1
-#define RT_USING_SYSTIMER3
-#define BSP_USING_I2C
-#define BSP_USING_I2C1
-#define BSP_USING_SPI
-#define BSP_USING_SPI0_BUS
-#define BSP_USING_SPI0_DEVICE0
-#define BSP_USING_WDT
-#define BSP_USING_SDIO
-#define BSP_USING_SDIO0
-/* end of BCM Peripheral Drivers */
-
-/* Board Peripheral Drivers */
-
-#define BSP_USING_HDMI
-#define BSP_USING_HDMI_DISPLAY
-/* end of Board Peripheral Drivers */
-/* end of Hardware Drivers Config */
-
#endif
diff --git a/bsp/raspberry-pi/raspi3-64/rtconfig.py b/bsp/raspberry-pi/raspi3-64/rtconfig.py
index cef22a954e..d49cfdbc58 100644
--- a/bsp/raspberry-pi/raspi3-64/rtconfig.py
+++ b/bsp/raspberry-pi/raspi3-64/rtconfig.py
@@ -26,6 +26,7 @@ if PLATFORM == 'gcc':
PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
+ CPP = PREFIX + 'cpp'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
@@ -34,7 +35,8 @@ if PLATFORM == 'gcc':
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
- DEVICE = ' -march=armv8-a -mtune=cortex-a53'
+ CPPFLAGS = ' -nostdinc -undef -E -P -x assembler-with-cpp'
+ DEVICE = ' -march=armv8-a -mtune=cortex-a53 -fdiagnostics-color=always -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing'
CFLAGS = DEVICE + ' -Wall -Wno-cpp'
AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
@@ -51,3 +53,10 @@ if PLATFORM == 'gcc':
DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
POST_ACTION = OBJCPY + ' -O binary $TARGET kernel8.img\n' + SIZE + ' $TARGET \n'
+
+
+def dist_handle(BSP_ROOT, dist_dir):
+ import sys
+ sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
+ from sdk_dist import dist_do_building
+ dist_do_building(BSP_ROOT, dist_dir)
diff --git a/bsp/raspberry-pi/raspi4-64/.config b/bsp/raspberry-pi/raspi4-64/.config
index ecdaf52e70..d471b43c31 100644
--- a/bsp/raspberry-pi/raspi4-64/.config
+++ b/bsp/raspberry-pi/raspi4-64/.config
@@ -12,17 +12,7 @@
#
# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set
CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y
-# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set
-CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6
-CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9
-CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
+# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set
# end of rt_vsnprintf options
#
@@ -116,7 +106,7 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
# end of rt_strnlen options
# end of klibc options
-CONFIG_RT_NAME_MAX=12
+CONFIG_RT_NAME_MAX=24
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_NANO is not set
# CONFIG_RT_USING_SMART is not set
@@ -141,7 +131,8 @@ CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192
# CONFIG_RT_USING_TIMER_ALL_SOFT is not set
-# CONFIG_RT_USING_CPU_USAGE_TRACER is not set
+CONFIG_RT_USING_CPU_USAGE_TRACER=y
+CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200
#
# kservice options
@@ -173,7 +164,7 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
#
# Memory Management
#
-# CONFIG_RT_USING_MEMPOOL is not set
+CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_SMALL_MEM is not set
CONFIG_RT_USING_SLAB=y
# CONFIG_RT_USING_MEMHEAP is not set
@@ -203,13 +194,14 @@ CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
#
# AArch64 Architecture Configuration
#
-CONFIG_ARCH_TEXT_OFFSET=0x200000
+CONFIG_ARCH_TEXT_OFFSET=0x208000
CONFIG_ARCH_RAM_OFFSET=0
CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=4096
CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-# CONFIG_ARCH_USING_GENERIC_CPUID is not set
+CONFIG_ARCH_USING_GENERIC_CPUID=y
CONFIG_ARCH_HEAP_SIZE=0x4000000
CONFIG_ARCH_INIT_PAGE_SIZE=0x200000
+# CONFIG_ARCH_USING_CPUIDLE is not set
# end of AArch64 Architecture Configuration
CONFIG_ARCH_CPU_64BIT=y
@@ -220,6 +212,7 @@ CONFIG_ARCH_ARM=y
CONFIG_ARCH_ARM_MMU=y
CONFIG_ARCH_ARMV8=y
CONFIG_ARCH_USING_ASID=y
+CONFIG_ARCH_USING_HW_THREAD_SELF=y
CONFIG_ARCH_USING_IRQ_CTX_LIST=y
#
@@ -227,7 +220,7 @@ CONFIG_ARCH_USING_IRQ_CTX_LIST=y
#
CONFIG_RT_USING_COMPONENTS_INIT=y
CONFIG_RT_USING_USER_MAIN=y
-CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=16384
CONFIG_RT_MAIN_THREAD_PRIORITY=10
# CONFIG_RT_USING_LEGACY is not set
CONFIG_RT_USING_MSH=y
@@ -296,7 +289,7 @@ CONFIG_RT_USING_DFS_TMPFS=y
#
# Device Drivers
#
-# CONFIG_RT_USING_DM is not set
+CONFIG_RT_USING_DM=y
CONFIG_RT_USING_DEV_BUS=y
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_UNAMED_PIPE_NUMBER=64
@@ -308,38 +301,77 @@ CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
CONFIG_RT_SERIAL_USING_DMA=y
CONFIG_RT_SERIAL_RB_BUFSZ=64
-# CONFIG_RT_USING_SERIAL_BYPASS is not set
+CONFIG_RT_USING_SERIAL_BYPASS=y
+# CONFIG_RT_SERIAL_EARLY_HVC is not set
+CONFIG_RT_SERIAL_PL011=y
+CONFIG_RT_SERIAL_8250=y
+# CONFIG_RT_SERIAL_8250_DW is not set
+# CONFIG_RT_SERIAL_8250_PCI is not set
+CONFIG_RT_SERIAL_8250_BCM2835AUX=y
+# CONFIG_RT_SERIAL_8250_BCM7271 is not set
# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_ADC is not set
CONFIG_RT_USING_CLOCK_TIME=y
+# CONFIG_RT_USING_CLOCK_TIMER_TRIGGER is not set
+CONFIG_RT_CLOCK_TIME_ARM_ARCH=y
+CONFIG_RT_CLOCK_TIME_BCM2835=y
+CONFIG_RT_USING_ETHERNET=y
+# CONFIG_RT_ETHERNET_CADENCE is not set
+# CONFIG_RT_ETHERNET_DWMAC is not set
+CONFIG_RT_ETHERNET_BCMGENET=y
CONFIG_RT_USING_I2C=y
# CONFIG_RT_I2C_DEBUG is not set
-CONFIG_RT_USING_I2C_BITOPS=y
-# CONFIG_RT_I2C_BITOPS_DEBUG is not set
+# CONFIG_RT_USING_I2C_BITOPS is not set
# CONFIG_RT_USING_SOFT_I2C is not set
+CONFIG_RT_I2C_BCM2835=y
+CONFIG_RT_I2C_BRCMSTB=y
# CONFIG_RT_USING_PHY is not set
-# CONFIG_RT_USING_PHY_V2 is not set
-# CONFIG_RT_USING_ADC is not set
+CONFIG_RT_USING_PHY_V2=y
+# CONFIG_RT_PHY_V2_REALTEK is not set
+CONFIG_RT_PHY_MDIO_BCM_UNIMAC=y
+CONFIG_RT_PHY_BCM54213=y
# CONFIG_RT_USING_DAC is not set
CONFIG_RT_USING_NULL=y
CONFIG_RT_USING_ZERO=y
CONFIG_RT_USING_RANDOM=y
-# CONFIG_RT_USING_PWM is not set
+CONFIG_RT_USING_PWM=y
+CONFIG_RT_PWM_BCM2835=y
+CONFIG_RT_PWM_BRCMSTB=y
+# CONFIG_RT_PWM_RP1 is not set
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
CONFIG_RT_USING_RTC=y
-# CONFIG_RT_USING_ALARM is not set
-CONFIG_RT_USING_SOFT_RTC=y
+CONFIG_RT_USING_ALARM=y
+CONFIG_RT_ALARM_STACK_SIZE=8192
+CONFIG_RT_ALARM_TIMESLICE=5
+CONFIG_RT_ALARM_PRIORITY=10
+# CONFIG_RT_ALARM_USING_LOCAL_TIME is not set
+# CONFIG_RT_USING_SOFT_RTC is not set
+# CONFIG_RT_RTC_DS1302 is not set
+CONFIG_RT_RTC_DS1307=y
+# CONFIG_RT_RTC_GOLDFISH is not set
+# CONFIG_RT_RTC_HYM8563 is not set
+# CONFIG_RT_RTC_PCF8523 is not set
+# CONFIG_RT_RTC_PCF8563 is not set
+# CONFIG_RT_RTC_PL031 is not set
+# CONFIG_RT_RTC_RX8010 is not set
+# CONFIG_RT_RTC_RPI is not set
CONFIG_RT_USING_SDIO=y
CONFIG_RT_SDIO_STACK_SIZE=8192
CONFIG_RT_SDIO_THREAD_PRIORITY=15
-CONFIG_RT_MMCSD_STACK_SIZE=8192
+CONFIG_RT_MMCSD_STACK_SIZE=16384
CONFIG_RT_MMCSD_THREAD_PRIORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
# CONFIG_RT_SDIO_DEBUG is not set
-# CONFIG_RT_USING_SDHCI is not set
+CONFIG_RT_USING_SDHCI=y
+# CONFIG_RT_SDIO_SDHCI_PCI is not set
+# CONFIG_RT_SDIO_DW_MMC is not set
+# CONFIG_RT_SDIO_SDHCI_DWCMSHC is not set
+CONFIG_RT_SDIO_SDHCI_BRCMSTB=y
+CONFIG_RT_SDIO_SDHCI_IPROC=y
CONFIG_RT_USING_SPI=y
CONFIG_RT_USING_SPI_ISR=y
# CONFIG_RT_USING_SPI_BITOPS is not set
@@ -349,14 +381,81 @@ CONFIG_RT_USING_SPI_ISR=y
# CONFIG_RT_USING_SFUD is not set
# CONFIG_RT_USING_ENC28J60 is not set
# CONFIG_RT_USING_SPI_WIFI is not set
+CONFIG_RT_SPI_BCM2835=y
+CONFIG_RT_SPI_BCM2835AUX=y
CONFIG_RT_USING_WDT=y
-# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_WDT_DW is not set
+# CONFIG_RT_WDT_I6300ESB is not set
+CONFIG_RT_WDT_BCM2835=y
+CONFIG_RT_USING_AUDIO=y
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2
+CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048
+# CONFIG_RT_AUDIO_INTEL_HDA is not set
+CONFIG_RT_AUDIO_BCM2835_I2S=y
# CONFIG_RT_USING_SENSOR is not set
CONFIG_RT_USING_TOUCH=y
# CONFIG_RT_TOUCH_PIN_IRQ is not set
CONFIG_RT_USING_LCD=y
-# CONFIG_RT_USING_HWCRYPTO is not set
+CONFIG_RT_USING_GRAPHIC=y
+CONFIG_RT_GRAPHIC_BACKLIGHT=y
+# CONFIG_RT_GRAPHIC_BACKLIGHT_GPIO is not set
+# CONFIG_RT_GRAPHIC_BACKLIGHT_PWM is not set
+CONFIG_RT_GRAPHIC_BACKLIGHT_RPI=y
+CONFIG_RT_GRAPHIC_FB=y
+CONFIG_RT_GRAPHIC_FB_ILI9486=y
+CONFIG_RT_GRAPHIC_FB_SIMPLE=y
+CONFIG_RT_GRAPHIC_FB_BCM2708=y
+CONFIG_RT_GRAPHIC_FB_RPISENSE=y
+CONFIG_RT_GRAPHIC_LOGO=y
+# CONFIG_RT_GRAPHIC_LOGO_NONE is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_CLUT224 is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_WHITE_CLUT224 is not set
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224=y
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH="../dm/graphic/logo/logo-raspi-clut224.ppm"
+CONFIG_RT_USING_HWCRYPTO=y
+CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto"
+CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16
+CONFIG_RT_HWCRYPTO_KEYBIT_MAX_SIZE=256
+# CONFIG_RT_HWCRYPTO_USING_GCM is not set
+# CONFIG_RT_HWCRYPTO_USING_AES is not set
+# CONFIG_RT_HWCRYPTO_USING_DES is not set
+# CONFIG_RT_HWCRYPTO_USING_3DES is not set
+# CONFIG_RT_HWCRYPTO_USING_RC4 is not set
+# CONFIG_RT_HWCRYPTO_USING_MD5 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA1 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA2 is not set
+CONFIG_RT_HWCRYPTO_USING_RNG=y
+# CONFIG_RT_HWCRYPTO_USING_CRC is not set
+# CONFIG_RT_HWCRYPTO_USING_BIGNUM is not set
+CONFIG_RT_HWCRYPTO_RNG_BCM2835=y
+CONFIG_RT_HWCRYPTO_RNG_IPROC_RNG200=y
# CONFIG_RT_USING_WIFI is not set
+# CONFIG_RT_USING_PTP is not set
+CONFIG_RT_USING_LED=y
+CONFIG_RT_LED_GPIO=y
+# CONFIG_RT_LED_PWM is not set
+# CONFIG_RT_LED_SYSCON is not set
+CONFIG_RT_USING_INPUT=y
+CONFIG_RT_INPUT_POWER=y
+# CONFIG_RT_INPUT_UAPI is not set
+CONFIG_RT_INPUT_JOYSTICK=y
+CONFIG_RT_INPUT_JOYSTICK_RPISENSE=y
+# CONFIG_RT_INPUT_KEYBOARD is not set
+# CONFIG_RT_INPUT_MISC is not set
+CONFIG_RT_INPUT_TOUCHSCREEN=y
+CONFIG_RT_INPUT_TOUCHSCREEN_ADS7846=y
+# CONFIG_RT_INPUT_TOUCHSCREEN_GOODIX is not set
+CONFIG_RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW=y
+CONFIG_RT_USING_MBOX=y
+# CONFIG_RT_MBOX_PIC is not set
+CONFIG_RT_MBOX_BCM2835=y
+# CONFIG_RT_USING_HWSPINLOCK is not set
+# CONFIG_RT_USING_RPMSG is not set
+CONFIG_RT_USING_PHYE=y
+CONFIG_RT_PHYE_GENERIC_USB=y
+# CONFIG_RT_USING_ATA is not set
+# CONFIG_RT_USING_NVME is not set
CONFIG_RT_USING_BLK=y
#
@@ -366,11 +465,132 @@ CONFIG_RT_BLK_PARTITION_DFS=y
CONFIG_RT_BLK_PARTITION_EFI=y
# end of Partition Types
-# CONFIG_RT_USING_REGULATOR is not set
+CONFIG_RT_USING_SCSI=y
+CONFIG_RT_SCSI_SD=y
+# CONFIG_RT_SCSI_CDROM is not set
+# CONFIG_RT_USING_UFS is not set
+CONFIG_RT_USING_FIRMWARE=y
+# CONFIG_RT_FIRMWARE_QEMU_FW_CFG is not set
+# CONFIG_RT_FIRMWARE_ARM_SCMI is not set
+CONFIG_RT_FIRMWARE_RASPBERRYPI=y
+# CONFIG_RT_USING_TEE is not set
+# CONFIG_RT_USING_HWCACHE is not set
+CONFIG_RT_USING_DVFS=y
+CONFIG_RT_USING_DVFS_EVENT=y
+CONFIG_RT_USING_DVFS_OPP_RETRY_MAX=10
+
+#
+# DVFS Event Drivers
+#
+
+#
+# DVFS CPUfreq Drivers
+#
+CONFIG_RT_DVFS_RASPBERRY_CPUFREQ=y
+
+#
+# DVFS Devfreq Drivers
+#
+CONFIG_RT_USING_REGULATOR=y
+# CONFIG_RT_REGULATOR_FAN53555 is not set
+CONFIG_RT_REGULATOR_FIXED=y
+CONFIG_RT_REGULATOR_GPIO=y
+# CONFIG_RT_REGULATOR_PWM is not set
+CONFIG_RT_USING_RESET=y
+CONFIG_RT_RESET_SIMPLE=y
+CONFIG_RT_RESET_BRCMSTB_RESCAL=y
+CONFIG_RT_RESET_BRCMSTB=y
+CONFIG_RT_RESET_RASPBERRYPI=y
+
+#
+# Power Management (PM) Domains device drivers
+#
+# CONFIG_RT_PMDOMAIN_BCM2835 is not set
+CONFIG_RT_PMDOMAIN_RASPBERRYPI=y
+# end of Power Management (PM) Domains device drivers
+
+# CONFIG_RT_USING_POWER_RESET is not set
# CONFIG_RT_USING_POWER_SUPPLY is not set
+CONFIG_RT_USING_THERMAL=y
+
+#
+# Thermal Sensors Drivers
+#
+CONFIG_RT_THERMAL_BCM2835=y
+CONFIG_RT_THERMAL_BCM2711=y
+
+#
+# Thermal Cool Drivers
+#
+# CONFIG_RT_THERMAL_COOL_DVFS is not set
+# CONFIG_RT_THERMAL_COOL_GPIO_FAN is not set
+# CONFIG_RT_THERMAL_COOL_PWM_FAN is not set
# CONFIG_RT_USING_VIRTIO is not set
+CONFIG_RT_USING_NVMEM=y
+CONFIG_RT_NVMEM_RASPBERRYPI_OTP=y
+CONFIG_RT_USING_DMA=y
+# CONFIG_RT_DMA_PL330 is not set
+# CONFIG_RT_DMA_DW_AXI_DMAC is not set
+CONFIG_RT_DMA_BCM2835=y
+CONFIG_RT_USING_MFD=y
+# CONFIG_RT_MFD_EDU is not set
+CONFIG_RT_MFD_SYSCON=y
+CONFIG_RT_MFD_BCM2835_PM=y
+# CONFIG_RT_MFD_RP1 is not set
+CONFIG_RT_MFD_RPI_SENSE=y
+# CONFIG_RT_USING_IVSHMEM is not set
+CONFIG_RT_USING_OFW=y
+# CONFIG_RT_USING_BUILTIN_FDT is not set
+CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128
+CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8
+CONFIG_RT_USING_PCI=y
+CONFIG_RT_PCI_MSI=y
+# CONFIG_RT_PCI_ENDPOINT is not set
+CONFIG_RT_PCI_SYS_64BIT=y
+CONFIG_RT_PCI_CACHE_LINE_SIZE=8
+# CONFIG_RT_PCI_LOCKLESS is not set
+
+#
+# PCI Device Drivers
+#
+CONFIG_RT_PCI_ECAM=y
+CONFIG_RT_PCI_HOST_COMMON=y
+CONFIG_RT_PCI_HOST_GENERIC=y
+# CONFIG_RT_PCI_DW is not set
+CONFIG_RT_PCIE_BRCMSTB=y
+CONFIG_RT_USING_PIC=y
+# CONFIG_RT_USING_PIC_STATISTICS is not set
+CONFIG_MAX_HANDLERS=512
+CONFIG_RT_PIC_ARM_GIC=y
+# CONFIG_RT_PIC_ARM_GIC_V2M is not set
+# CONFIG_RT_PIC_ARM_GIC_V3 is not set
+CONFIG_RT_PIC_ARM_GIC_MAX_NR=1
+# CONFIG_RT_PIC_BCM2712_MIP is not set
+CONFIG_RT_PIC_BCM2835_INTC=y
+CONFIG_RT_PIC_BCM2836_L1_INTC=y
+CONFIG_RT_PIC_BRCMSTB_L2_IRQ=y
CONFIG_RT_USING_PIN=y
+# CONFIG_RT_PIN_PL061 is not set
+CONFIG_RT_PIN_BCM_VIRT=y
+CONFIG_RT_PIN_BRCMSTB=y
+CONFIG_RT_PIN_RASPBERRYPI_EXP=y
+CONFIG_RT_USING_PINCTRL=y
+# CONFIG_RT_PINCTRL_SINGLE is not set
+# CONFIG_RT_PINCTRL_BCM2712 is not set
+CONFIG_RT_PINCTRL_BCM2835=y
+# CONFIG_RT_PINCTRL_RP1 is not set
+CONFIG_RT_USING_CLK=y
+CONFIG_RT_CLK_BCM2711_DVP=y
+CONFIG_RT_CLK_BCM2835=y
+CONFIG_RT_CLK_RASPBERRYPI=y
+# CONFIG_RT_CLK_RP1 is not set
# CONFIG_RT_USING_CHERRYUSB is not set
+
+#
+# SoC (System on Chip) Drivers
+#
+CONFIG_RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR=y
+# end of SoC (System on Chip) Drivers
# end of Device Drivers
#
@@ -551,7 +771,8 @@ CONFIG_RT_USING_ADT_REF=y
# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set
CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000
CONFIG_RT_PAGE_MAX_ORDER=11
-# CONFIG_RT_USING_MEMBLOCK is not set
+CONFIG_RT_USING_MEMBLOCK=y
+CONFIG_RT_INIT_MEMORY_REGIONS=128
#
# Debugging
@@ -570,6 +791,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# end of Using USB legacy version
# CONFIG_RT_USING_FDT is not set
+# CONFIG_RT_USING_LEGACY_VIRTIO is not set
# CONFIG_RT_USING_RUST is not set
# end of RT-Thread Components
@@ -772,7 +994,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_U8G2 is not set
# end of u8g2: a monochrome graphic library
-# CONFIG_PKG_USING_NES_SIMULATOR is not set
# CONFIG_PKG_USING_OPENMV is not set
# CONFIG_PKG_USING_MUPDF is not set
# CONFIG_PKG_USING_STEMWIN is not set
@@ -797,9 +1018,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# tools packages
#
-# CONFIG_PKG_USING_VECTOR is not set
-# CONFIG_PKG_USING_SORCH is not set
-# CONFIG_PKG_USING_DICT is not set
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_MCOREDUMP is not set
# CONFIG_PKG_USING_EASYFLASH is not set
@@ -848,9 +1066,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_RVBACKTRACE is not set
# CONFIG_PKG_USING_HPATCHLITE is not set
# CONFIG_PKG_USING_THREAD_METRIC is not set
-# CONFIG_PKG_USING_UORB is not set
-# CONFIG_PKG_USING_RT_TUNNEL is not set
-# CONFIG_PKG_USING_VIRTUAL_TERMINAL is not set
# end of tools packages
#
@@ -945,9 +1160,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_R_RHEALSTONE is not set
# CONFIG_PKG_USING_HEARTBEAT is not set
# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set
-# CONFIG_PKG_USING_CHERRYECAT is not set
-# CONFIG_PKG_USING_EVENT_LOOP is not set
-# CONFIG_PKG_USING_THREAD_MANAGER is not set
# end of system packages
#
@@ -1093,7 +1305,9 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# NUVOTON Drivers
#
+# CONFIG_PKG_USING_NUVOTON_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_NUVOTON_SERIES_DRIVER is not set
+# CONFIG_PKG_USING_NUVOTON_ARM926_LIB is not set
# end of NUVOTON Drivers
#
@@ -1101,24 +1315,7 @@ CONFIG_RT_PAGE_MAX_ORDER=11
#
# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32_RISCV_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32VW55X_WIFI is not set
# end of GD32 Drivers
-
-#
-# HPMicro SDK
-#
-# CONFIG_PKG_USING_HPM_SDK is not set
-# end of HPMicro SDK
-
-#
-# FT32 HAL & SDK Drivers
-#
-# CONFIG_PKG_USING_FT32F0_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F0_CMSIS_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_CMSIS_DRIVER is not set
-# end of FT32 HAL & SDK Drivers
# end of HAL & SDK Drivers
#
@@ -1164,11 +1361,9 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_RT3020 is not set
# CONFIG_PKG_USING_MLX90632 is not set
# CONFIG_PKG_USING_MLX90382 is not set
-# CONFIG_PKG_USING_MLX90384 is not set
# CONFIG_PKG_USING_MLX90393 is not set
# CONFIG_PKG_USING_MLX90392 is not set
# CONFIG_PKG_USING_MLX90394 is not set
-# CONFIG_PKG_USING_MLX90396 is not set
# CONFIG_PKG_USING_MLX90397 is not set
# CONFIG_PKG_USING_MS5611 is not set
# CONFIG_PKG_USING_MAX31865 is not set
@@ -1197,7 +1392,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_P3T1755 is not set
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
-# CONFIG_PKG_USING_SCD4X is not set
# end of sensors drivers
#
@@ -1215,7 +1409,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_CST812T is not set
# end of touch drivers
-# CONFIG_PKG_USING_LCD_SPI_DRIVER is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_BUTTON is not set
# CONFIG_PKG_USING_PCF8574 is not set
@@ -1295,13 +1488,6 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# CONFIG_PKG_USING_IC74HC165 is not set
# CONFIG_PKG_USING_IST8310 is not set
# CONFIG_PKG_USING_ST7789_SPI is not set
-# CONFIG_PKG_USING_CAN_UDS is not set
-# CONFIG_PKG_USING_ISOTP_C is not set
-# CONFIG_PKG_USING_IKUNLED is not set
-# CONFIG_PKG_USING_INS5T8025 is not set
-# CONFIG_PKG_USING_IRUART is not set
-# CONFIG_PKG_USING_ST7305 is not set
-# CONFIG_PKG_USING_TM1668 is not set
# CONFIG_PKG_USING_SPI_TOOLS is not set
# end of peripheral libraries and drivers
@@ -1641,41 +1827,4 @@ CONFIG_RT_PAGE_MAX_ORDER=11
# end of Arduino libraries
# end of RT-Thread online packages
-CONFIG_BCM2711_SOC=y
-CONFIG_BSP_SUPPORT_FPU=y
-# CONFIG_BSP_USING_VM_MODE is not set
-
-#
-# Hardware Drivers Config
-#
-
-#
-# BCM Peripheral Drivers
-#
-CONFIG_BSP_USING_UART=y
-CONFIG_RT_USING_UART0=y
-# CONFIG_RT_USING_UART1 is not set
-CONFIG_RT_USING_UART3=y
-CONFIG_RT_USING_UART4=y
-# CONFIG_RT_USING_UART5 is not set
-CONFIG_BSP_USING_GIC=y
-CONFIG_BSP_USING_GICV2=y
-# CONFIG_BSP_USING_GICV3 is not set
-CONFIG_BSP_USING_PIN=y
-# CONFIG_BSP_USING_SPI is not set
-CONFIG_BSP_USING_CORETIMER=y
-# CONFIG_BSP_USING_SYSTIMER is not set
-CONFIG_BSP_USING_WDT=y
-# CONFIG_BSP_USING_RTC is not set
-CONFIG_BSP_USING_SDIO=y
-CONFIG_BSP_USING_SDIO0=y
-# end of BCM Peripheral Drivers
-
-#
-# Board Peripheral Drivers
-#
-CONFIG_BSP_USING_HDMI=y
-# CONFIG_BSP_USING_HDMI_DISPLAY is not set
-# CONFIG_BSP_USING_TOUCH is not set
-# end of Board Peripheral Drivers
-# end of Hardware Drivers Config
+CONFIG_SOC_BCM2711=y
diff --git a/bsp/raspberry-pi/raspi4-64/Kconfig b/bsp/raspberry-pi/raspi4-64/Kconfig
index f62b1758e9..9a2d2d7992 100644
--- a/bsp/raspberry-pi/raspi4-64/Kconfig
+++ b/bsp/raspberry-pi/raspi4-64/Kconfig
@@ -6,17 +6,18 @@ RTT_DIR := ../../..
PKGS_DIR := packages
+SOC_DM_DIR := $BSP_DIR/../dm/
+
+source "$(SOC_DM_DIR)/Kconfig"
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
-config BCM2711_SOC
+config SOC_BCM2711
bool
select ARCH_ARMV8
- select ARCH_ARM_MMU
- select RT_USING_CACHE
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select ARCH_CPU_64BIT
+ select RT_USING_CACHE
+ select RT_USING_STDC_ATOMIC
default y
-
-rsource "drivers/Kconfig"
diff --git a/bsp/raspberry-pi/raspi4-64/README.md b/bsp/raspberry-pi/raspi4-64/README.md
index 66e6b8e996..a531d674cc 100644
--- a/bsp/raspberry-pi/raspi4-64/README.md
+++ b/bsp/raspberry-pi/raspi4-64/README.md
@@ -47,7 +47,7 @@ windows系统电脑上可以安装tftpd搭建tftp服务器。将目录指定到`
在控制台输入下列命令:
```
-setenv bootcmd "dhcp 0x00208000 x.x.x.x:rtthread.bin;dcache flush;go 0x00208000"
+setenv bootcmd "dhcp 0x208000 x.x.x.x:rtthread.bin;fdt addr ${fdt_addr};fdt set /chosen bootargs 'earlycon=uart8250,mmio32,0xfe215040 console=ttyAMA0 cma=8M coherent_pool=2M';booti 0x208000 - ${fdt_addr}"
saveenv
reset
```
diff --git a/bsp/raspberry-pi/raspi4-64/SConscript b/bsp/raspberry-pi/raspi4-64/SConscript
index c7ef7659ec..40e1864cf6 100644
--- a/bsp/raspberry-pi/raspi4-64/SConscript
+++ b/bsp/raspberry-pi/raspi4-64/SConscript
@@ -11,4 +11,6 @@ for d in list:
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
+objs = objs + SConscript(cwd + '/../dm/SConscript', variant_dir = 'dm', duplicate = 0)
+
Return('objs')
diff --git a/bsp/raspberry-pi/raspi4-64/SConstruct b/bsp/raspberry-pi/raspi4-64/SConstruct
index 55cab35463..ec6fe0187f 100644
--- a/bsp/raspberry-pi/raspi4-64/SConstruct
+++ b/bsp/raspberry-pi/raspi4-64/SConstruct
@@ -11,20 +11,19 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
- AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
- CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
- CPP = rtconfig.CPP, CXXFLAGS = rtconfig.CXXFLAGS,
- AR = rtconfig.AR, ARFLAGS = '-rc',
+ AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+ CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+ CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
+ AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
-env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
-objs = PrepareBuilding(env, RTT_ROOT)
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
# make a building
DoBuilding(TARGET, objs)
diff --git a/bsp/raspberry-pi/raspi4-64/applications/SConscript b/bsp/raspberry-pi/raspi4-64/applications/SConscript
index bda7b8b585..bda7b8b585 100644..100755
--- a/bsp/raspberry-pi/raspi4-64/applications/SConscript
+++ b/bsp/raspberry-pi/raspi4-64/applications/SConscript
diff --git a/bsp/raspberry-pi/raspi4-64/applications/main.c b/bsp/raspberry-pi/raspi4-64/applications/main.c
index 9400e2a598..c492727ca7 100644..100755
--- a/bsp/raspberry-pi/raspi4-64/applications/main.c
+++ b/bsp/raspberry-pi/raspi4-64/applications/main.c
@@ -9,8 +9,6 @@
*/
#include <rtthread.h>
-#include <rtdevice.h>
-#include <board.h>
int main(int argc, char** argv)
{
diff --git a/bsp/raspberry-pi/raspi4-64/applications/mnt.c b/bsp/raspberry-pi/raspi4-64/applications/mnt.c
deleted file mode 100644
index d204e788b5..0000000000
--- a/bsp/raspberry-pi/raspi4-64/applications/mnt.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2017-5-30 bernard the first version
- */
-
-#include <rtthread.h>
-
-#ifdef BSP_USING_SDIO
-#include <dfs_fs.h>
-
-int mnt_init(void)
-{
- rt_thread_delay(RT_TICK_PER_SECOND/100);
- if (dfs_mount("sd1", "/", "ext", 0, 0) == 0)
- {
- rt_kprintf("file system initialization done!\n");
- }
- else if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
- {
- rt_kprintf("file system initialization done!\n");
- }
-
-#ifdef RT_USING_DFS_ROMFS
- mkdir("/rom", 0777);
- extern const struct romfs_dirent romfs_root;
- if (dfs_mount(RT_NULL, "/rom", "rom", 0, &romfs_root) == 0)
- {
- rt_kprintf("ROM File System initialized!\n");
- }
-#endif
-
- return 0;
-}
-INIT_ENV_EXPORT(mnt_init);
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/Kconfig b/bsp/raspberry-pi/raspi4-64/drivers/Kconfig
deleted file mode 100644
index 3ea981e1f1..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/Kconfig
+++ /dev/null
@@ -1,139 +0,0 @@
-
-config BSP_SUPPORT_FPU
- bool "Using Float"
- default n
-
-menuconfig BSP_USING_VM_MODE
- bool "Enable VM mode"
- default n
-
-menu "Hardware Drivers Config"
- menu "BCM Peripheral Drivers"
- menuconfig BSP_USING_UART
- bool "Using UART"
- select RT_USING_SERIAL
- default y
-
- if BSP_USING_UART
- config RT_USING_UART0
- bool "Enable UART 0"
- default y
-
- config RT_USING_UART1
- bool "Enable UART 1"
- default n
-
- config RT_USING_UART3
- bool "Enable UART 3"
- default n
-
- config RT_USING_UART4
- bool "Enable UART 4"
- default n
-
- config RT_USING_UART5
- bool "Enable UART 5"
- default n
- endif
-
- menuconfig BSP_USING_GIC
- bool "Enable GIC"
- select RT_USING_GIC
- default y
- if BSP_USING_GIC
- config BSP_USING_GICV2
- bool "Enable GIC400(GICV2)"
- default y
- config BSP_USING_GICV3
- bool "Enable GIC500(GICV3)"
- default n
- endif
-
- config BSP_USING_PIN
- bool "Using PIN"
- select RT_USING_PIN
- default y
-
- menuconfig BSP_USING_SPI
- bool "Enable SPI"
- select RT_USING_SPI
- default n
-
- if BSP_USING_SPI
- config BSP_USING_SPI0_BUS
- bool "Enable SPI0 BUS"
- default n
- config BSP_USING_SPI0_DEVICE0
- bool "Enable SPI0 DEVICE0"
- select BSP_USING_SPI0_BUS
- default n
- config BSP_USING_SPI0_DEVICE1
- bool "Enable SPI0 DEVICE1"
- select BSP_USING_SPI0_BUS
- default n
- endif
-
- config BSP_USING_CORETIMER
- bool "Using core timer"
- select RT_USING_CORETIMER
- default y
-
- menuconfig BSP_USING_SYSTIMER
- bool "Enable SYSTIMER"
- default n
-
- if BSP_USING_SYSTIMER
- config RT_USING_SYSTIMER1
- bool "Enable sys timer1"
- default n
- config RT_USING_SYSTIMER3
- bool "Enable sys timer3"
- default n
- endif
-
- config BSP_USING_WDT
- bool "Enable WDT"
- select RT_USING_WDT
- default n
-
- menuconfig BSP_USING_RTC
- bool "Enable RTC"
- select RT_USING_RTC
- default n
-
- if BSP_USING_RTC
- config BSP_USING_ALARM
- bool "Enable Alarm"
- select RT_USING_ALARM
- default n
- endif
-
- menuconfig BSP_USING_SDIO
- bool "Enable SDIO"
- select RT_USING_SDIO
- default n
-
- if BSP_USING_SDIO
- config BSP_USING_SDIO0
- bool "Enable SDIO0"
- select RT_USING_SDIO
- default n
- endif
- endmenu
-
- menu "Board Peripheral Drivers"
- menuconfig BSP_USING_HDMI
- bool "Enable HDMI"
- default n
-
- if BSP_USING_HDMI
- config BSP_USING_HDMI_DISPLAY
- bool "HDMI DISPLAY"
- default n
- endif
-
- menuconfig BSP_USING_TOUCH
- bool "Enable Touch"
- default n
- endmenu
-endmenu
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/SConscript b/bsp/raspberry-pi/raspi4-64/drivers/SConscript
index 98c38943e9..f7e8f47ce8 100644
--- a/bsp/raspberry-pi/raspi4-64/drivers/SConscript
+++ b/bsp/raspberry-pi/raspi4-64/drivers/SConscript
@@ -1,19 +1,12 @@
+# RT-Thread building script for component
+
from building import *
cwd = GetCurrentDir()
-src = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
-CPPPATH = [cwd, str(Dir('#'))]
-
-group = DefineGroup('driver', src, depend = [''], CPPPATH = CPPPATH)
-
-# build for sub-directory
-list = os.listdir(cwd)
-objs = []
+src = Glob('*.c')
+CPPPATH = [cwd]
+objs = []
-for d in list:
- path = os.path.join(cwd, d)
- if os.path.isfile(os.path.join(path, 'SConscript')):
- objs = objs + SConscript(os.path.join(d, 'SConscript'))
-group = group + objs
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/board.c b/bsp/raspberry-pi/raspi4-64/drivers/board.c
index e66a4bc09e..f79e5e7bbb 100644
--- a/bsp/raspberry-pi/raspi4-64/drivers/board.c
+++ b/bsp/raspberry-pi/raspi4-64/drivers/board.c
@@ -10,204 +10,67 @@
* 2023-03-28 WangXiaoyao sync works & memory layout fixups
* code formats
*/
-#define DBG_TAG "board"
-#define DBG_LVL DBG_INFO
-#include <rtdbg.h>
-#include <rthw.h>
-#include <rtthread.h>
+#include <setup.h>
+#include <board.h>
+#include <rtdevice.h>
+#include <mmu.h>
#include <mm_aspace.h>
-#include "board.h"
-#include "drv_uart.h"
+// extern char __noncacheable_start[];
+// extern char __noncacheable_end[];
-#include "cp15.h"
-#include "mmu.h"
-#include "mbox.h"
-#include <mm_page.h>
+// static void rt_hw_noncacheable_map(void)
+// {
+// rt_ubase_t start = (rt_ubase_t)__noncacheable_start;
+// rt_ubase_t end = (rt_ubase_t)__noncacheable_end;
+// rt_size_t size;
-#ifdef RT_USING_SMART
-#include <lwp_arch.h>
-#endif
+// if (end <= start)
+// {
+// return;
+// }
-extern size_t MMUTable[];
+// RT_ASSERT((start & (ARCH_SECTION_SIZE - 1)) == 0);
+// RT_ASSERT((end & (ARCH_SECTION_SIZE - 1)) == 0);
+// size = end - start;
-size_t gpio_base_addr = GPIO_BASE_ADDR;
+// rt_hw_mmu_control(&rt_kernel_space, (void *)start, size, MMU_CNTL_NONCACHE);
+// rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)start, size);
+// rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, (void *)start, size);
+// }
-size_t uart_base_addr = UART_BASE;
-
-size_t gic_base_addr = GIC_V2_BASE;
-
-size_t arm_timer_base = ARM_TIMER_BASE;
-
-size_t pactl_cs_base = PACTL_CS_ADDR;
-
-size_t stimer_base_addr = STIMER_BASE;
-
-size_t mmc2_base_addr = MMC2_BASE_ADDR;
-
-size_t videocore_mbox = VIDEOCORE_MBOX;
-
-size_t mbox_addr = MBOX_ADDR;
-
-size_t wdt_base_addr = WDT_BASE;
-
-uint8_t *mac_reg_base_addr = (uint8_t *)MAC_REG;
-
-uint8_t *eth_send_no_cache = (uint8_t *)SEND_DATA_NO_CACHE;
-uint8_t *eth_recv_no_cache = (uint8_t *)RECV_DATA_NO_CACHE;
-
-#ifdef RT_USING_SMART
-struct mem_desc platform_mem_desc[] = {
- {KERNEL_VADDR_START, KERNEL_VADDR_START + 0x0fffffff, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM}
-};
-#else
-struct mem_desc platform_mem_desc[] = {
- {0x00200000, (256ul << 20) - 1, 0x00200000, NORMAL_MEM},
- {0xFC000000, 0x000100000000 - 1, 0xFC000000, DEVICE_MEM},
-};
-#endif
-
-const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
-
-void idle_wfi(void)
-{
- asm volatile ("wfi");
-}
-
-/**
- * This function will initialize board
- */
-
-extern size_t MMUTable[];
-int rt_hw_gtimer_init(void);
-
-rt_region_t init_page_region = {
- PAGE_START,
- PAGE_END,
-};
-
-/**
- * Initialize the Hardware related stuffs. Called from rtthread_startup()
- * after interrupt disabled.
- */
void rt_hw_board_init(void)
{
- rt_hw_earlycon_ioremap_early();
-
- /* io device remap */
-#ifdef RT_USING_SMART
- rt_hw_mmu_map_init(&rt_kernel_space, (void*)0xfffffffff0000000, 0x10000000, MMUTable, PV_OFFSET);
-#else
- rt_hw_mmu_map_init(&rt_kernel_space, (void*)0x080000000000, 0x10000000, MMUTable, 0);
-#endif /* RT_USING_SMART */
- rt_page_init(init_page_region);
- rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, platform_mem_desc_size);
-
- /* map peripheral address to virtual address */
-#ifdef RT_USING_HEAP
- /* initialize system heap */
- rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
-#endif
-
- /* initialize hardware interrupt */
- rt_hw_interrupt_init();
-
- //gpio
- gpio_base_addr = (size_t)rt_ioremap((void*)GPIO_BASE_ADDR, 0x1000);
-
- //pactl
- pactl_cs_base = (size_t)rt_ioremap((void*)PACTL_CS_ADDR, 0x1000);
-
- //stimer
- stimer_base_addr = (size_t)rt_ioremap((void*)STIMER_BASE, 0x1000);
-
- //mmc2_base_addr
- mmc2_base_addr = (size_t)rt_ioremap((void*)MMC2_BASE_ADDR, 0x1000);
-
- //mbox
- videocore_mbox = (size_t)rt_ioremap((void*)VIDEOCORE_MBOX, 0x1000);
-
- // mbox msg
- mbox = (volatile unsigned int *)rt_pages_alloc(0);
-
- //wdt
- wdt_base_addr = (size_t)rt_ioremap((void*)WDT_BASE, 0x1000);
-
- //mac
- mac_reg_base_addr = (void *)rt_ioremap((void*)MAC_REG, 0x80000);
-
- // eth data
- eth_send_no_cache = (void *)rt_pages_alloc(rt_page_bits(0x200000));
- eth_recv_no_cache = (void *)rt_pages_alloc(rt_page_bits(0x200000));
-
- /* initialize uart */
- rt_hw_uart_init();
-
- /* initialize timer for os tick */
- rt_hw_gtimer_init();
-
-#ifdef RT_USING_CONSOLE
- /* set console device */
- rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
-#endif /* RT_USING_CONSOLE */
-
-#ifdef RT_USING_COMPONENTS_INIT
- rt_components_board_init();
-#endif
- rt_thread_idle_sethook(idle_wfi);
+ rt_hw_common_setup();
+ // rt_hw_noncacheable_map();
}
-#ifdef RT_USING_SMP
-#include <gic.h>
-
-void rt_hw_mmu_ktbl_set(unsigned long tbl);
-void _secondary_cpu_entry(void);
-
-static unsigned long cpu_release_paddr[] =
+static int ttyAMA0_init(void)
{
- [0] = 0xd8,
- [1] = 0xe0,
- [2] = 0xe8,
- [3] = 0xf0,
- [4] = 0x00
-};
+ const char *con = rt_ofw_bootargs_select("console=", 0);
+ struct rt_device_pin *pinctrl;
+ struct rt_ofw_node *pinctrl_np, *conf_np;
-void rt_hw_secondary_cpu_up(void)
-{
- int i;
- void *release_addr;
-
- for (i = 1; i < RT_CPUS_NR && cpu_release_paddr[i]; ++i)
+ /*
+ * Pi4 DT routes PL011 to GPIO32/33 (BT). Header UART needs GPIO14/15.
+ */
+ if (!con || rt_strncmp(con, "ttyAMA0", 7))
{
- release_addr = rt_ioremap((void *)cpu_release_paddr[i], sizeof(cpu_release_paddr[0]));
- __asm__ volatile ("str %0, [%1]"::"rZ"((unsigned long)_secondary_cpu_entry + PV_OFFSET), "r"(release_addr));
- rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, release_addr, sizeof(release_addr));
- asm volatile ("dsb sy");
- asm volatile ("sev");
+ return 0;
}
-}
-
-void rt_hw_secondary_cpu_bsp_start(void)
-{
- rt_hw_spin_lock(&_cpus_lock);
-
- rt_hw_mmu_ktbl_set((unsigned long)MMUTable);
-
- rt_hw_vector_init();
- arm_gic_cpu_init(0, 0);
+ pinctrl_np = rt_ofw_find_node_by_path("/soc/gpio@7e200000");
+ conf_np = rt_ofw_get_child_by_tag(pinctrl_np, "uart0-gpio14");
- rt_hw_gtimer_init();
-
- rt_kprintf("\rcpu %d boot success\n", rt_hw_cpu_id());
+ if (conf_np && (pinctrl = rt_ofw_data(pinctrl_np)))
+ {
+ pinctrl->ops->pin_ctrl_confs_apply(&pinctrl->parent, conf_np);
+ }
- rt_system_scheduler_start();
-}
+ rt_ofw_node_put(conf_np);
+ rt_ofw_node_put(pinctrl_np);
-void rt_hw_secondary_cpu_idle_exec(void)
-{
- asm volatile ("wfe":::"memory", "cc");
+ return 0;
}
-
-#endif
+INIT_EXPORT(ttyAMA0_init, "1.3");
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/board.h b/bsp/raspberry-pi/raspi4-64/drivers/board.h
index 9d28915ba3..f3525ae59b 100644
--- a/bsp/raspberry-pi/raspi4-64/drivers/board.h
+++ b/bsp/raspberry-pi/raspi4-64/drivers/board.h
@@ -11,26 +11,6 @@
#ifndef BOARD_H__
#define BOARD_H__
-#include <stdint.h>
-#include "raspi4.h"
-#include "mmu.h"
-#include "ioremap.h"
-
-extern int __bss_end;
-#define HEAP_BEGIN ((void*)&__bss_end)
-
-#ifdef RT_USING_SMART
-#define HEAP_END ((size_t)KERNEL_VADDR_START + 32 * 1024 * 1024)
-#define PAGE_START HEAP_END
-#define PAGE_END ((size_t)KERNEL_VADDR_START + 128 * 1024 * 1024)
-#else
-#define KERNEL_VADDR_START 0x0
-
-#define HEAP_END (KERNEL_VADDR_START + 32 * 1024 * 1024)
-#define PAGE_START HEAP_END
-#define PAGE_END ((size_t)PAGE_START + 128 * 1024 * 1024)
-#endif
-
void rt_hw_board_init(void);
-#endif
+#endif /* BOARD_H__ */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c
deleted file mode 100644
index 2628ea5404..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_dsi_touch.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-11-26 bigmagic first version
- */
-#include <rtthread.h>
-#include <rtdevice.h>
-#include "drivers/dev_touch.h"
-#include <ioremap.h>
-#include <mmu.h>
-
-#ifdef RT_USING_SMART
-#include <lwp.h>
-#include <lwp_user_mm.h>
-#endif
-
-#include <hypercall.h>
-
-#ifdef BSP_USING_TOUCH
-
-#include "mbox.h"
-#include "drv_dsi_touch.h"
-
-#define DBG_TAG "dsi_touch"
-#define DBG_LVL DBG_INFO
-#include <rtdbg.h>
-
-static rt_touch_t touch_device = RT_NULL;
-static struct rt_semaphore dsi_touch_ack;
-
-static rt_uint32_t touch_x;
-static rt_uint32_t touch_y;
-static rt_uint32_t touch_state = 0;
-
-static rt_thread_t dsi_touch_tid = RT_NULL;
-#define DSI_TOUCH_THREAD_STACK_SIZE (4096)
-#define DSI_TOUCH_THREAD_PRIORITY (25)
-#define DSI_TOUCH_THREAD_TIMESLICE (10)
-
-#define MAXIMUM_SUPPORTED_POINTS (10)
-
-struct touch_regs
-{
- uint8_t device_mode;
- uint8_t gesture_id;
- uint8_t num_points;
- struct touch
- {
- uint8_t xh;
- uint8_t xl;
- uint8_t yh;
- uint8_t yl;
- uint8_t res1;
- uint8_t res2;
- } point[MAXIMUM_SUPPORTED_POINTS];
-};
-
-struct drv_mouse_device
-{
- struct rt_device parent;
- struct rt_touch_data touchdata;
- int channel;
-};
-
-struct drv_mouse_device _mouse;
-
-static void post_event(rt_uint16_t x, rt_uint16_t y, rt_uint8_t event)
-{
- struct rt_touch_data *minfo = &_mouse.touchdata;
- struct rt_channel_msg ch_msg;
-
- LOG_D("event:%d, x:%d, y:%d\n", event, x, y);
-
- minfo->x_coordinate = x;
- minfo->y_coordinate = y;
- minfo->event = event;
- ch_msg.type = RT_CHANNEL_RAW;
- ch_msg.u.d = (void *)(size_t)event;
- rt_channel_send(_mouse.channel, &ch_msg);
-}
-
-static void dsi_touch_thread_entry(void *param)
-{
- static volatile unsigned long touchbuf;
- touchbuf = bcm271x_mbox_get_touch();
-
- if (touchbuf == RT_NULL)
- {
- rt_kprintf("init dsi touch err!\n");
- return;
- }
-
-#ifdef BSP_USING_VM_MODE
- if (rt_hv_stage2_map((unsigned long)touchbuf, 0x1000))
- {
- rt_kprintf("alloc mmio from hyper fail!\n");
- return;
- }
-#endif
-
- touchbuf = (unsigned long)rt_ioremap((void *)touchbuf, 0x1000);
-
- while (1)
- {
- struct touch_regs *regs = (struct touch_regs *)touchbuf;
- if ((regs->num_points > 0) && (regs->num_points < MAXIMUM_SUPPORTED_POINTS))
- {
- /* only one touch point */
- touch_x = (((int)regs->point[0].xh & 0xf) << 8) + regs->point[0].xl;
- touch_y = (((int)regs->point[0].yh & 0xf) << 8) + regs->point[0].yl;
- if (!touch_state)
- {
- post_event(touch_x, touch_y, RT_TOUCH_EVENT_DOWN);
- }
- else
- {
- post_event(touch_x, touch_y, RT_TOUCH_EVENT_MOVE);
- }
- touch_state = 1;
- }
- else
- {
- if (touch_state)
- {
- post_event(touch_x, touch_y, RT_TOUCH_EVENT_UP);
- }
- touch_state = 0;
- }
- rt_thread_mdelay(1);
- }
-}
-
-static rt_size_t dsi_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
-{
- rt_uint16_t* touchxy = (rt_uint16_t *)buf;
-
- if ((read_num != 0) && (touch_state == 1))
- {
- touchxy[0] = touch_x;
- touchxy[1] = touch_y;
- touch_state = 0;
- return read_num;
- }
- else
- {
- return 0;
- }
-}
-
-static rt_err_t dsi_control(struct rt_touch_device *device, int cmd, void *data)
-{
- return RT_EOK;
-}
-
-static struct rt_touch_ops dsi_touch_ops =
-{
- .touch_readpoint = dsi_read_point,
- .touch_control = dsi_control,
-};
-
-static rt_err_t drv_mouse_init(struct rt_device *device)
-{
- struct drv_mouse_device *mouse = (struct drv_mouse_device*)device;
-
- return RT_EOK;
-}
-
-static rt_err_t drv_mouse_control(struct rt_device *device, int cmd, void *args)
-{
- switch (cmd)
- {
-#define CMD_MOUSE_SET_NOTIFY 0 /* arg is shmid, in the shm, a sem point is given */
- case CMD_MOUSE_SET_NOTIFY:
- *(unsigned long *)args = (rt_uint32_t)(unsigned long)lwp_map_user_phy(lwp_self(), RT_NULL, (uint32_t*)((size_t)&_mouse.touchdata + PV_OFFSET), sizeof(struct rt_touch_data), 1);
- break;
- default:
- break;
- }
- return RT_EOK;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops _mouse_ops =
-{
- drv_mouse_init,
- RT_NULL,
- RT_NULL,
- RT_NULL,
- RT_NULL,
- drv_mouse_control
-};
-#endif
-
-static int hw_dsi_touch_init(void)
-{
- struct rt_device *device = &_mouse.parent;
-
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &_mouse_ops;
-#else
- device->init = drv_mouse_init;
- device->open = RT_NULL;
- device->close = RT_NULL;
- device->read = RT_NULL;
- device->write = RT_NULL;
- device->control = drv_mouse_control;
-#endif
- rt_device_register(device, "mouse", RT_DEVICE_FLAG_RDWR);
- _mouse.channel = rt_channel_open("mouse", O_CREAT);
-
- /* touch sem */
- rt_sem_init(&dsi_touch_ack, "dsi_touch_ack", 0, RT_IPC_FLAG_FIFO);
-
- dsi_touch_tid = rt_thread_create("dsi_touch",
- dsi_touch_thread_entry, RT_NULL,
- DSI_TOUCH_THREAD_STACK_SIZE,
- DSI_TOUCH_THREAD_PRIORITY, DSI_TOUCH_THREAD_TIMESLICE);
- if (dsi_touch_tid != RT_NULL)
- {
- rt_thread_startup(dsi_touch_tid);
- }
-
- touch_device = (rt_touch_t)rt_malloc(sizeof(struct rt_touch_device));
-
- if (touch_device == RT_NULL)
- {
- return -RT_ERROR;
- }
-
- /* register touch device */
- touch_device->info.type = RT_TOUCH_TYPE_RESISTANCE;
- touch_device->info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
-
- touch_device->ops = &dsi_touch_ops;
- rt_hw_touch_register(touch_device, "dsi_touch", RT_DEVICE_FLAG_INT_RX, RT_NULL);
- return 0;
-}
-INIT_APP_EXPORT(hw_dsi_touch_init);
-#endif /* BSP_USING_TOUCH */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c
deleted file mode 100644
index 81380896c5..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.c
+++ /dev/null
@@ -1,714 +0,0 @@
-
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-30 bigmagic first version
- * 2023-03-28 WangXiaoyao Modify pbuf_alloc
- */
-
-#include <rthw.h>
-#include <stdint.h>
-#include <rtthread.h>
-#include <lwip/sys.h>
-#include <netif/ethernetif.h>
-
-#include "mbox.h"
-#include "raspi4.h"
-#include "drv_eth.h"
-
-#define LOG_LVL DBG_LOG
-#define LOG_TAG "drv.eth"
-#include <rtdbg.h>
-
-static int link_speed = 0;
-static int link_flag = 0;
-
-#define DMA_DISC_ADDR_SIZE (4 * 1024 *1024)
-
-#define RX_DESC_BASE (mac_reg_base_addr + GENET_RX_OFF)
-#define TX_DESC_BASE (mac_reg_base_addr + GENET_TX_OFF)
-
-#define MAX_ADDR_LEN (6)
-
-#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
-#define lower_32_bits(n) ((rt_uint32_t)(n))
-
-#define BIT(nr) (1UL << (nr))
-
-static rt_thread_t link_thread_tid = RT_NULL;
-#define LINK_THREAD_STACK_SIZE (8192)
-#define LINK_THREAD_PRIORITY (20)
-#define LINK_THREAD_TIMESLICE (10)
-
-static rt_uint32_t tx_index = 0;
-static rt_uint32_t rx_index = 0;
-static rt_uint32_t index_flag = 0;
-
-struct rt_eth_dev
-{
- struct eth_device parent;
- rt_uint8_t dev_addr[MAX_ADDR_LEN];
- char *name;
- void *iobase;
- int state;
- int index;
- struct rt_timer link_timer;
- void *priv;
-};
-static struct rt_eth_dev eth_dev;
-static struct rt_semaphore link_ack;
-
-static inline rt_uint32_t read32(void *addr)
-{
- return (*((volatile unsigned int*)(addr)));
-}
-
-static inline void write32(void *addr, rt_uint32_t value)
-{
- (*((volatile unsigned int*)(addr))) = value;
-}
-
-static void eth_rx_irq(int irq, void *param)
-{
- rt_uint32_t val = 0;
- val = read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT);
- val &= ~read32(mac_reg_base_addr + GENET_INTRL2_CPU_STAT_MASK);
-
- write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR, val);
-
- if (val & GENET_IRQ_RXDMA_DONE)
- {
- eth_device_ready(&eth_dev.parent);
- }
-
- if (val & GENET_IRQ_TXDMA_DONE)
- {
- //todo
- }
-}
-
-/* We only support RGMII (as used on the RPi4). */
-static int bcmgenet_interface_set(void)
-{
- int phy_mode = PHY_INTERFACE_MODE_RGMII;
- switch (phy_mode)
- {
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- write32(mac_reg_base_addr + SYS_PORT_CTRL, PORT_MODE_EXT_GPHY);
- break;
-
- default:
- rt_kprintf("unknown phy mode: %d\n", mac_reg_base_addr);
- return -1;
- }
- return 0;
-}
-
-static void bcmgenet_umac_reset(void)
-{
- rt_uint32_t reg;
- reg = read32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL);
- reg |= BIT(1);
- write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg);
-
- reg &= ~BIT(1);
- write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), reg);
-
- DELAY_MICROS(10);
-
- write32((mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL), 0);
- DELAY_MICROS(10);
-
- write32(mac_reg_base_addr + UMAC_CMD, 0);
- write32(mac_reg_base_addr + UMAC_CMD, (CMD_SW_RESET | CMD_LCL_LOOP_EN));
- DELAY_MICROS(2);
-
- write32(mac_reg_base_addr + UMAC_CMD, 0);
- /* clear tx/rx counter */
- write32(mac_reg_base_addr + UMAC_MIB_CTRL, MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT);
- write32(mac_reg_base_addr + UMAC_MIB_CTRL, 0);
- write32(mac_reg_base_addr + UMAC_MAX_FRAME_LEN, ENET_MAX_MTU_SIZE);
-
- /* init rx registers, enable ip header optimization */
- reg = read32(mac_reg_base_addr + RBUF_CTRL);
- reg |= RBUF_ALIGN_2B;
- write32(mac_reg_base_addr + RBUF_CTRL, reg);
- write32(mac_reg_base_addr + RBUF_TBUF_SIZE_CTRL, 1);
-}
-
-static void bcmgenet_disable_dma(void)
-{
- rt_uint32_t tdma_reg = 0, rdma_reg = 0;
-
- tdma_reg = read32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL);
- tdma_reg &= ~(1UL << DMA_EN);
- write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, tdma_reg);
- rdma_reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL);
- rdma_reg &= ~(1UL << DMA_EN);
- write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, rdma_reg);
- write32(mac_reg_base_addr + UMAC_TX_FLUSH, 1);
- DELAY_MICROS(100);
- write32(mac_reg_base_addr + UMAC_TX_FLUSH, 0);
-}
-
-static void bcmgenet_enable_dma(void)
-{
- rt_uint32_t reg = 0;
- rt_uint32_t dma_ctrl = 0;
-
- dma_ctrl = (1 << (DEFAULT_Q + DMA_RING_BUF_EN_SHIFT)) | DMA_EN;
- write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_CTRL, dma_ctrl);
-
- reg = read32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL);
- write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_CTRL, dma_ctrl | reg);
-}
-
-static int bcmgenet_mdio_write(rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t value)
-{
- int count = 10000;
- rt_uint32_t val;
- val = MDIO_WR | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & value);
- write32(mac_reg_base_addr + MDIO_CMD, val);
-
- rt_uint32_t reg_val = read32(mac_reg_base_addr + MDIO_CMD);
- reg_val = reg_val | MDIO_START_BUSY;
- write32(mac_reg_base_addr + MDIO_CMD, reg_val);
-
- while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count))
- DELAY_MICROS(1);
-
- reg_val = read32(mac_reg_base_addr + MDIO_CMD);
-
- return reg_val & 0xffff;
-}
-
-static int bcmgenet_mdio_read(rt_uint32_t addr, rt_uint32_t reg)
-{
- int count = 10000;
- rt_uint32_t val = 0;
- rt_uint32_t reg_val = 0;
-
- val = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT);
- write32(mac_reg_base_addr + MDIO_CMD, val);
-
- reg_val = read32(mac_reg_base_addr + MDIO_CMD);
- reg_val = reg_val | MDIO_START_BUSY;
- write32(mac_reg_base_addr + MDIO_CMD, reg_val);
-
- while ((read32(mac_reg_base_addr + MDIO_CMD) & MDIO_START_BUSY) && (--count))
- DELAY_MICROS(1);
-
- reg_val = read32(mac_reg_base_addr + MDIO_CMD);
-
- return reg_val & 0xffff;
-}
-
-static int bcmgenet_gmac_write_hwaddr(void)
-{
- rt_uint8_t addr[6];
- rt_uint32_t reg;
- bcm271x_mbox_hardware_get_mac_address(&addr[0]);
-
- reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
- write32(mac_reg_base_addr + UMAC_MAC0, reg);
-
- reg = addr[4] << 8 | addr[5];
- write32(mac_reg_base_addr + UMAC_MAC1, reg);
- return 0;
-}
-
-static int get_ethernet_uid(void)
-{
- rt_uint32_t uid_high = 0;
- rt_uint32_t uid_low = 0;
- rt_uint32_t uid = 0;
-
- uid_high = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_HIGH);
- uid_low = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_LOW);
- uid = (uid_high << 16 | uid_low);
-
- if (BCM54213PE_VERSION_B1 == uid)
- {
- LOG_I("version is B1\n");
- }
- return uid;
-}
-
-static void bcmgenet_mdio_init(void)
-{
- rt_uint32_t ret = 0;
- /*get ethernet uid*/
- ret = get_ethernet_uid();
- if (ret == 0) return;
-
- /* reset phy */
- bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
- /* read control reg */
- bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
- /* reset phy again */
- bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
- /* read control reg */
- bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
- /* read status reg */
- bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
- /* read status reg */
- bcmgenet_mdio_read(1, BCM54213PE_IEEE_EXTENDED_STATUS);
- bcmgenet_mdio_read(1, BCM54213PE_AUTO_NEGOTIATION_ADV);
-
- bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
- bcmgenet_mdio_read(1, BCM54213PE_CONTROL);
- /* half full duplex capability */
- bcmgenet_mdio_write(1, BCM54213PE_CONTROL, (CONTROL_HALF_DUPLEX_CAPABILITY | CONTROL_FULL_DUPLEX_CAPABILITY));
- bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
-
- /* set mii control */
- bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, (MII_CONTROL_AUTO_NEGOTIATION_ENABLED | MII_CONTROL_AUTO_NEGOTIATION_RESTART | MII_CONTROL_PHY_FULL_DUPLEX | MII_CONTROL_SPEED_SELECTION));
-}
-
-static void rx_ring_init(void)
-{
- write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
- write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
- write32(mac_reg_base_addr + RDMA_READ_PTR, 0x0);
- write32(mac_reg_base_addr + RDMA_WRITE_PTR, 0x0);
- write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_END_ADDR, RX_DESCS * DMA_DESC_SIZE / 4 - 1);
-
- write32(mac_reg_base_addr + RDMA_PROD_INDEX, 0x0);
- write32(mac_reg_base_addr + RDMA_CONS_INDEX, 0x0);
- write32(mac_reg_base_addr + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
- write32(mac_reg_base_addr + RDMA_XON_XOFF_THRESH, DMA_FC_THRESH_VALUE);
- write32(mac_reg_base_addr + RDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
-}
-
-static void tx_ring_init(void)
-{
- write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
- write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
- write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
- write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
- write32(mac_reg_base_addr + TDMA_READ_PTR, 0x0);
- write32(mac_reg_base_addr + TDMA_WRITE_PTR, 0x0);
- write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_END_ADDR, TX_DESCS * DMA_DESC_SIZE / 4 - 1);
- write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0x0);
- write32(mac_reg_base_addr + TDMA_CONS_INDEX, 0x0);
- write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH, 0x1);
- write32(mac_reg_base_addr + TDMA_FLOW_PERIOD, 0x0);
- write32(mac_reg_base_addr + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
- write32(mac_reg_base_addr + TDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
-}
-
-static void rx_descs_init(void)
-{
- char *rxbuffs = (char *)RECV_DATA_NO_CACHE;
- rt_uint32_t len_stat, i;
- void *desc_base = (void *)RX_DESC_BASE;
-
- len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
- for (i = 0; i < RX_DESCS; i++)
- {
- write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_LO), lower_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
- write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_HI), upper_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
- write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_LENGTH_STATUS), len_stat);
- }
-}
-
-static int bcmgenet_adjust_link(void)
-{
- rt_uint32_t speed;
- rt_uint32_t phy_dev_speed = link_speed;
-
- switch (phy_dev_speed)
- {
- case SPEED_1000:
- speed = UMAC_SPEED_1000;
- break;
- case SPEED_100:
- speed = UMAC_SPEED_100;
- break;
- case SPEED_10:
- speed = UMAC_SPEED_10;
- break;
- default:
- rt_kprintf("bcmgenet: Unsupported PHY speed: %d\n", phy_dev_speed);
- return -1;
- }
-
- rt_uint32_t reg1 = read32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL);
- //reg1 &= ~(1UL << OOB_DISABLE);
-
- //rt_kprintf("OOB_DISABLE is %d\n", OOB_DISABLE);
- reg1 |= (RGMII_LINK | RGMII_MODE_EN | ID_MODE_DIS);
- write32(mac_reg_base_addr + EXT_RGMII_OOB_CTRL, reg1);
- DELAY_MICROS(1000);
- write32(mac_reg_base_addr + UMAC_CMD, speed << CMD_SPEED_SHIFT);
- return 0;
-}
-
-void link_irq(void *param)
-{
- if ((bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS) & MII_STATUS_LINK_UP) != 0)
- {
- rt_sem_release(&link_ack);
- }
-}
-
-static int bcmgenet_gmac_eth_start(void)
-{
- rt_uint32_t ret;
- rt_uint32_t count = 10000;
-
- bcmgenet_umac_reset();
-
- bcmgenet_gmac_write_hwaddr();
- /* Disable RX/TX DMA and flush TX queues */
- bcmgenet_disable_dma();
- rx_ring_init();
- rx_descs_init();
- tx_ring_init();
-
- /* Enable RX/TX DMA */
- bcmgenet_enable_dma();
-
- /* Update MAC registers based on PHY property */
- ret = bcmgenet_adjust_link();
- if(ret)
- {
- rt_kprintf("bcmgenet: adjust PHY link failed: %d\n", ret);
- return ret;
- }
-
- /* wait tx index clear */
- while ((read32(mac_reg_base_addr + TDMA_CONS_INDEX) != 0) && (--count))
- DELAY_MICROS(1);
-
- tx_index = read32(mac_reg_base_addr + TDMA_CONS_INDEX);
- write32(mac_reg_base_addr + TDMA_PROD_INDEX, tx_index);
-
- index_flag = read32(mac_reg_base_addr + RDMA_PROD_INDEX);
-
- rx_index = index_flag % 256;
-
- write32(mac_reg_base_addr + RDMA_CONS_INDEX, index_flag);
- write32(mac_reg_base_addr + RDMA_PROD_INDEX, index_flag);
-
- /* Enable Rx/Tx */
- rt_uint32_t rx_tx_en;
- rx_tx_en = read32(mac_reg_base_addr + UMAC_CMD);
- rx_tx_en |= (CMD_TX_EN | CMD_RX_EN);
-
- write32(mac_reg_base_addr + UMAC_CMD, rx_tx_en);
-
- // eanble IRQ for TxDMA done and RxDMA done
- write32(mac_reg_base_addr + GENET_INTRL2_CPU_CLEAR_MASK, GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
- return 0;
-}
-
-static rt_uint32_t prev_recv_cnt = 0;
-static rt_uint32_t cur_recv_cnt = 0;
-static rt_uint32_t bcmgenet_gmac_eth_recv(rt_uint8_t **packetp)
-{
- void* desc_base;
- rt_uint32_t length = 0;
- size_t addr = 0;
- rt_uint32_t prod_index = read32(mac_reg_base_addr + RDMA_PROD_INDEX);
- //get next
- if(prod_index == index_flag)
- {
- cur_recv_cnt = index_flag;
- index_flag = 0x7fffffff;
- //no buff
- return 0;
- }
- else
- {
- if(prev_recv_cnt == (prod_index & 0xffffUL))
- {
- return 0;
- }
-
- desc_base = RX_DESC_BASE + rx_index * DMA_DESC_SIZE;
- length = read32(desc_base + DMA_DESC_LENGTH_STATUS);
- length = (length >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK;
- addr = read32(desc_base + DMA_DESC_ADDRESS_LO);
- /* To cater for the IP headepr alignment the hardware does.
- * This would actually not be needed if we don't program
- * RBUF_ALIGN_2B
- */
- *packetp = (rt_uint8_t *)(addr + RX_BUF_OFFSET);
-
- rx_index = rx_index + 1;
- if(rx_index >= 256)
- {
- rx_index = 0;
- }
- write32(mac_reg_base_addr + RDMA_CONS_INDEX, cur_recv_cnt);
-
- cur_recv_cnt = cur_recv_cnt + 1;
-
- if(cur_recv_cnt > 0xffff)
- {
- cur_recv_cnt = 0;
- }
- prev_recv_cnt = cur_recv_cnt;
-
- return length;
- }
-}
-
-static int bcmgenet_gmac_eth_send(void *packet, int length)
-{
- rt_ubase_t level;
- void *desc_base = (TX_DESC_BASE + tx_index * DMA_DESC_SIZE);
- rt_uint32_t len_stat = length << DMA_BUFLENGTH_SHIFT;
-
- rt_uint32_t prod_index, cons;
- rt_uint32_t tries = 100;
-
- prod_index = read32(mac_reg_base_addr + TDMA_PROD_INDEX);
-
- len_stat |= 0x3F << DMA_TX_QTAG_SHIFT;
- len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP;
-
- write32((desc_base + DMA_DESC_ADDRESS_LO), SEND_DATA_NO_CACHE);
- write32((desc_base + DMA_DESC_ADDRESS_HI), 0);
- write32((desc_base + DMA_DESC_LENGTH_STATUS), len_stat);
-
- tx_index = tx_index == 255? 0 : tx_index + 1;
- prod_index = prod_index + 1;
-
- if (prod_index == 0xe000)
- {
- write32(mac_reg_base_addr + TDMA_PROD_INDEX, 0);
- prod_index = 0;
- }
-
- /* Start Transmisson */
- write32(mac_reg_base_addr + TDMA_PROD_INDEX, prod_index);
-
- level = rt_hw_interrupt_disable();
- do
- {
- cons = read32(mac_reg_base_addr + TDMA_CONS_INDEX);
- } while ((cons & 0xffff) < prod_index && --tries);
- rt_hw_interrupt_enable(level);
-
- if (!tries)
- {
- rt_kprintf("send err! tries is %d\n", tries);
- return -1;
- }
-
- return 0;
-}
-
-static void link_task_entry(void *param)
-{
- struct eth_device *eth_device = (struct eth_device *)param;
- RT_ASSERT(eth_device != RT_NULL);
- struct rt_eth_dev *dev = &eth_dev;
-
- //start mdio
- bcmgenet_mdio_init();
-
- //start timer link
- rt_timer_init(&dev->link_timer, "link_timer",
- link_irq,
- NULL,
- 100,
- RT_TIMER_FLAG_PERIODIC);
- rt_timer_start(&dev->link_timer);
-
- //link wait forever
- rt_sem_take(&link_ack, RT_WAITING_FOREVER);
- eth_device_linkchange(&eth_dev.parent, RT_TRUE); //link up
- rt_timer_stop(&dev->link_timer);
-
- //set mac
- // bcmgenet_gmac_write_hwaddr();
- bcmgenet_gmac_write_hwaddr();
-
- //check link speed
- if ((bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 10)) || (bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 11)))
- {
- link_speed = 1000;
- LOG_I("Support link mode Speed 1000M\n");
- }
- else if ((bcmgenet_mdio_read(1, 0x05) & (1 << 7)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 8)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 9)))
- {
- link_speed = 100;
- LOG_I("Support link mode Speed 100M\n");
- }
- else
- {
- link_speed = 10;
- LOG_I("Support link mode Speed 10M\n");
- }
-
- bcmgenet_gmac_eth_start();
-
- rt_hw_interrupt_install(ETH_IRQ, eth_rx_irq, NULL, "eth_irq");
- rt_hw_interrupt_umask(ETH_IRQ);
-
- link_flag = 1;
-}
-
-static rt_err_t bcmgenet_eth_init(rt_device_t device)
-{
- rt_uint32_t ret = 0;
- rt_uint32_t hw_reg = 0;
-
- /* Read GENET HW version */
- rt_uint8_t major = 0;
- hw_reg = read32(mac_reg_base_addr + SYS_REV_CTRL);
- major = (hw_reg >> 24) & 0x0f;
- if (major != 6)
- {
- if (major == 5)
- major = 4;
- else if (major == 0)
- major = 1;
-
- LOG_W("Unsupported GENETv%d.%d\n", major, (hw_reg >> 16) & 0x0f);
- return -RT_ERROR;
- }
- /* set interface */
- ret = bcmgenet_interface_set();
- if (ret)
- {
- return ret;
- }
-
- /* rbuf clear */
- write32(mac_reg_base_addr + SYS_RBUF_FLUSH_CTRL, 0);
-
- /* disable MAC while updating its registers */
- write32(mac_reg_base_addr + UMAC_CMD, 0);
- /* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
- write32(mac_reg_base_addr + UMAC_CMD, CMD_SW_RESET | CMD_LCL_LOOP_EN);
-
- link_thread_tid = rt_thread_create("link", link_task_entry, (void *)device,
- LINK_THREAD_STACK_SIZE,
- LINK_THREAD_PRIORITY, LINK_THREAD_TIMESLICE);
- if (link_thread_tid != RT_NULL)
- rt_thread_startup(link_thread_tid);
-
- return RT_EOK;
-}
-
-static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args)
-{
- switch (cmd)
- {
- case NIOCTL_GADDR:
- if (args)
- rt_memcpy(args, eth_dev.dev_addr, 6);
- else
- return -RT_ERROR;
- break;
- default:
- break;
- }
- return RT_EOK;
-}
-
-rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p)
-{
- int copy_len = 0;
-
- /* lock eth device */
- if (link_flag != 1)
- {
- LOG_I("link disconnected\n");
- return -RT_ERROR;
- }
-
- copy_len = pbuf_copy_partial(p, eth_send_no_cache, p->tot_len, 0);
- if (copy_len == 0)
- {
-
- LOG_I("copy len is zero\n");
- return -RT_ERROR;
- }
- bcmgenet_gmac_eth_send((void *)eth_send_no_cache, p->tot_len);
-
- return RT_EOK;
-}
-
-struct pbuf *rt_eth_rx(rt_device_t device)
-{
- int recv_len = 0;
- size_t addr_point;
- struct pbuf *pbuf = RT_NULL;
- if (link_flag != 1)
- {
- return RT_NULL;
- }
-
- recv_len = bcmgenet_gmac_eth_recv((rt_uint8_t **)&addr_point);
- if (recv_len > 0)
- {
- pbuf = pbuf_alloc(PBUF_LINK, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL);
- if (pbuf != RT_NULL)
- {
- //calc offset
- addr_point= (size_t)(addr_point+ (eth_recv_no_cache - RECV_DATA_NO_CACHE));
- rt_memcpy(pbuf->payload, (char *)addr_point, recv_len);
- }
- }
-
- return pbuf;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-static struct rt_device_ops eth_devops = {
- .init = bcmgenet_eth_init,
- .control = bcmgenet_eth_control,
-};
-#endif /* RT_USING_DEVICE_OPS */
-
-int rt_hw_eth_init(void)
-{
- rt_uint8_t mac_addr[6] = {0xdc, 0xa6, 0x32, 0x28, 0x22, 0x50};
-
- rt_sem_init(&link_ack, "link_ack", 0, RT_IPC_FLAG_FIFO);
-
- memset(&eth_dev, 0, sizeof(eth_dev));
- memset((void *)eth_send_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE));
- memset((void *)eth_recv_no_cache, 0, sizeof(DMA_DISC_ADDR_SIZE));
- bcm271x_mbox_hardware_get_mac_address(&mac_addr[0]);
-
- eth_dev.iobase = mac_reg_base_addr;
- eth_dev.name = "e0";
- eth_dev.dev_addr[0] = mac_addr[0];
- eth_dev.dev_addr[1] = mac_addr[1];
- eth_dev.dev_addr[2] = mac_addr[2];
- eth_dev.dev_addr[3] = mac_addr[3];
- eth_dev.dev_addr[4] = mac_addr[4];
- eth_dev.dev_addr[5] = mac_addr[5];
-
- eth_dev.parent.parent.type = RT_Device_Class_NetIf;
-#ifdef RT_USING_DEVICE_OPS
- eth_dev.parent.parent.ops = &eth_devops;
-#else /* !RT_USING_DEVICE_OPS */
- eth_dev.parent.parent.init = bcmgenet_eth_init;
- eth_dev.parent.parent.open = RT_NULL;
- eth_dev.parent.parent.close = RT_NULL;
- eth_dev.parent.parent.read = RT_NULL;
- eth_dev.parent.parent.write = RT_NULL;
- eth_dev.parent.parent.control = bcmgenet_eth_control;
-#endif /* RT_USING_DEVICE_OPS */
- eth_dev.parent.parent.user_data = RT_NULL;
-
- eth_dev.parent.eth_tx = rt_eth_tx;
- eth_dev.parent.eth_rx = rt_eth_rx;
-
- eth_device_init(&(eth_dev.parent), "e0");
- eth_device_linkchange(&eth_dev.parent, RT_FALSE); //link down
- return 0;
-}
-INIT_COMPONENT_EXPORT(rt_hw_eth_init);
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h
deleted file mode 100644
index 952c8c5bc1..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_eth.h
+++ /dev/null
@@ -1,225 +0,0 @@
-
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-30 bigmagic first version
- */
-
-#ifndef __DRV_ETH_H__
-#define __DRV_ETH_H__
-
-
-//#define BIT(nr) (1UL << (nr))
-#define ENET_FRAME_MAX_FRAMELEN 1518U
-
-#define SYS_REV_CTRL (0x00)
-#define SYS_PORT_CTRL (0x04)
-#define PORT_MODE_EXT_GPHY (3)
-
-#define GENET_SYS_OFF (0x0000)
-#define SYS_RBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x08)
-#define SYS_TBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x0c)
-
-#define GENET_EXT_OFF (0x0080)
-#define EXT_RGMII_OOB_CTRL (GENET_EXT_OFF + 0x0c)
-#define RGMII_LINK BIT(4)
-#define OOB_DISABLE BIT(5)
-#define RGMII_MODE_EN BIT(6)
-#define ID_MODE_DIS BIT(16)
-
-#define GENET_RBUF_OFF (0x0300)
-#define RBUF_TBUF_SIZE_CTRL (GENET_RBUF_OFF + 0xb4)
-#define RBUF_CTRL (GENET_RBUF_OFF + 0x00)
-#define RBUF_ALIGN_2B BIT(1)
-
-#define GENET_UMAC_OFF (0x0800)
-#define UMAC_MIB_CTRL (GENET_UMAC_OFF + 0x580)
-#define UMAC_MAX_FRAME_LEN (GENET_UMAC_OFF + 0x014)
-#define UMAC_MAC0 (GENET_UMAC_OFF + 0x00c)
-#define UMAC_MAC1 (GENET_UMAC_OFF + 0x010)
-#define UMAC_CMD (GENET_UMAC_OFF + 0x008)
-#define MDIO_CMD (GENET_UMAC_OFF + 0x614)
-#define UMAC_TX_FLUSH (GENET_UMAC_OFF + 0x334)
-#define MDIO_START_BUSY BIT(29)
-#define MDIO_READ_FAIL BIT(28)
-#define MDIO_RD (2 << 26)
-#define MDIO_WR BIT(26)
-#define MDIO_PMD_SHIFT (21)
-#define MDIO_PMD_MASK (0x1f)
-#define MDIO_REG_SHIFT (16)
-#define MDIO_REG_MASK (0x1f)
-
-#define GENET_INTRL2_OFF (0x0200)
-#define GENET_INTRL2_CPU_STAT (GENET_INTRL2_OFF + 0x00)
-#define GENET_INTRL2_CPU_CLEAR (GENET_INTRL2_OFF + 0x08)
-#define GENET_INTRL2_CPU_STAT_MASK (GENET_INTRL2_OFF + 0x0c)
-#define GENET_INTRL2_CPU_SET_MASK (GENET_INTRL2_OFF + 0x10)
-#define GENET_INTRL2_CPU_CLEAR_MASK (GENET_INTRL2_OFF + 0x14)
-#define GENET_IRQ_MDIO_ERROR BIT(24)
-#define GENET_IRQ_MDIO_DONE BIT(23)
-#define GENET_IRQ_TXDMA_DONE BIT(16)
-#define GENET_IRQ_RXDMA_DONE BIT(13)
-
-#define CMD_TX_EN BIT(0)
-#define CMD_RX_EN BIT(1)
-#define UMAC_SPEED_10 (0)
-#define UMAC_SPEED_100 (1)
-#define UMAC_SPEED_1000 (2)
-#define UMAC_SPEED_2500 (3)
-#define CMD_SPEED_SHIFT (2)
-#define CMD_SPEED_MASK (3)
-#define CMD_SW_RESET BIT(13)
-#define CMD_LCL_LOOP_EN BIT(15)
-#define CMD_TX_EN BIT(0)
-#define CMD_RX_EN BIT(1)
-
-#define MIB_RESET_RX BIT(0)
-#define MIB_RESET_RUNT BIT(1)
-#define MIB_RESET_TX BIT(2)
-
-/* total number of Buffer Descriptors, same for Rx/Tx */
-#define TOTAL_DESCS (256)
-#define RX_DESCS TOTAL_DESCS
-#define TX_DESCS TOTAL_DESCS
-
-#define DEFAULT_Q (0x10)
-
-#define ETH_DATA_LEN (1500)
-#define ETH_HLEN (14)
-#define VLAN_HLEN (4)
-#define ETH_FCS_LEN (4)
-/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
- * 1536 is multiple of 256 bytes
- */
-#define ENET_BRCM_TAG_LEN (6)
-#define ENET_PAD (8)
-#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + \
- VLAN_HLEN + ENET_BRCM_TAG_LEN + \
- ETH_FCS_LEN + ENET_PAD)
-
-/* Tx/Rx Dma Descriptor common bits */
-#define DMA_EN BIT(0)
-#define DMA_RING_BUF_EN_SHIFT (0x01)
-#define DMA_RING_BUF_EN_MASK (0xffff)
-#define DMA_BUFLENGTH_MASK (0x0fff)
-#define DMA_BUFLENGTH_SHIFT (16)
-#define DMA_RING_SIZE_SHIFT (16)
-#define DMA_OWN (0x8000)
-#define DMA_EOP (0x4000)
-#define DMA_SOP (0x2000)
-#define DMA_WRAP (0x1000)
-#define DMA_MAX_BURST_LENGTH (0x8)
-/* Tx specific DMA descriptor bits */
-#define DMA_TX_UNDERRUN (0x0200)
-#define DMA_TX_APPEND_CRC (0x0040)
-#define DMA_TX_OW_CRC (0x0020)
-#define DMA_TX_DO_CSUM (0x0010)
-#define DMA_TX_QTAG_SHIFT (7)
-
-/* DMA rings size */
-#define DMA_RING_SIZE (0x40)
-#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DEFAULT_Q + 1))
-
-/* DMA descriptor */
-#define DMA_DESC_LENGTH_STATUS (0x00)
-#define DMA_DESC_ADDRESS_LO (0x04)
-#define DMA_DESC_ADDRESS_HI (0x08)
-#define DMA_DESC_SIZE (12)
-
-#define GENET_RX_OFF (0x2000)
-#define GENET_RDMA_REG_OFF \
- (GENET_RX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
-#define GENET_TX_OFF (0x4000)
-#define GENET_TDMA_REG_OFF \
- (GENET_TX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
-
-#define DMA_FC_THRESH_HI (RX_DESCS >> 4)
-#define DMA_FC_THRESH_LO (5)
-#define DMA_FC_THRESH_VALUE ((DMA_FC_THRESH_LO << 16) | \
- DMA_FC_THRESH_HI)
-
-#define DMA_XOFF_THRESHOLD_SHIFT (16)
-
-#define TDMA_RING_REG_BASE \
- (GENET_TDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE)
-#define TDMA_READ_PTR (TDMA_RING_REG_BASE + 0x00)
-#define TDMA_CONS_INDEX (TDMA_RING_REG_BASE + 0x08)
-#define TDMA_PROD_INDEX (TDMA_RING_REG_BASE + 0x0c)
-#define DMA_RING_BUF_SIZE (0x10)
-#define DMA_START_ADDR (0x14)
-#define DMA_END_ADDR (0x1c)
-#define DMA_MBUF_DONE_THRESH (0x24)
-#define TDMA_FLOW_PERIOD (TDMA_RING_REG_BASE + 0x28)
-#define TDMA_WRITE_PTR (TDMA_RING_REG_BASE + 0x2c)
-
-#define RDMA_RING_REG_BASE \
- (GENET_RDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE)
-#define RDMA_WRITE_PTR (RDMA_RING_REG_BASE + 0x00)
-#define RDMA_PROD_INDEX (RDMA_RING_REG_BASE + 0x08)
-#define RDMA_CONS_INDEX (RDMA_RING_REG_BASE + 0x0c)
-#define RDMA_XON_XOFF_THRESH (RDMA_RING_REG_BASE + 0x28)
-#define RDMA_READ_PTR (RDMA_RING_REG_BASE + 0x2c)
-
-#define TDMA_REG_BASE (GENET_TDMA_REG_OFF + DMA_RINGS_SIZE)
-#define RDMA_REG_BASE (GENET_RDMA_REG_OFF + DMA_RINGS_SIZE)
-#define DMA_RING_CFG (0x00)
-#define DMA_CTRL (0x04)
-#define DMA_SCB_BURST_SIZE (0x0c)
-
-#define RX_BUF_LENGTH (2048)
-#define RX_TOTAL_BUFSIZE (RX_BUF_LENGTH * RX_DESCS)
-#define RX_BUF_OFFSET (2)
-
-#define PHY_INTERFACE_MODE_RGMII (7)
-#define PHY_INTERFACE_MODE_RGMII_RXID (9)
-
-#define BCM54213PE_MII_CONTROL (0x00)
-#define BCM54213PE_MII_STATUS (0x01)
-#define BCM54213PE_PHY_IDENTIFIER_HIGH (0x02)
-#define BCM54213PE_PHY_IDENTIFIER_LOW (0x03)
-
-#define BCM54213PE_AUTO_NEGOTIATION_ADV (0x04)
-#define BCM54213PE_AUTO_NEGOTIATION_LINK (0x05)
-#define BCM54213PE_AUTO_NEGOTIATION_EXPANSION (0x06)
-
-#define BCM54213PE_NEXT_PAGE_TX (0x07)
-
-#define BCM54213PE_PARTNER_RX (0x08)
-
-#define BCM54213PE_CONTROL (0x09)
-#define BCM54213PE_STATUS (0x0A)
-
-#define BCM54213PE_IEEE_EXTENDED_STATUS (0x0F)
-#define BCM54213PE_PHY_EXTENDED_CONTROL (0x10)
-#define BCM54213PE_PHY_EXTENDED_STATUS (0x11)
-
-#define BCM54213PE_RECEIVE_ERROR_COUNTER (0x12)
-#define BCM54213PE_FALSE_C_S_COUNTER (0x13)
-#define BCM54213PE_RECEIVE_NOT_OK_COUNTER (0x14)
-
-#define BCM54213PE_VERSION_B1 (0x600d84a2)
-#define BCM54213PE_VERSION_X (0x600d84a0)
-
-//BCM54213PE_MII_CONTROL
-#define MII_CONTROL_PHY_RESET (1 << 15)
-#define MII_CONTROL_AUTO_NEGOTIATION_ENABLED (1 << 12)
-#define MII_CONTROL_AUTO_NEGOTIATION_RESTART (1 << 9)
-#define MII_CONTROL_PHY_FULL_DUPLEX (1 << 8)
-#define MII_CONTROL_SPEED_SELECTION (1 << 6)
-
-//BCM54213PE_MII_STATUS
-#define MII_STATUS_LINK_UP (1 << 2)
-
-//BCM54213PE_CONTROL
-#define CONTROL_FULL_DUPLEX_CAPABILITY (1 << 9)
-#define CONTROL_HALF_DUPLEX_CAPABILITY (1 << 8)
-
-#define SPEED_1000 (1000)
-#define SPEED_100 (100)
-#define SPEED_10 (10)
-
-#endif/* __DRV_ETH_H__ */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c
deleted file mode 100644
index 602d508e6b..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- * 2020-06-16 bigmagic add gpio irq
- */
-
-#include "drv_gpio.h"
-
-#ifdef BSP_USING_PIN
-
-/*
- * gpio_int[0] for BANK0 (pins 0-27)
- * gpio_int[1] for BANK1 (pins 28-45)
- * gpio_int[2] for BANK2 (pins 46-53)
- */
-static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_IRQ_NUM];
-
-uint32_t raspi_get_pin_state(uint32_t fselnum)
-{
- uint32_t gpfsel = 0;
-
- switch (fselnum)
- {
- case 0:
- gpfsel = GPIO_REG_GPFSEL0(gpio_base_addr);
- break;
- case 1:
- gpfsel = GPIO_REG_GPFSEL1(gpio_base_addr);
- break;
- case 2:
- gpfsel = GPIO_REG_GPFSEL2(gpio_base_addr);
- break;
- case 3:
- gpfsel = GPIO_REG_GPFSEL3(gpio_base_addr);
- break;
- case 4:
- gpfsel = GPIO_REG_GPFSEL4(gpio_base_addr);
- break;
- case 5:
- gpfsel = GPIO_REG_GPFSEL5(gpio_base_addr);
- break;
- default:
- break;
- }
- return gpfsel;
-}
-
-void raspi_set_pin_state(uint32_t fselnum, uint32_t gpfsel)
-{
- switch (fselnum)
- {
- case 0:
- GPIO_REG_GPFSEL0(gpio_base_addr) = gpfsel;
- break;
- case 1:
- GPIO_REG_GPFSEL1(gpio_base_addr) = gpfsel;
- break;
- case 2:
- GPIO_REG_GPFSEL2(gpio_base_addr) = gpfsel;
- break;
- case 3:
- GPIO_REG_GPFSEL3(gpio_base_addr) = gpfsel;
- break;
- case 4:
- GPIO_REG_GPFSEL4(gpio_base_addr) = gpfsel;
- break;
- case 5:
- GPIO_REG_GPFSEL5(gpio_base_addr) = gpfsel;
- break;
- default:
- break;
- }
-}
-
-static void gpio_set_pud(GPIO_PIN pin, GPIO_PUPD_FUNC mode)
-{
- uint32_t fselnum = pin / 16;
- uint32_t fselrest = pin % 16;
- uint32_t reg_value = 0;
-
- switch (fselnum)
- {
- case 0:
- reg_value = GPIO_PUP_PDN_CNTRL_REG0(gpio_base_addr);
- GPIO_PUP_PDN_CNTRL_REG0(gpio_base_addr) = (reg_value | (mode << (fselrest*2)));
- break;
- case 1:
- reg_value = GPIO_PUP_PDN_CNTRL_REG1(gpio_base_addr);
- GPIO_PUP_PDN_CNTRL_REG1(gpio_base_addr) = (reg_value | (mode << (fselrest*2)));
- break;
-
- case 2:
- reg_value = GPIO_PUP_PDN_CNTRL_REG2(gpio_base_addr);
- GPIO_PUP_PDN_CNTRL_REG2(gpio_base_addr) = (reg_value | (mode << (fselrest*2)));
- break;
-
- case 3:
- reg_value = GPIO_PUP_PDN_CNTRL_REG3(gpio_base_addr);
- GPIO_PUP_PDN_CNTRL_REG3(gpio_base_addr) = (reg_value | (mode << (fselrest*2)));
- break;
- default:
- break;
- }
-}
-
-void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode)
-{
- uint32_t fselnum = pin / 10;
- uint32_t fselrest = pin % 10;
- uint32_t gpfsel = 0;
-
- gpfsel = raspi_get_pin_state(fselnum);
- gpfsel &= ~((uint32_t)(0x07 << (fselrest * 3)));
- gpfsel |= (uint32_t)(mode << (fselrest * 3));
- raspi_set_pin_state(fselnum, gpfsel);
-}
-
-void prev_raspi_pin_write(GPIO_PIN pin, int pin_value)
-{
- uint32_t num = pin / 32;
-
- if(num == 0)
- {
- if(pin_value == 1)
- {
- GPIO_REG_GPSET0(gpio_base_addr) = 1 << (pin % 32);
- }
- else
- {
- GPIO_REG_GPCLR0(gpio_base_addr) = 1 << (pin % 32);
- }
- }
- else
- {
- if(pin_value == 1)
- {
- GPIO_REG_GPSET1(gpio_base_addr) = 1 << (pin % 32);
- }
- else
- {
- GPIO_REG_GPCLR1(gpio_base_addr) = 1 << (pin % 32);
- }
- }
-}
-
-static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_uint8_t mode)
-{
- GPIO_FUNC raspi_mode = OUTPUT;
-
- switch (mode)
- {
- case PIN_MODE_OUTPUT:
- raspi_mode = OUTPUT;
- break;
- case PIN_MODE_INPUT:
- raspi_mode = INPUT;
- break;
- case PIN_MODE_INPUT_PULLUP:
- gpio_set_pud(pin, RASPI_PULL_UP);
- raspi_mode = INPUT;
- break;
- case PIN_MODE_INPUT_PULLDOWN:
- gpio_set_pud(pin, RASPI_PULL_DOWN);
- raspi_mode = INPUT;
- break;
- case PIN_MODE_OUTPUT_OD:
- raspi_mode = OUTPUT;
- break;
- }
- prev_raspi_pin_mode((GPIO_PIN)pin, raspi_mode);
-}
-
-static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_uint8_t value)
-{
- prev_raspi_pin_write(pin, value);
-}
-
-static rt_ssize_t raspi_pin_read(struct rt_device *device, rt_base_t pin)
-{
- uint32_t num = pin / 32;
- rt_ssize_t pin_level = 0;
-
- if(num == 0)
- {
- if(GPIO_REG_GPLEV0(gpio_base_addr) & (1 << pin))
- {
- pin_level = 1;
- }
- else
- {
- pin_level = 0;
- }
-
- }
- else
- {
- if(GPIO_REG_GPLEV1(gpio_base_addr) & (1 << pin))
- {
- pin_level = 1;
- }
- else
- {
- pin_level = 0;
- }
- }
-
- return pin_level;
-}
-
-static rt_err_t raspi_pin_attach_irq(struct rt_device *device, rt_base_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args)
-{
- rt_uint8_t index;
- rt_uint32_t reg_value;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
- _g_gpio_irq_tbl[index].irq_cb[pin] = hdr;
- _g_gpio_irq_tbl[index].irq_arg[pin] = args;
- _g_gpio_irq_tbl[index].irq_type[pin] = mode;
-
- rt_uint8_t shift = pin % 32;
- rt_uint8_t pin_num = pin / 32;
- rt_uint32_t mask = 1 << shift;
-
- switch (mode)
- {
- case PIN_IRQ_MODE_RISING:
- if(pin_num == 0)
- {
- reg_value = GPIO_REG_GPREN0(gpio_base_addr);
- GPIO_REG_GPREN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- else
- {
- reg_value = GPIO_REG_GPREN1(gpio_base_addr);
- GPIO_REG_GPREN1(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- break;
- case PIN_IRQ_MODE_FALLING:
- if(pin_num == 0)
- {
- reg_value = GPIO_REG_GPFEN0(gpio_base_addr);
- GPIO_REG_GPFEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- else
- {
- reg_value = GPIO_REG_GPFEN1(gpio_base_addr);
- GPIO_REG_GPFEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- break;
- case PIN_IRQ_MODE_RISING_FALLING:
- if(pin_num == 0)
- {
- reg_value = GPIO_REG_GPAREN0(gpio_base_addr);
- GPIO_REG_GPAREN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- reg_value = GPIO_REG_GPFEN0(gpio_base_addr);
- GPIO_REG_GPFEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- else
- {
- reg_value = GPIO_REG_GPAREN1(gpio_base_addr);
- GPIO_REG_GPAREN1(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- reg_value = GPIO_REG_GPFEN1(gpio_base_addr);
- GPIO_REG_GPFEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- break;
- case PIN_IRQ_MODE_HIGH_LEVEL:
- if(pin_num == 0)
- {
- reg_value = GPIO_REG_GPHEN0(gpio_base_addr);
- GPIO_REG_GPHEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- else
- {
- reg_value = GPIO_REG_GPHEN1(gpio_base_addr);
- GPIO_REG_GPHEN1(gpio_base_addr) = (reg_value & ~ mask) | ( mask);
- }
- break;
- case PIN_IRQ_MODE_LOW_LEVEL:
- if(pin_num == 0)
- {
- reg_value = GPIO_REG_GPLEN0(gpio_base_addr);
- GPIO_REG_GPLEN0(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- else
- {
- reg_value = GPIO_REG_GPLEN1(gpio_base_addr);
- GPIO_REG_GPLEN1(gpio_base_addr) = (reg_value & ~ mask) | (mask);
- }
- break;
- }
- return RT_EOK;
-}
-
-static rt_err_t raspi_pin_detach_irq(struct rt_device *device, rt_base_t pin)
-{
- rt_uint8_t index;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
-
- _g_gpio_irq_tbl[index].irq_cb[pin] = RT_NULL;
- _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL;
- _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL;
- _g_gpio_irq_tbl[index].state[pin] = RT_NULL;
-
- return RT_EOK;
-}
-
-rt_err_t raspi_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
-{
- rt_uint8_t index;
- if (pin <= 27)
- index = 0;
- else if (pin <= 45)
- index = 1;
- else
- index = 2;
-
- if (enabled)
- _g_gpio_irq_tbl[index].state[pin] = 1;
- else
- _g_gpio_irq_tbl[index].state[pin] = 0;
-
- return RT_EOK;
-}
-
-static const struct rt_pin_ops ops =
-{
- raspi_pin_mode,
- raspi_pin_write,
- raspi_pin_read,
- raspi_pin_attach_irq,
- raspi_pin_detach_irq,
- raspi_pin_irq_enable,
- RT_NULL,
-};
-
-static void gpio_irq_handler(int irq, void *param)
-{
- struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param;
- rt_uint32_t pin;
- rt_uint32_t value;
- rt_uint32_t tmpvalue;
-
- if(irq == IRQ_GPIO0)
- {
- /* 0~27 */
- value = GPIO_REG_GPEDS0(gpio_base_addr);
- value &= 0x0fffffff;
- pin = 0;
- GPIO_REG_GPEDS0(gpio_base_addr) = value;
- }
- else if(irq == IRQ_GPIO1)
- {
- /* 28-45 */
- tmpvalue = GPIO_REG_GPEDS0(gpio_base_addr);
- tmpvalue &= (~0x0fffffff);
- GPIO_REG_GPEDS0(gpio_base_addr) = tmpvalue;
-
- value = GPIO_REG_GPEDS1(gpio_base_addr);
- value &= 0x3fff;
- GPIO_REG_GPEDS1(gpio_base_addr) = value;
- value = (value) | tmpvalue;
- pin = 28;
- }
- else if (irq == IRQ_GPIO2)
- {
- /* 46-53 */
- value = GPIO_REG_GPEDS1(gpio_base_addr);
- value &= (~0x3fff);
- GPIO_REG_GPEDS1(gpio_base_addr) = value;
- pin = 46;
- }
-
- while (value)
- {
- if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL))
- {
- if(irq_def->state[pin])
- {
- irq_def->irq_cb[pin](irq_def->irq_arg[pin]);
- }
- }
- pin++;
- value = value >> 1;
- }
-}
-#endif
-
-int rt_hw_gpio_init(void)
-{
-#ifdef BSP_USING_PIN
- rt_device_pin_register("gpio", &ops, RT_NULL);
-
- //disable all intr
- GPIO_REG_GPEDS0(gpio_base_addr) = 0xffffffff;
- GPIO_REG_GPEDS1(gpio_base_addr) = 0xffffffff;
-
- GPIO_REG_GPREN0(gpio_base_addr) = 0x0;
- GPIO_REG_GPREN1(gpio_base_addr) = 0x0;
-
- GPIO_REG_GPFEN0(gpio_base_addr) = 0x0;
- GPIO_REG_GPFEN1(gpio_base_addr) = 0x0;
-
- GPIO_REG_GPHEN0(gpio_base_addr) = 0x0;
- GPIO_REG_GPHEN1(gpio_base_addr) = 0x0;
-
- GPIO_REG_GPAREN0(gpio_base_addr) = 0x0;
- GPIO_REG_GPAREN1(gpio_base_addr) = 0x0;
-
- GPIO_REG_GPAFEN0(gpio_base_addr) = 0x0;
- GPIO_REG_GPAFEN0(gpio_base_addr) = 0x0;
-
- rt_hw_interrupt_install(IRQ_GPIO0, gpio_irq_handler, &_g_gpio_irq_tbl[0], "gpio0_irq");
- rt_hw_interrupt_umask(IRQ_GPIO0);
-
- rt_hw_interrupt_install(IRQ_GPIO1, gpio_irq_handler, &_g_gpio_irq_tbl[1], "gpio1_irq");
- rt_hw_interrupt_umask(IRQ_GPIO1);
-
- rt_hw_interrupt_install(IRQ_GPIO2, gpio_irq_handler, &_g_gpio_irq_tbl[2], "gpio2_irq");
- rt_hw_interrupt_umask(IRQ_GPIO2);
-
-#endif
-
- return 0;
-}
-INIT_DEVICE_EXPORT(rt_hw_gpio_init);
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h
deleted file mode 100644
index 5f564e35d1..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_gpio.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- */
-
-#ifndef __DRV_GPIO_H__
-#define __DRV_GPIO_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "board.h"
-#include "interrupt.h"
-
-struct gpio_irq_def
-{
- void *irq_arg[32];
- void (*irq_cb[32])(void *param);
- rt_uint8_t irq_type[32];
- rt_uint8_t state[32];
-};
-
-#define GPIO_REG_GPFSEL0(BASE) HWREG32(BASE + 0x00)
-#define GPIO_REG_GPFSEL1(BASE) HWREG32(BASE + 0x04)
-#define GPIO_REG_GPFSEL2(BASE) HWREG32(BASE + 0x08)
-#define GPIO_REG_GPFSEL3(BASE) HWREG32(BASE + 0x0C)
-#define GPIO_REG_GPFSEL4(BASE) HWREG32(BASE + 0x10)
-#define GPIO_REG_GPFSEL5(BASE) HWREG32(BASE + 0x14)
-#define GPIO_REG_REV0(BASE) HWREG32(BASE + 0x18)
-#define GPIO_REG_GPSET0(BASE) HWREG32(BASE + 0x1C)
-#define GPIO_REG_GPSET1(BASE) HWREG32(BASE + 0x20)
-#define GPIO_REG_REV1(BASE) HWREG32(BASE + 0x24)
-#define GPIO_REG_GPCLR0(BASE) HWREG32(BASE + 0x28)
-#define GPIO_REG_GPCLR1(BASE) HWREG32(BASE + 0x2C)
-#define GPIO_REG_REV2(BASE) HWREG32(BASE + 0x30)
-#define GPIO_REG_GPLEV0(BASE) HWREG32(BASE + 0x34)
-#define GPIO_REG_GPLEV1(BASE) HWREG32(BASE + 0x38)
-#define GPIO_REG_REV3(BASE) HWREG32(BASE + 0x3C)
-#define GPIO_REG_GPEDS0(BASE) HWREG32(BASE + 0x40)
-#define GPIO_REG_GPEDS1(BASE) HWREG32(BASE + 0x44)
-#define GPIO_REG_REV4(BASE) HWREG32(BASE + 0x48)
-#define GPIO_REG_GPREN0(BASE) HWREG32(BASE + 0x4C)
-#define GPIO_REG_GPREN1(BASE) HWREG32(BASE + 0x50)
-#define GPIO_REG_REV5(BASE) HWREG32(BASE + 0x54)
-#define GPIO_REG_GPFEN0(BASE) HWREG32(BASE + 0x58)
-#define GPIO_REG_GPFEN1(BASE) HWREG32(BASE + 0x5C)
-#define GPIO_REG_REV6(BASE) HWREG32(BASE + 0x60)
-#define GPIO_REG_GPHEN0(BASE) HWREG32(BASE + 0x64)
-#define GPIO_REG_GPHEN1(BASE) HWREG32(BASE + 0x68)
-#define GPIO_REG_REV7(BASE) HWREG32(BASE + 0x6C)
-#define GPIO_REG_GPLEN0(BASE) HWREG32(BASE + 0x70)
-#define GPIO_REG_GPLEN1(BASE) HWREG32(BASE + 0x74)
-#define GPIO_REG_REV8(BASE) HWREG32(BASE + 0x78)
-#define GPIO_REG_GPAREN0(BASE) HWREG32(BASE + 0x7C)
-#define GPIO_REG_GPAREN1(BASE) HWREG32(BASE + 0x80)
-#define GPIO_REG_REV11(BASE) HWREG32(BASE + 0x84)
-#define GPIO_REG_GPAFEN0(BASE) HWREG32(BASE + 0x88)
-#define GPIO_REG_GPAFEN1(BASE) HWREG32(BASE + 0x8C)
-#define GPIO_REG_REV10(BASE) HWREG32(BASE + 0x90)
-#define GPIO_REG_GPPUD(BASE) HWREG32(BASE + 0x94)
-#define GPIO_REG_GPPUDCLK0(BASE) HWREG32(BASE + 0x98)
-#define GPIO_REG_GPPUDCLK1(BASE) HWREG32(BASE + 0x9C)
-#define GPIO_REG_REV9(BASE) HWREG32(BASE + 0xA0)
-#define GPIO_REG_TEST(BASE) HWREG32(BASE + 0xA4)
-#define GPIO_PUP_PDN_CNTRL_REG0(BASE) HWREG32(BASE + 0xE4)
-#define GPIO_PUP_PDN_CNTRL_REG1(BASE) HWREG32(BASE + 0xE8)
-#define GPIO_PUP_PDN_CNTRL_REG2(BASE) HWREG32(BASE + 0xEC)
-#define GPIO_PUP_PDN_CNTRL_REG3(BASE) HWREG32(BASE + 0xF0)
-
-typedef enum {
- GPIO_PIN_0,
- GPIO_PIN_1,
- GPIO_PIN_2,
- GPIO_PIN_3,
- GPIO_PIN_4,
- GPIO_PIN_5,
- GPIO_PIN_6,
- GPIO_PIN_7,
- GPIO_PIN_8,
- GPIO_PIN_9,
- GPIO_PIN_10,
- GPIO_PIN_11,
- GPIO_PIN_12,
- GPIO_PIN_13,
- GPIO_PIN_14,
- GPIO_PIN_15,
- GPIO_PIN_16,
- GPIO_PIN_17,
- GPIO_PIN_18,
- GPIO_PIN_19,
- GPIO_PIN_20,
- GPIO_PIN_21,
- GPIO_PIN_22,
- GPIO_PIN_23,
- GPIO_PIN_24,
- GPIO_PIN_25,
- GPIO_PIN_26,
- GPIO_PIN_27,
- GPIO_PIN_28,
- GPIO_PIN_29,
- GPIO_PIN_30,
- GPIO_PIN_31,
- GPIO_PIN_32,
- GPIO_PIN_33,
- GPIO_PIN_34,
- GPIO_PIN_35,
- GPIO_PIN_36,
- GPIO_PIN_37,
- GPIO_PIN_38,
- GPIO_PIN_39,
- GPIO_PIN_40,
-} GPIO_PIN;
-
-typedef enum {
- INPUT = 0b000,
- OUTPUT = 0b001,
- ALT0 = 0b100,
- ALT1 = 0b101,
- ALT2 = 0b110,
- ALT3 = 0b111,
- ALT4 = 0b011,
- ALT5 = 0b010
-} GPIO_FUNC;
-
-typedef enum {
- RASPI_NO_RESISTOR = 0x00,
- RASPI_PULL_UP = 0x01,
- RASPI_PULL_DOWN = 0x10
-} GPIO_PUPD_FUNC;
-
-void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode);
-void prev_raspi_pin_write(GPIO_PIN pin, int pin_value);
-int rt_hw_gpio_init(void);
-
-#endif /* __DRV_GPIO_H__ */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c
deleted file mode 100644
index d8a1c77abd..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_gtimer.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include <rtthread.h>
-#include "interrupt.h"
-
-#ifndef RT_CPUS_NR
-#define RT_CPUS_NR 1
-#endif
-
-#define GTIMER_IRQ (27)
-
-static uint64_t _tickval[RT_CPUS_NR];
-static uint64_t _increaseval[RT_CPUS_NR];
-#define tickval _tickval[cpu_id]
-#define increaseval _increaseval[cpu_id]
-
-/**
- * This function is the gtimer isr handler.
- *
- * @param vector interrupt ID
- * @param parameter the parameter specified by rt_hw_interrupt_install
- *
- * @return none
- */
-static void _hw_timer_isr(int vector, void *parameter)
-{
-#ifdef RT_USING_SMP
- int cpu_id = rt_hw_cpu_id();
-#else
- int cpu_id = 0;
-#endif
- uint64_t cntvct_el0;
- do
- {
- tickval += increaseval;
- __asm__ volatile("msr CNTV_CVAL_EL0, %0"::"r"(tickval));
- __asm__ volatile("mrs %0, CNTVCT_EL0":"=r"(cntvct_el0));
- } while (cntvct_el0 >= tickval);
- rt_tick_increase();
-}
-
-/**
- * The function will initialize the general timer used for the system tick.
- *
- * @param none
- *
- * @return none
- */
-rt_weak int rt_hw_gtimer_init(void)
-{
-#ifdef RT_USING_SMP
- int cpu_id = rt_hw_cpu_id();
-#else
- int cpu_id = 0;
-#endif
- uint64_t val;
-
- rt_hw_interrupt_install(GTIMER_IRQ, _hw_timer_isr, RT_NULL, "tick");
- rt_hw_interrupt_umask(GTIMER_IRQ);
-
- __asm__ volatile("mrs %0, CNTFRQ_EL0":"=r"(val));
- increaseval = val / RT_TICK_PER_SECOND;
-
- __asm__ volatile("msr CNTV_CTL_EL0, %0"::"r"(val));
- tickval = increaseval;
- __asm__ volatile("msr CNTV_CVAL_EL0, %0"::"r"(tickval));
- val = 1;
- __asm__ volatile("msr CNTV_CTL_EL0, %0"::"r"(val));
- return 0;
-}
-INIT_BOARD_EXPORT(rt_hw_gtimer_init);
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c
deleted file mode 100644
index 1ba43e9a48..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-26 bigmagic first version
- */
-
-#include <stdint.h>
-#include <rtthread.h>
-#include <ioremap.h>
-
-#if defined(BSP_USING_HDMI) && defined(RT_USING_SMART)
-#include <lwp.h>
-#include <lwp_user_mm.h>
-
-#include <hypercall.h>
-
-#include "mbox.h"
-#include "drv_hdmi.h"
-
-#define LCD_WIDTH (800)
-#define LCD_HEIGHT (480)
-#define LCD_DEPTH (32)
-#define LCD_BPP (32)
-
-#define TAG_ALLOCATE_BUFFER 0x00040001
-#define TAG_SET_PHYS_WIDTH_HEIGHT 0x00048003
-#define TAG_SET_VIRT_WIDTH_HEIGHT 0x00048004
-#define TAG_SET_DEPTH 0x00048005
-#define TAG_SET_PIXEL_ORDER 0x00048006
-#define TAG_GET_PITCH 0x00040008
-#define TAG_SET_VIRT_OFFSET 0x00048009
-#define TAG_END 0x00000000
-
-
-enum {
- MBOX_TAG_FB_GET_GPIOVIRT = 0x00040010,
- MBOX_TAG_FB_ALLOCATE_BUFFER = 0x00040001,
- MBOX_TAG_FB_RELEASE_BUFFER = 0x00048001,
- MBOX_TAG_FB_BLANK_SCREEN = 0x00040002,
- MBOX_TAG_FB_GET_PHYS_WH = 0x00040003,
- MBOX_TAG_FB_TEST_PHYS_WH = 0x00044003,
- MBOX_TAG_FB_SET_PHYS_WH = 0x00048003,
- MBOX_TAG_FB_GET_VIRT_WH = 0x00040004,
- MBOX_TAG_FB_TEST_VIRT_WH = 0x00044004,
- MBOX_TAG_FB_SET_VIRT_WH = 0x00048004,
- MBOX_TAG_FB_GET_DEPTH = 0x00040005,
- MBOX_TAG_FB_TEST_DEPTH = 0x00044005,
- MBOX_TAG_FB_SET_DEPTH = 0x00048005,
- MBOX_TAG_FB_GET_PIXEL_ORDER = 0x00040006,
- MBOX_TAG_FB_TEST_PIXEL_ORDER = 0x00044006,
- MBOX_TAG_FB_SET_PIXEL_ORDER = 0x00048006,
- MBOX_TAG_FB_GET_ALPHA_MODE = 0x00040007,
- MBOX_TAG_FB_TEST_ALPHA_MODE = 0x00044007,
- MBOX_TAG_FB_SET_ALPHA_MODE = 0x00048007,
- MBOX_TAG_FB_GET_PITCH = 0x00040008,
- MBOX_TAG_FB_GET_VIRT_OFFSET = 0x00040009,
- MBOX_TAG_FB_TEST_VIRT_OFFSET = 0x00044009,
- MBOX_TAG_FB_SET_VIRT_OFFSET = 0x00048009,
- MBOX_TAG_FB_GET_OVERSCAN = 0x0004000a,
- MBOX_TAG_FB_TEST_OVERSCAN = 0x0004400a,
- MBOX_TAG_FB_SET_OVERSCAN = 0x0004800a,
- MBOX_TAG_FB_GET_PALETTE = 0x0004000b,
- MBOX_TAG_FB_TEST_PALETTE = 0x0004400b,
- MBOX_TAG_FB_SET_PALETTE = 0x0004800b,
-};
-
-#define LCD_DEVICE(dev) (struct rt_hdmi_fb_device*)(dev)
-
-static struct rt_hdmi_fb_device _hdmi;
-
-typedef rt_uint16_t color_t;
-
-rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
-{
- return RT_EOK;
-}
-
-rt_err_t hdmi_fb_close(rt_device_t dev)
-{
- return RT_EOK;
-}
-
-rt_ssize_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
-{
- return 0;
-}
-
-rt_ssize_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
- return size;
-}
-
-rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
-{
- static unsigned long smem_start = 0;
- static unsigned long smem_len = 0;
- struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev);
-
- switch (cmd)
- {
- case RTGRAPHIC_CTRL_RECT_UPDATE:
- {
- if (smem_start != 0)
- {
- rt_hw_cpu_dcache_clean_and_invalidate((void *)smem_start, smem_len);
- }
- }
- break;
- case RTGRAPHIC_CTRL_GET_INFO:
- {
- struct rt_device_graphic_info *lcd_info = (struct rt_device_graphic_info *)args;
- lcd_info->bits_per_pixel = 32;
- lcd_info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888; /* should be coherent to adding layers */
- lcd_info->width = lcd->width;
- lcd_info->height = lcd->height;
- lcd_info->framebuffer = (void *)lwp_map_user_phy(lwp_self(), RT_NULL, lcd->fb, lcd->width * lcd->height * sizeof(rt_uint32_t), 1);
- }
- break;
-#define FBIOGET_FSCREENINFO 0x4602
- case FBIOGET_FSCREENINFO:
- {
- struct fb_fix_screeninfo
- {
- char id[16];
- unsigned long smem_start;
- uint32_t smem_len;
-
- uint32_t line_length;
- } *info = (struct fb_fix_screeninfo *)args;
- rt_strncpy(info->id, "lcd", sizeof(info->id));
- info->smem_len = lcd->width * lcd->height * sizeof(rt_uint32_t);
- info->smem_start = (size_t)lwp_map_user_phy(lwp_self(), RT_NULL, lcd->fb, info->smem_len, 1);
- info->line_length = lcd->width * sizeof(rt_uint32_t);
- rt_memset((void *)info->smem_start, 0, info->smem_len);
- smem_start = info->smem_start;
- smem_len = info->smem_len;
- }
- break;
- }
- return RT_EOK;
-}
-
-#ifdef RT_USING_DEVICE_OPS
-const static struct rt_device_ops hdmi_fb_ops =
-{
- RT_NULL,
- hdmi_fb_open,
- hdmi_fb_close,
- hdmi_fb_read,
- hdmi_fb_write,
- hdmi_fb_control,
-};
-#endif
-
-rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
-{
- struct rt_device *device;
- RT_ASSERT(hdmi_fb != RT_NULL);
-
- device = &hdmi_fb->parent;
-
- /* set device type */
- device->type = RT_Device_Class_Graphic;
- /* initialize device interface */
-#ifdef RT_USING_DEVICE_OPS
- device->ops = &hdmi_fb_ops;
-#else
- device->init = RT_NULL;
- device->open = hdmi_fb_open;
- device->close = hdmi_fb_close;
- device->read = hdmi_fb_read;
- device->write = hdmi_fb_write;
- device->control = hdmi_fb_control;
-#endif
-
- /* register to device manager */
- rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
-
- return RT_EOK;
-}
-
-rt_uint32_t bcm271x_mbox_fb_get_gpiovirt(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return (mbox[5] & 0x3fffffff);
-}
-
-rt_uint32_t bcm271x_mbox_fb_get_pitch(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_GET_PITCH;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return mbox[5];
-}
-
-void bcm271x_mbox_fb_set_porder(int rgb)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER;
- mbox[3] = 4; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = rgb; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-void bcm271x_mbox_fb_setoffset(int xoffset, int yoffset)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = xoffset; // id
- mbox[6] = yoffset;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-
-void bcm271x_mbox_fb_setalpha(int alpha)
-{
-
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE;
- mbox[3] = 4; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = alpha; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-}
-
-void *bcm271x_mbox_fb_alloc(int width, int height, int bpp, int nrender)
-{
- mbox[0] = 4 * 35;
- mbox[1] = MBOX_REQUEST;
-
- mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request
- mbox[3] = 8; //size
- mbox[4] = 4; //len
- mbox[5] = 4096; //The design of MBOX driver forces us to give the virtual address 0x3C100000
- mbox[6] = 0; //FrameBufferInfo.size
-
- mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT;
- mbox[8] = 8;
- mbox[9] = 8;
- mbox[10] = width;
- mbox[11] = height;
-
- mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT;
- mbox[13] = 8;
- mbox[14] = 8;
- mbox[15] = width;
- mbox[16] = height * nrender;
-
- mbox[17] = TAG_SET_DEPTH;
- mbox[18] = 4;
- mbox[19] = 4;
- mbox[20] = bpp;
-
- mbox[21] = TAG_SET_PIXEL_ORDER;
- mbox[22] = 4;
- mbox[23] = 0;
- mbox[24] = 0; //RGB, not BGR preferably
-
- mbox[25] = TAG_GET_PITCH;
- mbox[26] = 4;
- mbox[27] = 0;
- mbox[28] = 0;
-
- mbox[29] = TAG_SET_VIRT_OFFSET;
- mbox[30] = 8;
- mbox[31] = 8;
- mbox[32] = 0;
- mbox[33] = 0;
-
- mbox[34] = TAG_END;
-
- mbox_call(8, MMU_DISABLE);
- return (void *)((size_t)(mbox[5] & 0x3fffffff));
-}
-
-int hdmi_fb_init(void)
-{
- _hdmi.fb = (rt_uint8_t *)bcm271x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1);
-
- if (_hdmi.fb == RT_NULL)
- {
- rt_kprintf("init hdmi fb err!\n");
- return -RT_ERROR;
- }
-
-#ifdef BSP_USING_VM_MODE
- if (rt_hv_stage2_map((unsigned long)_hdmi.fb, 0x1400000))
- {
- rt_kprintf("alloc mmio from hyper fail!\n");
- return -RT_ERROR;
- }
-#endif
-
- bcm271x_mbox_fb_setoffset(0, 0);
- bcm271x_mbox_fb_set_porder(0);
- _hdmi.width = LCD_WIDTH;
- _hdmi.height = LCD_HEIGHT;
- _hdmi.depth = LCD_DEPTH;
- _hdmi.pitch = 0;
- _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
-
- //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb);
- rt_hdmi_fb_device_init(&_hdmi, "lcd");
-
- return 0;
-}
-
-INIT_DEVICE_EXPORT(hdmi_fb_init);
-#endif /*BSP_USING_HDMI */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h
deleted file mode 100644
index c9a06358d0..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_hdmi.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-26 bigmagic first version
- */
-#ifndef __DRV_HDMI_H__
-#define __DRV_HDMI_H__
-
-#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b)))
-
-struct rt_hdmi_fb_device
-{
- struct rt_device parent;
-
- rt_uint32_t width;
- rt_uint32_t height;
- rt_uint32_t depth;
- rt_uint32_t pitch;
- rt_uint32_t pixel_format;
-
- rt_uint8_t *fb;
-};
-#endif/* __DRV_HDMI_H__ */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c
deleted file mode 100644
index 6206165098..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-27 bigmagic first version
- */
-
-#include "mbox.h"
-#include "raspi4.h"
-#include "drv_sdio.h"
-
-static rt_uint32_t mmc_base_clock = 0;
-
-static rt_uint32_t sdCommandTable[] = {
- SD_CMD_INDEX(0),
- SD_CMD_RESERVED(1),
- SD_CMD_INDEX(2) | SD_RESP_R2,
- SD_CMD_INDEX(3) | SD_RESP_R1,
- SD_CMD_INDEX(4),
- SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
- SD_CMD_INDEX(6) | SD_RESP_R1,
- SD_CMD_INDEX(7) | SD_RESP_R1b,
- SD_CMD_INDEX(8) | SD_RESP_R1,
- SD_CMD_INDEX(9) | SD_RESP_R2,
- SD_CMD_INDEX(10) | SD_RESP_R2,
- SD_CMD_INDEX(11) | SD_RESP_R1,
- SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
- SD_CMD_INDEX(13) | SD_RESP_R1,
- SD_CMD_RESERVED(14),
- SD_CMD_INDEX(15),
- SD_CMD_INDEX(16) | SD_RESP_R1,
- SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_INDEX(20) | SD_RESP_R1b,
- SD_CMD_RESERVED(21),
- SD_CMD_RESERVED(22),
- SD_CMD_INDEX(23) | SD_RESP_R1,
- SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
- SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
- SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
- SD_CMD_INDEX(28) | SD_RESP_R1b,
- SD_CMD_INDEX(29) | SD_RESP_R1b,
- SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(31),
- SD_CMD_INDEX(32) | SD_RESP_R1,
- SD_CMD_INDEX(33) | SD_RESP_R1,
- SD_CMD_RESERVED(34),
- SD_CMD_INDEX(35) | SD_RESP_R1, //add
- SD_CMD_INDEX(36) | SD_RESP_R1, //add
- SD_CMD_RESERVED(37),
- SD_CMD_INDEX(38) | SD_RESP_R1b,
- SD_CMD_INDEX(39) | SD_RESP_R4, //add
- SD_CMD_INDEX(40) | SD_RESP_R5, //add
- SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
- SD_CMD_RESERVED(42) | SD_RESP_R1,
- SD_CMD_RESERVED(43),
- SD_CMD_RESERVED(44),
- SD_CMD_RESERVED(45),
- SD_CMD_RESERVED(46),
- SD_CMD_RESERVED(47),
- SD_CMD_RESERVED(48),
- SD_CMD_RESERVED(49),
- SD_CMD_RESERVED(50),
- SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
- SD_CMD_RESERVED(52),
- SD_CMD_RESERVED(53),
- SD_CMD_RESERVED(54),
- SD_CMD_INDEX(55) | SD_RESP_R3,
- SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
- SD_CMD_RESERVED(57),
- SD_CMD_RESERVED(58),
- SD_CMD_RESERVED(59),
- SD_CMD_RESERVED(60),
- SD_CMD_RESERVED(61),
- SD_CMD_RESERVED(62),
- SD_CMD_RESERVED(63)
-};
-
-static inline rt_uint32_t read32(size_t addr)
-{
- return (*((volatile unsigned int*)(addr)));
-}
-
-static inline void write32(size_t addr, rt_uint32_t value)
-{
- (*((volatile unsigned int*)(addr))) = value;
-}
-
-rt_err_t sd_int(struct sdhci_pdata_t * pdat, rt_uint32_t mask)
-{
- rt_uint32_t r;
- rt_uint32_t m = mask | INT_ERROR_MASK;
- int cnt = 1000000;
- while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
- DELAY_MICROS(1);
- r = read32(pdat->virt + EMMC_INTERRUPT);
- if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
- {
- write32(pdat->virt + EMMC_INTERRUPT, r);
- //qemu maybe can not use sdcard
- rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
- return -RT_ETIMEOUT;
- }
- else if (r & INT_ERROR_MASK)
- {
- write32(pdat->virt + EMMC_INTERRUPT, r);
- rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
- return -RT_ERROR;
- }
- write32(pdat->virt + EMMC_INTERRUPT, mask);
- return RT_EOK;
-}
-
-rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
-{
- int cnt = 500000;
- while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
- DELAY_MICROS(1);
- if (cnt <= 0)
- {
- return -RT_ETIMEOUT;
- }
- else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
- {
- return -RT_ERROR;
- }
-
- return RT_EOK;
-}
-
-static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
-{
- rt_uint32_t cmdidx;
- rt_err_t ret = RT_EOK;
- ret = sd_status(pdat, SR_CMD_INHIBIT);
- if (ret)
- {
- rt_kprintf("ERROR: EMMC busy %d\n", ret);
- return ret;
- }
-
- cmdidx = sdCommandTable[cmd->cmdidx];
- if (cmdidx == 0xFFFFFFFF)
- return -RT_EINVAL;
- if (cmd->datarw == DATA_READ)
- cmdidx |= SD_DATA_READ;
- if (cmd->datarw == DATA_WRITE)
- cmdidx |= SD_DATA_WRITE;
- mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
- write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
- write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
- write32(pdat->virt + EMMC_CMDTM, cmdidx);
- if (cmd->cmdidx == SD_APP_OP_COND)
- DELAY_MICROS(1000);
- else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
- DELAY_MICROS(100);
-
- ret = sd_int(pdat, INT_CMD_DONE);
- if (ret)
- {
- return ret;
- }
- if (cmd->resptype & RESP_MASK)
- {
-
- if (cmd->resptype & RESP_R2)
- {
- rt_uint32_t resp[4];
- resp[0] = read32(pdat->virt + EMMC_RESP0);
- resp[1] = read32(pdat->virt + EMMC_RESP1);
- resp[2] = read32(pdat->virt + EMMC_RESP2);
- resp[3] = read32(pdat->virt + EMMC_RESP3);
- if (cmd->resptype == RESP_R2)
- {
- cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
- cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
- cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
- cmd->response[3] = resp[0]<<8 ;
- }
- else
- {
- cmd->response[0] = resp[0];
- cmd->response[1] = resp[1];
- cmd->response[2] = resp[2];
- cmd->response[3] = resp[3];
- }
- }
- else
- cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
- }
- mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
- return ret;
-}
-
-static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
-{
- int c = 0;
- rt_err_t ret;
- int d;
- while (c < blkcount)
- {
- if ((ret = sd_int(pdat, INT_READ_RDY)))
- {
- rt_kprintf("timeout happens when reading block %d\n",c);
- return ret;
- }
- for (d=0; d < blksize / 4; d++)
- if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
- buf[d] = read32(pdat->virt + EMMC_DATA);
- c++;
- buf += blksize / 4;
- }
- return RT_EOK;
-}
-
-static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
-{
- int c = 0;
- rt_err_t ret;
- int d;
- while (c < blkcount)
- {
- if ((ret = sd_int(pdat, INT_WRITE_RDY)))
- {
- return ret;
- }
- for (d=0; d < blksize / 4; d++)
- write32(pdat->virt + EMMC_DATA, buf[d]);
- c++;
- buf += blksize / 4;
- }
-
- if ((ret = sd_int(pdat, INT_DATA_DONE)))
- {
- return ret;
- }
- return RT_EOK;
-}
-
-static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
-{
- rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
- rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
- if (ret)
- {
- rt_kprintf("ERROR: EMMC busy\n");
- return ret;
- }
- if (dat->blkcnt > 1)
- {
- struct sdhci_cmd_t newcmd;
- newcmd.cmdidx = SET_BLOCK_COUNT;
- newcmd.cmdarg = dat->blkcnt;
- newcmd.resptype = RESP_R1;
- ret = raspi_transfer_command(pdat, &newcmd);
- if (ret) return ret;
- }
-
- if(dlen < 512)
- {
- write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
- }
- else
- {
- write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
- }
- if (dat->flag & DATA_DIR_READ)
- {
- cmd->datarw = DATA_READ;
- ret = raspi_transfer_command(pdat, cmd);
- if (ret) return ret;
- mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
- ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
- }
- else if (dat->flag & DATA_DIR_WRITE)
- {
- cmd->datarw = DATA_WRITE;
- ret = raspi_transfer_command(pdat, cmd);
- if (ret) return ret;
- mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
- ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
- }
- return ret;
-}
-
-static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
-{
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
- if (!dat)
- return raspi_transfer_command(pdat, cmd);
-
- return raspi_transfer_data(pdat, cmd, dat);
-}
-
-static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
-{
- struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
- struct sdhci_cmd_t cmd;
- struct sdhci_cmd_t stop;
- struct sdhci_data_t dat;
- rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
- rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
- rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
-
- cmd.cmdidx = req->cmd->cmd_code;
- cmd.cmdarg = req->cmd->arg;
- cmd.resptype =resp_type(req->cmd);
- if (req->data)
- {
- dat.buf = (rt_uint8_t *)req->data->buf;
- dat.flag = req->data->flags;
- dat.blksz = req->data->blksize;
- dat.blkcnt = req->data->blks;
-
- req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
- }
- else
- {
- req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
- }
-
- req->cmd->resp[3] = cmd.response[3];
- req->cmd->resp[2] = cmd.response[2];
- req->cmd->resp[1] = cmd.response[1];
- req->cmd->resp[0] = cmd.response[0];
-
- if (req->stop)
- {
- stop.cmdidx = req->stop->cmd_code;
- stop.cmdarg = req->stop->arg;
- cmd.resptype =resp_type(req->stop);
- req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
- }
-
- mmcsd_req_complete(host);
-}
-
-rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
-{
- return 0;
-}
-
-static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
-{
- return RT_EOK;
-}
-
-static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
-{
- rt_uint32_t temp = 0;
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
- if (width == MMCSD_BUS_WIDTH_4)
- {
- temp = read32((pdat->virt + EMMC_CONTROL0));
- temp |= C0_HCTL_HS_EN;
- temp |= C0_HCTL_DWITDH; // always use 4 data lines:
- write32((pdat->virt + EMMC_CONTROL0), temp);
- }
- return RT_EOK;
-}
-
-
-static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer ,rt_uint32_t base_clock, rt_uint32_t target_rate)
-{
- rt_uint32_t targetted_divisor = 0;
- rt_uint32_t freq_select = 0;
- rt_uint32_t upper_bits = 0;
- rt_uint32_t ret = 0;
-
- if(target_rate > base_clock)
- targetted_divisor = 1;
- else
- {
- targetted_divisor = base_clock / target_rate;
- rt_uint32_t mod = base_clock % target_rate;
- if(mod)
- targetted_divisor--;
- }
-
- // Decide on the clock mode to use
-
- // Currently only 10-bit divided clock mode is supported
-
- // HCI version 3 or greater supports 10-bit divided clock mode
- // This requires a power-of-two divider
-
- // Find the first bit set
- int divisor = -1;
- for(int first_bit = 31; first_bit >= 0; first_bit--)
- {
- rt_uint32_t bit_test = (1 << first_bit);
- if(targetted_divisor & bit_test)
- {
- divisor = first_bit;
- targetted_divisor &= ~bit_test;
- if(targetted_divisor)
- {
- // The divisor is not a power-of-two, increase it
- divisor++;
- }
- break;
- }
- }
-
- if(divisor == -1)
- divisor = 31;
- if(divisor >= 32)
- divisor = 31;
-
- if(divisor != 0)
- divisor = (1 << (divisor - 1));
-
- if(divisor >= 0x400)
- divisor = 0x3ff;
-
- freq_select = divisor & 0xff;
- upper_bits = (divisor >> 8) & 0x3;
- ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
-
- return ret;
-}
-
-static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
-{
- rt_uint32_t temp = 0;
- rt_uint32_t sdHostVer = 0;
- int count = 100000;
- struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
-
- while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
- DELAY_MICROS(1);
- if (count <= 0)
- {
- rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
- return -RT_ERROR;
- }
-
- // Switch clock off.
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp &= ~C1_CLK_EN;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
- // Request the new clock setting and enable the clock
- temp = read32(pdat->virt + EMMC_SLOTISR_VER);
- sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
- int cdiv = sd_get_clock_divider(sdHostVer, mmc_base_clock, clock);
- temp = read32((pdat->virt + EMMC_CONTROL1));
- temp |= 1;
- temp |= cdiv;
- temp |= (7 << 16);
-
- temp = (temp & 0xffff003f) | cdiv;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
-
- // Enable the clock.
- temp = read32(pdat->virt + EMMC_CONTROL1);
- temp |= C1_CLK_EN;
- write32((pdat->virt + EMMC_CONTROL1),temp);
- DELAY_MICROS(10);
-
- // Wait for clock to be stable.
- count = 10000;
- while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
- DELAY_MICROS(10);
- if (count <= 0)
- {
- rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
- return -RT_ERROR;
- }
-
- mmcsd_dbg("set stable clock %d.\n", clock);
- return RT_EOK;
-}
-
-static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
-{
- struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
- sdhci_setclock(sdhci, io_cfg->clock);
- sdhci_setwidth(sdhci, io_cfg->bus_width);
-}
-
-static const struct rt_mmcsd_host_ops ops =
-{
- mmc_request_send,
- mmc_set_iocfg,
- RT_NULL,
- RT_NULL,
-};
-
-static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat)
-{
- rt_uint32_t control1;
-
- //Reset the controller
- control1 = read32((pdat->virt + EMMC_CONTROL1));
- control1 |= (1 << 24);
- // Disable clock
- control1 &= ~(1 << 2);
- control1 &= ~(1 << 0);
- //temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
- write32((pdat->virt + EMMC_CONTROL1),control1);
- int cnt = 10000;
- do
- {
- DELAY_MICROS(10);
- cnt = cnt - 1;
- if(cnt == 0)
- {
- break;
- }
- } while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0);
-
- // Enable SD Bus Power VDD1 at 3.3V
- rt_uint32_t control0 = read32(pdat->virt + EMMC_CONTROL0);
- control0 |= 0x0F << 8;
- write32(pdat->virt + EMMC_CONTROL0, control0);
-
- rt_thread_delay(100);
- //usleep(2000);
-
-
- // Check for a valid card
- mmcsd_dbg("EMMC: checking for an inserted card\n");
- cnt = 10000;
- do
- {
- DELAY_MICROS(10);
- cnt = cnt - 1;
- if(cnt == 0)
- {
- break;
- }
- } while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0);
-
- rt_uint32_t status_reg = read32(pdat->virt + EMMC_STATUS);
-
- if((status_reg & (1 << 16)) == 0)
- {
- rt_kprintf("EMMC: no card inserted\n");
- return -1;
- }
- else
- {
- mmcsd_dbg("EMMC: status: %08x\n", status_reg);
- }
-
- // Clear control2
- write32(pdat->virt + EMMC_CONTROL2, 0);
- // Get the base clock rate //12
- mmc_base_clock = bcm271x_mbox_clock_get_rate(EMMC_CLK_ID);
- if(mmc_base_clock == 0)
- {
- rt_kprintf("EMMC: assuming clock rate to be 100MHz\n");
- mmc_base_clock = 100000000;
- }
- mmcsd_dbg("EMMC: setting clock rate is %d\n", mmc_base_clock);
- return RT_EOK;
-}
-
-#ifdef RT_MMCSD_DBG
-void dump_registers(struct sdhci_pdata_t * pdat)
-{
- rt_kprintf("EMMC registers:");
- int i = EMMC_ARG2;
- for (; i <= EMMC_CONTROL2; i += 4)
- rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
- rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
- rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
- rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
- rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
- rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
- rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
- rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
- rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
- rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
- rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
-}
-#endif
-
-int raspi_sdmmc_init(void)
-{
- size_t virt;
- struct rt_mmcsd_host * host = RT_NULL;
- struct sdhci_pdata_t * pdat = RT_NULL;
- struct sdhci_t * sdhci = RT_NULL;
-
-#ifdef BSP_USING_SDIO0
- host = mmcsd_alloc_host();
- if (!host)
- {
- rt_kprintf("alloc host failed");
- goto err;
- }
- sdhci = rt_malloc(sizeof(struct sdhci_t));
- if (!sdhci)
- {
- rt_kprintf("alloc sdhci failed");
- goto err;
- }
- rt_memset(sdhci, 0, sizeof(struct sdhci_t));
-
- virt = mmc2_base_addr;
- pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
- RT_ASSERT(pdat != RT_NULL);
-
- pdat->virt = virt;
- reset_emmc(pdat);
- sdhci->name = "sd0";
- sdhci->voltages = VDD_33_34;
- sdhci->width = MMCSD_BUSWIDTH_4;
- sdhci->clock = 1000 * 1000 * 1000;
- sdhci->removeable = RT_TRUE;
-
- sdhci->detect = sdhci_detect;
- sdhci->setwidth = sdhci_setwidth;
- sdhci->setclock = sdhci_setclock;
- sdhci->transfer = sdhci_transfer;
- sdhci->priv = pdat;
- host->ops = &ops;
- host->freq_min = 400000;
- host->freq_max = 50000000;
- host->valid_ocr = VDD_32_33 | VDD_33_34;
- host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
- host->max_seg_size = 2048;
- host->max_dma_segs = 10;
- host->max_blk_size = 512;
- host->max_blk_count = 1;
-
- host->private_data = sdhci;
- write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
- write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
-#ifdef RT_MMCSD_DBG
- dump_registers(pdat);
-#endif
- mmcsd_change(host);
-#endif
- return RT_EOK;
-err:
- if (host) rt_free(host);
- if (sdhci) rt_free(sdhci);
-
- return -RT_EIO;
-}
-
-INIT_DEVICE_EXPORT(raspi_sdmmc_init);
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h
deleted file mode 100644
index 6dc566fcac..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_sdio.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-27 bigmagic first version
- */
-
-#ifndef __DRV_SDIO_H__
-#define __DRV_SDIO_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-#include <drivers/dev_mmcsd_core.h>
-
-#include "board.h"
-#include "raspi4.h"
-
-/* Struct for Intrrrupt Information */
-#define SDXC_CmdDone BIT(0)
-#define SDXC_DataDone BIT(1)
-#define SDXC_BlockGap BIT(2)
-#define SDXC_WriteRdy BIT(4)
-#define SDXC_ReadRdy BIT(5)
-#define SDXC_Card BIT(8)
-#define SDXC_Retune BIT(12)
-#define SDXC_BootAck BIT(13)
-#define SDXC_EndBoot BIT(14)
-#define SDXC_Err BIT(15)
-#define SDXC_CTOErr BIT(16)
-#define SDXC_CCRCErr BIT(17)
-#define SDXC_CENDErr BIT(18)
-#define SDXC_CBADErr BIT(19)
-#define SDXC_DTOErr BIT(20)
-#define SDXC_DCRCErr BIT(21)
-#define SDXC_DENDErr BIT(22)
-#define SDXC_ACMDErr BIT(24)
-
-#define SDXC_BLKCNT_EN BIT(1)
-#define SDXC_AUTO_CMD12_EN BIT(2)
-#define SDXC_AUTO_CMD23_EN BIT(3)
-#define SDXC_DAT_DIR BIT(4) //from card to host
-#define SDXC_MULTI_BLOCK BIT(5)
-#define SDXC_CMD_RSPNS_136 BIT(16)
-#define SDXC_CMD_RSPNS_48 BIT(17)
-#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17)
-#define SDXC_CHECK_CRC_CMD BIT(19)
-#define SDXC_CMD_IXCHK_EN BIT(20)
-#define SDXC_CMD_ISDATA BIT(21)
-#define SDXC_CMD_SUSPEND BIT(22)
-#define SDXC_CMD_RESUME BIT(23)
-#define SDXC_CMD_ABORT BIT(23)|BIT(22)
-
-#define SDXC_CMD_INHIBIT BIT(0)
-#define SDXC_DAT_INHIBIT BIT(1)
-#define SDXC_DAT_ACTIVE BIT(2)
-#define SDXC_WRITE_TRANSFER BIT(8)
-#define SDXC_READ_TRANSFER BIT(9)
-
-struct sdhci_cmd_t
-{
- rt_uint32_t cmdidx;
- rt_uint32_t cmdarg;
- rt_uint32_t resptype;
- rt_uint32_t datarw;
-#define DATA_READ 1
-#define DATA_WRITE 2
- rt_uint32_t response[4];
-};
-
-struct sdhci_data_t
-{
- rt_uint8_t * buf;
- rt_uint32_t flag;
- rt_uint32_t blksz;
- rt_uint32_t blkcnt;
-};
-
-struct sdhci_t
-{
- char * name;
- rt_uint32_t voltages;
- rt_uint32_t width;
- rt_uint32_t clock;
- rt_err_t removeable;
- void * sdcard;
-
- rt_err_t (*detect)(struct sdhci_t * sdhci);
- rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width);
- rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock);
- rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat);
- void * priv;
-};
-
-struct sdhci_pdata_t
-{
- size_t virt;
-};
-
-// EMMC command flags
-#define CMD_TYPE_NORMAL (0x00000000)
-#define CMD_TYPE_SUSPEND (0x00400000)
-#define CMD_TYPE_RESUME (0x00800000)
-#define CMD_TYPE_ABORT (0x00c00000)
-#define CMD_IS_DATA (0x00200000)
-#define CMD_IXCHK_EN (0x00100000)
-#define CMD_CRCCHK_EN (0x00080000)
-#define CMD_RSPNS_NO (0x00000000)
-#define CMD_RSPNS_136 (0x00010000)
-#define CMD_RSPNS_48 (0x00020000)
-#define CMD_RSPNS_48B (0x00030000)
-#define TM_MULTI_BLOCK (0x00000020)
-#define TM_DAT_DIR_HC (0x00000000)
-#define TM_DAT_DIR_CH (0x00000010)
-#define TM_AUTO_CMD23 (0x00000008)
-#define TM_AUTO_CMD12 (0x00000004)
-#define TM_BLKCNT_EN (0x00000002)
-#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN)
-
-#define RCA_NO (1)
-#define RCA_YES (2)
-
-// INTERRUPT register settings
-#define INT_AUTO_ERROR (0x01000000)
-#define INT_DATA_END_ERR (0x00400000)
-#define INT_DATA_CRC_ERR (0x00200000)
-#define INT_DATA_TIMEOUT (0x00100000)
-#define INT_INDEX_ERROR (0x00080000)
-#define INT_END_ERROR (0x00040000)
-#define INT_CRC_ERROR (0x00020000)
-#define INT_CMD_TIMEOUT (0x00010000)
-#define INT_ERR (0x00008000)
-#define INT_ENDBOOT (0x00004000)
-#define INT_BOOTACK (0x00002000)
-#define INT_RETUNE (0x00001000)
-#define INT_CARD (0x00000100)
-#define INT_READ_RDY (0x00000020)
-#define INT_WRITE_RDY (0x00000010)
-#define INT_BLOCK_GAP (0x00000004)
-#define INT_DATA_DONE (0x00000002)
-#define INT_CMD_DONE (0x00000001)
-#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \
- INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \
- INT_ERR|INT_AUTO_ERROR)
-#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK)
-
-#define EMMC_ARG2 (0x00)
-#define EMMC_BLKSIZECNT (0x04)
-#define EMMC_ARG1 (0x08)
-#define EMMC_CMDTM (0x0c)
-#define EMMC_RESP0 (0x10)
-#define EMMC_RESP1 (0x14)
-#define EMMC_RESP2 (0x18)
-#define EMMC_RESP3 (0x1c)
-#define EMMC_DATA (0x20)
-#define EMMC_STATUS (0x24)
-#define EMMC_CONTROL0 (0x28)
-#define EMMC_CONTROL1 (0x2c)
-#define EMMC_INTERRUPT (0x30)
-#define EMMC_IRPT_MASK (0x34)
-#define EMMC_IRPT_EN (0x38)
-#define EMMC_CONTROL2 (0x3c)
-#define EMMC_CAPABILITIES_0 (0x40)
-#define EMMC_CAPABILITIES_1 (0x44)
-#define EMMC_BOOT_TIMEOUT (0x70)
-#define EMMC_EXRDFIFO_EN (0x84)
-#define EMMC_SPI_INT_SPT (0xf0)
-#define EMMC_SLOTISR_VER (0xfc)
-
-// CONTROL register settings
-#define C0_SPI_MODE_EN (0x00100000)
-#define C0_HCTL_HS_EN (0x00000004)
-#define C0_HCTL_DWITDH (0x00000002)
-
-#define C1_SRST_DATA (0x04000000)
-#define C1_SRST_CMD (0x02000000)
-#define C1_SRST_HC (0x01000000)
-#define C1_TOUNIT_DIS (0x000f0000)
-#define C1_TOUNIT_MAX (0x000e0000)
-#define C1_CLK_GENSEL (0x00000020)
-#define C1_CLK_EN (0x00000004)
-#define C1_CLK_STABLE (0x00000002)
-#define C1_CLK_INTLEN (0x00000001)
-
-#define FREQ_SETUP (400000) // 400 Khz
-#define FREQ_NORMAL (25000000) // 25 Mhz
-
-// SLOTISR_VER values
-#define HOST_SPEC_NUM 0x00ff0000
-#define HOST_SPEC_NUM_SHIFT 16
-#define HOST_SPEC_V3 2
-#define HOST_SPEC_V2 1
-#define HOST_SPEC_V1 0
-
-// STATUS register settings
-#define SR_DAT_LEVEL1 (0x1e000000)
-#define SR_CMD_LEVEL (0x01000000)
-#define SR_DAT_LEVEL0 (0x00f00000)
-#define SR_DAT3 (0x00800000)
-#define SR_DAT2 (0x00400000)
-#define SR_DAT1 (0x00200000)
-#define SR_DAT0 (0x00100000)
-#define SR_WRITE_PROT (0x00080000) // From SDHC spec v2, BCM says reserved
-#define SR_READ_AVAILABLE (0x00000800) // ???? undocumented
-#define SR_WRITE_AVAILABLE (0x00000400) // ???? undocumented
-#define SR_READ_TRANSFER (0x00000200)
-#define SR_WRITE_TRANSFER (0x00000100)
-#define SR_DAT_ACTIVE (0x00000004)
-#define SR_DAT_INHIBIT (0x00000002)
-#define SR_CMD_INHIBIT (0x00000001)
-
-#define CONFIG_MMC_USE_DMA
-#define DMA_ALIGN (32U)
-
-#define SD_CMD_INDEX(a) ((a) << 24)
-#define SD_CMD_RESERVED(a) (0xffffffff)
-#define SD_CMD_INDEX(a) ((a) << 24)
-#define SD_CMD_TYPE_NORMAL (0x0)
-#define SD_CMD_TYPE_SUSPEND (1 << 22)
-#define SD_CMD_TYPE_RESUME (2 << 22)
-#define SD_CMD_TYPE_ABORT (3 << 22)
-#define SD_CMD_TYPE_MASK (3 << 22)
-#define SD_CMD_ISDATA (1 << 21)
-#define SD_CMD_IXCHK_EN (1 << 20)
-#define SD_CMD_CRCCHK_EN (1 << 19)
-#define SD_CMD_RSPNS_TYPE_NONE (0) // For no response
-#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC)
-#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC)
-#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC)
-#define SD_CMD_RSPNS_TYPE_MASK (3 << 16)
-#define SD_CMD_MULTI_BLOCK (1 << 5)
-#define SD_CMD_DAT_DIR_HC (0)
-#define SD_CMD_DAT_DIR_CH (1 << 4)
-#define SD_CMD_AUTO_CMD_EN_NONE (0)
-#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2)
-#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2)
-#define SD_CMD_BLKCNT_EN (1 << 1)
-#define SD_CMD_DMA (1)
-#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE
-#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) // | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B) // | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136) // | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48
-#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136
-#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
-#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
-#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c
deleted file mode 100644
index 5f9921958b..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-06-22 bigmagic first version
- */
-#include <rtthread.h>
-#include <rthw.h>
-#include <rtdevice.h>
-
-#include "raspi4.h"
-#include "drv_spi.h"
-
-#ifdef BSP_USING_SPI
-
-#define RPI_CORE_CLK_HZ (250000000)
-#define BSP_SPI_MAX_HZ (30* 1000 *1000)
-#define SPITIMEOUT 0x0FFF
-
-static rt_uint8_t raspi_byte_reverse_table[] =
-{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-#if defined (BSP_USING_SPI0_BUS)
-#define SPI0_BUS_NAME "spi0"
-#define SPI0_DEVICE0_NAME "spi0.0"
-#define SPI0_DEVICE1_NAME "spi0.1"
-
-struct rt_spi_bus spi0_bus;
-
-#if defined (BSP_USING_SPI0_DEVICE0)
-static struct rt_spi_device spi0_device0;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
-static struct rt_spi_device spi0_device1;
-#endif
-#endif
-
-static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
-{
- RT_ASSERT(cfg != RT_NULL);
- RT_ASSERT(device != RT_NULL);
- rt_uint16_t divider;
- struct raspi_spi_device* hw_config = (struct raspi_spi_device *)(device->parent.user_data);
- struct raspi_spi_hw_config *hwcfg = (struct raspi_spi_hw_config *)hw_config->spi_hw_config;
- // spi clear fifo
- SPI_REG_CS(hwcfg->hw_base) = (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX);
- if(cfg->mode & RT_SPI_CPOL)
- {
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CPOL;
- }
-
- if(cfg->mode & RT_SPI_CPHA)
- {
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CPHA;
- }
-
- if(cfg->mode & RT_SPI_CS_HIGH)
- {
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CSPOL_HIGH;
- }
-
- //set clk
- if (cfg->max_hz > BSP_SPI_MAX_HZ)
- cfg->max_hz = BSP_SPI_MAX_HZ;
-
- divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz);
- divider &= 0xFFFE;
-
- SPI_REG_CLK(hwcfg->hw_base) = divider;
-
- return RT_EOK;
-}
-
-rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag)
-{
- if (flag)
- return raspi_byte_reverse_table[b];//reverse
- else
- return b;
-}
-
-static rt_err_t spi_transfernb(struct raspi_spi_hw_config *hwcfg, rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag)
-{
- rt_uint32_t TXCnt=0;
- rt_uint32_t RXCnt=0;
-
- /* Clear TX and RX fifos */
- SPI_REG_CS(hwcfg->hw_base) |= (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX);
-
- /* Set TA = 1 */
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_TA;
-
- /* Use the FIFO's to reduce the interbyte times */
- while ((TXCnt < len) || (RXCnt < len))
- {
- /* TX fifo not full, so add some more bytes */
- while (((SPI_REG_CS(hwcfg->hw_base) & SPI_CS_TX_DATA)) && (TXCnt < len))
- {
- SPI_REG_FIFO(hwcfg->hw_base) = correct_order(tbuf[TXCnt],flag);
- TXCnt++;
- }
- /* Rx fifo not empty, so get the next received bytes */
- while (((SPI_REG_CS(hwcfg->hw_base) & SPI_CS_RX_DATA)) && (RXCnt < len))
- {
- rbuf[RXCnt] = correct_order(SPI_REG_FIFO(hwcfg->hw_base), flag);
- RXCnt++;
- }
- }
- /* Wait for DONE to be set */
- while (!(SPI_REG_CS(hwcfg->hw_base) & SPI_CS_DONE));
- /* Set TA = 0, and also set the barrier */
- SPI_REG_CS(hwcfg->hw_base) |= (0 & SPI_CS_TA);
-
- return RT_EOK;
-}
-
-static rt_uint32_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
-{
- rt_err_t res;
- rt_uint8_t flag;
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(device->parent.user_data != RT_NULL);
- RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);
-
- struct rt_spi_configuration config = device->config;
- struct raspi_spi_device * hw_config = (struct raspi_spi_device *)device->parent.user_data;
- GPIO_PIN cs_pin = (GPIO_PIN)hw_config->cs_pin;
- struct raspi_spi_hw_config *hwcfg = (struct raspi_spi_hw_config *)hw_config->spi_hw_config;
-
- if (config.mode & RT_SPI_MSB)
- {
- flag = 0;
- }
- else
- {
- flag = 1;
- }
-
- if (message->cs_take)
- {
- (config.mode & RT_SPI_CS_HIGH)?prev_raspi_pin_write(cs_pin, 1):prev_raspi_pin_write(cs_pin, 0);
- }
-
- res = spi_transfernb(hwcfg, (rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf, (rt_int32_t)message->length, flag);
- if (message->cs_release)
- {
- (config.mode & RT_SPI_CS_HIGH)?prev_raspi_pin_write(cs_pin, 0):prev_raspi_pin_write(cs_pin, 1);
- }
- if (res != RT_EOK)
- return -RT_ERROR;
-
- return message->length;
-}
-
-rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device)
-{
- rt_err_t ret;
- RT_ASSERT(device != RT_NULL);
- ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device));
- return ret;
-}
-
-rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg)
-{
- prev_raspi_pin_mode(hwcfg->sclk_pin, hwcfg->sclk_mode);
- prev_raspi_pin_mode(hwcfg->miso_pin, hwcfg->miso_mode);
- prev_raspi_pin_mode(hwcfg->mosi_pin, hwcfg->mosi_mode);
-#if defined (BSP_USING_SPI0_DEVICE0)
- prev_raspi_pin_mode(hwcfg->ce0_pin, hwcfg->ce0_mode);
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- prev_raspi_pin_mode(hwcfg->ce1_pin, hwcfg->ce1_mode);
-#endif
- //clear rx and tx
- SPI_REG_CS(hwcfg->hw_base) = (SPI_CS_CLEAR_TX | SPI_CS_CLEAR_RX);
- //enable chip select
-#if defined (BSP_USING_SPI0_DEVICE0)
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CHIP_SELECT_0;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- SPI_REG_CS(hwcfg->hw_base) |= SPI_CS_CHIP_SELECT_1;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1)
- HWREG32(SPI_REG_CS(hwcfg->hw_base)) |= (SPI_CS_CHIP_SELECT_0 | SPI_CS_CHIP_SELECT_1);
-#endif
- return RT_EOK;
-}
-
-static struct rt_spi_ops raspi_spi_ops =
-{
- .configure = raspi_spi_configure,
- .xfer = raspi_spi_xfer
-};
-
-struct raspi_spi_hw_config raspi_spi0_hw =
-{
- .spi_num = 0,
- .sclk_pin = GPIO_PIN_11,
- .sclk_mode = ALT0,
- .mosi_pin = GPIO_PIN_10,
- .mosi_mode = ALT0,
- .miso_pin = GPIO_PIN_9,
- .miso_mode = ALT0,
-
-#if defined (BSP_USING_SPI0_DEVICE0)
- .ce0_pin = GPIO_PIN_8,
- .ce0_mode = ALT0,
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- .ce1_pin = GPIO_PIN_7,
- .ce1_mode = ALT0,
-#endif
- .hw_base = SPI_0_BASE,
-};
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE0)
-struct raspi_spi_device raspi_spi0_device0 =
-{
- .device_name = SPI0_DEVICE0_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device0,
- .spi_hw_config = &raspi_spi0_hw,
- .cs_pin = GPIO_PIN_8,
-};
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
-struct raspi_spi_device raspi_spi0_device1 =
-{
- .device_name = SPI0_DEVICE1_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device1,
- .cs_pin = GPIO_PIN_7,
-};
-#endif
-
-int rt_hw_spi_init(void)
-{
-#if defined (BSP_USING_SPI0_BUS)
- raspi_spi_hw_init(&raspi_spi0_hw);
- rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops);
-
-#if defined (BSP_USING_SPI0_DEVICE0)
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0);
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1)
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1);
-#endif
-#endif
- return RT_EOK;
-}
-INIT_DEVICE_EXPORT(rt_hw_spi_init);
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h
deleted file mode 100644
index 80876a43c6..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_spi.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-06-16 bigmagic first version
- */
-#ifndef __DRV_SPI_H__
-#define __DRV_SPI_H__
-
-#include "drv_gpio.h"
-
-#define SPI_REG_CS(BASE) HWREG32(BASE + 0x00)
-#define SPI_REG_FIFO(BASE) HWREG32(BASE + 0x04)
-#define SPI_REG_CLK(BASE) HWREG32(BASE + 0x08)
-#define SPI_REG_DLEN(BASE) HWREG32(BASE + 0x0C)
-#define SPI_REG_LTOH(BASE) HWREG32(BASE + 0x10)
-#define SPI_REG_DC(BASE) HWREG32(BASE + 0x14)
-
-/* CS Register */
-#define SPI_CS_LOSSI_LONG_32BIT (1 << 25)
-#define SPI_CS_LOSSI_DMA_MODE (1 << 24)
-#define SPI_CS_CSPOL2 (1 << 23)
-#define SPI_CS_CSPOL1 (1 << 22)
-#define SPI_CS_CSPOL0 (1 << 21)
-#define SPI_CS_RX_FIFO_FULL (1 << 20)
-#define SPI_CS_RX_FIFO_3_QUARTER (1 << 19)
-#define SPI_CS_TX_DATA (1 << 18)
-#define SPI_CS_RX_DATA (1 << 17)
-#define SPI_CS_DONE (1 << 16)
-#define SPI_CS_LOSSI_EN (1 << 13)
-#define SPI_CS_READ_EN (1 << 12)
-#define SPI_CS_AUTO_CS (1 << 11)
-#define SPI_CS_INTR_RXR (1 << 10)
-#define SPI_CS_INTR_DONE (1 << 9)
-#define SPI_CS_DMA_EN (1 << 8)
-#define SPI_CS_TA (1 << 7)
-#define SPI_CS_CSPOL_HIGH (1 << 6)
-#define SPI_CS_CLEAR_RX (2 << 4)
-#define SPI_CS_CLEAR_TX (1 << 4)
-#define SPI_CS_CPOL (1 << 3)
-#define SPI_CS_CPHA (1 << 2)
-#define SPI_CS_CHIP_SELECT_2 (2 << 0)
-#define SPI_CS_CHIP_SELECT_1 (1 << 0)
-#define SPI_CS_CHIP_SELECT_0 (0 << 0)
-
-struct raspi_spi_hw_config
-{
- rt_uint8_t spi_num;
- GPIO_PIN sclk_pin;
- GPIO_FUNC sclk_mode;
- GPIO_PIN mosi_pin;
- GPIO_FUNC mosi_mode;
- GPIO_PIN miso_pin;
- GPIO_FUNC miso_mode;
-#if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0)
- GPIO_PIN ce0_pin;
- GPIO_FUNC ce0_mode;
-#endif
-
-#if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1)
- GPIO_PIN ce1_pin;
- GPIO_FUNC ce1_mode;
-#endif
-
-#if defined (BSP_USING_SPI1_DEVICE2)
- GPIO_PIN ce2_pin;
- GPIO_FUNC ce2_mode;
-#endif
- rt_ubase_t hw_base;
-
-};
-
-struct raspi_spi_device
-{
- char *device_name;
- struct rt_spi_bus *spi_bus;
- struct rt_spi_device *spi_device;
- struct raspi_spi_hw_config *spi_hw_config;
- GPIO_PIN cs_pin;
-};
-
-int rt_hw_spi_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c
deleted file mode 100644
index 5d4b07a9fb..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- * 2020-05-26 bigmagic add other uart
- */
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "board.h"
-#include "drv_uart.h"
-#include "drv_gpio.h"
-#include <mmu.h>
-
-size_t uart0_addr = 0;
-size_t uart3_addr = 0;
-size_t uart4_addr = 0;
-size_t uart5_addr = 0;
-
-#ifdef RT_USING_UART0
-static struct rt_serial_device _serial0;
-#endif
-
-#ifdef RT_USING_UART1
-static struct rt_serial_device _serial1;
-#endif
-
-#ifdef RT_USING_UART3
-static struct rt_serial_device _serial3;
-#endif
-
-#ifdef RT_USING_UART4
-static struct rt_serial_device _serial4;
-#endif
-
-#ifdef RT_USING_UART5
-static struct rt_serial_device _serial5;
-#endif
-
-struct hw_uart_device
-{
- rt_ubase_t hw_base;
- rt_uint32_t irqno;
-};
-
-static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
-{
- struct hw_uart_device *uart;
- uint32_t bauddiv = (UART_REFERENCE_CLOCK / cfg->baud_rate)* 1000 / 16;
- uint32_t ibrd = bauddiv / 1000;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- if(uart->hw_base == AUX_BASE)
- {
- prev_raspi_pin_mode(GPIO_PIN_14, ALT5);
- prev_raspi_pin_mode(GPIO_PIN_15, ALT5);
-
- AUX_ENABLES(uart->hw_base) = 1; /* Enable UART1 */
- AUX_MU_IER_REG(uart->hw_base) = 0; /* Disable interrupt */
- AUX_MU_CNTL_REG(uart->hw_base) = 0; /* Disable Transmitter and Receiver */
- AUX_MU_LCR_REG(uart->hw_base) = 3; /* Works in 8-bit mode */
- AUX_MU_MCR_REG(uart->hw_base) = 0; /* Disable RTS */
- AUX_MU_IIR_REG(uart->hw_base) = 0xC6; /* Enable FIFO, Clear FIFO */
- AUX_MU_BAUD_REG(uart->hw_base) = 270; /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */
- AUX_MU_CNTL_REG(uart->hw_base) = 3; /* Enable Transmitter and Receiver */
- return RT_EOK;
- }
-
- if(uart->hw_base == uart0_addr)
- {
- prev_raspi_pin_mode(GPIO_PIN_14, ALT0);
- prev_raspi_pin_mode(GPIO_PIN_15, ALT0);
- }
-
- if(uart->hw_base == uart3_addr)
- {
- prev_raspi_pin_mode(GPIO_PIN_4, ALT4);
- prev_raspi_pin_mode(GPIO_PIN_5, ALT4);
- }
-
- if(uart->hw_base == uart4_addr)
- {
- prev_raspi_pin_mode(GPIO_PIN_8, ALT4);
- prev_raspi_pin_mode(GPIO_PIN_9, ALT4);
- }
-
- if(uart->hw_base == uart5_addr)
- {
- prev_raspi_pin_mode(GPIO_PIN_12, ALT4);
- prev_raspi_pin_mode(GPIO_PIN_13, ALT4);
- }
-
- PL011_REG_CR(uart->hw_base) = 0;/*Clear UART setting*/
- PL011_REG_LCRH(uart->hw_base) = 0;/*disable FIFO*/
- PL011_REG_IBRD(uart->hw_base) = ibrd;
- PL011_REG_FBRD(uart->hw_base) = (((bauddiv - ibrd * 1000) * 64 + 500) / 1000);
- PL011_REG_LCRH(uart->hw_base) = PL011_LCRH_WLEN_8;/*FIFO*/
- PL011_REG_CR(uart->hw_base) = PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE;/*art enable, TX/RX enable*/
-
- return RT_EOK;
-}
-
-static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
-{
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- break;
-
- case RT_DEVICE_CTRL_SET_INT:
- /* enable rx irq */
- if(uart->hw_base == AUX_BASE)
- {
- AUX_MU_IER_REG(uart->hw_base) = 0x1;
- }
- else
- {
- PL011_REG_IMSC(uart->hw_base) |= PL011_IMSC_RXIM;
- }
- rt_hw_interrupt_umask(uart->irqno);
- break;
- }
- return RT_EOK;
-}
-
-static int uart_putc(struct rt_serial_device *serial, char c)
-{
- struct hw_uart_device *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
- if(uart->hw_base == AUX_BASE)
- {
- while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20));
- AUX_MU_IO_REG(uart->hw_base) = c;
- }
- else
- {
- while ((PL011_REG_FR(uart->hw_base) & PL011_FR_TXFF));
- PL011_REG_DR(uart->hw_base) = (uint8_t)c;
- }
- return 1;
-}
-
-static int uart_getc(struct rt_serial_device *serial)
-{
- int ch = -1;
- struct hw_uart_device *uart;
-
- RT_ASSERT(serial != RT_NULL);
- uart = (struct hw_uart_device *)serial->parent.user_data;
-
- if(uart->hw_base == AUX_BASE)
- {
- if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01))
- {
- ch = AUX_MU_IO_REG(uart->hw_base) & 0xff;
- }
- }
- else
- {
- if((PL011_REG_FR(uart->hw_base) & PL011_FR_RXFE) == 0)
- {
- ch = PL011_REG_DR(uart->hw_base) & 0xff;
- }
- }
-
- return ch;
-}
-
-static const struct rt_uart_ops _uart_ops =
-{
- uart_configure,
- uart_control,
- uart_putc,
- uart_getc,
-};
-
-volatile void *earlycon_base = 0;
-const size_t earlycon_size = 0x1000;
-
-extern void early_putc(int c)
-{
- if (c == '\n')
- {
- early_putc('\r');
- }
- while (!(AUX_MU_LSR_REG(earlycon_base) & 0x20));
- AUX_MU_IO_REG(earlycon_base) = c;
-}
-
-void rt_hw_earlycon_ioremap_early(void)
-{
- earlycon_base = rt_ioremap_early((void *)AUX_BASE, earlycon_size);
-}
-
-void rt_hw_console_output(const char *str)
-{
- if (earlycon_base)
- {
- while (*str)
- {
- early_putc(*str++);
- }
- }
-}
-
-void early_printhex(rt_ubase_t number)
-{
- char str[sizeof("0123456789abcdef")];
-
- str[16] = 0;
-
- for (int i = 15; i >= 0; --i)
- {
- str[i] = "0123456789abcdef"[(number & 0xf)];
-
- number >>= 4;
- }
-
- rt_kputs(str);
-}
-
-#ifdef RT_USING_UART1
-static void rt_hw_aux_uart_isr(int irqno, void *param)
-{
- struct rt_serial_device *serial = (struct rt_serial_device*)param;
- rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
-}
-#endif
-
-static void rt_hw_uart_isr(int irqno, void *param)
-{
-#ifdef RT_USING_UART0
- if((PACTL_CS & IRQ_UART0) == IRQ_UART0)
- {
- PACTL_CS &= ~(IRQ_UART0);
- rt_hw_serial_isr(&_serial0, RT_SERIAL_EVENT_RX_IND);
- PL011_REG_ICR(uart0_addr) = PL011_INTERRUPT_RECEIVE;
- }
-#endif
-
-#ifdef RT_USING_UART3
- if((PACTL_CS & IRQ_UART3) == IRQ_UART3)
- {
- PACTL_CS &= ~(IRQ_UART3);
- rt_hw_serial_isr(&_serial3, RT_SERIAL_EVENT_RX_IND);
- PL011_REG_ICR(uart3_addr) = PL011_INTERRUPT_RECEIVE;
- }
-#endif
-
-#ifdef RT_USING_UART4
- if((PACTL_CS & IRQ_UART4) == IRQ_UART4)
- {
- PACTL_CS &= ~(IRQ_UART4);
- rt_hw_serial_isr(&_serial4, RT_SERIAL_EVENT_RX_IND);
- PL011_REG_ICR(uart4_addr) = PL011_INTERRUPT_RECEIVE;
- }
-#endif
-
-#ifdef RT_USING_UART5
- if((PACTL_CS & IRQ_UART5) == IRQ_UART5)
- {
- PACTL_CS &= ~(IRQ_UART5);
- rt_hw_serial_isr(&_serial5, RT_SERIAL_EVENT_RX_IND);
- PL011_REG_ICR(uart5_addr) = PL011_INTERRUPT_RECEIVE;
- }
-#endif
-}
-
-#ifdef RT_USING_UART0
-/* UART device driver structure */
-static struct hw_uart_device _uart0_device =
-{
- UART0_BASE,
- IRQ_PL011,
-};
-#endif
-
-#ifdef RT_USING_UART1
-/* UART device driver structure */
-static struct hw_uart_device _uart1_device =
-{
- AUX_BASE,
- IRQ_AUX_UART,
-};
-#endif
-
-#ifdef RT_USING_UART3
-static struct hw_uart_device _uart3_device =
-{
- UART3_BASE,
- IRQ_PL011,
-};
-#endif
-
-#ifdef RT_USING_UART4
-static struct hw_uart_device _uart4_device =
-{
- UART4_BASE,
- IRQ_PL011,
-};
-#endif
-
-#ifdef RT_USING_UART5
-static struct hw_uart_device _uart5_device =
-{
- UART5_BASE,
- IRQ_PL011,
-};
-#endif
-
-int rt_hw_uart_init(void)
-{
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
-#ifdef RT_USING_UART0
- struct hw_uart_device *uart0;
- uart0 = &_uart0_device;
-
- _serial0.ops = &_uart_ops;
- _serial0.config = config;
-
- uart0_addr = UART0_BASE;
-#ifdef RT_USING_SMART
- uart0_addr = (size_t)rt_ioremap((void*)UART0_BASE, 0x1000);
-#endif
- earlycon_base = (void *)uart0_addr;
- uart0->hw_base = uart0_addr;
-
-
- /* register UART0 device */
- rt_hw_serial_register(&_serial0, "uart0",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart0);
- rt_hw_interrupt_install(uart0->irqno, rt_hw_uart_isr, &_serial0, "uart0");
-
-#endif
-
-#ifdef RT_USING_UART1
- struct hw_uart_device *uart1;
- uart1 = &_uart1_device;
-
- _serial1.ops = &_uart_ops;
- _serial1.config = config;
-
- uart1->hw_base = (size_t)rt_ioremap((void*)AUX_BASE, 0x1000);
-
- /* register UART1 device */
- rt_hw_serial_register(&_serial1, "uart1",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart1);
- rt_hw_interrupt_install(uart1->irqno, rt_hw_aux_uart_isr, &_serial1, "uart1");
-#endif
-
-#ifdef RT_USING_UART3
- struct hw_uart_device *uart3;
- uart3 = &_uart3_device;
-
- _serial3.ops = &_uart_ops;
- _serial3.config = config;
-
- uart3_addr = (size_t)rt_ioremap((void*)UART3_BASE, 0x1000);
- uart3->hw_base = uart3_addr;
-
- /* register UART3 device */
- rt_hw_serial_register(&_serial3, "uart3",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart3);
- rt_hw_interrupt_install(uart3->irqno, rt_hw_uart_isr, &_serial3, "uart3");
-#endif
-
-#ifdef RT_USING_UART4
- struct hw_uart_device *uart4;
- uart4 = &_uart4_device;
-
- _serial4.ops = &_uart_ops;
- _serial4.config = config;
-
- uart4_addr = (size_t)rt_ioremap((void*)UART4_BASE, 0x1000);
- uart4->hw_base = uart4_addr;
-
- /* register UART4 device */
- rt_hw_serial_register(&_serial4, "uart4",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart4);
- rt_hw_interrupt_install(uart4->irqno, rt_hw_uart_isr, &_serial4, "uart4");
-#endif
-
-#ifdef RT_USING_UART5
- struct hw_uart_device *uart5;
- uart5 = &_uart5_device;
-
- _serial5.ops = &_uart_ops;
- _serial5.config = config;
-
- uart5_addr = (size_t)rt_ioremap((void*)UART5_BASE, 0x1000);
- uart5->hw_base = uart5_addr;
-
- /* register UART5 device */
- rt_hw_serial_register(&_serial5, "uart5",
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- uart5);
- rt_hw_interrupt_install(uart5->irqno, rt_hw_uart_isr, &_serial5, "uart5");
-#endif
- return 0;
-}
-
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h
deleted file mode 100644
index 4b2c565c31..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_uart.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-04-16 bigmagic first version
- */
-
-#ifndef DRV_UART_H__
-#define DRV_UART_H__
-
-// register's bit
-#define PL011_FR_RI (1 << 8)
-#define PL011_FR_TXFE (1 << 7)
-#define PL011_FR_RXFF (1 << 6)
-#define PL011_FR_TXFF (1 << 5)
-#define PL011_FR_RXFE (1 << 4)
-#define PL011_FR_BUSY (1 << 3)
-#define PL011_FR_DCD (1 << 2)
-#define PL011_FR_DSR (1 << 1)
-#define PL011_FR_CTS (1 << 0)
-
-#define PL011_LCRH_SPS (1 << 7)
-#define PL011_LCRH_WLEN_8 (3 << 5)
-#define PL011_LCRH_WLEN_7 (2 << 5)
-#define PL011_LCRH_WLEN_6 (1 << 5)
-#define PL011_LCRH_WLEN_5 (0 << 5)
-#define PL011_LCRH_FEN (1 << 4)
-#define PL011_LCRH_STP2 (1 << 3)
-#define PL011_LCRH_EPS (1 << 2)
-#define PL011_LCRH_PEN (1 << 1)
-#define PL011_LCRH_BRK (1 << 0)
-
-#define PL011_CR_CTSEN (1 << 15)
-#define PL011_CR_RTSEN (1 << 14)
-#define PL011_CR_RTS (1 << 11)
-#define PL011_CR_DTR (1 << 10)
-#define PL011_CR_RXE (1 << 9)
-#define PL011_CR_TXE (1 << 8)
-#define PL011_CR_LBE (1 << 7)
-#define PL011_CR_SIRLP (1 << 2)
-#define PL011_CR_SIREN (1 << 1)
-#define PL011_CR_UARTEN (1 << 0)
-
-#define PL011_IMSC_TXIM (1 << 5)
-#define PL011_IMSC_RXIM (1 << 4)
-
-#define PL011_INTERRUPT_OVERRUN_ERROR (1 << 10)
-#define PL011_INTERRUPT_BREAK_ERROR (1 << 9)
-#define PL011_INTERRUPT_PARITY_ERROR (1 << 8)
-#define PL011_INTERRUPT_FRAMING_ERROR (1 << 7)
-#define PL011_INTERRUPT_RECEIVE_TIMEOUT (1 << 6)
-#define PL011_INTERRUPT_TRANSMIT (1 << 5)
-#define PL011_INTERRUPT_RECEIVE (1 << 4)
-#define PL011_INTERRUPT_nUARTCTS (1 << 1)
-
-#define PL011_REG_DR(BASE) HWREG32(BASE + 0x00)
-#define PL011_REG_RSRECR(BASE) HWREG32(BASE + 0x04)
-#define PL011_REG_RESERVED0(BASE) HWREG32(BASE + 0x08)
-#define PL011_REG_FR(BASE) HWREG32(BASE + 0x18)
-#define PL011_REG_RESERVED1(BASE) HWREG32(BASE + 0x1C)
-#define PL011_REG_ILPR(BASE) HWREG32(BASE + 0x20)
-#define PL011_REG_IBRD(BASE) HWREG32(BASE + 0x24)
-#define PL011_REG_FBRD(BASE) HWREG32(BASE + 0x28)
-#define PL011_REG_LCRH(BASE) HWREG32(BASE + 0x2C)
-#define PL011_REG_CR(BASE) HWREG32(BASE + 0x30)
-#define PL011_REG_IFLS(BASE) HWREG32(BASE + 0x34)
-#define PL011_REG_IMSC(BASE) HWREG32(BASE + 0x38)
-#define PL011_REG_RIS(BASE) HWREG32(BASE + 0x3C)
-#define PL011_REG_MIS(BASE) HWREG32(BASE + 0x40)
-#define PL011_REG_ICR(BASE) HWREG32(BASE + 0x44)
-#define PL011_REG_DMACR(BASE) HWREG32(BASE + 0x48)
-#define PL011_REG_RESERVED2(BASE) HWREG32(BASE + 0x4C)
-#define PL011_REG_ITCR(BASE) HWREG32(BASE + 0x80)
-#define PL011_REG_ITIP(BASE) HWREG32(BASE + 0x84)
-#define PL011_REG_ITOP(BASE) HWREG32(BASE + 0x88)
-#define PL011_REG_TDR(BASE) HWREG32(BASE + 0x8C)
-
-/*
- * Auxiliary
- */
-#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */
-#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */
-#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */
-#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */
-#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */
-#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */
-#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */
-#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */
-#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */
-#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */
-#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */
-#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */
-#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */
-#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */
-#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */
-#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */
-#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */
-#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */
-#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */
-#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */
-
-int rt_hw_uart_init(void);
-void rt_hw_earlycon_ioremap_early(void);
-
-#endif /* DRV_UART_H__ */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c
deleted file mode 100644
index ce7e8c2a6c..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-26 bigmagic first version
- */
-#include <rthw.h>
-#include "drv_wdt.h"
-#include "raspi4.h"
-
-#ifdef BSP_USING_WDT
-
-#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
-#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
-
-static struct raspi_wdt_driver bcm_wdt;
-
-void raspi_watchdog_init(rt_uint32_t time_init)
-{
- bcm_wdt.timeout = time_init;
-}
-
-void raspi_watchdog_start()
-{
- volatile rt_uint32_t cur;
- PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
- cur = (PM_RSTC);
- PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
-}
-
-void raspi_watchdog_stop()
-{
- PM_RSTC = PM_PASSWORD | PM_RSTC_RESET;
-}
-
-void raspi_watchdog_clr()
-{
- bcm_wdt.timeout = 0;
-}
-
-void raspi_watchdog_set_timeout(rt_uint32_t timeout_us)
-{
- bcm_wdt.timeout = timeout_us;
-}
-
-rt_uint64_t raspi_watchdog_get_timeout()
-{
- return bcm_wdt.timeout;
-}
-
-rt_uint64_t raspi_watchdog_get_timeleft()
-{
- rt_uint32_t ret = (PM_WDOG);
- return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
-}
-
-static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
-{
- /*init for 10S*/
- raspi_watchdog_init(1000000);
- raspi_watchdog_start();
- raspi_watchdog_stop();
- return RT_EOK;
-}
-
-static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
-{
- rt_uint64_t timeout_us = 0;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
- timeout_us = *((rt_uint32_t *)arg) * 1000000;
- if (timeout_us >= 0xFFFFFFFF)
- timeout_us = 0xFFFFFFFF;
- raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
- break;
- case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
- timeout_us = raspi_watchdog_get_timeout();
- *((rt_uint32_t *)arg) = timeout_us / 1000000;
- break;
- case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
- timeout_us = raspi_watchdog_get_timeleft();
- *((rt_uint32_t *)arg) = timeout_us / 1000000;
- break;
- case RT_DEVICE_CTRL_WDT_KEEPALIVE:
- raspi_watchdog_clr();
- break;
- case RT_DEVICE_CTRL_WDT_START:
- raspi_watchdog_start();
- break;
- case RT_DEVICE_CTRL_WDT_STOP:
- raspi_watchdog_stop();
- break;
- default:
- return -RT_EIO;
- }
- return RT_EOK;
-}
-
-static const struct rt_watchdog_ops raspi_wdg_pos =
-{
- raspi_wdg_init,
- raspi_wdg_control,
-};
-
-static rt_watchdog_t raspi_wdg;
-
-int rt_hw_wdt_init(void)
-{
- raspi_wdg.ops = &raspi_wdg_pos;
- rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
- return RT_EOK;
-}
-INIT_DEVICE_EXPORT(rt_hw_wdt_init);
-
-void rt_hw_cpu_reset(void)
-{
- unsigned int r;
-
- rt_kprintf("reboot system...\n");
- rt_thread_mdelay(100);
- r = PM_RSTS;
- // trigger a restart by instructing the GPU to boot from partition 0
- r &= ~0xfffffaaa;
- PM_RSTS |= (PM_PASSWORD | r); // boot from partition 0
- PM_WDOG |= (PM_PASSWORD | 0x0A);
- PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET);
-
- while (1);
-}
-MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reboot system...);
-#endif /*BSP_USING_WDT */
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h b/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h
deleted file mode 100644
index 58c48d3d77..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/drv_wdt.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-10-26 bigmagic first version
- */
-#ifndef __DRV_WDT_H__
-#define __DRV_WDT_H__
-
-#include <rtthread.h>
-#include <rtdevice.h>
-
-#include "board.h"
-
-struct raspi_wdt_driver
-{
- rt_uint32_t timeout;
-};
-
-int rt_hw_wdt_init(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/mbox.c b/bsp/raspberry-pi/raspi4-64/drivers/mbox.c
deleted file mode 100644
index 0bbbdd6665..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/mbox.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-08-29 zdzn first version
- * 2020-09-10 bigmagic add other mbox option
- */
-
-/* mailbox message buffer */
-#include <rthw.h>
-#include "mbox.h"
-#include "mmu.h"
-//volatile unsigned int __attribute__((aligned(16))) mbox[36];
-
-#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000)
-volatile unsigned int *mbox;
-
-/**
- * Make a mailbox call. Returns 0 on failure, non-zero on success
- */
-int mbox_call(unsigned char ch, int mmu_enable)
-{
- unsigned int r = ((((rt_uint32_t)MBOX_ADDR)&~0xF) | (ch&0xF));
- if(mmu_enable)
- r = BUS_ADDRESS(r);
- /* wait until we can write to the mailbox */
- do
- {
- asm volatile("nop");
- } while (*MBOX_STATUS & MBOX_FULL);
- /* write the address of our message to the mailbox with channel identifier */
- *MBOX_WRITE = r;
- /* now wait for the response */
- while(1)
- {
- /* is there a response? */
- do
- {
- asm volatile("nop");
- } while (*MBOX_STATUS & MBOX_EMPTY);
- /* is it a response to our message? */
- if (r == *MBOX_READ){
- /* is it a valid successful response? */
- return mbox[1] == MBOX_RESPONSE;
- }
- }
- return 0;
-}
-
-int bcm271x_mbox_get_touch(void)
-{
- mbox[0] = 8 * 4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_GET_TOUCHBUF;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- return (int)(mbox[5] & ~0xC0000000);
-}
-
-int bcm271x_notify_reboot(void)
-{
- mbox[0] = 7*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
- mbox[2] = MBOX_TAG_NOTIFY_REBOOT; // (the tag id)
- mbox[3] = 0x00000004; // length + 4
- mbox[4] = 0x00000000; // size of the data
- mbox[5] = 0x00000000; // request
-
- mbox[6] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return 0;
-}
-
-int bcm271x_notify_xhci_reset(void)
-{
- mbox[0] = 7*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
- mbox[2] = MBOX_TAG_NOTIFY_XHCI_RESET; // (the tag id)
- mbox[3] = 0x00000004; // length + 4
- mbox[4] = 0x00000004; // size of the data
- mbox[5] = 0x00100000; // request
- mbox[6] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
- return 0;
-}
-
-int bcm271x_gpu_enable(void)
-{
- mbox[0] = 12*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
- mbox[3] = 0x00000008; // (the tag id)
- mbox[4] = 0x00000008; // (the tag id)
- mbox[5] = 5; // V3D
- mbox[6] = 250 * 1000 * 1000;
- mbox[7] = MBOX_TAG_ENABLE_QPU; // (the tag id)
- mbox[8] = 0x00000004; // (size of the buffer)
- mbox[9] = 0x00000004; // (size of the data)
- mbox[10] = 0x00000001;
- mbox[11] = MBOX_TAG_LAST; // end tag
- mbox_call(8, MMU_DISABLE);
- return mbox[1];
-}
-
-int bcm271x_mbox_hardware_get_model(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_MODEL;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- return mbox[5];
-}
-
-int bcm271x_mbox_hardware_get_revison(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_REV;
- mbox[3] = 4; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- return mbox[5];
-}
-
-int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_MAC_ADDRESS;
- mbox[3] = 6; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- char * mac_str = (char *)&mbox[5];
- mac[0] = mac_str[0];
- mac[1] = mac_str[1];
- mac[2] = mac_str[2];
- mac[3] = mac_str[3];
- mac[4] = mac_str[4];
- mac[5] = mac_str[5];
- return 0;
-}
-
-
-int bcm271x_mbox_hardware_get_serial(rt_uint64_t* sn)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_SERIAL;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- *sn = *(rt_uint64_t *)&mbox[5];
-
- return 0;
-}
-
-int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_ARM_MEMORY;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- *base = mbox[5];
- *size = mbox[6];
-
- return 0;
-
-}
-
-int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_HARDWARE_GET_VC_MEMORY;
- mbox[3] = 8; // buffer size
- mbox[4] = 0; // len
-
- mbox[5] = 0;
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- *base = mbox[5];
- *size = mbox[6];
-
- return 0;
-}
-
-int bcm271x_mbox_clock_get_turbo(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_TURBO;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0; // val
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_clock_set_turbo(int level)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_TURBO;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = 0; // id
- mbox[6] = level ? 1 : 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_clock_get_state(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm271x_mbox_clock_set_state(int id, int state)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = state & 0x3;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm271x_mbox_clock_get_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_clock_set_rate(int id, int rate)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = rate;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_clock_get_max_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_MAX_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_clock_get_min_rate(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_CLOCK_GET_MIN_RATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_power_get_state(int id)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_POWER_GET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = id; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm271x_mbox_power_set_state(int id, int state)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_POWER_SET_STATE;
- mbox[3] = 8; // buffer size
- mbox[4] = 8; // len
-
- mbox[5] = id; // id
- mbox[6] = state & 0x3;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != id)
- {
- return -1;
- }
-
- return (mbox[6] & 0x3);
-}
-
-int bcm271x_mbox_temp_get(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_TEMP_GET;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; //id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
-
-int bcm271x_mbox_temp_get_max(void)
-{
- mbox[0] = 8*4; // length of the message
- mbox[1] = MBOX_REQUEST; // this is a request message
-
- mbox[2] = MBOX_TAG_TEMP_GET_MAX;
- mbox[3] = 8; // buffer size
- mbox[4] = 4; // len
-
- mbox[5] = 0; // id
- mbox[6] = 0;
-
- mbox[7] = MBOX_TAG_LAST;
- mbox_call(8, MMU_DISABLE);
-
- if(mbox[5] != 0)
- {
- return -1;
- }
-
- return mbox[6];
-}
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/mbox.h b/bsp/raspberry-pi/raspi4-64/drivers/mbox.h
deleted file mode 100644
index 291cd77cf0..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/mbox.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-09-10 bigmagic first version
- */
-
-#ifndef __MBOX_H__
-#define __MBOX_H__
-
-#include <rtthread.h>
-
-//https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
-//https://github.com/hermanhermitage/videocoreiv
-
-/* a properly aligned buffer */
-extern volatile unsigned int* mbox;
-
-#define MBOX_REQUEST 0
-
-/* channels */
-#define MBOX_CH_POWER 0
-#define MBOX_CH_FB 1
-#define MBOX_CH_VUART 2
-#define MBOX_CH_VCHIQ 3
-#define MBOX_CH_LEDS 4
-#define MBOX_CH_BTNS 5
-#define MBOX_CH_TOUCH 6
-#define MBOX_CH_COUNT 7
-#define MBOX_CH_PROP 8
-
-/* tags */
-#define MBOX_TAG_SETPOWER 0x28001
-#define MBOX_TAG_SETCLKRATE 0x38002
-#define MBOX_GET_MAC_ADDRESS 0x10003
-#define MBOX_TAG_LAST 0
-
-#define MMIO_BASE 0xFE000000
-#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
-extern size_t videocore_mbox;
-#define MBOX_READ ((volatile unsigned int*)(videocore_mbox+0x0))
-#define MBOX_POLL ((volatile unsigned int*)(videocore_mbox+0x10))
-#define MBOX_SENDER ((volatile unsigned int*)(videocore_mbox+0x14))
-#define MBOX_STATUS ((volatile unsigned int*)(videocore_mbox+0x18))
-#define MBOX_CONFIG ((volatile unsigned int*)(videocore_mbox+0x1C))
-#define MBOX_WRITE ((volatile unsigned int*)(videocore_mbox+0x20))
-#define MBOX_RESPONSE 0x80000000
-#define MBOX_FULL 0x80000000
-#define MBOX_EMPTY 0x40000000
-
-#define DEVICE_ID_SD_CARD (0)
-#define DEVICE_ID_USB_HCD (3)
-#define POWER_STATE_OFF (0 << 0)
-#define POWER_STATE_ON (1 << 0)
-#define POWER_STATE_WAIT (1 << 1)
-#define POWER_STATE_NO_DEVICE (1 << 1) // in response
-#define MMU_ENABLE (1)
-#define MMU_DISABLE (0)
-
-/*
- * raspi hardware info
- */
-enum {
- MBOX_TAG_HARDWARE_GET_MODEL = 0x00010001,
- MBOX_TAG_HARDWARE_GET_REV = 0x00010002,
- MBOX_TAG_HARDWARE_GET_MAC_ADDRESS = 0x00010003,
- MBOX_TAG_HARDWARE_GET_SERIAL = 0x00010004,
- MBOX_TAG_HARDWARE_GET_ARM_MEMORY = 0x00010005,
- MBOX_TAG_HARDWARE_GET_VC_MEMORY = 0x00010006,
- MBOX_TAG_HARDWARE_GET_CLOCKS = 0x00010007,
-};
-
-/*
- * raspi clock
- */
-enum {
- MBOX_TAG_CLOCK_GET_TURBO = 0x00030009,
- MBOX_TAG_CLOCK_SET_TURBO = 0x00038009,
- MBOX_TAG_CLOCK_GET_STATE = 0x00030001,
- MBOX_TAG_CLOCK_SET_STATE = 0x00038001,
- MBOX_TAG_CLOCK_GET_RATE = 0x00030002,
- MBOX_TAG_CLOCK_SET_RATE = 0x00038002,
- MBOX_TAG_CLOCK_GET_MAX_RATE = 0x00030004,
- MBOX_TAG_CLOCK_GET_MIN_RATE = 0x00030007,
-};
-
-/*
- * raspi power
- */
-enum {
- MBOX_TAG_POWER_GET_STATE = 0x00020001,
- MBOX_TAG_POWER_SET_STATE = 0x00028001,
-};
-
-/*
- * raspi temperature
- */
-enum {
- MBOX_TAG_TEMP_GET = 0x00030006,
- MBOX_TAG_TEMP_GET_MAX = 0x0003000A,
-};
-
-/*
- * raspi Memory
- */
-enum {
- MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle)
- MBOX_TAG_LOCK_MEMORY = 0x0003000D, // Memory: Unlock Buffer (Response: Status)
- MBOX_TAG_UNLOCK_MEMORY = 0x0003000E, // Memory: Unlock Buffer (Response: Status)
- MBOX_TAG_RELEASE_MEMORY = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status)
- MBOX_TAG_EXECUTE_CODE = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given
-};
-
-/*
- * raspi GPU
- */
-enum {
- MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given (Response: Number Of QPUs, Control, No Flush, Timeout In ms)
- MBOX_TAG_ENABLE_QPU = 0x00030012, // QPU: Enables The QPU (Response: Enable State)
-};
-
-/*
- * raspi HDMI
- */
-#define MBOX_TAG_GET_EDID_BLOCK 0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device (Response: Block Number, Status, EDID Block (128 Bytes))
-
-/*
- * raspi NOTIFY
- */
-#define MBOX_TAG_NOTIFY_REBOOT 0x00030048
-#define MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058
-
-/*
-* touch
-*/
-#define MBOX_TAG_GET_TOUCHBUF (0x0004000F)
-
-#define MBOX_ADDR 0x08000000
-extern size_t mbox_addr;
-
-#define RES_CLK_ID (0x000000000)
-#define EMMC_CLK_ID (0x000000001)
-#define UART_CLK_ID (0x000000002)
-#define ARM_CLK_ID (0x000000003)
-#define CORE_CLK_ID (0x000000004)
-#define V3D_CLK_ID (0x000000005)
-#define H264_CLK_ID (0x000000006)
-#define ISP_CLK_ID (0x000000007)
-#define SDRAM_CLK_ID (0x000000008)
-#define PIXEL_CLK_ID (0x000000009)
-#define PWM_CLK_ID (0x00000000a)
-
-int mbox_call(unsigned char ch, int mmu_enable);
-int bcm271x_mbox_get_touch(void);
-int bcm271x_notify_reboot(void);
-int bcm271x_notify_xhci_reset(void);
-int bcm271x_gpu_enable(void);
-int bcm271x_mbox_hardware_get_model(void);
-int bcm271x_mbox_hardware_get_revison(void);
-int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac);
-int bcm271x_mbox_hardware_get_serial(rt_uint64_t* sn);
-int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t * base, rt_uint32_t * size);
-int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t * base, rt_uint32_t * size);
-int bcm271x_mbox_clock_get_turbo(void);
-int bcm271x_mbox_clock_set_turbo(int level);
-int bcm271x_mbox_clock_get_state(int id);
-int bcm271x_mbox_clock_set_state(int id, int state);
-int bcm271x_mbox_clock_get_rate(int id);
-int bcm271x_mbox_clock_set_rate(int id, int rate);
-int bcm271x_mbox_clock_get_max_rate(int id);
-int bcm271x_mbox_clock_get_min_rate(int id);
-int bcm271x_mbox_power_get_state(int id);
-int bcm271x_mbox_power_set_state(int id, int state);
-int bcm271x_mbox_temp_get(void);
-int bcm271x_mbox_temp_get_max(void);
-
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h b/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h
deleted file mode 100644
index 64b40d3753..0000000000
--- a/bsp/raspberry-pi/raspi4-64/drivers/raspi4.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-02-06 RT-Thread first version
- */
-#ifndef __RASPI4_H__
-#define __RASPI4_H__
-
-#include <rtthread.h>
-
-//https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
-
-#define __REG32(x) (*((volatile unsigned int *)(x)))
-#define __REG16(x) (*((volatile unsigned short *)(x)))
-
-/* GIC IRQ MAX */
-#define MAX_HANDLERS (256)
-
-/* base address */
-#define PER_BASE (0xFE000000)
-
-//gpio offset
-#define GPIO_BASE_OFFSET (0x00200000)
-
-
-#define PL011_UART_BASE_OFFSET (0x00201000)
-//pl011 offset
-#define PL011_UART0_BASE_OFFSET (0x00201000)
-#define PL011_UART2_BASE_OFFSET (0x00201400)
-#define PL011_UART3_BASE_OFFSET (0x00201600)
-#define PL011_UART4_BASE_OFFSET (0x00201800)
-#define PL011_UART5_BASE_OFFSET (0x00201A00)
-
-//pactl cs offset
-#define PACTL_CS_OFFSET (0x00204E00)
-
-//aux offset
-#define AUX_BASE_OFFSET (0x00215000)
-
-/* GPIO */
-#define GPIO_BASE_ADDR (PER_BASE + GPIO_BASE_OFFSET)
-extern size_t gpio_base_addr;
-#define GPIO_BASE (gpio_base_addr)
-#define GPIO_IRQ_NUM (3) //40 pin mode
-#define IRQ_GPIO0 (96 + 49) //bank0 (0 to 27)
-#define IRQ_GPIO1 (96 + 50) //bank1 (28 to 45)
-#define IRQ_GPIO2 (96 + 51) //bank2 (46 to 57)
-#define IRQ_GPIO3 (96 + 52) //bank3
-
-/* Timer (ARM side) */
-#define ARM_TIMER_IRQ (64)
-extern size_t arm_timer_base;
-#define ARM_TIMER_BASE (PER_BASE + 0xB000)
-#define ARM_TIMER_LOAD HWREG32(arm_timer_base + 0x400)
-#define ARM_TIMER_VALUE HWREG32(arm_timer_base + 0x404)
-#define ARM_TIMER_CTRL HWREG32(arm_timer_base + 0x408)
-#define ARM_TIMER_IRQCLR HWREG32(arm_timer_base + 0x40C)
-#define ARM_TIMER_RAWIRQ HWREG32(arm_timer_base + 0x410)
-#define ARM_TIMER_MASKIRQ HWREG32(arm_timer_base + 0x414)
-#define ARM_TIMER_RELOAD HWREG32(arm_timer_base + 0x418)
-#define ARM_TIMER_PREDIV HWREG32(arm_timer_base + 0x41C)
-#define ARM_TIMER_CNTR HWREG32(arm_timer_base + 0x420)
-
-/* UART PL011 */
-#define UART_BASE (PER_BASE + PL011_UART_BASE_OFFSET)
-//extern uint32_t uart_base_addr;
-#define UART0_BASE (UART_BASE + 0x0)
-#define UART2_BASE (UART_BASE + 0x400)
-#define UART3_BASE (UART_BASE + 0x600)
-#define UART4_BASE (UART_BASE + 0x800)
-#define UART5_BASE (UART_BASE + 0xA00)
-#define IRQ_AUX_UART (96 + 29)
-#define UART_REFERENCE_CLOCK (48000000)
-
-/* AUX */
-//#define AUX_BASE_ADDR (PER_BASE + AUX_BASE_OFFSET)
-//extern uint32_t aux_addr;
-//#define AUX_BASE (aux_addr + 0x0)
-
-#define AUX_BASE (PER_BASE + AUX_BASE_OFFSET)
-#define IRQ_PL011 (96 + 57)
-
-/* Peripheral IRQ OR-ing */
-#define PACTL_CS_ADDR (PER_BASE + PACTL_CS_OFFSET)
-extern size_t pactl_cs_base;
-#define PACTL_CS HWREG32(pactl_cs_base)
-typedef enum
-{
- IRQ_SPI0 = 0x00000000,
- IRQ_SPI1 = 0x00000002,
- IRQ_SPI2 = 0x00000004,
- IRQ_SPI3 = 0x00000008,
- IRQ_SPI4 = 0x00000010,
- IRQ_SPI5 = 0x00000020,
- IRQ_SPI6 = 0x00000040,
- IRQ_I2C0 = 0x00000100,
- IRQ_I2C1 = 0x00000200,
- IRQ_I2C2 = 0x00000400,
- IRQ_I2C3 = 0x00000800,
- IRQ_I2C4 = 0x00001000,
- IRQ_I2C5 = 0x00002000,
- IRQ_I2C6 = 0x00004000,
- IRQ_I2C7 = 0x00008000,
- IRQ_UART5 = 0x00010000,
- IRQ_UART4 = 0x00020000,
- IRQ_UART3 = 0x00040000,
- IRQ_UART2 = 0x00080000,
- IRQ_UART0 = 0x00100000
-} PACTL_CS_VAL;
-
-// 0x40, 0x44, 0x48, 0x4c: Core 0~3 Timers interrupt control
-#define CORE0_TIMER_IRQ_CTRL HWREG32(0xFF800040)
-#define TIMER_IRQ 30
-#define NON_SECURE_TIMER_IRQ (1 << 1)
-
-/* GIC */
-#define INTC_BASE (0xff800000)
-#define ARM_GIC_NR_IRQS (512)
-#define ARM_GIC_MAX_NR (512)
-#define GIC_V2_BASE (INTC_BASE + 0x00040000)
-extern size_t gic_base_addr;
-#define GIC_V2_DISTRIBUTOR_BASE (gic_base_addr + 0x1000)
-#define GIC_V2_CPU_INTERFACE_BASE (gic_base_addr + 0x2000)
-#define GIC_V2_HYPERVISOR_BASE (gic_base_addr + 0x4000)
-#define GIC_V2_VIRTUAL_CPU_BASE (gic_base_addr + 0x6000)
-
-#define GIC_PL400_DISTRIBUTOR_PPTR GIC_V2_DISTRIBUTOR_BASE
-#define GIC_PL400_CONTROLLER_PPTR GIC_V2_CPU_INTERFACE_BASE
-
-#define GIC_IRQ_START 0
-
-#define GIC_ACK_INTID_MASK 0x000003ff
-
-
-//watchdog
-#define WDT_BASE (PER_BASE + 0x00100000)
-extern size_t wdt_base_addr;
-#define PM_RSTC HWREG32(wdt_base_addr + 0x1c)
-#define PM_RSTS HWREG32(wdt_base_addr + 0x20)
-#define PM_WDOG HWREG32(wdt_base_addr + 0x24)
-
-#define PM_PASSWORD (0x5A000000)
-#define PM_WDOG_TIME_SET (0x000fffff)
-#define PM_RSTS_HADWRH_SET (0x00000040)
-#define PM_RSTC_WRCFG_FULL_RESET (0x00000020)
-#define PM_RSTC_WRCFG_CLR (0xffffffcf)
-#define PM_RSTC_RESET (0x00000102)
-
-//timer
-#define ST_BASE_OFFSET (0x003000)
-#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET)
-extern size_t stimer_base_addr;
-#define STIMER_CS __REG32(stimer_base_addr + 0x0000)
-#define STIMER_CLO __REG32(stimer_base_addr + 0x0004)
-#define STIMER_CHI __REG32(stimer_base_addr + 0x0008)
-#define STIMER_C0 __REG32(stimer_base_addr + 0x000C)
-#define STIMER_C1 __REG32(stimer_base_addr + 0x0010)
-#define STIMER_C2 __REG32(stimer_base_addr + 0x0014)
-#define STIMER_C3 __REG32(stimer_base_addr + 0x0018)
-
-#define DELAY_MICROS(micros) \
- do{ \
- rt_uint32_t compare = STIMER_CLO + micros * 25; \
- while (STIMER_CLO < compare); \
- } while (0)
-
-//External Mass Media Controller (SD Card)
-#define MMC0_BASE_ADDR (PER_BASE+0x300000)
-extern size_t mmc0_base_addr;
-#define MMC2_BASE_ADDR (PER_BASE+0x340000)
-extern size_t mmc2_base_addr;
-
-//mac
-#define MAC_REG (void *)(0xfd580000)
-extern uint8_t * mac_reg_base_addr;
-
-#define ETH_IRQ (160+29)
-
-#define SEND_DATA_NO_CACHE (0x08200000)
-extern uint8_t * eth_send_no_cache;
-
-#define RECV_DATA_NO_CACHE (0x08400000)
-extern uint8_t * eth_recv_no_cache;
-
-/* the basic constants and interfaces needed by gic */
-rt_inline size_t platform_get_gic_dist_base(void)
-{
- return GIC_PL400_DISTRIBUTOR_PPTR;
-}
-
-rt_inline size_t platform_get_gic_cpu_base(void)
-{
- return GIC_PL400_CONTROLLER_PPTR;
-}
-
-#endif
diff --git a/bsp/raspberry-pi/raspi4-64/qemu.py b/bsp/raspberry-pi/raspi4-64/qemu.py
new file mode 100755
index 0000000000..247119f25d
--- /dev/null
+++ b/bsp/raspberry-pi/raspi4-64/qemu.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import os, sys, re, shutil
+
+if os.getenv('RTT_QEMU_ROOT'):
+ RTT_QEMU_ROOT = os.getenv('RTT_QEMU_ROOT')
+else:
+ RTT_QEMU_ROOT = ""
+
+if os.getenv('RTT_ROOT'):
+ RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+ RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
+
+sys.path.append(RTT_ROOT + '/tools')
+
+from building import *
+import dtc
+
+dts_name = "bcm2711-rpi-4-b"
+
+dtc.dts_to_dtb(RTT_ROOT, ["../dm/dts/" + dts_name + ".dts"], include_paths = [os.getcwd() + '/../dm/include'],
+ ignore_warning = ["simple_bus_reg", "unit_address_vs_reg", "clocks_is_cell", "gpios_property"])
+try:
+ shutil.move("../dm/dts/" + dts_name + ".dtb", dts_name + ".dtb")
+except:
+ exit(-1)
+
+opt = sys.argv
+
+q_graphic = "-nographic"
+q_debug = ""
+
+def is_opt(key, inkey):
+ if str("-" + key) == inkey:
+ return True
+ return False
+
+for i in range(len(opt)):
+ if i == 0:
+ continue
+ inkey = opt[i]
+
+ if is_opt("debug", inkey): q_debug = "-S -s"
+ if is_opt("graphic", inkey): q_graphic = "-usb -device usb-mouse -device usb-kbd"
+
+disk = "sd.qcow2"
+if not os.path.exists(disk):
+ os.system("qemu-img create -f qcow2 {} 64M".format(disk))
+
+flash = "flash.bin"
+if not os.path.exists(flash):
+ os.system("qemu-img create -f raw {} 1M".format(flash))
+
+os.system("""
+{}qemu-system-aarch64 \
+ -M raspi4b \
+ -m 2G \
+ -kernel rtthread.bin \
+ -dtb {}.dtb \
+ -append "console=ttyAMA0 earlycon=pl011,0xfe201000 cma=8M coherent_pool=2M root=sd0p0 rootfstype=elm rootwait rw" \
+ -serial mon:stdio \
+ -drive if=sd,file={},format=qcow2 \
+ -device ds1338,address=0x68,bus=i2c-bus.0 \
+ -device m25p80,write-enable=true,drive=flash0,bus=spi \
+ -blockdev node-name=flash0,driver=file,filename={} \
+ -device usb-net,netdev=net0 -netdev user,id=net0 \
+ {} \
+ {}
+""".format(RTT_QEMU_ROOT, dts_name, disk, flash, q_graphic, q_debug))
diff --git a/bsp/raspberry-pi/raspi4-64/rtconfig.h b/bsp/raspberry-pi/raspi4-64/rtconfig.h
index 03c771e6b3..deaa70e437 100644
--- a/bsp/raspberry-pi/raspi4-64/rtconfig.h
+++ b/bsp/raspberry-pi/raspi4-64/rtconfig.h
@@ -8,16 +8,6 @@
/* rt_vsnprintf options */
#define RT_KLIBC_USING_VSNPRINTF_LONGLONG
-#define RT_KLIBC_USING_VSNPRINTF_STANDARD
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6
-#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
-#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4
/* end of rt_vsnprintf options */
/* rt_vsscanf options */
@@ -72,7 +62,7 @@
/* end of rt_strnlen options */
/* end of klibc options */
-#define RT_NAME_MAX 12
+#define RT_NAME_MAX 24
#define RT_USING_SMP
#define RT_CPUS_NR 4
#define RT_ALIGN_SIZE 4
@@ -89,6 +79,8 @@
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 8192
+#define RT_USING_CPU_USAGE_TRACER
+#define RT_CPU_USAGE_CALC_INTERVAL_MS 200
/* kservice options */
@@ -109,6 +101,7 @@
/* Memory Management */
+#define RT_USING_MEMPOOL
#define RT_USING_SLAB
#define RT_USING_SLAB_AS_HEAP
#define RT_USING_HEAP
@@ -127,10 +120,11 @@
/* AArch64 Architecture Configuration */
-#define ARCH_TEXT_OFFSET 0x200000
+#define ARCH_TEXT_OFFSET 0x208000
#define ARCH_RAM_OFFSET 0
#define ARCH_SECONDARY_CPU_STACK_SIZE 4096
#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#define ARCH_USING_GENERIC_CPUID
#define ARCH_HEAP_SIZE 0x4000000
#define ARCH_INIT_PAGE_SIZE 0x200000
/* end of AArch64 Architecture Configuration */
@@ -142,13 +136,14 @@
#define ARCH_ARM_MMU
#define ARCH_ARMV8
#define ARCH_USING_ASID
+#define ARCH_USING_HW_THREAD_SELF
#define ARCH_USING_IRQ_CTX_LIST
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
-#define RT_MAIN_THREAD_STACK_SIZE 8192
+#define RT_MAIN_THREAD_STACK_SIZE 16384
#define RT_MAIN_THREAD_PRIORITY 10
#define RT_USING_MSH
#define RT_USING_FINSH
@@ -194,6 +189,7 @@
/* Device Drivers */
+#define RT_USING_DM
#define RT_USING_DEV_BUS
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
@@ -204,25 +200,86 @@
#define RT_USING_SERIAL_V1
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
+#define RT_USING_SERIAL_BYPASS
+#define RT_SERIAL_PL011
+#define RT_SERIAL_8250
+#define RT_SERIAL_8250_BCM2835AUX
#define RT_USING_CLOCK_TIME
+#define RT_CLOCK_TIME_ARM_ARCH
+#define RT_CLOCK_TIME_BCM2835
+#define RT_USING_ETHERNET
+#define RT_ETHERNET_BCMGENET
#define RT_USING_I2C
-#define RT_USING_I2C_BITOPS
+#define RT_I2C_BCM2835
+#define RT_I2C_BRCMSTB
+#define RT_USING_PHY_V2
+#define RT_PHY_MDIO_BCM_UNIMAC
+#define RT_PHY_BCM54213
#define RT_USING_NULL
#define RT_USING_ZERO
#define RT_USING_RANDOM
+#define RT_USING_PWM
+#define RT_PWM_BCM2835
+#define RT_PWM_BRCMSTB
#define RT_USING_RTC
-#define RT_USING_SOFT_RTC
+#define RT_USING_ALARM
+#define RT_ALARM_STACK_SIZE 8192
+#define RT_ALARM_TIMESLICE 5
+#define RT_ALARM_PRIORITY 10
+#define RT_RTC_DS1307
#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 8192
#define RT_SDIO_THREAD_PRIORITY 15
-#define RT_MMCSD_STACK_SIZE 8192
+#define RT_MMCSD_STACK_SIZE 16384
#define RT_MMCSD_THREAD_PRIORITY 22
#define RT_MMCSD_MAX_PARTITION 16
+#define RT_USING_SDHCI
+#define RT_SDIO_SDHCI_BRCMSTB
+#define RT_SDIO_SDHCI_IPROC
#define RT_USING_SPI
#define RT_USING_SPI_ISR
+#define RT_SPI_BCM2835
+#define RT_SPI_BCM2835AUX
#define RT_USING_WDT
+#define RT_WDT_BCM2835
+#define RT_USING_AUDIO
+#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096
+#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2
+#define RT_AUDIO_RECORD_PIPE_SIZE 2048
+#define RT_AUDIO_BCM2835_I2S
#define RT_USING_TOUCH
#define RT_USING_LCD
+#define RT_USING_GRAPHIC
+#define RT_GRAPHIC_BACKLIGHT
+#define RT_GRAPHIC_BACKLIGHT_RPI
+#define RT_GRAPHIC_FB
+#define RT_GRAPHIC_FB_ILI9486
+#define RT_GRAPHIC_FB_SIMPLE
+#define RT_GRAPHIC_FB_BCM2708
+#define RT_GRAPHIC_FB_RPISENSE
+#define RT_GRAPHIC_LOGO
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH "../dm/graphic/logo/logo-raspi-clut224.ppm"
+#define RT_USING_HWCRYPTO
+#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto"
+#define RT_HWCRYPTO_IV_MAX_SIZE 16
+#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256
+#define RT_HWCRYPTO_USING_RNG
+#define RT_HWCRYPTO_RNG_BCM2835
+#define RT_HWCRYPTO_RNG_IPROC_RNG200
+#define RT_USING_LED
+#define RT_LED_GPIO
+#define RT_USING_INPUT
+#define RT_INPUT_POWER
+#define RT_INPUT_JOYSTICK
+#define RT_INPUT_JOYSTICK_RPISENSE
+#define RT_INPUT_TOUCHSCREEN
+#define RT_INPUT_TOUCHSCREEN_ADS7846
+#define RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW
+#define RT_USING_MBOX
+#define RT_MBOX_BCM2835
+#define RT_USING_PHYE
+#define RT_PHYE_GENERIC_USB
#define RT_USING_BLK
/* Partition Types */
@@ -230,7 +287,88 @@
#define RT_BLK_PARTITION_DFS
#define RT_BLK_PARTITION_EFI
/* end of Partition Types */
+#define RT_USING_SCSI
+#define RT_SCSI_SD
+#define RT_USING_FIRMWARE
+#define RT_FIRMWARE_RASPBERRYPI
+#define RT_USING_DVFS
+#define RT_USING_DVFS_EVENT
+#define RT_USING_DVFS_OPP_RETRY_MAX 10
+
+/* DVFS Event Drivers */
+
+/* DVFS CPUfreq Drivers */
+
+#define RT_DVFS_RASPBERRY_CPUFREQ
+
+/* DVFS Devfreq Drivers */
+
+#define RT_USING_REGULATOR
+#define RT_REGULATOR_FIXED
+#define RT_REGULATOR_GPIO
+#define RT_USING_RESET
+#define RT_RESET_SIMPLE
+#define RT_RESET_BRCMSTB_RESCAL
+#define RT_RESET_BRCMSTB
+#define RT_RESET_RASPBERRYPI
+
+/* Power Management (PM) Domains device drivers */
+
+#define RT_PMDOMAIN_RASPBERRYPI
+/* end of Power Management (PM) Domains device drivers */
+#define RT_USING_THERMAL
+
+/* Thermal Sensors Drivers */
+
+#define RT_THERMAL_BCM2835
+#define RT_THERMAL_BCM2711
+
+/* Thermal Cool Drivers */
+
+#define RT_USING_NVMEM
+#define RT_NVMEM_RASPBERRYPI_OTP
+#define RT_USING_DMA
+#define RT_DMA_BCM2835
+#define RT_USING_MFD
+#define RT_MFD_SYSCON
+#define RT_MFD_BCM2835_PM
+#define RT_MFD_RPI_SENSE
+#define RT_USING_OFW
+#define RT_FDT_EARLYCON_MSG_SIZE 128
+#define RT_USING_OFW_BUS_RANGES_NUMBER 8
+#define RT_USING_PCI
+#define RT_PCI_MSI
+#define RT_PCI_SYS_64BIT
+#define RT_PCI_CACHE_LINE_SIZE 8
+
+/* PCI Device Drivers */
+
+#define RT_PCI_ECAM
+#define RT_PCI_HOST_COMMON
+#define RT_PCI_HOST_GENERIC
+#define RT_PCIE_BRCMSTB
+#define RT_USING_PIC
+#define MAX_HANDLERS 512
+#define RT_PIC_ARM_GIC
+#define RT_PIC_ARM_GIC_MAX_NR 1
+#define RT_PIC_BCM2835_INTC
+#define RT_PIC_BCM2836_L1_INTC
+#define RT_PIC_BRCMSTB_L2_IRQ
#define RT_USING_PIN
+#define RT_PIN_BCM_VIRT
+#define RT_PIN_BRCMSTB
+#define RT_PIN_RASPBERRYPI_EXP
+#define RT_USING_PINCTRL
+#define RT_PINCTRL_BCM2835
+#define RT_USING_CLK
+#define RT_CLK_BCM2711_DVP
+#define RT_CLK_BCM2835
+#define RT_CLK_RASPBERRYPI
+
+/* SoC (System on Chip) Drivers */
+
+#define RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR
+/* end of SoC (System on Chip) Drivers */
/* end of Device Drivers */
/* C/C++ and POSIX layer */
@@ -354,6 +492,8 @@
#define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000
#define RT_PAGE_MAX_ORDER 11
+#define RT_USING_MEMBLOCK
+#define RT_INIT_MEMORY_REGIONS 128
/* Debugging */
@@ -490,14 +630,6 @@
/* GD32 Drivers */
/* end of GD32 Drivers */
-
-/* HPMicro SDK */
-
-/* end of HPMicro SDK */
-
-/* FT32 HAL & SDK Drivers */
-
-/* end of FT32 HAL & SDK Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
@@ -577,30 +709,6 @@
/* end of Arduino libraries */
/* end of RT-Thread online packages */
-#define BCM2711_SOC
-#define BSP_SUPPORT_FPU
-
-/* Hardware Drivers Config */
-
-/* BCM Peripheral Drivers */
-
-#define BSP_USING_UART
-#define RT_USING_UART0
-#define RT_USING_UART3
-#define RT_USING_UART4
-#define BSP_USING_GIC
-#define BSP_USING_GICV2
-#define BSP_USING_PIN
-#define BSP_USING_CORETIMER
-#define BSP_USING_WDT
-#define BSP_USING_SDIO
-#define BSP_USING_SDIO0
-/* end of BCM Peripheral Drivers */
-
-/* Board Peripheral Drivers */
-
-#define BSP_USING_HDMI
-/* end of Board Peripheral Drivers */
-/* end of Hardware Drivers Config */
+#define SOC_BCM2711
#endif
diff --git a/bsp/raspberry-pi/raspi4-64/rtconfig.py b/bsp/raspberry-pi/raspi4-64/rtconfig.py
index 17edd896c5..f15aa8b502 100644
--- a/bsp/raspberry-pi/raspi4-64/rtconfig.py
+++ b/bsp/raspberry-pi/raspi4-64/rtconfig.py
@@ -25,7 +25,8 @@ if PLATFORM == 'gcc':
# toolchains
PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
CC = PREFIX + 'gcc'
- CPP = PREFIX + 'g++'
+ CXX = PREFIX + 'g++'
+ CPP = PREFIX + 'cpp'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
@@ -34,8 +35,8 @@ if PLATFORM == 'gcc':
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
- DEVICE = ' -march=armv8-a -mtune=cortex-a72'
- CPPFLAGS = ' -E -P -x assembler-with-cpp'
+ DEVICE = ' -march=armv8-a -mtune=cortex-a72 -fdiagnostics-color=always -ftree-vectorize -ffast-math -funwind-tables -fno-strict-aliasing'
+ CPPFLAGS = ' -nostdinc -undef -E -P -x assembler-with-cpp'
CFLAGS = DEVICE + ' -Wall -Wno-cpp -D_POSIX_SOURCE'
AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
@@ -52,3 +53,10 @@ if PLATFORM == 'gcc':
DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
+
+
+def dist_handle(BSP_ROOT, dist_dir):
+ import sys
+ sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
+ from sdk_dist import dist_do_building
+ dist_do_building(BSP_ROOT, dist_dir)
diff --git a/bsp/raspberry-pi/raspi-dm2.0/.config b/bsp/raspberry-pi/raspi5/.config
index 0988715951..c272203b32 100644
--- a/bsp/raspberry-pi/raspi-dm2.0/.config
+++ b/bsp/raspberry-pi/raspi5/.config
@@ -12,17 +12,7 @@
#
# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set
CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y
-CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y
-# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set
-CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32
-CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6
-CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9
-CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
+# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set
# end of rt_vsnprintf options
#
@@ -116,30 +106,30 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4
# end of rt_strnlen options
# end of klibc options
-CONFIG_RT_NAME_MAX=12
+CONFIG_RT_NAME_MAX=24
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_NANO is not set
CONFIG_RT_USING_SMART=y
# CONFIG_RT_USING_AMP is not set
CONFIG_RT_USING_SMP=y
CONFIG_RT_CPUS_NR=4
-CONFIG_RT_ALIGN_SIZE=4
+CONFIG_RT_ALIGN_SIZE=8
# CONFIG_RT_THREAD_PRIORITY_8 is not set
CONFIG_RT_THREAD_PRIORITY_32=y
# CONFIG_RT_THREAD_PRIORITY_256 is not set
CONFIG_RT_THREAD_PRIORITY_MAX=32
-CONFIG_RT_TICK_PER_SECOND=1000
+CONFIG_RT_TICK_PER_SECOND=100
CONFIG_RT_USING_OVERFLOW_CHECK=y
CONFIG_RT_USING_HOOK=y
CONFIG_RT_HOOK_USING_FUNC_PTR=y
# CONFIG_RT_USING_HOOKLIST is not set
CONFIG_RT_USING_IDLE_HOOK=y
CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
-CONFIG_IDLE_THREAD_STACK_SIZE=16384
-CONFIG_SYSTEM_THREAD_STACK_SIZE=16384
+CONFIG_IDLE_THREAD_STACK_SIZE=8192
+CONFIG_SYSTEM_THREAD_STACK_SIZE=8192
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
-CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384
+CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192
# CONFIG_RT_USING_TIMER_ALL_SOFT is not set
CONFIG_RT_USING_CPU_USAGE_TRACER=y
CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200
@@ -151,12 +141,12 @@ CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200
# end of kservice options
CONFIG_RT_USING_DEBUG=y
-# CONFIG_RT_DEBUGING_ASSERT is not set
+CONFIG_RT_DEBUGING_ASSERT=y
CONFIG_RT_DEBUGING_COLOR=y
CONFIG_RT_DEBUGING_CONTEXT=y
# CONFIG_RT_DEBUGING_AUTO_INIT is not set
# CONFIG_RT_DEBUGING_SPINLOCK is not set
-# CONFIG_RT_DEBUGING_CRITICAL is not set
+CONFIG_RT_DEBUGING_CRITICAL=y
# CONFIG_RT_USING_CI_ACTION is not set
#
@@ -174,27 +164,29 @@ CONFIG_RT_USING_MESSAGEQUEUE=y
#
# Memory Management
#
-# CONFIG_RT_USING_MEMPOOL is not set
+CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_SMALL_MEM is not set
CONFIG_RT_USING_SLAB=y
-# CONFIG_RT_USING_MEMHEAP is not set
+CONFIG_RT_USING_MEMHEAP=y
+CONFIG_RT_MEMHEAP_FAST_MODE=y
+# CONFIG_RT_MEMHEAP_BEST_MODE is not set
# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set
# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
CONFIG_RT_USING_SLAB_AS_HEAP=y
# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_NOHEAP is not set
# CONFIG_RT_USING_MEMTRACE is not set
-# CONFIG_RT_USING_HEAP_ISR is not set
+CONFIG_RT_USING_HEAP_ISR=y
CONFIG_RT_USING_HEAP=y
# end of Memory Management
CONFIG_RT_USING_DEVICE=y
CONFIG_RT_USING_DEVICE_OPS=y
CONFIG_RT_USING_INTERRUPT_INFO=y
-# CONFIG_RT_USING_THREADSAFE_PRINTF is not set
+CONFIG_RT_USING_THREADSAFE_PRINTF=y
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=256
-CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart10"
CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y
CONFIG_RT_VER_NUM=0x50300
CONFIG_RT_USING_STDC_ATOMIC=y
@@ -204,13 +196,14 @@ CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
#
# AArch64 Architecture Configuration
#
-CONFIG_ARCH_TEXT_OFFSET=0x200000
-CONFIG_ARCH_RAM_OFFSET=0x0
-CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=65536
+CONFIG_ARCH_TEXT_OFFSET=0x210000
+CONFIG_ARCH_RAM_OFFSET=0x200000
+CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=4096
CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-# CONFIG_ARCH_USING_GENERIC_CPUID is not set
+CONFIG_ARCH_USING_GENERIC_CPUID=y
CONFIG_ARCH_HEAP_SIZE=0x4000000
CONFIG_ARCH_INIT_PAGE_SIZE=0x200000
+# CONFIG_ARCH_USING_CPUIDLE is not set
# end of AArch64 Architecture Configuration
CONFIG_ARCH_CPU_64BIT=y
@@ -222,6 +215,7 @@ CONFIG_ARCH_ARM_MMU=y
CONFIG_KERNEL_VADDR_START=0xffff000000000000
CONFIG_ARCH_ARMV8=y
CONFIG_ARCH_USING_ASID=y
+CONFIG_ARCH_USING_HW_THREAD_SELF=y
CONFIG_ARCH_USING_IRQ_CTX_LIST=y
#
@@ -239,11 +233,11 @@ CONFIG_FINSH_THREAD_NAME="tshell"
CONFIG_FINSH_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=8192
CONFIG_FINSH_USING_HISTORY=y
-CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_HISTORY_LINES=10
# CONFIG_FINSH_USING_WORD_OPERATION is not set
# CONFIG_FINSH_USING_FUNC_EXT is not set
CONFIG_FINSH_USING_SYMTAB=y
-CONFIG_FINSH_CMD_SIZE=80
+CONFIG_FINSH_CMD_SIZE=256
CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
CONFIG_FINSH_USING_DESCRIPTION=y
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
@@ -257,7 +251,7 @@ CONFIG_FINSH_USING_OPTION_COMPLETION=y
CONFIG_RT_USING_DFS=y
CONFIG_DFS_USING_POSIX=y
CONFIG_DFS_USING_WORKDIR=y
-CONFIG_DFS_FD_MAX=64
+CONFIG_DFS_FD_MAX=32
CONFIG_RT_USING_DFS_V2=y
CONFIG_RT_USING_DFS_ELMFAT=y
@@ -286,11 +280,11 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000
# end of elm-chan's FatFs, Generic FAT Filesystem Module
CONFIG_RT_USING_DFS_DEVFS=y
-# CONFIG_RT_USING_DFS_ROMFS is not set
+CONFIG_RT_USING_DFS_ROMFS=y
CONFIG_RT_USING_DFS_PTYFS=y
-CONFIG_RT_USING_DFS_PROCFS=y
+# CONFIG_RT_USING_DFS_PROCFS is not set
# CONFIG_RT_USING_DFS_CROMFS is not set
-CONFIG_RT_USING_DFS_TMPFS=y
+# CONFIG_RT_USING_DFS_TMPFS is not set
# CONFIG_RT_USING_DFS_MQUEUE is not set
CONFIG_RT_USING_PAGECACHE=y
@@ -316,57 +310,91 @@ CONFIG_RT_USING_DEV_BUS=y
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_UNAMED_PIPE_NUMBER=64
CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
-CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=16384
+CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=8192
CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_USING_SERIAL_V1=y
# CONFIG_RT_USING_SERIAL_V2 is not set
CONFIG_RT_SERIAL_USING_DMA=y
-CONFIG_RT_SERIAL_RB_BUFSZ=64
+CONFIG_RT_SERIAL_RB_BUFSZ=256
CONFIG_RT_USING_SERIAL_BYPASS=y
# CONFIG_RT_SERIAL_EARLY_HVC is not set
-# CONFIG_RT_SERIAL_PL011 is not set
-# CONFIG_RT_SERIAL_8250 is not set
+CONFIG_RT_SERIAL_PL011=y
+CONFIG_RT_SERIAL_8250=y
+# CONFIG_RT_SERIAL_8250_DW is not set
+# CONFIG_RT_SERIAL_8250_PCI is not set
+# CONFIG_RT_SERIAL_VIRTUAL is not set
+CONFIG_RT_SERIAL_8250_BCM2835AUX=y
+CONFIG_RT_SERIAL_8250_BCM7271=y
# CONFIG_RT_USING_CAN is not set
+CONFIG_RT_USING_ADC=y
+# CONFIG_RT_USING_ADC_V2 is not set
+CONFIG_RT_USING_ADC_V1=y
+CONFIG_RT_ADC_RP1=y
CONFIG_RT_USING_CLOCK_TIME=y
-# CONFIG_RT_CLOCK_TIME_ARM_ARCH is not set
+# CONFIG_RT_USING_CLOCK_TIMER_TRIGGER is not set
+CONFIG_RT_CLOCK_TIME_ARM_ARCH=y
+CONFIG_RT_CLOCK_TIME_BCM2835=y
+CONFIG_RT_USING_ETHERNET=y
+CONFIG_RT_ETHERNET_CADENCE=y
+# CONFIG_RT_ETHERNET_CADENCE_PCI is not set
+CONFIG_RT_ETHERNET_CADENCE_PTP=y
+# CONFIG_RT_ETHERNET_DWMAC is not set
+# CONFIG_RT_ETHERNET_BCMGENET is not set
CONFIG_RT_USING_I2C=y
# CONFIG_RT_I2C_DEBUG is not set
CONFIG_RT_USING_I2C_BITOPS=y
# CONFIG_RT_I2C_BITOPS_DEBUG is not set
# CONFIG_RT_USING_SOFT_I2C is not set
+CONFIG_RT_I2C_BCM2835=y
+CONFIG_RT_I2C_BRCMSTB=y
# CONFIG_RT_USING_PHY is not set
-# CONFIG_RT_USING_PHY_V2 is not set
-# CONFIG_RT_USING_ADC is not set
+CONFIG_RT_USING_PHY_V2=y
+# CONFIG_RT_PHY_V2_REALTEK is not set
+# CONFIG_RT_PHY_MDIO_BCM_UNIMAC is not set
+CONFIG_RT_PHY_BCM54213=y
# CONFIG_RT_USING_DAC is not set
CONFIG_RT_USING_NULL=y
CONFIG_RT_USING_ZERO=y
CONFIG_RT_USING_RANDOM=y
-# CONFIG_RT_USING_PWM is not set
+CONFIG_RT_USING_PWM=y
+CONFIG_RT_PWM_BCM2835=y
+CONFIG_RT_PWM_BRCMSTB=y
+CONFIG_RT_PWM_RP1=y
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
CONFIG_RT_USING_RTC=y
-# CONFIG_RT_USING_ALARM is not set
-CONFIG_RT_USING_SOFT_RTC=y
-# CONFIG_RT_RTC_DS1302 is not set
-# CONFIG_RT_RTC_DS1307 is not set
+CONFIG_RT_USING_ALARM=y
+CONFIG_RT_ALARM_STACK_SIZE=8192
+CONFIG_RT_ALARM_TIMESLICE=5
+CONFIG_RT_ALARM_PRIORITY=10
+# CONFIG_RT_ALARM_USING_LOCAL_TIME is not set
+# CONFIG_RT_USING_SOFT_RTC is not set
+CONFIG_RT_RTC_DS1302=y
+CONFIG_RT_RTC_DS1307=y
# CONFIG_RT_RTC_GOLDFISH is not set
# CONFIG_RT_RTC_HYM8563 is not set
-# CONFIG_RT_RTC_PCF8523 is not set
+CONFIG_RT_RTC_PCF8523=y
# CONFIG_RT_RTC_PCF8563 is not set
# CONFIG_RT_RTC_PL031 is not set
# CONFIG_RT_RTC_RX8010 is not set
+CONFIG_RT_RTC_RPI=y
CONFIG_RT_USING_SDIO=y
-CONFIG_RT_SDIO_STACK_SIZE=16384
+CONFIG_RT_SDIO_STACK_SIZE=8192
CONFIG_RT_SDIO_THREAD_PRIORITY=15
CONFIG_RT_MMCSD_STACK_SIZE=8192
CONFIG_RT_MMCSD_THREAD_PRIORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
# CONFIG_RT_SDIO_DEBUG is not set
CONFIG_RT_USING_SDHCI=y
+# CONFIG_RT_SDIO_SDHCI_PCI is not set
+# CONFIG_RT_SDIO_DW_MMC is not set
+# CONFIG_RT_SDIO_SDHCI_DWCMSHC is not set
+CONFIG_RT_SDIO_SDHCI_BRCMSTB=y
+CONFIG_RT_SDIO_SDHCI_IPROC=y
CONFIG_RT_USING_SPI=y
CONFIG_RT_USING_SPI_ISR=y
# CONFIG_RT_USING_SPI_BITOPS is not set
@@ -376,19 +404,86 @@ CONFIG_RT_USING_SPI_ISR=y
# CONFIG_RT_USING_SFUD is not set
# CONFIG_RT_USING_ENC28J60 is not set
# CONFIG_RT_USING_SPI_WIFI is not set
+CONFIG_RT_SPI_BCM2835=y
+CONFIG_RT_SPI_BCM2835AUX=y
CONFIG_RT_USING_WDT=y
-# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_WDT_DW is not set
+# CONFIG_RT_WDT_I6300ESB is not set
+CONFIG_RT_WDT_BCM2835=y
+CONFIG_RT_USING_AUDIO=y
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096
+CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2
+CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048
+# CONFIG_RT_AUDIO_INTEL_HDA is not set
+CONFIG_RT_AUDIO_BCM2835_I2S=y
# CONFIG_RT_USING_SENSOR is not set
CONFIG_RT_USING_TOUCH=y
# CONFIG_RT_TOUCH_PIN_IRQ is not set
-# CONFIG_RT_USING_GRAPHIC is not set
-# CONFIG_RT_USING_HWCRYPTO is not set
+CONFIG_RT_USING_LCD=y
+CONFIG_RT_USING_GRAPHIC=y
+CONFIG_RT_GRAPHIC_BACKLIGHT=y
+# CONFIG_RT_GRAPHIC_BACKLIGHT_GPIO is not set
+# CONFIG_RT_GRAPHIC_BACKLIGHT_PWM is not set
+CONFIG_RT_GRAPHIC_BACKLIGHT_RPI=y
+CONFIG_RT_GRAPHIC_FB=y
+CONFIG_RT_GRAPHIC_FB_ILI9486=y
+CONFIG_RT_GRAPHIC_FB_SIMPLE=y
+CONFIG_RT_GRAPHIC_FB_BCM2708=y
+CONFIG_RT_GRAPHIC_FB_RPISENSE=y
+CONFIG_RT_GRAPHIC_LOGO=y
+# CONFIG_RT_GRAPHIC_LOGO_NONE is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_CLUT224 is not set
+# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_WHITE_CLUT224 is not set
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224=y
+CONFIG_RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH="../dm/graphic/logo/logo-raspi-clut224.ppm"
+CONFIG_RT_USING_HWCRYPTO=y
+CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto"
+CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16
+CONFIG_RT_HWCRYPTO_KEYBIT_MAX_SIZE=256
+# CONFIG_RT_HWCRYPTO_USING_GCM is not set
+# CONFIG_RT_HWCRYPTO_USING_AES is not set
+# CONFIG_RT_HWCRYPTO_USING_DES is not set
+# CONFIG_RT_HWCRYPTO_USING_3DES is not set
+# CONFIG_RT_HWCRYPTO_USING_RC4 is not set
+# CONFIG_RT_HWCRYPTO_USING_MD5 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA1 is not set
+# CONFIG_RT_HWCRYPTO_USING_SHA2 is not set
+CONFIG_RT_HWCRYPTO_USING_RNG=y
+# CONFIG_RT_HWCRYPTO_USING_CRC is not set
+# CONFIG_RT_HWCRYPTO_USING_BIGNUM is not set
+CONFIG_RT_HWCRYPTO_RNG_BCM2835=y
+CONFIG_RT_HWCRYPTO_RNG_IPROC_RNG200=y
# CONFIG_RT_USING_WIFI is not set
-# CONFIG_RT_USING_LED is not set
-# CONFIG_RT_USING_INPUT is not set
-# CONFIG_RT_USING_MBOX is not set
+CONFIG_RT_USING_PTP=y
+CONFIG_RT_USING_LED=y
+CONFIG_RT_LED_GPIO=y
+# CONFIG_RT_LED_PWM is not set
+# CONFIG_RT_LED_SYSCON is not set
+CONFIG_RT_USING_INPUT=y
+CONFIG_RT_INPUT_POWER=y
+# CONFIG_RT_INPUT_UAPI is not set
+CONFIG_RT_INPUT_JOYSTICK=y
+# CONFIG_RT_INPUT_JOYSTICK_ADC is not set
+CONFIG_RT_INPUT_JOYSTICK_RPISENSE=y
+CONFIG_RT_INPUT_KEYBOARD=y
+# CONFIG_RT_INPUT_KEYBOARD_ADC is not set
+CONFIG_RT_INPUT_KEYBOARD_GPIO=y
+# CONFIG_RT_INPUT_MISC is not set
+CONFIG_RT_INPUT_TOUCHSCREEN=y
+CONFIG_RT_INPUT_TOUCHSCREEN_ADS7846=y
+# CONFIG_RT_INPUT_TOUCHSCREEN_GOODIX is not set
+CONFIG_RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW=y
+CONFIG_RT_USING_MBOX=y
+# CONFIG_RT_MBOX_PIC is not set
+CONFIG_RT_MBOX_BCM2835=y
# CONFIG_RT_USING_HWSPINLOCK is not set
-# CONFIG_RT_USING_PHYE is not set
+# CONFIG_RT_USING_RPMSG is not set
+CONFIG_RT_USING_PHYE=y
+CONFIG_RT_PHYE_GENERIC_USB=y
+# CONFIG_RT_USING_ATA is not set
+CONFIG_RT_USING_NVME=y
+CONFIG_RT_USING_NVME_IO_QUEUE=1
+CONFIG_RT_NVME_PCI=y
CONFIG_RT_USING_BLK=y
#
@@ -399,43 +494,125 @@ CONFIG_RT_BLK_PARTITION_EFI=y
# end of Partition Types
# CONFIG_RT_USING_SCSI is not set
-# CONFIG_RT_USING_FIRMWARE is not set
+CONFIG_RT_USING_FIRMWARE=y
+# CONFIG_RT_FIRMWARE_QEMU_FW_CFG is not set
+# CONFIG_RT_FIRMWARE_ARM_SCMI is not set
+CONFIG_RT_FIRMWARE_RASPBERRYPI=y
+# CONFIG_RT_USING_TEE is not set
# CONFIG_RT_USING_HWCACHE is not set
-# CONFIG_RT_USING_REGULATOR is not set
-# CONFIG_RT_USING_RESET is not set
+CONFIG_RT_USING_DVFS=y
+CONFIG_RT_USING_DVFS_EVENT=y
+CONFIG_RT_USING_DVFS_OPP_RETRY_MAX=10
+
+#
+# DVFS Event Drivers
+#
+
+#
+# DVFS CPUfreq Drivers
+#
+CONFIG_RT_DVFS_RASPBERRY_CPUFREQ=y
+
+#
+# DVFS Devfreq Drivers
+#
+CONFIG_RT_USING_REGULATOR=y
+# CONFIG_RT_REGULATOR_FAN53555 is not set
+CONFIG_RT_REGULATOR_FIXED=y
+CONFIG_RT_REGULATOR_GPIO=y
+# CONFIG_RT_REGULATOR_PWM is not set
+CONFIG_RT_USING_RESET=y
+CONFIG_RT_RESET_SIMPLE=y
+CONFIG_RT_RESET_BRCMSTB_RESCAL=y
+CONFIG_RT_RESET_BRCMSTB=y
+CONFIG_RT_RESET_RASPBERRYPI=y
#
# Power Management (PM) Domains device drivers
#
+CONFIG_RT_PMDOMAIN_BCM2835=y
+CONFIG_RT_PMDOMAIN_RASPBERRYPI=y
# end of Power Management (PM) Domains device drivers
# CONFIG_RT_USING_POWER_RESET is not set
# CONFIG_RT_USING_POWER_SUPPLY is not set
-# CONFIG_RT_USING_THERMAL is not set
+CONFIG_RT_USING_THERMAL=y
+
+#
+# Thermal Sensors Drivers
+#
+CONFIG_RT_THERMAL_BCM2835=y
+CONFIG_RT_THERMAL_BCM2711=y
+
+#
+# Thermal Cool Drivers
+#
+CONFIG_RT_THERMAL_COOL_DVFS=y
+# CONFIG_RT_THERMAL_COOL_GPIO_FAN is not set
+CONFIG_RT_THERMAL_COOL_PWM_FAN=y
# CONFIG_RT_USING_VIRTIO is not set
# CONFIG_RT_USING_NVMEM is not set
-# CONFIG_RT_USING_DMA is not set
-# CONFIG_RT_USING_MFD is not set
+CONFIG_RT_USING_DMA=y
+# CONFIG_RT_DMA_PL330 is not set
+CONFIG_RT_DMA_DW_AXI_DMAC=y
+CONFIG_RT_DMA_BCM2835=y
+CONFIG_RT_USING_MFD=y
+# CONFIG_RT_MFD_EDU is not set
+CONFIG_RT_MFD_SYSCON=y
+CONFIG_RT_MFD_BCM2835_PM=y
+CONFIG_RT_MFD_RP1=y
+CONFIG_RT_MFD_RPI_SENSE=y
+# CONFIG_RT_USING_IVSHMEM is not set
CONFIG_RT_USING_OFW=y
# CONFIG_RT_USING_BUILTIN_FDT is not set
CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128
CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8
-# CONFIG_RT_USING_PCI is not set
+CONFIG_RT_USING_PCI=y
+CONFIG_RT_PCI_MSI=y
+# CONFIG_RT_PCI_ENDPOINT is not set
+CONFIG_RT_PCI_SYS_64BIT=y
+CONFIG_RT_PCI_CACHE_LINE_SIZE=8
+# CONFIG_RT_PCI_LOCKLESS is not set
+
+#
+# PCI Device Drivers
+#
+# CONFIG_RT_PCI_ECAM is not set
+# CONFIG_RT_PCI_DW is not set
+CONFIG_RT_PCIE_BRCMSTB=y
CONFIG_RT_USING_PIC=y
# CONFIG_RT_USING_PIC_STATISTICS is not set
-CONFIG_MAX_HANDLERS=256
+CONFIG_MAX_HANDLERS=1024
CONFIG_RT_PIC_ARM_GIC=y
+# CONFIG_RT_PIC_ARM_GIC_V2M is not set
# CONFIG_RT_PIC_ARM_GIC_V3 is not set
CONFIG_RT_PIC_ARM_GIC_MAX_NR=1
+CONFIG_RT_PIC_BCM2712_MIP=y
+CONFIG_RT_PIC_BCM2835_INTC=y
+CONFIG_RT_PIC_BCM2836_L1_INTC=y
+CONFIG_RT_PIC_BRCMSTB_L2_IRQ=y
CONFIG_RT_USING_PIN=y
# CONFIG_RT_PIN_PL061 is not set
-# CONFIG_RT_USING_PINCTRL is not set
+CONFIG_RT_PIN_BCM_VIRT=y
+CONFIG_RT_PIN_BRCMSTB=y
+CONFIG_RT_PIN_RASPBERRYPI_EXP=y
+CONFIG_RT_USING_PINCTRL=y
+# CONFIG_RT_PINCTRL_SINGLE is not set
+CONFIG_RT_PINCTRL_BCM2712=y
+CONFIG_RT_PINCTRL_BCM2835=y
+CONFIG_RT_PINCTRL_RP1=y
CONFIG_RT_USING_CLK=y
+CONFIG_RT_CLK_BCM2711_DVP=y
+CONFIG_RT_CLK_BCM2835=y
+CONFIG_RT_CLK_RASPBERRYPI=y
+CONFIG_RT_CLK_RP1=y
# CONFIG_RT_USING_CHERRYUSB is not set
#
# SoC (System on Chip) Drivers
#
+CONFIG_RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR=y
+# end of SoC (System on Chip) Drivers
# end of Device Drivers
#
@@ -464,12 +641,12 @@ CONFIG_RT_USING_POSIX_FS=y
CONFIG_RT_USING_POSIX_DEVIO=y
CONFIG_RT_USING_POSIX_STDIO=y
CONFIG_RT_USING_POSIX_POLL=y
-# CONFIG_RT_USING_POSIX_SELECT is not set
-# CONFIG_RT_USING_POSIX_EVENTFD is not set
+CONFIG_RT_USING_POSIX_SELECT=y
+CONFIG_RT_USING_POSIX_EVENTFD=y
CONFIG_RT_USING_POSIX_EPOLL=y
CONFIG_RT_USING_POSIX_SIGNALFD=y
CONFIG_RT_SIGNALFD_MAX_NUM=10
-# CONFIG_RT_USING_POSIX_TIMERFD is not set
+CONFIG_RT_USING_POSIX_TIMERFD=y
# CONFIG_RT_USING_POSIX_SOCKET is not set
CONFIG_RT_USING_POSIX_TERMIOS=y
# CONFIG_RT_USING_POSIX_AIO is not set
@@ -483,7 +660,8 @@ CONFIG_RT_USING_POSIX_TIMER=y
#
# Interprocess Communication (IPC)
#
-# CONFIG_RT_USING_POSIX_PIPE is not set
+CONFIG_RT_USING_POSIX_PIPE=y
+CONFIG_RT_USING_POSIX_PIPE_SIZE=512
# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
@@ -524,12 +702,12 @@ CONFIG_NETDEV_IPV6=0
CONFIG_RT_USING_LWIP=y
# CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set
# CONFIG_RT_USING_LWIP141 is not set
-# CONFIG_RT_USING_LWIP203 is not set
-CONFIG_RT_USING_LWIP212=y
+CONFIG_RT_USING_LWIP203=y
+# CONFIG_RT_USING_LWIP212 is not set
# CONFIG_RT_USING_LWIP_LATEST is not set
-CONFIG_RT_USING_LWIP_VER_NUM=0x20102
+CONFIG_RT_USING_LWIP_VER_NUM=0x20003
# CONFIG_RT_USING_LWIP_IPV6 is not set
-CONFIG_RT_LWIP_MEM_ALIGNMENT=4
+CONFIG_RT_LWIP_MEM_ALIGNMENT=8
CONFIG_RT_LWIP_IGMP=y
CONFIG_RT_LWIP_ICMP=y
# CONFIG_RT_LWIP_SNMP is not set
@@ -541,8 +719,8 @@ CONFIG_IP_SOF_BROADCAST_RECV=1
#
# Static IPv4 Address
#
-CONFIG_RT_LWIP_IPADDR="192.168.137.100"
-CONFIG_RT_LWIP_GWADDR="192.168.137.1"
+CONFIG_RT_LWIP_IPADDR="192.168.1.30"
+CONFIG_RT_LWIP_GWADDR="192.168.1.1"
CONFIG_RT_LWIP_MSKADDR="255.255.255.0"
# end of Static IPv4 Address
@@ -550,23 +728,23 @@ CONFIG_RT_LWIP_UDP=y
CONFIG_RT_LWIP_TCP=y
CONFIG_RT_LWIP_RAW=y
# CONFIG_RT_LWIP_PPP is not set
-CONFIG_RT_MEMP_NUM_NETCONN=16
+CONFIG_RT_MEMP_NUM_NETCONN=8
CONFIG_RT_LWIP_PBUF_NUM=16
CONFIG_RT_LWIP_RAW_PCB_NUM=4
-CONFIG_RT_LWIP_UDP_PCB_NUM=8
-CONFIG_RT_LWIP_TCP_PCB_NUM=8
+CONFIG_RT_LWIP_UDP_PCB_NUM=4
+CONFIG_RT_LWIP_TCP_PCB_NUM=4
CONFIG_RT_LWIP_TCP_SEG_NUM=40
-CONFIG_RT_LWIP_TCP_SND_BUF=8192
-CONFIG_RT_LWIP_TCP_WND=8192
+CONFIG_RT_LWIP_TCP_SND_BUF=8196
+CONFIG_RT_LWIP_TCP_WND=8196
CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
-CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=32768
+CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=8192
# CONFIG_LWIP_NO_RX_THREAD is not set
-CONFIG_LWIP_NO_TX_THREAD=y
+# CONFIG_LWIP_NO_TX_THREAD is not set
CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
-CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=32768
+CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=8192
CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
-CONFIG_RT_LWIP_REASSEMBLY_FRAG=y
+# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
CONFIG_LWIP_NETIF_LINK_CALLBACK=1
CONFIG_RT_LWIP_NETIF_NAMESIZE=6
@@ -575,8 +753,8 @@ CONFIG_LWIP_SO_RCVTIMEO=1
CONFIG_LWIP_SO_SNDTIMEO=1
CONFIG_LWIP_SO_RCVBUF=1
CONFIG_LWIP_SO_LINGER=0
-CONFIG_RT_LWIP_NETIF_LOOPBACK=y
-CONFIG_LWIP_NETIF_LOOPBACK=1
+# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set
+CONFIG_LWIP_NETIF_LOOPBACK=0
# CONFIG_RT_LWIP_STATS is not set
# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
CONFIG_RT_LWIP_USING_PING=y
@@ -598,11 +776,7 @@ CONFIG_RT_LWIP_USING_PING=y
#
# CONFIG_RT_USING_RYM is not set
# CONFIG_RT_USING_ULOG is not set
-CONFIG_RT_USING_UTEST=y
-CONFIG_UTEST_THR_STACK_SIZE=8192
-CONFIG_UTEST_THR_PRIORITY=20
-# CONFIG_RT_UTEST_USING_AUTO_RUN is not set
-CONFIG_RT_UTEST_MAX_OPTIONS=64
+# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_VAR_EXPORT is not set
CONFIG_RT_USING_RESOURCE_ID=y
CONFIG_RT_USING_ADT=y
@@ -655,114 +829,14 @@ CONFIG_RT_USING_VDSO=y
# end of Using USB legacy version
# CONFIG_RT_USING_FDT is not set
+# CONFIG_RT_USING_LEGACY_VIRTIO is not set
# CONFIG_RT_USING_RUST is not set
# end of RT-Thread Components
#
# RT-Thread Utestcases
#
-CONFIG_RT_USING_UTESTCASES=y
-
-#
-# Kernel Core
-#
-# CONFIG_RT_UTEST_OBJECT is not set
-# CONFIG_RT_UTEST_SLAB is not set
-# CONFIG_RT_UTEST_IRQ is not set
-# CONFIG_RT_UTEST_SEMAPHORE is not set
-# CONFIG_RT_UTEST_EVENT is not set
-# CONFIG_RT_UTEST_TIMER is not set
-# CONFIG_RT_UTEST_MESSAGEQUEUE is not set
-# CONFIG_RT_UTEST_SIGNAL is not set
-# CONFIG_RT_UTEST_MUTEX is not set
-# CONFIG_RT_UTEST_MAILBOX is not set
-# CONFIG_RT_UTEST_THREAD is not set
-# CONFIG_RT_UTEST_ATOMIC is not set
-# CONFIG_RT_UTEST_HOOKLIST is not set
-# CONFIG_RT_UTEST_MTSAFE_KPRINT is not set
-CONFIG_RT_UTEST_SCHEDULER=y
-# CONFIG_RT_UTEST_SYS_PERF is not set
-# CONFIG_RT_UTEST_TC_USING_KLIBC is not set
-
-#
-# SMP Test
-#
-# CONFIG_RT_UTEST_SMP_AFFFINITY is not set
-# CONFIG_RT_UTEST_SMP_ASSIGNED_IDLE_CORE is not set
-# CONFIG_RT_UTEST_SMP_INTERRUPT_PRI is not set
-# CONFIG_RT_UTEST_SMP_SPINLOCK is not set
-# CONFIG_RT_UTEST_SMP_THREAD_PREEMPTION is not set
-# end of SMP Test
-# end of Kernel Core
-
-#
-# Kernel Components
-#
-
-#
-# Drivers
-#
-# CONFIG_RT_UTEST_DRIVERS_CORE is not set
-
-#
-# IPC Test
-#
-# CONFIG_RT_UTEST_COMPLETION is not set
-# CONFIG_RT_UTEST_WORKQUEUE is not set
-# end of IPC Test
-
-#
-# Serial Test
-#
-# CONFIG_RT_UTEST_SERIAL_BYPASS is not set
-# end of Serial Test
-
-#
-# SMP-Call Test
-#
-# CONFIG_RT_UTEST_SMP_CALL_FUNC is not set
-# end of SMP-Call Test
-# end of Drivers
-
-#
-# File System
-#
-# CONFIG_RT_UTEST_TC_USING_DFS_API is not set
-# end of File System
-
-#
-# CPP11
-#
-# CONFIG_RT_UTEST_CPP11_THREAD is not set
-# end of CPP11
-
-#
-# Network
-#
-# CONFIG_RT_UTEST_TC_USING_SAL is not set
-# CONFIG_RT_UTEST_TC_USING_NETDEV is not set
-# CONFIG_RT_UTEST_TC_USING_LWIP is not set
-# end of Network
-
-#
-# Utest Framework
-#
-# CONFIG_RT_UTEST_SELF_PASS is not set
-# end of Utest Framework
-# end of Kernel Components
-
-#
-# Memory Management Subsytem Testcase
-#
-# CONFIG_RT_UTEST_MM_API is not set
-# CONFIG_RT_UTEST_MM_LWP is not set
-# end of Memory Management Subsytem Testcase
-
-#
-# Tmpfs Testcase
-#
-# CONFIG_RT_UTEST_TMPFS_CP is not set
-# end of Tmpfs Testcase
+# CONFIG_RT_USING_UTESTCASES is not set
# end of RT-Thread Utestcases
#
@@ -958,7 +1032,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_U8G2 is not set
# end of u8g2: a monochrome graphic library
-# CONFIG_PKG_USING_NES_SIMULATOR is not set
# CONFIG_PKG_USING_OPENMV is not set
# CONFIG_PKG_USING_MUPDF is not set
# CONFIG_PKG_USING_STEMWIN is not set
@@ -983,9 +1056,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
#
# tools packages
#
-# CONFIG_PKG_USING_VECTOR is not set
-# CONFIG_PKG_USING_SORCH is not set
-# CONFIG_PKG_USING_DICT is not set
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_MCOREDUMP is not set
# CONFIG_PKG_USING_EASYFLASH is not set
@@ -1034,9 +1104,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_RVBACKTRACE is not set
# CONFIG_PKG_USING_HPATCHLITE is not set
# CONFIG_PKG_USING_THREAD_METRIC is not set
-# CONFIG_PKG_USING_UORB is not set
-# CONFIG_PKG_USING_RT_TUNNEL is not set
-# CONFIG_PKG_USING_VIRTUAL_TERMINAL is not set
# end of tools packages
#
@@ -1131,9 +1198,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_R_RHEALSTONE is not set
# CONFIG_PKG_USING_HEARTBEAT is not set
# CONFIG_PKG_USING_MICRO_ROS_RTTHREAD_PACKAGE is not set
-# CONFIG_PKG_USING_CHERRYECAT is not set
-# CONFIG_PKG_USING_EVENT_LOOP is not set
-# CONFIG_PKG_USING_THREAD_MANAGER is not set
# end of system packages
#
@@ -1279,7 +1343,9 @@ CONFIG_RT_UTEST_SCHEDULER=y
#
# NUVOTON Drivers
#
+# CONFIG_PKG_USING_NUVOTON_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_NUVOTON_SERIES_DRIVER is not set
+# CONFIG_PKG_USING_NUVOTON_ARM926_LIB is not set
# end of NUVOTON Drivers
#
@@ -1287,24 +1353,7 @@ CONFIG_RT_UTEST_SCHEDULER=y
#
# CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set
# CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32_RISCV_SERIES_DRIVER is not set
-# CONFIG_PKG_USING_GD32VW55X_WIFI is not set
# end of GD32 Drivers
-
-#
-# HPMicro SDK
-#
-# CONFIG_PKG_USING_HPM_SDK is not set
-# end of HPMicro SDK
-
-#
-# FT32 HAL & SDK Drivers
-#
-# CONFIG_PKG_USING_FT32F0_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F0_CMSIS_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_STD_DRIVER is not set
-# CONFIG_PKG_USING_FT32F4_CMSIS_DRIVER is not set
-# end of FT32 HAL & SDK Drivers
# end of HAL & SDK Drivers
#
@@ -1350,11 +1399,9 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_RT3020 is not set
# CONFIG_PKG_USING_MLX90632 is not set
# CONFIG_PKG_USING_MLX90382 is not set
-# CONFIG_PKG_USING_MLX90384 is not set
# CONFIG_PKG_USING_MLX90393 is not set
# CONFIG_PKG_USING_MLX90392 is not set
# CONFIG_PKG_USING_MLX90394 is not set
-# CONFIG_PKG_USING_MLX90396 is not set
# CONFIG_PKG_USING_MLX90397 is not set
# CONFIG_PKG_USING_MS5611 is not set
# CONFIG_PKG_USING_MAX31865 is not set
@@ -1383,7 +1430,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_P3T1755 is not set
# CONFIG_PKG_USING_QMI8658 is not set
# CONFIG_PKG_USING_ICM20948 is not set
-# CONFIG_PKG_USING_SCD4X is not set
# end of sensors drivers
#
@@ -1401,7 +1447,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_CST812T is not set
# end of touch drivers
-# CONFIG_PKG_USING_LCD_SPI_DRIVER is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_BUTTON is not set
# CONFIG_PKG_USING_PCF8574 is not set
@@ -1481,13 +1526,6 @@ CONFIG_RT_UTEST_SCHEDULER=y
# CONFIG_PKG_USING_IC74HC165 is not set
# CONFIG_PKG_USING_IST8310 is not set
# CONFIG_PKG_USING_ST7789_SPI is not set
-# CONFIG_PKG_USING_CAN_UDS is not set
-# CONFIG_PKG_USING_ISOTP_C is not set
-# CONFIG_PKG_USING_IKUNLED is not set
-# CONFIG_PKG_USING_INS5T8025 is not set
-# CONFIG_PKG_USING_IRUART is not set
-# CONFIG_PKG_USING_ST7305 is not set
-# CONFIG_PKG_USING_TM1668 is not set
# CONFIG_PKG_USING_SPI_TOOLS is not set
# end of peripheral libraries and drivers
@@ -1827,11 +1865,4 @@ CONFIG_RT_UTEST_SCHEDULER=y
# end of Arduino libraries
# end of RT-Thread online packages
-CONFIG_BCM2711_SOC=y
-
-#
-# Hardware Drivers Config
-#
-CONFIG_BSP_USING_PL011=y
-CONFIG_BSP_USING_SDHCI=y
-# end of Hardware Drivers Config
+CONFIG_SOC_BCM2712=y
diff --git a/bsp/raspberry-pi/raspi-dm2.0/Kconfig b/bsp/raspberry-pi/raspi5/Kconfig
index f62b1758e9..424bd6f235 100644..100755
--- a/bsp/raspberry-pi/raspi-dm2.0/Kconfig
+++ b/bsp/raspberry-pi/raspi5/Kconfig
@@ -6,17 +6,18 @@ RTT_DIR := ../../..
PKGS_DIR := packages
+SOC_DM_DIR := $BSP_DIR/../dm/
+
+source "$(SOC_DM_DIR)/Kconfig"
source "$(RTT_DIR)/Kconfig"
osource "$PKGS_DIR/Kconfig"
-config BCM2711_SOC
+config SOC_BCM2712
bool
select ARCH_ARMV8
- select ARCH_ARM_MMU
- select RT_USING_CACHE
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select ARCH_CPU_64BIT
+ select RT_USING_CACHE
+ select RT_USING_STDC_ATOMIC
default y
-
-rsource "drivers/Kconfig"
diff --git a/bsp/raspberry-pi/raspi5/README.md b/bsp/raspberry-pi/raspi5/README.md
new file mode 100644
index 0000000000..6a40a90509
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/README.md
@@ -0,0 +1,217 @@
+# Raspberry Pi 5 BSP 使用说明
+
+[English](README_en.md)
+
+## 1. 简介
+
+本 BSP 为 Raspberry Pi 5 提供 RT-Thread 64 位板级支持,目标 SoC 为 Broadcom BCM2712(4 核 Cortex-A76),并使用 RT-Thread Device Model 管理板载设备及 RP1 南桥外设。
+
+当前启动流程为:Raspberry Pi 固件加载 U-Boot,U-Boot 再加载 `rtthread.bin`,并将固件提供的设备树传递给 RT-Thread。BSP 默认启用 SMP,控制台设备为设备树中的 `uart10`。
+
+## 2. 准备工作
+
+### 2.1 硬件
+
+- Raspberry Pi 5;
+- microSD 卡及读卡器;
+- 3.3 V TTL 串口工具;
+- 可选:用于 TFTP 启动的有线网络。
+
+> 串口电平必须为 3.3 V,请勿直接连接 RS-232 或 5 V 串口。默认波特率为 `115200 8N1`,关闭硬件和软件流控。
+
+### 2.2 软件
+
+- Python 3;
+- SCons 及 RT-Thread Env 工具;
+- AArch64 bare-metal GCC 工具链;
+- 适用于 Raspberry Pi 5 的 U-Boot;
+- 可选:TFTP 服务器。
+
+默认工具链前缀为 `aarch64-none-elf-`,`rtconfig.py` 中的默认搜索路径为:
+
+```text
+/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/
+```
+
+推荐通过环境变量指定本机工具链,避免修改仓库文件:
+
+```bash
+export RTT_EXEC_PATH=/path/to/aarch64-toolchain/bin
+export RTT_CC_PREFIX=aarch64-none-elf-
+```
+
+编译脚本优先使用 `-mtune=cortex-a76`;旧工具链不支持时,会依次回退到 `cortex-a73` 或 `generic`。
+
+## 3. 配置与编译
+
+进入 BSP 目录:
+
+```bash
+cd bsp/raspberry-pi/raspi5
+```
+
+如需调整功能,可先打开配置菜单:
+
+```bash
+scons --menuconfig
+```
+
+编译 BSP:
+
+```bash
+scons -j$(nproc)
+```
+
+Windows 环境可直接使用 `scons`,或将 `$(nproc)` 替换为合适的并行任务数。
+
+成功后会生成:
+
+| 文件 | 说明 |
+| --- | --- |
+| `rtthread.elf` | 带符号信息的 ELF 文件,用于调试和反汇编 |
+| `rtthread.bin` | U-Boot 实际加载的裸二进制镜像 |
+| `rtthread.map` | 链接映射文件 |
+| `rtt.asm` | 反汇编结果 |
+
+`rtthread.bin` 的加载地址为 `0x210000`,与默认配置中的 `ARCH_TEXT_OFFSET` 一致,请勿随意修改启动命令中的地址。
+
+## 4. 准备启动介质
+
+### 4.1 准备 U-Boot
+
+先准备一张能够由 Raspberry Pi 5 固件正常识别的 microSD 卡。将适用于 Raspberry Pi 5 的 U-Boot 镜像放到 FAT 启动分区根目录,并命名为:
+
+```text
+u-boot.bin
+```
+
+本目录的 [`tools/config.txt`](tools/config.txt) 包含 BSP 所需的最小固件配置:
+
+```ini
+kernel=u-boot.bin
+dtparam=pciex1
+```
+
+如果启动分区已经存在 `config.txt`,请合并上述配置,不要直接覆盖其中仍需保留的显示、串口或其他板级设置。
+
+### 4.2 放置 RT-Thread 镜像
+
+使用 SD 卡启动时,将编译生成的 `rtthread.bin` 复制到第一个 FAT 分区的根目录:
+
+```text
+<boot partition>/rtthread.bin
+```
+
+默认命令使用 U-Boot 的 `mmc 0:1`。如果实际 SD 卡控制器或分区编号不同,请先用以下命令确认:
+
+```text
+mmc list
+mmc dev 0
+part list mmc 0
+fatls mmc 0:1
+```
+
+## 5. U-Boot 启动
+
+### 5.1 设置公共启动参数
+
+在 U-Boot 控制台设置 RT-Thread 使用的启动参数:
+
+```text
+setenv bootargs_rtt 'earlycon cma=8M coherent_pool=2M'
+saveenv
+```
+
+启动命令会复制固件提供的活动设备树,并更新 `/chosen/bootargs`。不要使用与当前开发板不匹配的静态 DTB 替代该设备树,否则 RP1、PCIe 和板载外设信息可能不完整。
+
+### 5.2 从 SD 卡加载
+
+```text
+setenv bootrtt 'mmc dev 0; fatload mmc 0:1 0x210000 rtthread.bin; fdt addr ${fdtcontroladdr}; fdt move ${fdt_addr_r} 0x20000; fdt addr ${fdt_addr_r}; fdt resize 8192; setenv bootargs ${bootargs_rtt}; fdt set /chosen bootargs ${bootargs}; booti 0x210000 - ${fdt_addr_r}'
+saveenv
+run bootrtt
+```
+
+如需每次上电自动启动,可在确认手动启动正常后设置:
+
+```text
+setenv bootcmd 'run bootrtt'
+saveenv
+```
+
+### 5.3 从 TFTP 加载
+
+先将 `rtthread.bin` 放到 TFTP 服务器根目录。下面地址仅为示例,请根据实际网络修改:
+
+```text
+setenv bootrtt_tftp 'setenv ethprime eth0; setenv ipaddr 192.168.10.2; setenv serverip 192.168.10.1; setenv netmask 255.255.255.0; ping 192.168.10.1; tftp 0x210000 rtthread.bin; fdt addr ${fdtcontroladdr}; fdt move ${fdt_addr_r} 0x20000; fdt addr ${fdt_addr_r}; fdt resize 8192; setenv bootargs ${bootargs_rtt}; fdt set /chosen bootargs ${bootargs}; booti 0x210000 - ${fdt_addr_r}'
+saveenv
+run bootrtt_tftp
+```
+
+如果 U-Boot 中的有线网卡名称不是 `eth0`,可通过 `printenv ethact ethprime` 或 `bdinfo` 检查后调整 `ethprime`。
+
+## 6. 启动结果
+
+启动成功后,串口应出现 RT-Thread 标志、SMP 初始化信息,随后进入 MSH:
+
+```text
+ \ | /
+- RT - Thread Operating System
+ / | \
+ 2006 - 2026 Copyright by RT-Thread team
+Hi, this is RT-Thread!!
+msh />
+```
+
+实际版本号、构建时间和设备初始化日志会随配置变化。
+
+## 7. 默认配置
+
+默认 `rtconfig.h` 启用了以下主要功能。是否能探测到具体设备,仍取决于 Raspberry Pi 固件版本、活动设备树、扩展板和外设连接情况。
+
+| 类别 | 默认配置中的主要支持 |
+| --- | --- |
+| CPU | AArch64、4 核 SMP、MMU、Cache、ASID |
+| 控制台 | PL011/8250 串口,默认 `uart10` |
+| 存储 | SDHCI/MMC、FatFs、NVMe over PCIe |
+| 网络 | RP1 以太网、PHY、lwIP、DHCP |
+| 总线 | PCIe、I2C、SPI、SDIO、Device Tree/OFW |
+| RP1 外设 | ADC、PWM、GPIO/Pinctrl、时钟、MFD |
+| 系统服务 | RTC、Watchdog、DMA、Thermal、DVFS、Mailbox |
+| 多媒体与输入 | I2S Audio、Framebuffer、Touchscreen、Joystick、Keyboard |
+| 用户态 | RT-Smart、DFS、POSIX、LWP、动态链接支持 |
+
+## 8. 常见问题
+
+### 8.1 U-Boot 找不到 `rtthread.bin`
+
+先执行:
+
+```text
+fatls mmc 0:1
+```
+
+确认文件名、设备号和分区号。Linux 文件名区分大小写。
+
+### 8.2 `Bad Linux ARM64 Image magic!` 或跳转后无输出
+
+- 确认加载的是 `rtthread.bin`,而不是 `rtthread.elf`;
+- 确认加载及启动地址均为 `0x210000`;
+- 确认使用 `booti 0x210000 - ${fdt_addr_r}`;
+- 检查串口参数以及设备树中的 `stdout-path`。
+
+### 8.3 设备树或 RP1 外设初始化失败
+
+- 确认 Raspberry Pi 固件和 U-Boot 支持 Raspberry Pi 5;
+- 确认 `config.txt` 中包含 `dtparam=pciex1`;
+- 保留并传递固件提供的活动设备树;
+- 不要在 U-Boot 中覆盖成其他 Raspberry Pi 型号的 DTB。
+
+### 8.4 TFTP 下载失败
+
+检查 `ipaddr`、`serverip`、`netmask`、TFTP 根目录、防火墙和网线连接,并先在 U-Boot 中执行 `ping ${serverip}`。
+
+## 9. 重新配置后的注意事项
+
+运行 `scons --menuconfig` 后,配置可能与本文记录的默认 `rtconfig.h` 不同。提交 BSP 配置变更前,应同时检查生成的 `rtconfig.h`,并确认新增驱动在 Raspberry Pi 5 实机上完成验证。
diff --git a/bsp/raspberry-pi/raspi5/README_en.md b/bsp/raspberry-pi/raspi5/README_en.md
new file mode 100644
index 0000000000..83d124fc18
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/README_en.md
@@ -0,0 +1,217 @@
+# Raspberry Pi 5 BSP User Guide
+
+[中文](README.md)
+
+## 1. Introduction
+
+This BSP provides 64-bit RT-Thread support for Raspberry Pi 5. It targets the Broadcom BCM2712 SoC, which contains four Cortex-A76 cores, and uses the RT-Thread Device Model to manage on-board devices and RP1 southbridge peripherals.
+
+The current boot flow is: Raspberry Pi firmware loads U-Boot, U-Boot loads `rtthread.bin`, and the firmware-provided device tree is passed to RT-Thread. SMP is enabled by default, and the default console device is `uart10` from the device tree.
+
+## 2. Prerequisites
+
+### 2.1 Hardware
+
+- Raspberry Pi 5;
+- A microSD card and card reader;
+- A 3.3 V TTL serial adapter;
+- Optional: a wired network for TFTP boot.
+
+> The serial interface must use 3.3 V levels. Do not connect an RS-232 or 5 V serial adapter directly. The default serial settings are `115200 8N1`, with hardware and software flow control disabled.
+
+### 2.2 Software
+
+- Python 3;
+- SCons and the RT-Thread Env tools;
+- An AArch64 bare-metal GCC toolchain;
+- A Raspberry Pi 5-compatible U-Boot image;
+- Optional: a TFTP server.
+
+The default toolchain prefix is `aarch64-none-elf-`. The default search path in `rtconfig.py` is:
+
+```text
+/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/
+```
+
+Using environment variables is recommended so that repository files do not need to be modified:
+
+```bash
+export RTT_EXEC_PATH=/path/to/aarch64-toolchain/bin
+export RTT_CC_PREFIX=aarch64-none-elf-
+```
+
+The build script prefers `-mtune=cortex-a76`. If an older compiler does not support it, the script falls back to `cortex-a73` and then `generic`.
+
+## 3. Configuration and Build
+
+Enter the BSP directory:
+
+```bash
+cd bsp/raspberry-pi/raspi5
+```
+
+To change the default configuration, open menuconfig first:
+
+```bash
+scons --menuconfig
+```
+
+Build the BSP:
+
+```bash
+scons -j$(nproc)
+```
+
+On Windows, run `scons` directly or replace `$(nproc)` with a suitable number of parallel jobs.
+
+A successful build produces:
+
+| File | Description |
+| --- | --- |
+| `rtthread.elf` | ELF image with symbols for debugging and disassembly |
+| `rtthread.bin` | Raw binary image loaded by U-Boot |
+| `rtthread.map` | Linker map |
+| `rtt.asm` | Disassembly output |
+
+The load address of `rtthread.bin` is `0x210000`, matching `ARCH_TEXT_OFFSET` in the default configuration. Do not change this address in the boot commands without updating the BSP configuration accordingly.
+
+## 4. Preparing the Boot Media
+
+### 4.1 Preparing U-Boot
+
+Prepare a microSD card that can be recognized by the Raspberry Pi 5 firmware. Place a Raspberry Pi 5-compatible U-Boot image in the root of the FAT boot partition and name it:
+
+```text
+u-boot.bin
+```
+
+The [`tools/config.txt`](tools/config.txt) file contains the minimum firmware configuration required by this BSP:
+
+```ini
+kernel=u-boot.bin
+dtparam=pciex1
+```
+
+If the boot partition already contains a `config.txt`, merge these settings into it. Do not overwrite display, serial, or other board-specific settings that are still required.
+
+### 4.2 Copying the RT-Thread Image
+
+For SD card boot, copy the generated `rtthread.bin` to the root of the first FAT partition:
+
+```text
+<boot partition>/rtthread.bin
+```
+
+The default commands use U-Boot device and partition `mmc 0:1`. If your SD controller or partition number differs, inspect it first:
+
+```text
+mmc list
+mmc dev 0
+part list mmc 0
+fatls mmc 0:1
+```
+
+## 5. Booting from U-Boot
+
+### 5.1 Common Boot Arguments
+
+Set the RT-Thread boot arguments at the U-Boot console:
+
+```text
+setenv bootargs_rtt 'earlycon cma=8M coherent_pool=2M'
+saveenv
+```
+
+The boot commands copy the live device tree provided by the firmware and update `/chosen/bootargs`. Do not replace it with a static DTB for another board revision or Raspberry Pi model, because RP1, PCIe, and on-board peripheral information may be incomplete.
+
+### 5.2 Booting from the SD Card
+
+```text
+setenv bootrtt 'mmc dev 0; fatload mmc 0:1 0x210000 rtthread.bin; fdt addr ${fdtcontroladdr}; fdt move ${fdt_addr_r} 0x20000; fdt addr ${fdt_addr_r}; fdt resize 8192; setenv bootargs ${bootargs_rtt}; fdt set /chosen bootargs ${bootargs}; booti 0x210000 - ${fdt_addr_r}'
+saveenv
+run bootrtt
+```
+
+After manual boot has been verified, enable automatic boot if desired:
+
+```text
+setenv bootcmd 'run bootrtt'
+saveenv
+```
+
+### 5.3 Booting over TFTP
+
+Place `rtthread.bin` in the TFTP server root. The addresses below are examples and must be adjusted for your network:
+
+```text
+setenv bootrtt_tftp 'setenv ethprime eth0; setenv ipaddr 192.168.10.2; setenv serverip 192.168.10.1; setenv netmask 255.255.255.0; ping 192.168.10.1; tftp 0x210000 rtthread.bin; fdt addr ${fdtcontroladdr}; fdt move ${fdt_addr_r} 0x20000; fdt addr ${fdt_addr_r}; fdt resize 8192; setenv bootargs ${bootargs_rtt}; fdt set /chosen bootargs ${bootargs}; booti 0x210000 - ${fdt_addr_r}'
+saveenv
+run bootrtt_tftp
+```
+
+If the U-Boot Ethernet device is not named `eth0`, inspect `printenv ethact ethprime` or `bdinfo` and adjust `ethprime`.
+
+## 6. Expected Output
+
+After a successful boot, the serial console should display the RT-Thread banner and SMP initialization messages before entering MSH:
+
+```text
+ \ | /
+- RT - Thread Operating System
+ / | \
+ 2006 - 2026 Copyright by RT-Thread team
+Hi, this is RT-Thread!!
+msh />
+```
+
+The exact version, build time, and device initialization messages depend on the active configuration.
+
+## 7. Default Configuration
+
+The default `rtconfig.h` enables the major features listed below. Whether a particular device is detected still depends on the Raspberry Pi firmware version, live device tree, expansion boards, and connected peripherals.
+
+| Category | Major features enabled by default |
+| --- | --- |
+| CPU | AArch64, four-core SMP, MMU, cache, and ASID |
+| Console | PL011/8250 serial drivers; `uart10` is the default console |
+| Storage | SDHCI/MMC, FatFs, and NVMe over PCIe |
+| Networking | RP1 Ethernet, PHY support, lwIP, and DHCP |
+| Buses | PCIe, I2C, SPI, SDIO, and Device Tree/OFW |
+| RP1 peripherals | ADC, PWM, GPIO/pinctrl, clocks, and MFD |
+| System services | RTC, watchdog, DMA, thermal control, DVFS, and mailbox |
+| Multimedia and input | I2S audio, framebuffer, touchscreen, joystick, and keyboard |
+| User space | RT-Smart, DFS, POSIX, LWP, and dynamic linking |
+
+## 8. Troubleshooting
+
+### 8.1 U-Boot Cannot Find `rtthread.bin`
+
+Run:
+
+```text
+fatls mmc 0:1
+```
+
+Check the filename, device number, and partition number. Linux filenames are case-sensitive.
+
+### 8.2 `Bad Linux ARM64 Image magic!` or No Output After Jumping
+
+- Make sure `rtthread.bin`, not `rtthread.elf`, was loaded;
+- Make sure both the load and boot addresses are `0x210000`;
+- Make sure the command is `booti 0x210000 - ${fdt_addr_r}`;
+- Check the serial settings and `stdout-path` in the device tree.
+
+### 8.3 Device Tree or RP1 Peripheral Initialization Fails
+
+- Make sure the Raspberry Pi firmware and U-Boot support Raspberry Pi 5;
+- Make sure `config.txt` contains `dtparam=pciex1`;
+- Preserve and pass the live device tree provided by the firmware;
+- Do not replace it in U-Boot with a DTB for another Raspberry Pi model.
+
+### 8.4 TFTP Download Fails
+
+Check `ipaddr`, `serverip`, `netmask`, the TFTP root, the host firewall, and the Ethernet connection. Run `ping ${serverip}` in U-Boot before downloading the image.
+
+## 9. Notes After Reconfiguration
+
+After running `scons --menuconfig`, the active configuration may differ from the default `rtconfig.h` documented here. Before submitting BSP configuration changes, inspect the generated `rtconfig.h` and verify newly enabled drivers on Raspberry Pi 5 hardware.
diff --git a/bsp/raspberry-pi/raspi5/SConscript b/bsp/raspberry-pi/raspi5/SConscript
new file mode 100755
index 0000000000..3b4078130e
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/SConscript
@@ -0,0 +1,17 @@
+# for module compiling
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+ path = os.path.join(cwd, d)
+ if os.path.isfile(os.path.join(path, 'SConscript')):
+ objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+objs = objs + SConscript(cwd + '/../dm/SConscript', variant_dir = 'dm', duplicate = 0)
+
+Return('objs')
+ \ No newline at end of file
diff --git a/bsp/raspberry-pi/raspi-dm2.0/SConstruct b/bsp/raspberry-pi/raspi5/SConstruct
index 55cab35463..ec6fe0187f 100644..100755
--- a/bsp/raspberry-pi/raspi-dm2.0/SConstruct
+++ b/bsp/raspberry-pi/raspi5/SConstruct
@@ -11,20 +11,19 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
- AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
- CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
- CPP = rtconfig.CPP, CXXFLAGS = rtconfig.CXXFLAGS,
- AR = rtconfig.AR, ARFLAGS = '-rc',
+ AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+ CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+ CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
+ AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
-env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
-objs = PrepareBuilding(env, RTT_ROOT)
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
# make a building
DoBuilding(TARGET, objs)
diff --git a/bsp/raspberry-pi/raspi5/applications/SConscript b/bsp/raspberry-pi/raspi5/applications/SConscript
new file mode 100755
index 0000000000..c583d3016e
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/applications/SConscript
@@ -0,0 +1,9 @@
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c') + Glob('*.cpp')
+CPPPATH = [cwd]
+
+group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/raspi5/applications/main.c b/bsp/raspberry-pi/raspi5/applications/main.c
new file mode 100644
index 0000000000..b54235ce9b
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/applications/main.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2017-05-30 bernard the first version
+ */
+
+#include <rtthread.h>
+
+int main(int argc, char **argv)
+{
+ rt_kprintf("Hi, this is RT-Thread!!\n");
+
+ return 0;
+}
diff --git a/bsp/raspberry-pi/raspi5/drivers/SConscript b/bsp/raspberry-pi/raspi5/drivers/SConscript
new file mode 100755
index 0000000000..f7e8f47ce8
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/drivers/SConscript
@@ -0,0 +1,12 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+CPPPATH = [cwd]
+objs = []
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/bsp/raspberry-pi/raspi5/drivers/board.c b/bsp/raspberry-pi/raspi5/drivers/board.c
new file mode 100755
index 0000000000..5283c37f53
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/drivers/board.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#include <setup.h>
+#include <board.h>
+#include <rtdevice.h>
+#include <drivers/ofw.h>
+
+void rt_hw_board_init(void)
+{
+ rt_hw_common_setup();
+}
+
+/*
+ * Several root-level nodes reference RP1 GPIO in the live DT.
+ * Resolving that phandle from an early driver probe calls rt_platform_ofw_request()
+ * on the RP1 subtree before PCIe has enumerated the RP1 device.
+ *
+ * Mark those nodes unavailable at INIT_CORE (before platform_ofw / early probes),
+ * then restore them later once platform init has passed the RP1 bring-up window.
+ */
+static struct rt_ofw_prop *cam0_status_prop = RT_NULL;
+static struct rt_ofw_prop *cam1_status_prop = RT_NULL;
+static struct rt_ofw_prop *leds_status_prop = RT_NULL;
+
+static void ofw_status_mark(const char *path, struct rt_ofw_prop **status_prop,
+ const char *status)
+{
+ struct rt_ofw_node *np;
+ rt_size_t len = rt_strlen(status) + 1;
+
+ if (!(np = rt_ofw_find_node_by_path(path)))
+ {
+ return;
+ }
+
+ if (!(*status_prop = rt_ofw_get_prop(np, "status", RT_NULL)))
+ {
+ if (rt_ofw_append_prop(np, "status", len, (void *)status))
+ {
+ rt_kprintf("append prop status failed on %s\n", path);
+ RT_ASSERT(0);
+ }
+
+ *status_prop = rt_ofw_get_prop(np, "status", RT_NULL);
+ }
+
+ if (*status_prop)
+ {
+ (*status_prop)->value = (char *)status;
+ (*status_prop)->length = len;
+ }
+
+ rt_ofw_node_put(np);
+}
+
+static int early_rp1_consumer_disable(void)
+{
+ ofw_status_mark("/cam0_reg", &cam0_status_prop, "disabled");
+ ofw_status_mark("/cam1_reg", &cam1_status_prop, "disabled");
+ ofw_status_mark("/leds", &leds_status_prop, "disabled");
+
+ return RT_EOK;
+}
+INIT_CORE_EXPORT(early_rp1_consumer_disable);
+
+static struct rt_ofw_prop *fb_status_prop = RT_NULL;
+
+#ifdef RT_GRAPHIC_FB_BCM2708
+static int legacy_framebuffer_enable(void)
+{
+ ofw_status_mark("/soc/fb", &fb_status_prop, "okay");
+
+ return RT_EOK;
+}
+INIT_CORE_EXPORT(legacy_framebuffer_enable);
+#endif /* RT_GRAPHIC_FB_BCM2708 */
+
+static int cam_regulator_enable(void)
+{
+ ofw_status_mark("/cam0_reg", &cam0_status_prop, "okay");
+ ofw_status_mark("/cam1_reg", &cam1_status_prop, "okay");
+
+ return RT_EOK;
+}
+INIT_PREV_EXPORT(cam_regulator_enable);
+
+/*
+ * /leds is kept out of the INIT_PLATFORM scan above. After INIT_DEVICE, only
+ * register it once mfd.rp1 has published the RP1 PIC on the OFW node; otherwise
+ * gpio-leds would pull the RP1 subtree in via GPIO phandle (Path B).
+ */
+static int leds_init(void)
+{
+ struct rt_ofw_node *np;
+
+ ofw_status_mark("/leds", &leds_status_prop, "okay");
+
+ if (!(np = rt_ofw_find_node_by_path("/leds")))
+ {
+ return RT_EOK;
+ }
+
+ rt_platform_ofw_request(np);
+ rt_ofw_node_put(np);
+
+ return RT_EOK;
+}
+INIT_EXPORT(leds_init, "3.1");
diff --git a/bsp/raspberry-pi/raspi5/drivers/board.h b/bsp/raspberry-pi/raspi5/drivers/board.h
new file mode 100755
index 0000000000..87ec007d29
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/drivers/board.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-11-25 GuEe-GUI first version
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+void rt_hw_board_init(void);
+
+#endif /* __BOARD_H__ */
diff --git a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.h b/bsp/raspberry-pi/raspi5/rtconfig.h
index 634c26b675..0ee061d2f1 100644..100755
--- a/bsp/raspberry-pi/raspi-dm2.0/rtconfig.h
+++ b/bsp/raspberry-pi/raspi5/rtconfig.h
@@ -8,16 +8,6 @@
/* rt_vsnprintf options */
#define RT_KLIBC_USING_VSNPRINTF_LONGLONG
-#define RT_KLIBC_USING_VSNPRINTF_STANDARD
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS
-#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER
-#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32
-#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6
-#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
-#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4
/* end of rt_vsnprintf options */
/* rt_vsscanf options */
@@ -72,24 +62,24 @@
/* end of rt_strnlen options */
/* end of klibc options */
-#define RT_NAME_MAX 12
+#define RT_NAME_MAX 24
#define RT_USING_SMART
#define RT_USING_SMP
#define RT_CPUS_NR 4
-#define RT_ALIGN_SIZE 4
+#define RT_ALIGN_SIZE 8
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
-#define RT_TICK_PER_SECOND 1000
+#define RT_TICK_PER_SECOND 100
#define RT_USING_OVERFLOW_CHECK
#define RT_USING_HOOK
#define RT_HOOK_USING_FUNC_PTR
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
-#define IDLE_THREAD_STACK_SIZE 16384
-#define SYSTEM_THREAD_STACK_SIZE 16384
+#define IDLE_THREAD_STACK_SIZE 8192
+#define SYSTEM_THREAD_STACK_SIZE 8192
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
-#define RT_TIMER_THREAD_STACK_SIZE 16384
+#define RT_TIMER_THREAD_STACK_SIZE 8192
#define RT_USING_CPU_USAGE_TRACER
#define RT_CPU_USAGE_CALC_INTERVAL_MS 200
@@ -97,8 +87,10 @@
/* end of kservice options */
#define RT_USING_DEBUG
+#define RT_DEBUGING_ASSERT
#define RT_DEBUGING_COLOR
#define RT_DEBUGING_CONTEXT
+#define RT_DEBUGING_CRITICAL
/* Inter-Thread communication */
@@ -111,16 +103,21 @@
/* Memory Management */
+#define RT_USING_MEMPOOL
#define RT_USING_SLAB
+#define RT_USING_MEMHEAP
+#define RT_MEMHEAP_FAST_MODE
#define RT_USING_SLAB_AS_HEAP
+#define RT_USING_HEAP_ISR
#define RT_USING_HEAP
/* end of Memory Management */
#define RT_USING_DEVICE
#define RT_USING_DEVICE_OPS
#define RT_USING_INTERRUPT_INFO
+#define RT_USING_THREADSAFE_PRINTF
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 256
-#define RT_CONSOLE_DEVICE_NAME "uart0"
+#define RT_CONSOLE_DEVICE_NAME "uart10"
#define RT_USING_CONSOLE_OUTPUT_CTL
#define RT_VER_NUM 0x50300
#define RT_USING_STDC_ATOMIC
@@ -129,10 +126,11 @@
/* AArch64 Architecture Configuration */
-#define ARCH_TEXT_OFFSET 0x200000
-#define ARCH_RAM_OFFSET 0x0
-#define ARCH_SECONDARY_CPU_STACK_SIZE 65536
+#define ARCH_TEXT_OFFSET 0x210000
+#define ARCH_RAM_OFFSET 0x200000
+#define ARCH_SECONDARY_CPU_STACK_SIZE 4096
#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS
+#define ARCH_USING_GENERIC_CPUID
#define ARCH_HEAP_SIZE 0x4000000
#define ARCH_INIT_PAGE_SIZE 0x200000
/* end of AArch64 Architecture Configuration */
@@ -145,6 +143,7 @@
#define KERNEL_VADDR_START 0xffff000000000000
#define ARCH_ARMV8
#define ARCH_USING_ASID
+#define ARCH_USING_HW_THREAD_SELF
#define ARCH_USING_IRQ_CTX_LIST
/* RT-Thread Components */
@@ -160,9 +159,9 @@
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 8192
#define FINSH_USING_HISTORY
-#define FINSH_HISTORY_LINES 5
+#define FINSH_HISTORY_LINES 10
#define FINSH_USING_SYMTAB
-#define FINSH_CMD_SIZE 80
+#define FINSH_CMD_SIZE 256
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
@@ -173,7 +172,7 @@
#define RT_USING_DFS
#define DFS_USING_POSIX
#define DFS_USING_WORKDIR
-#define DFS_FD_MAX 64
+#define DFS_FD_MAX 32
#define RT_USING_DFS_V2
#define RT_USING_DFS_ELMFAT
@@ -192,9 +191,8 @@
#define RT_DFS_ELM_MUTEX_TIMEOUT 3000
/* end of elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_USING_DFS_DEVFS
+#define RT_USING_DFS_ROMFS
#define RT_USING_DFS_PTYFS
-#define RT_USING_DFS_PROCFS
-#define RT_USING_DFS_TMPFS
#define RT_USING_PAGECACHE
/* page cache config */
@@ -215,32 +213,107 @@
#define RT_USING_DEVICE_IPC
#define RT_UNAMED_PIPE_NUMBER 64
#define RT_USING_SYSTEM_WORKQUEUE
-#define RT_SYSTEM_WORKQUEUE_STACKSIZE 16384
+#define RT_SYSTEM_WORKQUEUE_STACKSIZE 8192
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_USING_DMA
-#define RT_SERIAL_RB_BUFSZ 64
+#define RT_SERIAL_RB_BUFSZ 256
#define RT_USING_SERIAL_BYPASS
+#define RT_SERIAL_PL011
+#define RT_SERIAL_8250
+#define RT_SERIAL_8250_BCM2835AUX
+#define RT_SERIAL_8250_BCM7271
+#define RT_USING_ADC
+#define RT_USING_ADC_V1
+#define RT_ADC_RP1
#define RT_USING_CLOCK_TIME
+#define RT_CLOCK_TIME_ARM_ARCH
+#define RT_CLOCK_TIME_BCM2835
+#define RT_USING_ETHERNET
+#define RT_ETHERNET_CADENCE
+#define RT_ETHERNET_CADENCE_PTP
#define RT_USING_I2C
#define RT_USING_I2C_BITOPS
+#define RT_I2C_BCM2835
+#define RT_I2C_BRCMSTB
+#define RT_USING_PHY_V2
+#define RT_PHY_BCM54213
#define RT_USING_NULL
#define RT_USING_ZERO
#define RT_USING_RANDOM
+#define RT_USING_PWM
+#define RT_PWM_BCM2835
+#define RT_PWM_BRCMSTB
+#define RT_PWM_RP1
#define RT_USING_RTC
-#define RT_USING_SOFT_RTC
+#define RT_USING_ALARM
+#define RT_ALARM_STACK_SIZE 8192
+#define RT_ALARM_TIMESLICE 5
+#define RT_ALARM_PRIORITY 10
+#define RT_RTC_DS1302
+#define RT_RTC_DS1307
+#define RT_RTC_PCF8523
+#define RT_RTC_RPI
#define RT_USING_SDIO
-#define RT_SDIO_STACK_SIZE 16384
+#define RT_SDIO_STACK_SIZE 8192
#define RT_SDIO_THREAD_PRIORITY 15
#define RT_MMCSD_STACK_SIZE 8192
#define RT_MMCSD_THREAD_PRIORITY 22
#define RT_MMCSD_MAX_PARTITION 16
#define RT_USING_SDHCI
+#define RT_SDIO_SDHCI_BRCMSTB
+#define RT_SDIO_SDHCI_IPROC
#define RT_USING_SPI
#define RT_USING_SPI_ISR
+#define RT_SPI_BCM2835
+#define RT_SPI_BCM2835AUX
#define RT_USING_WDT
+#define RT_WDT_BCM2835
+#define RT_USING_AUDIO
+#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096
+#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2
+#define RT_AUDIO_RECORD_PIPE_SIZE 2048
+#define RT_AUDIO_BCM2835_I2S
#define RT_USING_TOUCH
+#define RT_USING_LCD
+#define RT_USING_GRAPHIC
+#define RT_GRAPHIC_BACKLIGHT
+#define RT_GRAPHIC_BACKLIGHT_RPI
+#define RT_GRAPHIC_FB
+#define RT_GRAPHIC_FB_ILI9486
+#define RT_GRAPHIC_FB_SIMPLE
+#define RT_GRAPHIC_FB_BCM2708
+#define RT_GRAPHIC_FB_RPISENSE
+#define RT_GRAPHIC_LOGO
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224
+#define RT_GRAPHIC_LOGO_RASPI_CLUT224_PATH "../dm/graphic/logo/logo-raspi-clut224.ppm"
+#define RT_USING_HWCRYPTO
+#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto"
+#define RT_HWCRYPTO_IV_MAX_SIZE 16
+#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256
+#define RT_HWCRYPTO_USING_RNG
+#define RT_HWCRYPTO_RNG_BCM2835
+#define RT_HWCRYPTO_RNG_IPROC_RNG200
+#define RT_USING_PTP
+#define RT_USING_LED
+#define RT_LED_GPIO
+#define RT_USING_INPUT
+#define RT_INPUT_POWER
+#define RT_INPUT_JOYSTICK
+#define RT_INPUT_JOYSTICK_RPISENSE
+#define RT_INPUT_KEYBOARD
+#define RT_INPUT_KEYBOARD_GPIO
+#define RT_INPUT_TOUCHSCREEN
+#define RT_INPUT_TOUCHSCREEN_ADS7846
+#define RT_INPUT_TOUCHSCREEN_RASPBERRYPI_FW
+#define RT_USING_MBOX
+#define RT_MBOX_BCM2835
+#define RT_USING_PHYE
+#define RT_PHYE_GENERIC_USB
+#define RT_USING_NVME
+#define RT_USING_NVME_IO_QUEUE 1
+#define RT_NVME_PCI
#define RT_USING_BLK
/* Partition Types */
@@ -248,22 +321,90 @@
#define RT_BLK_PARTITION_DFS
#define RT_BLK_PARTITION_EFI
/* end of Partition Types */
+#define RT_USING_FIRMWARE
+#define RT_FIRMWARE_RASPBERRYPI
+#define RT_USING_DVFS
+#define RT_USING_DVFS_EVENT
+#define RT_USING_DVFS_OPP_RETRY_MAX 10
+
+/* DVFS Event Drivers */
+
+/* DVFS CPUfreq Drivers */
+
+#define RT_DVFS_RASPBERRY_CPUFREQ
+
+/* DVFS Devfreq Drivers */
+
+#define RT_USING_REGULATOR
+#define RT_REGULATOR_FIXED
+#define RT_REGULATOR_GPIO
+#define RT_USING_RESET
+#define RT_RESET_SIMPLE
+#define RT_RESET_BRCMSTB_RESCAL
+#define RT_RESET_BRCMSTB
+#define RT_RESET_RASPBERRYPI
/* Power Management (PM) Domains device drivers */
+#define RT_PMDOMAIN_BCM2835
+#define RT_PMDOMAIN_RASPBERRYPI
/* end of Power Management (PM) Domains device drivers */
+#define RT_USING_THERMAL
+
+/* Thermal Sensors Drivers */
+
+#define RT_THERMAL_BCM2835
+#define RT_THERMAL_BCM2711
+
+/* Thermal Cool Drivers */
+
+#define RT_THERMAL_COOL_DVFS
+#define RT_THERMAL_COOL_PWM_FAN
+#define RT_USING_DMA
+#define RT_DMA_DW_AXI_DMAC
+#define RT_DMA_BCM2835
+#define RT_USING_MFD
+#define RT_MFD_SYSCON
+#define RT_MFD_BCM2835_PM
+#define RT_MFD_RP1
+#define RT_MFD_RPI_SENSE
#define RT_USING_OFW
#define RT_FDT_EARLYCON_MSG_SIZE 128
#define RT_USING_OFW_BUS_RANGES_NUMBER 8
+#define RT_USING_PCI
+#define RT_PCI_MSI
+#define RT_PCI_SYS_64BIT
+#define RT_PCI_CACHE_LINE_SIZE 8
+
+/* PCI Device Drivers */
+
+#define RT_PCIE_BRCMSTB
#define RT_USING_PIC
-#define MAX_HANDLERS 256
+#define MAX_HANDLERS 1024
#define RT_PIC_ARM_GIC
#define RT_PIC_ARM_GIC_MAX_NR 1
+#define RT_PIC_BCM2712_MIP
+#define RT_PIC_BCM2835_INTC
+#define RT_PIC_BCM2836_L1_INTC
+#define RT_PIC_BRCMSTB_L2_IRQ
#define RT_USING_PIN
+#define RT_PIN_BCM_VIRT
+#define RT_PIN_BRCMSTB
+#define RT_PIN_RASPBERRYPI_EXP
+#define RT_USING_PINCTRL
+#define RT_PINCTRL_BCM2712
+#define RT_PINCTRL_BCM2835
+#define RT_PINCTRL_RP1
#define RT_USING_CLK
+#define RT_CLK_BCM2711_DVP
+#define RT_CLK_BCM2835
+#define RT_CLK_RASPBERRYPI
+#define RT_CLK_RP1
/* SoC (System on Chip) Drivers */
+#define RT_SOC_BROADCOM_RASPBERRYPI_VOLTAGE_MONITOR
+/* end of SoC (System on Chip) Drivers */
/* end of Device Drivers */
/* C/C++ and POSIX layer */
@@ -285,9 +426,12 @@
#define RT_USING_POSIX_DEVIO
#define RT_USING_POSIX_STDIO
#define RT_USING_POSIX_POLL
+#define RT_USING_POSIX_SELECT
+#define RT_USING_POSIX_EVENTFD
#define RT_USING_POSIX_EPOLL
#define RT_USING_POSIX_SIGNALFD
#define RT_SIGNALFD_MAX_NUM 10
+#define RT_USING_POSIX_TIMERFD
#define RT_USING_POSIX_TERMIOS
#define RT_USING_POSIX_DELAY
#define RT_USING_POSIX_CLOCK
@@ -295,6 +439,8 @@
/* Interprocess Communication (IPC) */
+#define RT_USING_POSIX_PIPE
+#define RT_USING_POSIX_PIPE_SIZE 512
/* Socket is in the 'Network' category */
@@ -321,9 +467,9 @@
#define NETDEV_IPV4 1
#define NETDEV_IPV6 0
#define RT_USING_LWIP
-#define RT_USING_LWIP212
-#define RT_USING_LWIP_VER_NUM 0x20102
-#define RT_LWIP_MEM_ALIGNMENT 4
+#define RT_USING_LWIP203
+#define RT_USING_LWIP_VER_NUM 0x20003
+#define RT_LWIP_MEM_ALIGNMENT 8
#define RT_LWIP_IGMP
#define RT_LWIP_ICMP
#define RT_LWIP_DNS
@@ -333,29 +479,27 @@
/* Static IPv4 Address */
-#define RT_LWIP_IPADDR "192.168.137.100"
-#define RT_LWIP_GWADDR "192.168.137.1"
+#define RT_LWIP_IPADDR "192.168.1.30"
+#define RT_LWIP_GWADDR "192.168.1.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
/* end of Static IPv4 Address */
#define RT_LWIP_UDP
#define RT_LWIP_TCP
#define RT_LWIP_RAW
-#define RT_MEMP_NUM_NETCONN 16
+#define RT_MEMP_NUM_NETCONN 8
#define RT_LWIP_PBUF_NUM 16
#define RT_LWIP_RAW_PCB_NUM 4
-#define RT_LWIP_UDP_PCB_NUM 8
-#define RT_LWIP_TCP_PCB_NUM 8
+#define RT_LWIP_UDP_PCB_NUM 4
+#define RT_LWIP_TCP_PCB_NUM 4
#define RT_LWIP_TCP_SEG_NUM 40
-#define RT_LWIP_TCP_SND_BUF 8192
-#define RT_LWIP_TCP_WND 8192
+#define RT_LWIP_TCP_SND_BUF 8196
+#define RT_LWIP_TCP_WND 8196
#define RT_LWIP_TCPTHREAD_PRIORITY 10
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
-#define RT_LWIP_TCPTHREAD_STACKSIZE 32768
-#define LWIP_NO_TX_THREAD
+#define RT_LWIP_TCPTHREAD_STACKSIZE 8192
#define RT_LWIP_ETHTHREAD_PRIORITY 12
-#define RT_LWIP_ETHTHREAD_STACKSIZE 32768
+#define RT_LWIP_ETHTHREAD_STACKSIZE 8192
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
-#define RT_LWIP_REASSEMBLY_FRAG
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define RT_LWIP_NETIF_NAMESIZE 6
@@ -364,8 +508,7 @@
#define LWIP_SO_SNDTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_SO_LINGER 0
-#define RT_LWIP_NETIF_LOOPBACK
-#define LWIP_NETIF_LOOPBACK 1
+#define LWIP_NETIF_LOOPBACK 0
#define RT_LWIP_USING_PING
/* end of Network */
@@ -375,10 +518,6 @@
/* Utilities */
-#define RT_USING_UTEST
-#define UTEST_THR_STACK_SIZE 8192
-#define UTEST_THR_PRIORITY 20
-#define RT_UTEST_MAX_OPTIONS 64
#define RT_USING_RESOURCE_ID
#define RT_USING_ADT
#define RT_USING_ADT_AVL
@@ -418,59 +557,6 @@
/* RT-Thread Utestcases */
-#define RT_USING_UTESTCASES
-
-/* Kernel Core */
-
-#define RT_UTEST_SCHEDULER
-
-/* SMP Test */
-
-/* end of SMP Test */
-/* end of Kernel Core */
-
-/* Kernel Components */
-
-/* Drivers */
-
-
-/* IPC Test */
-
-/* end of IPC Test */
-
-/* Serial Test */
-
-/* end of Serial Test */
-
-/* SMP-Call Test */
-
-/* end of SMP-Call Test */
-/* end of Drivers */
-
-/* File System */
-
-/* end of File System */
-
-/* CPP11 */
-
-/* end of CPP11 */
-
-/* Network */
-
-/* end of Network */
-
-/* Utest Framework */
-
-/* end of Utest Framework */
-/* end of Kernel Components */
-
-/* Memory Management Subsytem Testcase */
-
-/* end of Memory Management Subsytem Testcase */
-
-/* Tmpfs Testcase */
-
-/* end of Tmpfs Testcase */
/* end of RT-Thread Utestcases */
/* RT-Thread online packages */
@@ -594,14 +680,6 @@
/* GD32 Drivers */
/* end of GD32 Drivers */
-
-/* HPMicro SDK */
-
-/* end of HPMicro SDK */
-
-/* FT32 HAL & SDK Drivers */
-
-/* end of FT32 HAL & SDK Drivers */
/* end of HAL & SDK Drivers */
/* sensors drivers */
@@ -681,12 +759,6 @@
/* end of Arduino libraries */
/* end of RT-Thread online packages */
-#define BCM2711_SOC
-
-/* Hardware Drivers Config */
-
-#define BSP_USING_PL011
-#define BSP_USING_SDHCI
-/* end of Hardware Drivers Config */
+#define SOC_BCM2712
#endif
diff --git a/bsp/raspberry-pi/raspi5/rtconfig.py b/bsp/raspberry-pi/raspi5/rtconfig.py
new file mode 100755
index 0000000000..0d2b07daff
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/rtconfig.py
@@ -0,0 +1,88 @@
+import os
+import subprocess
+
+# toolchains options
+ARCH ='aarch64'
+CPU ='cortex-a'
+CROSS_TOOL ='gcc'
+
+if os.getenv('RTT_ROOT'):
+ RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+ RTT_ROOT = r'../../..'
+
+if os.getenv('RTT_CC'):
+ CROSS_TOOL = os.getenv('RTT_CC')
+
+PLATFORM = 'gcc'
+EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/'
+
+if os.getenv('RTT_EXEC_PATH'):
+ EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+
+PREFERRED_MTUNE = 'cortex-a76'
+MTUNE_FALLBACKS = ('cortex-a73', 'generic')
+
+def _gcc_supports_mtune(cc, exec_path, march, tune):
+ env = os.environ.copy()
+ if exec_path:
+ env['PATH'] = exec_path + os.pathsep + env.get('PATH', '')
+
+ try:
+ ret = subprocess.run(
+ [cc, '-march=' + march, '-mtune=' + tune, '-c', '-x', 'c', '-', '-o', os.devnull],
+ input=b'',
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ env=env,
+ check=False,
+ )
+ return ret.returncode == 0
+ except (OSError, subprocess.SubprocessError):
+ return False
+
+def resolve_mtune(cc, exec_path, preferred=PREFERRED_MTUNE, march='armv8-a',
+ fallbacks=MTUNE_FALLBACKS):
+ for tune in (preferred,) + fallbacks:
+ if _gcc_supports_mtune(cc, exec_path, march, tune):
+ if tune != preferred:
+ print('Note: %s does not support -mtune=%s, using -mtune=%s' % (
+ cc, preferred, tune))
+ return tune
+ return fallbacks[-1]
+
+BUILD = 'debug'
+
+if PLATFORM == 'gcc':
+ # toolchains
+ PREFIX = os.getenv('RTT_CC_PREFIX') or 'aarch64-none-elf-'
+ CC = PREFIX + 'gcc'
+ CXX = PREFIX + 'g++'
+ CPP = PREFIX + 'cpp'
+ AS = PREFIX + 'gcc'
+ AR = PREFIX + 'ar'
+ LINK = PREFIX + 'gcc'
+ TARGET_EXT = 'elf'
+ SIZE = PREFIX + 'size'
+ OBJDUMP = PREFIX + 'objdump'
+ OBJCPY = PREFIX + 'objcopy'
+
+ MTUNE = resolve_mtune(CC, EXEC_PATH)
+ DEVICE = ' -march=armv8-a -mtune=%s -fdiagnostics-color=always' % MTUNE
+ CPPFLAGS = ' -nostdinc -undef -E -P -x assembler-with-cpp'
+ CFLAGS = DEVICE + ' -Wall -Wno-cpp -D_POSIX_SOURCE'
+ AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
+ LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
+ CPATH = ''
+ LPATH = ''
+
+ if BUILD == 'debug':
+ CFLAGS += ' -O0 -ggdb'
+ AFLAGS += ' -ggdb'
+ else:
+ CFLAGS += ' -O2'
+
+ CXXFLAGS = CFLAGS
+
+DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
+POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
diff --git a/bsp/raspberry-pi/raspi5/tools/config.txt b/bsp/raspberry-pi/raspi5/tools/config.txt
new file mode 100644
index 0000000000..6b8cc37169
--- /dev/null
+++ b/bsp/raspberry-pi/raspi5/tools/config.txt
@@ -0,0 +1,2 @@
+kernel=u-boot.bin
+dtparam=pciex1
diff --git a/bsp/raspberry-pi/tools/sdk_dist.py b/bsp/raspberry-pi/tools/sdk_dist.py
new file mode 100644
index 0000000000..1eb07fc906
--- /dev/null
+++ b/bsp/raspberry-pi/tools/sdk_dist.py
@@ -0,0 +1,30 @@
+import os
+
+
+def update_dm_paths(dm_dir, dist_dir):
+ components_dir = os.path.join(dist_dir, 'rt-thread', 'components')
+
+ for root, dirs, files in os.walk(dm_dir):
+ if 'SConscript' not in files:
+ continue
+
+ sconscript_path = os.path.join(root, 'SConscript')
+ component_path = os.path.relpath(components_dir, root).replace(os.path.sep, '/')
+ with open(sconscript_path, 'r') as f:
+ data = f.read()
+
+ data = data.replace('../../../../components', component_path)
+
+ with open(sconscript_path, 'w') as f:
+ f.write(data)
+
+
+def dist_do_building(BSP_ROOT, dist_dir):
+ from mkdist import bsp_copy_files
+
+ dm_dir = os.path.join(os.path.dirname(dist_dir), 'dm')
+
+ print('=> copy raspberry-pi dm')
+ bsp_copy_files(os.path.join(os.path.dirname(BSP_ROOT), 'dm'),
+ dm_dir)
+ update_dm_paths(dm_dir, dist_dir)