Ultra96 PYNQ入门之五——PMIC

不合理的地方欢迎批评指正!!!

源代码链接:Ultra96-PYNQ_A-simple-summary

1 监控电源状态

PYNQ提供了很方便的工具可以查看电源轨的状态

from pynq import pmbus
rails = pmbus.get_rails()
rails
{'in1': Rail {name=in1, voltage=Sensor {name=in1_voltage, value=1.195V}},
 'in10': Rail {name=in10, voltage=Sensor {name=in10_voltage, value=1.798V}},
 'in11': Rail {name=in11, voltage=Sensor {name=in11_voltage, value=1.098V}},
 'in2': Rail {name=in2, voltage=Sensor {name=in2_voltage, value=1.796V}},
 'in3': Rail {name=in3, voltage=Sensor {name=in3_voltage, value=0.845V}},
 'in4': Rail {name=in4, voltage=Sensor {name=in4_voltage, value=0.845V}},
 'in5': Rail {name=in5, voltage=Sensor {name=in5_voltage, value=1.793V}},
 'in6': Rail {name=in6, voltage=Sensor {name=in6_voltage, value=1.795V}},
 'in7': Rail {name=in7, voltage=Sensor {name=in7_voltage, value=0.841V}},
 'in8': Rail {name=in8, voltage=Sensor {name=in8_voltage, value=0.841V}},
 'in9': Rail {name=in9, voltage=Sensor {name=in9_voltage, value=0.841V}}}

但是没法修改…,仅仅是监控。

2 查看PCB的IRPS5401

首先PS的I2C通过一个hub扩展了I2C口的数目,其中SC4、SD4是我们使用的接口
在这里插入图片描述
在sysfs中对应i2c-6

xilinx@pynq:~$ cd /sys/class/i2c-
i2c-adapter/ i2c-dev/
xilinx@pynq:~$ cd /sys/class/i2c-dev/
xilinx@pynq:/sys/class/i2c-dev$ tree
.
├── i2c-0 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-dev/i2c-0
├── i2c-1 -> ../../devices/platform/amba/fd4a0000.zynqmp-display/i2c-1/i2c-dev/i2c-1
├── i2c-2 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-2/i2c-dev/i2c-2
├── i2c-3 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-3/i2c-dev/i2c-3
├── i2c-4 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-4/i2c-dev/i2c-4
├── i2c-5 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-5/i2c-dev/i2c-5
├── i2c-6 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-6/i2c-dev/i2c-6
├── i2c-7 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-7/i2c-dev/i2c-7
├── i2c-8 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-8/i2c-dev/i2c-8
└── i2c-9 -> ../../devices/platform/amba/ff030000.i2c/i2c-0/i2c-9/i2c-dev/i2c-9

所有的PMIC芯片均挂载在i2c-6
在这里插入图片描述
在设备树中查看相应的PMIC信息,可以发现设备树与真实的器件并不对应…,设备树中挂载的设备为ti,tps65086

xilinx@pynq:~$ cd /sys/firmware/devicetree/base/a
aliases/     amba/        amba_apu@0/  aux_ref_clk/
xilinx@pynq:~$ cd /sys/firmware/devicetree/base/amba/
ahci@fd0c0000/              dma@fd530000/               dma@ffac0000/               gpio@ff0a0000/              pcie@fd0e0000/              spi@ff050000/               watchdog@ff150000/
ams@ffa50000/               dma@fd540000/               dma@ffad0000/               gpu@fd4b0000/               perf-monitor@fd0b0000/      spi@ff0f0000/               zynqmp-display@fd4a0000/
can@ff060000/               dma@fd550000/               dma@ffae0000/               i2c@ff020000/               perf-monitor@fd490000/      timer@ff110000/             zynqmp_phy@fd400000/
can@ff070000/               dma@fd560000/               dma@ffaf0000/               i2c@ff030000/               perf-monitor@ffa00000/      timer@ff120000/             zyxclmm_drm/
cci@fd6e0000/               dma@fd570000/               ethernet@ff0b0000/          memory-controller@fd070000/ perf-monitor@ffa10000/      timer@ff130000/
dma@fd4c0000/               dma@ffa80000/               ethernet@ff0c0000/          memory-controller@ff960000/ rtc@ffa60000/               timer@ff140000/
dma@fd500000/               dma@ffa90000/               ethernet@ff0d0000/          mmc@ff160000/               serial@ff000000/            usb0@ff9d0000/
dma@fd510000/               dma@ffaa0000/               ethernet@ff0e0000/          mmc@ff170000/               serial@ff010000/            usb1@ff9e0000/
dma@fd520000/               dma@ffab0000/               fabric@A0000000/            nand@ff100000/              spi@ff040000/               watchdog@fd4d0000/
xilinx@pynq:~$ cd /sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@
i2c@0/ i2c@1/ i2c@2/ i2c@3/ i2c@4/ i2c@5/ i2c@6/ i2c@7/
xilinx@pynq:~$ cd /sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@4/pmic@5e/
xilinx@pynq:/sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@4/pmic@5e$ cat name
pmicxilinx@pynq:/sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@4/pmic@5e$ tree
.
├── compatible
├── #gpio-cells
├── gpio-controller
├── interrupt-parent
├── interrupts
├── name
├── phandle
└── reg

0 directories, 8 files
xilinx@pynq:/sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@4/pmic@5e$ cat compatible
ti,tps65086xilinx@pynq:/sys/firmware/devicetree/base/amba/i2c@ff030000/i2c-mux@75/i2c@4/pmic@5e$

从这个patch[3/3] hwmon: (pmbus) add support for Infineon IRPS5401发现2019年6月Linux内核才支持IRPS5401,自认为驱动工程师偷懒,没有合并最新的驱动到内核中,所以用已有的ti,tps65086驱动暂且代替。

如果内核中有IRPS5401的驱动,那么就没有下面的骚操作了,可以简单地通过sysfs修改电源轨,具体方法可参阅下面这篇博文。
linux PMBus总线及设备驱动分析

3 修改IRPS5401的电源轨

3.1 想好了再进行

如果没有需求,千万不要修改PMIC,很容易造成板子重启烧坏,因为Ultra96-V2在简化设计中,复用了相应的电源轨。我为了修改PL部分的Bank65,只能忍痛割爱把USB3.0hub芯片用热风枪拆了…

如果没有需求,千万不要修改PMIC。
如果没有需求,千万不要修改PMIC。

在这里插入图片描述
USB5744-I/2G这款IC,仅耐受1.2V,如果将电源轨直接修改到1.8V,将会造成芯片损坏。

3.2 硬件解决方案

可以购买USB-to-I2C dongle,然后用官方配套的软件PowIRCenter Software进行解决,方便又省事。

3.3 软件解决方案

直接通过i2c-6修改读取相应的寄存器

3.3.1 支持的PMBus commands

看到那么多寄存器是不是头大,经过阅读,我发现需要修改的寄存器并不多。有钱的话,还是尽量使用USB-to-I2C dongle,省的受罪。
在这里插入图片描述
在这里插入图片描述

需要修改读取的寄存器如下

PAGE = 0x00
VOUT_MAX = 0x24
VOUT_MARGIN_HIGH = 0x25
VOUT_OV_FAULT_LIMIT = 0x40
VOUT_OV_WARN_LIMIT = 0x42
VOUT_COMMAND = 0x21
VOUT_UV_WARN_LIMIT = 0x43
VOUT_UV_FAULT_LIMIT = 0x44
VOUT_MARGIN_LOW = 0x26
POWER_GOOD_OFF = 0x5F
POWER_GOOD_ON = 0x5E

看这个图是不是明白了些,具体我也懒得细说了,可以查阅数据手册。
数值的设置,可以通过阅读参数符合的PMIC电源轨寄存器相应的值,来初始化想要初始化的电源轨的寄存器。
在这里插入图片描述

https://www.cnblogs.com/wahaha02/p/6475966.html

3.3.2 一个示例代码

下面是将PMIC#1的CHB通道由1.2V修改到1.8V的代码。
如果没有需求,千万不要修改PMIC。
如果没有需求,千万不要修改PMIC。
如果没有需求,千万不要修改PMIC。

import smbus

i2c_6 = smbus.SMBus(6) 

PMIC_ADDR = 0x43
PAGE = 0x00
VOUT_MAX = 0x24
VOUT_MARGIN_HIGH = 0x25
VOUT_OV_FAULT_LIMIT = 0x40
VOUT_OV_WARN_LIMIT = 0x42
VOUT_COMMAND = 0x21
VOUT_UV_WARN_LIMIT = 0x43
VOUT_UV_FAULT_LIMIT = 0x44
VOUT_MARGIN_LOW = 0x26
POWER_GOOD_OFF = 0x5F
POWER_GOOD_ON = 0x5E

PAGE_01 = 0x01
VOUT_MAX_1894V = 0x01E4
VOUT_MARGIN_HIGH_1855V = 0x01DA
VOUT_OV_FAULT_LIMIT_1953V = 0x01F3
VOUT_OV_WARN_LIMIT_1902V = 0x01E6
VOUT_COMMAND_1801V = 0x01CD
VOUT_UV_WARN_LIMIT_1702V = 0x01B3
VOUT_UV_FAULT_LIMIT_1651V = 0x01A6
VOUT_MARGIN_LOW_1753V = 0x01C0
POWER_GOOD_OFF_1603V = 0x019A
POWER_GOOD_ON_1702V = 0x01B3

i2c_6.write_byte_data(PMIC_ADDR, PAGE, PAGE_01)
temp_reg = i2c_6.read_byte_data(PMIC_ADDR, PAGE)
print("Set PAGE 0x%X %s." %(PAGE_01, "successfully"if temp_reg == PAGE_01 else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_MAX, VOUT_MAX_1894V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_MAX)
print("Set VOUT_MAX 1.894V %s." %("successfully"if temp_reg == VOUT_MAX_1894V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_MARGIN_HIGH, VOUT_MARGIN_HIGH_1855V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_MARGIN_HIGH)
print("Set VOUT_MARGIN_HIGH 1.855V %s." %("successfully"if temp_reg == VOUT_MARGIN_HIGH_1855V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_OV_FAULT_LIMIT, VOUT_OV_FAULT_LIMIT_1953V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_OV_FAULT_LIMIT)
print("Set VOUT_OV_FAULT_LIMIT 1.953V %s." %("successfully"if temp_reg == VOUT_OV_FAULT_LIMIT_1953V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_OV_WARN_LIMIT, VOUT_OV_WARN_LIMIT_1902V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_OV_WARN_LIMIT)
print("Set VOUT_OV_WARN_LIMIT 1.902V %s." %("successfully"if temp_reg == VOUT_OV_WARN_LIMIT_1902V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_COMMAND, VOUT_COMMAND_1801V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_COMMAND)
print("Set VOUT_COMMAND 1.801V %s." %("successfully"if temp_reg == VOUT_COMMAND_1801V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_UV_WARN_LIMIT, VOUT_UV_WARN_LIMIT_1702V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_UV_WARN_LIMIT)
print("Set VOUT_UV_WARN_LIMIT 1.702V %s." %("successfully"if temp_reg == VOUT_UV_WARN_LIMIT_1702V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_UV_FAULT_LIMIT, VOUT_UV_FAULT_LIMIT_1651V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_UV_FAULT_LIMIT)
print("Set VOUT_UV_FAULT_LIMIT 1.651V %s." %("successfully"if temp_reg == VOUT_UV_FAULT_LIMIT_1651V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, VOUT_MARGIN_LOW, VOUT_MARGIN_LOW_1753V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, VOUT_MARGIN_LOW)
print("Set VOUT_MARGIN_LOW 1.753V %s." %("successfully"if temp_reg == VOUT_MARGIN_LOW_1753V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, POWER_GOOD_OFF, POWER_GOOD_OFF_1603V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, POWER_GOOD_OFF)
print("Set POWER_GOOD_OFF 1.603V %s." %("successfully"if temp_reg == POWER_GOOD_OFF_1603V else "faulty") )

i2c_6.write_word_data(PMIC_ADDR, POWER_GOOD_ON, POWER_GOOD_ON_1702V)
temp_reg = i2c_6.read_word_data(PMIC_ADDR, POWER_GOOD_ON)
print("Set POWER_GOOD_ON 1.702V %s." %("successfully"if temp_reg == POWER_GOOD_ON_1702V else "faulty") )


原创不易,严禁剽窃!

在这里插入图片描述

欢迎大家关注我创建的微信公众号——小白仓库
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章