【STM32MP135F-DK】硬件资源测试:玩转GPIO
本帖最后由 fangkaixin 于 2024-1-1 15:50 编辑<div>前面介绍了如何通过简单的配置,对Linux设备树进行修改,实现在用户空间通过sysfs来控制LED灯亮灭,大家对STM32MP135F-DK的引脚控制应该有了简单的认识,接下来就详细介绍下Linux中控制GPIO的方法。</div>
<div>实际Linux上控制GPIO的方式是非常多样化的,可以满足不同类型用户的需求,今天带大家一起基于STM32MP135F-DK套件的Linux系统来玩转GPIO,还是以LED为例,主要通过另外两个方面来进行测试验证:</div>
<div>一是在系统内核空间,通过修改内核驱动来控制LED;</div>
<div>二是在用户空间,用C代码通过mmap直接对LED进行控制</div>
<div> </div>
<div>
<hr />
<p> </p>
</div>
<h2>概念介绍</h2>
<div>每个ST微控制器管脚都经过多路复用,以支持多种功能。可以配置为以下在三种模式:</div>
<ul>
<li>通用输入/输出GPIO:由软件控制</li>
<li>模拟GPIO:由硬件模块直接控制</li>
<li>Alternate功能:由硬件模块直接控制</li>
</ul>
<div>可以使用两种框架来配置和控制给定的引脚:<strong>pinctrl</strong> 和 <strong>GPIOLib</strong>。</div>
<ul>
<li><strong>Pinctrl</strong> 主要用于引脚由内部外设控制的情况。Pinctrl 处理引脚配置,并允许将特定功能分配给引脚。</li>
<li><strong>GPIOLib</strong> 用于需要在运行时动态控制引脚的情况。GPIOLib 用于通过软件控制引脚。</li>
</ul>
<div>此外,当引脚用作外部中断源时,Irqchip框架提供了一个允许配置此中断的 API。</div>
<div>引脚管理框架</div>
<div></div>
<hr />
<h2>通过内核驱动控制LED</h2>
<div>目标:使用ST的gpiolib框架,在内核层实现对LED(GPIO-PA13)的控制</div>
<div>步骤:</div>
<ul>
<li><em><strong>修改设备树,添加对应的GPIO设备文件描述,并重新编译设备树文件</strong></em></li>
</ul>
<p><em>make ARCH=arm </em><em>dtbs</em><em> LOADADDR=0xC2000040</em></p>
<div></div>
<div></div>
<div></div>
<ul>
<li><em><strong>编写内核模块代码,Makefile文件,并编译</strong></em></li>
</ul>
<p><em>make</em></p>
<p><em>make install</em></p>
<div></div>
<div></div>
<div></div>
<ul>
<li><em><strong>更新设备树和设备模块到开发板</strong></em></li>
</ul>
<p><em>scp</em><em> arch/arm/boot/</em><em>dts</em><em>/stm32mp135*.</em><em>dtb</em> <a href="mailto:root@%3cyour.ip.address.x%3e:/boot"><em>root@<your.ip.address.x>:/boot</em></a></p>
<p><em>scp</em><em> outputs/lib/modules/6.1.28/extra/</em><em>red_</em><em>led.ko</em> <a href="mailto:root@%3cyour.ip.address.x%3e:/lib/modules">root@<your.ip.address.x>:/lib/modules</a><em>/</em><em>6.1.28</em> <em>red_led.ko</em></p>
<div></div>
<div></div>
<ul>
<li><em><strong>更新内核模块依赖,同步内存后重启</strong></em></li>
</ul>
<p></p>
<ul>
<li><em><strong>加载内核模块验证</strong></em></li>
</ul>
<p>检查当前gpio状态(以防有gpio冲突)</p>
<div></div>
<p><em>modprobe</em> <em>red_led</em></p>
<p>效果:led快速闪烁<br />
</p>
<ul>
<li>退出</li>
</ul>
<p><em>rmmod</em> <em>red_led</em></p>
<div></div>
<hr />
<h2>在用户空间编写C代码通过mmap方法直接控制LED</h2>
<div>在用户空间中控制LED,前面介绍了sysfs操作的方法,这里介绍另一种方式:mmap。mmap可以将物理设备/dev/mem映射到内存,通过读写内存的方式操作GPIO寄存器,由于避免了系统调用,不需要用户空间和内核空间频繁切换,可以提高使用效率。</div>
<div>还是以上面的红色LED:GPIO-PA13为例</div>
<div>我们先查找一下手册中该GPIO的内存地址:参考手册下载地址<a href="https://www.st.com/resource/en/reference_manual/DM00670465-.pdf">STM32MP13xx advanced Arm<Sup>®</Sup>-based 32-bit MPUs - Reference manual</a></div>
<div></div>
<div></div>
<div>可以看到GPIOA的内存起始地址是<span style="color:#3498db;">0x50002000 ~ 0x500023FF</span></div>
<div>接着找到相关寄存器,进行配置,以下是寄存器地址</div>
<div><span style="font-size:18px;"><em><strong>配置相关寄存器</strong></em></span></div>
<div></div>
<div></div>
<div><strong><em>1)MODER寄存器用来配置GPIO的模式,这里我们需要配置为输出0x01</em></strong></div>
<div></div>
<div>从图中可以看出PA13对应的MODER13是对应寄存器的bit27和bit26,可以编写配置代码如下</div>
<div></div>
<div><strong><em>2)OTYPER寄存器,配置为推挽输出状态,0x00</em></strong></div>
<div></div>
<div></div>
<div><em><strong>3)BSRR寄存器用来</strong>改变管脚状态高电平还是低电平,这是一个只写寄存器,<strong>对寄存器高</strong><strong> 16bit </strong><strong>写</strong><strong>1 </strong><strong>对应管脚为</strong><strong>低</strong><strong>电平,对寄存器低</strong><strong>16bit</strong><strong>写</strong><strong>1</strong><strong>对应管脚为</strong><strong>高</strong><strong>电平。写</strong><strong> 0 ,</strong><strong>无动作</strong></em></div>
<div>用来控制电平的翻转,实现LED的闪烁效果</div>
<div></div>
<div></div>
<div>
<hr /><span style="font-size:18px;"><strong>效果展示:</strong></span></div>
<div>e96e59d4ce1819159a16831533495346<br />
本文中涉及到的代码:</div>
<div>
<pre>
<code class="language-cpp">/*led内核模块*/
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/timer.h>
struct gpio_desc *red;
struct timer_list timer;
static void led_expires(struct timer_list *t)
{
int toggle;
if(t == &timer){
printk("red led toggled\n");
toggle = gpiod_get_value(red);
gpiod_set_value(red, !toggle);
mod_timer(t, jiffies + HZ/50);
}
}
static int gpio_init_probe(struct platform_device *pdev)
{
printk("Start example gpio red blink\n");
red = devm_gpiod_get(&pdev->dev, "redled", GPIOD_OUT_LOW);
timer_setup(&timer, led_expires, 0);
mod_timer(&timer, jiffies + HZ/50);
printk("start timer\n");
return(0);
}
static int gpio_exit_remove(struct platform_device *pdev)
{
printk("Example gpio red blink exit\n");
del_timer(&timer);
return(0);
}
static struct of_device_id foo_match[] = {
{.compatible = "gpio-redled"},
{}
};
static struct platform_driver foo_driver = {
.probe = gpio_init_probe,
.remove = gpio_exit_remove,
.driver = {
.name = "foo_driver",
.owner = THIS_MODULE,
.of_match_table = foo_match,
}
};
module_platform_driver(foo_driver);
MODULE_AUTHOR("Frank");
MODULE_DESCRIPTION("Gpio red flash");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:foo_driver");</code></pre>
<pre>
<code class="language-cpp"># Makefile for external out-of-tree Linux kernel module
/*内核模块对应的Makefile*/
# Object file(s) to be built
obj-m := red_led.o
# Path to the directory that contains the Linux kernel source code
# and the configuration file (.config)
KERNEL_DIR ?= /home/frank/STM32MP135F-DK/source/stm32mp1-openstlinux-6.1-yocto-mickledore-mp1-v23.06.21/sources/arm-ostl-linux-gnueabi/linux-stm32mp-6.1.28-stm32mp-r1-r0/linux-6.1.28
# Path to the directory that contains the generated objects
DESTDIR ?= /home/frank/STM32MP135F-DK/demo/test_leds/outputs
# Path to the directory that contains the source file(s) to compile
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) INSTALL_MOD_PATH=$(DESTDIR) modules_install
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean</code></pre>
<pre>
<code class="language-cpp">/*led应用程序*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#define MEM_DEV "/dev/mem"
#define GPIOA_START_ADDR 0x50002000
#define GPIOA_END_ADDR 0x500023FF
#define GPIOA_MAP_SIZE (GPIOA_END_ADDR - GPIOA_START_ADDR)
#define GPIO_REG_MODER 0x00 /**< GPIO port mode register */
#define GPIO_REG_OTYPER 0x04 /**< GPIO port output type register */
#define GPIO_REG_BSRR 0x18 /**< GPIO port bit set/reset register */
#define GPIO_PIN_13 ((uint16_t)0x2000U)
#define GPIO_PIN_OUTPUT_DIRECTION 0x01 /**< Output */
#define GPIO_PIN_OUTPUT_PUSHPULL 0x00 /**< Output Push Pull Mode */
#define GPIO_PIN_13_REG_DEFINITION (GPIOA_START_ADDR+GPIO_PIN_13)
int main(int argc, char **argv)
{
int ret = EXIT_SUCCESS;
static void *mmapBase = NULL; /* Virtual base address */
/* Try to open the mem device special file */
int fdMem = open(MEM_DEV, O_RDWR | O_SYNC);
if (fdMem < 1)
{
exit(1);
}
/* Map memory region for the gpio registers */
mmapBase = mmap(NULL,
GPIOA_MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fdMem,
GPIOA_START_ADDR);
if (mmapBase == (void*) -1)
{
exit(1);
}
{ /* MODER */
/* Load the different gpio register pointers with its address */
volatile uint32_t *gpioRegAddr = mmapBase + GPIO_REG_MODER;
/* Get the value of the gpio direction register */
uint32_t gpioRegVal = *gpioRegAddr;
/* Clear the GPIO, write it back to the direction register */
gpioRegVal &= ~(0x03 << (13 * 2)); /* mask out the 2 bits giving the direction */
gpioRegVal |= ((GPIO_PIN_OUTPUT_DIRECTION) << (13 * 2));
*gpioRegAddr = gpioRegVal;
}
{ /* OTYPE */
/* Load the different gpio register pointers with its address */
volatile uint32_t *gpioRegAddr = mmapBase + GPIO_REG_OTYPER;
/* Get the value of the gpio direction register */
uint32_t gpioRegVal = *gpioRegAddr;
/* Clear the GPIO, write it back to the direction register */
gpioRegVal &= ~(0x0 << (13)); /* mask out */
gpioRegVal |= ((GPIO_PIN_OUTPUT_PUSHPULL) << (13));
*gpioRegAddr = gpioRegVal;
}
volatile uint32_t *const gpioSetClearDataOutAddr = mmapBase + GPIO_REG_BSRR;
while(1)
{
*gpioSetClearDataOutAddr = GPIO_PIN_13; /* set the pin */
usleep(50*1000);
*gpioSetClearDataOutAddr = (uint32_t)(GPIO_PIN_13 << 16); /* reset the pin */
usleep(50*1000);
}
return ret;
}</code></pre>
<pre>
<code class="language-cpp">/*应用程序对应的Makefile*/
PROG = led
SRCS = led.c
CLEANFILES = $(PROG)
# Add / change option in CFLAGS and LDFLAGS
CFLAGS += -Wall
LDFLAGS +=
all: $(PROG)
$(PROG): $(SRCS)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
clean:
rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS))</code></pre>
<pre>
<code class="language-cpp">//设备树
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (C) STMicroelectronics 2021 - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/regulator/st,stm32mp13-regulator.h>
#include <dt-bindings/rtc/rtc-stm32.h>
#include "stm32mp135.dtsi"
#include "stm32mp13xf.dtsi"
#include "stm32mp13-pinctrl.dtsi"
/ {
model = "STMicroelectronics STM32MP135F-DK Discovery Board";
compatible = "st,stm32mp135f-dk", "st,stm32mp135";
aliases {
ethernet0 = &eth1;
ethernet1 = &eth2;
serial0 = &uart4;
serial1 = &usart1;
serial2 = &uart8;
serial3 = &usart2;
};
chosen {
stdout-path = "serial0:115200n8";
#address-cells = <1>;
#size-cells = <1>;
ranges;
framebuffer {
compatible = "simple-framebuffer";
clocks = <&rcc LTDC_PX>;
status = "disabled";
};
};
clocks {
clk_ext_camera: clk-ext-camera {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
clk_mco1: clk-mco1 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
};
memory@c0000000 {
device_type = "memory";
reg = <0xc0000000 0x20000000>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
optee@dd000000 {
reg = <0xdd000000 0x3000000>;
no-map;
};
};
gpio-keys {
compatible = "gpio-keys";
// user-pa13 {
// label = "User-PA13";
// linux,code = <BTN_1>;
// gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
// };
};
leds {
compatible = "gpio-leds";
led-blue {
function = LED_FUNCTION_HEARTBEAT;
color = <LED_COLOR_ID_BLUE>;
gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
// led-red {
// function = LED_FUNCTION_ACTIVITY;
// color = <LED_COLOR_ID_RED>;
// gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
// linux,default-trigger = "active";
// default-state = "off";
// };
};
foo_device {
compatible = "gpio-redled";
status = "okay";
redled-gpios = <&gpioa 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
};
panel_backlight: panel-backlight {
compatible = "gpio-backlight";
gpios = <&gpioe 12 GPIO_ACTIVE_HIGH>;
default-on;
default-brightness-level = <0>;
status = "okay";
};
panel_rgb: panel-rgb {
compatible = "rocktech,rk043fn48h", "panel-dpi";
enable-gpios = <&gpioi 7 GPIO_ACTIVE_HIGH>;
backlight = <&panel_backlight>;
power-supply = <&scmi_v3v3_sw>;
data-mapping = "bgr666";
status = "okay";
width-mm = <105>;
height-mm = <67>;
port {
panel_in_rgb: endpoint {
remote-endpoint = <&ltdc_out_rgb>;
};
};
panel-timing {
clock-frequency = <10000000>;
hactive = <480>;
vactive = <272>;
hsync-len = <52>;
hfront-porch = <10>;
hback-porch = <10>;
vsync-len = <10>;
vfront-porch = <10>;
vback-porch = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <1>;
};
};
v3v3_ao: v3v3-ao {
compatible = "regulator-fixed";
regulator-name = "v3v3_ao";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
wake_up {
compatible = "gpio-keys";
status = "okay";
button {
label = "wake-up";
linux,code = <KEY_WAKEUP>;
interrupts-extended = <&optee 0>;
status = "okay";
};
};
wifi_pwrseq: wifi-pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&mcp23017 11 GPIO_ACTIVE_LOW>;
};
};
&adc_1 {
pinctrl-names = "default";
pinctrl-0 = <&adc1_usb_cc_pins_a>;
vdda-supply = <&scmi_vdd_adc>;
vref-supply = <&scmi_vdd_adc>;
status = "okay";
adc1: adc@0 {
status = "okay";
/*
* Type-C USB_PWR_CC1 & USB_PWR_CC2 on in6 & in12.
* Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C:
* 5 * (5.1 + 47kOhms) * 5pF => 1.3us.
* Use arbitrary margin here (e.g. 5us).
*/
channel@6 {
reg = <6>;
st,min-sample-time-ns = <5000>;
};
channel@12 {
reg = <12>;
st,min-sample-time-ns = <5000>;
};
};
};
&arm_wdt {
timeout-sec = <32>;
status = "okay";
};
&crc1 {
status = "okay";
};
&cryp {
status = "okay";
};
&dcmipp {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&dcmipp_pins_a>;
pinctrl-1 = <&dcmipp_sleep_pins_a>;
port {
dcmipp_0: endpoint {
remote-endpoint = <&mipid02_2>;
bus-width = <8>;
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <0>;
pclk-max-frequency = <120000000>;
};
};
};
&dts {
status = "okay";
};
&eth1 {
status = "okay";
pinctrl-0 = <&eth1_rmii_pins_a>;
pinctrl-1 = <&eth1_rmii_sleep_pins_a>;
pinctrl-names = "default", "sleep";
phy-mode = "rmii";
max-speed = <100>;
phy-handle = <&phy0_eth1>;
nvmem-cells = <&ethernet_mac1_address>;
nvmem-cell-names = "mac-address";
mdio1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0_eth1: ethernet-phy@0 {
compatible = "ethernet-phy-id0007.c131";
reset-gpios =<&mcp23017 9 GPIO_ACTIVE_LOW>;
reg = <0>;
wakeup-source;
};
};
};
&eth2 {
status = "okay";
pinctrl-0 = <&eth2_rmii_pins_a>;
pinctrl-1 = <&eth2_rmii_sleep_pins_a>;
pinctrl-names = "default", "sleep";
phy-mode = "rmii";
max-speed = <100>;
phy-handle = <&phy0_eth2>;
st,ext-phyclk;
phy-supply = <&scmi_v3v3_sw>;
nvmem-cells = <&ethernet_mac2_address>;
nvmem-cell-names = "mac-address";
mdio1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0_eth2: ethernet-phy@0 {
compatible = "ethernet-phy-id0007.c131";
reset-gpios = <&mcp23017 10 GPIO_ACTIVE_LOW>;
reg = <0>;
};
};
};
&i2c1 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c1_pins_a>;
pinctrl-1 = <&i2c1_sleep_pins_a>;
i2c-scl-rising-time-ns = <96>;
i2c-scl-falling-time-ns = <3>;
clock-frequency = <1000000>;
status = "okay";
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
mcp23017: pinctrl@21 {
compatible = "microchip,mcp23017";
reg = <0x21>;
gpio-controller;
#gpio-cells = <2>;
interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpiog>;
pinctrl-names = "default";
pinctrl-0 = <&mcp23017_pins_a>;
interrupt-controller;
#interrupt-cells = <2>;
microchip,irq-mirror;
};
typec@53 {
compatible = "st,stm32g0-typec";
reg = <0x53>;
/* Alert pin on PI2 (PWR wakeup pin), managed by optee */
interrupts-extended = <&optee 1>;
firmware-name = "stm32g0-ucsi.mp135f-dk.fw";
wakeup-source;
connector {
compatible = "usb-c-connector";
label = "USB-C";
port {
con_usb_c_g0_ep: endpoint {
remote-endpoint = <&usbotg_hs_ep>;
};
};
};
};
};
&i2c5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_pins_a>;
pinctrl-1 = <&i2c5_sleep_pins_a>;
i2c-scl-rising-time-ns = <170>;
i2c-scl-falling-time-ns = <5>;
clock-frequency = <400000>;
status = "okay";
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
stmipi: stmipi@14 {
compatible = "st,st-mipid02";
reg = <0x14>;
status = "okay";
clocks = <&clk_mco1>;
clock-names = "xclk";
VDDE-supply = <&scmi_v1v8_periph>;
VDDIN-supply = <&scmi_v1v8_periph>;
reset-gpios = <&mcp23017 2 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mipid02_0: endpoint {
data-lanes = <1 2>;
lane-polarities = <0 0 0>;
remote-endpoint = <&gc2145_ep>;
};
};
port@2 {
reg = <2>;
mipid02_2: endpoint {
bus-width = <8>;
hsync-active = <0>;
vsync-active = <0>;
pclk-sample = <0>;
remote-endpoint = <&dcmipp_0>;
};
};
};
};
gc2145: gc2145@3c {
compatible = "galaxycore,gc2145";
reg = <0x3c>;
clocks = <&clk_ext_camera>;
IOVDD-supply = <&scmi_v3v3_sw>;
AVDD-supply = <&scmi_v3v3_sw>;
DVDD-supply = <&scmi_v3v3_sw>;
powerdown-gpios = <&mcp23017 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
reset-gpios = <&mcp23017 4 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
status = "okay";
port {
gc2145_ep: endpoint {
remote-endpoint = <&mipid02_0>;
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
};
ov5640: camera@3c {
compatible = "ovti,ov5640";
reg = <0x3c>;
clocks = <&clk_ext_camera>;
clock-names = "xclk";
DOVDD-supply = <&scmi_v3v3_sw>;
status = "disabled";
powerdown-gpios = <&mcp23017 3 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
reset-gpios = <&mcp23017 4 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
port {
ov5640_0: endpoint {
/*remote-endpoint = <&mipid02_0>;*/
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
};
goodix: goodix-ts@5d {
compatible = "goodix,gt911";
reg = <0x5d>;
pinctrl-names = "default";
pinctrl-0 = <&goodix_pins_a>;
interrupt-parent = <&gpiof>;
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpioh 2 GPIO_ACTIVE_LOW>;
AVDD28-supply = <&scmi_v3v3_sw>;
VDDIO-supply = <&scmi_v3v3_sw>;
touchscreen-size-x = <480>;
touchscreen-size-y = <272>;
status = "okay" ;
};
};
&ltdc {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&ltdc_pins_a>;
pinctrl-1 = <&ltdc_sleep_pins_a>;
status = "okay";
port {
ltdc_out_rgb: endpoint {
remote-endpoint = <&panel_in_rgb>;
};
};
};
&rtc {
st,lsco = <RTC_OUT2_RMP>;
pinctrl-0 = <&rtc_out2_rmp_pins_a>;
pinctrl-names = "default";
status = "okay";
};
&scmi_regu {
scmi_vddcpu: voltd-vddcpu {
reg = <VOLTD_SCMI_STPMIC1_BUCK1>;
regulator-name = "vddcpu";
};
scmi_vdd: voltd-vdd {
reg = <VOLTD_SCMI_STPMIC1_BUCK3>;
regulator-name = "vdd";
};
scmi_vddcore: voltd-vddcore {
reg = <VOLTD_SCMI_STPMIC1_BUCK4>;
regulator-name = "vddcore";
};
scmi_vdd_adc: voltd-vdd-adc {
reg = <VOLTD_SCMI_STPMIC1_LDO1>;
regulator-name = "vdd_adc";
};
scmi_vdd_usb: voltd-vdd-usb {
reg = <VOLTD_SCMI_STPMIC1_LDO4>;
regulator-name = "vdd_usb";
};
scmi_vdd_sd: voltd-vdd-sd {
reg = <VOLTD_SCMI_STPMIC1_LDO5>;
regulator-name = "vdd_sd";
};
scmi_v1v8_periph: voltd-v1v8-periph {
reg = <VOLTD_SCMI_STPMIC1_LDO6>;
regulator-name = "v1v8_periph";
};
scmi_v3v3_sw: voltd-v3v3-sw {
reg = <VOLTD_SCMI_STPMIC1_PWR_SW2>;
regulator-name = "v3v3_sw";
};
};
&sdmmc1 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>;
pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_clk_pins_a>;
pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
cd-gpios = <&gpioh 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
disable-wp;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&scmi_vdd_sd>;
status = "okay";
};
/* Wifi */
&sdmmc2 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_clk_pins_a>;
pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_clk_pins_a>;
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a>;
non-removable;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&v3v3_ao>;
mmc-pwrseq = <&wifi_pwrseq>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
brcmf: bcrmf@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
interrupt-parent = <&gpiof>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; /* WL_HOST_WAKE */
interrupt-names = "host-wake";
};
};
&spi5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&spi5_pins_a>;
pinctrl-1 = <&spi5_sleep_pins_a>;
status = "disabled";
};
&timers3 {
/delete-property/dmas;
/delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm3_pins_a>;
pinctrl-1 = <&pwm3_sleep_pins_a>;
pinctrl-names = "default", "sleep";
status = "okay";
};
timer@2 {
status = "okay";
};
};
&timers4 {
/delete-property/dmas;
/delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm4_pins_a>;
pinctrl-1 = <&pwm4_sleep_pins_a>;
pinctrl-names = "default", "sleep";
status = "okay";
};
timer@3 {
status = "okay";
};
};
&timers8 {
/delete-property/dmas;
/delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm8_pins_a>;
pinctrl-1 = <&pwm8_sleep_pins_a>;
pinctrl-names = "default", "sleep";
status = "okay";
};
timer@7 {
status = "okay";
};
};
&timers14 {
status = "disabled";
pwm {
pinctrl-0 = <&pwm14_pins_a>;
pinctrl-1 = <&pwm14_sleep_pins_a>;
pinctrl-names = "default", "sleep";
status = "okay";
};
timer@13 {
status = "okay";
};
};
&uart4 {
pinctrl-names = "default", "sleep", "idle";
pinctrl-0 = <&uart4_pins_a>;
pinctrl-1 = <&uart4_sleep_pins_a>;
pinctrl-2 = <&uart4_idle_pins_a>;
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
};
&uart8 {
pinctrl-names = "default", "sleep", "idle";
pinctrl-0 = <&uart8_pins_a>;
pinctrl-1 = <&uart8_sleep_pins_a>;
pinctrl-2 = <&uart8_idle_pins_a>;
/delete-property/dmas;
/delete-property/dma-names;
status = "disabled";
};
&usart1 {
pinctrl-names = "default", "sleep", "idle";
pinctrl-0 = <&usart1_pins_a>;
pinctrl-1 = <&usart1_sleep_pins_a>;
pinctrl-2 = <&usart1_idle_pins_a>;
uart-has-rtscts;
status = "disabled";
};
/* Bluetooth */
&usart2 {
pinctrl-names = "default", "sleep", "idle";
pinctrl-0 = <&usart2_pins_a>;
pinctrl-1 = <&usart2_sleep_pins_a>;
pinctrl-2 = <&usart2_idle_pins_a>;
uart-has-rtscts;
status = "okay";
bluetooth {
shutdown-gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>;
compatible = "brcm,bcm43438-bt";
max-speed = <3000000>;
vbat-supply = <&v3v3_ao>;
vddio-supply = <&v3v3_ao>;
};
};
&usbh_ehci {
phys = <&usbphyc_port0>;
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
/* onboard HUB */
hub@1 {
compatible = "usb424,2514";
reg = <1>;
vdd-supply = <&scmi_v3v3_sw>;
};
};
&usbotg_hs {
phys = <&usbphyc_port1 0>;
phy-names = "usb2-phy";
usb-role-switch;
status = "okay";
port {
usbotg_hs_ep: endpoint {
remote-endpoint = <&con_usb_c_g0_ep>;
};
};
};
&usbphyc {
status = "okay";
};
&usbphyc_port0 {
phy-supply = <&scmi_vdd_usb>;
st,current-boost-microamp = <1000>;
st,decrease-hs-slew-rate;
st,tune-hs-dc-level = <2>;
st,enable-hs-rftime-reduction;
st,trim-hs-current = <11>;
st,trim-hs-impedance = <2>;
st,tune-squelch-level = <1>;
st,enable-hs-rx-gain-eq;
st,no-hs-ftime-ctrl;
st,no-lsfs-sc;
};
&usbphyc_port1 {
phy-supply = <&scmi_vdd_usb>;
st,current-boost-microamp = <1000>;
st,decrease-hs-slew-rate;
st,tune-hs-dc-level = <2>;
st,enable-hs-rftime-reduction;
st,trim-hs-current = <11>;
st,trim-hs-impedance = <2>;
st,tune-squelch-level = <1>;
st,enable-hs-rx-gain-eq;
st,no-hs-ftime-ctrl;
st,no-lsfs-sc;
};
</code></pre>
<p> </p>
</div>
页:
[1]