meta-ethanolx: Add PID control for fans

Add support for dynamic fan RPM control based on the values from
temperature sensors.

Control is based on PIDs and is splitted to 3 thermal zones:

Zone 1:
- CPU0 SB-TSI temp with a setpoint 60.0 C
- P0 FAN

Zone 2:
- CPU1 SB-TSI temp with a setpoint 60.0 C
- P1 FAN

Zone 3:
- All LM75A sensors on board with a setpoint 35.0 C
- SYS FAN1 - SYS FAN6

Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Change-Id: Ifca359ba23777e2b1f46783272cf98ff0b08fe68
diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json
index 08d66c0..b95e909 100644
--- a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json
+++ b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-baseboard.json
@@ -2,42 +2,50 @@
     "Exposes": [
         {
             "Name": "P0 Fan connector",
-            "Status": "disabled",
+            "Pwm" : 0,
+            "Tachs": [0],
             "Type": "FanConnector"
         },
         {
             "Name": "P1 Fan connector",
-            "Status": "disabled",
+            "Pwm" : 1,
+            "Tachs": [1],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN1 connector",
-            "Status": "disabled",
+            "Pwm" : 2,
+            "Tachs": [2],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN2 connector",
-            "Status": "disabled",
+            "Pwm" : 3,
+            "Tachs": [3],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN3 connector",
-            "Status": "disabled",
+            "Pwm" : 4,
+            "Tachs": [4],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN4 connector",
-            "Status": "disabled",
+            "Pwm" : 5,
+            "Tachs": [5],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN5 connector",
-            "Status": "disabled",
+            "Pwm" : 6,
+            "Tachs": [6],
             "Type": "FanConnector"
         },
         {
             "Name": "SYS FAN6 connector",
-            "Status": "disabled",
+            "Pwm" : 7,
+            "Tachs": [7],
             "Type": "FanConnector"
         },
         {
@@ -1148,6 +1156,314 @@
                 }
             ],
             "Type": "SBTSI"
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "P0_Fan"
+            ],
+            "Name": "P0_Fan",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 1"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 1"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "P1_Fan"
+            ],
+            "Name": "P1_Fan",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 2"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 2"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN1"
+            ],
+            "Name": "SYS_FAN1",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 3"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN2"
+            ],
+            "Name": "SYS_FAN2",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 4"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN3"
+            ],
+            "Name": "SYS_FAN3",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 5"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN4"
+            ],
+            "Name": "SYS_FAN4",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 6"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN5"
+            ],
+            "Name": "SYS_FAN5",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 7"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "fan",
+            "FFGainCoefficient": 1.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": 0.0,
+            "ILimitMax": 0.0,
+            "ILimitMin": 0.0,
+            "Inputs": [
+                "SYS_FAN6"
+            ],
+            "Name": "SYS_FAN6",
+            "NegativeHysteresis": 0.0,
+            "OutLimitMax": 100.0,
+            "OutLimitMin": 10.0,
+            "Outputs": [
+                "Pwm 8"
+            ],
+            "PCoefficient": 0.0,
+            "PositiveHysteresis": 0.0,
+            "SlewNeg": 0.0,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "Class": "temp",
+            "FFGainCoefficient": 0.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": -1.0,
+            "ILimitMax": 100,
+            "ILimitMin": 20,
+            "Inputs": [
+                "CPU0"
+            ],
+            "Name": "CPU0 Temperature Control",
+            "NegativeHysteresis": 5.0,
+            "OutLimitMax": 100,
+            "OutLimitMin": 30,
+            "Outputs": [],
+            "PCoefficient": -5,
+            "PositiveHysteresis": 0.0,
+            "SetPoint": 60.0,
+            "SlewNeg": -1,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 1"
+            ]
+        },
+        {
+            "Class": "temp",
+            "FFGainCoefficient": 0.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": -1.0,
+            "ILimitMax": 100,
+            "ILimitMin": 20,
+            "Inputs": [
+                "CPU1"
+            ],
+            "Name": "CPU1 Temperature Control",
+            "NegativeHysteresis": 5.0,
+            "OutLimitMax": 100,
+            "OutLimitMin": 30,
+            "Outputs": [],
+            "PCoefficient": -5,
+            "PositiveHysteresis": 0.0,
+            "SetPoint": 60.0,
+            "SlewNeg": -1,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 2"
+            ]
+        },
+        {
+            "Class": "temp",
+            "FFGainCoefficient": 0.0,
+            "FFOffCoefficient": 0.0,
+            "ICoefficient": -1.0,
+            "ILimitMax": 100,
+            "ILimitMin": 20,
+            "Inputs": [
+                "BMC",
+                "DIMM_P0_ABCD",
+                "DIMM_P0_ABCD_P1_EFGH",
+                "DIMM_P0_EFGH",
+                "DIMM_P0_EFGH_P1_ABCD",
+                "DIMM_P1_ABCD",
+                "DIMM_P1_EFGH",
+                "PCIe_Slots"
+            ],
+            "Name": "Board Temperature Control",
+            "NegativeHysteresis": 3.0,
+            "OutLimitMax": 100,
+            "OutLimitMin": 30,
+            "Outputs": [],
+            "PCoefficient": -5,
+            "PositiveHysteresis": 0.0,
+            "SetPoint": 35.0,
+            "SlewNeg": -1,
+            "SlewPos": 0.0,
+            "Type": "Pid",
+            "Zones": [
+                "Zone 3"
+            ]
+        },
+        {
+            "FailSafePercent": 100,
+            "MinThermalOutput": 10,
+            "Name": "Zone 1",
+            "Type": "Pid.Zone"
+        },
+        {
+            "FailSafePercent": 100,
+            "MinThermalOutput": 10,
+            "Name": "Zone 2",
+            "Type": "Pid.Zone"
+        },
+        {
+            "FailSafePercent": 100,
+            "MinThermalOutput": 10,
+            "Name": "Zone 3",
+            "Type": "Pid.Zone"
         }
     ],
     "Name": "AMD EthanolX Baseboard",
diff --git a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json
index 329ed02..ed4fec8 100644
--- a/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json
+++ b/meta-amd/meta-ethanolx/recipes-phosphor/configuration/entity-manager/ethanolx-chassis.json
@@ -6,8 +6,6 @@
             "MaxReading": 6000,
             "Name": "P0_Fan",
             "Type": "AspeedFan",
-            "Pwm": 1,
-            "Tachs": [1],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -41,8 +39,6 @@
             "MaxReading": 6000,
             "Name": "P1_Fan",
             "Type": "AspeedFan",
-            "Pwm": 2,
-            "Tachs": [2],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -76,8 +72,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN1",
             "Type": "AspeedFan",
-            "Pwm": 3,
-            "Tachs": [3],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -111,8 +105,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN2",
             "Type": "AspeedFan",
-            "Pwm": 4,
-            "Tachs": [4],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -146,8 +138,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN3",
             "Type": "AspeedFan",
-            "Pwm": 5,
-            "Tachs": [5],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -181,8 +171,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN4",
             "Type": "AspeedFan",
-            "Pwm": 6,
-            "Tachs": [6],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -216,8 +204,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN5",
             "Type": "AspeedFan",
-            "Pwm": 7,
-            "Tachs": [7],
             "Thresholds": [
                 {
                     "Direction": "less than",
@@ -251,8 +237,6 @@
             "MaxReading": 6000,
             "Name": "SYS_FAN6",
             "Type": "AspeedFan",
-            "Pwm": 8,
-            "Tachs": [8],
             "Thresholds": [
                 {
                     "Direction": "less than",
diff --git a/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb b/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb
index 0693805..f99de84 100644
--- a/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb
+++ b/meta-amd/recipes-amd/packagegroups/packagegroup-amd-apps.bb
@@ -28,7 +28,9 @@
         "
 
 SUMMARY:${PN}-fans = "AMD Fans"
-RDEPENDS:${PN}-fans = ""
+RDEPENDS:${PN}-fans = " \
+        phosphor-pid-control \
+        "
 
 SUMMARY:${PN}-flash = "AMD Flash"
 RDEPENDS:${PN}-flash = " \
diff --git a/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service b/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service
new file mode 100644
index 0000000..659ff3e
--- /dev/null
+++ b/meta-amd/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Phosphor-Pid-Control Margin-based Fan Control Daemon
+After=xyz.openbmc_project.EntityManager.service
+After=xyz.openbmc_project.ObjectMapper.service
+
+[Service]
+Restart=always
+ExecStart={bindir}/swampd -t
+RestartSec=5
+StartLimitInterval=0
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
index 4cdfe5a..6e528dc 100644
--- a/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
+++ b/meta-amd/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
@@ -1,3 +1,5 @@
 FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
 
-EXTRA_OECONF:append = " --enable-configure-dbus=yes"
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE:${PN} = "phosphor-pid-control.service"