meta-ampere: mtjade: Support automatic fan control

This commit supports phosphor-fan application for mtjade platform.
phosphor-fan-control service controls fan speed following the mapping
tables with TS4_Temp, OCP_Temp, nvme_bp_max and nvme_m2_max sensor.
phosphor-fan-presence-tach and phosphor-fan-monitor services are fully
supported.

Signed-off-by: Chau Ly <chaul@amperecomputing.com>
Change-Id: I11a598f627d5e261689c2bd9d85ce65f4fc330ea
diff --git a/meta-ampere/meta-jade/conf/machine/mtjade.conf b/meta-ampere/meta-jade/conf/machine/mtjade.conf
index c13d458..914c160 100644
--- a/meta-ampere/meta-jade/conf/machine/mtjade.conf
+++ b/meta-ampere/meta-jade/conf/machine/mtjade.conf
@@ -14,6 +14,7 @@
 MACHINE_FEATURES += "\
         obmc-phosphor-chassis-mgmt \
         obmc-phosphor-flash-mgmt \
+        obmc-phosphor-fan-mgmt \
         obmc-chassis-state-mgmt \
         obmc-host-state-mgmt \
         obmc-bmc-state-mgmt \
diff --git a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
index 7493039..f1a1bbe 100644
--- a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
+++ b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
@@ -9,15 +9,18 @@
         ${PN}-chassis \
         ${PN}-flash \
         ${PN}-system \
+        ${PN}-fans \
         "
 
 PROVIDES += "virtual/obmc-chassis-mgmt"
 PROVIDES += "virtual/obmc-flash-mgmt"
 PROVIDES += "virtual/obmc-system-mgmt"
+PROVIDES += "virtual/obmc-fan-mgmt"
 
 RPROVIDES:${PN}-chassis += "virtual-obmc-chassis-mgmt"
 RPROVIDES:${PN}-flash += "virtual-obmc-flash-mgmt"
 RPROVIDES:${PN}-system += "virtual-obmc-system-mgmt"
+RPROVIDES:${PN}-fans += "virtual-obmc-fan-mgmt"
 
 SUMMARY:${PN}-chassis = "Ampere Chassis"
 RDEPENDS:${PN}-chassis = " \
@@ -42,3 +45,7 @@
 RDEPENDS:${PN}-flash = " \
         phosphor-software-manager \
         "
+
+SUMMARY:${PN}-fans = "Ampere Fans"
+RDEPENDS:${PN}-fans = " \
+        "
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh
new file mode 100644
index 0000000..1802790
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/ampere_set_fan_max_speed.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# shellcheck disable=SC2086
+
+for filename in /sys/class/hwmon/*/pwm*
+do
+  echo 255 > $filename
+done;
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json
new file mode 100644
index 0000000..2d21436
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/events.json
@@ -0,0 +1,394 @@
+[
+  {
+    "name": "set_target_fan_not_present",
+    "groups": [
+      {
+        "name": "air_cooled_zone0_fans",
+        "interface": "xyz.openbmc_project.Inventory.Item",
+        "property": { "name": "Present" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      }
+    ],
+    "actions": [
+      {
+        "name": "count_state_before_target",
+        "count": 1,
+        "state": false,
+        "target": 255
+      }
+    ]
+  },
+  {
+    // Hold fans at the given target when a number of rotors are nonfunctional.
+    "name": "set_target_fan_not_functional",
+    "groups": [
+      {
+        "name": "fan3",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      },
+      {
+        "name": "fan4",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      },
+      {
+        "name": "fan5",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      },
+      {
+        "name": "fan6",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      },
+      {
+        "name": "fan7",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      },
+      {
+        "name": "fan8",
+        "interface": "xyz.openbmc_project.State.Decorator.OperationalStatus",
+        "property": { "name": "Functional" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      }
+    ],
+    "actions": [
+      {
+        "name": "count_state_before_target",
+        "count": 1,
+        "state": false,
+        "target": 255
+      }
+    ]
+  },
+  {
+    "name": "default_fan_floor_on_missing_service",
+    "groups": [
+        {
+        "name": "zone0_ambient",
+        "interface": "xyz.openbmc_project.Sensor.Value",
+        "property": { "name": "Value" }
+        }
+    ],
+    "triggers": [
+        {
+        "class": "init",
+        "method": "name_has_owner"
+        },
+        {
+        "class": "signal",
+        "signal": "name_owner_changed"
+        }
+    ],
+    "actions": [
+        {
+        "name": "call_actions_based_on_timer",
+        "timer": {
+            "interval": 5000000,
+            "type": "oneshot"
+        },
+        "actions": [
+            {
+            "name": "default_floor_on_missing_owner",
+            "groups": [
+              {
+              "name": "zone0_ambient",
+              "interface": "xyz.openbmc_project.Sensor.Value",
+              "property": { "name": "Value" }
+              }
+            ]
+            }
+        ]
+        }
+    ]
+  },
+  {
+    "name": "target_mapping_from_TS_temp",
+    "groups": [
+      {
+        "name": "zone0_ambient",
+        "interface": "xyz.openbmc_project.Sensor.Value",
+        "property": { "name": "Value" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      },
+      {
+        "class": "timer",
+        "type": "repeating",
+        "interval": 5000000,
+        "preload_groups": true
+      }
+    ],
+    "actions": [
+      {
+        "name": "target_from_group_max",
+        "groups": [
+          {
+            "name": "zone0_ambient",
+            "interface": "xyz.openbmc_project.Sensor.Value",
+            "property": { "name": "Value" }
+          }
+        ],
+        "neg_hysteresis": 1,
+        "pos_hysteresis": 0,
+        "index": 0,
+        "map": [
+              { "value": 10.0, "target": 38.0 },
+              { "value": 18.0, "target": 38.0 },
+              { "value": 20.0, "target": 41.0 },
+              { "value": 21.0, "target": 43.0 },
+              { "value": 22.0, "target": 46.0 },
+              { "value": 24.0, "target": 48.0 },
+              { "value": 28.0, "target": 51.0 },
+              { "value": 32.0, "target": 56.0 },
+              { "value": 34.0, "target": 59.0 },
+              { "value": 36.0, "target": 61.0 },
+              { "value": 40.0, "target": 64.0 },
+              { "value": 41.0, "target": 66.0 },
+              { "value": 42.0, "target": 69.0 },
+              { "value": 43.0, "target": 71.0 },
+              { "value": 44.0, "target": 74.0 },
+              { "value": 45.0, "target": 77.0 },
+              { "value": 46.0, "target": 79.0 },
+              { "value": 47.0, "target": 82.0 },
+              { "value": 48.0, "target": 84.0 },
+              { "value": 49.0, "target": 87.0 },
+              { "value": 50.0, "target": 89.0 }
+        ]
+      }
+    ]
+  },
+  {
+    "name": "target_mapping_from_OCP_temp",
+    "groups": [
+      {
+        "name": "zone0_ocp",
+        "interface": "xyz.openbmc_project.Sensor.Value",
+        "property": { "name": "Value" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      },
+      {
+        "class": "timer",
+        "type": "repeating",
+        "interval": 5000000,
+        "preload_groups": true
+      }
+    ],
+    "actions": [
+      {
+        "name": "target_from_group_max",
+        "groups": [
+          {
+            "name": "zone0_ocp",
+            "interface": "xyz.openbmc_project.Sensor.Value",
+            "property": { "name": "Value" }
+          }
+        ],
+        "neg_hysteresis": 2,
+        "pos_hysteresis": 2,
+        "index": 3,
+        "map": [
+          { "value": 10.0, "target": 38.0 },
+          { "value": 65.0, "target": 38.0 },
+          { "value": 66.0, "target": 43.0 },
+          { "value": 67.0, "target": 51.0 },
+          { "value": 68.0, "target": 54.0 },
+          { "value": 69.0, "target": 56.0 },
+          { "value": 70.0, "target": 61.0 },
+          { "value": 71.0, "target": 66.0 },
+          { "value": 72.0, "target": 71.0 },
+          { "value": 73.0, "target": 77.0 },
+          { "value": 74.0, "target": 82.0 },
+          { "value": 75.0, "target": 87.0 },
+          { "value": 76.0, "target": 92.0 },
+          { "value": 77.0, "target": 97.0 },
+          { "value": 78.0, "target": 102.0 },
+          { "value": 79.0, "target": 107.0 },
+          { "value": 80.0, "target": 112.0 },
+          { "value": 81.0, "target": 122.0 },
+          { "value": 82.0, "target": 128.0 },
+          { "value": 83.0, "target": 133.0 },
+          { "value": 84.0, "target": 140.0 },
+          { "value": 85.0, "target": 148.0 },
+          { "value": 86.0, "target": 156.0 },
+          { "value": 87.0, "target": 163.0 },
+          { "value": 88.0, "target": 171.0 },
+          { "value": 89.0, "target": 179.0 },
+          { "value": 90.0, "target": 186.0 },
+          { "value": 91.0, "target": 194.0 },
+          { "value": 92.0, "target": 201.0 },
+          { "value": 93.0, "target": 209.0 },
+          { "value": 94.0, "target": 217.0 },
+          { "value": 95.0, "target": 224.0 },
+          { "value": 96.0, "target": 232.0 },
+          { "value": 97.0, "target": 240.0 },
+          { "value": 98.0, "target": 247.0 },
+          { "value": 99.0, "target": 255.0 }
+        ]
+      }
+    ]
+  },
+  {
+    "name": "target_mapping_from_BP_NVME_temp",
+    "groups": [
+      {
+        "name": "zone0_bp_nvme",
+        "interface": "xyz.openbmc_project.Sensor.Value",
+        "property": { "name": "Value" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      },
+      {
+        "class": "timer",
+        "type": "repeating",
+        "interval": 5000000,
+        "preload_groups": true
+      }
+    ],
+    "actions": [
+      {
+        "name": "target_from_group_max",
+        "groups": [
+          {
+            "name": "zone0_bp_nvme",
+            "interface": "xyz.openbmc_project.Sensor.Value",
+            "property": { "name": "Value" }
+          }
+        ],
+        "neg_hysteresis": 2,
+        "pos_hysteresis": 0,
+        "index": 4,
+        "map": [
+          { "value": 10.0, "target": 38.0 },
+          { "value": 35.0, "target": 38.0 },
+          { "value": 36.0, "target": 43.0 },
+          { "value": 37.0, "target": 48.0 },
+          { "value": 38.0, "target": 54.0 },
+          { "value": 39.0, "target": 59.0 },
+          { "value": 40.0, "target": 64.0 },
+          { "value": 41.0, "target": 66.0 },
+          { "value": 42.0, "target": 69.0 },
+          { "value": 43.0, "target": 71.0 },
+          { "value": 44.0, "target": 74.0 },
+          { "value": 45.0, "target": 77.0 },
+          { "value": 46.0, "target": 79.0 },
+          { "value": 47.0, "target": 82.0 },
+          { "value": 48.0, "target": 84.0 },
+          { "value": 49.0, "target": 87.0 },
+          { "value": 50.0, "target": 89.0 },
+          { "value": 51.0, "target": 99.0 },
+          { "value": 52.0, "target": 99.0 },
+          { "value": 53.0, "target": 105.0 },
+          { "value": 54.0, "target": 110.0 },
+          { "value": 55.0, "target": 115.0 },
+          { "value": 56.0, "target": 120.0 },
+          { "value": 57.0, "target": 125.0 },
+          { "value": 58.0, "target": 130.0 },
+          { "value": 59.0, "target": 135.0 },
+          { "value": 60.0, "target": 140.0 },
+          { "value": 61.0, "target": 150.0 },
+          { "value": 62.0, "target": 161.0 },
+          { "value": 63.0, "target": 171.0 },
+          { "value": 64.0, "target": 181.0 },
+          { "value": 65.0, "target": 191.0 },
+          { "value": 66.0, "target": 204.0 },
+          { "value": 67.0, "target": 217.0 },
+          { "value": 68.0, "target": 230.0 },
+          { "value": 69.0, "target": 255.0 }
+        ]
+      }
+    ]
+  },
+  {
+    "name": "target_mapping_from_M2_NVME_temp",
+    "groups": [
+      {
+        "name": "zone0_m2_nvme",
+        "interface": "xyz.openbmc_project.Sensor.Value",
+        "property": { "name": "Value" }
+      }
+    ],
+    "triggers": [
+      {
+        "class": "init",
+        "method": "get_properties"
+      },
+      {
+        "class": "signal",
+        "signal": "properties_changed"
+      },
+      {
+        "class": "timer",
+        "type": "repeating",
+        "interval": 5000000,
+        "preload_groups": true
+      }
+    ],
+    "actions": [
+      {
+        "name": "target_from_group_max",
+        "groups": [
+          {
+            "name": "zone0_m2_nvme",
+            "interface": "xyz.openbmc_project.Sensor.Value",
+            "property": { "name": "Value" }
+          }
+        ],
+        "neg_hysteresis": 2,
+        "pos_hysteresis": 0,
+        "index": 5,
+        "map": [
+          { "value": 10.0, "target": 38.0 },
+          { "value": 61.0, "target": 38.0 },
+          { "value": 68.0, "target": 38.0 },
+          { "value": 69.0, "target": 204.0 }
+        ]
+      }
+    ]
+  }
+]
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json
new file mode 100644
index 0000000..a14cab6
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/fans.json
@@ -0,0 +1,44 @@
+[
+    {
+        "name": "FAN3",
+        "zone": "0",
+        "sensors": ["PWM3"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    },
+    {
+        "name": "FAN4",
+        "zone": "0",
+        "sensors": ["PWM4"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    },
+    {
+        "name": "FAN5",
+        "zone": "0",
+        "sensors": ["PWM5"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    },
+    {
+        "name": "FAN6",
+        "zone": "0",
+        "sensors": ["PWM6"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    },
+    {
+        "name": "FAN7",
+        "zone": "0",
+        "sensors": ["PWM7"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    },
+    {
+        "name": "FAN8",
+        "zone": "0",
+        "sensors": ["PWM8"],
+        "target_interface": "xyz.openbmc_project.Control.FanPwm",
+        "target_path": "/xyz/openbmc_project/control/fanpwm/"
+    }
+]
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json
new file mode 100644
index 0000000..6bff7bb
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/groups.json
@@ -0,0 +1,80 @@
+[
+    {
+        "name": "air_cooled_zone0_fans",
+        "members": [
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3",
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4",
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5",
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6",
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7",
+            "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8"
+        ]
+    },
+    {
+        "name": "fan3",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3/FAN3_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN3/FAN3_2"
+        ]
+    },
+    {
+        "name": "fan4",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4/FAN4_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN4/FAN4_2"
+        ]
+    },
+    {
+        "name": "fan5",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5/FAN5_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN5/FAN5_2"
+        ]
+    },
+    {
+        "name": "fan6",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6/FAN6_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN6/FAN6_2"
+        ]
+    },
+    {
+        "name": "fan7",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7/FAN7_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN7/FAN7_2"
+        ]
+    },
+    {
+        "name": "fan8",
+        "members": [
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8/FAN8_1",
+          "/xyz/openbmc_project/inventory/system/chassis/Mt_Jade/FAN8/FAN8_2"
+        ]
+    },
+    {
+        "name": "zone0_ambient",
+        "service": "xyz.openbmc_project.HwmonTempSensor",
+        "members": [
+            "/xyz/openbmc_project/sensors/temperature/TS4_Temp"
+        ]
+    },
+    {
+        "name": "zone0_ocp",
+        "members": [
+            "/xyz/openbmc_project/sensors/temperature/OCP_Temp"
+        ]
+    },
+    {
+        "name": "zone0_bp_nvme",
+        "members": [
+            "/xyz/openbmc_project/sensors/temperature/nvme_bp_max"
+        ]
+    },
+    {
+        "name": "zone0_m2_nvme",
+        "members": [
+            "/xyz/openbmc_project/sensors/temperature/nvme_m2_max"
+        ]
+    }
+]
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json
new file mode 100644
index 0000000..db706e0
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/monitor.json
@@ -0,0 +1,160 @@
+{
+    "fans": [
+       {
+         "inventory": "/system/chassis/Mt_Jade/FAN3",
+         "allowed_out_of_range_time": 10,
+         "deviation": 25,
+         "num_sensors_nonfunc_for_fan_nonfunc": 1,
+         "monitor_start_delay": 30,
+         "set_func_on_present": false,
+         "sensors": [
+            {
+               "name": "FAN3_1",
+               "has_target": true,
+               "target_interface": "xyz.openbmc_project.Control.FanPwm",
+               "target_path": "/xyz/openbmc_project/control/fanpwm/PWM3",
+               "factor": 82,
+               "offset": 0
+            },
+            {
+               "name": "FAN3_2",
+               "has_target": false,
+               "target_interface": "xyz.openbmc_project.Control.FanPwm",
+               "target_path": "/xyz/openbmc_project/control/fanpwm/PWM3",
+               "factor": 82,
+               "offset": 0
+            }
+         ]
+       },
+       {
+        "inventory": "/system/chassis/Mt_Jade/FAN4",
+        "allowed_out_of_range_time": 10,
+        "deviation": 25,
+        "num_sensors_nonfunc_for_fan_nonfunc": 1,
+        "monitor_start_delay": 30,
+        "set_func_on_present": false,
+        "sensors": [
+           {
+              "name": "FAN4_1",
+              "has_target": true,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM4",
+              "factor": 82,
+              "offset": 0
+           },
+           {
+              "name": "FAN4_2",
+               "has_target": false,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM4",
+              "factor": 82,
+              "offset": 0
+           }
+        ]
+       },
+       {
+        "inventory": "/system/chassis/Mt_Jade/FAN5",
+        "allowed_out_of_range_time": 10,
+        "deviation": 25,
+        "num_sensors_nonfunc_for_fan_nonfunc": 1,
+        "monitor_start_delay": 30,
+        "set_func_on_present": false,
+        "sensors": [
+           {
+              "name": "FAN5_1",
+              "has_target": true,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM5",
+              "factor": 82,
+              "offset": 0
+           },
+           {
+              "name": "FAN5_2",
+               "has_target": false,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM5",
+              "factor": 82,
+              "offset": 0
+           }
+        ]
+       },
+       {
+        "inventory": "/system/chassis/Mt_Jade/FAN6",
+        "allowed_out_of_range_time": 10,
+        "deviation": 25,
+        "num_sensors_nonfunc_for_fan_nonfunc": 1,
+        "monitor_start_delay": 30,
+        "set_func_on_present": false,
+        "sensors": [
+           {
+              "name": "FAN6_1",
+              "has_target": true,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM6",
+              "factor": 82,
+              "offset": 0
+           },
+           {
+              "name": "FAN6_2",
+               "has_target": false,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM6",
+              "factor": 82,
+              "offset": 0
+           }
+        ]
+       },
+       {
+        "inventory": "/system/chassis/Mt_Jade/FAN7",
+        "allowed_out_of_range_time": 10,
+        "deviation": 25,
+        "num_sensors_nonfunc_for_fan_nonfunc": 1,
+        "monitor_start_delay": 30,
+        "set_func_on_present": false,
+        "sensors": [
+           {
+              "name": "FAN7_1",
+              "has_target": true,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM7",
+              "factor": 82,
+              "offset": 0
+           },
+           {
+              "name": "FAN7_2",
+               "has_target": false,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM7",
+              "factor": 82,
+              "offset": 0
+           }
+        ]
+       },
+       {
+        "inventory": "/system/chassis/Mt_Jade/FAN8",
+        "allowed_out_of_range_time": 10,
+        "deviation": 25,
+        "num_sensors_nonfunc_for_fan_nonfunc": 1,
+        "monitor_start_delay": 30,
+        "set_func_on_present": false,
+        "sensors": [
+           {
+              "name": "FAN8_1",
+              "has_target": true,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM8",
+              "factor": 82,
+              "offset": 0
+           },
+           {
+              "name": "FAN8_2",
+               "has_target": false,
+              "target_interface": "xyz.openbmc_project.Control.FanPwm",
+              "target_path": "/xyz/openbmc_project/control/fanpwm/PWM8",
+              "factor": 82,
+              "offset": 0
+           }
+        ]
+       }
+    ]
+ }
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json
new file mode 100644
index 0000000..0eb8296
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/presence.json
@@ -0,0 +1,99 @@
+[
+   {
+        "name": "FAN3",
+        "path": "/system/chassis/Mt_Jade/FAN3",
+        "methods": [
+           {
+              "type": "tach",
+              "sensors": [
+                 "FAN3_1",
+                 "FAN3_2"
+              ]
+           }
+        ],
+        "rpolicy": {
+           "type": "anyof"
+        }
+   },
+   {
+       "name": "FAN4",
+       "path": "/system/chassis/Mt_Jade/FAN4",
+       "methods": [
+          {
+             "type": "tach",
+             "sensors": [
+                "FAN4_1",
+                "FAN4_2"
+             ]
+          }
+       ],
+       "rpolicy": {
+          "type": "anyof"
+       }
+   },
+   {
+       "name": "FAN5",
+       "path": "/system/chassis/Mt_Jade/FAN5",
+       "methods": [
+          {
+             "type": "tach",
+             "sensors": [
+                "FAN5_1",
+                "FAN5_2"
+             ]
+          }
+       ],
+       "rpolicy": {
+          "type": "anyof"
+       }
+   },
+   {
+       "name": "FAN6",
+       "path": "/system/chassis/Mt_Jade/FAN6",
+       "methods": [
+          {
+             "type": "tach",
+             "sensors": [
+                "FAN6_1",
+                "FAN6_2"
+             ]
+          }
+       ],
+       "rpolicy": {
+          "type": "anyof"
+       }
+   },
+   {
+       "name": "FAN7",
+       "path": "/system/chassis/Mt_Jade/FAN7",
+       "methods": [
+          {
+             "type": "tach",
+             "sensors": [
+                "FAN7_1",
+                "FAN7_2"
+             ]
+          }
+       ],
+       "rpolicy": {
+          "type": "anyof"
+       }
+   },
+   {
+       "name": "FAN8",
+       "path": "/system/chassis/Mt_Jade/FAN8",
+       "methods": [
+          {
+             "type": "tach",
+             "sensors": [
+                "FAN8_1",
+                "FAN8_2"
+             ]
+          }
+       ],
+       "rpolicy": {
+          "type": "anyof"
+       }
+   }
+]
+
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json
new file mode 100644
index 0000000..d8ec74f
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/mtjade/zones.json
@@ -0,0 +1,10 @@
+[
+    {
+        "name": "0",
+        "poweron_target": 153,
+        "default_ceiling": 255,
+        "default_floor": 255,
+        "increase_delay": 5,
+        "decrease_interval": 30
+    }
+]
\ No newline at end of file
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service
new file mode 100644
index 0000000..d50fafb
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Phosphor Fan Control Daemon
+Wants=xyz.openbmc_project.fansensor.service
+After=xyz.openbmc_project.fansensor.service
+StartLimitIntervalSec=30
+StartLimitBurst=3
+
+[Service]
+Restart=on-failure
+ExecStart=phosphor-fan-control
+RestartSec=20
+ExecStopPost=/usr/bin/ampere_set_fan_max_speed.sh
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service
new file mode 100644
index 0000000..78efeed
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Phosphor Fan Monitor Daemon
+Wants=xyz.openbmc_project.fansensor.service
+After=xyz.openbmc_project.fansensor.service
+StartLimitIntervalSec=30
+StartLimitBurst=3
+
+[Service]
+Restart=on-failure
+ExecStart=phosphor-fan-monitor
+RestartSec=20
+ExecStopPost=/usr/bin/ampere_set_fan_max_speed.sh
diff --git a/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend
new file mode 100644
index 0000000..fbcb1be
--- /dev/null
+++ b/meta-ampere/meta-jade/recipes-phosphor/fans/phosphor-fan_%.bbappend
@@ -0,0 +1,41 @@
+FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
+FILESEXTRAPATHS:append := "${THISDIR}/${PN}/${MACHINE}:"
+
+RDEPENDS:${PN} += "bash"
+
+PACKAGECONFIG:append = " json"
+
+SRC_URI:append = " file://events.json \
+                  file://fans.json \
+                  file://groups.json \
+                  file://zones.json \
+                  file://monitor.json \
+                  file://presence.json \
+                  file://phosphor-fan-control@.service \
+                  file://phosphor-fan-monitor@.service \
+                  file://ampere_set_fan_max_speed.sh \
+                "
+
+do_configure:prepend() {
+        mkdir -p ${S}/control/config_files/${MACHINE}
+        cp ${WORKDIR}/events.json ${S}/control/config_files/${MACHINE}/events.json
+        cp ${WORKDIR}/fans.json ${S}/control/config_files/${MACHINE}/fans.json
+        cp ${WORKDIR}/groups.json ${S}/control/config_files/${MACHINE}/groups.json
+        cp ${WORKDIR}/zones.json ${S}/control/config_files/${MACHINE}/zones.json
+
+        mkdir -p ${S}/monitor/config_files/${MACHINE}
+        cp ${WORKDIR}/monitor.json ${S}/monitor/config_files/${MACHINE}/config.json
+
+        mkdir -p ${S}/presence/config_files/${MACHINE}
+        cp ${WORKDIR}/presence.json ${S}/presence/config_files/${MACHINE}/config.json
+}
+
+do_install:append() {
+  install -d ${D}${bindir}
+  install -m 0755 ${WORKDIR}/ampere_set_fan_max_speed.sh ${D}${bindir}/ampere_set_fan_max_speed.sh
+  install -d ${D}${systemd_system_unitdir}
+  install -m 0644 ${WORKDIR}/phosphor-fan-monitor@.service ${D}${systemd_system_unitdir}
+  install -m 0644 ${WORKDIR}/phosphor-fan-control@.service ${D}${systemd_system_unitdir}
+}
+
+