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等軟硬件開發,另外分享生活中的趣事以及感悟。目的是建立一個平臺記錄學習過的知識,並分享出來自認爲有用的與感興趣的道友相互交流進步。

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