diff --git a/bsp/raspberry-pi/raspi4-32/.config b/bsp/raspberry-pi/raspi4-32/.config index e0db6a3e95..e9231821d0 100644 --- a/bsp/raspberry-pi/raspi4-32/.config +++ b/bsp/raspberry-pi/raspi4-32/.config @@ -112,7 +112,23 @@ CONFIG_DFS_FILESYSTEMS_MAX=2 CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 CONFIG_DFS_FD_MAX=16 # CONFIG_RT_USING_DFS_MNTTABLE is not set -# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=2 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set @@ -140,14 +156,20 @@ CONFIG_RT_USING_PIN=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_SDIO is not set +CONFIG_RT_USING_SDIO=y +CONFIG_RT_SDIO_STACK_SIZE=512 +CONFIG_RT_SDIO_THREAD_PRIORITY=15 +CONFIG_RT_MMCSD_STACK_SIZE=1024 +CONFIG_RT_MMCSD_THREAD_PREORITY=22 +CONFIG_RT_MMCSD_MAX_PARTITION=16 +# CONFIG_RT_SDIO_DEBUG is not set CONFIG_RT_USING_SPI=y # 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_ENC28J60 is not set # CONFIG_RT_USING_SPI_WIFI is not set -# CONFIG_RT_USING_WDT is not set +CONFIG_RT_USING_WDT=y # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set @@ -170,6 +192,7 @@ CONFIG_RT_USING_LIBC=y CONFIG_RT_USING_POSIX=y # CONFIG_RT_USING_POSIX_MMAP is not set # CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set # CONFIG_RT_USING_MODULE is not set @@ -216,7 +239,9 @@ CONFIG_RT_USING_POSIX=y # # IoT - internet of things # +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set # CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set # CONFIG_PKG_USING_WEBCLIENT is not set # CONFIG_PKG_USING_WEBNET is not set # CONFIG_PKG_USING_MONGOOSE is not set @@ -262,7 +287,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set @@ -284,6 +309,10 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_CAPNP is not set # CONFIG_PKG_USING_RT_CJSON_TOOLS is not set # CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set # # security packages @@ -292,6 +321,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_libsodium is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set # # language packages @@ -308,6 +338,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set # CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set # # tools packages @@ -326,7 +357,9 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set # CONFIG_PKG_USING_LUNAR_CALENDAR is not set # CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set # CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set # # system packages @@ -337,6 +370,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set @@ -349,6 +383,11 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_SYSWATCH is not set # CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set # CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_PPOOL is not set # # peripheral libraries and drivers @@ -386,6 +425,7 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_RPLIDAR is not set # CONFIG_PKG_USING_AS608 is not set # CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set # CONFIG_PKG_USING_EMBARC_BSP is not set # CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set # CONFIG_PKG_USING_MULTI_RTIMER is not set @@ -393,6 +433,15 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_BEEP is not set # CONFIG_PKG_USING_EASYBLINK is not set # CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set # # miscellaneous packages @@ -429,6 +478,11 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set # # Privated Packages of RealThread @@ -461,6 +515,10 @@ CONFIG_RT_USING_POSIX=y # CONFIG_PKG_USING_ZBAR is not set # CONFIG_PKG_USING_MCF is not set # CONFIG_PKG_USING_URPC is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_DCM is not set +# CONFIG_PKG_USING_EMQ is not set +# CONFIG_PKG_USING_CFGM is not set CONFIG_BCM2711_SOC=y # CONFIG_BSP_SUPPORT_FPU is not set @@ -487,11 +545,13 @@ CONFIG_BSP_USING_SPI0_DEVICE0=y # CONFIG_BSP_USING_SPI0_DEVICE1 is not set CONFIG_BSP_USING_CORETIMER=y # CONFIG_BSP_USING_SYSTIMER is not set -# CONFIG_BSP_USING_WDT is not set +CONFIG_BSP_USING_WDT=y # CONFIG_BSP_USING_RTC is not set -# CONFIG_BSP_USING_SDIO is not set +CONFIG_BSP_USING_SDIO=y +CONFIG_BSP_USING_SDIO0=y # # Board Peripheral Drivers # -# CONFIG_BSP_USING_HDMI is not set +CONFIG_BSP_USING_HDMI=y +CONFIG_BSP_USING_HDMI_DISPLAY=y diff --git a/bsp/raspberry-pi/raspi4-32/README.md b/bsp/raspberry-pi/raspi4-32/README.md index 1034b3f467..98bd2d5df1 100644 --- a/bsp/raspberry-pi/raspi4-32/README.md +++ b/bsp/raspberry-pi/raspi4-32/README.md @@ -20,17 +20,8 @@ scons 来编译这个板级支持包。如果编译正确无误,会产生rtthread.elf、kernel7.img文件。 -## 3. 执行 - -### 3.1 下载**Raspberry Pi Imager**,生成可以运行的raspbian SD卡 - -首先下载镜像 - -* [Raspberry Pi Imager for Ubuntu](https://downloads.raspberrypi.org/imager/imager_amd64.deb) -* [Raspberry Pi Imager for Windows](https://downloads.raspberrypi.org/imager/imager.exe) -* [Raspberry Pi Imager for macOS](https://downloads.raspberrypi.org/imager/imager.dmg) - -### 3.2 准备好串口线 +## 3. 环境搭建 +### 3.1 准备好串口线 目前版本是使用raspi4的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示: @@ -38,27 +29,90 @@ scons 串口参数: 115200 8N1 ,硬件和软件流控为关。 -### 3.3 程序下载 +### 3.2 RTT固件放在SD卡运行 -当编译生成了rtthread.bin文件后,我们可以将该文件放到sd卡上,并修改sd卡中的`config.txt`文件如下: +首先需要准备一张空的32GB以下的SD卡,如果不想自己制作启动固件,可以直接从百度网盘上下载boot的固件。 ``` -enable_uart=1 -arm_64bit=0 -kernel_addr=0x8000 -kernel=kernel7.img -core_freq=250 +链接:https://pan.baidu.com/s/1PxgvXAChUIOgueNXhgMs8w +提取码:pioj ``` -按上面的方法做好SD卡后,插入树莓派4,通电可以在串口上看到如下所示的输出信息: +解压后将sd目录下的文件拷贝到sd卡即可。以后每次编译后,将生成的kernel7.img进行替换即可。上电后可以看到程序正常运行。 -```text -heap: 0x00044270 - 0x04044270 +### 3.3 RTT程序用uboot加载 + +为了调试方便,已经将uboot引导程序放入uboot目录下,直接将这些文件放到sd卡中即可。 + +需要注意的以下步骤: + +**1.电脑上启动tftp服务器** + +windows系统电脑上可以安装tftpd搭建tftp服务器。将目录指定到`bsp\raspberry-pi\raspi4-32`。 + +**2.修改设置uboot** + +在控制台输入下列命令: + +``` +setenv bootcmd "dhcp 0x00200000 x.x.x.x:kernel7.img;dcache flush;go 0x00200000" +saveenv +reset +``` + +其中`x.x.x.x`为tftp服务器的pc的ip地址。 + +**3.修改链接脚本** + +将树莓派`bsp\raspberry-pi\raspi4-32\link.ld`的文件链接地址改为`0x200000`。 + +``` +SECTIONS +{ + . = 0x8000; + . = ALIGN(4096); + . + . + . +} +``` + +改为 + +``` +SECTIONS +{ + . = 0x200000; + . = ALIGN(4096); + . + . + . +} +``` + +重新编译程序: + +``` +scons -c +scons +``` + +**3.插入网线** + +上述准备完成后,将网线插入,保证开发板和tftp服务器在同一个网段的路由器上。上电后uboot可以自动从tftp服务器上获取固件,然后开始执行了。 + +完成后可以看到串口的输出信息 + +``` +heap: 0x000607e8 - 0x040607e8 \ | / - RT - Thread Operating System - / | \ 4.0.3 build May 25 2020 + / | \ 4.0.3 build Oct 27 2020 2006 - 2020 Copyright by rt-thread team +[I/SDIO] SD card capacity 31205376 KB. +found part[0], begin: 1048576, size: 29.777GB +file system initialization done! Hi, this is RT-Thread!! msh /> ``` @@ -71,8 +125,15 @@ msh /> | GPIO | 支持 | - | | SPI | 支持 | SPI0 | | MAILBOX | 支持 | - | +| WATCHDOG | 支持 | - | +| HDMI | 支持 | - | +| SDIO | 支持 | - | -## 5. 联系人信息 +## 5. 注意事项 + +目前rt-thread程序可以使用的内存在100MB以内,可以通过调整`board.c`中`platform_mem_desc`表的数据进行相关内存的映射以及修改`board.h`来确定程序使用的堆栈大小。目前在地址`0x08000000`处的1M空间被映射成非cache区供树莓派4的CPU与GPU通信的消息管道。若需要扩大系统内存使用,可自行修改代码进行调整。 + +## 6. 联系人信息 维护人:[bernard][5] diff --git a/bsp/raspberry-pi/raspi4-32/applications/main.c b/bsp/raspberry-pi/raspi4-32/applications/main.c index 9664e67d01..15dc74dc58 100644 --- a/bsp/raspberry-pi/raspi4-32/applications/main.c +++ b/bsp/raspberry-pi/raspi4-32/applications/main.c @@ -12,8 +12,20 @@ #include #include +#define ACTLED (42) + int main(int argc, char** argv) { rt_kprintf("Hi, this is RT-Thread!!\n"); - return 0; + + rt_pin_mode(ACTLED, PIN_MODE_OUTPUT); + + while(1) + { + rt_pin_write(ACTLED, PIN_HIGH); + rt_thread_mdelay(1000); + rt_pin_write(ACTLED, PIN_LOW); + rt_thread_mdelay(1000); + } + return RT_EOK; } diff --git a/bsp/raspberry-pi/raspi4-32/applications/mnt.c b/bsp/raspberry-pi/raspi4-32/applications/mnt.c new file mode 100644 index 0000000000..ae224e8e89 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/applications/mnt.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 bernard the first version + */ + +#include + +#ifdef BSP_USING_SDIO0 +#include + +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/raspi4-32/driver/board.c b/bsp/raspberry-pi/raspi4-32/driver/board.c index 7a3524126d..242a14cc78 100644 --- a/bsp/raspberry-pi/raspi4-32/driver/board.c +++ b/bsp/raspberry-pi/raspi4-32/driver/board.c @@ -19,8 +19,10 @@ struct mem_desc platform_mem_desc[] = { {0x0, 0x6400000, 0x0, NORMAL_MEM}, - {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM},//uart gpio - {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM} //gic + {0x8000000, 0x8100000, 0x8000000, DEVICE_MEM}, //mbox msg + {0x0EA00000, 0x0EE00000, 0x0EA00000, DEVICE_MEM}, //framebuffer + {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM}, //peripheral + {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM} //gic }; const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]); diff --git a/bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.c b/bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.c new file mode 100644 index 0000000000..a8d68fd9cf --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.c @@ -0,0 +1,309 @@ +/* + * 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 +#include +#include "mbox.h" +#include "drv_hdmi.h" + +#ifdef BSP_USING_HDMI +#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; +} + +#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 *)((rt_uint32_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); + 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-32/driver/drv_hdmi.h b/bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.h new file mode 100644 index 0000000000..c9a06358d0 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.h @@ -0,0 +1,27 @@ +/* + * 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-32/driver/drv_sdio.c b/bsp/raspberry-pi/raspi4-32/driver/drv_sdio.c new file mode 100644 index 0000000000..8d34f3ab73 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_sdio.c @@ -0,0 +1,656 @@ +/* + * 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(rt_uint32_t addr) +{ + return (*((volatile unsigned int*)(addr))); +} + +static inline void write32(rt_uint32_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 + mmc_base_clock = bcm271x_mbox_clock_get_rate(12); + 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) +{ + 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)); + + virt = MMC2_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 = 250 * 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/raspi4-32/driver/drv_sdio.h b/bsp/raspberry-pi/raspi4-32/driver/drv_sdio.h new file mode 100644 index 0000000000..5919bd64d3 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_sdio.h @@ -0,0 +1,253 @@ +/* + * 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 +#include +#include + +#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 +{ + 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_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-32/driver/drv_wdt.c b/bsp/raspberry-pi/raspi4-32/driver/drv_wdt.c new file mode 100644 index 0000000000..3c091354bb --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_wdt.c @@ -0,0 +1,135 @@ +/* + * 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 +#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 reboot(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(reboot,reboot system...); +#endif /*BSP_USING_WDT */ diff --git a/bsp/raspberry-pi/raspi4-32/driver/drv_wdt.h b/bsp/raspberry-pi/raspi4-32/driver/drv_wdt.h new file mode 100644 index 0000000000..4c9454ed91 --- /dev/null +++ b/bsp/raspberry-pi/raspi4-32/driver/drv_wdt.h @@ -0,0 +1,25 @@ +/* + * 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_WDT_H__ +#define __DRV_WDT_H__ + +#include +#include + +#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-32/driver/mbox.c b/bsp/raspberry-pi/raspi4-32/driver/mbox.c index 186440ffce..b0c79e09bd 100644 --- a/bsp/raspberry-pi/raspi4-32/driver/mbox.c +++ b/bsp/raspberry-pi/raspi4-32/driver/mbox.c @@ -49,6 +49,52 @@ int mbox_call(unsigned char ch, int mmu_enable) return 0; } +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 diff --git a/bsp/raspberry-pi/raspi4-32/driver/mbox.h b/bsp/raspberry-pi/raspi4-32/driver/mbox.h index bf9ac0e96d..ec31370f6b 100644 --- a/bsp/raspberry-pi/raspi4-32/driver/mbox.h +++ b/bsp/raspberry-pi/raspi4-32/driver/mbox.h @@ -35,7 +35,7 @@ extern volatile unsigned int* mbox; /* tags */ #define MBOX_TAG_SETPOWER 0x28001 #define MBOX_TAG_SETCLKRATE 0x38002 -#define MBOX_GET_MAC_ADDRESS 0x10003 +#define MBOX_GET_MAC_ADDRESS 0x10003 #define MBOX_TAG_LAST 0 #define MMIO_BASE 0xFE000000 @@ -50,14 +50,14 @@ extern volatile unsigned int* mbox; #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 +#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 @@ -102,9 +102,42 @@ enum { MBOX_TAG_TEMP_GET_MAX = 0x0003000A, }; -#define MBOX_ADDR 0xc00000 +/* + * 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 + +#define MBOX_ADDR 0x08000000 int mbox_call(unsigned char ch, int mmu_enable); +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); diff --git a/bsp/raspberry-pi/raspi4-32/driver/raspi4.h b/bsp/raspberry-pi/raspi4-32/driver/raspi4.h index f874696705..5a91796d40 100644 --- a/bsp/raspberry-pi/raspi4-32/driver/raspi4.h +++ b/bsp/raspberry-pi/raspi4-32/driver/raspi4.h @@ -119,6 +119,39 @@ typedef enum { #define GIC_ACK_INTID_MASK 0x000003ff +//watchdog +#define PM_RSTC HWREG32(PER_BASE + 0x0010001c) +#define PM_RSTS HWREG32(PER_BASE + 0x00100020) +#define PM_WDOG HWREG32(PER_BASE + 0x00100024) + +#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) +#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) \ + +//External Mass Media Controller (SD Card) +#define MMC0_BASE_ADDR (PER_BASE+0x300000) +#define MMC2_BASE_ADDR (PER_BASE+0x340000) + /* the basic constants and interfaces needed by gic */ rt_inline rt_uint32_t platform_get_gic_dist_base(void) { diff --git a/bsp/raspberry-pi/raspi4-32/rtconfig.h b/bsp/raspberry-pi/raspi4-32/rtconfig.h index c5ad40fc0b..f7a5e8de27 100644 --- a/bsp/raspberry-pi/raspi4-32/rtconfig.h +++ b/bsp/raspberry-pi/raspi4-32/rtconfig.h @@ -76,6 +76,18 @@ #define DFS_FILESYSTEMS_MAX 2 #define DFS_FILESYSTEM_TYPES_MAX 2 #define DFS_FD_MAX 16 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_REENTRANT #define RT_USING_DFS_DEVFS /* Device Drivers */ @@ -86,7 +98,14 @@ #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 #define RT_USING_SPI +#define RT_USING_WDT /* Using USB */ @@ -178,8 +197,13 @@ #define BSP_USING_SPI0_BUS #define BSP_USING_SPI0_DEVICE0 #define BSP_USING_CORETIMER +#define BSP_USING_WDT +#define BSP_USING_SDIO +#define BSP_USING_SDIO0 /* Board Peripheral Drivers */ +#define BSP_USING_HDMI +#define BSP_USING_HDMI_DISPLAY #endif