Linux Versal Sysmon Driver

Table of Contents

Introduction:

Linux Versal Sysmon Driver uses IIO framework for abstraction in Linux. The following section describes the hardware as well as the software design.

Basic HW Architecture:

Sysmon for Versal follows a different architecture than the previous generations. The Sysmon is capable of measuring upto 160 supply and temperature measurement and monitoring across the chip.
Each supply has its dedicated alarm enable and alarm flag bit to allow for voltage monitoring. The S80 chip has 184 measurement points scattered across the chip, but the user can monitor only 160 at
a given time. As far as temperature is concerned, the Sysmon provides the user with current Min and Max values on the chip as well as the historical Min and Max values reached on the chip. Both
temperature and supply voltages have upper and a lower threshold around which the monitoring is done. An event is generated when the thresholds are breached by temperature and voltage. This event
is reflected in the ISR register as well as ALARM_FLAG_REG for supplies. 

SW Architecture:

As mentioned earlier the Sysmon Driver uses Linux IIO framework which was used to abstract the supply voltages and temperatures across the chip as Voltage and Temperature Channels in the framework.
Since there are only 152 (0…151) supply voltage registers, there is no constant mapping of supply voltage registers and the measurement points. User has to select the voltages to monitor
in Vivado. Depending on the selection, a voltage supply gets mapped to one of the supply registers. So, this mapping information is provided to the driver via a device tree. Depending on the number of supplies enabled in the design, the device tree will contain the information of name of the supply enabled and the supply register it maps to.

Device Tree: 

Example Device Tree looks as follows:

sysmon@f1270000 {                compatible = "xlnx,versal-sysmon";                reg = <0x00 0xf1270000 0x00 0x4000>;                interrupts = <0x00 0x90 0x04>;                xlnx,numchannels = [08];                status = "okay";                  vccint {                        xlnx,register = [00];                        xlnx,bipolar;                        xlnx,name = "vccint";                };                  vccsoc {                        xlnx,register = [1f];                        xlnx,bipolar;                        xlnx,name = "vccsoc";