summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/pull_request_template.md3
-rw-r--r--.github/workflows/main.yml21
-rw-r--r--README.md231
-rw-r--r--meta-aspeed/recipes-bsp/u-boot/files/0001-aspeed-Limit-bootm-memory.patch31
-rw-r--r--meta-aspeed/recipes-kernel/linux/linux-aspeed-sdk/aspeed-g6/0001-aspeed-espi-Clean-up-error-handling.patch102
-rw-r--r--meta-openbmc-mods/COPYING.MIT17
-rw-r--r--meta-openbmc-mods/COPYING.apache-2.0175
-rw-r--r--meta-openbmc-mods/README64
-rw-r--r--meta-openbmc-mods/conf/layer.conf22
-rw-r--r--meta-openbmc-mods/conf/machine/include/intel.inc29
-rw-r--r--meta-openbmc-mods/files/group12
-rw-r--r--meta-openbmc-mods/files/passwd10
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/layer.conf20
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc12
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc43
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch424
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch51
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch73
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch53
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch387
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0007-Add-espi-support.patch347
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch158
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch427
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch96
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch158
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch149
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch141
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch89
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch112
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch46
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch164
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch36
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch106
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch613
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch37
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch50
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch330
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch114
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch1524
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch302
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch59
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch1273
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0030-Support-Get-Set-Security-mode-command.patch124
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0031-Make-it-so-TFTP-port-can-be-modified.patch40
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch530
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0033-Reboot-into-UBOOT-on-Watchdog-Failures.patch110
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0034-Disable-uart-debug-interface.patch54
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0035-PFR-platform-EXTRST-reset-mask-selection.patch124
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0036-Re-Enable-KCS.patch35
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0037-aspeed-ast-scu.c-fix-MAC1LINK-and-MAC2LINK-pin-pads-.patch80
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0038-Increase-default-fan-speed-for-cooper-city.patch131
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0040-Initialize-the-BMC-host-mailbox-at-reset-time.patch65
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0041-Disabling-boot-delay.patch27
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0043-PFR-Skip-counting-WDT2-event-when-EXTRST-is-set.patch45
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend72
l---------meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg0
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/0001-Blacklist-DIMM-Bus.patch26
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json1909
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json1427
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json91
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/J85894-HSBP.json92
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json104
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json49
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json1777
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json2424
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json455
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json2415
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend19
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console.conf3
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console@.service21
-rwxr-xr-xmeta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/sol-option-check.sh25
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console_%.bbappend17
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch36
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes.txt3
-rw-r--r--meta-openbmc-mods/meta-ast2600/conf/layer.conf21
-rw-r--r--meta-openbmc-mods/meta-ast2600/conf/machine/include/intel-ast2600.inc20
-rw-r--r--meta-openbmc-mods/meta-ast2600/conf/machine/include/obmc-bsp-si-common.inc41
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0001-Add-ast2600-intel-as-a-new-board.patch1373
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0003-ast2600-intel-layout-environment-addr.patch67
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0004-AST2600-Adjust-default-GPIO-settings.patch86
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0005-Ast2600-Enable-interrupt-in-u-boot.patch567
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0006-SPI-Quad-IO-Mode.patch105
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0007-ast2600-Override-OTP-strap-settings.patch78
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0008-AST2600-Add-TPM-pulse-trigger.patch50
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0009-AST2600-Disable-DMA-arbitration-options-on-MAC1-and-.patch57
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0010-Fix-timer-support.patch173
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0011-KCS-driver-support-in-uBoot.patch614
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0012-IPMI-command-handler-implementation-in-uboot.patch330
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0013-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch58
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0014-Add-a-workaround-to-cover-eSPI-OOB-free-bug-in-AST26.patch138
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0021-AST2600-Enable-host-searial-port-clock-configuration.patch71
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch35
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/intel.cfg27
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend32
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-fw-utils-aspeed-sdk_%.bbappend18
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0001-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch186
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/intel-ast2600.cfg21
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed_%.bbappend7
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json2055
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json91
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json53
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json49
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager_%.bbappend12
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/obmc-console.conf3
-rwxr-xr-xmeta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/sol-option-check.sh25
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes.txt3
-rw-r--r--meta-openbmc-mods/meta-common-small/conf/layer.conf11
-rw-r--r--meta-openbmc-mods/meta-common-small/recipes-core/systemd/systemd_%.bbappend14
-rw-r--r--meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/files/0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch100
-rw-r--r--meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-native_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-system-native_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu_%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/COPYING.MIT17
-rw-r--r--meta-openbmc-mods/meta-common/README64
-rw-r--r--meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass131
-rw-r--r--meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass79
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass532
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass55
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-dev.bbclass7
-rw-r--r--meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass35
-rw-r--r--meta-openbmc-mods/meta-common/conf/layer.conf11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/fw_env.config25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/files/environment.d-openssl.sh1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-skip-test_symbol_presence.patch46
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/afalg.patch31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/reproducible.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/run-ptest12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1g.bb211
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.sh8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check_git.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug_git.bb33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebugJtagTest.service12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/base-files/base-files/fstab10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/base-files/base-files_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/dev-only.cfg4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/disable.cfg6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/crashdump/files/com.intel.crashdump.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/dropbear/dropbear_%.bbappend22
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-core/dropbear/files/enable-ssh.sh15
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh366
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl136
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch119
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt27
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c93
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c467
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check.bb26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.service9
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.sh16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/libpeci/libpeci_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/libxcrypt/libxcrypt_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd.inc43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/avoid_parallel_tests.patch20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/configure-sbindir.patch23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/display_testname_for_subtest.patch25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/ptest.patch23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/run-ptest43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser-l.pamd3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser.pamd4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd_2.34.bb12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/microsoft-gsl/microsoft-gsl.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/os-release/os-release.bbappend34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc81
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/packagegroups/packagegroup-core-standalone-sdk-target.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/readline/readline/inputrc61
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/readline/readline_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/rest-dbus/rest-dbus-static.bb23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/safec/safec_%.bbappend11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb15
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check.bb26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.sh42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/obmc-targets.bbappend10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/journald.conf42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/systemd-timesyncd-save-time.conf2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf_%.bbappend11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0002-Disable-LLMNR-port-5355.patch26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-time-wait-sync.service36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-devtools/python/python_%.bbappend7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-devtools/template-recipe/template-recipe.bb18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/pam/pam-ipmi_%.bbappend7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.service9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.sh10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/pam.d/login90
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch162
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb18
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py385
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/bmc_config.xml48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_prv.pem8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_pub.pem4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfm_config.xml48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfr_manifest.json196
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_prv.pem8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_pub.pem4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-blocksign-native.bb20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service11
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.sh14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/psu-manager/psu-manager.bb26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1/smbios-mdrv1.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch510
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch557
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch212
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch645
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch173
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch70
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch45
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch123
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch117
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch760
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch227
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch425
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch491
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch580
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch762
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch95
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch145
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch135
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch559
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch85
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch245
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch514
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch488
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch105
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch154
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch139
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch273
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch67
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch920
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch1466
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch107
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch310
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch57
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch1148
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch491
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch180
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch191
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch88
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch155
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch1107
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch47
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch70
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch35
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch105
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch271
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch63
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch97
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch405
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch136
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch57
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch783
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch237
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch151
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch94
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch129
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch215
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch922
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch79
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch1265
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0109-signal-Extend-exec_id-to-64bits.patch88
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch75
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg89
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend87
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch412
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch506
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check109
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/beepcode-mgr.bb25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/.clang-format98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/CMakeLists.txt39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode-mgr.service12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp325
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/cmake-format.json12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp265
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/datetime/phosphor-time-manager_git.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0001-Reapply-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-e.patch47
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch86
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.patch57
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0025-Add-PreInterruptFlag-properity-in-DBUS.patch39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0026-Add-StandbySpare-support-for-software-inventory.patch55
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch459
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch41
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch188
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch438
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch408
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru.bb30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/CMakeLists.txt7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/SetBaseboardFru.service9
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/checkFru.sh76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/mkfru.cpp219
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-support-for-StandBySpare.patch462
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Use-chip-id-based-UUID-for-Service-Root.patch71
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json178
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/.clang-format99
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch231
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch41
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch80
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch105
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch356
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch259
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch291
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch140
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service15
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/transporthandler_oem.cpp147
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb/0001-Add-dbus-method-SlotIpmbRequest.patch536
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch39
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch319
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch336
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/10-nice-rules.conf2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml0
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.service11
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.sh12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off_git.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb21
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb17
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl.bb27
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/multi-node-nl.target4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.service9
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.sh23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/phosphor-u-boot-mgr/phosphor-u-boot-mgr_git.bb18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb30
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts.bbappend3
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts/init258
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/prov-mode-mgr/prov-mode-mgr_git.bb18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/security-manager/security-manager_git.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch1658
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb35
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp258
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch336
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog.service16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb24
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.timer8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset.sh18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset@.service7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/files/ldb.sh1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/files/locked_groups1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/files/nscd.conf2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.conf16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.service15
-rw-r--r--meta-openbmc-mods/meta-common/recipes-security/sssd/sssd_%.bbappend26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/boost/boost/0001-Fix-Issue-62.patch28
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/boost/boost_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/default1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/init42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/rngd.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools_6.7.bb52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/beeper-test.bb17
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/.clang-format99
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/CMakeLists.txt7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/beeper-test.cpp81
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/dimmsensor.bb17
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/CMakeLists.txt7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/DimmSensor.cpp143
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/intel-signed-image/files/genimage-si.ini277
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/CMakeLists.txt7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/io-app.c696
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/io-app/io-app.bb17
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/CMakeLists.txt7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_cmds.c528
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h79
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/lpc-cmds.bb16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit/0001-Force-nbdkit-to-send-PATCH-as-upload-method.patch71
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit_git.bb35
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/files/peci-hwmon-test.py144
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/peci-hwmon-test.bb20
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend3
-rw-r--r--meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample25
-rw-r--r--meta-openbmc-mods/meta-wht/conf/conf-notes.txt6
-rw-r--r--meta-openbmc-mods/meta-wht/conf/layer.conf14
-rw-r--r--meta-openbmc-mods/meta-wht/conf/local.conf.sample32
-rw-r--r--meta-openbmc-mods/meta-wht/conf/machine/intel-ast2500.conf1
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample25
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/conf-notes.txt6
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/layer.conf14
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample25
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/machine/intel-ast2500.conf1
491 files changed, 67888 insertions, 156 deletions
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index 55a1b0a92..000000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Please do not submit a Pull Request via github. Our project makes use of
-Gerrit for patch submission and review. For more details please
-see https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md#submitting-changes-via-gerrit-server
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 000000000..7c36ade7a
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,21 @@
+name: CI
+
+on: [pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: Run a multi-line script
+ run: |
+ sudo apt update
+ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat
+ sudo apt autoremove
+ rm -rf build
+ export TEMPLATECONF=meta-openbmc-mods/meta-wht/conf
+ source oe-init-build-env
+ echo "INHERIT += \"rm_work_and_downloads\"" >> conf/local.conf
+ bitbake intel-platforms
diff --git a/README.md b/README.md
index 34ad9c2f3..178c83869 100644
--- a/README.md
+++ b/README.md
@@ -1,170 +1,95 @@
# OpenBMC
-[![Build Status](https://openpower.xyz/buildStatus/icon?job=openbmc-build)](https://openpower.xyz/job/openbmc-build/)
+![Build status](https://dev.azure.com/openbmc/OpenBMC/_apis/build/status/Intel-BMC.openbmc?branchName=intel "Build status")
+
+Intel-BMC/openbmc is a BMC implementation for servers. The purpose is to provide
+early access to features and capabilities which have not yet been accepted or
+merged in the OpenBMC main project (github.com/openbmc). In due course, all of
+the capabilities here will be brought to the OpenBMC project.
+
+For questions or support please email OpenBMC.Support@intel.com.
+
+Some answers to the main questions that tend to get asked:
+
+### Does this mean that Intel is no longer contributing to the Linux foundation project?
+
+No. This repo is for components that are intended for the eventual
+release to the LF OpenBMC project. There are a number of reasons where things
+might be checked in here. For example: functionality that is still under
+discussion or in the LF OpenBMC project, features that have not gone through
+the level of testing or integration needed to be included in the OpenBMC
+project
+
+### Why does this repo exist at all?
+
+Upstreaming changes to the linux kernel, uboot, systemd, yocto, and the various
+projects that OpenBMC pulls in requires a significant effort. While we aspire
+to that process being fast, painless, and with minimal rework, the reality is
+far from that, and features or functions that require changes across a number
+of repos require a coordinated effort, and a single source of function. As a
+general rule, this repository loosens the requirements of "form over function"
+and prefers to make some simplifying assumptions of BMC capabilities, chipsets,
+and required features.
+
+### Can I upstream/release the code from this repository?
+
+It very much depends on the component. While in general the answer ends up
+being "yes", prior approval should be granted, as this repo contains future
+facing capabilities that may not have been announced yet. Please email
+OpenBMC.Support@intel.com to discuss. Appropriate licenses will be applied to
+the portions of this codebase that are approved for upstreaming.
+
+### How to build for Wolf Pass
+```bash
+export TEMPLATECONF=meta-openbmc-mods/meta-wolfpass/conf
+source oe-init-build-env
+bitbake intel-platforms
+```
+### How to build for Intel reference
+```bash
+export TEMPLATECONF=meta-openbmc-mods/meta-wht/conf
+source oe-init-build-env
+bitbake intel-platforms
+```
-The OpenBMC project can be described as a Linux distribution for embedded
-devices that have a BMC; typically, but not limited to, things like servers,
-top of rack switches or RAID appliances. The OpenBMC stack uses technologies
-such as [Yocto](https://www.yoctoproject.org/),
-[OpenEmbedded](https://www.openembedded.org/wiki/Main_Page),
-[systemd](https://www.freedesktop.org/wiki/Software/systemd/), and
-[D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) to allow easy
-customization for your server platform.
+### Default User Credentials
+To meet Intel security requirements, this OpenBMC implementation will not have
+default user credentials enabled by default.
-## Setting up your OpenBMC project
+IPMI commands are available to enable the root user for serial console access
+and to enable users for IPMI, Redfish, and web access.
-### 1) Prerequisite
-- Ubuntu 14.04
+There is also a `"debug-tweaks"` feature that can be added to a build to
+re-enable the default user credentials.
-```
-sudo apt-get install -y git build-essential libsdl1.2-dev texinfo gawk chrpath diffstat
-```
+#### Enable root user
-- Fedora 28
+Without `"debug-tweaks"`, the root user is disabled by default.
-```
-sudo dnf install -y git patch diffstat texinfo chrpath SDL-devel bitbake \
- rpcgen perl-Thread-Queue perl-bignum perl-Crypt-OpenSSL-Bignum
-sudo dnf groupinstall "C Development Tools and Libraries"
-```
-### 2) Download the source
-```
-git clone git@github.com:openbmc/openbmc.git
-cd openbmc
-```
+The following IPMI command can be used to enable the root user. This root
+user allows access to the BMC serial console, but cannot be used to access
+IPMI, Redfish, or the web console.
-### 3) Target your hardware
-Any build requires an environment set up according to your hardware target.
-There is a special script in the root of this repository that can be used
-to configure the environment as needed. The script is called `setup` and
-takes the name of your hardware target as an argument.
+IPMI OEM net function 0x30, command 0x5f. For root user, the first byte is
+0 followed by the password.
-The script needs to be sourced while in the top directory of the OpenBMC
-repository clone, and, if run without arguments, will display the list
-of supported hardware targets, see the following example:
+For example, to enable the root user with password `0penBmc1`:
-```
-$ . setup
-Target machine must be specified. Use one of:
-
-centriq2400-rep nicole stardragon4800-rep2
-f0b olympus swift
-fp5280g2 olympus-nuvoton tiogapass
-gsj on5263m5 vesnin
-hr630 palmetto witherspoon
-hr855xg2 qemuarm witherspoon-128
-lanyang quanta-q71l witherspoon-tacoma
-mihawk rainier yosemitev2
-msn romulus zaius
-neptune s2600wf
-```
+```ipmitool raw 0x30 0x5f 0x00 0x30 0x70 0x65 0x6e 0x42 0x6d 0x63 0x31```
-Once you know the target (e.g. romulus), source the `setup` script as follows:
+#### Enable IPMI, Redfish, and web users
-```
-. setup romulus
-```
+Without `"debug-tweaks"`, there are no IPMI, Redfish, or web users by default.
-### 4) Build
+The standard IPMI commands to set usernames and passwords are supported.
+These users allow access to IPMI, Redfish, and the web console, but cannot be
+used to access the BMC serial console.
-```
-bitbake obmc-phosphor-image
-```
+#### debug-tweaks
+
+Debug features, including the default user credentials, can be enabled by
+adding the `"debug-tweaks"` feature to the build by including the following
+in your `local.conf` file:
-Additional details can be found in the [docs](https://github.com/openbmc/docs)
-repository.
-
-## OpenBMC Development
-
-The OpenBMC community maintains a set of tutorials new users can go through
-to get up to speed on OpenBMC development out
-[here](https://github.com/openbmc/docs/blob/master/development/README.md)
-
-## Build Validation and Testing
-Commits submitted by members of the OpenBMC GitHub community are compiled and
-tested via our [Jenkins](https://openpower.xyz/) server. Commits are run
-through two levels of testing. At the repository level the makefile `make
-check` directive is run. At the system level, the commit is built into a
-firmware image and run with an arm-softmmu QEMU model against a barrage of
-[CI tests](https://openpower.xyz/job/openbmc-test-qemu-ci/).
-
-Commits submitted by non-members do not automatically proceed through CI
-testing. After visual inspection of the commit, a CI run can be manually
-performed by the reviewer.
-
-Automated testing against the QEMU model along with supported systems are
-performed. The OpenBMC project uses the
-[Robot Framework](http://robotframework.org/) for all automation. Our
-complete test repository can be found
-[here](https://github.com/openbmc/openbmc-test-automation).
-
-## Submitting Patches
-Support of additional hardware and software packages is always welcome.
-Please follow the [contributing guidelines](https://github.com/openbmc/docs/blob/master/CONTRIBUTING.md)
-when making a submission. It is expected that contributions contain test
-cases.
-
-## Bug Reporting
-[Issues](https://github.com/openbmc/openbmc/issues) are managed on
-GitHub. It is recommended you search through the issues before opening
-a new one.
-
-## Questions
-
-First, please do a search on the internet. There's a good chance your question
-has already been asked.
-
-For general questions, please use the openbmc tag on
-[Stack Overflow](https://stackoverflow.com/questions/tagged/openbmc).
-Please review the [discussion](https://meta.stackexchange.com/questions/272956/a-new-code-license-the-mit-this-time-with-attribution-required?cb=1)
-on Stack Overflow licensing before posting any code.
-
-For technical discussions, please see [contact info](#contact) below for IRC and
-mailing list information. Please don't file an issue to ask a question. You'll
-get faster results by using the mailing list or IRC.
-
-## Features of OpenBMC
-
-**Feature List**
-* Host management: Power, Cooling, LEDs, Inventory, Events, Watchdog
-* Full IPMI 2.0 Compliance with DCMI
-* Code Update Support for multiple BMC/BIOS images
-* Web-based user interface
-* REST interfaces
-* D-Bus based interfaces
-* SSH based SOL
-* Remote KVM
-* Hardware Simulation
-* Automated Testing
-* User management
-* Virtual media
-
-**Features In Progress**
-* OpenCompute Redfish Compliance
-* Verified Boot
-
-**Features Requested but need help**
-* OpenBMC performance monitoring
-
-
-## Finding out more
-
-Dive deeper into OpenBMC by opening the
-[docs](https://github.com/openbmc/docs) repository.
-
-## Technical Steering Committee
-
-The Technical Steering Committee (TSC) guides the project. Members are:
-
- * Brad Bishop (chair), IBM
- * Nancy Yuen, Google
- * Sai Dasari, Facebook
- * James Mihm, Intel
- * Sagar Dharia, Microsoft
- * Supreeth Venkatesh, Arm
-
-## Contact
-- Mail: openbmc@lists.ozlabs.org [https://lists.ozlabs.org/listinfo/openbmc](https://lists.ozlabs.org/listinfo/openbmc)
-- IRC: #openbmc on freenode.net
-- Riot: [#openbmc:matrix.org](https://riot.im/app/#/room/#openbmc:matrix.org)
+```EXTRA_IMAGE_FEATURES += "debug-tweaks"```
diff --git a/meta-aspeed/recipes-bsp/u-boot/files/0001-aspeed-Limit-bootm-memory.patch b/meta-aspeed/recipes-bsp/u-boot/files/0001-aspeed-Limit-bootm-memory.patch
new file mode 100644
index 000000000..f6062971c
--- /dev/null
+++ b/meta-aspeed/recipes-bsp/u-boot/files/0001-aspeed-Limit-bootm-memory.patch
@@ -0,0 +1,31 @@
+From 41d6940891b91e27ea5509eda2247811a3ba0c0d Mon Sep 17 00:00:00 2001
+From: Joel Stanley <joel@jms.id.au>
+Date: Tue, 30 Jul 2019 15:52:05 +0930
+Subject: [PATCH] aspeed: Limit bootm memory
+
+This ensures u-boot places the kernel, device tree and initrd at an
+address that is accessible by the Linux early boot code.
+
+Without this, when booting with FIT the device tree is placed at the end
+of RAM which is not mapped on the AST2600 EVB which contains 2GB of RAM.
+
+Signed-off-by: Joel Stanley <joel@jms.id.au>
+---
+ include/configs/aspeed-common.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/configs/aspeed-common.h b/include/configs/aspeed-common.h
+index 3b345ba46333..eba4e1c79d80 100644
+--- a/include/configs/aspeed-common.h
++++ b/include/configs/aspeed-common.h
+@@ -41,6 +41,7 @@
+ #define CONFIG_SYS_INIT_SP_ADDR \
+ (SYS_INIT_RAM_END - GENERATED_GBL_DATA_SIZE)
+
++#define CONFIG_SYS_BOOTMAPSZ (256 * 1024 * 1024)
+ #define CONFIG_SYS_MALLOC_LEN (32 << 20)
+
+ /*
+--
+2.20.1
+
diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed-sdk/aspeed-g6/0001-aspeed-espi-Clean-up-error-handling.patch b/meta-aspeed/recipes-kernel/linux/linux-aspeed-sdk/aspeed-g6/0001-aspeed-espi-Clean-up-error-handling.patch
new file mode 100644
index 000000000..8c69abc34
--- /dev/null
+++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed-sdk/aspeed-g6/0001-aspeed-espi-Clean-up-error-handling.patch
@@ -0,0 +1,102 @@
+From aa808480fb9fa62c96bd38a83328a87971a95ed4 Mon Sep 17 00:00:00 2001
+From: Joel Stanley <joel@jms.id.au>
+Date: Wed, 31 Jul 2019 18:10:37 +0930
+Subject: [PATCH] aspeed: espi: Clean up error handling
+
+I was seeing a crash shortly after the ESPI driver failed to probe:
+
+ AST ESPI Unable to get GPIO IRQ -22
+ Trying to free nonexistent resource <000000001e6ee000-000000001e6ee1ff>
+ aspeed_espi: probe of 1e6ee000.espi failed with error -22
+
+The error handling was freeing the unallocated resource.
+
+The driver correctly makes allocations using the devm APIs. This means
+the kernel will handle cleaning up of resources on failure. This patch
+removes the unnecessary error handling.
+
+Signed-off-by: Joel Stanley <joel@jms.id.au>
+---
+ drivers/soc/aspeed/aspeed-espi.c | 30 ++++++------------------------
+ 1 file changed, 6 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/soc/aspeed/aspeed-espi.c b/drivers/soc/aspeed/aspeed-espi.c
+index 342d45bdbad3..2b72f05dd24f 100644
+--- a/drivers/soc/aspeed/aspeed-espi.c
++++ b/drivers/soc/aspeed/aspeed-espi.c
+@@ -1284,17 +1284,10 @@ static int aspeed_espi_probe(struct platform_device *pdev)
+ aspeed_espi->dma_mode = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (res == NULL) {
+- dev_err(&pdev->dev, "no memory resource defined\n");
+- ret = -ENODEV;
+- goto err_free;
+- }
+-
+ aspeed_espi->reg_base = devm_ioremap_resource(&pdev->dev, res);
+- if (aspeed_espi->reg_base == NULL) {
++ if (IS_ERR(aspeed_espi->reg_base)) {
+ dev_err(&pdev->dev, "failed to ioremap() registers\n");
+- ret = -ENODEV;
+- goto err_free_mem;
++ return ERR_PTR(aspeed_espi->reg_base);
+ }
+
+ sysfs_bin_attr_init(&aspeed_espi->oob_channel);
+@@ -1398,15 +1391,14 @@ static int aspeed_espi_probe(struct platform_device *pdev)
+ aspeed_espi->irq = platform_get_irq(pdev, 0);
+ if (aspeed_espi->irq < 0) {
+ dev_err(&pdev->dev, "no irq specified\n");
+- ret = -ENOENT;
+- goto err_free_mem;
++ return aspeed_espi->irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, aspeed_espi->irq, aspeed_espi_isr,
+ 0, dev_name(&pdev->dev), aspeed_espi);
+ if (ret) {
+ printk("AST ESPI Unable to get IRQ");
+- goto err_free_mem;
++ return ret;
+ }
+
+ aspeed_espi->reset = devm_reset_control_get(&pdev->dev, NULL);
+@@ -1421,7 +1413,7 @@ static int aspeed_espi_probe(struct platform_device *pdev)
+ 0, dev_name(&pdev->dev), aspeed_espi);
+ if (ret) {
+ printk("AST ESPI Unable to get GPIO IRQ %d\n", ret);
+- goto err_free_mem;
++ return ret;
+ }
+
+ aspeed_espi_ctrl_init(aspeed_espi);
+@@ -1429,7 +1421,7 @@ static int aspeed_espi_probe(struct platform_device *pdev)
+ ret = misc_register(&aspeed_espi_misc);
+ if (ret) {
+ printk(KERN_ERR "ESPI : failed misc_register\n");
+- goto err_free_irq;
++ return ret;
+ }
+
+ platform_set_drvdata(pdev, aspeed_espi);
+@@ -1444,16 +1436,6 @@ static int aspeed_espi_probe(struct platform_device *pdev)
+ printk(KERN_INFO "aspeed_espi: driver successfully loaded.\n");
+
+ return 0;
+-
+-err_free_irq:
+- free_irq(aspeed_espi->irq, pdev);
+-
+-err_free_mem:
+- release_mem_region(res->start, resource_size(res));
+-err_free:
+- kfree(aspeed_espi);
+-
+- return ret;
+ }
+
+ static int aspeed_espi_remove(struct platform_device *pdev)
+--
+2.20.1
+
diff --git a/meta-openbmc-mods/COPYING.MIT b/meta-openbmc-mods/COPYING.MIT
new file mode 100644
index 000000000..89de35479
--- /dev/null
+++ b/meta-openbmc-mods/COPYING.MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/meta-openbmc-mods/COPYING.apache-2.0 b/meta-openbmc-mods/COPYING.apache-2.0
new file mode 100644
index 000000000..67db85882
--- /dev/null
+++ b/meta-openbmc-mods/COPYING.apache-2.0
@@ -0,0 +1,175 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
diff --git a/meta-openbmc-mods/README b/meta-openbmc-mods/README
new file mode 100644
index 000000000..3d883acb2
--- /dev/null
+++ b/meta-openbmc-mods/README
@@ -0,0 +1,64 @@
+This README file contains information on the contents of the
+intel layer.
+
+Please see the corresponding sections below for details.
+
+
+Dependencies
+============
+
+This layer depends on:
+
+ URI: git://git.openembedded.org/bitbake
+ branch: master
+
+ URI: git://git.openembedded.org/openembedded-core
+ layers: meta
+ branch: master
+
+ URI: git://git.yoctoproject.org/xxxx
+ layers: xxxx
+ branch: master
+
+
+Patches
+=======
+
+Please submit any patches against the intel layer to the
+xxxx mailing list (xxxx@zzzz.org) and cc: the maintainer:
+
+Maintainer: XXX YYYYYY <xxx.yyyyyy@zzzzz.com>
+
+
+Table of Contents
+=================
+
+ I. Adding the intel layer to your build
+ II. Misc
+
+
+I. Adding the intel layer to your build
+=================================================
+
+--- replace with specific instructions for the intel layer ---
+
+In order to use this layer, you need to make the build system aware of
+it.
+
+Assuming the intel layer exists at the top-level of your
+yocto build tree, you can add it to the build system by adding the
+location of the intel layer to bblayers.conf, along with any
+other layers needed. e.g.:
+
+ BBLAYERS ?= " \
+ /path/to/yocto/meta \
+ /path/to/yocto/meta-poky \
+ /path/to/yocto/meta-yocto-bsp \
+ /path/to/yocto/meta-intel \
+ "
+
+
+II. Misc
+========
+
+--- replace with specific information about the intel layer ---
diff --git a/meta-openbmc-mods/conf/layer.conf b/meta-openbmc-mods/conf/layer.conf
new file mode 100644
index 000000000..71d23a2ba
--- /dev/null
+++ b/meta-openbmc-mods/conf/layer.conf
@@ -0,0 +1,22 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "intel-openbmc"
+BBFILE_PATTERN_intel-openbmc = "^${LAYERDIR}/"
+BBFILE_PRIORITY_intel-openbmc = "5"
+LAYERSERIES_COMPAT_intel-openbmc = "warrior zeus"
+
+IMAGE_FEATURES[validitems] += "tools-sdk tools-debug validation-unsecure"
+
+# static userid assignments
+USERADDEXTENSION = "useradd-staticids"
+USERADD_UID_TABLES = "files/passwd"
+USERADD_GID_TABLES = "files/group"
+
+LAYER_CONF_VERSION = "11"
+
+INTELBASE = '${@os.path.normpath("${LAYERDIR}/")}'
diff --git a/meta-openbmc-mods/conf/machine/include/intel.inc b/meta-openbmc-mods/conf/machine/include/intel.inc
new file mode 100644
index 000000000..8f1c9403e
--- /dev/null
+++ b/meta-openbmc-mods/conf/machine/include/intel.inc
@@ -0,0 +1,29 @@
+OBMC_MACHINE_FEATURES += "\
+ obmc-phosphor-fan-mgmt \
+ obmc-phosphor-chassis-mgmt \
+ obmc-phosphor-flash-mgmt \
+ obmc-host-ipmi \
+ obmc-host-state-mgmt \
+ obmc-chassis-state-mgmt \
+ obmc-bmc-state-mgmt \
+ "
+
+VIRTUAL-RUNTIME_skeleton_workbook = "${MACHINE}-config"
+VIRTUAL-RUNTIME_obmc-inventory-manager = "entity-manager"
+VIRTUAL-RUNTIME_obmc-led-monitor = ""
+VIRTUAL-RUNTIME_obmc-host-state-manager = "x86-power-control"
+VIRTUAL-RUNTIME_obmc-chassis-state-manager = "x86-power-control"
+VIRTUAL-RUNTIME_obmc-discover-system-state = "x86-power-control"
+
+PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw = "phosphor-ipmi-kcs"
+PREFERRED_PROVIDER_virtual/obmc-chassis-mgmt = "packagegroup-intel-apps"
+PREFERRED_PROVIDER_virtual/obmc-fan-mgmt = "packagegroup-intel-apps"
+PREFERRED_PROVIDER_virtual/obmc-flash-mgmt = "packagegroup-intel-apps"
+PREFERRED_PROVIDER_virtual/obmc-system-mgmt = "packagegroup-intel-apps"
+PREFERRED_PROVIDER_virtual/obmc-host-ctl ?= ""
+PREFERRED_PROVIDER_virtual/obmc-inventory-data = "entity-manager"
+PREFERRED_PROVIDER_virtual/phosphor-led-manager-config-native ?= "intel-led-manager-config-native"
+#PREFERRED_PROVIDER_virtual/obmc-gpio-monitor ?= "phosphor-gpio-monitor"
+
+# add all the upstream intel override fixes
+OVERRIDES .= ":intel"
diff --git a/meta-openbmc-mods/files/group b/meta-openbmc-mods/files/group
new file mode 100644
index 000000000..8f8c8e325
--- /dev/null
+++ b/meta-openbmc-mods/files/group
@@ -0,0 +1,12 @@
+bmcweb:x:443:
+ipmid:x:197:
+lock:x:198:
+netdev:x:208:
+avahi:x:200:
+messagebus:x:201
+systemd-journal:x:202:
+systemd-network:x:203:
+systemd-timesync:x:204:
+systemd-coredump:x:205:
+systemd-bus-proxy:x:206:
+systemd-resolve:!:207:
diff --git a/meta-openbmc-mods/files/passwd b/meta-openbmc-mods/files/passwd
new file mode 100644
index 000000000..ae48cfb46
--- /dev/null
+++ b/meta-openbmc-mods/files/passwd
@@ -0,0 +1,10 @@
+bmcweb:x:443:443::/home/bmcweb:/bin/false
+hostipmid:x:196:197::/:/bin/false
+netipmid:x:197:197::/:/bin/false
+avahi:x:200:200::/var/run/avahi-daemon:/bin/false
+messagebus:x:201:201::/var/lib/dbus:/bin/false
+systemd-network:x:203:203::/:/bin/false
+systemd-timesync:x:204:204::/:/bin/false
+systemd-coredump:x:205:205::/:/bin/false
+systemd-bus-proxy:x:206:206::/:/bin/false
+systemd-resolve:!:207:207::/:/bin/nologin
diff --git a/meta-openbmc-mods/meta-ast2500/conf/layer.conf b/meta-openbmc-mods/meta-ast2500/conf/layer.conf
new file mode 100644
index 000000000..85a83d411
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/conf/layer.conf
@@ -0,0 +1,20 @@
+LOCALCONF_VERSION = "3"
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "ast2500"
+BBFILE_PATTERN_ast2500 = ""
+BBFILE_PRIORITY_ast2500 = "4"
+LAYERSERIES_COMPAT_ast2500 = "warrior zeus"
+
+INHERIT += "extrausers"
+#INHERIT += " cve-check"
+
+EXTRA_USERS_PARAMS_append_pn-intel-platforms = " \
+${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', "usermod -p '\$1\$UGMqyqdG\$FZiylVFmRRfl9Z0Ue8G7e/' root;", '', d)}"
+
+hostname_pn-base-files = "intel-obmc"
diff --git a/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc b/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
new file mode 100644
index 000000000..1889831c8
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
@@ -0,0 +1,12 @@
+KMACHINE = "aspeed"
+KERNEL_DEVICETREE = "${KMACHINE}-bmc-intel-ast2500.dtb"
+
+require conf/machine/include/ast2500.inc
+require conf/machine/include/obmc-bsp-si-common.inc
+require conf/machine/include/intel.inc
+require conf/distro/include/phosphor-tiny.inc
+require conf/distro/include/phosphor-isolation.inc
+
+UBOOT_MACHINE = "ast_g5_phy_config"
+
+VIRTUAL-RUNTIME_skeleton_workbook = "${MACHINE}-config"
diff --git a/meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc b/meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc
new file mode 100644
index 000000000..3ad449118
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc
@@ -0,0 +1,43 @@
+#@TYPE: Machine
+#@NAME: OpenBMC
+#@DESCRIPTION: Common machine configuration for OpenBMC chips
+
+MACHINE_EXTRA_RRECOMMENDS = " kernel-modules"
+EXTRA_IMAGEDEPENDS += "u-boot"
+
+IMAGE_FSTYPES += "squashfs-xz"
+IMAGE_FSTYPES += "mtd-auto"
+INITRAMFS_FSTYPES = "squashfs-xz"
+EXTRA_IMAGECMD_squashfs-xz_append = "-processors ${BB_NUMBER_THREADS} -b 262144 -Xdict-size 100% -Xbcj arm"
+
+KERNEL_CLASSES ?= "kernel-fitimage"
+KERNEL_IMAGETYPES ?= "fitImage"
+KERNEL_EXTRA_ARGS += "LOADADDR=${UBOOT_ENTRYPOINT}"
+
+UBOOT_SUFFIX ?= "bin"
+
+MACHINEOVERRIDES =. "openbmc:"
+
+OBMC_PHOSPHOR_IMAGE_OVERLAY= "1"
+OBMC_IMAGE_EXTRA_INSTALL_append = " u-boot-fw-utils-aspeed"
+
+IMAGE_CLASSES += "image_types image_types_phosphor_auto qemuboot"
+IMAGE_CLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'image_types_intel_pfr', '', d)}"
+
+# do not generate an initramfs; use the above squashfs-xz as an initrd instead
+INITRAMFS_FSTYPES = ""
+INITRAMFS_CTYPE = ""
+INITRAMFS_IMAGE = ""
+
+MACHINE_FEATURES_BACKFILL_CONSIDERED = "qemu-usermode"
+
+KERNEL_IMAGETYPES += "zImage"
+
+# runqemu
+QB_SYSTEM_NAME = "qemu-system-arm"
+QB_DEFAULT_FSTYPE = "mtd"
+QB_ROOTFS_OPT = "-drive file=@ROOTFS@,format=raw,if=mtd"
+QB_MACHINE = "-M intel-ast2500"
+QB_OPT_APPEND += " -nographic"
+QB_NETWORK_DEVICE = "-net nic,macaddr=C0:FF:EE:00:00:02,model=ftgmac100"
+QB_DEFAULT_KERNEL = "none"
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch
new file mode 100644
index 000000000..73ab78a65
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch
@@ -0,0 +1,424 @@
+Index: u-boot/arch/arm/mach-aspeed/flash.c
+===================================================================
+--- u-boot.orig/arch/arm/mach-aspeed/flash.c
++++ u-boot/arch/arm/mach-aspeed/flash.c
+@@ -28,6 +28,7 @@
+ #include <common.h>
+ #include <asm/processor.h>
+ #include <asm/byteorder.h>
++#include <asm/io.h>
+ #include <environment.h>
+
+ #include <asm/arch/ast_scu.h>
+@@ -199,7 +200,7 @@ static void reset_flash (flash_info_t *
+ if (info->dualport)
+ ulCtrlData |= 0x08;
+ #endif
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ }
+
+@@ -228,28 +229,22 @@ static void enable_write (flash_info_t *
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x06);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x06, base);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x05);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x05, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while (!(jReg & 0x02));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ }
+
+@@ -280,30 +275,23 @@ static void write_status_register (flash
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x01);
+- udelay(10);
+- *(uchar *) (base) = (uchar) (data);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x01, base);
++ writeb(data, base);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x05);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x05, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while (jReg & 0x01);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+-
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+ }
+
+ static void enable4b (flash_info_t * info)
+@@ -330,13 +318,11 @@ static void enable4b (flash_info_t * inf
+
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0xb7);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0xb7, base);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ } /* enable4b */
+
+@@ -366,29 +352,23 @@ static void enable4b_spansion (flash_inf
+ /* Enable 4B: BAR0 D[7] = 1 */
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x17);
+- udelay(10);
+- *(uchar *) (base) = (uchar) (0x80);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x17, base);
++ writeb(0x80, base);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x16);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x16, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while (!(jReg & 0x80));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ } /* enable4b_spansion */
+
+@@ -420,14 +400,11 @@ static void enable4b_numonyx (flash_info
+ /* Enable 4B: CMD:0xB7 */
+ ulCtrlData = (info->tCK_Write << 8);
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0xB7);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0xB7, base);
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ } /* enable4b_numonyx */
+
+@@ -463,63 +440,49 @@ static void flash_write_buffer (flash_in
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x02);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x02, base);
+ if (info->address32)
+ {
+- *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
+- udelay(10);
++ writeb((uchar) ((offset & 0xff000000) >> 24), base);
+ }
+- *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
+- udelay(10);
+- *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
+- udelay(10);
+- *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
+- udelay(10);
++ writeb((uchar) ((offset & 0xff0000) >> 16), base);
++ writeb((uchar) ((offset & 0x00ff00) >> 8), base);
++ writeb((uchar) ((offset & 0x0000ff)), base);
+
+ for (j=0; j<len; j++)
+ {
+- *(uchar *) (base) = *(uchar *) (src++);
+- udelay(10);
++ writeb(*src++, base);
+ }
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x05);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x05, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while ((jReg & 0x01));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ /* RFSR */
+ if (info->specificspi == SpecificSPI_N25Q512)
+ {
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x70);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x70, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while (!(jReg & 0x80));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+ }
+ }
+
+@@ -603,57 +566,44 @@ int flash_erase (flash_info_t * info, in
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0xd8);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0xd8, base);
+ if (info->address32)
+ {
+- *(uchar *) (base) = (uchar) ((offset & 0xff000000) >> 24);
+- udelay(10);
++ writeb((uchar) ((offset & 0xff000000) >> 24), base);
+ }
+- *(uchar *) (base) = (uchar) ((offset & 0xff0000) >> 16);
+- udelay(10);
+- *(uchar *) (base) = (uchar) ((offset & 0x00ff00) >> 8);
+- udelay(10);
+- *(uchar *) (base) = (uchar) ((offset & 0x0000ff));
+- udelay(10);
++ writeb((uchar) ((offset & 0xff0000) >> 16), base);
++ writeb((uchar) ((offset & 0x00ff00) >> 8), base);
++ writeb((uchar) ((offset & 0x0000ff)), base);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x05);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x05, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while ((jReg & 0x01));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+
+ /* RFSR */
+ if (info->specificspi == SpecificSPI_N25Q512)
+ {
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (base) = (uchar) (0x70);
+- udelay(10);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x70, base);
+ do {
+- jReg = *(volatile uchar *) (base);
++ jReg = readb(base);
+ } while (!(jReg & 0x80));
+ ulCtrlData &= CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+ }
+
+ putc ('.');
+@@ -764,22 +714,16 @@ static ulong flash_get_size (ulong base,
+ }
+
+ /* Get Flash ID */
+- ulCtrlData = *(ulong *) (info->reg_base + CtrlOffset) & CMD_MASK;
++ ulCtrlData = readl(info->reg_base + CtrlOffset) & CMD_MASK;
+ ulCtrlData |= CE_LOW | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
+- *(uchar *) (vbase) = (uchar) (0x9F);
+- udelay(10);
+- ch[0] = *(volatile uchar *)(vbase);
+- udelay(10);
+- ch[1] = *(volatile uchar *)(vbase);
+- udelay(10);
+- ch[2] = *(volatile uchar *)(vbase);
+- udelay(10);
+- ulCtrlData = *(ulong *) (info->reg_base + CtrlOffset) & CMD_MASK;
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
++ writeb(0x9F, vbase);
++ ch[0] = readb(vbase);
++ ch[1] = readb(vbase);
++ ch[2] = readb(vbase);
++ ulCtrlData = readl(info->reg_base + CtrlOffset) & CMD_MASK;
+ ulCtrlData |= CE_HIGH | USERMODE;
+- *(ulong *) (info->reg_base + CtrlOffset) = ulCtrlData;
+- udelay(200);
++ writel(ulCtrlData, info->reg_base + CtrlOffset);
+ ulID = ((ulong)ch[0]) | ((ulong)ch[1] << 8) | ((ulong)ch[2] << 16) ;
+ info->flash_id = ulID;
+
+@@ -1294,13 +1238,13 @@ static ulong flash_get_size (ulong base,
+
+ if (info->address32) {
+ #ifndef AST_SOC_G5
+- reg = *((volatile ulong*) 0x1e6e2070); /* set H/W Trappings */
++ reg = readl(0x1e6e2070); /* set H/W Trappings */
+ reg |= 0x10;
+- *((volatile ulong*) 0x1e6e2070) = reg;
++ writel(reg, 0x1e6e2070);
+ #endif
+- reg = *((volatile ulong*) (info->reg_base + 0x4)); /* enable 32b control bit*/
++ reg = readl(info->reg_base + 0x4); /* enable 32b control bit*/
+ reg |= (0x01 << info->CE);
+- *((volatile ulong*) (info->reg_base + 0x4)) = reg;
++ writel(reg, info->reg_base + 0x4);
+
+ /* set flash chips to 32bits addressing mode */
+ if ((info->flash_id & 0xFF) == 0x01) /* Spansion */
+@@ -1322,7 +1266,7 @@ unsigned long flash_init (void)
+ unsigned long size = 0;
+ int i;
+
+- *((volatile ulong*) AST_FMC_BASE) |= 0x800f0000; /* enable Flash Write */
++ writel(readl(AST_FMC_BASE) | 0x800f0000, AST_FMC_BASE); /* enable Flash Write */
+
+ /* Init: FMC */
+ /* BANK 0 : FMC CS0 , 1: FMC CS1, */
+@@ -1352,7 +1296,7 @@ unsigned long flash_init (void)
+ #ifdef CONFIG_SPI0_CS
+ //pin switch by trap[13:12] -- [0:1] Enable SPI Master
+ ast_scu_spi_master(1); /* enable SPI master */
+- *((volatile ulong*) AST_FMC_SPI0_BASE) |= 0x10000; /* enable Flash Write */
++ writel(readl(AST_FMC_SPI0_BASE) | 0x10000, AST_FMC_SPI0_BASE); /* enable Flash Write */
+ flash_info[CONFIG_FMC_CS].sysspi = 1;
+ flash_info[CONFIG_FMC_CS].reg_base = AST_FMC_SPI0_BASE;
+ flash_info[CONFIG_FMC_CS].flash_id = FLASH_UNKNOWN;
+@@ -1403,21 +1347,24 @@ void memmove_dma(void * dest,const void
+ poll_time = 100; /* set 100 us as default */
+
+ /* force end of burst read */
+- *(volatile ulong *) (AST_FMC_BASE + CS0_CTRL) |= CE_HIGH;
+- *(volatile ulong *) (AST_FMC_BASE + CS0_CTRL) &= ~CE_HIGH;
+-
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_DMA_CONTROL) = (ulong) (~FLASH_DMA_ENABLE);
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_DMA_FLASH_BASE) = (ulong) (src);
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_DMA_DRAM_BASE) = (ulong) (dest);
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_DMA_LENGTH) = (ulong) (count_align);
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_DMA_CONTROL) = (ulong) (FLASH_DMA_ENABLE);
++ data = readl(AST_FMC_BASE + CS0_CTRL);
++ writel(data | CE_HIGH, AST_FMC_BASE + CS0_CTRL);
++ writel(data & ~CE_HIGH, AST_FMC_BASE + CS0_CTRL);
++
++ writel(~FLASH_DMA_ENABLE, AST_FMC_BASE + REG_FLASH_DMA_CONTROL);
++ writel((ulong)src, AST_FMC_BASE + REG_FLASH_DMA_FLASH_BASE);
++ writel((ulong)dest, AST_FMC_BASE + REG_FLASH_DMA_DRAM_BASE);
++ writel(count_align, AST_FMC_BASE + REG_FLASH_DMA_LENGTH);
++ writel(FLASH_DMA_ENABLE, AST_FMC_BASE + REG_FLASH_DMA_CONTROL);
+
+ /* wait poll */
+ do {
+ udelay(poll_time);
+- data = *(ulong *) (AST_FMC_BASE + REG_FLASH_INTERRUPT_STATUS);
++ data = readl(AST_FMC_BASE + REG_FLASH_INTERRUPT_STATUS);
+ } while (!(data & FLASH_STATUS_DMA_READY));
+
+ /* clear status */
+- *(ulong *) (AST_FMC_BASE + REG_FLASH_INTERRUPT_STATUS) |= FLASH_STATUS_DMA_CLEAR;
++ data = readl(AST_FMC_BASE + REG_FLASH_INTERRUPT_STATUS);
++ writel(data | FLASH_STATUS_DMA_CLEAR,
++ AST_FMC_BASE + REG_FLASH_INTERRUPT_STATUS);
+ }
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch
new file mode 100644
index 000000000..8937047c5
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch
@@ -0,0 +1,51 @@
+From 7979a73fba832747ed3c037c0b47c9e67dcf283e Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Mon, 30 Apr 2018 10:52:37 -0700
+
+---
+ common/board_r.c | 8 ++++++--
+ include/configs/ast-common.h | 9 ++++++---
+ 2 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/common/board_r.c b/common/board_r.c
+index d959ad3..74797ed 100644
+--- a/common/board_r.c
++++ b/common/board_r.c
+@@ -494,10 +494,14 @@ static int should_load_env(void)
+ static int initr_env(void)
+ {
+ /* initialize environment */
+- if (should_load_env())
++ if (should_load_env()) {
++ /* try again, in case the environment failed to load the first time */
++ if (!gd->env_valid)
++ env_init();
+ env_relocate();
+- else
++ } else {
+ set_default_env(NULL);
++ }
+ #ifdef CONFIG_OF_CONTROL
+ setenv_addr("fdtcontroladdr", gd->fdt_blob);
+ #endif
+diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h
+index eff6d2b..b7d7192 100644
+--- a/include/configs/ast-common.h
++++ b/include/configs/ast-common.h
+@@ -103,10 +103,13 @@
+ #define CONFIG_SYS_MAX_FLASH_BANKS (CONFIG_FMC_CS)
+ #define CONFIG_SYS_MAX_FLASH_SECT (8192) /* max number of sectors on one chip */
+ #define CONFIG_ENV_IS_IN_FLASH 1
+-#define CONFIG_ENV_ADDR (AST_FMC_CS0_BASE + 0x60000)
++#define CONFIG_ENV_OFFSET 0x2400000 /* environment starts here */
++#define CONFIG_ENV_ADDR (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET)
++#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
+
+-#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */
+-#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */
++#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
++#define CONFIG_ENV_ADDR_REDUND (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET_REDUND)
++#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
+
+ #define CONFIG_BOOTCOMMAND "bootm 20080000"
+ #define CONFIG_ENV_OVERWRITE
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch
new file mode 100644
index 000000000..e7e6c56d7
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch
@@ -0,0 +1,73 @@
+From 954e7dd9ff9c5d1159f0896afa34c673061b82ea Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Tue, 11 Sep 2018 16:24:06 +0800
+Subject: [PATCH] Make sure debug uart is using 24MHz clock source
+
+u-boot defines the uart5(debug console) as 24MHz,
+set the SCU14[28] to 0, to make sure the clock source is 24M
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+
+---
+ arch/arm/include/asm/arch-aspeed/ast_scu.h | 2 ++
+ arch/arm/include/asm/arch-aspeed/platform.h | 1 +
+ arch/arm/mach-aspeed/ast-scu.c | 6 ++++++
+ board/aspeed/ast-g5/ast-g5.c | 8 ++++++++
+ 4 files changed, 17 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+index dcbc673..06825ce 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast_scu.h
++++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+@@ -46,4 +46,6 @@ extern void ast_scu_init_eth(u8 num);
+ extern void ast_scu_multi_func_eth(u8 num);
+ extern void ast_scu_multi_func_romcs(u8 num);
+
++void ast_config_uart5_clk(void);
++
+ #endif
+diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h
+index 1c02914..92ea33b 100644
+--- a/arch/arm/include/asm/arch-aspeed/platform.h
++++ b/arch/arm/include/asm/arch-aspeed/platform.h
+@@ -27,6 +27,7 @@
+ #include <asm/arch/ast2400_platform.h>
+ #elif defined(AST_SOC_G5)
+ #include <asm/arch/ast_g5_platform.h>
++#define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */
+ #else
+ #err "No define for platform.h"
+ #endif
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index 12de9b8..fff02dc 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -538,3 +538,9 @@ void ast_scu_get_who_init_dram(void)
+ break;
+ }
+ }
++
++void ast_config_uart5_clk(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) &
++ ~(1 << 28), AST_SCU_MISC2_CTRL);
++}
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index e67a4bf..5a1fade 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -16,6 +16,14 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
++int board_early_init_f(void)
++{
++ /* make sure uart5 is using 24MHz clock */
++ ast_config_uart5_clk();
++
++ return 0;
++}
++
+ int board_init(void)
+ {
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch
new file mode 100644
index 000000000..6bd063e39
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch
@@ -0,0 +1,53 @@
+From 7e11461d6b65969005605f13677269eb91d39643 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Wed, 7 Nov 2018 13:57:57 +0800
+Subject: [PATCH] enable passthrough in uboot
+
+---
+ arch/arm/mach-aspeed/ast-scu.c | 22 ++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5.c | 2 ++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index fff02dc..d27f3d3 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -544,3 +544,25 @@ void ast_config_uart5_clk(void)
+ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) &
+ ~(1 << 28), AST_SCU_MISC2_CTRL);
+ }
++
++
++void ast_enable_pass_through(void)
++{
++ //Enable GPIOE pin mode, SCU80[16:23] = 00 */
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & (~0x00FF0000),
++ AST_SCU_FUN_PIN_CTRL1);
++
++ //Enable all pass through pins by setting SCU8C[15:12] = 0x3.
++ //Pass-through pins set:
++ //GPIOE0 -> GPIOE1
++ //GPIOE2 -> GPIOE3
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | (0x3000),
++ AST_SCU_FUN_PIN_CTRL4);
++
++ //Disable HWStrap for GPIOE pass-through mode
++ //The write operation to SCU70(0x1e6e2070) only can set to '1'.
++ //To clear to '0', it must write '1' to 0x1e6e207c
++ if (ast_scu_read(AST_SCU_HW_STRAP1) & (0x1 << 22)){
++ ast_scu_write((0x1 << 22), AST_SCU_REVISION_ID);
++ }
++}
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index 5a1fade..b492003 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -20,6 +20,8 @@ int board_early_init_f(void)
+ {
+ /* make sure uart5 is using 24MHz clock */
+ ast_config_uart5_clk();
++ /*enable pass through*/
++ ast_enable_pass_through();
+
+ return 0;
+ }
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch
new file mode 100644
index 000000000..4f90d6dfe
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch
@@ -0,0 +1,387 @@
+From e782f6a90468fee35877b78e248a17f39f67c94c Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Wed, 14 Nov 2018 10:21:40 -0800
+Subject: [PATCH] Add Aspeed g5 interrupt support
+
+This adds a few new files to the board g5 directory. Several Intel
+features require interrupts running in U-Boot, so this adds basic
+interrupt registration and handling support.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Change-Id: Id7072f1408dcf364968b1b74f2192e50a22a82f0
+
+---
+ Kconfig | 13 +++
+ arch/arm/lib/interrupts.c | 11 +++
+ board/aspeed/ast-g5/Makefile | 3 +-
+ board/aspeed/ast-g5/ast-g5-irq.c | 176 ++++++++++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-irq.h | 39 ++++++++
+ board/aspeed/ast-g5/ast-g5.c | 3 +
+ board/aspeed/ast-g5/ast-g5.h | 7 ++
+ cmd/Kconfig | 5 +
+ configs/ast_g5_ncsi_2boot_defconfig | 1 +
+ configs/ast_g5_ncsi_defconfig | 1 +
+ configs/ast_g5_phy_defconfig | 1 +
+ 11 files changed, 259 insertions(+), 1 deletion(-)
+ create mode 100644 board/aspeed/ast-g5/ast-g5-irq.c
+ create mode 100644 board/aspeed/ast-g5/ast-g5-irq.h
+ create mode 100644 board/aspeed/ast-g5/ast-g5.h
+
+diff --git a/Kconfig b/Kconfig
+index 3ceff25..d6439d0 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -115,6 +115,19 @@ if EXPERT
+ When disabling this, please check if malloc calls, maybe
+ should be replaced by calloc - if one expects zeroed memory.
+ endif
++
++config USE_IRQ
++ bool "Use interrupts"
++ default n
++
++config STACKSIZE_IRQ
++ int "Size for IRQ stack (only if USE_IRQ enabled)"
++ default 16384
++
++config STACKSIZE_FIQ
++ int "Size for FIQ stack (only if USE_IRQ enabled)"
++ default 16384
++
+ endmenu # General setup
+
+ menu "Boot images"
+diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
+index ed83043..a96b3aa 100644
+--- a/arch/arm/lib/interrupts.c
++++ b/arch/arm/lib/interrupts.c
+@@ -94,6 +94,17 @@ int disable_interrupts (void)
+ : "memory");
+ return (old & 0x80) == 0;
+ }
++
++int global_interrupts_enabled(void)
++{
++ unsigned long old;
++ __asm__ __volatile__("mrs %0, cpsr\n"
++ : "=r" (old)
++ :
++ : "memory");
++ return (old & 0x80) == 0;
++}
++
+ #else
+ int interrupt_init (void)
+ {
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index d1d7f85..df4e639 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -1 +1,2 @@
+-obj-y = ast-g5.o
++obj-y += ast-g5.o
++obj-y += ast-g5-irq.o
+diff --git a/board/aspeed/ast-g5/ast-g5-irq.c b/board/aspeed/ast-g5/ast-g5-irq.c
+new file mode 100644
+index 0000000..860f16c
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-irq.c
+@@ -0,0 +1,176 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <netdev.h>
++
++#include <asm/arch/ast_scu.h>
++#include <asm/arch/ast-sdmc.h>
++#include <asm/io.h>
++
++#include "ast-g5.h"
++#include "ast-g5-irq.h"
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#ifdef CONFIG_USE_IRQ
++
++#define VIC_STATUS_L 0x80
++#define VIC_STATUS_H 0x84
++#define VIC_IRQ_SELECTION_L 0x98
++#define VIC_IRQ_SELECTION_H 0x9C
++#define VIC_ENABLE_L 0xA0
++#define VIC_ENABLE_H 0xA4
++#define VIC_ENABLE_CLEAR_L 0xA8
++#define VIC_ENABLE_CLEAR_H 0xAC
++#define VIC_INTERRUPT_CLEAR_L 0xD8
++#define VIC_INTERRUPT_CLEAR_H 0xDC
++
++#define VIC_CLEAR_ALL (~0)
++
++int arch_interrupt_init_early(void)
++{
++ writel(VIC_CLEAR_ALL, AST_VIC_BASE + VIC_ENABLE_CLEAR_L);
++ writel(VIC_CLEAR_ALL, AST_VIC_BASE + VIC_ENABLE_CLEAR_H);
++ return 0;
++}
++int arch_interrupt_init(void)
++{
++ return 0;
++}
++
++#define AST_IRQ_START_L 0
++#define AST_IRQ_END_L 31
++#define AST_IRQ_START_H 32
++#define AST_IRQ_END_H 63
++#define AST_IRQ_COUNT 64
++static interrupt_handler_t *handlers[AST_IRQ_COUNT] = {NULL};
++static unsigned long irq_total = 0;
++static unsigned long irq_counts[AST_IRQ_COUNT] = {0};
++
++int request_irq(int irq, interrupt_handler_t *handler)
++{
++ if (irq < AST_IRQ_START_L || irq > AST_IRQ_END_H) {
++ printf("irq %d out of range\n", irq);
++ return -1;
++ }
++ if (handlers[irq]) {
++ printf("irq %d already in use (%p)\n", irq, handlers[irq]);
++ return -1;
++ }
++ handlers[irq] = handler;
++ if (irq < AST_IRQ_START_H) {
++ writel((1 << irq), AST_VIC_BASE + VIC_ENABLE_L);
++ } else {
++ writel((1 << (irq - AST_IRQ_START_H)),
++ AST_VIC_BASE + VIC_ENABLE_H);
++ }
++ return 0;
++}
++
++int release_irq(int irq)
++{
++ if (irq < AST_IRQ_START_L || irq > AST_IRQ_END_H) {
++ return -1;
++ }
++ if (handlers[irq]) {
++ handlers[irq] = NULL;
++ if (irq < AST_IRQ_START_H) {
++ writel((1 << irq), AST_VIC_BASE + VIC_ENABLE_CLEAR_L);
++ } else {
++ writel((1 << (irq - AST_IRQ_START_H)),
++ AST_VIC_BASE + VIC_ENABLE_CLEAR_H);
++ }
++ }
++ return 0;
++}
++
++extern int global_interrupts_enabled(void);
++int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
++{
++ int i;
++ int enabled = global_interrupts_enabled();
++ unsigned long long irqs_enabled =
++ ((unsigned long long)readl(AST_VIC_BASE + VIC_ENABLE_H))
++ << AST_IRQ_START_H
++ | readl(AST_VIC_BASE + VIC_ENABLE_L);
++ printf("interrupts %sabled\n", (enabled ? "en" : "dis"));
++ for (i = AST_IRQ_START_L; i < AST_IRQ_COUNT; i++) {
++ printf("% 2i (% 3s): %lu\n", i,
++ ((irqs_enabled & 1) ? "on" : "off"), irq_counts[i]);
++ irqs_enabled >>= 1;
++ }
++ printf("total: %lu\n", irq_total);
++ return 0;
++}
++
++void do_irq(struct pt_regs *pt_regs)
++{
++ uint32_t irq = readl(AST_VIC_BASE + VIC_STATUS_L);
++ int i;
++ irq_total++;
++ if (irq) {
++ // handler irq0-31
++ for (i = AST_IRQ_START_L; i <= AST_IRQ_END_L; i++) {
++ if (irq & (1 << i)) {
++ irq_counts[i]++;
++ /* mask */
++ writel((1 << i),
++ AST_VIC_BASE + VIC_ENABLE_CLEAR_L);
++ if (handlers[i]) {
++ handlers[i](pt_regs);
++ /* clear */
++ writel((1 << i),
++ AST_VIC_BASE
++ + VIC_INTERRUPT_CLEAR_L);
++ /* unmask */
++ writel((1 << i),
++ AST_VIC_BASE + VIC_ENABLE_L);
++ } else {
++ printf("unexpected interrupt %i; masking\n",
++ i);
++ /* clear; do not unmask */
++ writel((1 << i),
++ AST_VIC_BASE
++ + VIC_INTERRUPT_CLEAR_L);
++ }
++ }
++ }
++ }
++ irq = readl(AST_VIC_BASE + VIC_STATUS_H);
++ if (irq) {
++ // handler irq32-63
++ for (i = AST_IRQ_START_H; i <= AST_IRQ_END_H; i++) {
++ if (irq & (1 << (i - AST_IRQ_START_H))) {
++ irq_counts[i]++;
++ /* mask */
++ writel((1 << (i - AST_IRQ_START_H)),
++ AST_VIC_BASE + VIC_ENABLE_CLEAR_H);
++ if (handlers[i]) {
++ handlers[i](pt_regs);
++ /* clear */
++ writel((1 << (i - AST_IRQ_START_H)),
++ AST_VIC_BASE
++ + VIC_INTERRUPT_CLEAR_H);
++ /* unmask */
++ writel((1 << (i - AST_IRQ_START_H)),
++ AST_VIC_BASE + VIC_ENABLE_H);
++ } else {
++ printf("unexpected interrupt %i; masking\n",
++ i);
++ /* clear; do not unmask */
++ writel((1 << (i - AST_IRQ_START_H)),
++ AST_VIC_BASE
++ + VIC_INTERRUPT_CLEAR_H);
++ }
++ }
++ }
++ }
++}
++#endif
+diff --git a/board/aspeed/ast-g5/ast-g5-irq.h b/board/aspeed/ast-g5/ast-g5-irq.h
+new file mode 100644
+index 0000000..703eeab
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-irq.h
+@@ -0,0 +1,39 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef __AST_G5_IRQ_H__
++#define __AST_G5_IRQ_H__
++
++#include <common.h>
++
++#ifdef CONFIG_USE_IRQ
++
++int arch_interrupt_init_early(void);
++
++int request_irq(int irq, interrupt_handler_t *handler);
++
++int release_irq(int irq);
++
++#else /* CONFIG_USE_IRQ */
++
++int arch_interrupt_init_early(void) {
++ return 0;
++}
++
++int request_irq(int irq, interrupt_handler_t *handler) {
++ return -1;
++}
++
++int release_irq(int irq) {
++ return -1;
++}
++
++#endif /* CONFIG_USE_IRQ */
++
++#endif /* __AST_G5_IRQ_H__ */
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index b492003..2472aa3 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -14,6 +14,8 @@
+ #include <asm/arch/ast-sdmc.h>
+ #include <asm/io.h>
+
++#include "ast-g5.h"
++
+ DECLARE_GLOBAL_DATA_PTR;
+
+ int board_early_init_f(void)
+@@ -22,6 +24,7 @@ int board_early_init_f(void)
+ ast_config_uart5_clk();
+ /*enable pass through*/
+ ast_enable_pass_through();
++ arch_interrupt_init_early();
+
+ return 0;
+ }
+diff --git a/board/aspeed/ast-g5/ast-g5.h b/board/aspeed/ast-g5/ast-g5.h
+new file mode 100644
+index 0000000..9fd10ec
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5.h
+@@ -0,0 +1,7 @@
++#ifndef _AST_G5_H_
++#define _AST_G5_H_
++
++#include <common.h>
++#include "ast-g5-irq.h"
++
++#endif /* _AST_G5_H_ */
+diff --git a/cmd/Kconfig b/cmd/Kconfig
+index d69b817..33be240 100644
+--- a/cmd/Kconfig
++++ b/cmd/Kconfig
+@@ -313,6 +313,11 @@ endmenu
+
+ menu "Device access commands"
+
++config CMD_IRQ
++ bool "interrupts - enable/disable interrupts"
++ depends on USE_IRQ
++ default y
++
+ config CMD_DM
+ bool "dm - Access to driver model information"
+ depends on DM
+diff --git a/configs/ast_g5_ncsi_2boot_defconfig b/configs/ast_g5_ncsi_2boot_defconfig
+index 2d28c86..d5b7894 100644
+--- a/configs/ast_g5_ncsi_2boot_defconfig
++++ b/configs/ast_g5_ncsi_2boot_defconfig
+@@ -33,3 +33,4 @@ CONFIG_CMD_CRC32=y
+ CONFIG_LOOPW=y
+ CONFIG_CMD_MEMTEST=y
+ CONFIG_CMD_MX_CYCLIC=y
++CONFIG_USE_IRQ=y
+diff --git a/configs/ast_g5_ncsi_defconfig b/configs/ast_g5_ncsi_defconfig
+index 74029ed..9481e5f 100644
+--- a/configs/ast_g5_ncsi_defconfig
++++ b/configs/ast_g5_ncsi_defconfig
+@@ -11,3 +11,4 @@ CONFIG_HUSH_PARSER=y
+ CONFIG_OF_LIBFDT=y
+ CONFIG_SPI_FLASH=y
+ CONFIG_SYS_NS16550=y
++CONFIG_USE_IRQ=y
+diff --git a/configs/ast_g5_phy_defconfig b/configs/ast_g5_phy_defconfig
+index 767f3af..4aefcf4 100644
+--- a/configs/ast_g5_phy_defconfig
++++ b/configs/ast_g5_phy_defconfig
+@@ -12,3 +12,4 @@ CONFIG_HUSH_PARSER=y
+ CONFIG_OF_LIBFDT=y
+ CONFIG_SPI_FLASH=y
+ CONFIG_SYS_NS16550=y
++CONFIG_USE_IRQ=y
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0007-Add-espi-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0007-Add-espi-support.patch
new file mode 100644
index 000000000..40336d3dd
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0007-Add-espi-support.patch
@@ -0,0 +1,347 @@
+From dff3a123b0318f83ecd753eea8945ebdc15fd2f9 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Wed, 14 Nov 2018 10:21:40 -0800
+Subject: [PATCH 1/1] Add espi support
+
+This adds basic eSPI support for U-Boot. The eSPI driver works best with
+interrupts because the timing of the initialization with the PCH is not
+trivial.
+
+The espi driver is currently just a bare-minimum driver allowing the
+host to boot. In the future it may be expanded to have further
+functions.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ arch/arm/include/asm/arch-aspeed/regs-scu.h | 2 +
+ board/aspeed/ast-g5/Makefile | 2 +
+ board/aspeed/ast-g5/ast-g5-espi.c | 248 ++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 16 ++
+ board/aspeed/ast-g5/ast-g5.c | 3 +
+ 5 files changed, 271 insertions(+)
+ create mode 100644 board/aspeed/ast-g5/ast-g5-espi.c
+ create mode 100644 board/aspeed/ast-g5/ast-g5-intel.c
+
+diff --git a/arch/arm/include/asm/arch-aspeed/regs-scu.h b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+index c9b91795d1..019c00036a 100644
+--- a/arch/arm/include/asm/arch-aspeed/regs-scu.h
++++ b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+@@ -554,6 +554,8 @@
+
+ #define CLK_25M_IN (0x1 << 23)
+
++#define SCU_HW_STRAP_FAST_RESET (1 << 27)
++#define SCU_HW_STRAP_ESPI_ENABLED (1 << 25)
+ #define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
+ #define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
+ #define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index df4e63966e..58e0c648f4 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -1,2 +1,4 @@
+ obj-y += ast-g5.o
++obj-y += ast-g5-intel.o
++obj-y += ast-g5-espi.o
+ obj-y += ast-g5-irq.o
+diff --git a/board/aspeed/ast-g5/ast-g5-espi.c b/board/aspeed/ast-g5/ast-g5-espi.c
+new file mode 100644
+index 0000000000..5a3ffe7bef
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-espi.c
+@@ -0,0 +1,248 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <asm/io.h>
++#include <asm/arch/regs-scu.h>
++#include <asm/arch/ast_scu.h>
++#include <asm/arch/aspeed.h>
++
++#include "ast-g5.h"
++
++#define DEBUG_ESPI_ENABLED 1
++#ifdef DEBUG_ESPI_ENABLED
++#define DBG_ESPI debug
++#else
++#define DBG_ESPI(...)
++#endif
++/* eSPI controller registers */
++#define ESPI000 0x000 /* Engine Control. */
++#define ESPI004 0x004 /* Engine Status. */
++#define ESPI008 0x008 /* Interrupt Status. */
++#define ESPI00C 0x00C /* Interrupt Enable. */
++#define ESPI010 0x010 /* DMA Addr of Peripheral Channel Posted Rx pkt */
++#define ESPI014 0x014 /* Control of Peripheral Channel Posted Rx pkt. */
++#define ESPI018 0x018 /* Data port of Peripheral Channel Posted Rx pkt. */
++#define ESPI020 0x020 /* DMA Addr of Peripheral Channel Posted Tx pkt. */
++#define ESPI024 0x024 /* Control of Peripheral Channel Posted Tx pkt. */
++#define ESPI028 0x028 /* Data port of Peripheral Channel Posted Tx pkt. */
++#define ESPI030 0x030 /* DMA Addr of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI034 0x034 /* Control of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI038 0x038 /* Data port of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI040 0x040 /* DMA Addr of OOB Channel Rx pkt. */
++#define ESPI044 0x044 /* Control of OOB Channel Rx pkt. */
++#define ESPI048 0x048 /* Data port of OOB Channel Rx pkt. */
++#define ESPI050 0x050 /* DMA Addr of OOB Channel Tx pkt. */
++#define ESPI054 0x054 /* Control of OOB Channel Tx pkt. */
++#define ESPI058 0x058 /* Data port of OOB Channel Tx pkt. */
++#define ESPI060 0x060 /* DMA Addr of Flash Channel Rx pkt. */
++#define ESPI064 0x064 /* Control of Flash Channel Rx pkt. */
++#define ESPI068 0x068 /* Data port of Flash Channel Rx pkt. */
++#define ESPI070 0x070 /* DMA Addr of Flash Channel Tx pkt. */
++#define ESPI074 0x074 /* Control of Flash Channel Tx pkt. */
++#define ESPI078 0x078 /* Data port of Flash Channel Tx pkt. */
++#define ESPI084 0x084 /* Mapping Src Addr of Peripheral Channel Rx pkt. */
++#define ESPI088 0x088 /* Mapping Tgt Addr of Peripheral Channel Rx pkt. */
++#define ESPI08C 0x08C /* Mapping Addr Mask of Peripheral Channel Rx pkt. */
++#define ESPI090 0x090 /* Mapping Target Addr and Mask of Flash Channel. */
++#define ESPI094 0x094 /* Interrupt enable of System Event from Master. */
++#define ESPI098 0x098 /* System Event from and to Master. */
++#define ESPI09C 0x09C /* GPIO through Virtual Wire Channel. */
++#define ESPI0A0 0x0A0 /* General Capabilities and Configurations. */
++#define ESPI0A4 0x0A4 /* Channel 0 Capabilities and Configurations. */
++#define ESPI0A8 0x0A8 /* Channel 1 Capabilities and Configurations. */
++#define ESPI0AC 0x0AC /* Channel 2 Capabilities and Configurations. */
++#define ESPI0B0 0x0B0 /* Channel 3 Capabilities and Configurations. */
++#define ESPI0B4 0x0B4 /* GPIO Direction of Virtual Wire Channel. */
++#define ESPI0B8 0x0B8 /* GPIO Selection of Virtual Wire Channel. */
++#define ESPI0BC 0x0BC /* GPIO Reset Selection of Virtual Wire Channel. */
++#define ESPI100 0x100 /* Interrupt enable of System Event 1 from Master. */
++#define ESPI104 0x104 /* System Event 1 from and to Master. */
++#define ESPI110 0x110 /* Interrupt type 0 of System Event from Master. */
++#define ESPI114 0x114 /* Interrupt type 1 of System Event from Master. */
++#define ESPI118 0x118 /* Interrupt type 2 of System Event from Master. */
++#define ESPI11C 0x11C /* Interrupt status of System Event from Master. */
++#define ESPI120 0x120 /* Interrupt type 0 of System Event 1 from Master. */
++#define ESPI124 0x124 /* Interrupt type 1 of System Event 1 from Master. */
++#define ESPI128 0x128 /* Interrupt type 2 of System Event 1 from Master. */
++#define ESPI12C 0x12C /* Interrupt status of System Event 1 from Master. */
++#define ESPICFG004 0x004 /* Device Identification. */
++#define ESPICFG008 0x008 /* General Capabilities and Configurations. */
++#define ESPICFG010 0x010 /* Channel 0 Capabilities and Configurations. */
++#define ESPICFG020 0x020 /* Channel 1 Capabilities and Configurations. */
++#define ESPICFG030 0x030 /* Channel 2 Capabilities and Configurations. */
++#define ESPICFG040 0x040 /* Channel 3 Capabilities and Configurations. */
++#define ESPICFG044 0x044 /* Channel 3 Capabilities and Configurations 2. */
++#define ESPICFG800 0x800 /* GPIO Direction of Virtual Wire Channel. */
++#define ESPICFG804 0x804 /* GPIO Selection of Virtual Wire Channel. */
++#define ESPICFG808 0x808 /* GPIO Reset Selection of Virtual Wire Channel. */
++#define ESPICFG810 0x810 /* Mapping Src Addr of Peripheral Channel Rx pkt */
++#define ESPICFG814 0x814 /* Mapping Tgt Addr of Peripheral Channel Rx pkt */
++#define ESPICFG818 0x818 /* Mapping Addr Mask of Peripheral Channel Rx pkt */
++
++/* ESPI000 bits */
++#define AST_ESPI_OOB_CHRDY (1 << 4)
++#define AST_ESPI_FLASH_SW_CHRDY (0x1 << 7)
++#define AST_ESPI_FLASH_SW_READ (0x1 << 10)
++#define ASPEED_ESPI_CTRL_SW_RESET GENMASK(31, 24)
++
++/* ESPI00C bits (Interrupt Enable) */
++#define AST_ESPI_IEN_SYS_EV (1 << 8)
++#define AST_ESPI_IEN_GPIO_EV (1 << 9)
++#define AST_ESPI_IEN_HW_RST (1 << 31)
++
++/* ESPI008 bits ISR */
++#define AST_ESPI_VW_SYS_EVT (1 << 8)
++#define AST_ESPI_VW_SYS_EV1 (1 << 22)
++
++/* ESPI098 and ESPI11C bits */
++#define AST_ESPI_OOB_RST_WARN (1 << 6)
++#define AST_ESPI_HOST_RST_WARN (1 << 8)
++#define AST_ESPI_OOB_RST_ACK (1 << 16)
++#define AST_ESPI_SL_BT_DONE (1 << 20)
++#define AST_ESPI_SL_BT_STATUS (1 << 23)
++#define AST_ESPI_HOST_RST_ACK (1 << 27)
++
++/* ESPI104 bits */
++#define AST_ESPI_SUS_WARN (1 << 0)
++#define AST_ESPI_SUS_ACK (1 << 20)
++
++/* LPC chip ID */
++#define SCR0SIO 0x170
++#define IRQ_SRC_ESPI 23 /* IRQ 23 */
++
++static void espi_handshake_ack(void)
++{
++ // IRQ only serviced if strapped, so no strap check
++ if (!(readl(AST_ESPI_BASE + ESPI098) & AST_ESPI_SL_BT_STATUS)) {
++ DBG_ESPI("Setting espi slave boot done\n");
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098)
++ | AST_ESPI_SL_BT_STATUS | AST_ESPI_SL_BT_DONE;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ }
++
++ if (readl(AST_ESPI_BASE + ESPI104) & AST_ESPI_SUS_WARN) {
++ DBG_ESPI("Boot SUS WARN set %08x\n",
++ readl(AST_ESPI_BASE + ESPI104));
++ uint32_t v = readl(AST_ESPI_BASE + ESPI104) | AST_ESPI_SUS_ACK;
++ writel(v, AST_ESPI_BASE + ESPI104);
++ }
++}
++
++static int espi_irq_handler(struct pt_regs *regs)
++{
++ uint32_t irq_status = readl(AST_ESPI_BASE + ESPI008);
++ DBG_ESPI("ISR irq_status : 0x%08X\n", irq_status);
++
++ if (irq_status & AST_ESPI_VW_SYS_EV1) {
++ uint32_t sys1_status = readl(AST_ESPI_BASE + ESPI12C);
++ uint32_t sys1_event = readl(AST_ESPI_BASE + ESPI104);
++
++ DBG_ESPI("sys1_status : 0x%08X\n", sys1_status);
++ if (sys1_status & AST_ESPI_SUS_WARN) {
++ DBG_ESPI("SUS WARN ev: %08X\n", sys1_event);
++ if (sys1_event & AST_ESPI_SUS_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI104)
++ | AST_ESPI_SUS_ACK;
++ writel(v, AST_ESPI_BASE + ESPI104);
++ }
++ }
++ writel(sys1_status, AST_ESPI_BASE + ESPI12C); // clear status
++ }
++
++ if (irq_status & AST_ESPI_VW_SYS_EVT) {
++ uint32_t sys_status = readl(AST_ESPI_BASE + ESPI11C);
++ uint32_t sys_event = readl(AST_ESPI_BASE + ESPI098);
++
++ if (!(sys_event & AST_ESPI_SL_BT_STATUS)) {
++ DBG_ESPI("Setting espi slave boot done\n");
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098)
++ | AST_ESPI_SL_BT_STATUS | AST_ESPI_SL_BT_DONE;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ }
++
++ DBG_ESPI("sys_status : 0x%08X\n", sys_status);
++ if (sys_status & AST_ESPI_HOST_RST_WARN) {
++ DBG_ESPI("HOST_RST_WARN ev: %08X\n", sys_event);
++ if (sys_event & AST_ESPI_HOST_RST_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098)
++ | AST_ESPI_HOST_RST_ACK;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ }
++ }
++ if (sys_status & AST_ESPI_OOB_RST_WARN) {
++ DBG_ESPI("OOB_RST_WARN ev: %08X\n", sys_event);
++ if (sys_event & AST_ESPI_OOB_RST_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098)
++ | AST_ESPI_OOB_RST_ACK;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ }
++ }
++ writel(sys_status, AST_ESPI_BASE + ESPI11C); // clear status
++ }
++
++ if (irq_status & AST_ESPI_IEN_HW_RST) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI000);
++ writel(v & ~ASPEED_ESPI_CTRL_SW_RESET, AST_ESPI_BASE + ESPI000);
++ writel(v | ASPEED_ESPI_CTRL_SW_RESET, AST_ESPI_BASE + ESPI000);
++ espi_handshake_ack();
++ }
++
++ writel(irq_status, AST_ESPI_BASE + ESPI008); // clear irq_status
++ return 0;
++}
++
++void espi_init(void)
++{
++ if (readl(AST_SCU_BASE + AST_SCU_HW_STRAP1)
++ & SCU_HW_STRAP_ESPI_ENABLED) {
++ uint32_t v;
++ DBG_ESPI("espi_init\n");
++
++ /* Block flash access from Host */
++ v = readl(AST_ESPI_BASE + ESPI000) & ~AST_ESPI_FLASH_SW_CHRDY;
++ v |= AST_ESPI_FLASH_SW_READ;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ /* Set SIO register 0x28 to 0xa8 as a faked ASPEED ChipID for
++ * BIOS using in eSPI mode */
++ v = readl(AST_LPC_BASE + SCR0SIO) & ~0x000000ff;
++ writel(v, AST_LPC_BASE + SCR0SIO);
++ v = readl(AST_LPC_BASE + SCR0SIO) | 0xa8;
++ writel(v, AST_LPC_BASE + SCR0SIO);
++
++ v = readl(AST_ESPI_BASE + ESPI000) | AST_ESPI_OOB_CHRDY;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ writel(0, AST_ESPI_BASE + ESPI110);
++ writel(0, AST_ESPI_BASE + ESPI114);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN,
++ AST_ESPI_BASE + ESPI118);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN,
++ AST_ESPI_BASE + ESPI094);
++
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE + ESPI120); // int type 0 susp warn
++ writel(0, AST_ESPI_BASE + ESPI124);
++ writel(0, AST_ESPI_BASE + ESPI128);
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE
++ + ESPI100); // Enable sysev1 ints for susp warn
++
++ writel(AST_ESPI_IEN_SYS_EV | AST_ESPI_IEN_HW_RST
++ | AST_ESPI_VW_SYS_EV1,
++ AST_ESPI_BASE + ESPI00C); // Enable events
++
++ espi_handshake_ack();
++
++ request_irq(IRQ_SRC_ESPI, espi_irq_handler);
++ } else {
++ DBG_ESPI("No espi strap\n");
++ }
++}
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+new file mode 100644
+index 0000000000..e79235c8d0
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -0,0 +1,16 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++
++extern void espi_init(void);
++void ast_g5_intel(void)
++{
++ espi_init();
++}
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index ca25348178..cab5fabcef 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -21,6 +21,8 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
++extern void ast_g5_intel(void);
++
+ int board_early_init_f(void)
+ {
+ /* make sure uart5 is using 24MHz clock */
+@@ -84,6 +86,7 @@ int board_init(void)
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+ gd->flags = 0;
+
++ ast_g5_intel();
+ return 0;
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch
new file mode 100644
index 000000000..5fa4bffa1
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch
@@ -0,0 +1,158 @@
+From 40e02e4ffa13c0128db555a3a3982a7cdc0ebf60 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Wed, 14 Nov 2018 12:09:52 -0800
+Subject: [PATCH] add sgio support for port80 snoop post LEDs
+
+This ties together the port 80 snooping to the SGPIO output that
+ultimately drives the POST code LEDs.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Change-Id: Iaa1b91cd40f4b6323dba0598da373cb631459e66
+
+---
+ arch/arm/include/asm/arch-aspeed/ast_scu.h | 1 +
+ arch/arm/mach-aspeed/ast-scu.c | 8 +++
+ board/aspeed/ast-g5/ast-g5-intel.c | 96 ++++++++++++++++++++++++++++++
+ 3 files changed, 105 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+index 06825ce..369c4e3 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast_scu.h
++++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+@@ -45,6 +45,7 @@ extern u32 ast_scu_get_vga_memsize(void);
+ extern void ast_scu_init_eth(u8 num);
+ extern void ast_scu_multi_func_eth(u8 num);
+ extern void ast_scu_multi_func_romcs(u8 num);
++extern void ast_scu_multi_func_sgpio(void);
+
+ void ast_config_uart5_clk(void);
+
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index d27f3d3..3a9ba05 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -449,6 +449,14 @@ void ast_scu_multi_func_romcs(u8 num)
+ SCU_FUN_PIN_ROMCS(num), AST_SCU_FUN_PIN_CTRL3);
+ }
+
++void ast_scu_multi_func_sgpio(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
++ SCU_FUN_PIN_SGPMI | SCU_FUN_PIN_SGPMO |
++ SCU_FUN_PIN_SGPMLD | SCU_FUN_PIN_SGPMCK,
++ AST_SCU_FUN_PIN_CTRL2);
++}
++
+ u32 ast_scu_revision_id(void)
+ {
+ int i;
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index e79235c..c2a8b33 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -8,9 +8,105 @@
+ */
+
+ #include <common.h>
++#include <asm/io.h>
++#include <asm/arch/regs-scu.h>
++#include <asm/arch/ast_scu.h>
++#include <asm/arch/aspeed.h>
++
++#include "ast-g5.h"
++
++#define LPC_SNOOP_ADDR 0x80
++#define HICR5 0x080 /* Host Interface Control Register 5 */
++#define HICR6 0x084 /* Host Interface Control Register 6 */
++#define HICR7 0x088 /* Host Interface Control Register 7 */
++#define HICR8 0x08c /* Host Interface Control Register 8 */
++#define SNPWADR 0x090 /* LPC Snoop Address Register */
++#define SNPWDR 0x094 /* LPC Snoop Data Register */
++#define HICR9 0x098 /* Host Interface Control Register 9 */
++#define HICRA 0x09c /* Host Interface Control Register A */
++#define LHCR0 0x0a0 /* LPC Host Control Register 0 */
++#define LHCR1 0x0a4 /* LPC Host Control Register 1 */
++#define LHCR2 0x0a8 /* LPC Host Control Register 2 */
++#define LHCR3 0x0ac /* LPC Host Control Register 3 */
++#define LHCR4 0x0b0 /* LPC Host Control Register 4 */
++#define LHCR5 0x0b4 /* LPC Host Control Register 5 */
++#define LHCR6 0x0b8 /* LPC Host Control Register 6 */
++#define LHCR7 0x0bc /* LPC Host Control Register 7 */
++#define LHCR8 0x0c0 /* LPC Host Control Register 8 */
++#define PCCR6 0x0c4 /* Post Code Control Register 6 */
++#define LHCRA 0x0c8 /* LPC Host Control Register A */
++#define LHCRB 0x0cc /* LPC Host Control Register B */
++#define PCCR4 0x0d0 /* Post Code Control Register 4 */
++#define PCCR5 0x0d4 /* Post Code Control Register 5 */
++#define HICRB 0x100 /* Host Interface Control Register B */
++#define HICRC 0x104 /* Host Interface Control Register C */
++/* HICR5 Bits */
++#define HICR5_EN_SIOGIO (1 << 31) /* Enable SIOGIO */
++#define HICR5_EN80HGIO (1 << 30) /* Enable 80hGIO */
++#define HICR5_SEL80HGIO (0x1f << 24) /* Select 80hGIO */
++#define SET_SEL80HGIO(x) ((x & 0x1f) << 24) /* Select 80hGIO Offset */
++#define HICR5_UNKVAL_MASK 0x1FFF0000 /* Bits with unknown values on reset */
++#define HICR5_ENINT_SNP0W (1 << 1) /* Enable Snooping address 0 */
++#define HICR5_EN_SNP0W (1 << 0) /* Enable Snooping address 0 */
++
++/* HRCR6 Bits */
++#define HICR6_STR_SNP0W (1 << 0) /* Interrupt Status Snoop address 0 */
++#define HICR6_STR_SNP1W (1 << 1) /* Interrupt Status Snoop address 1 */
++
++/* HICRB Bits */
++#define HICRB_EN80HSGIO (1 << 13) /* Enable 80hSGIO */
++
++#define SGPIO_CLK_DIV(N) ((N) << 16)
++#define SGPIO_BYTES(N) ((N) << 6)
++#define SGPIO_ENABLE 1
++#define GPIO254 0x254
++
++static void sgpio_init(void)
++{
++ uint32_t value;
++ /*
++ 33.4.2
++ LPC port80h direct to SGPIO
++ In AST2500 SGPIO, it supports output data from 80h. It always uses SGPIOA.
++ 1. Configure LPC snoop function.
++ (a) Set SNPWADR(0x1e789090)[15:0] to 0x80.
++ (b) Set HICR5(0x1e789080)[0] to 1 to enable snoop.
++ 2. Configure SGPIO
++ (a) Set GPIO254[9:6] to larger than or equal to 0x1.
++ (b) Set GPIO254[0] to 1 to enable SGPIO.
++ 3. Set SuperIO
++ (a) Set SIOR7 30h to 0x40.
++ */
++ /* make sure multi-pin stuff goes in our favor */
++ ast_scu_multi_func_sgpio();
++
++ /* set lpc snoop #0 to port 0x80 */
++ value = readl(AST_LPC_BASE + SNPWADR) & 0xffff0000;
++ writel(value | LPC_SNOOP_ADDR, AST_LPC_BASE + SNPWADR);
++
++ /* clear interrupt status */
++ value = readl(AST_LPC_BASE + HICR6);
++ value |= HICR6_STR_SNP0W | HICR6_STR_SNP1W;
++ writel(value, AST_LPC_BASE + HICR6);
++
++ /* enable lpc snoop #0 and SIOGIO */
++ value = readl(AST_LPC_BASE + HICR5) & ~(HICR5_UNKVAL_MASK);
++ value |= HICR5_EN_SIOGIO | HICR5_EN_SNP0W;
++ writel(value, AST_LPC_BASE + HICR5);
++
++
++ /* enable port80h snoop on SGPIO */
++ value = readl(AST_LPC_BASE + HICRB) | HICRB_EN80HSGIO;
++ writel(value, AST_LPC_BASE + HICRB);
++
++ /* set the gpio clock to pclk/(2*(5+1)) or ~2 MHz */
++ value = SGPIO_CLK_DIV(256) | SGPIO_BYTES(10) | SGPIO_ENABLE;
++ writel(value, AST_GPIO_BASE + GPIO254);
++}
+
+ extern void espi_init(void);
+ void ast_g5_intel(void)
+ {
+ espi_init();
++ sgpio_init();
+ }
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch
new file mode 100644
index 000000000..e11f15870
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch
@@ -0,0 +1,427 @@
+From 15d04184a94aca6db889d77c2cc5a800b280da4b Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri, 16 Nov 2018 09:58:01 -0800
+Subject: [PATCH 01/30] Add basic GPIO support
+
+Add a table of well-known gpios (such as FP LEDs and FF UPD jumper) and
+initialize them at boot.
+
+Add a mechanism to get/set well known gpios from command line.
+
+Change-Id: I4136a5ccb048b3604f13b17ea0c18a4bc596c249
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+%% original patch: 0009-Add-basic-GPIO-support.patch
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-gpio.c | 202 +++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-gpio.h | 103 +++++++++++++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 45 +++++++
+ board/aspeed/ast-g5/ast-g5.h | 1 +
+ 5 files changed, 352 insertions(+)
+ create mode 100644 board/aspeed/ast-g5/ast-g5-gpio.c
+ create mode 100644 board/aspeed/ast-g5/ast-g5-gpio.h
+
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index 58e0c648f4..2970ae5741 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -2,3 +2,4 @@ obj-y += ast-g5.o
+ obj-y += ast-g5-intel.o
+ obj-y += ast-g5-espi.o
+ obj-y += ast-g5-irq.o
++obj-y += ast-g5-gpio.o
+diff --git a/board/aspeed/ast-g5/ast-g5-gpio.c b/board/aspeed/ast-g5/ast-g5-gpio.c
+new file mode 100644
+index 0000000000..dc6962f4ba
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-gpio.c
+@@ -0,0 +1,202 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <asm/io.h>
++#include <asm/arch/regs-scu.h>
++#include <asm/arch/ast_scu.h>
++#include <asm/arch/aspeed.h>
++
++#include "ast-g5.h"
++#include "ast-g5-gpio.h"
++
++typedef struct _gpio_bases {
++ uint32_t u32ddr; /* data and direction registers */
++ uint32_t u32intcfg; /* interrupt config */
++ uint32_t u32debounce; /* debounce config */
++ uint32_t u32cmdsrc; /* command source config */
++} sGPIO_BASES;
++
++static const sGPIO_BASES GPIO_BASES[] = {
++ /* ABCD */
++ {AST_GPIO_BASE + 0x0000, AST_GPIO_BASE + 0x0008,
++ AST_GPIO_BASE + 0x0040, AST_GPIO_BASE + 0x0060},
++ /* EFGH */
++ {AST_GPIO_BASE + 0x0020, AST_GPIO_BASE + 0x0028,
++ AST_GPIO_BASE + 0x0048, AST_GPIO_BASE + 0x0068},
++ /* IJKL */
++ {AST_GPIO_BASE + 0x0070, AST_GPIO_BASE + 0x0098,
++ AST_GPIO_BASE + 0x00b0, AST_GPIO_BASE + 0x0090},
++ /* MNOP */
++ {AST_GPIO_BASE + 0x0078, AST_GPIO_BASE + 0x00e8,
++ AST_GPIO_BASE + 0x0100, AST_GPIO_BASE + 0x00e0},
++ /* QRST */
++ {AST_GPIO_BASE + 0x0080, AST_GPIO_BASE + 0x0118,
++ AST_GPIO_BASE + 0x0130, AST_GPIO_BASE + 0x0110},
++ /* UVWX */
++ {AST_GPIO_BASE + 0x0088, AST_GPIO_BASE + 0x0148,
++ AST_GPIO_BASE + 0x0160, AST_GPIO_BASE + 0x0140},
++ /* YZAB */
++ {AST_GPIO_BASE + 0x01e0, AST_GPIO_BASE + 0x0178,
++ AST_GPIO_BASE + 0x0190, AST_GPIO_BASE + 0x0170},
++ /* AC__ */
++ {AST_GPIO_BASE + 0x01e8, AST_GPIO_BASE + 0x01a8,
++ AST_GPIO_BASE + 0x01c0, AST_GPIO_BASE + 0x01a0},
++};
++
++static size_t gpio_max = 0;
++static const GPIOValue * gpio_table = NULL;
++
++void gpio_set_value(int n, int asserted)
++{
++ uint8_t port;
++ uint8_t pin;
++ uint32_t base;
++ uint8_t shift;
++ uint8_t assert;
++ uint32_t gpio_value;
++
++ if (n >= gpio_max || !gpio_table) {
++ return;
++ }
++ port = GPIO_PORT(gpio_table[n].u8PortPin);
++ assert = GPIO_ASSERT(gpio_table[n].u8PinCFG);
++ pin = GPIO_PIN(gpio_table[n].u8PortPin);
++ base = GPIO_BASES[GPIO_GROUP(port)].u32ddr;
++ shift = GPIO_SHIFT(port, pin);
++
++ gpio_value = readl(base + GPIO_DATA_VALUE);
++ if ((assert && asserted) || !(assert || asserted)) {
++ // set the bit
++ gpio_value |= (1 << shift);
++ } else {
++ // clear the bit
++ gpio_value &= ~(1 << shift);
++ }
++ writel(gpio_value, base + GPIO_DATA_VALUE);
++}
++
++int gpio_get_value(int n)
++{
++ uint8_t port;
++ uint8_t pin;
++ uint32_t base;
++ uint8_t shift;
++ uint8_t assert;
++ uint32_t gpio_value;
++
++ if (n >= gpio_max || !gpio_table) {
++ return -1;
++ }
++ port = GPIO_PORT(gpio_table[n].u8PortPin);
++ assert = GPIO_ASSERT(gpio_table[n].u8PinCFG);
++ pin = GPIO_PIN(gpio_table[n].u8PortPin);
++ base = GPIO_BASES[GPIO_GROUP(port)].u32ddr;
++ shift = GPIO_SHIFT(port, pin);
++
++ gpio_value = readl(base + GPIO_DATA_VALUE);
++ gpio_value >>= shift;
++ gpio_value &= 1;
++ // the output here is the logical output, which is
++ // NOT (value XOR assert)
++ // This just gets there without a conditional
++ gpio_value ^= assert;
++ return !gpio_value;
++}
++
++void gpio_init(const GPIOValue* table, size_t count)
++{
++ uint32_t pclk, value;
++ int i;
++
++ gpio_table = table;
++ gpio_max = count;
++ /* set up the debounce timers (in units of PCLK cycles) */
++ pclk = ast_get_ahbclk();
++ /* GPIO_DEBOUNCE_120us */
++ writel((pclk / 1000000) * 120, AST_GPIO_BASE + GPIO_DEBOUNCE_TIMER_0);
++ /* GPIO_DEBOUNCE_8ms */
++ writel((pclk / 1000000) * 8000, AST_GPIO_BASE + GPIO_DEBOUNCE_TIMER_1);
++ /* GPIO_DEBOUNCE_16ms */
++ writel((pclk / 1000000) * 16000, AST_GPIO_BASE + GPIO_DEBOUNCE_TIMER_2);
++
++ for (i = 0; i < gpio_max; i++) {
++ uint8_t port;
++ uint8_t pin;
++ uint32_t base;
++ uint8_t shift;
++ uint8_t assert;
++ uint8_t init_val;
++
++ port = GPIO_PORT(gpio_table[i].u8PortPin);
++ pin = GPIO_PIN(gpio_table[i].u8PortPin);
++ base = GPIO_BASES[GPIO_GROUP(port)].u32ddr;
++ shift = GPIO_SHIFT(port, pin);
++
++ /* set direction */
++ value = readl(base + GPIO_DIRECTION);
++ if (gpio_table[i].u8PinCFG & GPCFG_OUTPUT_EN)
++ value |= (1 << shift);
++ else
++ value &= ~(1 << shift);
++ writel(value, base + GPIO_DIRECTION);
++
++ /* set data value */
++ value = readl(base + GPIO_DATA_VALUE);
++ assert = GPIO_ASSERT(gpio_table[i].u8PinCFG);
++ init_val = gpio_table[i].u8Value;
++ if ((assert && init_val) || !(assert || init_val))
++ value |= (1 << shift);
++ else
++ value &= ~(1 << shift);
++ writel(value, base + GPIO_DATA_VALUE);
++
++ /* set debounce */
++ base = GPIO_BASES[GPIO_GROUP(port)].u32debounce;
++ value = readl(base + GPIO_DEBOUNCE_SEL_0);
++ if (gpio_table[i].u8Debounce & 0x01)
++ value |= (1 << shift);
++ else
++ value &= ~(1 << shift);
++ writel(value, base + GPIO_DEBOUNCE_SEL_0);
++ value = readl(base + GPIO_DEBOUNCE_SEL_1);
++ if (gpio_table[i].u8Debounce & 0x02)
++ value |= (1 << shift);
++ else
++ value &= ~(1 << shift);
++ writel(value, base + GPIO_DEBOUNCE_SEL_1);
++ }
++}
++
++int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
++{
++ int n;
++ if (argc < 3) {
++ return 1;
++ }
++ n = simple_strtoul(argv[2], NULL, 0);
++ if (argv[1][0] == 'g') {
++ printf("%d\n", gpio_get_value(n));
++ return 0;
++ }
++ if (argc < 4) {
++ return 1;
++ }
++ if (argv[1][0] == 's') {
++ int value;
++ value = simple_strtoul(argv[3], NULL, 0);
++ gpio_set_value(n, value);
++ return 0;
++ }
++
++ return 1;
++}
++U_BOOT_CMD(gpio, 4, 0, do_gpio,
++ "do stuff with gpios <set|get> [n] [value]",
++ "");
+diff --git a/board/aspeed/ast-g5/ast-g5-gpio.h b/board/aspeed/ast-g5/ast-g5-gpio.h
+new file mode 100644
+index 0000000000..54b7388a22
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-gpio.h
+@@ -0,0 +1,103 @@
++#ifndef __HW_GPIO_H__
++#define __HW_GPIO_H__
++
++#define GPIO_PORT_A 0
++#define GPIO_PORT_B 1
++#define GPIO_PORT_C 2
++#define GPIO_PORT_D 3
++#define GPIO_PORT_E 4
++#define GPIO_PORT_F 5
++#define GPIO_PORT_G 6
++#define GPIO_PORT_H 7
++#define GPIO_PORT_I 8
++#define GPIO_PORT_J 9
++#define GPIO_PORT_K 10
++#define GPIO_PORT_L 11
++#define GPIO_PORT_M 12
++#define GPIO_PORT_N 13
++#define GPIO_PORT_O 14
++#define GPIO_PORT_P 15
++#define GPIO_PORT_Q 16
++#define GPIO_PORT_R 17
++#define GPIO_PORT_S 18
++#define GPIO_PORT_T 19
++#define GPIO_PORT_U 20
++#define GPIO_PORT_V 21
++#define GPIO_PORT_W 22
++#define GPIO_PORT_X 23
++#define GPIO_PORT_Y 24
++#define GPIO_PORT_Z 25
++#define GPIO_PORT_AA 26
++#define GPIO_PORT_AB 27
++#define GPIO_PORT_AC 28
++
++#define GPIO_PIN_0 0
++#define GPIO_PIN_1 1
++#define GPIO_PIN_2 2
++#define GPIO_PIN_3 3
++#define GPIO_PIN_4 4
++#define GPIO_PIN_5 5
++#define GPIO_PIN_6 6
++#define GPIO_PIN_7 7
++
++#define GPIO_DEBOUNCE_TIMER_0 0x50
++#define GPIO_DEBOUNCE_TIMER_1 0x54
++#define GPIO_DEBOUNCE_TIMER_2 0x58
++
++/* relative to u32ddr base */
++#define GPIO_DATA_VALUE 0x00
++#define GPIO_DIRECTION 0x04
++/* relative to u32intcfg base */
++#define GPIO_INT_ENABLE 0x00
++#define GPIO_INT_SENSE0 0x04
++#define GPIO_INT_SENSE1 0x18
++#define GPIO_INT_SENSE2 0x1c
++#define GPIO_INT_STATUS 0x20
++#define GPIO_RESET_TOL 0x24
++/* relative to u32debounce base */
++#define GPIO_DEBOUNCE_SEL_0 0
++#define GPIO_DEBOUNCE_SEL_1 4
++/* relative to u32cmdsrc base */
++#define GPIO_CMD_SRC_0 0
++#define GPIO_CMD_SRC_1 4
++
++#define PORT_PIN(PORT, PIN) (((PORT) << 3) | ((PIN)&0x07))
++#define GPIO_PIN(N) (N & 0x07)
++#define GPIO_PORT(N) (N >> 3)
++#define GPIO_SHIFT(PORT, PIN) ((PIN) + (((PORT) % 4) * 8))
++#define GPIO_GROUP(PORT) ((PORT) / 4)
++#define GPIO_ASSERT(N) (((N) >> 4) & 0x01)
++
++#define ID_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_6)
++#define GRN_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_4)
++#define AMB_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_5)
++#define FORCE_BMC_UPDATE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_0)
++#define TPM_EN_PULSE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_6)
++
++
++// GPIO Configuration Register bits
++#define GPCFG_EVENT_TO_SMI (1 << 7) // 1 == enabled
++#define GPCFG_EVENT_TO_IRQ (1 << 6) // 1 == enabled
++#define GPCFG_DEBOUNCE_EN (1 << 5) // 1 == input debounce, 0 == pulse output
++#define GPCFG_ACTIVE_HIGH (1 << 4) // 1 == Active high
++#define GPCFG_LEVEL_TRIG (1 << 3) // 1 == level (default), 0 == edge
++#define GPCFG_OUTPUT_EN (1 << 0) // 1 == Output enabled
++
++// GPIO Debounce and Blink Configuration Register bits
++#define GPIO_DEBOUNCE_NONE 0x00
++#define GPIO_DEBOUNCE_60US 0x01
++#define GPIO_DEBOUNCE_8MS 0x02
++#define GPIO_DEBOUNCE_16MS 0x03
++
++typedef struct {
++ uint8_t u8PortPin;
++ uint8_t u8PinCFG;
++ uint8_t u8Value;
++ uint8_t u8Debounce;
++} GPIOValue;
++
++void gpio_init(const GPIOValue* table, size_t count);
++void gpio_set_value(int n, int asserted);
++int gpio_get_value(int n);
++
++#endif /* __HW_GPIO_H__ */
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index c2a8b33aec..1868c230eb 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -14,6 +14,50 @@
+ #include <asm/arch/aspeed.h>
+
+ #include "ast-g5.h"
++#include "ast-g5-gpio.h"
++
++/* Names to match the GPIOs */
++enum gpio_names {
++ GPIO_ID_LED = 0,
++ GPIO_GREEN_LED,
++ GPIO_AMBER_LED,
++ GPIO_FF_UPD_JUMPER,
++ GPIO_ENABLE_TPM_PULSE,
++};
++
++#define GPIO_CFG_DEFAULT (GPCFG_ACTIVE_HIGH | GPCFG_LEVEL_TRIG)
++// Active High, Level, Output Disabled
++
++#define GPIO_CFG_LOW_INPUT (GPCFG_LEVEL_TRIG)
++// Active Low, Level, Output Disabled
++
++#define GPIO_CFG_FP_LED (GPCFG_OUTPUT_EN)
++// Active High, Pull-up, Level, Output Enabled
++
++// Format is:
++// GPIO PORT, GPIO PIN Number, GPIO PIN Configuration, GPIO PIN Value, GPIO
++// Debounce/Blink Setting
++static const GPIOValue gpio_table[] = {
++ /* ID LED pin S6 - low asserted, 0=on */
++ [GPIO_ID_LED] = {ID_LED_PORT_PIN, GPIO_CFG_FP_LED, 0,
++ GPIO_DEBOUNCE_NONE},
++
++ /* Green LED pin S4 - high asserted, 0=off */
++ [GPIO_GREEN_LED] = {GRN_LED_PORT_PIN, GPIO_CFG_FP_LED, 1,
++ GPIO_DEBOUNCE_NONE},
++
++ /* Amber LED pin S5 - high asserted, 0=off */
++ [GPIO_AMBER_LED] = {AMB_LED_PORT_PIN, GPIO_CFG_FP_LED, 1,
++ GPIO_DEBOUNCE_NONE},
++
++ /* Force Update Jumper -- pin D0 */
++ [GPIO_FF_UPD_JUMPER] = {FORCE_BMC_UPDATE_PORT_PIN, GPIO_CFG_LOW_INPUT, 0,
++ GPIO_DEBOUNCE_8MS},
++
++ /* Enable Pulse -- pin D6 */
++ [GPIO_ENABLE_TPM_PULSE] = {PORT_PIN(GPIO_PORT_D, GPIO_PIN_6),
++ GPIO_CFG_DEFAULT, 0, GPIO_DEBOUNCE_8MS},
++};
+
+ #define LPC_SNOOP_ADDR 0x80
+ #define HICR5 0x080 /* Host Interface Control Register 5 */
+@@ -107,6 +151,7 @@ static void sgpio_init(void)
+ extern void espi_init(void);
+ void ast_g5_intel(void)
+ {
++ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+ espi_init();
+ sgpio_init();
+ }
+diff --git a/board/aspeed/ast-g5/ast-g5.h b/board/aspeed/ast-g5/ast-g5.h
+index 9fd10eccb3..908db1477b 100644
+--- a/board/aspeed/ast-g5/ast-g5.h
++++ b/board/aspeed/ast-g5/ast-g5.h
+@@ -3,5 +3,6 @@
+
+ #include <common.h>
+ #include "ast-g5-irq.h"
++#include "ast-g5-gpio.h"
+
+ #endif /* _AST_G5_H_ */
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch
new file mode 100644
index 000000000..c6ee49f57
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch
@@ -0,0 +1,96 @@
+From d08d22af794eed7b928ab96030a103cfb7bf6ce1 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri, 16 Nov 2018 14:59:04 -0800
+Subject: [PATCH] Update Force Firmware Update Jumper to use new gpio API
+
+Add a function that allows easy reading of the FFUJ from other
+functions, such as autoboot.
+
+Change-Id: I8ead931e9dd828522095a0ef386875be652ec885
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+---
+ arch/arm/include/asm/arch-aspeed/ast-g5-intel.h | 19 +++++++++++++++++++
+ arch/arm/include/asm/arch-aspeed/platform.h | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 5 +++++
+ common/autoboot.c | 6 ++++++
+ 4 files changed, 31 insertions(+)
+ create mode 100644 arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+new file mode 100644
+index 0000000..cd9a099
+--- /dev/null
++++ b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+@@ -0,0 +1,19 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef __AST_INTEL_G5_H__
++#define __AST_INTEL_G5_H__
++
++#define AST_G5_INTEL 1
++
++#ifndef __ASSEMBLY__
++int intel_force_firmware_jumper_enabled(void);
++#endif
++
++#endif /* __AST_INTEL_G5_H__ */
+diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h
+index 92ea33b..3b06e52 100644
+--- a/arch/arm/include/asm/arch-aspeed/platform.h
++++ b/arch/arm/include/asm/arch-aspeed/platform.h
+@@ -27,6 +27,7 @@
+ #include <asm/arch/ast2400_platform.h>
+ #elif defined(AST_SOC_G5)
+ #include <asm/arch/ast_g5_platform.h>
++#include <asm/arch/ast-g5-intel.h>
+ #define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */
+ #else
+ #err "No define for platform.h"
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 069e7a3..144765a 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -145,6 +145,11 @@ static void sgpio_init(void)
+ writel(value, AST_GPIO_BASE + GPIO254);
+ }
+
++int intel_force_firmware_jumper_enabled(void)
++{
++ return gpio_get_value(GPIO_FF_UPD_JUMPER);
++}
++
+ extern void espi_init(void);
+ void ast_g5_intel(void)
+ {
+diff --git a/common/autoboot.c b/common/autoboot.c
+index c52bad8..d66c0fa 100644
+--- a/common/autoboot.c
++++ b/common/autoboot.c
+@@ -14,6 +14,7 @@
+ #include <menu.h>
+ #include <post.h>
+ #include <u-boot/sha256.h>
++#include <asm/arch/platform.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+@@ -259,6 +260,11 @@ static int abortboot(int bootdelay)
+ {
+ int abort = 0;
+
++# ifdef AST_G5_INTEL
++ if (intel_force_firmware_jumper_enabled())
++ return 1;
++# endif
++
+ if (bootdelay >= 0)
+ abort = __abortboot(bootdelay);
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch
new file mode 100644
index 000000000..26b4c4fc9
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch
@@ -0,0 +1,158 @@
+From 320cf189fd017e3578b6949ff640213d7bddb20c Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri, 16 Nov 2018 14:44:49 -0800
+Subject: [PATCH] Add basic timer support for Aspeed g5 in U-Boot
+
+Timers will be used for timing events and making blinky LEDs. This just
+adds the API and infrastructure.
+
+Change-Id: I8ff03b26070b43a47fb970ddf6124d6c3f29b058
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 1 +
+ board/aspeed/ast-g5/ast-g5-timer.c | 66 ++++++++++++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-timer.h | 27 ++++++++++++++++
+ board/aspeed/ast-g5/ast-g5.h | 1 +
+ 5 files changed, 96 insertions(+)
+ create mode 100644 board/aspeed/ast-g5/ast-g5-timer.c
+ create mode 100644 board/aspeed/ast-g5/ast-g5-timer.h
+
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index 2970ae5..9022433 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -3,3 +3,4 @@ obj-y += ast-g5-intel.o
+ obj-y += ast-g5-espi.o
+ obj-y += ast-g5-irq.o
+ obj-y += ast-g5-gpio.o
++obj-y += ast-g5-timer.o
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 144765a..6e45cb4 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -15,6 +15,7 @@
+
+ #include "ast-g5.h"
+ #include "ast-g5-gpio.h"
++#include "ast-g5-timer.h"
+
+ /* Names to match the GPIOs */
+ enum gpio_names {
+diff --git a/board/aspeed/ast-g5/ast-g5-timer.c b/board/aspeed/ast-g5/ast-g5-timer.c
+new file mode 100644
+index 0000000..5615722
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-timer.c
+@@ -0,0 +1,66 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <asm/io.h>
++#include <asm/arch/regs-scu.h>
++#include <asm/arch/ast_scu.h>
++#include <asm/arch/aspeed.h>
++
++#include "ast-g5.h"
++#include "ast-g5-timer.h"
++#include "ast-g5-irq.h"
++
++static const int timer_irqs[] = {16, 17, 18, 35, 37, 37, 38, 39};
++/* offsets from AST_TIMER_BASE for each timer */
++static const uint32_t timer_bases[] = {0, 0x10, 0x20, 0x40,
++ 0x50, 0x60, 0x70, 0x80};
++#define TIMER_1MHZ_CLK_COUNT 1000000u
++#define TIMER_ENABLE 1
++#define TIMER_1MHZ_CLK_SEL 2
++#define TIMER_ENABLE_IRQ 4
++#define TIMER_ENABLE_PULSE 8
++#define TIMER_CONTROL 0x30
++#define TIMER_RELOAD 0x04
++
++void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler)
++{
++ if (n < 0 || n > 7) {
++ return;
++ }
++ uint32_t tctrl = readl(AST_TIMER_BASE + TIMER_CONTROL);
++ writel(tctrl & ~(0x0f << (n * 4)), AST_TIMER_BASE + TIMER_CONTROL);
++
++ // figure out best base for requested frequency
++ // (this will give 1MHz clock preference if period is within 1ms of
++ // requested)
++ uint32_t v = TIMER_1MHZ_CLK_COUNT / freq;
++ if (v > 1000 || v * freq == TIMER_1MHZ_CLK_COUNT) {
++ tctrl |= (TIMER_1MHZ_CLK_SEL << (n * 4));
++ } else {
++ uint32_t pclk = ast_get_ahbclk();
++ v = pclk / freq;
++ }
++ writel(v, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
++ if (handler) {
++ request_irq(timer_irqs[n], handler);
++ tctrl |= (TIMER_ENABLE_IRQ << (n * 4));
++ }
++ tctrl |= (TIMER_ENABLE << (n * 4));
++ writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL);
++}
++
++void timer_disable(int n)
++{
++ if (n < 0 || n > 7) {
++ return;
++ }
++ uint32_t tctrl = readl(AST_TIMER_BASE + TIMER_CONTROL);
++ writel(tctrl & ~(0x0f << (n * 4)), AST_TIMER_BASE + TIMER_CONTROL);
++}
+diff --git a/board/aspeed/ast-g5/ast-g5-timer.h b/board/aspeed/ast-g5/ast-g5-timer.h
+new file mode 100644
+index 0000000..4b1ac28
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-timer.h
+@@ -0,0 +1,27 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef __AST_G5_TIMER_H__
++#define __AST_G5_TIMER_H__
++
++#include <common.h>
++
++#define TIMER_1 0
++#define TIMER_2 1
++#define TIMER_3 2
++#define TIMER_4 3
++#define TIMER_5 4
++#define TIMER_6 5
++#define TIMER_7 6
++#define TIMER_8 7
++
++void timer_enable(int n, uint32_t freq, interrupt_handler_t handler);
++void timer_disable(int n);
++
++#endif /* __AST_G5_TIMER_H__ */
+diff --git a/board/aspeed/ast-g5/ast-g5.h b/board/aspeed/ast-g5/ast-g5.h
+index 908db14..28fe5ea 100644
+--- a/board/aspeed/ast-g5/ast-g5.h
++++ b/board/aspeed/ast-g5/ast-g5.h
+@@ -4,5 +4,6 @@
+ #include <common.h>
+ #include "ast-g5-irq.h"
+ #include "ast-g5-gpio.h"
++#include "ast-g5-timer.h"
+
+ #endif /* _AST_G5_H_ */
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch
new file mode 100644
index 000000000..e376001b3
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch
@@ -0,0 +1,149 @@
+From 2db86017f1cd48da9f6c102665d5ae3d1efe48cc Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Wed, 14 Nov 2018 12:16:53 -0800
+Subject: [PATCH] Add status and ID LED support
+
+Add status (amber and green) and ID (blue) LED support. In the
+bootloader phase, the LEDs should be blinking. When booting linux, they
+should turn to a fixed state.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: Ic9595621b21000ef465ff57ed2047855296e2714
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 113 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 113 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 6e45cb4..e749992 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -146,6 +146,112 @@ static void sgpio_init(void)
+ writel(value, AST_GPIO_BASE + GPIO254);
+ }
+
++/* running the timer at 48 hertz will easily give a 24Hz blink */
++#define TICK_HZ 48
++#define BLINK_DELAY(HZ) ((int)((TICK_HZ / (HZ)) / 2) - 1)
++typedef enum {
++ /*
++ * Identifies the control request for the ID LED.
++ */
++ EIDLED_Initialize = 0,
++ EIDLED_Tick,
++ EIDLED_Toggle,
++ EIDLED_Off,
++ EIDLED_On,
++ EIDLED_Blink,
++ EIDLED_Blink_24HZ = EIDLED_Blink + BLINK_DELAY(24),
++ EIDLED_Blink_12HZ = EIDLED_Blink + BLINK_DELAY(12),
++ EIDLED_Blink_6HZ = EIDLED_Blink + BLINK_DELAY(6),
++ EIDLED_Blink_3HZ = EIDLED_Blink + BLINK_DELAY(3),
++ EIDLED_Blink_1HZ = EIDLED_Blink + BLINK_DELAY(1),
++ EIDLED_Blink_0_5HZ = EIDLED_Blink + BLINK_DELAY(0.5),
++} EIDLEDControl;
++
++struct led_info {
++ int gpio;
++ EIDLEDControl mode;
++ int count;
++ int state;
++};
++
++static struct led_info s_led_info[] = {
++ /* BMC Executing bootloader (Default) :-
++ * ChassisID: Blinking Blue 3Hz, StatusLED: Blinking Green 1Hz */
++ [GPIO_ID_LED] = {GPIO_ID_LED, EIDLED_Blink_3HZ, 1, 0},
++ [GPIO_GREEN_LED] = {GPIO_GREEN_LED, EIDLED_Blink_1HZ, 0, 0},
++ [GPIO_AMBER_LED] = {GPIO_AMBER_LED, EIDLED_Off, 0, 0},
++};
++
++extern void gpio_set_value(int n, int asserted);
++void id_led_control(int id, int action)
++{
++ if (id >= ARRAY_SIZE(s_led_info)) {
++ return;
++ }
++ /* don't bother with LEDs that are not initialized */
++ if (EIDLED_Initialize == s_led_info[id].mode) {
++ return;
++ }
++
++ /* check for a blinker action */
++ if (EIDLED_Tick == action) {
++ if (s_led_info[id].mode < EIDLED_Blink) {
++ return;
++ }
++ /* check countdown for blink */
++ if (s_led_info[id].count == 0) {
++ s_led_info[id].count =
++ s_led_info[id].mode - EIDLED_Blink;
++ s_led_info[id].state = !s_led_info[id].state;
++ } else {
++ s_led_info[id].count--;
++ return;
++ }
++ } else if (EIDLED_Toggle == action) {
++ s_led_info[id].state = !s_led_info[id].state;
++ s_led_info[id].mode =
++ s_led_info[id].state ? EIDLED_On : EIDLED_Off;
++ } else if (action > EIDLED_Toggle) {
++ s_led_info[id].mode = action;
++ if (EIDLED_Off == action) {
++ s_led_info[id].state = 0;
++ } else if (EIDLED_On == action) {
++ s_led_info[id].state = 1;
++ } else if (action >= EIDLED_Blink) {
++ s_led_info[id].count = action - EIDLED_Blink;
++ /* wait for the next tick */
++ return;
++ }
++ } else if (EIDLED_Initialize == action) {
++ if (s_led_info[id].mode >= EIDLED_Blink) {
++ s_led_info[id].count =
++ s_led_info[id].mode - EIDLED_Blink;
++ }
++ }
++ gpio_set_value(s_led_info[id].gpio, s_led_info[id].state);
++}
++
++static void timer8_irq_handler(void *regs)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(s_led_info); i++) {
++ id_led_control(i, EIDLED_Tick);
++ }
++}
++
++void timer8_init(void)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(s_led_info); i++) {
++ id_led_control(i, EIDLED_Initialize);
++ }
++
++ /* set up the timer to fire at TICK_HZ HZ */
++ timer_enable(TIMER_8, TICK_HZ, timer8_irq_handler);
++}
++
+ int intel_force_firmware_jumper_enabled(void)
+ {
+ return gpio_get_value(GPIO_FF_UPD_JUMPER);
+@@ -157,4 +263,11 @@ void ast_g5_intel(void)
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+ espi_init();
+ sgpio_init();
++ timer8_init();
++ if (intel_force_firmware_jumper_enabled()) {
++ /* FFUJ mode:- ChassisID: Solid Blue, StatusLED: Solid Amber */
++ id_led_control(GPIO_ID_LED, EIDLED_On);
++ id_led_control(GPIO_GREEN_LED, EIDLED_Off);
++ id_led_control(GPIO_AMBER_LED, EIDLED_On);
++ }
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch
new file mode 100644
index 000000000..4714dd6cc
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch
@@ -0,0 +1,141 @@
+From 039b9a278a4d075e455a38ec93171dc812aec8b2 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri, 16 Nov 2018 15:57:57 -0800
+Subject: [PATCH 1/1] aspeed: add Pwm Driver
+
+Change-Id: Ia8b80212f7c70aafcc6a71782936ec95cf9b7f38
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 113 +++++++++++++++++++++++++++++
+ 1 file changed, 113 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index e74999223b..74e218dfd0 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -257,9 +257,122 @@ int intel_force_firmware_jumper_enabled(void)
+ return gpio_get_value(GPIO_FF_UPD_JUMPER);
+ }
+
++/* PWM offsets */
++
++#define PWM_BASE_ADDR 0x1E786000
++#define PWM_CONTROL 0x00
++#define PWM_CLOCK_SELECTION 0x04
++#define PWM_DUTY_CYCLE 0x08
++#define PWM_M0 0x10
++#define PWM_M1 0x14
++#define PWM_N0 0x18
++#define PWM_N1 0x1c
++#define PWM_CONTROL_EXT 0x40
++#define PWM_CLOCK_SEL_EXT 0x44
++#define PWM_O0 0x50
++#define PWM_O1 0x54
++#define PWM_CHANNEL_COUNT 8
++
++#define PWM_CLK_ENABLE BIT(0)
++#define PWM_DUTY(PCT) (((PCT) * 128) / 100)
++#define DEFAULT_PWM_DUTY_VALUE PWM_DUTY(57)
++
++
++static inline uint32_t ast_scu_read(uint32_t reg)
++{
++ uint32_t val = readl(AST_SCU_BASE + reg);
++
++ debug("ast_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val);
++ return val;
++}
++
++static inline void ast_scu_write(uint32_t val, uint32_t reg)
++{
++ debug("ast_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val);
++
++ writel(SCU_PROTECT_UNLOCK, AST_SCU_BASE);
++ writel(val, AST_SCU_BASE + reg);
++#ifdef CONFIG_AST_SCU_LOCK
++ writel(0xaa, AST_SCU_BASE);
++#endif
++}
++
++static void set_pwm_duty_cycle(int duty)
++{
++ uint32_t chan;
++ uint32_t val;
++
++ /* enable pwm channels */
++ for (chan = 0; chan < PWM_CHANNEL_COUNT; chan++) {
++ uint32_t base = chan < 4 ? PWM_BASE_ADDR : PWM_BASE_ADDR + 0x40;
++ uint8_t ch_duty_shift = 16 * (chan & 0x1);
++ uint8_t ch_pair = (chan & 0x3) / 2;
++
++ /* enable pwm for the channel */
++ val = readl(base);
++ val |= ((1 << (chan & 0x3)) << 8);
++ writel(val, base);
++
++ /* set duty cycle */
++ val = readl(base + PWM_DUTY_CYCLE + ch_pair * 4);
++ val &= ~(0xffff << ch_duty_shift);
++ val |= (((uint32_t)duty) << 8) << ch_duty_shift;
++ writel(val, base + PWM_DUTY_CYCLE + ch_pair * 4);
++ }
++
++}
++
++static void pwm_init(void)
++{
++ uint32_t val;
++
++ /* select pwm 0-7 */
++ val = ast_scu_read(AST_SCU_FUN_PIN_CTRL3);
++ val |= (SCU_FUN_PIN_VPIG7 | SCU_FUN_PIN_VPIG6 | SCU_FUN_PIN_VPIG5
++ | SCU_FUN_PIN_VPIG4 | SCU_FUN_PIN_VPIG3 | SCU_FUN_PIN_VPIG2
++ | SCU_FUN_PIN_VPIG1 | SCU_FUN_PIN_VPIG0);
++ ast_scu_write(val, AST_SCU_FUN_PIN_CTRL3);
++
++ /* disable video output mux */
++ val = ast_scu_read(AST_SCU_FUN_PIN_CTRL5);
++ val &= 0xffffffcf;
++ ast_scu_write(val, AST_SCU_FUN_PIN_CTRL5);
++ val = readl(AST_SCU_FUN_PIN_CTRL6);
++ val &= 0xfffffffc;
++ ast_scu_write(val, AST_SCU_FUN_PIN_CTRL6);
++
++ /* SCU reset of PWM module */
++ val = ast_scu_read(AST_SCU_RESET);
++ val |= SCU_RESET_PWM;
++ ast_scu_write(val, AST_SCU_RESET);
++ val &= ~SCU_RESET_PWM;
++ ast_scu_write(val, AST_SCU_RESET);
++
++ /* set M, N, and 0 clock regs to 0 */
++ writel(0, PWM_BASE_ADDR + PWM_M0);
++ writel(0, PWM_BASE_ADDR + PWM_N0);
++ writel(0, PWM_BASE_ADDR + PWM_O0);
++
++ /* disable fans and tachos, set M type control */
++ writel(0x1, PWM_BASE_ADDR + PWM_CONTROL);
++ writel(0x1, PWM_BASE_ADDR + PWM_CONTROL_EXT);
++
++ set_pwm_duty_cycle(DEFAULT_PWM_DUTY_VALUE);
++
++ /* set up clock type M: period = 127 units at 24MHz/8 (resulting ~23kHz period) */
++ writel(0x7f30, PWM_BASE_ADDR + PWM_CLOCK_SELECTION);
++
++ /* enable pwm-tacho */
++
++ val = readl(PWM_BASE_ADDR + PWM_CONTROL);
++ val |= PWM_CLK_ENABLE;
++ writel(val, PWM_BASE_ADDR + PWM_CONTROL);
++}
++
+ extern void espi_init(void);
+ void ast_g5_intel(void)
+ {
++ pwm_init();
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+ espi_init();
+ sgpio_init();
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch
new file mode 100644
index 000000000..22191f07a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch
@@ -0,0 +1,89 @@
+From 040c9c13778076403198ce93f43c4aa3a1ed3907 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Sat, 17 Nov 2018 14:17:27 -0800
+Subject: [PATCH] Keep interrupts enabled until last second
+
+The U-Boot bootm command disabled interrupts almost first thing. This
+would prevent a person hitting the power button on the host immediatly
+after AC on because the BMC would fail to respond to the espi interrupts
+and the host would power off.
+
+Change-Id: I6c0fb5cca1be6c326da4c9a3d3dfbab89dac9928
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 8 ++++++++
+ common/bootm.c | 7 -------
+ common/bootm_os.c | 1 +
+ 3 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index c7ae566..01f8a13 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -255,6 +255,14 @@ int intel_force_firmware_jumper_enabled(void)
+ return gpio_get_value(GPIO_FF_UPD_JUMPER);
+ }
+
++void arch_preboot_os(void)
++{
++ // last second before booting... set the LEDs
++ id_led_control(GPIO_ID_LED, EIDLED_On);
++ id_led_control(GPIO_GREEN_LED, EIDLED_On);
++ id_led_control(GPIO_AMBER_LED, EIDLED_Off);
++}
++
+ /* PWM offsets */
+
+ #define PWM_BASE_ADDR 0x1E786000
+diff --git a/common/bootm.c b/common/bootm.c
+index 2431019..46909ec 100644
+--- a/common/bootm.c
++++ b/common/bootm.c
+@@ -602,7 +602,6 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+ int states, bootm_headers_t *images, int boot_progress)
+ {
+ boot_os_fn *boot_fn;
+- ulong iflag = 0;
+ int ret = 0, need_boot_fn;
+
+ images->state |= states;
+@@ -626,7 +625,6 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+ if (!ret && (states & BOOTM_STATE_LOADOS)) {
+ ulong load_end;
+
+- iflag = bootm_disable_interrupts();
+ ret = bootm_load_os(images, &load_end, 0);
+ if (ret == 0)
+ lmb_reserve(&images->lmb, images->os.load,
+@@ -670,8 +668,6 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+ BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
+ BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
+ if (boot_fn == NULL && need_boot_fn) {
+- if (iflag)
+- enable_interrupts();
+ printf("ERROR: booting os '%s' (%d) is not supported\n",
+ genimg_get_os_name(images->os.os), images->os.os);
+ bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
+@@ -711,9 +707,6 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+
+ /* Deal with any fallout */
+ err:
+- if (iflag)
+- enable_interrupts();
+-
+ if (ret == BOOTM_ERR_UNIMPLEMENTED)
+ bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
+ else if (ret == BOOTM_ERR_RESET)
+diff --git a/common/bootm_os.c b/common/bootm_os.c
+index 9ec84bd..b56eb39 100644
+--- a/common/bootm_os.c
++++ b/common/bootm_os.c
+@@ -476,6 +476,7 @@ __weak void arch_preboot_os(void)
+ int boot_selected_os(int argc, char * const argv[], int state,
+ bootm_headers_t *images, boot_os_fn *boot_fn)
+ {
++ disable_interrupts();
+ arch_preboot_os();
+ boot_fn(state, argc, argv, images);
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch
new file mode 100644
index 000000000..d93d9c4a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch
@@ -0,0 +1,112 @@
+From 711c7bc5a07b62e8369bc76a9db265c960bacef8 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Mon, 19 Nov 2018 11:04:02 -0800
+Subject: [PATCH] Rewrite memmove to optimize on word transfers
+
+Reading from the flash at boot time was using byte-sized transfers,
+which ultimately turns into four word transfers over spi for every real
+word read. This change breaks memmove down into a header, body, and
+trailer, where the body is all done with word-sized transfers.
+
+Change-Id: Ie0a1f3261e507fb34a908571883d9bf04a1059ee
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+---
+ lib/string.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 64 insertions(+), 13 deletions(-)
+
+diff --git a/lib/string.c b/lib/string.c
+index 67d5f6a..0bf472f 100644
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -505,26 +505,77 @@ void * memcpy(void *dest, const void *src, size_t count)
+ *
+ * Unlike memcpy(), memmove() copes with overlapping areas.
+ */
+-void * memmove(void * dest,const void *src,size_t count)
++void *memmove(void *dest, const void *src, size_t count)
+ {
+- char *tmp, *s;
+-
+- if (src == dest)
++ unsigned char *bdst = (unsigned char *)dest;
++ const unsigned char *bsrc = (const unsigned char *)src;
++ unsigned long *ldst;
++ const unsigned long *lsrc;
++ size_t unaligned_header = 0, unaligned_trailer = 0;
++ size_t unaligned_src =
++ (sizeof(*ldst) - (size_t)src) & (sizeof(*ldst) - 1);
++ size_t unaligned_dst =
++ (sizeof(*ldst) - (size_t)dest) & (sizeof(*ldst) - 1);
++
++ if (src == dest || !count)
+ return dest;
+
++ if (unaligned_src || unaligned_dst) {
++ if (unaligned_dst != unaligned_src) {
++ unaligned_header = count;
++ } else {
++ unaligned_header = unaligned_src;
++ if (unaligned_header > count) {
++ unaligned_header = count;
++ }
++ }
++ count -= unaligned_header;
++ }
++ if (count & (sizeof(*ldst) - 1)) {
++ unaligned_trailer = count & (sizeof(*ldst) - 1);
++ count -= unaligned_trailer;
++ }
++
+ if (dest <= src) {
+- tmp = (char *) dest;
+- s = (char *) src;
+- while (count--)
+- *tmp++ = *s++;
++ /* possible un-aligned bytes */
++ while (unaligned_header--)
++ *bdst++ = *bsrc++;
++
++ /* aligned words */
++ ldst = (unsigned long *)bdst;
++ lsrc = (const unsigned long *)bsrc;
++ while (count >= sizeof(*ldst)) {
++ count -= sizeof(*ldst);
++ *ldst++ = *lsrc++;
+ }
+- else {
+- tmp = (char *) dest + count;
+- s = (char *) src + count;
+- while (count--)
+- *--tmp = *--s;
++
++ /* possibly un-aligned bytes */
++ bdst = (unsigned char *)ldst;
++ bsrc = (const unsigned char *)lsrc;
++ while (unaligned_trailer--)
++ *bdst++ = *bsrc++;
++ } else {
++ bdst += unaligned_header + count + unaligned_trailer;
++ bsrc += unaligned_header + count + unaligned_trailer;
++
++ /* possibly un-aligned bytes */
++ while (unaligned_trailer--)
++ *--bdst = *--bsrc;
++
++ /* aligned words */
++ ldst = (unsigned long *)bdst;
++ lsrc = (unsigned long *)bsrc;
++ while (count >= sizeof(*ldst)) {
++ count -= sizeof(*ldst);
++ *--ldst = *--lsrc;
+ }
+
++ /* possibly un-aligned bytes */
++ bdst = (unsigned char *)ldst;
++ bsrc = (const unsigned char *)lsrc;
++ while (unaligned_header--)
++ *--bdst = *--bsrc;
++ }
+ return dest;
+ }
+ #endif
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch
new file mode 100644
index 000000000..8a63edbb7
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch
@@ -0,0 +1,46 @@
+From 9b05a276af65dd436f30b1b2680a09821c5a81aa Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Mon, 17 Dec 2018 20:37:23 -0800
+Subject: [PATCH] u-boot: full platform reset + espi oob-ready
+
+If the platform is strapped for fast reset, have platform-g5.S do a full
+reset and then immediately set oob-ready so the espi master controller
+can initiate communication.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+---
+ arch/arm/mach-aspeed/platform_g5.S | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-aspeed/platform_g5.S b/arch/arm/mach-aspeed/platform_g5.S
+index 2ac1ca4..66427b6 100644
+--- a/arch/arm/mach-aspeed/platform_g5.S
++++ b/arch/arm/mach-aspeed/platform_g5.S
+@@ -139,7 +139,7 @@
+ But if FW has other initial code executed before platform.S, then it should use WDT_SOC mode.
+ Use WDT_Full may clear the initial result of prior initial code.
+ ******************************************************************************/
+-//#define ASTMMC_INIT_RESET_MODE_FULL
++#define ASTMMC_INIT_RESET_MODE_FULL
+
+ /******************************************************************************
+ There is a compatibility issue for Hynix DDR4 SDRAM.
+@@ -563,6 +563,17 @@ wait_first_reset:
+ *******************************************/
+
+ bypass_first_reset:
++ /* Timing from ESPI master requires OOB channel ready bit be set early */
++ ldr r0, =0x1e6e2070 @ check strapping for eSPI mode
++ tst r0, #0x02000000 @ Test for bit 25 - eSPI Mode
++ beq espi_early_init_done @ if bit 25 clear, dont set OOB ready
++
++ ldr r0, =0x1e6ee000
++ ldr r1, [r0] @ ESPI000: ESPI Engine Control Reg
++ orr r1, r1, #0x00000010 @ Set OOB Channel Ready bit
++ str r1, [r0]
++espi_early_init_done:
++
+ /* Enable Timer separate clear mode */
+ ldr r0, =0x1e782038
+ mov r1, #0xAE
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch
new file mode 100644
index 000000000..afdd610b3
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch
@@ -0,0 +1,164 @@
+From 54616ade08517374200a332e50f68ee9d0fbf5c5 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Tue, 9 Apr 2019 14:42:05 +0800
+Subject: [PATCH] Add system reset status support
+
+Will display the reset reasons and other CPU information in u-boot,
+and save the reset reasons into kernel command line,
+for applications to query.
+
+Change-Id: I87ada3ecf14368519e4d09035bb1e09fdc05469b
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+---
+ arch/arm/include/asm/arch-aspeed/platform.h | 2 +
+ arch/arm/mach-aspeed/ast-scu.c | 4 ++
+ board/aspeed/ast-g5/ast-g5-intel.c | 73 +++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5.c | 7 +++
+ 4 files changed, 86 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h
+index 3b06e52..4e4140d 100644
+--- a/arch/arm/include/asm/arch-aspeed/platform.h
++++ b/arch/arm/include/asm/arch-aspeed/platform.h
+@@ -29,6 +29,8 @@
+ #include <asm/arch/ast_g5_platform.h>
+ #include <asm/arch/ast-g5-intel.h>
+ #define CONFIG_BOARD_EARLY_INIT_F 1 /* Call board_early_init_f */
++#define CONFIG_BOARD_LATE_INIT 1 /* Call board_late_init */
++#define CONFIG_DISPLAY_CPUINFO 1
+ #else
+ #err "No define for platform.h"
+ #endif
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index 3a9ba05..976c59b 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -494,6 +494,9 @@ void ast_scu_sys_rest_info(void)
+ {
+ u32 rest = ast_scu_read(AST_SCU_SYS_CTRL);
+
++#ifdef AST_SOC_G5
++ printf("RST : 0x%02x\n", rest);
++#else
+ if (rest & SCU_SYS_EXT_RESET_FLAG) {
+ printf("RST : External\n");
+ ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL);
+@@ -506,6 +509,7 @@ void ast_scu_sys_rest_info(void)
+ } else {
+ printf("RST : CLK en\n");
+ }
++#endif
+ }
+
+ u32 ast_scu_get_vga_memsize(void)
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 01f8a13..e0bf9ee 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -303,6 +303,79 @@ static inline void ast_scu_write(uint32_t val, uint32_t reg)
+ #endif
+ }
+
++
++static void update_bootargs_cmd(const char *key, const char *value)
++{
++ int buf_len;
++ char *buf;
++ char *cmdline;
++ char comp_key[128];
++
++ if (!key || (key[0] == '\0')) {
++ printf("%s - Empty key not allowed\n", __func__);
++ return;
++ }
++
++ cmdline = getenv("bootargs");
++
++ /* Allocate space for maximum possible new command line */
++ if (value)
++ buf_len = strlen(cmdline) + strlen(key) + 3 + strlen(value);
++ else
++ buf_len = strlen(cmdline) + strlen(key) + 3;
++
++ buf = malloc(buf_len);
++ if (!buf) {
++ printf("%s: out of memory\n", __func__);
++ return;
++ }
++ memset(buf, 0, buf_len);
++
++ if (!cmdline) {
++ /* lets add key-value, though bootargs are empty */
++ snprintf(buf, buf_len, "%s=%s", key, (value ? value : ""));
++ setenv("bootargs", buf);
++ free(buf);
++ return;
++ }
++
++ snprintf(comp_key, sizeof(comp_key), "%s=", key);
++ char *start = strstr(cmdline, comp_key);
++
++ /* Check for full word match. Match should be start of cmdline
++ * or there should be space before match */
++ if (start && ((start == cmdline) || (*(start-1) == ' '))) {
++ char *end = strchr(start, ' ');
++ strncpy(buf, cmdline, (start - cmdline));
++
++ if (end)
++ snprintf(buf, buf_len, "%s%s=%s %s", buf, key,
++ (value ? value : ""), end+1);
++ else
++ snprintf(buf, buf_len, "%s%s=%s", buf, key,
++ (value ? value : ""));
++ } else {
++ snprintf(buf, buf_len, "%s %s=%s", cmdline, key,
++ (value ? value : ""));
++ }
++
++ setenv("bootargs", buf);
++ free(buf);
++}
++
++void ast_g5_intel_late_init(void)
++{
++ char value[32];
++ u32 reset_reason = 0;
++
++ /* save and clear reset status */
++ reset_reason = ast_scu_read(AST_SCU_SYS_CTRL);
++ snprintf(value, sizeof(value), "0x%x", reset_reason);
++ ast_scu_write(0, AST_SCU_SYS_CTRL);
++
++ update_bootargs_cmd("resetreason", value);
++}
++
+ static void pwm_init(void)
+ {
+ uint32_t val;
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index d41ef9c..0953677 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -19,6 +19,7 @@
+ DECLARE_GLOBAL_DATA_PTR;
+
+ extern void ast_g5_intel(void);
++extern void ast_g5_intel_late_init(void);
+
+ int board_early_init_f(void)
+ {
+@@ -40,6 +41,12 @@ int board_init(void)
+ return 0;
+ }
+
++int board_late_init(void)
++{
++ ast_g5_intel_late_init();
++ return 0;
++}
++
+ int dram_init(void)
+ {
+ u32 vga = ast_scu_get_vga_memsize();
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch
new file mode 100644
index 000000000..6949856db
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch
@@ -0,0 +1,36 @@
+From 647cc2538ed6b64054c742b4668386fda9394221 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 8 Jan 2019 13:33:15 -0800
+Subject: [PATCH] Enable PCIe L1 support
+
+This commit enables PCIe L1 support using magic registers.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+
+---
+ arch/arm/mach-aspeed/platform_g5.S | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm/mach-aspeed/platform_g5.S b/arch/arm/mach-aspeed/platform_g5.S
+index 66427b6..b404353 100644
+--- a/arch/arm/mach-aspeed/platform_g5.S
++++ b/arch/arm/mach-aspeed/platform_g5.S
+@@ -2432,6 +2432,18 @@ spi_cbr_end:
+ bic r1, r1, #0x00400000
+ str r1, [r0]
+
++ ldr r0, =0x1e6ed07c @ Enable PCIe L1 support
++ ldr r1, =0xa8
++ str r1, [r0]
++
++ ldr r0, =0x1e6ed068
++ ldr r1, =0xc81f0a
++ str r1, [r0]
++
++ ldr r0, =0x1e6ed07c
++ mov r1, #0
++ str r1, [r0]
++
+ /******************************************************************************
+ Configure MAC timing
+ ******************************************************************************/
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch
new file mode 100644
index 000000000..32a40261f
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch
@@ -0,0 +1,106 @@
+From 30c634b4969b8a3cd3afc079d60d23d2cb9f5f5c Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 11 Feb 2019 15:19:56 +0800
+Subject: [PATCH] Config host uart clock source using environment variable
+
+In order to support high speed uart for host uarts,
+the uart clock needs to be switched between 24M and 192M.
+Config SCU4C based on environment variable hostserialcfg,
+this variable is set by IPMI OEM commands.
+
+Tested:
+Change the hostserialcfg variable to 0/1/2/3,
+using the below commands:
+
+ipmitool raw 0x32 0x90 1 0; reboot
+cat /sys/class/tty/ttyS*/uartclk, all should be 24MHz
+
+ipmitool raw 0x32 0x90 1 1; reboot
+cat /sys/class/tty/ttyS*/uartclk, ttyS0/2/3 should be 192MHz
+
+ipmitool raw 0x32 0x90 1 2; reboot
+cat /sys/class/tty/ttyS*/uartclk, ttyS1 should be 192MHz
+
+ipmitool raw 0x32 0x90 1 3; reboot
+cat /sys/class/tty/ttyS*/uartclk, ttyS0/12/3 should be 192MHz
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+
+---
+ arch/arm/include/asm/arch-aspeed/regs-scu.h | 5 ++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 39 +++++++++++++++++++++++++++++
+ 2 files changed, 44 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/regs-scu.h b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+index 10b983a..8a596ce 100644
+--- a/arch/arm/include/asm/arch-aspeed/regs-scu.h
++++ b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+@@ -529,6 +529,11 @@
+ /* AST_SCU_MAC_CLK 0x48 - MAC interface clock delay setting register */
+
+ /* AST_SCU_MISC2_CTRL 0x4C - Misc. 2 Control register */
++#define SCU_UART5_HS_CLOCK (1 << 28)
++#define SCU_UART4_HS_CLOCK (1 << 27)
++#define SCU_UART3_HS_CLOCK (1 << 26)
++#define SCU_UART2_HS_CLOCK (1 << 25)
++#define SCU_UART1_HS_CLOCK (1 << 24)
+ #ifdef AST_SOC_G5
+ #define SCU_PCIE_MAPPING_HIGH (1 << 15)
+ #define SCU_MALI_DTY_MODE (1 << 8)
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index e0bf9ee..e19df03 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -103,6 +103,9 @@ static const GPIOValue gpio_table[] = {
+ #define SGPIO_ENABLE 1
+ #define GPIO254 0x254
+
++#define HOST_SERIAL_A_HIGH_SPEED (1 << 0)
++#define HOST_SERIAL_B_HIGH_SPEED (1 << 1)
++
+ static void sgpio_init(void)
+ {
+ uint32_t value;
+@@ -368,6 +371,42 @@ void ast_g5_intel_late_init(void)
+ char value[32];
+ u32 reset_reason = 0;
+
++ /* By default host serail A and B use normal speed */
++ uint32_t host_serial_cfg = 0;
++ char *host_serial_cfg_txt = NULL;
++
++ /* Config the uart clock source based on environment configuration */
++ host_serial_cfg_txt = getenv("hostserialcfg");
++
++ if (host_serial_cfg_txt != NULL)
++ host_serial_cfg = simple_strtoul(host_serial_cfg_txt, NULL, 16);
++
++ if (host_serial_cfg > (HOST_SERIAL_A_HIGH_SPEED | HOST_SERIAL_B_HIGH_SPEED)) {
++ printf("Invalided hostserialcfg %x, use default!\n", host_serial_cfg);
++ host_serial_cfg = 0;
++ }
++
++ /* SOL implementation requires uart1/uart3/uart4 have the same clock
++ * source for data forwarding, config uart3 and uart4
++ */
++ if (host_serial_cfg & HOST_SERIAL_A_HIGH_SPEED) {
++ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) |
++ SCU_UART1_HS_CLOCK | SCU_UART3_HS_CLOCK |
++ SCU_UART4_HS_CLOCK, AST_SCU_MISC2_CTRL);
++ } else {
++ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) &
++ ~SCU_UART1_HS_CLOCK & ~SCU_UART3_HS_CLOCK &
++ ~SCU_UART4_HS_CLOCK, AST_SCU_MISC2_CTRL);
++ }
++
++ if (host_serial_cfg & HOST_SERIAL_B_HIGH_SPEED) {
++ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) |
++ SCU_UART2_HS_CLOCK, AST_SCU_MISC2_CTRL);
++ } else {
++ ast_scu_write(ast_scu_read(AST_SCU_MISC2_CTRL) &
++ ~SCU_UART2_HS_CLOCK, AST_SCU_MISC2_CTRL);
++ }
++
+ /* save and clear reset status */
+ reset_reason = ast_scu_read(AST_SCU_SYS_CTRL);
+ snprintf(value, sizeof(value), "0x%x", reset_reason);
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch
new file mode 100644
index 000000000..2b6382967
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch
@@ -0,0 +1,613 @@
+From 6d8db23becf9665193023e350adcad00b75195b0 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 13 Mar 2019 14:28:05 +0530
+Subject: [PATCH 1/1] KCS driver support in uBoot
+
+Added KCS support in uBoot. This will enable
+KCS channels and set the specified registers
+to do KCS communication in uBoot. It also
+consist of read and write KCS message transations
+work flow implementation( As specified in IPMI
+specification Section 9.15). It is enabled
+only when Force Firmware Update Jumper is ON.
+
+Tested By:
+Stopped booting in uBoot and sent IPMI commands
+via KCS interfaces using cmdtool.efi.
+ - Get Device ID:
+ Req: cmdtool.efi 20 18 1
+ Res: 00 23 00 12 03 02 BF 57 01 00 7B 00 00 00 00 00
+ - Get Self Test Results
+ Req: cmdtool.efi 20 18 4
+ Res: 00 56 00
+ - All other commands
+ Req: cmdtool.efi 20 18 2
+ Res: C1 (Invalid).
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 3 +
+ board/aspeed/ast-g5/ast-g5-kcs.c | 420 +++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-kcs.h | 112 ++++++++
+ 4 files changed, 536 insertions(+)
+ create mode 100644 board/aspeed/ast-g5/ast-g5-kcs.c
+ create mode 100644 board/aspeed/ast-g5/ast-g5-kcs.h
+
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index 90224333c4..05972b9d17 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -4,3 +4,4 @@ obj-y += ast-g5-espi.o
+ obj-y += ast-g5-irq.o
+ obj-y += ast-g5-gpio.o
+ obj-y += ast-g5-timer.o
++obj-y += ast-g5-kcs.o
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 032f716722..c149426947 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -256,6 +256,7 @@ int intel_force_firmware_jumper_enabled(void)
+ }
+
+ extern void espi_init(void);
++extern void kcs_init(void);
+ void ast_g5_intel(void)
+ {
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+@@ -264,5 +265,7 @@ void ast_g5_intel(void)
+ timer8_init();
+ if (intel_force_firmware_jumper_enabled()) {
+ id_led_control(GPIO_AMBER_LED, EIDLED_On);
++ kcs_init();
++ /* TODO: need to stop the booting here. */
+ }
+ }
+diff --git a/board/aspeed/ast-g5/ast-g5-kcs.c b/board/aspeed/ast-g5/ast-g5-kcs.c
+new file mode 100644
+index 0000000000..7bff26f9db
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-kcs.c
+@@ -0,0 +1,420 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include "ast-g5-kcs.h"
++
++#ifdef DEBUG_KCS_ENABLED
++#define DBG_KCS printf
++#else
++#define DBG_KCS(...)
++#endif
++
++/* TODO: Move to IPMI file. */
++#define IPMI_CC_OK 0x00
++#define IPMI_CC_INVALID 0xC1
++#define IPMI_CC_UNSPECIFIED 0xFF
++
++#define KCS_CHANNEL_NO_3 3
++
++static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 };
++
++static const struct kcs_io_reg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = {
++ { .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 },
++ { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 },
++ { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 },
++ { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }
++};
++
++#define NO_OF_ENABLED_KCS_CHANNELS ARRAY_SIZE(enabled_kcs_channel)
++
++static struct kcs_packet m_kcs_pkt[NO_OF_ENABLED_KCS_CHANNELS];
++
++static u16 read_status(u16 channel_num)
++{
++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str);
++}
++
++static void write_status(u16 channel_num, u16 value)
++{
++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str);
++}
++
++static u16 read_data(u16 channel_num)
++{
++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].idr);
++}
++
++static void write_data(u16 channel_num, u16 value)
++{
++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].odr);
++}
++
++static void set_kcs_state(u16 channel_num, u16 state)
++{
++ u16 status = read_status(channel_num);
++
++ status &= ~KCS_STATE_MASK;
++ status |= KCS_STATE(state) & KCS_STATE_MASK;
++ write_status(channel_num, status);
++}
++
++static struct kcs_packet *get_kcs_packet(u16 channel_num)
++{
++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) {
++ if (channel_num == enabled_kcs_channel[idx])
++ return &m_kcs_pkt[idx];
++ }
++
++ /* very unlike code hits here. */
++ DBG_KCS("ERROR: %s error. ChannelNo: %d\n", __func__, channel_num);
++ BUG();
++}
++
++static void kcs_force_abort(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ DBG_KCS("ERROR: KCS communication aborted (Channel:%d, Error:%d)\n",
++ channel_num, kcs_pkt->error);
++ set_kcs_state(channel_num, KCS_STATE_ERROR);
++ read_data(channel_num);
++ write_data(channel_num, ZERO_DATA);
++
++ kcs_pkt->phase = KCS_PHASE_ERROR;
++ kcs_pkt->read_req_done = false;
++ kcs_pkt->data_in_idx = 0;
++}
++
++static void init_kcs_packet(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ kcs_pkt->channel = channel_num;
++ kcs_pkt->read_req_done = false;
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ kcs_pkt->error = KCS_NO_ERROR;
++ kcs_pkt->data_in_idx = 0;
++ kcs_pkt->data_out_idx = 0;
++ kcs_pkt->data_out_len = 0;
++}
++
++static void process_kcs_request(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++ int i;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ if (!kcs_pkt->read_req_done)
++ return;
++
++ DBG_KCS("%s:- chan:%d\n", __func__, channel_num);
++
++#ifdef DEBUG_KCS_ENABLED
++ DBG_KCS("Request data(Len:%d): ", kcs_pkt->data_in_idx);
++ for (i = 0; i < kcs_pkt->data_in_idx; i++)
++ DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]);
++ DBG_KCS("\n");
++#endif
++
++ /*
++ * TODO: Move it to IPMI Command Handler
++ * Below code is added for timebeing till
++ * we implement the IPMI command handler.
++ */
++ kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */
++ kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */
++
++ if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
++ (kcs_pkt->data_in[1] == 0x01)) {
++ /* Get Device ID */
++ u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02,
++ 0xBF, 0x57, 0x01, 0x00, 0x7B,
++ 0x00, 0x00, 0x00, 0x00, 0x00 };
++ for (i = 0; i < 15; i++)
++ kcs_pkt->data_out[i + 3] = device_id[i];
++ kcs_pkt->data_out_len = 18;
++ } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
++ (kcs_pkt->data_in[1] == 0x04)) {
++ /* Get Self Test Results */
++ kcs_pkt->data_out[3] = 0x56;
++ kcs_pkt->data_out[4] = 0x00;
++ kcs_pkt->data_out_len = 5;
++ } else {
++ kcs_pkt->data_out[2] =
++ IPMI_CC_INVALID; /* Invalid or not supported. */
++ kcs_pkt->data_out_len = 3;
++ }
++ /* END: TODO */
++
++#ifdef DEBUG_KCS_ENABLED
++ DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len);
++ for (i = 0; i < kcs_pkt->data_out_len; i++)
++ DBG_KCS(" 0x%02x", kcs_pkt->data_out[i]);
++ DBG_KCS("\n");
++#endif
++
++ kcs_pkt->phase = KCS_PHASE_READ;
++ write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
++ kcs_pkt->read_req_done = false;
++}
++
++static void read_kcs_data(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++
++ switch (kcs_pkt->phase) {
++ case KCS_PHASE_WRITE_START:
++ kcs_pkt->phase = KCS_PHASE_WRITE_DATA;
++ /* fall through */
++
++ case KCS_PHASE_WRITE_DATA:
++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) {
++ kcs_pkt->error = KCS_LENGTH_ERROR;
++ kcs_force_abort(channel_num);
++ return;
++ }
++ set_kcs_state(channel_num, KCS_STATE_WRITE);
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] =
++ read_data(channel_num);
++ break;
++
++ case KCS_PHASE_WRITE_END:
++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) {
++ kcs_pkt->error = KCS_LENGTH_ERROR;
++ kcs_force_abort(channel_num);
++ return;
++ }
++ set_kcs_state(channel_num, KCS_STATE_READ);
++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] =
++ read_data(channel_num);
++ kcs_pkt->phase = KCS_PHASE_READ_WAIT;
++ kcs_pkt->read_req_done = true;
++
++ process_kcs_request(channel_num);
++ break;
++
++ case KCS_PHASE_READ:
++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len)
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++
++ u8 data = read_data(channel_num);
++ if (data != KCS_CTRL_CODE_READ) {
++ DBG_KCS("Invalid Read data. Phase:%d, Data:0x%02x\n",
++ kcs_pkt->phase, data);
++ set_kcs_state(channel_num, KCS_STATE_ERROR);
++ write_data(channel_num, ZERO_DATA);
++ break;
++ }
++
++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len) {
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ break;
++ }
++ write_data(channel_num,
++ kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
++ break;
++
++ case KCS_PHASE_ABORT_1:
++ set_kcs_state(channel_num, KCS_STATE_READ);
++ read_data(channel_num);
++ write_data(channel_num, kcs_pkt->error);
++ kcs_pkt->phase = KCS_PHASE_ABORT_2;
++ break;
++
++ case KCS_PHASE_ABORT_2:
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++ read_data(channel_num);
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ break;
++
++ default:
++ kcs_force_abort(channel_num);
++ }
++}
++
++static void read_kcs_cmd(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++
++ set_kcs_state(channel_num, KCS_STATE_WRITE);
++ write_data(channel_num, ZERO_DATA);
++
++ u16 cmd = read_data(channel_num);
++ switch (cmd) {
++ case KCS_CTRL_CODE_WRITE_START:
++ init_kcs_packet(channel_num);
++ kcs_pkt->phase = KCS_PHASE_WRITE_START;
++ break;
++
++ case KCS_CTRL_CODE_WRITE_END:
++ if (kcs_pkt->error != KCS_NO_ERROR) {
++ kcs_force_abort(channel_num);
++ return;
++ }
++
++ kcs_pkt->phase = KCS_PHASE_WRITE_END;
++ break;
++
++ case KCS_CTRL_CODE_GET_STATUS_ABORT:
++ kcs_pkt->phase = KCS_PHASE_ABORT_1;
++ kcs_pkt->error = KCS_ABORT_BY_CMD;
++ break;
++
++ default:
++ kcs_pkt->error = KCS_ILLEGAL_CTRL_CMD;
++ kcs_force_abort(channel_num);
++ }
++}
++
++static u16 kcs_irq_handler(struct pt_regs *regs)
++{
++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) {
++ u16 channel_num = enabled_kcs_channel[idx];
++ /* Look-up the interrupted KCS channel */
++ u16 status = read_status(channel_num);
++ if (status & BIT_STATUS_IBF) {
++ if (status & BIT_STATUS_COD)
++ read_kcs_cmd(channel_num);
++ else
++ read_kcs_data(channel_num);
++ }
++ }
++
++ return 0;
++}
++
++static void set_kcs_channel_addr(u16 channel_num)
++{
++ u32 val;
++
++ switch (channel_num) {
++ case 1:
++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_LADR12AS;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = (KCS_CHANNEL1_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR12H);
++ val = (KCS_CHANNEL1_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR12L);
++ break;
++
++ case 2:
++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_LADR12AS;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = (KCS_CHANNEL2_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR12H);
++ val = (KCS_CHANNEL2_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR12L);
++ break;
++
++ case 3:
++ val = (KCS_CHANNEL3_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR3H);
++ val = (KCS_CHANNEL3_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR3L);
++ break;
++
++ case 4:
++ val = (((KCS_CHANNEL4_ADDR + 1) << 16) | KCS_CHANNEL4_ADDR);
++ writel(val, AST_LPC_BASE + LPC_LADR4);
++ break;
++
++ default:
++ DBG_KCS("Invalid channel (%d) specified\n", channel_num);
++ break;
++ }
++}
++
++static void enable_kcs_channel(u16 channel_num, u16 enable)
++{
++ u32 val;
++
++ switch (channel_num) {
++ case 1:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE1;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC1E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC1E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE1;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 2:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE2;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC2E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC2E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE2;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 3:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE3;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC3E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_KCSENBL;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC3E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_KCSENBL;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE3;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 4:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICRB) | BIT_IBFIE4 |
++ BIT_LPC4E;
++ writel(val, AST_LPC_BASE + LPC_HICRB);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICRB) &
++ ~(BIT_IBFIE4 | BIT_LPC4E);
++ writel(val, AST_LPC_BASE + LPC_HICRB);
++ }
++ break;
++
++ default:
++ DBG_KCS("Invalid channel (%d) specified\n", channel_num);
++ }
++}
++
++void kcs_init(void)
++{
++ /* Initialize the KCS channels. */
++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) {
++ u16 channel_num = enabled_kcs_channel[idx];
++ DBG_KCS("%s Channel: %d\n", __func__, channel_num);
++ set_kcs_channel_addr(channel_num);
++ enable_kcs_channel(channel_num, 1);
++
++ /* Set KCS channel state to idle */
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++ }
++
++ /* KCS interrupt */
++ request_irq(IRQ_SRC_LPC, kcs_irq_handler);
++}
+diff --git a/board/aspeed/ast-g5/ast-g5-kcs.h b/board/aspeed/ast-g5/ast-g5-kcs.h
+new file mode 100644
+index 0000000000..bb697c455d
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-kcs.h
+@@ -0,0 +1,112 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018-2019 Intel Corporation */
++
++#include <asm/io.h>
++#include <common.h>
++
++#include "ast-g5.h"
++
++#define KCS_CHANNEL_MAX 4
++#define IRQ_SRC_LPC 8 /* IRQ 8 */
++#define MAX_KCS_PKT_SIZE (64 * 1024)
++/* KCS channel addresses */
++#define KCS_CHANNEL1_ADDR 0xCA0
++#define KCS_CHANNEL2_ADDR 0xCA8
++#define KCS_CHANNEL3_ADDR 0xCA2 /* KCS SMS */
++#define KCS_CHANNEL4_ADDR 0xCA4 /* KCS SMM */
++
++#define ZERO_DATA 0x00
++
++/* Aspeed KCS control registers */
++#define LPC_HICR0 0x00 /* Host Interface Control Register 0 */
++#define LPC_HICR1 0x04 /* Host Interface Control Register 1 */
++#define LPC_HICR2 0x08 /* Host Interface Control Register 2 */
++#define LPC_HICR3 0x0C /* Host Interface Control Register 3 */
++#define LPC_HICR4 0x10 /* Host Interface Control Register 4 */
++#define LPC_LADR3H 0x14 /* LPC channel #3 Address Register H */
++#define LPC_LADR3L 0x18 /* LPC channel #3 Address Register H */
++#define LPC_LADR12H 0x1C /* LPC channel #1#2 Address Register H */
++#define LPC_LADR12L 0x20 /* LPC channel #1#2 Address Register L */
++#define LPC_IDR1 0x24 /* Input Data Register 1 */
++#define LPC_IDR2 0x28 /* Input Data Register 2 */
++#define LPC_IDR3 0x2C /* Input Data Register 3 */
++#define LPC_ODR1 0x30 /* Output Data Register 1 */
++#define LPC_ODR2 0x34 /* Output Data Register 2 */
++#define LPC_ODR3 0x38 /* Output Data Register 3 */
++#define LPC_STR1 0x3C /* Status Register 1 */
++#define LPC_STR2 0x40 /* Status Register 2 */
++#define LPC_STR3 0x44 /* Status Register 3 */
++#define LPC_HICRB 0x100 /* Host Interface Control Register B */
++#define LPC_LADR4 0x110 /* LPC channel #4 Address Register */
++#define LPC_IDR4 0x114 /* Input Data Register 4 */
++#define LPC_ODR4 0x118 /* Output Data Register 4 */
++#define LPC_STR4 0x11C /* Status Data Register 4 */
++
++/* LPC Bits */
++#define BIT_LADR12AS BIT(7) /* Channel Address selection */
++#define BIT_IBFIE1 BIT(1) /* Enable IDR1 Recv completion interrupt */
++#define BIT_IBFIE2 BIT(2) /* Enable IDR2 Recv completion interrupt */
++#define BIT_IBFIE3 BIT(3) /* Enable IBF13 interrupt */
++#define BIT_LPC1E BIT(5) /* Enable LPC channel #1 */
++#define BIT_LPC2E BIT(6) /* Enable LPC channel #2 */
++#define BIT_LPC3E BIT(7) /* Enable LPC channel #2 */
++#define BIT_KCSENBL BIT(2) /* Enable KCS interface in Channel #3 */
++#define BIT_IBFIE4 BIT(1)
++#define BIT_LPC4E BIT(0)
++
++#define BIT_STATUS_OBF BIT(0) /* Output Data Register full #1/#2/#3 */
++#define BIT_STATUS_IBF BIT(1) /* Input Data Register full #1/#2/#3 */
++#define BIT_STATUS_COD BIT(3) /* Command/Data - (1=command,0=data) */
++
++#define KCS_STATE_MASK 0xC0 /* BIT[6:7] of status register */
++#define KCS_STATE(state) ((state) << 6)
++
++/* IPMI2.0(section 9.7) - KCS interface State Bits */
++#define KCS_STATE_IDLE 0x00
++#define KCS_STATE_READ 0x01
++#define KCS_STATE_WRITE 0x02
++#define KCS_STATE_ERROR 0x03
++
++/* IPMI2.0(section 9.10) - KCS interface control codes */
++#define KCS_CTRL_CODE_GET_STATUS_ABORT 0x60
++#define KCS_CTRL_CODE_WRITE_START 0x61
++#define KCS_CTRL_CODE_WRITE_END 0x62
++#define KCS_CTRL_CODE_READ 0x68
++
++struct kcs_io_reg {
++ u32 idr;
++ u32 odr;
++ u32 str;
++};
++
++enum kcs_phase {
++ KCS_PHASE_IDLE = 0,
++ KCS_PHASE_WRITE_START = 1,
++ KCS_PHASE_WRITE_DATA = 2,
++ KCS_PHASE_WRITE_END = 3,
++ KCS_PHASE_READ_WAIT = 4,
++ KCS_PHASE_READ = 5,
++ KCS_PHASE_ABORT_1 = 6,
++ KCS_PHASE_ABORT_2 = 7,
++ KCS_PHASE_ERROR = 8
++};
++
++enum kcs_error {
++ KCS_NO_ERROR = 0x00,
++ KCS_ABORT_BY_CMD = 0x01,
++ KCS_ILLEGAL_CTRL_CMD = 0x02,
++ KCS_LENGTH_ERROR = 0x06,
++ KCS_UNSPECIFIED_ERROR = 0xFF,
++};
++
++struct kcs_packet {
++ enum kcs_phase phase;
++ enum kcs_error error;
++ u16 channel;
++ bool read_req_done;
++ u16 data_in_idx;
++ u8 data_in[MAX_KCS_PKT_SIZE];
++ u16 data_out_len;
++ u16 data_out_idx;
++ u8 data_out[MAX_KCS_PKT_SIZE];
++};
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch
new file mode 100644
index 000000000..afba07abf
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch
@@ -0,0 +1,37 @@
+From 4cbfb21b7792e6dae74e2db6e2e2d6803bf6cc1d Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Tue, 26 Mar 2019 20:34:51 +0530
+Subject: [PATCH] u-boot env change for PFR image
+
+Tested: verified BMC booting from 0x20b00000
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ include/configs/ast-common.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h
+index 0bc7f2d..821ea8f 100644
+--- a/include/configs/ast-common.h
++++ b/include/configs/ast-common.h
+@@ -108,7 +108,7 @@
+ #define CONFIG_SYS_MAX_FLASH_BANKS (CONFIG_FMC_CS)
+ #define CONFIG_SYS_MAX_FLASH_SECT (8192) /* max number of sectors on one chip */
+ #define CONFIG_ENV_IS_IN_FLASH 1
+-#define CONFIG_ENV_OFFSET 0x2400000 /* environment starts here */
++#define CONFIG_ENV_OFFSET 0xa0000 /* environment starts here */
+ #define CONFIG_ENV_ADDR (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET)
+ #define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
+
+@@ -116,7 +116,7 @@
+ #define CONFIG_ENV_ADDR_REDUND (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET_REDUND)
+ #define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
+
+-#define CONFIG_BOOTCOMMAND "bootm 20080000"
++#define CONFIG_BOOTCOMMAND "bootm 20b00000"
+ #define CONFIG_ENV_OVERWRITE
+
+ #define ASPEED_ENV_SETTINGS \
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch
new file mode 100644
index 000000000..f3fc0738b
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch
@@ -0,0 +1,50 @@
+From 6b0f858e2dda7afce82797835f950e3501b3046d Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 29 Mar 2019 12:30:20 -0700
+Subject: [PATCH] Add TPM enable pulse triggering
+
+This commit adds onboard TPM enable pulse triggering.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index adc6d10..55afa09 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -53,8 +53,8 @@ static const GPIOValue gpio_table[] = {
+ GPIO_DEBOUNCE_8MS},
+
+ /* Enable Pulse -- pin D6 */
+- [GPIO_ENABLE_TPM_PULSE] = {PORT_PIN(GPIO_PORT_D, GPIO_PIN_6),
+- GPIO_CFG_DEFAULT, 0, GPIO_DEBOUNCE_8MS},
++ [GPIO_ENABLE_TPM_PULSE] = {TPM_EN_PULSE_PORT_PIN, GPCFG_OUTPUT_EN, 0,
++ GPIO_DEBOUNCE_NONE},
+ };
+
+ #define LPC_SNOOP_ADDR 0x80
+@@ -232,6 +232,13 @@ void id_led_control(int id, int action)
+ gpio_set_value(s_led_info[id].gpio, s_led_info[id].state);
+ }
+
++static void enable_onboard_tpm(void)
++{
++ gpio_set_value(GPIO_ENABLE_TPM_PULSE, 1);
++ mdelay(50);
++ gpio_set_value(GPIO_ENABLE_TPM_PULSE, 0);
++}
++
+ static void timer8_irq_handler(void *regs)
+ {
+ int i;
+@@ -488,6 +495,7 @@ void ast_g5_intel(void)
+ espi_init();
+ sgpio_init();
+ timer8_init();
++ enable_onboard_tpm();
+ if (intel_force_firmware_jumper_enabled()) {
+ id_led_control(GPIO_AMBER_LED, EIDLED_On);
+ kcs_init();
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch
new file mode 100644
index 000000000..252a9ea1b
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch
@@ -0,0 +1,330 @@
+From 2314db61ea792a98c35fcc75b0ac09cbc0db005d Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 21 May 2019 00:19:16 +0530
+Subject: [PATCH] IPMI command handler implementation in uboot
+
+IPMI command handler implemtation in uBoot.
+Implemented IPMI commands:
+ 1) Get Device ID
+ 2) Get Self Test Result
+
+Tested By:
+Ran the above IPMI command Via KCS channel
+and got proper response.
+- Get Device ID
+ Req: cmdtool.efi 20 18 1
+ Res: 0x00 0x23 0x00 0x82 0x03 0x02 0x00 0x57 0x01 0x00 0x7b 0x00 0x00 0x00 0x00 0x00
+- Get Self Test Results
+ Req: cmdtool.efi 20 18 4
+ Res: 00 56 00
+
+Change-Id: I18b205bc45c34f7c4ef16adc29fa5bd494624ceb
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-kcs.c | 77 +++++++++++++-----------
+ board/aspeed/ast-g5/ipmi-handler.c | 118 +++++++++++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ipmi-handler.h | 40 +++++++++++++
+ 4 files changed, 202 insertions(+), 34 deletions(-)
+ create mode 100644 board/aspeed/ast-g5/ipmi-handler.c
+ create mode 100644 board/aspeed/ast-g5/ipmi-handler.h
+
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index 05972b9..f28fcfe 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -5,3 +5,4 @@ obj-y += ast-g5-irq.o
+ obj-y += ast-g5-gpio.o
+ obj-y += ast-g5-timer.o
+ obj-y += ast-g5-kcs.o
++obj-y += ipmi-handler.o
+diff --git a/board/aspeed/ast-g5/ast-g5-kcs.c b/board/aspeed/ast-g5/ast-g5-kcs.c
+index 7bff26f..98bf69b 100644
+--- a/board/aspeed/ast-g5/ast-g5-kcs.c
++++ b/board/aspeed/ast-g5/ast-g5-kcs.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ // Copyright (c) 2018-2019 Intel Corporation
+
+-#include "ast-g5-kcs.h"
++#include "ipmi-handler.h"
+
+ #ifdef DEBUG_KCS_ENABLED
+ #define DBG_KCS printf
+@@ -9,11 +9,6 @@
+ #define DBG_KCS(...)
+ #endif
+
+-/* TODO: Move to IPMI file. */
+-#define IPMI_CC_OK 0x00
+-#define IPMI_CC_INVALID 0xC1
+-#define IPMI_CC_UNSPECIFIED 0xFF
+-
+ #define KCS_CHANNEL_NO_3 3
+
+ static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 };
+@@ -103,6 +98,7 @@ static void init_kcs_packet(u16 channel_num)
+ static void process_kcs_request(u16 channel_num)
+ {
+ struct kcs_packet *kcs_pkt = NULL;
++ struct ipmi_cmd_data ipmi_data;
+ int i;
+
+ kcs_pkt = get_kcs_packet(channel_num);
+@@ -117,37 +113,49 @@ static void process_kcs_request(u16 channel_num)
+ DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]);
+ DBG_KCS("\n");
+ #endif
++ u8 req_lun = kcs_pkt->data_in[0] & 0x03; /* LUN[1:0] */
++ ipmi_data.net_fun = (kcs_pkt->data_in[0] >> 2); /* netfn[7:2] */
++ ipmi_data.cmd = kcs_pkt->data_in[1]; /* cmd */
++ /* We support only BMC LUN 00h */
++ if (req_lun != LUN_BMC) {
++ kcs_pkt->data_out[0] =
++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_INVALID_CMD_LUN; /* CC code */
++ kcs_pkt->data_out_len = 3;
++ goto done;
++ }
+
+- /*
+- * TODO: Move it to IPMI Command Handler
+- * Below code is added for timebeing till
+- * we implement the IPMI command handler.
+- */
+- kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */
+- kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */
+- kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */
+-
+- if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
+- (kcs_pkt->data_in[1] == 0x01)) {
+- /* Get Device ID */
+- u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02,
+- 0xBF, 0x57, 0x01, 0x00, 0x7B,
+- 0x00, 0x00, 0x00, 0x00, 0x00 };
+- for (i = 0; i < 15; i++)
+- kcs_pkt->data_out[i + 3] = device_id[i];
+- kcs_pkt->data_out_len = 18;
+- } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
+- (kcs_pkt->data_in[1] == 0x04)) {
+- /* Get Self Test Results */
+- kcs_pkt->data_out[3] = 0x56;
+- kcs_pkt->data_out[4] = 0x00;
+- kcs_pkt->data_out_len = 5;
+- } else {
+- kcs_pkt->data_out[2] =
+- IPMI_CC_INVALID; /* Invalid or not supported. */
++ /* Boundary check */
++ if ((kcs_pkt->data_in_idx - 2) > sizeof(ipmi_data.req_data)) {
++ kcs_pkt->data_out[0] =
++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_OUT_OF_SPACE; /* CC code */
+ kcs_pkt->data_out_len = 3;
++ goto done;
+ }
+- /* END: TODO */
++ /* Fill in IPMI request data */
++ ipmi_data.req_len = kcs_pkt->data_in_idx - 2;
++ for (i = 0; i < kcs_pkt->data_in_idx - 2; i++)
++ ipmi_data.req_data[i] = kcs_pkt->data_in[i + 2];
++
++ /* Call IPMI command handler */
++ ipmi_cmd_handler(&ipmi_data);
++
++ /* Get IPMI response and fill KCS out data */
++ /* First 2 bytes in KCS response are netFn, Cmd */
++ kcs_pkt->data_out[0] = GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd;
++ if ((ipmi_data.res_len + 2) > sizeof(kcs_pkt->data_out)) {
++ kcs_pkt->data_out[2] = IPMI_CC_UNSPECIFIED; /* CC code */
++ kcs_pkt->data_out_len = 3;
++ goto done;
++ }
++ for (i = 0; i < ipmi_data.res_len; i++)
++ kcs_pkt->data_out[i + 2] = ipmi_data.res_data[i];
++
++ kcs_pkt->data_out_len = ipmi_data.res_len + 2;
+
+ #ifdef DEBUG_KCS_ENABLED
+ DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len);
+@@ -156,6 +164,7 @@ static void process_kcs_request(u16 channel_num)
+ DBG_KCS("\n");
+ #endif
+
++done:
+ kcs_pkt->phase = KCS_PHASE_READ;
+ write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
+ kcs_pkt->read_req_done = false;
+diff --git a/board/aspeed/ast-g5/ipmi-handler.c b/board/aspeed/ast-g5/ipmi-handler.c
+new file mode 100644
+index 0000000..9cccee9
+--- /dev/null
++++ b/board/aspeed/ast-g5/ipmi-handler.c
+@@ -0,0 +1,118 @@
++
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include "ipmi-handler.h"
++
++/* IPMI network function codes */
++#define NETFN_APP 0x06
++
++/* IPMI command codes */
++#define CMD_GET_DEV_ID 0x01
++#define CMD_GET_SELF_TEST_RESULTS 0x04
++
++typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res);
++
++struct get_dev_id {
++ u8 completion_code;
++ u8 dev_id;
++ u8 dev_rev;
++ u8 fw_rev1;
++ u8 fw_rev2;
++ u8 ipmi_ver;
++ u8 dev_support;
++ u8 mfg_id[3];
++ u8 product_id[2];
++ u8 aux_fw_rev[4];
++};
++struct self_test_res {
++ u8 completion_code;
++ u8 res_byte[2];
++};
++
++struct ipmi_cmd_table {
++ u8 net_fun;
++ u8 cmd;
++ fun_handler process_cmd;
++};
++
++static u16 get_device_id(u8 *req, u16 req_len, u8 *res)
++{
++ /* Get Device ID */
++ bool operation = 1; /* Firmware operation */
++ u8 intel_mfg_id[3] = { 0x57, 0x01, 0x00 };
++ u8 platform_id[2] = { 0x7B, 0x00 };
++ u8 aux_fw_rev[4] = { 0x00, 0x00, 0x00, 0x00 };
++ struct get_dev_id *result = (struct get_dev_id *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ result->dev_id = 0x23;
++ result->dev_rev = 0x00; /* Not provides dev SDR */
++
++ result->ipmi_ver = 0x02; /* IPMI 2.0 */
++ result->dev_support = 0x00; /* No dev support in this mode */
++ memcpy(result->mfg_id, intel_mfg_id, sizeof(result->mfg_id));
++ memcpy(result->aux_fw_rev, aux_fw_rev, sizeof(result->aux_fw_rev));
++
++ /* TODO: Get Firmware version from flash(PFM Header) */
++ result->fw_rev1 = ((operation << 7) | (0x02 & 0x7F));
++ result->fw_rev2 = 0x03;
++ /* TODO: Read Platform ID from GPIO */
++ memcpy(result->product_id, platform_id, sizeof(result->product_id));
++
++ return sizeof(struct get_dev_id);
++}
++
++static u16 get_self_test_result(u8 *req, u16 req_len, u8 *res)
++{
++ /* Get Self Test Results */
++ struct self_test_res *result = (struct self_test_res *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ result->res_byte[0] = 0x56; /* Self test function not implemented. */
++ result->res_byte[1] = 0x00;
++
++ return sizeof(struct self_test_res);
++}
++
++const struct ipmi_cmd_table cmd_info[] = {
++ { NETFN_APP, CMD_GET_DEV_ID, get_device_id },
++ { NETFN_APP, CMD_GET_SELF_TEST_RESULTS, get_self_test_result }
++};
++
++#define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info)
++
++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data)
++{
++ int i = 0;
++ for (i = 0; i < CMD_TABLE_SIZE; i++) {
++ if ((cmd_info[i].net_fun == ipmi_data->net_fun) &&
++ (cmd_info[i].cmd == ipmi_data->cmd)) {
++ break;
++ }
++ }
++
++ if (i == CMD_TABLE_SIZE) {
++ /* Invalid or not supported. */
++ ipmi_data->res_data[0] = IPMI_CC_INVALID_CMD;
++ ipmi_data->res_len = 1;
++ return;
++ }
++
++ /* Call the appropriate function handler */
++ ipmi_data->res_len =
++ cmd_info[i].process_cmd(ipmi_data->req_data, ipmi_data->req_len,
++ &ipmi_data->res_data[0]);
++
++ return;
++}
+diff --git a/board/aspeed/ast-g5/ipmi-handler.h b/board/aspeed/ast-g5/ipmi-handler.h
+new file mode 100644
+index 0000000..9d46d9b
+--- /dev/null
++++ b/board/aspeed/ast-g5/ipmi-handler.h
+@@ -0,0 +1,40 @@
++
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018-2019 Intel Corporation */
++
++#include "ast-g5-kcs.h"
++
++/* IPMI completion codes */
++#define IPMI_CC_OK 0x00
++#define IPMI_CC_NODE_BUSY 0xC0
++#define IPMI_CC_INVALID_CMD 0xC1
++#define IPMI_CC_INVALID_CMD_LUN 0xC2
++#define IPMI_CC_OUT_OF_SPACE 0xC4
++#define IPMI_CC_INVALID_DATA_LENGTH 0xC7
++#define IPMI_CC_INVALID_DATA_FIELD 0xCC
++#define IPMI_CC_UNSPECIFIED 0xFF
++
++/* BMC IPMB LUNs */
++#define LUN_BMC 0x00
++#define LUN_OEM1 0x01
++#define LUN_SMS 0x02
++#define LUN_OEM2 0x01
++
++
++#define MAX_IPMI_REQ_DATA_SIZE MAX_KCS_PKT_SIZE
++#define MAX_IPMI_RES_DATA_SIZE 64
++
++/* Response netFn[7:2], Lun[1:0] */
++#define GET_RESP_NETFN_LUN(lun, netfn) \
++ ((lun & 0x03) | (((netfn + 1) << 2) & 0xFD))
++
++struct ipmi_cmd_data {
++ u8 net_fun;
++ u8 cmd;
++ u16 req_len;
++ u16 res_len;
++ u8 req_data[MAX_IPMI_REQ_DATA_SIZE];
++ u8 res_data[MAX_IPMI_RES_DATA_SIZE];
++};
++
++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data);
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch
new file mode 100644
index 000000000..065f890bc
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch
@@ -0,0 +1,114 @@
+From b6f898ef15eede75700e9e13a8e0b69d88b12fd4 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Thu, 20 Jun 2019 18:11:43 +0530
+Subject: [PATCH 15/30] Manufacturing mode physical presence detection
+
+Support for physical presence of manufacturing mode added.
+Front panel power button press for 15 seconds will be detected
+and marked as special mode for manufacturing request.
+There will be 10 second Status LED blink for 10 seconds to
+do the physical indication to the user. This indicates the
+user that he has pressed power button long enough for
+manufacturing mode detection.
+
+Tested:
+1. Verified by holding the power button when u-boot boots for
+15 seconds, and confirmed that bootargs passed to linux has
+special=mfg string and status led blink physical indication
+has been provided
+2. Verified in normal condition special=mfg string is not passed
+and no physical indication has been provided
+
+Change-Id: Id7e7c7e7860c7ef3ae8e3a7a7cfda7ff506c0f2b
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+%% original patch: 0025-Manufacturing-mode-physical-presence-detection.patch
+---
+ board/aspeed/ast-g5/ast-g5-gpio.h | 2 +-
+ board/aspeed/ast-g5/ast-g5-intel.c | 35 ++++++++++++++++++++++++++++++
+ 2 files changed, 36 insertions(+), 1 deletion(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-gpio.h b/board/aspeed/ast-g5/ast-g5-gpio.h
+index 54b7388a22..8ccf437346 100644
+--- a/board/aspeed/ast-g5/ast-g5-gpio.h
++++ b/board/aspeed/ast-g5/ast-g5-gpio.h
+@@ -73,7 +73,7 @@
+ #define AMB_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_5)
+ #define FORCE_BMC_UPDATE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_0)
+ #define TPM_EN_PULSE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_6)
+-
++#define FP_PWR_BTN_PORT_PIN PORT_PIN(GPIO_PORT_E, GPIO_PIN_2)
+
+ // GPIO Configuration Register bits
+ #define GPCFG_EVENT_TO_SMI (1 << 7) // 1 == enabled
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 45ecd83fd3..efc3315caf 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -24,6 +24,7 @@ enum gpio_names {
+ GPIO_AMBER_LED,
+ GPIO_FF_UPD_JUMPER,
+ GPIO_ENABLE_TPM_PULSE,
++ GPIO_FP_PWR_BTN,
+ };
+
+ #define GPIO_CFG_DEFAULT (GPCFG_ACTIVE_HIGH | GPCFG_LEVEL_TRIG)
+@@ -58,6 +59,10 @@ static const GPIOValue gpio_table[] = {
+ /* Enable Pulse -- pin D6 */
+ [GPIO_ENABLE_TPM_PULSE] = {TPM_EN_PULSE_PORT_PIN, GPCFG_OUTPUT_EN, 0,
+ GPIO_DEBOUNCE_NONE},
++ /* Front Panel Power Button -- pin E2 */
++ [GPIO_FP_PWR_BTN] = {FP_PWR_BTN_PORT_PIN, GPIO_CFG_LOW_INPUT, 0,
++ GPIO_DEBOUNCE_8MS},
++
+ };
+
+ #define LPC_SNOOP_ADDR 0x80
+@@ -403,6 +408,30 @@ static void update_bootargs_cmd(const char *key, const char *value)
+ free(buf);
+ }
+
++static bool is_mfg_mode_phy_req(void)
++{
++ /*
++ * Assume mfg mode physical request is made, if power button
++ * is pressed continously for 15 seconds, indicate the
++ * same in bootargs
++ */
++ const uint32_t delay_in_ms = 100;
++ const uint32_t read_count = ((15 * 1000) / delay_in_ms);
++ const uint32_t delay_for_indication = 10 * 1000;
++ for (uint32_t count = 0; count < read_count; ++count) {
++ if (!gpio_get_value(GPIO_FP_PWR_BTN))
++ return false;
++
++ mdelay(delay_in_ms);
++ }
++ debug("is_mfg_mode_phy_req : detected mfg mode request\n");
++ id_led_control(GPIO_GREEN_LED, EIDLED_Blink_3HZ);
++ /* Delay the boot to do physical indication for mfg mode */
++ mdelay(delay_for_indication);
++
++ return true;
++}
++
+ void ast_g5_intel_late_init(void)
+ {
+ char value[32];
+@@ -450,6 +479,12 @@ void ast_g5_intel_late_init(void)
+ ast_scu_write(0, AST_SCU_SYS_CTRL);
+
+ update_bootargs_cmd("resetreason", value);
++
++ /* Update the special mode in bootargs */
++ if (is_mfg_mode_phy_req())
++ update_bootargs_cmd("special", "mfg");
++ else
++ update_bootargs_cmd("special", NULL);
+ }
+
+ static void pwm_init(void)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch
new file mode 100644
index 000000000..be2c4018d
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch
@@ -0,0 +1,1524 @@
+From ea4f14a24b67d5085149d48c7fb38d00f3a7444a Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 6 May 2019 03:01:55 +0530
+Subject: [PATCH] Aspeed I2C support in U-Boot
+
+Adding Aspeed I2C support in u-boot and enabled
+i2c command. It is mainly used for PFR to
+communicate with PFR CPLD while BMC is in
+"Force Firmware Update" mode.
+
+Tested:
+Using i2c command in u-boot, validated
+i2c functionalities like probe, read and write.
+
+Change-Id: Iad9af4a57a58bc8dc5c470bfadad9dac1371c238
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+---
+ arch/arm/include/asm/arch-aspeed/ast_g5_platform.h | 14 +
+ arch/arm/include/asm/arch-aspeed/ast_scu.h | 5 +
+ arch/arm/include/asm/arch-aspeed/regs-iic.h | 204 +++++
+ arch/arm/mach-aspeed/ast-scu.c | 122 +++
+ board/aspeed/ast-g5/ast-g5.c | 8 +
+ configs/ast_g5_phy_defconfig | 2 +
+ drivers/i2c/Kconfig | 5 +
+ drivers/i2c/Makefile | 1 +
+ drivers/i2c/ast_i2c.c | 852 +++++++++++++++++++++
+ drivers/i2c/ast_i2c.h | 131 ++++
+ include/configs/ast-common.h | 5 +
+ 11 files changed, 1349 insertions(+)
+ create mode 100644 arch/arm/include/asm/arch-aspeed/regs-iic.h
+ create mode 100644 drivers/i2c/ast_i2c.c
+ create mode 100644 drivers/i2c/ast_i2c.h
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h b/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h
+index 4210873..a84f471 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h
++++ b/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h
+@@ -105,6 +105,20 @@
+ #define AST_LPC_BASE 0x1E789000 /* LPC */
+ #define AST_MBX_BASE 0x1E789200 /* Mailbox */
+ #define AST_I2C_BASE 0x1E78A000 /* I2C */
++#define AST_I2C_DEV0_BASE 0x1E78A040 /* I2C DEV1 */
++#define AST_I2C_DEV1_BASE 0x1E78A080 /* I2C DEV2 */
++#define AST_I2C_DEV2_BASE 0x1E78A0C0 /* I2C DEV3 */
++#define AST_I2C_DEV3_BASE 0x1E78A100 /* I2C DEV4 */
++#define AST_I2C_DEV4_BASE 0x1E78A140 /* I2C DEV5 */
++#define AST_I2C_DEV5_BASE 0x1E78A180 /* I2C DEV6 */
++#define AST_I2C_DEV6_BASE 0x1E78A1C0 /* I2C DEV7 */
++#define AST_I2C_DEV7_BASE 0x1E78A300 /* I2C DEV8 */
++#define AST_I2C_DEV8_BASE 0x1E78A340 /* I2C DEV9 */
++#define AST_I2C_DEV9_BASE 0x1E78A380 /* I2C DEV10 */
++#define AST_I2C_DEV10_BASE 0x1E78A3C0 /* I2C DEV11 */
++#define AST_I2C_DEV11_BASE 0x1E78A400 /* I2C DEV12 */
++#define AST_I2C_DEV12_BASE 0x1E78A440 /* I2C DEV13 */
++#define AST_I2C_DEV13_BASE 0x1E78A480 /* I2C DEV14 */
+ #define AST_PECI_BASE 0x1E78B000 /* PECI */
+ #define AST_PCIARBITER_BASE 0x1E78C000 /* PCI ARBITER */
+ #define AST_UART2_BASE 0x1E78D000 /* UART2 */
+diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+index 369c4e3..b94d13e 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast_scu.h
++++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+@@ -28,6 +28,8 @@
+ #ifndef __AST_SCU_H
+ #define __AST_SCU_H
+
++#include <common.h>
++
+ extern void ast_scu_show_system_info (void);
+ extern void ast_scu_sys_rest_info(void);
+ extern void ast_scu_security_info(void);
+@@ -39,13 +41,16 @@ extern u32 ast_get_clk_source(void);
+ extern u32 ast_get_h_pll_clk(void);
+ extern u32 ast_get_m_pll_clk(void);
+ extern u32 ast_get_ahbclk(void);
++extern u32 ast_get_pclk(void);
+
+ extern u32 ast_scu_get_vga_memsize(void);
+
++extern void ast_scu_init_i2c(void);
+ extern void ast_scu_init_eth(u8 num);
+ extern void ast_scu_multi_func_eth(u8 num);
+ extern void ast_scu_multi_func_romcs(u8 num);
+ extern void ast_scu_multi_func_sgpio(void);
++extern void ast_scu_multi_func_i2c(u8 bus_no);
+
+ void ast_config_uart5_clk(void);
+
+diff --git a/arch/arm/include/asm/arch-aspeed/regs-iic.h b/arch/arm/include/asm/arch-aspeed/regs-iic.h
+new file mode 100644
+index 0000000..5eb3f0a
+--- /dev/null
++++ b/arch/arm/include/asm/arch-aspeed/regs-iic.h
+@@ -0,0 +1,204 @@
++/* arch/arm/plat-aspeed/include/mach/regs-iic.h
++ *
++ * Copyright (c) 2012 ASPEED Technology Inc. <ryan_chen@aspeedtech.com>
++ * http://www.aspeedtech.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * ASPEED I2C Controller
++*/
++
++#ifndef __ASM_ARCH_REGS_IIC_H
++#define __ASM_ARCH_REGS_IIC_H __FILE__
++
++#ifdef CONFIG_ARCH_AST1010
++#define AST_I2C_DMA_SIZE 512
++#else
++#define AST_I2C_DMA_SIZE 4096
++#endif
++#define AST_I2C_PAGE_SIZE 256
++
++#if defined(CONFIG_ARCH_AST2300)
++#define NUM_BUS 9
++#elif defined(CONFIG_ARCH_AST2400)
++#define NUM_BUS 14
++#elif defined(CONFIG_ARCH_AST1010)
++#define NUM_BUS 15
++#elif defined(CONFIG_ARCH_AST1520) || defined(CONFIG_ARCH_AST3200) || defined(CONFIG_ARCH_AST2500)
++#define NUM_BUS 14
++#elif defined(CONFIG_ARCH_AST1220)
++#define NUM_BUS 10
++#else
++#err "NO define NUM_BUS"
++#endif
++
++/* I2C Register */
++#define I2C_FUN_CTRL_REG 0x00
++#define I2C_AC_TIMING_REG1 0x04
++#define I2C_AC_TIMING_REG2 0x08
++#define I2C_INTR_CTRL_REG 0x0c
++#define I2C_INTR_STS_REG 0x10
++#define I2C_CMD_REG 0x14
++#define I2C_DEV_ADDR_REG 0x18
++#define I2C_BUF_CTRL_REG 0x1c
++#define I2C_BYTE_BUF_REG 0x20
++#define I2C_DMA_BASE_REG 0x24
++#define I2C_DMA_LEN_REG 0x28
++
++
++/* Gloable Register Definition */
++/* 0x00 : I2C Interrupt Status Register */
++/* 0x08 : I2C Interrupt Target Assignment */
++#if defined(CONFIG_ARCH_AST2400)
++#define AST_I2CG_INTR14 (0x1 << 13)
++#define AST_I2CG_INTR13 (0x1 << 12)
++#define AST_I2CG_INTR12 (0x1 << 11)
++#define AST_I2CG_INTR11 (0x1 << 10)
++#define AST_I2CG_INTR10 (0x1 << 9)
++#elif defined(CONFIG_ARCH_AST1010)
++#define AST_I2CG_INTR14 (0x1 << 13)
++#define AST_I2CG_INTR13 (0x1 << 12)
++#define AST_I2CG_INTR12 (0x1 << 11)
++#define AST_I2CG_INTR11 (0x1 << 10)
++#define AST_I2CG_INTR10 (0x1 << 9)
++#endif
++#define AST_I2CG_INTR09 (0x1 << 8)
++#define AST_I2CG_INTR08 (0x1 << 7)
++#define AST_I2CG_INTR07 (0x1 << 6)
++#define AST_I2CG_INTR06 (0x1 << 5)
++#define AST_I2CG_INTR05 (0x1 << 4)
++#define AST_I2CG_INTR04 (0x1 << 3)
++#define AST_I2CG_INTR03 (0x1 << 2)
++#define AST_I2CG_INTR02 (0x1 << 1)
++#define AST_I2CG_INTR01 (0x1)
++
++/* Device Register Definition */
++/* 0x00 : I2CD Function Control Register */
++#define AST_I2CD_BUFF_SEL_MASK (0x7 << 20)
++#define AST_I2CD_BUFF_SEL(x) (x << 20) // page 0 ~ 7
++#define AST_I2CD_M_SDA_LOCK_EN (0x1 << 16)
++#define AST_I2CD_MULTI_MASTER_DIS (0x1 << 15)
++#define AST_I2CD_M_SCL_DRIVE_EN (0x1 << 14)
++#define AST_I2CD_MSB_STS (0x1 << 9)
++#define AST_I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
++#define AST_I2CD_M_SDA_DRIVE_1T_EN (0x1 << 7)
++#define AST_I2CD_M_HIGH_SPEED_EN (0x1 << 6)
++#define AST_I2CD_DEF_ADDR_EN (0x1 << 5)
++#define AST_I2CD_DEF_ALERT_EN (0x1 << 4)
++#define AST_I2CD_DEF_ARP_EN (0x1 << 3)
++#define AST_I2CD_DEF_GCALL_EN (0x1 << 2)
++#define AST_I2CD_SLAVE_EN (0x1 << 1)
++#define AST_I2CD_MASTER_EN (0x1)
++
++/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
++#define AST_I2CD_tBUF (0x1 << 28) // 0~7
++#define AST_I2CD_tHDSTA (0x1 << 24) // 0~7
++#define AST_I2CD_tACST (0x1 << 20) // 0~7
++#define AST_I2CD_tCKHIGH (0x1 << 16) // 0~7
++#define AST_I2CD_tCKLOW (0x1 << 12) // 0~7
++#define AST_I2CD_tHDDAT (0x1 << 10) // 0~7
++#define AST_I2CD_CLK_TO_BASE_DIV (0x1 << 8) // 0~3
++#define AST_I2CD_CLK_BASE_DIV (0x1) // 0~0xf
++
++/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
++#define AST_I2CD_tTIMEOUT (0x1) // 0~7
++#define AST_NO_TIMEOUT_CTRL 0x0
++
++
++/* 0x0c : I2CD Interrupt Control Register */
++#define AST_I2CD_SDA_DL_TO_INTR_EN (0x1 << 14)
++#define AST_I2CD_BUS_RECOVER_INTR_EN (0x1 << 13)
++#define AST_I2CD_SMBUS_ALT_INTR_EN (0x1 << 12)
++#define AST_I2CD_SLAVE_MATCH_INTR_EN (0x1 << 7)
++#define AST_I2CD_SCL_TO_INTR_EN (0x1 << 6)
++#define AST_I2CD_ABNORMAL_INTR_EN (0x1 << 5)
++#define AST_I2CD_NORMAL_STOP_INTR_EN (0x1 << 4)
++#define AST_I2CD_ARBIT_LOSS_INTR_EN (0x1 << 3)
++#define AST_I2CD_RX_DOWN_INTR_EN (0x1 << 2)
++#define AST_I2CD_TX_NAK_INTR_EN (0x1 << 1)
++#define AST_I2CD_TX_ACK_INTR_EN (0x1)
++
++/* 0x10 : I2CD Interrupt Status Register : WC */
++#define AST_I2CD_INTR_STS_SDA_DL_TO (0x1 << 14)
++#define AST_I2CD_INTR_STS_BUS_RECOVER (0x1 << 13)
++#define AST_I2CD_INTR_STS_SMBUS_ALT (0x1 << 12)
++#define AST_I2CD_INTR_STS_SMBUS_ARP_ADDR (0x1 << 11)
++#define AST_I2CD_INTR_STS_SMBUS_DEV_ALT (0x1 << 10)
++#define AST_I2CD_INTR_STS_SMBUS_DEF_ADDR (0x1 << 9)
++#define AST_I2CD_INTR_STS_GCALL_ADDR (0x1 << 8)
++#define AST_I2CD_INTR_STS_SLAVE_MATCH (0x1 << 7)
++#define AST_I2CD_INTR_STS_SCL_TO (0x1 << 6)
++#define AST_I2CD_INTR_STS_ABNORMAL (0x1 << 5)
++#define AST_I2CD_INTR_STS_NORMAL_STOP (0x1 << 4)
++#define AST_I2CD_INTR_STS_ARBIT_LOSS (0x1 << 3)
++#define AST_I2CD_INTR_STS_RX_DOWN (0x1 << 2)
++#define AST_I2CD_INTR_STS_TX_NAK (0x1 << 1)
++#define AST_I2CD_INTR_STS_TX_ACK (0x1)
++
++/* 0x14 : I2CD Command/Status Register */
++#define AST_I2CD_SDA_OE (0x1 << 28)
++#define AST_I2CD_SDA_O (0x1 << 27)
++#define AST_I2CD_SCL_OE (0x1 << 26)
++#define AST_I2CD_SCL_O (0x1 << 25)
++#define AST_I2CD_TX_TIMING (0x1 << 24) // 0 ~3
++#define AST_I2CD_TX_STATUS (0x1 << 23)
++// Tx State Machine
++#define AST_I2CD_IDLE 0x0
++#define AST_I2CD_MACTIVE 0x8
++#define AST_I2CD_MSTART 0x9
++#define AST_I2CD_MSTARTR 0xa
++#define AST_I2CD_MSTOP 0xb
++#define AST_I2CD_MTXD 0xc
++#define AST_I2CD_MRXACK 0xd
++#define AST_I2CD_MRXD 0xe
++#define AST_I2CD_MTXACK 0xf
++#define AST_I2CD_SWAIT 0x1
++#define AST_I2CD_SRXD 0x4
++#define AST_I2CD_STXACK 0x5
++#define AST_I2CD_STXD 0x6
++#define AST_I2CD_SRXACK 0x7
++#define AST_I2CD_RECOVER 0x3
++
++#define AST_I2CD_SCL_LINE_STS (0x1 << 18)
++#define AST_I2CD_SDA_LINE_STS (0x1 << 17)
++#define AST_I2CD_BUS_BUSY_STS (0x1 << 16)
++#define AST_I2CD_SDA_OE_OUT_DIR (0x1 << 15)
++#define AST_I2CD_SDA_O_OUT_DIR (0x1 << 14)
++#define AST_I2CD_SCL_OE_OUT_DIR (0x1 << 13)
++#define AST_I2CD_SCL_O_OUT_DIR (0x1 << 12)
++#define AST_I2CD_BUS_RECOVER_CMD_EN (0x1 << 11)
++#define AST_I2CD_S_ALT_EN (0x1 << 10)
++// 0 : DMA Buffer, 1: Pool Buffer
++//AST1070 DMA register
++#define AST_I2CD_RX_DMA_ENABLE (0x1 << 9)
++#define AST_I2CD_TX_DMA_ENABLE (0x1 << 8)
++
++/* Command Bit */
++#define AST_I2CD_RX_BUFF_ENABLE (0x1 << 7)
++#define AST_I2CD_TX_BUFF_ENABLE (0x1 << 6)
++#define AST_I2CD_M_STOP_CMD (0x1 << 5)
++#define AST_I2CD_M_S_RX_CMD_LAST (0x1 << 4)
++#define AST_I2CD_M_RX_CMD (0x1 << 3)
++#define AST_I2CD_S_TX_CMD (0x1 << 2)
++#define AST_I2CD_M_TX_CMD (0x1 << 1)
++#define AST_I2CD_M_START_CMD (0x1)
++
++/* 0x18 : I2CD Slave Device Address Register */
++
++/* 0x1C : I2CD Pool Buffer Control Register */
++#define AST_I2CD_RX_BUF_ADDR_GET(x) ((x >> 24) & 0xff)
++#define AST_I2CD_RX_BUF_END_ADDR_SET(x) (x << 16)
++#define AST_I2CD_TX_DATA_BUF_END_SET(x) ((x & 0xff) << 8)
++#define AST_I2CD_TX_DATA_BUF_GET(x) ((x >> 8) & 0xff)
++#define AST_I2CD_BUF_BASE_ADDR_SET(x) (x & 0x3f)
++
++/* 0x20 : I2CD Transmit/Receive Byte Buffer Register */
++#define AST_I2CD_GET_MODE(x) ((x >> 8) & 0x1)
++
++#define AST_I2CD_RX_BYTE_BUFFER (0xff << 8)
++#define AST_I2CD_TX_BYTE_BUFFER (0xff)
++
++
++#endif /* __ASM_ARCH_REGS_IIC_H */
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index 976c59b..537cd4b 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -112,6 +112,12 @@ static struct soc_id soc_map_table[] = {
+ SOC_ID("AST2530-A2", 0x04030403),
+ };
+
++void ast_scu_init_i2c(void)
++{
++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_I2C,
++ AST_SCU_RESET);
++}
++
+ void ast_scu_init_eth(u8 num)
+ {
+ /* Set MAC delay Timing */
+@@ -292,6 +298,23 @@ u32 ast_get_ahbclk(void)
+ return ((hpll / axi_div) / ahb_div);
+ }
+
++u32 ast_get_pclk(void)
++{
++ unsigned int div, hpll;
++
++ hpll = ast_get_h_pll_clk();
++ div = SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL));
++#ifdef AST_SOC_G5
++ div = (div+1) << 2;
++#else
++ div = (div+1) << 1;
++#endif
++
++ debug("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div);
++ return (hpll/div);
++}
++
++
+ #else /* ! AST_SOC_G5 */
+
+ u32 ast_get_h_pll_clk(void)
+@@ -457,6 +480,105 @@ void ast_scu_multi_func_sgpio(void)
+ AST_SCU_FUN_PIN_CTRL2);
+ }
+
++extern void ast_scu_multi_func_i2c(u8 bus_no)
++{
++#ifdef CONFIG_ARCH_AST1010
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) |
++ SCU_FUN_PIN_SCL13 |
++ SCU_FUN_PIN_SDA13 |
++ SCU_FUN_PIN_SCL14 |
++ SCU_FUN_PIN_SDA14,
++ AST_SCU_FUN_PIN_CTRL4);
++
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) |
++ SCU_FUN_PIN_SCL1 |
++ SCU_FUN_PIN_SDA1 |
++ SCU_FUN_PIN_SCL2 |
++ SCU_FUN_PIN_SDA2 |
++ SCU_FUN_PIN_SCL3 |
++ SCU_FUN_PIN_SDA3 |
++ SCU_FUN_PIN_SCL4 |
++ SCU_FUN_PIN_SDA4 |
++ SCU_FUN_PIN_SCL5 |
++ SCU_FUN_PIN_SDA5 |
++ SCU_FUN_PIN_SCL6 |
++ SCU_FUN_PIN_SDA6 |
++ SCU_FUN_PIN_SCL7 |
++ SCU_FUN_PIN_SDA7 |
++ SCU_FUN_PIN_SCL8 |
++ SCU_FUN_PIN_SDA8 |
++ SCU_FUN_PIN_SALT1 |
++ SCU_FUN_PIN_SALT2 |
++ SCU_FUN_PIN_SALT3 |
++ SCU_FUN_PIN_SALT4,
++ AST_SCU_FUN_PIN_CTRL2);
++
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
++ SCU_FUN_PIN_SCL9 |
++ SCU_FUN_PIN_SDA9 |
++ SCU_FUN_PIN_SCL10 |
++ SCU_FUN_PIN_SDA10 |
++ SCU_FUN_PIN_SCL11 |
++ SCU_FUN_PIN_SDA11 |
++ SCU_FUN_PIN_SCL12 |
++ SCU_FUN_PIN_SDA12,
++ AST_SCU_FUN_PIN_CTRL1);
++#else
++ //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14
++ // AST 2400 have 14 , AST 2300 9 ...
++ u32 pin_ctrl = ast_scu_read(AST_SCU_FUN_PIN_CTRL5);
++ switch (bus_no) {
++ case 0:
++ break;
++ case 1:
++ break;
++ case 2:
++ pin_ctrl |= SCU_FUC_PIN_I2C3;
++ break;
++ case 3:
++ pin_ctrl |= SCU_FUC_PIN_I2C4;
++ break;
++ case 4:
++ pin_ctrl |= SCU_FUC_PIN_I2C5;
++ break;
++ case 5:
++ pin_ctrl |= SCU_FUC_PIN_I2C6;
++ break;
++ case 6:
++ pin_ctrl |= SCU_FUC_PIN_I2C7;
++ break;
++ case 7:
++ pin_ctrl |= SCU_FUC_PIN_I2C8;
++ break;
++ case 8:
++ pin_ctrl |= SCU_FUC_PIN_I2C9;
++ break;
++ case 9:
++ pin_ctrl |= SCU_FUC_PIN_I2C10;
++ pin_ctrl &= ~SCU_FUC_PIN_SD1;
++ break;
++ case 10:
++ pin_ctrl |= SCU_FUC_PIN_I2C11;
++ pin_ctrl &= ~SCU_FUC_PIN_SD1;
++ break;
++ case 11:
++ pin_ctrl |= SCU_FUC_PIN_I2C12;
++ pin_ctrl &= ~SCU_FUC_PIN_SD1;
++ break;
++ case 12:
++ pin_ctrl |= SCU_FUC_PIN_I2C13;
++ pin_ctrl &= ~SCU_FUC_PIN_SD1;
++ break;
++ case 13:
++ pin_ctrl |= SCU_FUC_PIN_I2C14;
++ break;
++ }
++
++ ast_scu_write(pin_ctrl, AST_SCU_FUN_PIN_CTRL5);
++#endif
++}
++
++
+ u32 ast_scu_revision_id(void)
+ {
+ int i;
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index 0953677..3c33546 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -13,6 +13,7 @@
+ #include <asm/arch/ast_scu.h>
+ #include <asm/arch/ast-sdmc.h>
+ #include <asm/io.h>
++#include <i2c.h>
+
+ #include "ast-g5.h"
+
+@@ -37,6 +38,13 @@ int board_init(void)
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+ gd->flags = 0;
+
++ /* Initialize I2C */
++#if defined(CONFIG_SYS_I2C)
++ i2c_init(I2C_ADAP->speed, I2C_ADAP->slaveaddr);
++#else
++ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
++#endif
++
+ ast_g5_intel();
+ return 0;
+ }
+diff --git a/configs/ast_g5_phy_defconfig b/configs/ast_g5_phy_defconfig
+index 4aefcf4..1b96ab7 100644
+--- a/configs/ast_g5_phy_defconfig
++++ b/configs/ast_g5_phy_defconfig
+@@ -13,3 +13,5 @@ CONFIG_OF_LIBFDT=y
+ CONFIG_SPI_FLASH=y
+ CONFIG_SYS_NS16550=y
+ CONFIG_USE_IRQ=y
++CONFIG_CMD_I2C=y
++CONFIG_SYS_I2C_AST=y
+diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
+index 6e22bba..5368ba2 100644
+--- a/drivers/i2c/Kconfig
++++ b/drivers/i2c/Kconfig
+@@ -58,6 +58,11 @@ config DM_I2C_GPIO
+ bindings are supported.
+ Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
+
++config SYS_I2C_AST
++ bool "Aspeed I2C bus driver"
++ help
++ Add support for Aspeed I2C busses on AST2500 processors.
++
+ config SYS_I2C_FSL
+ bool "Freescale I2C bus driver"
+ depends on DM_I2C
+diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
+index 167424d..b2a69ea 100644
+--- a/drivers/i2c/Makefile
++++ b/drivers/i2c/Makefile
+@@ -11,6 +11,7 @@ obj-$(CONFIG_$(SPL_)I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o
+ obj-$(CONFIG_$(SPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o
+
+ obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
++obj-$(CONFIG_SYS_I2C_AST) += ast_i2c.o
+ obj-$(CONFIG_I2C_MV) += mv_i2c.o
+ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
+ obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
+diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
+new file mode 100644
+index 0000000..533419f
+--- /dev/null
++++ b/drivers/i2c/ast_i2c.c
+@@ -0,0 +1,852 @@
++/*
++ * i2c_adap_ast.c
++ *
++ * I2C adapter for the ASPEED I2C bus access.
++ *
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * History:
++ * 2012.07.26: Initial version [Ryan Chen]
++ */
++
++#include <common.h>
++#include <configs/ast-common.h>
++#include <fdtdec.h>
++
++#include <asm/arch/ast_scu.h>
++#include <i2c.h>
++
++#include <asm/arch/regs-iic.h>
++#include <asm/io.h>
++
++// AST2400 buffer mode issue , force I2C slave write use byte mode , read use
++// buffer mode
++/* Use platform_data instead of module parameters */
++/* Fast Mode = 400 kHz, Standard = 100 kHz */
++// static int clock = 100; /* Default: 100 kHz */
++
++/***************************************************************************/
++DECLARE_GLOBAL_DATA_PTR;
++
++#define I2C_TIMEOUT_COUNT 200
++#define I2C_SLEEP_US 1000
++
++static unsigned int i2c_bus_num __attribute__((section(".data")));
++
++/* Information about i2c controller */
++struct ast_i2c_bus {
++ u32 reg_base; /* virtual */
++ u32 speed;
++ u32 state; /* I2C xfer mode state matchine */
++ u16 addr; /* slave address */
++ u16 flags;
++ u16 a_len; /* msg length */
++ u8 *a_buf; /* pointer to msg data */
++ u16 d_len; /* msg length */
++ u8 *d_buf; /* pointer to msg data */
++};
++
++static struct ast_i2c_bus ast_i2c[NUM_BUS] __attribute__((section(".data")));
++
++struct ast_i2c_timing_table {
++ u32 divisor;
++ u32 timing;
++};
++
++static struct ast_i2c_timing_table i2c_timing_table[] = {
++#if defined(AST_SOC_G5)
++ /* Divisor : Base Clock : tCK High : tCK Low */
++ /* Divisor : [3:0] : [19:16]: [15:12] */
++ { 6, 0x77700300 | (0x0) | (0x2 << 16) | (0x2 << 12) },
++ { 7, 0x77700300 | (0x0) | (0x3 << 16) | (0x2 << 12) },
++ { 8, 0x77700300 | (0x0) | (0x3 << 16) | (0x3 << 12) },
++ { 9, 0x77700300 | (0x0) | (0x4 << 16) | (0x3 << 12) },
++ { 10, 0x77700300 | (0x0) | (0x4 << 16) | (0x4 << 12) },
++ { 11, 0x77700300 | (0x0) | (0x5 << 16) | (0x4 << 12) },
++ { 12, 0x77700300 | (0x0) | (0x5 << 16) | (0x5 << 12) },
++ { 13, 0x77700300 | (0x0) | (0x6 << 16) | (0x5 << 12) },
++ { 14, 0x77700300 | (0x0) | (0x6 << 16) | (0x6 << 12) },
++ { 15, 0x77700300 | (0x0) | (0x7 << 16) | (0x6 << 12) },
++ { 16, 0x77700300 | (0x0) | (0x7 << 16) | (0x7 << 12) },
++ { 17, 0x77700300 | (0x0) | (0x8 << 16) | (0x7 << 12) },
++ { 18, 0x77700300 | (0x0) | (0x8 << 16) | (0x8 << 12) },
++ { 19, 0x77700300 | (0x0) | (0x9 << 16) | (0x8 << 12) },
++ { 20, 0x77700300 | (0x0) | (0x9 << 16) | (0x9 << 12) },
++ { 21, 0x77700300 | (0x0) | (0xa << 16) | (0x9 << 12) },
++ { 22, 0x77700300 | (0x0) | (0xa << 16) | (0xa << 12) },
++ { 23, 0x77700300 | (0x0) | (0xb << 16) | (0xa << 12) },
++ { 24, 0x77700300 | (0x0) | (0xb << 16) | (0xb << 12) },
++ { 25, 0x77700300 | (0x0) | (0xc << 16) | (0xb << 12) },
++ { 26, 0x77700300 | (0x0) | (0xc << 16) | (0xc << 12) },
++ { 27, 0x77700300 | (0x0) | (0xd << 16) | (0xc << 12) },
++ { 28, 0x77700300 | (0x0) | (0xd << 16) | (0xd << 12) },
++ { 29, 0x77700300 | (0x0) | (0xe << 16) | (0xd << 12) },
++ { 30, 0x77700300 | (0x0) | (0xe << 16) | (0xe << 12) },
++ { 31, 0x77700300 | (0x0) | (0xf << 16) | (0xe << 12) },
++ { 32, 0x77700300 | (0x0) | (0xf << 16) | (0xf << 12) },
++
++ { 34, 0x77700300 | (0x1) | (0x8 << 16) | (0x7 << 12) },
++ { 36, 0x77700300 | (0x1) | (0x8 << 16) | (0x8 << 12) },
++ { 38, 0x77700300 | (0x1) | (0x9 << 16) | (0x8 << 12) },
++ { 40, 0x77700300 | (0x1) | (0x9 << 16) | (0x9 << 12) },
++ { 42, 0x77700300 | (0x1) | (0xa << 16) | (0x9 << 12) },
++ { 44, 0x77700300 | (0x1) | (0xa << 16) | (0xa << 12) },
++ { 46, 0x77700300 | (0x1) | (0xb << 16) | (0xa << 12) },
++ { 48, 0x77700300 | (0x1) | (0xb << 16) | (0xb << 12) },
++ { 50, 0x77700300 | (0x1) | (0xc << 16) | (0xb << 12) },
++ { 52, 0x77700300 | (0x1) | (0xc << 16) | (0xc << 12) },
++ { 54, 0x77700300 | (0x1) | (0xd << 16) | (0xc << 12) },
++ { 56, 0x77700300 | (0x1) | (0xd << 16) | (0xd << 12) },
++ { 58, 0x77700300 | (0x1) | (0xe << 16) | (0xd << 12) },
++ { 60, 0x77700300 | (0x1) | (0xe << 16) | (0xe << 12) },
++ { 62, 0x77700300 | (0x1) | (0xf << 16) | (0xe << 12) },
++ { 64, 0x77700300 | (0x1) | (0xf << 16) | (0xf << 12) },
++
++ { 68, 0x77700300 | (0x2) | (0x8 << 16) | (0x7 << 12) },
++ { 72, 0x77700300 | (0x2) | (0x8 << 16) | (0x8 << 12) },
++ { 76, 0x77700300 | (0x2) | (0x9 << 16) | (0x8 << 12) },
++ { 80, 0x77700300 | (0x2) | (0x9 << 16) | (0x9 << 12) },
++ { 84, 0x77700300 | (0x2) | (0xa << 16) | (0x9 << 12) },
++ { 88, 0x77700300 | (0x2) | (0xa << 16) | (0xa << 12) },
++ { 92, 0x77700300 | (0x2) | (0xb << 16) | (0xa << 12) },
++ { 96, 0x77700300 | (0x2) | (0xb << 16) | (0xb << 12) },
++ { 100, 0x77700300 | (0x2) | (0xc << 16) | (0xb << 12) },
++ { 104, 0x77700300 | (0x2) | (0xc << 16) | (0xc << 12) },
++ { 108, 0x77700300 | (0x2) | (0xd << 16) | (0xc << 12) },
++ { 112, 0x77700300 | (0x2) | (0xd << 16) | (0xd << 12) },
++ { 116, 0x77700300 | (0x2) | (0xe << 16) | (0xd << 12) },
++ { 120, 0x77700300 | (0x2) | (0xe << 16) | (0xe << 12) },
++ { 124, 0x77700300 | (0x2) | (0xf << 16) | (0xe << 12) },
++ { 128, 0x77700300 | (0x2) | (0xf << 16) | (0xf << 12) },
++
++ { 136, 0x77700300 | (0x3) | (0x8 << 16) | (0x7 << 12) },
++ { 144, 0x77700300 | (0x3) | (0x8 << 16) | (0x8 << 12) },
++ { 152, 0x77700300 | (0x3) | (0x9 << 16) | (0x8 << 12) },
++ { 160, 0x77700300 | (0x3) | (0x9 << 16) | (0x9 << 12) },
++ { 168, 0x77700300 | (0x3) | (0xa << 16) | (0x9 << 12) },
++ { 176, 0x77700300 | (0x3) | (0xa << 16) | (0xa << 12) },
++ { 184, 0x77700300 | (0x3) | (0xb << 16) | (0xa << 12) },
++ { 192, 0x77700300 | (0x3) | (0xb << 16) | (0xb << 12) },
++ { 200, 0x77700300 | (0x3) | (0xc << 16) | (0xb << 12) },
++ { 208, 0x77700300 | (0x3) | (0xc << 16) | (0xc << 12) },
++ { 216, 0x77700300 | (0x3) | (0xd << 16) | (0xc << 12) },
++ { 224, 0x77700300 | (0x3) | (0xd << 16) | (0xd << 12) },
++ { 232, 0x77700300 | (0x3) | (0xe << 16) | (0xd << 12) },
++ { 240, 0x77700300 | (0x3) | (0xe << 16) | (0xe << 12) },
++ { 248, 0x77700300 | (0x3) | (0xf << 16) | (0xe << 12) },
++ { 256, 0x77700300 | (0x3) | (0xf << 16) | (0xf << 12) },
++
++ { 272, 0x77700300 | (0x4) | (0x8 << 16) | (0x7 << 12) },
++ { 288, 0x77700300 | (0x4) | (0x8 << 16) | (0x8 << 12) },
++ { 304, 0x77700300 | (0x4) | (0x9 << 16) | (0x8 << 12) },
++ { 320, 0x77700300 | (0x4) | (0x9 << 16) | (0x9 << 12) },
++ { 336, 0x77700300 | (0x4) | (0xa << 16) | (0x9 << 12) },
++ { 352, 0x77700300 | (0x4) | (0xa << 16) | (0xa << 12) },
++ { 368, 0x77700300 | (0x4) | (0xb << 16) | (0xa << 12) },
++ { 384, 0x77700300 | (0x4) | (0xb << 16) | (0xb << 12) },
++ { 400, 0x77700300 | (0x4) | (0xc << 16) | (0xb << 12) },
++ { 416, 0x77700300 | (0x4) | (0xc << 16) | (0xc << 12) },
++ { 432, 0x77700300 | (0x4) | (0xd << 16) | (0xc << 12) },
++ { 448, 0x77700300 | (0x4) | (0xd << 16) | (0xd << 12) },
++ { 464, 0x77700300 | (0x4) | (0xe << 16) | (0xd << 12) },
++ { 480, 0x77700300 | (0x4) | (0xe << 16) | (0xe << 12) },
++ { 496, 0x77700300 | (0x4) | (0xf << 16) | (0xe << 12) },
++ { 512, 0x77700300 | (0x4) | (0xf << 16) | (0xf << 12) },
++
++ { 544, 0x77700300 | (0x5) | (0x8 << 16) | (0x7 << 12) },
++ { 576, 0x77700300 | (0x5) | (0x8 << 16) | (0x8 << 12) },
++ { 608, 0x77700300 | (0x5) | (0x9 << 16) | (0x8 << 12) },
++ { 640, 0x77700300 | (0x5) | (0x9 << 16) | (0x9 << 12) },
++ { 672, 0x77700300 | (0x5) | (0xa << 16) | (0x9 << 12) },
++ { 704, 0x77700300 | (0x5) | (0xa << 16) | (0xa << 12) },
++ { 736, 0x77700300 | (0x5) | (0xb << 16) | (0xa << 12) },
++ { 768, 0x77700300 | (0x5) | (0xb << 16) | (0xb << 12) },
++ { 800, 0x77700300 | (0x5) | (0xc << 16) | (0xb << 12) },
++ { 832, 0x77700300 | (0x5) | (0xc << 16) | (0xc << 12) },
++ { 864, 0x77700300 | (0x5) | (0xd << 16) | (0xc << 12) },
++ { 896, 0x77700300 | (0x5) | (0xd << 16) | (0xd << 12) },
++ { 928, 0x77700300 | (0x5) | (0xe << 16) | (0xd << 12) },
++ { 960, 0x77700300 | (0x5) | (0xe << 16) | (0xe << 12) },
++ { 992, 0x77700300 | (0x5) | (0xf << 16) | (0xe << 12) },
++ { 1024, 0x77700300 | (0x5) | (0xf << 16) | (0xf << 12) },
++
++ { 1088, 0x77700300 | (0x6) | (0x8 << 16) | (0x7 << 12) },
++ { 1152, 0x77700300 | (0x6) | (0x8 << 16) | (0x8 << 12) },
++ { 1216, 0x77700300 | (0x6) | (0x9 << 16) | (0x8 << 12) },
++ { 1280, 0x77700300 | (0x6) | (0x9 << 16) | (0x9 << 12) },
++ { 1344, 0x77700300 | (0x6) | (0xa << 16) | (0x9 << 12) },
++ { 1408, 0x77700300 | (0x6) | (0xa << 16) | (0xa << 12) },
++ { 1472, 0x77700300 | (0x6) | (0xb << 16) | (0xa << 12) },
++ { 1536, 0x77700300 | (0x6) | (0xb << 16) | (0xb << 12) },
++ { 1600, 0x77700300 | (0x6) | (0xc << 16) | (0xb << 12) },
++ { 1664, 0x77700300 | (0x6) | (0xc << 16) | (0xc << 12) },
++ { 1728, 0x77700300 | (0x6) | (0xd << 16) | (0xc << 12) },
++ { 1792, 0x77700300 | (0x6) | (0xd << 16) | (0xd << 12) },
++ { 1856, 0x77700300 | (0x6) | (0xe << 16) | (0xd << 12) },
++ { 1920, 0x77700300 | (0x6) | (0xe << 16) | (0xe << 12) },
++ { 1984, 0x77700300 | (0x6) | (0xf << 16) | (0xe << 12) },
++ { 2048, 0x77700300 | (0x6) | (0xf << 16) | (0xf << 12) },
++
++ { 2176, 0x77700300 | (0x7) | (0x8 << 16) | (0x7 << 12) },
++ { 2304, 0x77700300 | (0x7) | (0x8 << 16) | (0x8 << 12) },
++ { 2432, 0x77700300 | (0x7) | (0x9 << 16) | (0x8 << 12) },
++ { 2560, 0x77700300 | (0x7) | (0x9 << 16) | (0x9 << 12) },
++ { 2688, 0x77700300 | (0x7) | (0xa << 16) | (0x9 << 12) },
++ { 2816, 0x77700300 | (0x7) | (0xa << 16) | (0xa << 12) },
++ { 2944, 0x77700300 | (0x7) | (0xb << 16) | (0xa << 12) },
++ { 3072, 0x77700300 | (0x7) | (0xb << 16) | (0xb << 12) },
++#else
++ /* Divisor : [3:0] : [18:16]: [13:12] */
++ { 6, 0x77700300 | (0x0) | (0x2 << 16) | (0x2 << 12) },
++ { 7, 0x77700300 | (0x0) | (0x3 << 16) | (0x2 << 12) },
++ { 8, 0x77700300 | (0x0) | (0x3 << 16) | (0x3 << 12) },
++ { 9, 0x77700300 | (0x0) | (0x4 << 16) | (0x3 << 12) },
++ { 10, 0x77700300 | (0x0) | (0x4 << 16) | (0x4 << 12) },
++ { 11, 0x77700300 | (0x0) | (0x5 << 16) | (0x4 << 12) },
++ { 12, 0x77700300 | (0x0) | (0x5 << 16) | (0x5 << 12) },
++ { 13, 0x77700300 | (0x0) | (0x6 << 16) | (0x5 << 12) },
++ { 14, 0x77700300 | (0x0) | (0x6 << 16) | (0x6 << 12) },
++ { 15, 0x77700300 | (0x0) | (0x7 << 16) | (0x6 << 12) },
++ { 16, 0x77700300 | (0x0) | (0x7 << 16) | (0x7 << 12) },
++
++ { 18, 0x77700300 | (0x1) | (0x4 << 16) | (0x3 << 12) },
++ { 20, 0x77700300 | (0x1) | (0x4 << 16) | (0x4 << 12) },
++ { 22, 0x77700300 | (0x1) | (0x5 << 16) | (0x4 << 12) },
++ { 24, 0x77700300 | (0x1) | (0x5 << 16) | (0x5 << 12) },
++ { 26, 0x77700300 | (0x1) | (0x6 << 16) | (0x5 << 12) },
++ { 28, 0x77700300 | (0x1) | (0x6 << 16) | (0x6 << 12) },
++ { 30, 0x77700300 | (0x1) | (0x7 << 16) | (0x6 << 12) },
++ { 32, 0x77700300 | (0x1) | (0x7 << 16) | (0x7 << 12) },
++
++ { 36, 0x77700300 | (0x2) | (0x4 << 16) | (0x3 << 12) },
++ { 40, 0x77700300 | (0x2) | (0x4 << 16) | (0x4 << 12) },
++ { 44, 0x77700300 | (0x2) | (0x5 << 16) | (0x4 << 12) },
++ { 48, 0x77700300 | (0x2) | (0x5 << 16) | (0x5 << 12) },
++ { 52, 0x77700300 | (0x2) | (0x6 << 16) | (0x5 << 12) },
++ { 56, 0x77700300 | (0x2) | (0x6 << 16) | (0x6 << 12) },
++ { 60, 0x77700300 | (0x2) | (0x7 << 16) | (0x6 << 12) },
++ { 64, 0x77700300 | (0x2) | (0x7 << 16) | (0x7 << 12) },
++
++ { 72, 0x77700300 | (0x3) | (0x4 << 16) | (0x3 << 12) },
++ { 80, 0x77700300 | (0x3) | (0x4 << 16) | (0x4 << 12) },
++ { 88, 0x77700300 | (0x3) | (0x5 << 16) | (0x4 << 12) },
++ { 96, 0x77700300 | (0x3) | (0x5 << 16) | (0x5 << 12) },
++ { 104, 0x77700300 | (0x3) | (0x6 << 16) | (0x5 << 12) },
++ { 112, 0x77700300 | (0x3) | (0x6 << 16) | (0x6 << 12) },
++ { 120, 0x77700300 | (0x3) | (0x7 << 16) | (0x6 << 12) },
++ { 128, 0x77700300 | (0x3) | (0x7 << 16) | (0x7 << 12) },
++
++ { 144, 0x77700300 | (0x4) | (0x4 << 16) | (0x3 << 12) },
++ { 160, 0x77700300 | (0x4) | (0x4 << 16) | (0x4 << 12) },
++ { 176, 0x77700300 | (0x4) | (0x5 << 16) | (0x4 << 12) },
++ { 192, 0x77700300 | (0x4) | (0x5 << 16) | (0x5 << 12) },
++ { 208, 0x77700300 | (0x4) | (0x6 << 16) | (0x5 << 12) },
++ { 224, 0x77700300 | (0x4) | (0x6 << 16) | (0x6 << 12) },
++ { 240, 0x77700300 | (0x4) | (0x7 << 16) | (0x6 << 12) },
++ { 256, 0x77700300 | (0x4) | (0x7 << 16) | (0x7 << 12) },
++
++ { 288, 0x77700300 | (0x5) | (0x4 << 16) | (0x3 << 12) },
++ { 320, 0x77700300 | (0x5) | (0x4 << 16) | (0x4 << 12) },
++ { 352, 0x77700300 | (0x5) | (0x5 << 16) | (0x4 << 12) },
++ { 384, 0x77700300 | (0x5) | (0x5 << 16) | (0x5 << 12) },
++ { 416, 0x77700300 | (0x5) | (0x6 << 16) | (0x5 << 12) },
++ { 448, 0x77700300 | (0x5) | (0x6 << 16) | (0x6 << 12) },
++ { 480, 0x77700300 | (0x5) | (0x7 << 16) | (0x6 << 12) },
++ { 512, 0x77700300 | (0x5) | (0x7 << 16) | (0x7 << 12) },
++
++ { 576, 0x77700300 | (0x6) | (0x4 << 16) | (0x3 << 12) },
++ { 640, 0x77700300 | (0x6) | (0x4 << 16) | (0x4 << 12) },
++ { 704, 0x77700300 | (0x6) | (0x5 << 16) | (0x4 << 12) },
++ { 768, 0x77700300 | (0x6) | (0x5 << 16) | (0x5 << 12) },
++ { 832, 0x77700300 | (0x6) | (0x6 << 16) | (0x5 << 12) },
++ { 896, 0x77700300 | (0x6) | (0x6 << 16) | (0x6 << 12) },
++ { 960, 0x77700300 | (0x6) | (0x7 << 16) | (0x6 << 12) },
++ { 1024, 0x77700300 | (0x6) | (0x7 << 16) | (0x7 << 12) },
++
++ { 1152, 0x77700300 | (0x7) | (0x4 << 16) | (0x3 << 12) },
++ { 1280, 0x77700300 | (0x7) | (0x4 << 16) | (0x4 << 12) },
++ { 1408, 0x77700300 | (0x7) | (0x5 << 16) | (0x4 << 12) },
++ { 1536, 0x77700300 | (0x7) | (0x5 << 16) | (0x5 << 12) },
++ { 1664, 0x77700300 | (0x7) | (0x6 << 16) | (0x5 << 12) },
++ { 1792, 0x77700300 | (0x7) | (0x6 << 16) | (0x6 << 12) },
++ { 1920, 0x77700300 | (0x7) | (0x7 << 16) | (0x6 << 12) },
++ { 2048, 0x77700300 | (0x7) | (0x7 << 16) | (0x7 << 12) },
++
++ { 2304, 0x77700300 | (0x8) | (0x4 << 16) | (0x3 << 12) },
++ { 2560, 0x77700300 | (0x8) | (0x4 << 16) | (0x4 << 12) },
++ { 2816, 0x77700300 | (0x8) | (0x5 << 16) | (0x4 << 12) },
++ { 3072, 0x77700300 | (0x8) | (0x5 << 16) | (0x5 << 12) },
++ { 3328, 0x77700300 | (0x8) | (0x6 << 16) | (0x5 << 12) },
++ { 3584, 0x77700300 | (0x8) | (0x6 << 16) | (0x6 << 12) },
++ { 3840, 0x77700300 | (0x8) | (0x7 << 16) | (0x6 << 12) },
++ { 4096, 0x77700300 | (0x8) | (0x7 << 16) | (0x7 << 12) },
++
++ { 4608, 0x77700300 | (0x9) | (0x4 << 16) | (0x3 << 12) },
++ { 5120, 0x77700300 | (0x9) | (0x4 << 16) | (0x4 << 12) },
++ { 5632, 0x77700300 | (0x9) | (0x5 << 16) | (0x4 << 12) },
++ { 6144, 0x77700300 | (0x9) | (0x5 << 16) | (0x5 << 12) },
++ { 6656, 0x77700300 | (0x9) | (0x6 << 16) | (0x5 << 12) },
++ { 7168, 0x77700300 | (0x9) | (0x6 << 16) | (0x6 << 12) },
++ { 7680, 0x77700300 | (0x9) | (0x7 << 16) | (0x6 << 12) },
++ { 8192, 0x77700300 | (0x9) | (0x7 << 16) | (0x7 << 12) },
++
++ { 9216, 0x77700300 | (0xa) | (0x4 << 16) | (0x3 << 12) },
++ { 10240, 0x77700300 | (0xa) | (0x4 << 16) | (0x4 << 12) },
++ { 11264, 0x77700300 | (0xa) | (0x5 << 16) | (0x4 << 12) },
++ { 12288, 0x77700300 | (0xa) | (0x5 << 16) | (0x5 << 12) },
++ { 13312, 0x77700300 | (0xa) | (0x6 << 16) | (0x5 << 12) },
++ { 14336, 0x77700300 | (0xa) | (0x6 << 16) | (0x6 << 12) },
++ { 15360, 0x77700300 | (0xa) | (0x7 << 16) | (0x6 << 12) },
++ { 16384, 0x77700300 | (0xa) | (0x7 << 16) | (0x7 << 12) },
++
++ { 18432, 0x77700300 | (0xb) | (0x4 << 16) | (0x3 << 12) },
++ { 20480, 0x77700300 | (0xb) | (0x4 << 16) | (0x4 << 12) },
++ { 22528, 0x77700300 | (0xb) | (0x5 << 16) | (0x4 << 12) },
++ { 24576, 0x77700300 | (0xb) | (0x5 << 16) | (0x5 << 12) },
++ { 26624, 0x77700300 | (0xb) | (0x6 << 16) | (0x5 << 12) },
++ { 28672, 0x77700300 | (0xb) | (0x6 << 16) | (0x6 << 12) },
++ { 30720, 0x77700300 | (0xb) | (0x7 << 16) | (0x6 << 12) },
++ { 32768, 0x77700300 | (0xb) | (0x7 << 16) | (0x7 << 12) },
++
++ { 36864, 0x77700300 | (0xc) | (0x4 << 16) | (0x3 << 12) },
++ { 40960, 0x77700300 | (0xc) | (0x4 << 16) | (0x4 << 12) },
++ { 45056, 0x77700300 | (0xc) | (0x5 << 16) | (0x4 << 12) },
++ { 49152, 0x77700300 | (0xc) | (0x5 << 16) | (0x5 << 12) },
++ { 53248, 0x77700300 | (0xc) | (0x6 << 16) | (0x5 << 12) },
++ { 57344, 0x77700300 | (0xc) | (0x6 << 16) | (0x6 << 12) },
++ { 61440, 0x77700300 | (0xc) | (0x7 << 16) | (0x6 << 12) },
++ { 65536, 0x77700300 | (0xc) | (0x7 << 16) | (0x7 << 12) },
++
++ { 73728, 0x77700300 | (0xd) | (0x4 << 16) | (0x3 << 12) },
++ { 81920, 0x77700300 | (0xd) | (0x4 << 16) | (0x4 << 12) },
++ { 90112, 0x77700300 | (0xd) | (0x5 << 16) | (0x4 << 12) },
++ { 98304, 0x77700300 | (0xd) | (0x5 << 16) | (0x5 << 12) },
++ { 106496, 0x77700300 | (0xd) | (0x6 << 16) | (0x5 << 12) },
++ { 114688, 0x77700300 | (0xd) | (0x6 << 16) | (0x6 << 12) },
++ { 122880, 0x77700300 | (0xd) | (0x7 << 16) | (0x6 << 12) },
++ { 131072, 0x77700300 | (0xd) | (0x7 << 16) | (0x7 << 12) },
++
++ { 147456, 0x77700300 | (0xe) | (0x4 << 16) | (0x3 << 12) },
++ { 163840, 0x77700300 | (0xe) | (0x4 << 16) | (0x4 << 12) },
++ { 180224, 0x77700300 | (0xe) | (0x5 << 16) | (0x4 << 12) },
++ { 196608, 0x77700300 | (0xe) | (0x5 << 16) | (0x5 << 12) },
++ { 212992, 0x77700300 | (0xe) | (0x6 << 16) | (0x5 << 12) },
++ { 229376, 0x77700300 | (0xe) | (0x6 << 16) | (0x6 << 12) },
++ { 245760, 0x77700300 | (0xe) | (0x7 << 16) | (0x6 << 12) },
++ { 262144, 0x77700300 | (0xe) | (0x7 << 16) | (0x7 << 12) },
++
++ { 294912, 0x77700300 | (0xf) | (0x4 << 16) | (0x3 << 12) },
++ { 327680, 0x77700300 | (0xf) | (0x4 << 16) | (0x4 << 12) },
++ { 360448, 0x77700300 | (0xf) | (0x5 << 16) | (0x4 << 12) },
++ { 393216, 0x77700300 | (0xf) | (0x5 << 16) | (0x5 << 12) },
++ { 425984, 0x77700300 | (0xf) | (0x6 << 16) | (0x5 << 12) },
++ { 458752, 0x77700300 | (0xf) | (0x6 << 16) | (0x6 << 12) },
++ { 491520, 0x77700300 | (0xf) | (0x7 << 16) | (0x6 << 12) },
++ { 524288, 0x77700300 | (0xf) | (0x7 << 16) | (0x7 << 12) },
++#endif
++};
++
++static inline void ast_i2c_write(struct ast_i2c_bus *i2c_bus, u32 val, u32 reg)
++{
++#if 0
++ printf("%x: W : reg %x , val: %x\n", i2c_bus->reg_base, reg, val);
++#endif
++ __raw_writel(val, i2c_bus->reg_base + reg);
++}
++
++static inline u32 ast_i2c_read(struct ast_i2c_bus *i2c_bus, u32 reg)
++{
++#if 0
++ u32 val = __raw_readl(i2c_bus->reg_base + reg);
++ printf("%x: R : reg %x , val: %x\n", i2c_bus->reg_base, reg, val);
++ return val;
++#else
++ return __raw_readl(i2c_bus->reg_base + reg);
++#endif
++}
++
++static u32 select_i2c_clock(unsigned int bus_clk)
++{
++#if 0
++ unsigned int clk, inc = 0, div, divider_ratio;
++ u32 SCL_Low, SCL_High, data;
++
++ clk = ast_get_pclk();
++// debug("pclk = %d\n", clk);
++ divider_ratio = clk / bus_clk;
++ for (div = 0; divider_ratio >= 16; div++)
++ {
++ inc |= (divider_ratio & 1);
++ divider_ratio >>= 1;
++ }
++ divider_ratio += inc;
++ SCL_Low = (divider_ratio >> 1) - 1;
++ SCL_High = divider_ratio - SCL_Low - 2;
++ data = 0x77700300 | (SCL_High << 16) | (SCL_Low << 12) | div;
++// printk("I2CD04 for %d = %08X\n", target_speed, data);
++ return data;
++#else
++ int i;
++ unsigned int clk;
++ u32 data;
++
++ clk = ast_get_pclk();
++ // debug("pclk = %d\n", clk);
++
++ for (i = 0;
++ i < sizeof(i2c_timing_table) / sizeof(struct ast_i2c_timing_table);
++ i++) {
++ if ((clk / i2c_timing_table[i].divisor) < bus_clk) {
++ break;
++ }
++ }
++ data = i2c_timing_table[i].timing;
++ // printk("divisor [%d], timing [%x]\n", i2c_timing_table[i].divisor,
++ // i2c_timing_table[i].timing);
++ return data;
++#endif
++}
++
++static int ast_i2c_wait_isr(struct ast_i2c_bus *i2c_bus, u32 flag)
++{
++ int timeout = 0;
++
++ while (!(ast_i2c_read(i2c_bus, I2C_INTR_STS_REG) & flag) &&
++ (timeout < I2C_TIMEOUT_COUNT)) {
++ udelay(I2C_SLEEP_US);
++ timeout++;
++ }
++
++ /* Clear Interrupt */
++ ast_i2c_write(i2c_bus, 0xfffffff, I2C_INTR_STS_REG);
++
++ if (timeout >= I2C_TIMEOUT_COUNT) {
++ debug("%s timed out:- flag: %x\n", __func__, flag);
++ return -ETIMEDOUT;
++ }
++
++ return 0;
++}
++
++static int ast_i2c_wait_tx(struct ast_i2c_bus *i2c_bus)
++{
++ int sts;
++ int timeout = 0;
++ while (1) {
++ sts = ast_i2c_read(i2c_bus, I2C_INTR_STS_REG);
++
++ if (timeout > I2C_TIMEOUT_COUNT) {
++ /* I2C Reset */
++ debug("Timeout: Bus:%d, Addr:0x%02x\n", i2c_bus_num,
++ i2c_bus->addr);
++ ast_i2c_write(i2c_bus, 0, I2C_FUN_CTRL_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_MASTER_EN,
++ I2C_FUN_CTRL_REG);
++
++ return -ETIMEDOUT;
++ } else if (sts & AST_I2CD_INTR_STS_TX_NAK) {
++ ast_i2c_write(i2c_bus, AST_I2CD_INTR_STS_TX_NAK,
++ I2C_INTR_STS_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_STOP_CMD,
++ I2C_CMD_REG);
++ ast_i2c_wait_isr(i2c_bus,
++ AST_I2CD_INTR_STS_NORMAL_STOP);
++
++ return -EREMOTEIO;
++ } else if (sts & AST_I2CD_INTR_STS_TX_ACK) {
++ ast_i2c_write(i2c_bus, AST_I2CD_INTR_STS_TX_ACK,
++ I2C_INTR_STS_REG);
++ break;
++ } else {
++ timeout++;
++ }
++ udelay(I2C_SLEEP_US);
++ }
++
++ return 0;
++}
++
++static int ast_i2c_deblock(struct ast_i2c_bus *i2c_bus)
++{
++ u32 csr;
++ int ret = 0;
++
++ if ((csr = ast_i2c_read(i2c_bus, I2C_CMD_REG)) &
++ AST_I2CD_BUS_BUSY_STS) {
++ if ((csr & AST_I2CD_SDA_LINE_STS) &&
++ (csr & AST_I2CD_SCL_LINE_STS)) {
++ /* Bus idle */
++ debug("Bus(%d) idle\n", i2c_bus_num);
++ ret = 0;
++ } else if (csr & AST_I2CD_SDA_LINE_STS) {
++ /* send stop command */
++ debug("Unterminated TXN in (%x), sending stop...\n",
++ csr);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_STOP_CMD,
++ I2C_CMD_REG);
++ ret = ast_i2c_wait_isr(i2c_bus,
++ AST_I2CD_INTR_STS_NORMAL_STOP);
++ } else if (csr & AST_I2CD_SCL_LINE_STS) {
++ /* Possibly stuck slave */
++ debug("Bus stuck (%x), attempting recovery...\n", csr);
++ ast_i2c_write(i2c_bus, AST_I2CD_BUS_RECOVER_CMD_EN,
++ I2C_CMD_REG);
++ ret = ast_i2c_wait_isr(i2c_bus,
++ AST_I2CD_INTR_STS_BUS_RECOVER);
++ } else {
++ debug("Bus(%d) slave(0x%02x) busy. Reseting bus...\n",
++ i2c_bus_num, i2c_bus->addr);
++ ast_i2c_write(i2c_bus, 0, I2C_FUN_CTRL_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_MASTER_EN,
++ I2C_FUN_CTRL_REG);
++ ret = 0;
++ }
++ }
++
++ return ret;
++}
++
++static int ast_i2c_xfer(struct ast_i2c_bus *i2c_bus)
++{
++ int sts, i, ret = 0;
++
++ /* Clear Interrupt */
++ ast_i2c_write(i2c_bus, 0xfffffff, I2C_INTR_STS_REG);
++
++ /* Check for bus busy */
++ ret = ast_i2c_deblock(i2c_bus);
++ if (ret != 0)
++ return ret;
++
++ // first start
++ debug(" %sing %d byte%s %s 0x%02x\n", i2c_bus->flags ? "read" : "write",
++ i2c_bus->d_len, i2c_bus->d_len > 1 ? "s" : "",
++ i2c_bus->flags ? "from" : "to", i2c_bus->addr);
++
++ if (i2c_bus->flags) {
++ // READ
++ if (i2c_bus->a_len) {
++ // send start
++ ast_i2c_write(i2c_bus, (i2c_bus->addr << 1),
++ I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus,
++ AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD,
++ I2C_CMD_REG);
++
++ /* Wait for ACK */
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++
++ /* Send Offset */
++ for (i = 0; i < i2c_bus->a_len; i++) {
++ debug("offset [%x]\n", i2c_bus->a_buf[i]);
++ ast_i2c_write(i2c_bus, i2c_bus->a_buf[i],
++ I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_TX_CMD,
++ I2C_CMD_REG);
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++ }
++ }
++
++ // repeat-start
++ ast_i2c_write(i2c_bus, (i2c_bus->addr << 1) | 0x1,
++ I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD,
++ I2C_CMD_REG);
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++
++ for (i = 0; i < i2c_bus->d_len; i++) {
++ if (i == (i2c_bus->d_len - 1)) {
++ ast_i2c_write(i2c_bus,
++ AST_I2CD_M_RX_CMD |
++ AST_I2CD_M_S_RX_CMD_LAST,
++ I2C_CMD_REG);
++ } else {
++ ast_i2c_write(i2c_bus, AST_I2CD_M_RX_CMD,
++ I2C_CMD_REG);
++ }
++
++ ret = ast_i2c_wait_isr(i2c_bus,
++ AST_I2CD_INTR_STS_RX_DOWN);
++ if (ret != 0)
++ return ret;
++
++ i2c_bus->d_buf[i] =
++ (ast_i2c_read(i2c_bus, I2C_BYTE_BUF_REG) &
++ AST_I2CD_RX_BYTE_BUFFER) >>
++ 8;
++ }
++ ast_i2c_write(i2c_bus, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
++ ret = ast_i2c_wait_isr(i2c_bus, AST_I2CD_INTR_STS_NORMAL_STOP);
++ if (ret != 0)
++ return ret;
++
++ } else {
++ // Write
++ // send start
++ ast_i2c_write(i2c_bus, (i2c_bus->addr << 1), I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD,
++ I2C_CMD_REG);
++
++ /* Wait for ACK */
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++
++ /* Send Offset */
++ for (i = 0; i < i2c_bus->a_len; i++) {
++ debug("offset [%x]\n", i2c_bus->a_buf[i]);
++ ast_i2c_write(i2c_bus, i2c_bus->a_buf[i],
++ I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_TX_CMD, I2C_CMD_REG);
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++ }
++
++ /* Tx data */
++ for (i = 0; i < i2c_bus->d_len; i++) {
++ debug("Tx data [%x]\n", i2c_bus->d_buf[i]);
++ ast_i2c_write(i2c_bus, i2c_bus->d_buf[i],
++ I2C_BYTE_BUF_REG);
++ ast_i2c_write(i2c_bus, AST_I2CD_M_TX_CMD, I2C_CMD_REG);
++ ret = ast_i2c_wait_tx(i2c_bus);
++ if (ret != 0)
++ return ret;
++ }
++ ast_i2c_write(i2c_bus, AST_I2CD_M_STOP_CMD, I2C_CMD_REG);
++ ret = ast_i2c_wait_isr(i2c_bus, AST_I2CD_INTR_STS_NORMAL_STOP);
++ if (ret != 0)
++ return ret;
++ }
++
++ return 0;
++}
++
++/*****************************************************************************/
++
++unsigned int i2c_get_bus_speed(void)
++{
++ return ast_i2c[i2c_bus_num].speed;
++}
++
++int i2c_set_bus_speed(unsigned int speed)
++{
++ struct ast_i2c_bus *i2c_bus = &ast_i2c[i2c_bus_num];
++
++ /* Set AC Timing */
++ ast_i2c_write(i2c_bus, select_i2c_clock(speed), I2C_AC_TIMING_REG1);
++ ast_i2c_write(i2c_bus, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2);
++
++ i2c_bus->speed = speed;
++
++ return 0;
++}
++
++unsigned int i2c_get_base(int bus_no)
++{
++ switch (bus_no) {
++ case 0:
++ return AST_I2C_DEV0_BASE;
++ break;
++ case 1:
++ return AST_I2C_DEV1_BASE;
++ break;
++ case 2:
++ return AST_I2C_DEV2_BASE;
++ break;
++ case 3:
++ return AST_I2C_DEV3_BASE;
++ break;
++ case 4:
++ return AST_I2C_DEV4_BASE;
++ break;
++ case 5:
++ return AST_I2C_DEV5_BASE;
++ break;
++ case 6:
++ return AST_I2C_DEV6_BASE;
++ break;
++ case 7:
++ return AST_I2C_DEV7_BASE;
++ break;
++ case 8:
++ return AST_I2C_DEV8_BASE;
++ break;
++ case 9:
++ return AST_I2C_DEV9_BASE;
++ break;
++ case 10:
++ return AST_I2C_DEV10_BASE;
++ break;
++ case 11:
++ return AST_I2C_DEV11_BASE;
++ break;
++ case 12:
++ return AST_I2C_DEV12_BASE;
++ break;
++ case 13:
++ return AST_I2C_DEV13_BASE;
++ break;
++ default:
++ printf("i2c base error\n");
++ break;
++ };
++ return 0;
++}
++
++void i2c_init(int speed, int slaveaddr)
++{
++ int i = 0;
++ struct ast_i2c_bus *i2c_bus;
++
++ // SCU I2C Reset
++ ast_scu_init_i2c();
++
++ /* This will override the speed selected in the fdt for that port */
++ debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
++
++ for (i = 0; i < CONFIG_SYS_MAX_I2C_BUS; i++) {
++ i2c_bus = &ast_i2c[i];
++ i2c_bus->reg_base = i2c_get_base(i);
++
++ i2c_bus->speed = CONFIG_SYS_I2C_SPEED;
++ i2c_bus->state = 0;
++
++ // I2C Multi-Pin
++ ast_scu_multi_func_i2c(i);
++
++ // I2CG Reset
++ ast_i2c_write(i2c_bus, 0, I2C_FUN_CTRL_REG);
++
++ // Enable Master Mode
++ ast_i2c_write(i2c_bus, AST_I2CD_MASTER_EN, I2C_FUN_CTRL_REG);
++
++ // SLAVE mode enable
++#if 0
++ if (slaveaddr) {
++ ast_i2c_write(i2c_bus, slaveaddr, I2C_DEV_ADDR_REG);
++ ast_i2c_write(i2c_bus,
++ ast_i2c_read(i2c_bus, I2C_FUN_CTRL_REG) |
++ AST_I2CD_SLAVE_EN,
++ I2C_FUN_CTRL_REG);
++ }
++#endif
++
++ /* Set AC Timing */
++ i2c_set_bus_speed(speed);
++
++ // Clear Interrupt
++ ast_i2c_write(i2c_bus, 0xfffffff, I2C_INTR_STS_REG);
++
++ /* Set interrupt generation of I2C controller */
++ ast_i2c_write(i2c_bus, 0, I2C_INTR_CTRL_REG);
++ }
++
++ i2c_bus_num = 0;
++ debug("end\n");
++}
++
++/* Probe to see if a chip is present. */
++int i2c_probe(uchar addr)
++{
++ uchar a_buf[1] = { 0 };
++
++ struct ast_i2c_bus *i2c_bus = &ast_i2c[i2c_bus_num];
++
++ debug("i2c_probe[bus:%d]: addr=0x%x\n", i2c_bus_num, addr);
++
++ i2c_bus->addr = addr;
++ i2c_bus->flags = 1;
++ i2c_bus->a_len = 1;
++ i2c_bus->a_buf = (u8 *)&a_buf;
++ i2c_bus->d_len = 1;
++ i2c_bus->d_buf = (u8 *)&a_buf;
++
++ return ast_i2c_xfer(i2c_bus);
++}
++
++/* Read bytes */
++int i2c_read(uchar addr, uint offset, int alen, uchar *buffer, int len)
++{
++ uchar xoffset[4];
++ struct ast_i2c_bus *i2c_bus = &ast_i2c[i2c_bus_num];
++
++ debug("i2c_read[bus:%d]: addr=0x%x, offset=0x%x, alen=0x%x len=0x%x\n",
++ i2c_bus_num, addr, offset, alen, len);
++
++ if (alen > 4) {
++ debug("I2C read: addr len %d not supported\n", alen);
++ return 1;
++ }
++
++ if (alen > 0) {
++ xoffset[0] = (offset >> 24) & 0xFF;
++ xoffset[1] = (offset >> 16) & 0xFF;
++ xoffset[2] = (offset >> 8) & 0xFF;
++ xoffset[3] = offset & 0xFF;
++ }
++
++ i2c_bus->addr = addr;
++ i2c_bus->flags = 1;
++ i2c_bus->a_len = alen;
++ i2c_bus->a_buf = &xoffset[4 - alen];
++ i2c_bus->d_len = len;
++ i2c_bus->d_buf = buffer;
++
++ return ast_i2c_xfer(i2c_bus);
++}
++
++/* Write bytes */
++int i2c_write(uchar addr, uint offset, int alen, uchar *buffer, int len)
++{
++ uchar xoffset[4];
++ struct ast_i2c_bus *i2c_bus = &ast_i2c[i2c_bus_num];
++
++ debug("i2c_write[bus:%d]: addr=0x%x, offset=0x%x, alen=0x%x len=0x%x\n",
++ i2c_bus_num, addr, offset, alen, len);
++
++ if (alen > 0) {
++ xoffset[0] = (offset >> 24) & 0xFF;
++ xoffset[1] = (offset >> 16) & 0xFF;
++ xoffset[2] = (offset >> 8) & 0xFF;
++ xoffset[3] = offset & 0xFF;
++ }
++
++ i2c_bus->addr = addr;
++ i2c_bus->flags = 0;
++ i2c_bus->a_len = alen;
++ i2c_bus->a_buf = &xoffset[4 - alen];
++ i2c_bus->d_len = len;
++ i2c_bus->d_buf = buffer;
++
++ return ast_i2c_xfer(i2c_bus);
++}
++
++#if defined(CONFIG_I2C_MULTI_BUS)
++/*
++ * Functions for multiple I2C bus handling
++ */
++unsigned int i2c_get_bus_num(void)
++{
++ return i2c_bus_num;
++}
++
++int i2c_set_bus_num(unsigned int bus)
++{
++ if (bus >= NUM_BUS)
++ return -1;
++ i2c_bus_num = bus;
++
++ return 0;
++}
++#endif
+diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
+new file mode 100644
+index 0000000..7cff0e5
+--- /dev/null
++++ b/drivers/i2c/ast_i2c.h
+@@ -0,0 +1,131 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ * Copyright 2016 IBM Corporation
++ * Copyright 2017 Google, Inc.
++ */
++#ifndef __AST_I2C_H_
++#define __AST_I2C_H_
++
++struct ast_i2c_regs {
++ u32 fcr;
++ u32 cactcr1;
++ u32 cactcr2;
++ u32 icr;
++ u32 isr;
++ u32 csr;
++ u32 sdar;
++ u32 pbcr;
++ u32 trbbr;
++#ifdef CONFIG_ASPEED_AST2500
++ u32 dma_mbar;
++ u32 dma_tlr;
++#endif
++};
++
++/* Device Register Definition */
++/* 0x00 : I2CD Function Control Register */
++#define I2CD_BUFF_SEL_MASK (0x7 << 20)
++#define I2CD_BUFF_SEL(x) (x << 20)
++#define I2CD_M_SDA_LOCK_EN (0x1 << 16)
++#define I2CD_MULTI_MASTER_DIS (0x1 << 15)
++#define I2CD_M_SCL_DRIVE_EN (0x1 << 14)
++#define I2CD_MSB_STS (0x1 << 9)
++#define I2CD_SDA_DRIVE_1T_EN (0x1 << 8)
++#define I2CD_M_SDA_DRIVE_1T_EN (0x1 << 7)
++#define I2CD_M_HIGH_SPEED_EN (0x1 << 6)
++#define I2CD_DEF_ADDR_EN (0x1 << 5)
++#define I2CD_DEF_ALERT_EN (0x1 << 4)
++#define I2CD_DEF_ARP_EN (0x1 << 3)
++#define I2CD_DEF_GCALL_EN (0x1 << 2)
++#define I2CD_SLAVE_EN (0x1 << 1)
++#define I2CD_MASTER_EN (0x1)
++
++/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
++/* Base register value. These bits are always set by the driver. */
++#define I2CD_CACTC_BASE 0xfff00300
++#define I2CD_TCKHIGH_SHIFT 16
++#define I2CD_TCKLOW_SHIFT 12
++#define I2CD_THDDAT_SHIFT 10
++#define I2CD_TO_DIV_SHIFT 8
++#define I2CD_BASE_DIV_SHIFT 0
++
++/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
++#define I2CD_tTIMEOUT 1
++#define I2CD_NO_TIMEOUT_CTRL 0
++
++/* 0x0c : I2CD Interrupt Control Register &
++ * 0x10 : I2CD Interrupt Status Register
++ *
++ * These share bit definitions, so use the same values for the enable &
++ * status bits.
++ */
++#define I2CD_INTR_SDA_DL_TIMEOUT (0x1 << 14)
++#define I2CD_INTR_BUS_RECOVER_DONE (0x1 << 13)
++#define I2CD_INTR_SMBUS_ALERT (0x1 << 12)
++#define I2CD_INTR_SMBUS_ARP_ADDR (0x1 << 11)
++#define I2CD_INTR_SMBUS_DEV_ALERT_ADDR (0x1 << 10)
++#define I2CD_INTR_SMBUS_DEF_ADDR (0x1 << 9)
++#define I2CD_INTR_GCALL_ADDR (0x1 << 8)
++#define I2CD_INTR_SLAVE_MATCH (0x1 << 7)
++#define I2CD_INTR_SCL_TIMEOUT (0x1 << 6)
++#define I2CD_INTR_ABNORMAL (0x1 << 5)
++#define I2CD_INTR_NORMAL_STOP (0x1 << 4)
++#define I2CD_INTR_ARBIT_LOSS (0x1 << 3)
++#define I2CD_INTR_RX_DONE (0x1 << 2)
++#define I2CD_INTR_TX_NAK (0x1 << 1)
++#define I2CD_INTR_TX_ACK (0x1 << 0)
++
++/* 0x14 : I2CD Command/Status Register */
++#define I2CD_SDA_OE (0x1 << 28)
++#define I2CD_SDA_O (0x1 << 27)
++#define I2CD_SCL_OE (0x1 << 26)
++#define I2CD_SCL_O (0x1 << 25)
++#define I2CD_TX_TIMING (0x1 << 24)
++#define I2CD_TX_STATUS (0x1 << 23)
++
++/* Tx State Machine */
++#define I2CD_IDLE 0x0
++#define I2CD_MACTIVE 0x8
++#define I2CD_MSTART 0x9
++#define I2CD_MSTARTR 0xa
++#define I2CD_MSTOP 0xb
++#define I2CD_MTXD 0xc
++#define I2CD_MRXACK 0xd
++#define I2CD_MRXD 0xe
++#define I2CD_MTXACK 0xf
++#define I2CD_SWAIT 0x1
++#define I2CD_SRXD 0x4
++#define I2CD_STXACK 0x5
++#define I2CD_STXD 0x6
++#define I2CD_SRXACK 0x7
++#define I2CD_RECOVER 0x3
++
++#define I2CD_SCL_LINE_STS (0x1 << 18)
++#define I2CD_SDA_LINE_STS (0x1 << 17)
++#define I2CD_BUS_BUSY_STS (0x1 << 16)
++#define I2CD_SDA_OE_OUT_DIR (0x1 << 15)
++#define I2CD_SDA_O_OUT_DIR (0x1 << 14)
++#define I2CD_SCL_OE_OUT_DIR (0x1 << 13)
++#define I2CD_SCL_O_OUT_DIR (0x1 << 12)
++#define I2CD_BUS_RECOVER_CMD (0x1 << 11)
++#define I2CD_S_ALT_EN (0x1 << 10)
++#define I2CD_RX_DMA_ENABLE (0x1 << 9)
++#define I2CD_TX_DMA_ENABLE (0x1 << 8)
++
++/* Command Bit */
++#define I2CD_RX_BUFF_ENABLE (0x1 << 7)
++#define I2CD_TX_BUFF_ENABLE (0x1 << 6)
++#define I2CD_M_STOP_CMD (0x1 << 5)
++#define I2CD_M_S_RX_CMD_LAST (0x1 << 4)
++#define I2CD_M_RX_CMD (0x1 << 3)
++#define I2CD_S_TX_CMD (0x1 << 2)
++#define I2CD_M_TX_CMD (0x1 << 1)
++#define I2CD_M_START_CMD 0x1
++
++#define I2CD_RX_DATA_SHIFT 8
++#define I2CD_RX_DATA_MASK (0xff << I2CD_RX_DATA_SHIFT)
++
++#define I2C_HIGHSPEED_RATE 400000
++
++#endif /* __AST_I2C_H_ */
+diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h
+index b7d7192..0bc7f2d 100644
+--- a/include/configs/ast-common.h
++++ b/include/configs/ast-common.h
+@@ -84,6 +84,11 @@
+ #define CONFIG_SYS_MAXARGS 16
+ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
++/* I2C config */
++#define CONFIG_I2C_MULTI_BUS 1
++#define CONFIG_SYS_MAX_I2C_BUS 8
++#define CONFIG_SYS_I2C_SPEED 100000
++
+ /*
+ * Optional MTD and UBI support
+ */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch
new file mode 100644
index 000000000..ac458dd6c
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch
@@ -0,0 +1,302 @@
+From 0083904a79527cef9ca99e516ed015b56a6b95c7 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 7 May 2019 11:26:35 +0530
+Subject: [PATCH] CPLD u-boot commands support for PFR
+
+Implemented the cpld command in u-boot for
+communicating with PFR CPLD.
+
+Tested:
+Simulated test on different I2C bus and slave
+as we don't have hardware available yet.
+ast# cpld dump
+*** Dumping CPLD Registers ***
+0x0000 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+----------------------------------------------------------
+0x0000 | 03 00 00 00 01 09 00 f5 01 09 19 cb 46 4c 45 --
+0x0001 | -- 52 4f 4e 49 43 53 cf 53 2d 31 31 30 30 41 44
+0x0002 | 55 -- 30 2d 32 30 31 ca 47 38 34 30 32 -- 2d --
+0x0003 | 30 37 c2 30 31 cc 45 58 57 44 36 34 39 30 30 38
+.............................
+ast# cpld read 0x00
+CPLD read successful. Reg:0x00 Val:0x03
+ast# cpld write 0x00 0x04
+CPLD write successful. Reg:0x00 Val:0x04
+ast# cpld read 0x00
+CPLD read successful. Reg:0x00 Val:0x04
+ast#
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ cmd/Makefile | 1 +
+ cmd/cpld.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 245 insertions(+)
+ create mode 100644 cmd/cpld.c
+
+diff --git a/cmd/Makefile b/cmd/Makefile
+index a1731be701..c8ac0af55c 100644
+--- a/cmd/Makefile
++++ b/cmd/Makefile
+@@ -66,6 +66,7 @@ obj-$(CONFIG_CMD_FUSE) += fuse.o
+ obj-$(CONFIG_CMD_GETTIME) += gettime.o
+ obj-$(CONFIG_CMD_GPIO) += gpio.o
+ obj-$(CONFIG_CMD_I2C) += i2c.o
++obj-$(CONFIG_CMD_I2C) += cpld.o
+ obj-$(CONFIG_CMD_IOTRACE) += iotrace.o
+ obj-$(CONFIG_CMD_HASH) += hash.o
+ obj-$(CONFIG_CMD_IDE) += ide.o
+diff --git a/cmd/cpld.c b/cmd/cpld.c
+new file mode 100644
+index 0000000000..1b225d20dc
+--- /dev/null
++++ b/cmd/cpld.c
+@@ -0,0 +1,244 @@
++/*
++ * Copyright (c) 2018-2019 Intel Corporation
++ * Written by AppaRao Puli <apparao.puli@intel.com>
++ *
++ * SPDX-License-Identifier: GPL-2.0+
++ */
++
++#include <common.h>
++#include <command.h>
++#include <cli.h>
++#include <i2c.h>
++#include <errno.h>
++#include <linux/compiler.h>
++
++#define PFR_CPLD_I2C_BUSNO 4
++#define PFR_CPLD_SLAVE_ADDR 0x70
++
++#define CPLD_READ_TIMEOUT_ATTEMPTS 5
++
++/* Some CPLD registers are self cleared after read.
++ * We should skip them reading to avoid functionality impact.*/
++/* TODO: Need to get this list from CPLD team. */
++static uchar cpld_reg_skip_read[] = {};
++
++static bool skip_cpld_reg_read(u32 reg)
++{
++ int size = ARRAY_SIZE(cpld_reg_skip_read);
++ for (int i = 0; i < size; i++) {
++ if (reg == cpld_reg_skip_read[i])
++ return true;
++ }
++
++ return false;
++}
++
++static int do_cpld_write(cmd_tbl_t *cmdtp, int flag, int argc,
++ char *const argv[])
++{
++ int ret = 0;
++ int current_bus_no;
++ u32 reg_addr;
++ uchar value;
++ int chip = (PFR_CPLD_SLAVE_ADDR >> 1);
++
++ if (argc != 3)
++ return CMD_RET_USAGE;
++
++ reg_addr = simple_strtoul(argv[1], NULL, 16);
++ if (reg_addr > 0xFF) {
++ printf("Invalid register. Valid range[0x00-0xFF].");
++ return CMD_RET_FAILURE;
++ }
++ value = simple_strtoul(argv[2], NULL, 16);
++
++ /* Get current I2C bus number to restore later. */
++ current_bus_no = i2c_get_bus_num();
++
++ /* Set I2C bus number to PFR CPLD I2C bus. */
++ ret = i2c_set_bus_num(PFR_CPLD_I2C_BUSNO);
++ if (ret) {
++ printf("Failure changing bus number (%d)\n", ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++
++ ret = i2c_write(chip, reg_addr, 1, &value, 1);
++ if (ret) {
++ printf("Error writing the chip: %d\n", ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++
++ printf("CPLD write successful. Reg:0x%02x Val:0x%02x\n", reg_addr,
++ value);
++
++done:
++ /* Restore I2C bus number */
++ if (i2c_set_bus_num(current_bus_no))
++ printf("Error in restoring bus number.\n");
++
++ return ret;
++}
++
++static int do_cpld_read(cmd_tbl_t *cmdtp, int flag, int argc,
++ char *const argv[])
++{
++ int ret = 0;
++ int current_bus_no;
++ u32 reg_addr;
++ uchar value[1];
++ int chip = (PFR_CPLD_SLAVE_ADDR >> 1);
++
++ if (argc != 2)
++ return CMD_RET_USAGE;
++
++ reg_addr = simple_strtoul(argv[1], NULL, 16);
++ if (reg_addr > 0xFF) {
++ printf("Invalid register. Valid range[0x00-0xFF].");
++ return CMD_RET_FAILURE;
++ }
++
++ /* Get current I2C bus number to restore later. */
++ current_bus_no = i2c_get_bus_num();
++
++ /* Set I2C bus number to PFR CPLD I2C bus. */
++ ret = i2c_set_bus_num(PFR_CPLD_I2C_BUSNO);
++ if (ret) {
++ printf("Failure changing bus number (%d)\n", ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++
++ if (skip_cpld_reg_read(reg_addr)) {
++ printf("CPLD register(0x%02x) reading is not allowed.\n",
++ reg_addr);
++ ret = 0;
++ goto done;
++ }
++
++ ret = i2c_read(chip, reg_addr, 1, value, 1);
++ if (ret) {
++ printf("Error reading the chip: %d\n", ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++
++ printf("CPLD read successful. Reg:0x%02x Val:0x%02x\n", reg_addr,
++ value[0]);
++
++done:
++ /* Restore I2C bus number */
++ if (i2c_set_bus_num(current_bus_no))
++ printf("Error in restoring bus number.\n");
++
++ return ret;
++}
++
++static int do_cpld_dump(cmd_tbl_t *cmdtp, int flag, int argc,
++ char *const argv[])
++{
++ int ret = 0;
++ int current_bus_no;
++ u32 reg_addr = 0x00;
++ uchar value[1];
++ int chip = (PFR_CPLD_SLAVE_ADDR >> 1);
++
++ if (argc != 1)
++ return CMD_RET_USAGE;
++
++ /* Get current I2C bus number to restore later. */
++ current_bus_no = i2c_get_bus_num();
++
++ /* Set I2C bus number to PFR CPLD I2C bus. */
++ ret = i2c_set_bus_num(PFR_CPLD_I2C_BUSNO);
++ if (ret) {
++ printf("Failure changing bus number (%d)\n", ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++
++ printf("*** Dumping CPLD Registers ***\n", reg_addr, value);
++ printf("0x%04x | ", reg_addr);
++ for (int i = 0; i < 0x10; i++)
++ printf(" %02x", i);
++ printf("\n----------------------------------------------------------\n");
++
++ while (reg_addr <= 0xFF) {
++ if ((reg_addr % 16) == 0)
++ printf("0x%04x | ", (reg_addr / 16));
++
++ if (skip_cpld_reg_read(reg_addr)) {
++ printf(" --");
++ } else {
++ int timeout = 0;
++ while (i2c_read(chip, reg_addr, 1, value, 1) != 0) {
++ if (timeout++ >= CPLD_READ_TIMEOUT_ATTEMPTS) {
++ printf("\nERROR: Reading the chip: %d\n",
++ ret);
++ ret = CMD_RET_FAILURE;
++ goto done;
++ }
++ /* Need delay for I2C devices continous read */
++ mdelay(3 * timeout);
++ }
++ printf(" %02x", value[0]);
++ }
++
++ reg_addr++;
++ if ((reg_addr % 16) == 0)
++ printf("\n");
++ }
++
++done:
++ /* Restore I2C bus number */
++ if (i2c_set_bus_num(current_bus_no))
++ printf("Error in restoring bus number.\n");
++
++ return ret;
++}
++static cmd_tbl_t cmd_cpld_sub[] = {
++ U_BOOT_CMD_MKENT(dump, 1, 1, do_cpld_dump, "", ""),
++ U_BOOT_CMD_MKENT(read, 2, 1, do_cpld_read, "", ""),
++ U_BOOT_CMD_MKENT(write, 3, 1, do_cpld_write, "", "")
++};
++
++/**
++ * do_cpld() - Handle the "cpld" command-line command
++ * @cmdtp: Command data struct pointer
++ * @flag: Command flag
++ * @argc: Command-line argument count
++ * @argv: Array of command-line arguments
++ *
++ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
++ * on error.
++ */
++static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
++{
++ cmd_tbl_t *c = NULL;
++
++ if (argc < 2)
++ return CMD_RET_USAGE;
++
++ /* Strip off leading 'cpld' command argument */
++ argc--;
++ argv++;
++
++ if (argc)
++ c = find_cmd_tbl(argv[0], cmd_cpld_sub,
++ ARRAY_SIZE(cmd_cpld_sub));
++
++ if (c)
++ return c->cmd(cmdtp, flag, argc, argv);
++ else
++ return CMD_RET_USAGE;
++}
++
++#ifdef CONFIG_SYS_LONGHELP
++static char cpld_help_text[] =
++ "cpld dump - Dump all CPLD registers.\n"
++ "cpld read <reg> - Read CPLD register.\n"
++ "cpld write <reg> <val> - Write CPLD register.\n";
++#endif
++
++U_BOOT_CMD(cpld, 4, 1, do_cpld, "PFR CPLD information", cpld_help_text);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch
new file mode 100644
index 000000000..0113fc3fe
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch
@@ -0,0 +1,59 @@
+From 41c08f1fcb5fa0b07ea541fc3d8bc322ddf8701d Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 13 May 2019 23:49:02 +0530
+Subject: [PATCH] Enabling uart1&uart2 in u-boot for BIOS messages
+
+Added uart init function in u-boot aspeed code
+to enable uart1 and uart2 for BIOS serial messages.
+
+Tested:
+Forced BMC to stop in u-boot( using Force Firmware Update
+Jumper), AC cycled system for multiple times, booted system
+to uefi, checked bios serial logs working fine and accessed
+keyboard in uefi without any issues.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 812e3ef..e68ab85 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -453,6 +453,26 @@ void ast_g5_intel_late_init(void)
+ update_bootargs_cmd("special", NULL);
+ }
+
++static void uart_init(void)
++{
++ u32 val;
++
++ /* Enable UART1 and UART2 for BIOS messages */
++ val = ast_scu_read(AST_SCU_FUN_PIN_CTRL2);
++
++ /* UART1 */
++ val |= (SCU_FUN_PIN_UART1_NCTS | SCU_FUN_PIN_UART1_NDCD |
++ SCU_FUN_PIN_UART1_NDSR | SCU_FUN_PIN_UART1_NRI |
++ SCU_FUN_PIN_UART1_NDTR | SCU_FUN_PIN_UART1_NRTS |
++ SCU_FUN_PIN_UART1_TXD | SCU_FUN_PIN_UART1_RXD);
++ /* UART2 */
++ val |= (SCU_FUN_PIN_UART2_NCTS | SCU_FUN_PIN_UART2_NDCD |
++ SCU_FUN_PIN_UART2_NDSR | SCU_FUN_PIN_UART2_NRI |
++ SCU_FUN_PIN_UART2_NDTR | SCU_FUN_PIN_UART2_NRTS |
++ SCU_FUN_PIN_UART2_TXD | SCU_FUN_PIN_UART2_RXD);
++ ast_scu_write(val, AST_SCU_FUN_PIN_CTRL2);
++}
++
+ static void pwm_init(void)
+ {
+ uint32_t val;
+@@ -521,6 +541,7 @@ extern void espi_init(void);
+ extern void kcs_init(void);
+ void ast_g5_intel(void)
+ {
++ uart_init();
+ pwm_init();
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+ espi_init();
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch
new file mode 100644
index 000000000..3c21a7c0a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch
@@ -0,0 +1,1273 @@
+From 0f64b0e0c0a122ce23b5ccc518f514ec296bc7f5 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 21 May 2019 00:53:04 +0530
+Subject: [PATCH] FFUJ: FW IPMI commands and flash support in u-boot
+
+Firmware update and OEM ipmi commands implementation
+for supporting Force Firmware Update Jumper(FFUJ)
+mode. Also added support to update the fit images
+in FFUJ mode.
+
+Firmware update commands:
+1) Get BMC Execution Context(0x23)
+2) Get Firmware Update Random Number(0x26)
+3) Set Firmware Update Mode(0x27)
+4) Exit Firmware Update Mode(0x28)
+5) Set/Get Firmware Update Control(0x29)
+6) Get Firmware Update status(0x2A)
+7) Set Firmware Update Options(0x2B)
+8) Firmware Image Write(0x2C)
+
+OEM Commands:
+1) Get Buffer Size(0x66)
+
+Tested:
+ - Used cmdtool.efi to test the individual commands
+ implementation and negative cases.
+ - Used debug fwpiaupd.efi tool for validating Firmware
+ image transfer via KCS and flashing.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ arch/arm/include/asm/arch-aspeed/ast-g5-intel.h | 1 +
+ board/aspeed/ast-g5/Makefile | 2 +
+ board/aspeed/ast-g5/fw-update.c | 486 ++++++++++++++++++++++++
+ board/aspeed/ast-g5/fw-update.h | 50 +++
+ board/aspeed/ast-g5/ipmi-fwupd.c | 402 ++++++++++++++++++++
+ board/aspeed/ast-g5/ipmi-fwupd.h | 81 ++++
+ board/aspeed/ast-g5/ipmi-handler.c | 66 +++-
+ board/aspeed/ast-g5/ipmi-handler.h | 3 +-
+ common/autoboot.c | 13 +
+ configs/ast_g5_phy_defconfig | 1 +
+ 10 files changed, 1093 insertions(+), 12 deletions(-)
+ create mode 100644 board/aspeed/ast-g5/fw-update.c
+ create mode 100644 board/aspeed/ast-g5/fw-update.h
+ create mode 100644 board/aspeed/ast-g5/ipmi-fwupd.c
+ create mode 100644 board/aspeed/ast-g5/ipmi-fwupd.h
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+index cd9a099..a88521a 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
++++ b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+@@ -14,6 +14,7 @@
+
+ #ifndef __ASSEMBLY__
+ int intel_force_firmware_jumper_enabled(void);
++void start_fw_update_loop(void);
+ #endif
+
+ #endif /* __AST_INTEL_G5_H__ */
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index f28fcfe..0b2d936 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -6,3 +6,5 @@ obj-y += ast-g5-gpio.o
+ obj-y += ast-g5-timer.o
+ obj-y += ast-g5-kcs.o
+ obj-y += ipmi-handler.o
++obj-y += ipmi-fwupd.o
++obj-y += fw-update.o
+diff --git a/board/aspeed/ast-g5/fw-update.c b/board/aspeed/ast-g5/fw-update.c
+new file mode 100644
+index 0000000..9923993
+--- /dev/null
++++ b/board/aspeed/ast-g5/fw-update.c
+@@ -0,0 +1,486 @@
++// SPDX-License-Identifier: GPL-2.0+
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include <common.h>
++#include <cli.h>
++#include <flash.h>
++
++#include "fw-update.h"
++
++#define BOOTCMD_BOOTM_STR "bootm "
++#define RANDOM_NUM_TIMEOUT 30 /* in seconds */
++#define WAIT_STATE_TIMEOUT 10000 /* 10 seconds */
++
++#define PROTECT_OFF 0
++#define PROTECT_ON 1
++
++extern struct fwupd_global_setting g_fwupd_settings;
++extern u32 g_write_addr;
++
++bool g_fwupd_settings_lock = false;
++unsigned long long etime;
++
++bool fwupd_settings_trylock(void)
++{
++ if (g_fwupd_settings_lock)
++ return false;
++
++ g_fwupd_settings_lock = true;
++ return g_fwupd_settings_lock;
++}
++
++void fwupd_settings_unlock(void)
++{
++ g_fwupd_settings_lock = false;
++}
++
++u8 get_active_boot_image(void)
++{
++ char *bootcmd = getenv("bootcmd");
++ char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR);
++ u8 boot_image = PRIMARY_IMAGE;
++
++ if (start) {
++ ulong boot_addr = simple_strtoul(
++ (start + strlen(BOOTCMD_BOOTM_STR)), NULL, 16);
++ if (boot_addr == SECONDARY_FITIMAGE_START_ADDR)
++ return SECONDARY_IMAGE;
++ }
++ return boot_image;
++}
++
++static ulong get_flash_image_address(void)
++{
++ char *bootcmd = getenv("bootcmd");
++ char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR);
++ ulong boot_addr = PRIMARY_FITIMAGE_START_ADDR;
++
++ if (start) {
++ boot_addr = simple_strtoul((start + strlen(BOOTCMD_BOOTM_STR)),
++ NULL, 16);
++ /* We update in backup region and set the bootcmd accordingly */
++ if (boot_addr == PRIMARY_FITIMAGE_START_ADDR)
++ boot_addr = SECONDARY_FITIMAGE_START_ADDR;
++ else
++ boot_addr = PRIMARY_FITIMAGE_START_ADDR;
++ }
++
++ return boot_addr;
++}
++
++static void update_processing_status(u8 status, u8 percent)
++{
++ if (!fwupd_settings_trylock())
++ return;
++
++ g_fwupd_settings.processing_status = status;
++ g_fwupd_settings.percentage_completion = percent;
++
++ fwupd_settings_unlock();
++ return;
++}
++
++static void reset_all_settings(void)
++{
++ if (!fwupd_settings_trylock())
++ return;
++
++ memset(&g_fwupd_settings, 0, sizeof(g_fwupd_settings));
++ g_fwupd_settings.fwupd_mode_active = false;
++ g_fwupd_settings.start_update = false;
++
++ fwupd_settings_unlock();
++}
++
++unsigned int get_seed(void)
++{
++ char seed_str[] = { "INTEL" };
++ unsigned int seed;
++
++ for (int i = 0; i < strlen(seed_str); i++)
++ seed += (seed_str[i] << (i * 8));
++
++ return seed;
++}
++
++int generate_random_number(void)
++{
++ srand(get_seed());
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ return -1;
++ }
++ for (int i = 0; i < RAND_NUMBER_SIZE; i++)
++ g_fwupd_settings.rand_num[i] = (u8)(rand() & 0xFF);
++
++ g_fwupd_settings.random_number_valid = true;
++
++ fwupd_settings_unlock();
++
++ /* Random number should be cleared after 30sec timeout */
++ etime = endtick(RANDOM_NUM_TIMEOUT);
++
++ return 0;
++}
++
++static int sect_roundb(ulong *addr)
++{
++ flash_info_t *info;
++ ulong bank, sector_end_addr;
++ char found;
++ int i;
++
++ /* find the end addr of the sector where the *addr is */
++ found = 0;
++ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS && !found; ++bank) {
++ info = &flash_info[bank];
++ for (i = 0; i < info->sector_count && !found; ++i) {
++ /* get the end address of the sector */
++ if (i == info->sector_count - 1) {
++ sector_end_addr =
++ info->start[0] + info->size - 1;
++ } else {
++ sector_end_addr = info->start[i + 1] - 1;
++ }
++
++ if (*addr <= sector_end_addr &&
++ *addr >= info->start[i]) {
++ found = 1;
++ /* adjust *addr if necessary */
++ if (*addr < sector_end_addr)
++ *addr = sector_end_addr;
++ } /* sector */
++ } /* bank */
++ }
++ if (!found) {
++ /* error, address not in flash */
++ printf("Error: end address (0x%08lx) not in flash!\n", *addr);
++ return 1;
++ }
++
++ return 0;
++}
++
++static int fill_flash_sect_ranges(ulong addr_first, ulong addr_last,
++ int *s_first, int *s_last, int *s_count)
++{
++ flash_info_t *info;
++ ulong bank;
++ int rcode = 0;
++
++ *s_count = 0;
++
++ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
++ s_first[bank] = -1; /* first sector to erase */
++ s_last[bank] = -1; /* last sector to erase */
++ }
++
++ for (bank = 0, info = &flash_info[0];
++ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (addr_first <= addr_last);
++ ++bank, ++info) {
++ ulong b_end;
++ int sect;
++ short s_end;
++
++ if (info->flash_id == FLASH_UNKNOWN)
++ continue;
++
++ b_end = info->start[0] + info->size - 1; /* bank end addr */
++ s_end = info->sector_count - 1; /* last sector */
++
++ for (sect = 0; sect < info->sector_count; ++sect) {
++ ulong end; /* last address in current sect */
++
++ end = (sect == s_end) ? b_end :
++ info->start[sect + 1] - 1;
++
++ if (addr_first > end)
++ continue;
++ if (addr_last < info->start[sect])
++ continue;
++
++ if (addr_first == info->start[sect])
++ s_first[bank] = sect;
++ if (addr_last == end)
++ s_last[bank] = sect;
++ }
++ if (s_first[bank] >= 0) {
++ if (s_last[bank] < 0) {
++ if (addr_last > b_end) {
++ s_last[bank] = s_end;
++ } else {
++ printf("Error: end address not on sector boundary\n");
++ rcode = 1;
++ break;
++ }
++ }
++ if (s_last[bank] < s_first[bank]) {
++ printf("Error: end sector precedes start sector\n");
++ rcode = 1;
++ break;
++ }
++ sect = s_last[bank];
++ addr_first = (sect == s_end) ? b_end + 1 :
++ info->start[sect + 1];
++ (*s_count) += s_last[bank] - s_first[bank] + 1;
++ } else if (addr_first >= info->start[0] && addr_first < b_end) {
++ printf("Error: start address not on sector boundary\n");
++ rcode = 1;
++ break;
++ } else if (s_last[bank] >= 0) {
++ printf("Error: cannot span across banks when they are mapped in reverse order\n");
++ rcode = 1;
++ break;
++ }
++ }
++
++ return rcode;
++}
++
++static int protect_flash_sector(int state, ulong addr_first, ulong addr_last)
++{
++ flash_info_t *info;
++ ulong bank;
++ int s_first[CONFIG_SYS_MAX_FLASH_BANKS],
++ s_last[CONFIG_SYS_MAX_FLASH_BANKS];
++ int protected = 0;
++ int planned;
++ int rcode, i;
++
++ rcode = fill_flash_sect_ranges(addr_first, addr_last, s_first, s_last,
++ &planned);
++
++ if (planned && (rcode == 0)) {
++ for (bank = 0, info = &flash_info[0];
++ bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
++ if (info->flash_id == FLASH_UNKNOWN)
++ continue;
++
++ if (s_first[bank] >= 0 &&
++ s_first[bank] <= s_last[bank]) {
++ debug("%sProtecting sectors %d..%d in bank %ld\n",
++ state ? "" : "Un-", s_first[bank],
++ s_last[bank], bank + 1);
++ protected
++ += s_last[bank] - s_first[bank] + 1;
++ for (i = s_first[bank]; i <= s_last[bank]; ++i)
++ info->protect[i] = state;
++ }
++ }
++ printf("%sProtected %d sectors\n", state ? "" : "Un-",
++ protected);
++ } else if (rcode == 0) {
++ printf("Error: start and/or end address not on sector boundary\n");
++ rcode = 1;
++ }
++
++ return rcode;
++}
++
++static int erase_flash_sector(ulong addr_first, ulong addr_last)
++{
++ flash_info_t *info;
++ ulong bank;
++ int s_first[CONFIG_SYS_MAX_FLASH_BANKS];
++ int s_last[CONFIG_SYS_MAX_FLASH_BANKS];
++ int erased = 0;
++ int planned;
++ int rcode = 0;
++
++ rcode = fill_flash_sect_ranges(addr_first, addr_last, s_first, s_last,
++ &planned);
++
++ if (planned && (rcode == 0)) {
++ for (bank = 0, info = &flash_info[0];
++ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (rcode == 0);
++ ++bank, ++info) {
++ if (s_first[bank] >= 0) {
++ erased += s_last[bank] - s_first[bank] + 1;
++ debug("Erase Flash from 0x%08lx to 0x%08lx "
++ "in Bank # %ld ",
++ info->start[s_first[bank]],
++ (s_last[bank] == info->sector_count) ?
++ info->start[0] + info->size - 1 :
++ info->start[s_last[bank] + 1] - 1,
++ bank + 1);
++ rcode = flash_erase(info, s_first[bank],
++ s_last[bank]);
++ }
++ }
++ if (rcode == 0)
++ printf("Erased %d sectors\n", erased);
++ } else if (rcode == 0) {
++ printf("Error: start and/or end address not on sector boundary\n");
++ rcode = 1;
++ }
++
++ return rcode;
++}
++
++static int verify_image(void)
++{
++ ulong src_addr = IMAGE_LOAD_RAM_ADDR;
++ void *hdr = (void *)src_addr;
++
++ printf("\n## Checking Image at 0x%08lx ...\n", src_addr);
++ /* AT the moment, we only support FIT image flash */
++ switch (genimg_get_format(hdr)) {
++ case IMAGE_FORMAT_FIT:
++ printf(" FIT image found\n");
++ if (!fit_check_format(hdr)) {
++ printf("Bad FIT image format!\n");
++ return -1;
++ }
++
++ if (!fit_all_image_verify(hdr)) {
++ printf("Bad hash in FIT image!\n");
++ return -1;
++ }
++ break;
++ default:
++ printf("Unknown image format!\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++static int flash_image(void)
++{
++ int rcode;
++ ulong max_size = MAX_FITIMAGE_SIZE;
++ ulong src_addr = IMAGE_LOAD_RAM_ADDR;
++ ulong addr_first = get_flash_image_address();
++ ulong addr_last = addr_first + max_size - 1;
++
++ if ((g_write_addr > max_size) || (g_write_addr == 0)) {
++ printf("ERROR: %s(): Invalid file uploaded. filesize(0x%08x)\n",
++ __func__, g_write_addr);
++ return -1;
++ }
++
++ if (sect_roundb(&addr_last) > 0) {
++ printf("ERROR: %s(): sect_roundb failed\n", __func__);
++ return -1;
++ }
++
++ if (addr_first >= addr_last) {
++ printf("ERROR: %s(): addr_first(0x%08lx) >= addr_last(0x%08lx)\n",
++ __func__, addr_first, addr_last);
++ return -1;
++ }
++
++ /* Hack: To update the percentage update,
++ * treat logical division as below.
++ * Image verify - 10%
++ * Unprotecting flash sectors - 10%
++ * Erase flash sectors - 40%
++ * Copy to flash - 40% */
++
++ /* Unprotect the flash sectors */
++ rcode = protect_flash_sector(PROTECT_OFF, addr_first, addr_last);
++ if (rcode != 0) {
++ printf("%s(): Protecting flash sector failed(%d).\n", __func__,
++ rcode);
++ return -1;
++ }
++ update_processing_status(IMG_PROGRAMMING, 20);
++
++ /* erase flash sectors */
++ rcode = erase_flash_sector(addr_first, addr_last);
++ if (rcode != 0) {
++ printf("%s(): Erasing flash sector failed(%d).\n", __func__,
++ rcode);
++ return -1;
++ }
++ update_processing_status(IMG_PROGRAMMING, 60);
++
++ /* write to flash area */
++ printf("Copy to Flash... ");
++ rcode = flash_write((char *)src_addr, addr_first, g_write_addr * 1);
++ if (rcode != 0) {
++ printf("%s(): Flash copy failed(%d).\n", __func__, rcode);
++ flash_perror(rcode);
++ return -1;
++ }
++ printf("done\n");
++ return 0;
++}
++
++void start_fw_update_loop(void)
++{
++ int rc;
++ ulong boot_addr;
++ char boot_cmd[20];
++
++ while (1) {
++ if (g_fwupd_settings.random_number_valid) {
++ /* Random number should be cleared after 30seconds */
++ if (get_ticks() >= etime) {
++ printf("Clearing random number\n");
++
++ if (!fwupd_settings_trylock())
++ continue;
++ memcpy(g_fwupd_settings.rand_num, 0,
++ RAND_NUMBER_SIZE);
++ g_fwupd_settings.random_number_valid = false;
++ fwupd_settings_unlock();
++ }
++ }
++
++ if (g_fwupd_settings.start_update) {
++ update_processing_status(IMG_VALIDATING, 0);
++
++ rc = verify_image();
++ if (rc != 0) {
++ update_processing_status(UPDATE_ERROR, 100);
++ /* Adding delay to make consumer gets status */
++ mdelay(WAIT_STATE_TIMEOUT);
++
++ reset_all_settings();
++ continue;
++ }
++
++ update_processing_status(IMG_PROGRAMMING, 10);
++
++ rc = flash_image();
++ if (rc == 0) {
++ /* Update successful, change the boot command */
++ boot_addr = get_flash_image_address();
++ snprintf(boot_cmd, sizeof(boot_cmd),
++ "bootm %08x", boot_addr);
++ setenv("bootcmd", boot_cmd);
++ saveenv();
++
++ update_processing_status(UPDATE_SUCCESSFUL,
++ 100);
++ } else {
++ update_processing_status(UPDATE_ERROR, 100);
++ }
++
++ /* Adding delay to make sure consumer gets status */
++ mdelay(WAIT_STATE_TIMEOUT);
++
++ reset_all_settings();
++
++ /* Reset BMC */
++ do_reset(NULL, 0, 0, NULL);
++ }
++ mdelay(WAIT_STATE_TIMEOUT);
++ }
++
++ return;
++}
++
++#if 1 /* Debug purpose */
++int do_fwupd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
++{
++ if (argc != 1)
++ return 1;
++
++ start_fw_update_loop();
++ return 0;
++}
++U_BOOT_CMD(fwupd, 1, 0, do_fwupd, "Start Firmware update process", "");
++#endif
+diff --git a/board/aspeed/ast-g5/fw-update.h b/board/aspeed/ast-g5/fw-update.h
+new file mode 100644
+index 0000000..ed033ad
+--- /dev/null
++++ b/board/aspeed/ast-g5/fw-update.h
+@@ -0,0 +1,50 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include <common.h>
++
++/* SPI flash map */
++#define MAX_FITIMAGE_SIZE 0x1B80000
++#define PRIMARY_FITIMAGE_START_ADDR 0x20080000
++#define SECONDARY_FITIMAGE_START_ADDR 0x22480000
++#define IMAGE_LOAD_RAM_ADDR 0x83000000
++
++#define MAX_FILENAME_LENGTH 256
++#define RAND_NUMBER_SIZE 8
++
++enum boot_image {
++ PRIMARY_IMAGE = 0x01,
++ SECONDARY_IMAGE = 0x02
++};
++
++enum update_status {
++ INITIALIZING = 0,
++ IDLE,
++ IMG_DOWNLOADING,
++ IMG_VALIDATING,
++ IMG_PROGRAMMING,
++ UPDATE_SUCCESSFUL,
++ UPDATE_ERROR = 0x0F,
++ UPDATE_FORBIDDEN = 0x80,
++ AC_CYCLE_REQUIRED = 0x83
++};
++
++struct fwupd_global_setting {
++ bool fwupd_mode_active;
++ bool start_update;
++ bool random_number_valid;
++ u8 ctrl_state;
++ u8 options_mask;
++ u8 options_value;
++ u8 processing_status;
++ u8 percentage_completion;
++ u8 integrity_check_status;
++ u8 filename_len;
++ u8 filename[MAX_FILENAME_LENGTH];
++ u8 rand_num[RAND_NUMBER_SIZE];
++};
++
++bool fwupd_settings_trylock(void);
++void fwupd_settings_unlock(void);
++u8 get_active_boot_image(void);
++int generate_random_number(void);
+diff --git a/board/aspeed/ast-g5/ipmi-fwupd.c b/board/aspeed/ast-g5/ipmi-fwupd.c
+new file mode 100644
+index 0000000..3eba056
+--- /dev/null
++++ b/board/aspeed/ast-g5/ipmi-fwupd.c
+@@ -0,0 +1,402 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include "ipmi-fwupd.h"
++
++struct fwupd_global_setting g_fwupd_settings;
++u32 g_write_addr = 0;
++
++u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res)
++{
++ int booting_image = 0x01;
++ struct fwupd_get_exe_ctx_res *result =
++ (struct fwupd_get_exe_ctx_res *)res;
++
++ /* Get active image location(primary/secondary) */
++ booting_image = get_active_boot_image();
++ result->patition_ptr = booting_image;
++ result->exection_ctx = 0x11; /* Forced Firmware Update mode */
++
++ result->completion_code = IPMI_CC_OK;
++ return sizeof(struct fwupd_get_exe_ctx_res);
++}
++u16 fwupd_get_rand_number(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_rand_num_res *result = (struct fwupd_rand_num_res *)res;
++
++ if (req_len != 0) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is critical operation is going on */
++ if (g_fwupd_settings.start_update) {
++ printf("%s(): Update in progress.\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is it already in fwupdate mode */
++ if (g_fwupd_settings.fwupd_mode_active) {
++ printf("%s(): Already in firmware update mode\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ if (generate_random_number() != 0) {
++ printf("%s(): Random number generation failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ memcpy(result->rand_num, g_fwupd_settings.rand_num, RAND_NUMBER_SIZE);
++
++ return sizeof(struct fwupd_rand_num_res);
++}
++
++u16 fwupd_enter_update_mode(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_set_update_mode_res *result =
++ (struct fwupd_set_update_mode_res *)res;
++
++ if (req_len != RAND_NUMBER_SIZE) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is critical operation is going on */
++ if (g_fwupd_settings.start_update) {
++ printf("%s(): Update in progress.\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is it already in fwupdate mode */
++ if (g_fwupd_settings.fwupd_mode_active) {
++ printf("%s(): Already in firmware update mode\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ /* This command should excute within 30 seconds
++ * after random number generation. */
++ if (!g_fwupd_settings.random_number_valid) {
++ printf("%s(): No valid random number exist.\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_CODE;
++ return sizeof(result->completion_code);
++ }
++
++ /* Validate the key to enter this mode */
++ for (int i = 0; i < RAND_NUMBER_SIZE; i++) {
++ if (req[i] != g_fwupd_settings.rand_num[i]) {
++ printf("%s(): Invalid key entered\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_CODE;
++ return sizeof(result->completion_code);
++ }
++ }
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ /* Reset all the settings */
++ memset(&g_fwupd_settings, 0, sizeof(g_fwupd_settings));
++ g_fwupd_settings.fwupd_mode_active = true;
++ fwupd_settings_unlock();
++
++ result->completion_code = IPMI_CC_OK;
++
++ return sizeof(struct fwupd_set_update_mode_res);
++}
++
++u16 fwupd_exit_update_mode(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_exit_update_mode_res *result =
++ (struct fwupd_exit_update_mode_res *)res;
++
++ if (req_len != 0) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ if (!g_fwupd_settings.fwupd_mode_active) {
++ printf("%s(): Invalid command entered\n", __func__);
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.fwupd_mode_active = false;
++ fwupd_settings_unlock();
++
++ result->completion_code = IPMI_CC_OK;
++
++ return sizeof(struct fwupd_exit_update_mode_res);
++}
++u16 fwupd_set_options(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_options_req *options_req = (struct fwupd_options_req *)req;
++ struct fwupd_options_res *result = (struct fwupd_options_res *)res;
++
++ if (req_len < 2) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is critical operation is going on */
++ if (g_fwupd_settings.start_update) {
++ printf("%s(): Update in progress.\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ /* Setting any reserved bits will result the command being rejected */
++ if (((options_req->options_mask & 0xF0) != 0) ||
++ ((options_req->options_value & 0xF0) != 0)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_FIELD;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.options_mask = options_req->options_mask;
++ g_fwupd_settings.options_value = options_req->options_value;
++ fwupd_settings_unlock();
++
++ result->completion_code = IPMI_CC_OK;
++ result->options_value = (g_fwupd_settings.options_mask &
++ g_fwupd_settings.options_value);
++
++ return sizeof(struct fwupd_options_res);
++}
++
++u16 fwupd_set_get_control(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_control_req *ctrl_req = (struct fwupd_control_req *)req;
++ struct fwupd_control_res *result = (struct fwupd_control_res *)res;
++
++ if (req_len < 1) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is critical operation is going on */
++ if (g_fwupd_settings.start_update) {
++ printf("%s(): Update in progress.\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ if ((ctrl_req->ctrl_state == SET_FW_FILENAME) && (req_len < 3)) {
++ printf("%s(): Invalid request data\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ } else if ((ctrl_req->ctrl_state != SET_FW_FILENAME) &&
++ (req_len != 1)) {
++ printf("%s(): Invalid request data\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ if ((!g_fwupd_settings.fwupd_mode_active) &&
++ (ctrl_req->ctrl_state != GET_CTRL_STATE)) {
++ printf("%s(): Invalid request. Control State: %d.\n", __func__,
++ ctrl_req->ctrl_state);
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ switch (ctrl_req->ctrl_state) {
++ case GET_CTRL_STATE:
++ break;
++ case IMG_TRANSFER_START:
++ if ((g_fwupd_settings.ctrl_state &
++ IMG_TRANSFER_CTRL_BIT_START)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code =
++ IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.processing_status = IMG_DOWNLOADING;
++ /* Reset control state during start */
++ g_fwupd_settings.ctrl_state = 0x00;
++ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_START;
++ /* Set current write address to ZERO */
++ g_write_addr = 0x00;
++ fwupd_settings_unlock();
++ break;
++ case IMG_TRANSFER_END:
++ if (!(g_fwupd_settings.ctrl_state &
++ IMG_TRANSFER_CTRL_BIT_START)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code =
++ IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.start_update = true;
++ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_END;
++
++ g_fwupd_settings.ctrl_state &= ~(IMG_TRANSFER_CTRL_BIT_START |
++ IMG_TRANSFER_CTRL_BIT_ABORT);
++ fwupd_settings_unlock();
++ break;
++ case IMG_TRANSFER_ABORT:
++ if (!(g_fwupd_settings.ctrl_state &
++ IMG_TRANSFER_CTRL_BIT_START)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code =
++ IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.processing_status = UPDATE_ERROR;
++ g_fwupd_settings.ctrl_state |= IMG_TRANSFER_CTRL_BIT_ABORT;
++ g_fwupd_settings.ctrl_state &= ~(IMG_TRANSFER_CTRL_BIT_START |
++ IMG_TRANSFER_CTRL_BIT_END);
++ fwupd_settings_unlock();
++ break;
++ case SET_FW_FILENAME:
++ /* Not supporting now */
++ if (ctrl_req->filename_len > sizeof(ctrl_req->filename)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_FIELD;
++ return sizeof(result->completion_code);
++ }
++
++ if (!(g_fwupd_settings.ctrl_state &
++ IMG_TRANSFER_CTRL_BIT_START)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code =
++ IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!fwupd_settings_trylock()) {
++ printf("%s(): Lock failed\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++ g_fwupd_settings.filename_len = ctrl_req->filename_len;
++ strncpy(g_fwupd_settings.filename, ctrl_req->filename,
++ ctrl_req->filename_len);
++ fwupd_settings_unlock();
++ /* TODO: Used for TFTP update but not implemented yet. */
++ /* TODO: Verify image and write to flash */
++ break;
++ case USB_DEV_ATTACH:
++ /* Not supporting now */
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ case USB_DEV_DETACH:
++ /* Not supporting now */
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ break;
++ default:
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_FIELD;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ result->curr_state = g_fwupd_settings.ctrl_state;
++ return sizeof(struct fwupd_control_res);
++}
++u16 fwupd_get_update_status(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_get_update_status_res *result =
++ (struct fwupd_get_update_status_res *)res;
++
++ if (req_len != 0) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ result->processing_status = g_fwupd_settings.processing_status;
++ result->percent_completion = g_fwupd_settings.percentage_completion;
++ result->check_status = 0;
++ /* We don't support error code messages cmd(0x0EH) in uboot.*/
++ result->error_code = 0;
++
++ result->completion_code = IPMI_CC_OK;
++
++ return sizeof(struct fwupd_get_update_status_res);
++}
++
++u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res)
++{
++ struct fwupd_image_write_res *result =
++ (struct fwupd_image_write_res *)res;
++
++ if (req_len < 1) {
++ printf("%s(): Invalid request length\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Check is critical operation is going on */
++ if (g_fwupd_settings.start_update) {
++ printf("%s(): Update in progress.\n", __func__);
++ result->completion_code = IPMI_CC_NODE_BUSY;
++ return sizeof(result->completion_code);
++ }
++
++ if (!g_fwupd_settings.fwupd_mode_active) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if (!(g_fwupd_settings.ctrl_state & IMG_TRANSFER_CTRL_BIT_START)) {
++ printf("%s(): Invalid request\n", __func__);
++ result->completion_code = IPMI_CC_NOT_SUPPORTED_IN_STATE;
++ return sizeof(result->completion_code);
++ }
++
++ if ((g_write_addr + req_len) > MAX_FITIMAGE_SIZE) {
++ printf("%s(): Request length exceeded max size\n", __func__);
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ u8 *mem_addr = (u8 *)((u32)IMAGE_LOAD_RAM_ADDR + g_write_addr);
++
++ memcpy(mem_addr, req, req_len);
++ g_write_addr += req_len;
++
++ result->completion_code = IPMI_CC_OK;
++ result->no_of_bytes_written = (u8)req_len;
++
++ return sizeof(struct fwupd_image_write_res);
++}
+diff --git a/board/aspeed/ast-g5/ipmi-fwupd.h b/board/aspeed/ast-g5/ipmi-fwupd.h
+new file mode 100644
+index 0000000..e490f6b
+--- /dev/null
++++ b/board/aspeed/ast-g5/ipmi-fwupd.h
+@@ -0,0 +1,81 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include "ipmi-handler.h"
++#include "fw-update.h"
++
++enum control_state {
++ GET_CTRL_STATE = 0,
++ IMG_TRANSFER_START,
++ IMG_TRANSFER_END,
++ IMG_TRANSFER_ABORT,
++ SET_FW_FILENAME,
++ USB_DEV_ATTACH,
++ USB_DEV_DETACH
++};
++enum control_state_bit {
++ IMG_TRANSFER_CTRL_BIT_START = (0x01 << 0),
++ IMG_TRANSFER_CTRL_BIT_END = (0x01 << 1),
++ IMG_TRANSFER_CTRL_BIT_ABORT = (0x01 << 2),
++ USB_CTRL_BIT_ATTACH = (0x01 << 3)
++};
++enum update_options_bit {
++ NO_DOWN_REVISION = 0,
++ DEFER_BMC_RESET = 1,
++ SHA32_INTEGRITY_CHECK = 2,
++ CRC32_INTEGRITY_CHECK = 3
++};
++
++struct fwupd_get_exe_ctx_res {
++ u8 completion_code;
++ u8 exection_ctx;
++ u8 patition_ptr;
++};
++struct fwupd_rand_num_res {
++ u8 completion_code;
++ u8 rand_num[RAND_NUMBER_SIZE];
++};
++struct fwupd_set_update_mode_res {
++ u8 completion_code;
++};
++struct fwupd_exit_update_mode_res {
++ u8 completion_code;
++};
++struct fwupd_options_req {
++ u8 options_mask;
++ u8 options_value;
++ u8 integrity_check_value[32];
++};
++struct fwupd_options_res {
++ u8 completion_code;
++ u8 options_value;
++};
++struct fwupd_control_req {
++ u8 ctrl_state;
++ u8 filename_len;
++ u8 filename[MAX_FILENAME_LENGTH];
++};
++struct fwupd_control_res {
++ u8 completion_code;
++ u8 curr_state;
++};
++struct fwupd_get_update_status_res {
++ u8 completion_code;
++ u8 processing_status;
++ u8 percent_completion;
++ u8 check_status;
++ u8 error_code;
++};
++struct fwupd_image_write_res {
++ u8 completion_code;
++ u8 no_of_bytes_written;
++};
++
++u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_get_rand_number(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_enter_update_mode(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_exit_update_mode(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_set_options(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_set_get_control(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_get_update_status(u8 *req, u16 req_len, u8 *res);
++u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res);
+diff --git a/board/aspeed/ast-g5/ipmi-handler.c b/board/aspeed/ast-g5/ipmi-handler.c
+index 9cccee9..5e78546 100644
+--- a/board/aspeed/ast-g5/ipmi-handler.c
++++ b/board/aspeed/ast-g5/ipmi-handler.c
+@@ -1,18 +1,37 @@
+-
+ // SPDX-License-Identifier: GPL-2.0
+ // Copyright (c) 2018-2019 Intel Corporation
+
+-#include "ipmi-handler.h"
++#include "ipmi-fwupd.h"
+
+ /* IPMI network function codes */
+ #define NETFN_APP 0x06
++#define NETFN_FIRMWARE 0x08
++#define NETFN_INTEL_OEM 0x30
+
+ /* IPMI command codes */
+-#define CMD_GET_DEV_ID 0x01
+-#define CMD_GET_SELF_TEST_RESULTS 0x04
++#define CMD_APP_GET_DEV_ID 0x01
++#define CMD_APP_GET_SELF_TEST_RESULTS 0x04
++#define CMD_FWUPD_GET_EXECUTION_CTX 0x23
++#define CMD_FWUPD_GET_RANDOM_NUMBER 0x26
++#define CMD_FWUPD_SET_UPDATE_MODE 0x27
++#define CMD_FWUPD_EXIT_UPDATE_MODE 0x28
++#define CMD_FWUPD_CONTROL_GET_SET 0x29
++#define CMD_FWUPD_GET_UPDATE_STATUS 0x2A
++#define CMD_FWUPD_SET_OPTIONS 0x2B
++#define CMD_FWUPD_IMAGE_WRITE 0x2C
++#define CMD_INTL_OEM_GET_BUFFER_SIZE 0x66
++
++#define MAX_KCS_BUF_SIZE 1020 /* (0xFF * 4) */
++#define MAX_IPMB_BUF_SIZE 1020 /* (0xFF * 4) */
+
+ typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res);
+
++struct ipmi_cmd_table {
++ u8 net_fun;
++ u8 cmd;
++ fun_handler process_cmd;
++};
++
+ struct get_dev_id {
+ u8 completion_code;
+ u8 dev_id;
+@@ -29,11 +48,10 @@ struct self_test_res {
+ u8 completion_code;
+ u8 res_byte[2];
+ };
+-
+-struct ipmi_cmd_table {
+- u8 net_fun;
+- u8 cmd;
+- fun_handler process_cmd;
++struct intc_get_buf_size_res {
++ u8 completion_code;
++ u8 kcs_size;
++ u8 ipmb_size;
+ };
+
+ static u16 get_device_id(u8 *req, u16 req_len, u8 *res)
+@@ -84,10 +102,36 @@ static u16 get_self_test_result(u8 *req, u16 req_len, u8 *res)
+
+ return sizeof(struct self_test_res);
+ }
++static u16 intel_get_buffer_size(u8 *req, u16 req_len, u8 *res)
++{
++ struct intc_get_buf_size_res *result =
++ (struct intc_get_buf_size_res *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Size is multiples of four bytes */
++ result->completion_code = IPMI_CC_OK;
++ result->kcs_size = MAX_KCS_BUF_SIZE / 4;
++ result->ipmb_size = MAX_IPMB_BUF_SIZE / 4;
++
++ return sizeof(struct intc_get_buf_size_res);
++}
+
+ const struct ipmi_cmd_table cmd_info[] = {
+- { NETFN_APP, CMD_GET_DEV_ID, get_device_id },
+- { NETFN_APP, CMD_GET_SELF_TEST_RESULTS, get_self_test_result }
++ { NETFN_APP, CMD_APP_GET_DEV_ID, get_device_id },
++ { NETFN_APP, CMD_APP_GET_SELF_TEST_RESULTS, get_self_test_result },
++ { NETFN_FIRMWARE, CMD_FWUPD_GET_EXECUTION_CTX, fwupd_get_execution_ctx },
++ { NETFN_FIRMWARE, CMD_FWUPD_GET_RANDOM_NUMBER, fwupd_get_rand_number },
++ { NETFN_FIRMWARE, CMD_FWUPD_SET_UPDATE_MODE, fwupd_enter_update_mode },
++ { NETFN_FIRMWARE, CMD_FWUPD_EXIT_UPDATE_MODE, fwupd_exit_update_mode },
++ { NETFN_FIRMWARE, CMD_FWUPD_CONTROL_GET_SET, fwupd_set_get_control },
++ { NETFN_FIRMWARE, CMD_FWUPD_GET_UPDATE_STATUS, fwupd_get_update_status },
++ { NETFN_FIRMWARE, CMD_FWUPD_SET_OPTIONS, fwupd_set_options },
++ { NETFN_FIRMWARE, CMD_FWUPD_IMAGE_WRITE, fwupd_image_write },
++ { NETFN_INTEL_OEM, CMD_INTL_OEM_GET_BUFFER_SIZE, intel_get_buffer_size }
+ };
+
+ #define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info)
+diff --git a/board/aspeed/ast-g5/ipmi-handler.h b/board/aspeed/ast-g5/ipmi-handler.h
+index 9d46d9b..8eea930 100644
+--- a/board/aspeed/ast-g5/ipmi-handler.h
++++ b/board/aspeed/ast-g5/ipmi-handler.h
+@@ -1,4 +1,3 @@
+-
+ /* SPDX-License-Identifier: GPL-2.0 */
+ /* Copyright (c) 2018-2019 Intel Corporation */
+
+@@ -6,12 +5,14 @@
+
+ /* IPMI completion codes */
+ #define IPMI_CC_OK 0x00
++#define IPMI_CC_INVALID_CODE 0x80
+ #define IPMI_CC_NODE_BUSY 0xC0
+ #define IPMI_CC_INVALID_CMD 0xC1
+ #define IPMI_CC_INVALID_CMD_LUN 0xC2
+ #define IPMI_CC_OUT_OF_SPACE 0xC4
+ #define IPMI_CC_INVALID_DATA_LENGTH 0xC7
+ #define IPMI_CC_INVALID_DATA_FIELD 0xCC
++#define IPMI_CC_NOT_SUPPORTED_IN_STATE 0xD5
+ #define IPMI_CC_UNSPECIFIED 0xFF
+
+ /* BMC IPMB LUNs */
+diff --git a/common/autoboot.c b/common/autoboot.c
+index d66c0fa..3647d5f 100644
+--- a/common/autoboot.c
++++ b/common/autoboot.c
+@@ -349,6 +349,19 @@ void autoboot_command(const char *s)
+ {
+ debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
+
++#ifdef AST_G5_INTEL
++ /* TODO: Make run_command_list as non-blocking(blocked by getc())
++ * and make main u-boot loop to check both keyboard inputs as well
++ * as start_update firmware flags during FFUJ.
++ * This will make sure debug mode intact during FFUJ.
++ */
++ if (intel_force_firmware_jumper_enabled()) {
++ printf("#### Force firmware update mode is enabled, "
++ "Serial console is disabled. ####\n");
++ start_fw_update_loop();
++ }
++#endif
++
+ if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
+ #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
+ int prev = disable_ctrlc(1); /* disable Control C checking */
+diff --git a/configs/ast_g5_phy_defconfig b/configs/ast_g5_phy_defconfig
+index 1b96ab7..5965a9b 100644
+--- a/configs/ast_g5_phy_defconfig
++++ b/configs/ast_g5_phy_defconfig
+@@ -15,3 +15,4 @@ CONFIG_SYS_NS16550=y
+ CONFIG_USE_IRQ=y
+ CONFIG_CMD_I2C=y
+ CONFIG_SYS_I2C_AST=y
++CONFIG_LIB_RAND=y
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0030-Support-Get-Set-Security-mode-command.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0030-Support-Get-Set-Security-mode-command.patch
new file mode 100644
index 000000000..519977e19
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0030-Support-Get-Set-Security-mode-command.patch
@@ -0,0 +1,124 @@
+From 294a5971c94099277ee5b5589c060896cf22c495 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Thu, 20 Jun 2019 15:26:50 +0530
+Subject: [PATCH] Support Get/Set Security mode command
+
+Support added for get/set security mode oem command. This
+command is used to read / write the RestrictionMode property
+which is saved in U-Boot environment variable. U-Boot
+command provides a way to downgrade RestrictionMode property
+value, which is not allowed in normal mode from Host interface
+
+Tested:
+1. Verified get security mode returns proper value read from
+U-Boot environment variable. cmdtool.efi 20 C0 B3
+2. Verified set security mode updates U-Boot environment variable
+and it is reflected in linux too cmdtool.efi 20 C0 B4 4
+3. Verified negative test cases with improper values and it
+throws correct errors
+
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+
+---
+ board/aspeed/ast-g5/ipmi-handler.c | 63 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 62 insertions(+), 1 deletion(-)
+
+diff --git a/board/aspeed/ast-g5/ipmi-handler.c b/board/aspeed/ast-g5/ipmi-handler.c
+index 5e78546..4e921bd 100644
+--- a/board/aspeed/ast-g5/ipmi-handler.c
++++ b/board/aspeed/ast-g5/ipmi-handler.c
+@@ -20,10 +20,19 @@
+ #define CMD_FWUPD_SET_OPTIONS 0x2B
+ #define CMD_FWUPD_IMAGE_WRITE 0x2C
+ #define CMD_INTL_OEM_GET_BUFFER_SIZE 0x66
++#define CMD_INTL_OEM_GET_SEC_MODE 0xB3
++#define CMD_INTL_OEM_SET_SEC_MODE 0xB4
+
+ #define MAX_KCS_BUF_SIZE 1020 /* (0xFF * 4) */
+ #define MAX_IPMB_BUF_SIZE 1020 /* (0xFF * 4) */
+
++/* Restriction mode values */
++#define RESTRICTION_MODE_MIN_VALUE 3 /*Provisioning*/
++#define RESTRICION_MODE_MAX_VALUE 5 /*Provisioned host disabled */
++
++#define STR_ENV_PROVISION "provision"
++
++
+ typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res);
+
+ struct ipmi_cmd_table {
+@@ -53,6 +62,11 @@ struct intc_get_buf_size_res {
+ u8 kcs_size;
+ u8 ipmb_size;
+ };
++struct intc_get_secuirty_mode_res {
++ u8 completion_code;
++ u8 restriction_mode;
++ u8 special_mode;
++};
+
+ static u16 get_device_id(u8 *req, u16 req_len, u8 *res)
+ {
+@@ -120,6 +134,51 @@ static u16 intel_get_buffer_size(u8 *req, u16 req_len, u8 *res)
+ return sizeof(struct intc_get_buf_size_res);
+ }
+
++static u16 intel_get_security_mode(u8 *req, u16 req_len, u8 *res)
++{
++ char *cmdline = NULL;
++ struct intc_get_secuirty_mode_res *result =
++ (struct intc_get_secuirty_mode_res *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ cmdline = getenv(STR_ENV_PROVISION);
++ if (!cmdline) {
++ /* Default provision must be set only by linux */
++ result->completion_code = IPMI_CC_UNSPECIFIED;
++ return sizeof(result->completion_code);
++ }
++ result->restriction_mode = simple_strtol(cmdline, NULL, 10);
++ /* special mode is non-volatile and not applicable in U-Boot */
++ result->special_mode = 0;
++ result->completion_code = IPMI_CC_OK;
++
++ return sizeof(*result);
++}
++
++static u16 intel_set_security_mode(u8 *req, u16 req_len, u8 *res)
++{
++ if (req_len != sizeof(*req)) {
++ *res = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(*res);
++ }
++
++ if (*req > RESTRICION_MODE_MAX_VALUE ||
++ *req < RESTRICTION_MODE_MIN_VALUE) {
++ *res = IPMI_CC_INVALID_DATA_FIELD;
++ return sizeof(*res);
++ }
++
++ setenv_ulong(STR_ENV_PROVISION, *req);
++ saveenv();
++ *res = IPMI_CC_OK;
++
++ return sizeof(*res);
++}
++
+ const struct ipmi_cmd_table cmd_info[] = {
+ { NETFN_APP, CMD_APP_GET_DEV_ID, get_device_id },
+ { NETFN_APP, CMD_APP_GET_SELF_TEST_RESULTS, get_self_test_result },
+@@ -131,7 +190,9 @@ const struct ipmi_cmd_table cmd_info[] = {
+ { NETFN_FIRMWARE, CMD_FWUPD_GET_UPDATE_STATUS, fwupd_get_update_status },
+ { NETFN_FIRMWARE, CMD_FWUPD_SET_OPTIONS, fwupd_set_options },
+ { NETFN_FIRMWARE, CMD_FWUPD_IMAGE_WRITE, fwupd_image_write },
+- { NETFN_INTEL_OEM, CMD_INTL_OEM_GET_BUFFER_SIZE, intel_get_buffer_size }
++ { NETFN_INTEL_OEM, CMD_INTL_OEM_GET_BUFFER_SIZE, intel_get_buffer_size },
++ { NETFN_INTEL_OEM, CMD_INTL_OEM_GET_SEC_MODE, intel_get_security_mode },
++ { NETFN_INTEL_OEM, CMD_INTL_OEM_SET_SEC_MODE, intel_set_security_mode },
+ };
+
+ #define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info)
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0031-Make-it-so-TFTP-port-can-be-modified.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0031-Make-it-so-TFTP-port-can-be-modified.patch
new file mode 100644
index 000000000..b70427fe0
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0031-Make-it-so-TFTP-port-can-be-modified.patch
@@ -0,0 +1,40 @@
+From 1d680678abb76bdea7cf2128b7ce6db4a5652151 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Tue, 16 Jul 2019 16:30:02 -0700
+Subject: [PATCH 1/1] Make it so TFTP port can be modified
+
+This makes it so we can use non-privileged tftp ports.
+
+Tested: Can load fw from non-privileged port.
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ include/configs/ast-g5-ncsi.h | 2 ++
+ include/configs/ast-g5-phy.h | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/include/configs/ast-g5-ncsi.h b/include/configs/ast-g5-ncsi.h
+index 12d6684551..20864b2798 100644
+--- a/include/configs/ast-g5-ncsi.h
++++ b/include/configs/ast-g5-ncsi.h
+@@ -28,4 +28,6 @@
+
+ #define CONFIG_HW_WATCHDOG
+
++#define CONFIG_TFTP_PORT
++
+ #endif /* __AST_G5_NCSI_CONFIG_H */
+diff --git a/include/configs/ast-g5-phy.h b/include/configs/ast-g5-phy.h
+index 62ddb841e5..371f50a1db 100644
+--- a/include/configs/ast-g5-phy.h
++++ b/include/configs/ast-g5-phy.h
+@@ -30,4 +30,6 @@
+ /* platform.S */
+ #define CONFIG_DRAM_ECC_SIZE 0x10000000
+
++#define CONFIG_TFTP_PORT
++
+ #endif /* __AST_G5_PHY_CONFIG_H */
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch
new file mode 100644
index 000000000..392acb9ad
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch
@@ -0,0 +1,530 @@
+From bd0d8af493387ab1602a0a40b4a548981c1e4d00 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 24 Jul 2019 20:11:30 +0530
+Subject: [PATCH] PFR FW update and checkpoint support in u-boot
+
+1) Added firmware update ipmi commands support
+for PFR images. This enables PFR based firmware
+updates for components BMC, BIOS and CPLD during
+FFUJ mode.
+
+2) Added two PFR boot flow checkpoint in u-boot
+ - Set the booting starts checkpoint(0x01)
+ - Set FFUJ checkpoint(0x07) when jumper on.
+
+Tested:
+
+Tested:
+1) Using debug fwpiaupd.efi utility, validated the PFR
+BMC image update via KCS ( In FFUJ mode).
+2) Loaded the image, dumped all cpld registers and
+cross verified the check-points properly set or not.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 10 +++
+ board/aspeed/ast-g5/fw-update.c | 112 +++++++++++++++--------------
+ board/aspeed/ast-g5/fw-update.h | 7 ++
+ board/aspeed/ast-g5/ipmi-fwupd.c | 37 ++++++++++
+ board/aspeed/ast-g5/ipmi-fwupd.h | 6 --
+ board/aspeed/ast-g5/pfr-mgr.c | 73 +++++++++++++++++++
+ board/aspeed/ast-g5/pfr-mgr.h | 73 +++++++++++++++++++
+ 8 files changed, 258 insertions(+), 61 deletions(-)
+ create mode 100644 board/aspeed/ast-g5/pfr-mgr.c
+ create mode 100644 board/aspeed/ast-g5/pfr-mgr.h
+
+diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile
+index 0b2d936c23..9021d7fc08 100644
+--- a/board/aspeed/ast-g5/Makefile
++++ b/board/aspeed/ast-g5/Makefile
+@@ -8,3 +8,4 @@ obj-y += ast-g5-kcs.o
+ obj-y += ipmi-handler.o
+ obj-y += ipmi-fwupd.o
+ obj-y += fw-update.o
++obj-y += pfr-mgr.o
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index dde5adbc70..6ef3ca9f73 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -16,6 +16,7 @@
+ #include "ast-g5.h"
+ #include "ast-g5-gpio.h"
+ #include "ast-g5-timer.h"
++#include "pfr-mgr.h"
+
+ /* Names to match the GPIOs */
+ enum gpio_names {
+@@ -634,6 +635,10 @@ void ast_g5_intel(void)
+ ast_scu_write(ast_scu_read(AST_SCU_MISC1_CTRL) |
+ SCU_MISC_UART_DEBUG_DIS, AST_SCU_MISC1_CTRL);
+
++ /* To notify the CPLD about the start of bootloader
++ * and hardware initialization */
++ set_cpld_reg(PFR_CPLD_BOOT_CHECKPOINT_REG, PFR_CPLD_CHKPOINT_START);
++
+ uart_init();
+ pwm_init();
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+@@ -649,6 +654,11 @@ void ast_g5_intel(void)
+ kcs_init();
+ if (intel_get_platform_id() == COOPER_CITY_BOARD_ID)
+ set_pwm_duty_cycle(ELEVATED_PWM_DUTY_VALUE);
++ /* Notify CPLD about FFUJ jumper set and pause
++ * of booting for indefinitely time. It will be
++ * resumed once reset is done. */
++ set_cpld_reg(PFR_CPLD_BOOT_CHECKPOINT_REG,
++ PFR_CPLD_CHKPOINT_FFUJ);
+ /* TODO: need to stop the booting here. */
+ }
+ }
+diff --git a/board/aspeed/ast-g5/fw-update.c b/board/aspeed/ast-g5/fw-update.c
+index 99239938b5..89fe5fd4fd 100644
+--- a/board/aspeed/ast-g5/fw-update.c
++++ b/board/aspeed/ast-g5/fw-update.c
+@@ -6,6 +6,7 @@
+ #include <flash.h>
+
+ #include "fw-update.h"
++#include "pfr-mgr.h"
+
+ #define BOOTCMD_BOOTM_STR "bootm "
+ #define RANDOM_NUM_TIMEOUT 30 /* in seconds */
+@@ -15,7 +16,7 @@
+ #define PROTECT_ON 1
+
+ extern struct fwupd_global_setting g_fwupd_settings;
+-extern u32 g_write_addr;
++extern struct fwupd_image_info g_img_info;
+
+ bool g_fwupd_settings_lock = false;
+ unsigned long long etime;
+@@ -36,16 +37,8 @@ void fwupd_settings_unlock(void)
+
+ u8 get_active_boot_image(void)
+ {
+- char *bootcmd = getenv("bootcmd");
+- char *start = strstr(bootcmd, BOOTCMD_BOOTM_STR);
++ /* For PFR, its always active region */
+ u8 boot_image = PRIMARY_IMAGE;
+-
+- if (start) {
+- ulong boot_addr = simple_strtoul(
+- (start + strlen(BOOTCMD_BOOTM_STR)), NULL, 16);
+- if (boot_addr == SECONDARY_FITIMAGE_START_ADDR)
+- return SECONDARY_IMAGE;
+- }
+ return boot_image;
+ }
+
+@@ -318,45 +311,22 @@ static int erase_flash_sector(ulong addr_first, ulong addr_last)
+ return rcode;
+ }
+
+-static int verify_image(void)
++static int verify_image(ulong src_addr, ulong img_length)
+ {
+- ulong src_addr = IMAGE_LOAD_RAM_ADDR;
+- void *hdr = (void *)src_addr;
+-
+- printf("\n## Checking Image at 0x%08lx ...\n", src_addr);
+- /* AT the moment, we only support FIT image flash */
+- switch (genimg_get_format(hdr)) {
+- case IMAGE_FORMAT_FIT:
+- printf(" FIT image found\n");
+- if (!fit_check_format(hdr)) {
+- printf("Bad FIT image format!\n");
+- return -1;
+- }
+-
+- if (!fit_all_image_verify(hdr)) {
+- printf("Bad hash in FIT image!\n");
+- return -1;
+- }
+- break;
+- default:
+- printf("Unknown image format!\n");
+- return -1;
+- }
+-
++ /* TODO: Verify the hash alone here.*/
++ /* Full image verification is done in CPLD. */
+ return 0;
+ }
+
+-static int flash_image(void)
++static int flash_image(ulong src_addr, ulong addr_first, ulong max_size,
++ ulong img_length)
+ {
+ int rcode;
+- ulong max_size = MAX_FITIMAGE_SIZE;
+- ulong src_addr = IMAGE_LOAD_RAM_ADDR;
+- ulong addr_first = get_flash_image_address();
+ ulong addr_last = addr_first + max_size - 1;
+
+- if ((g_write_addr > max_size) || (g_write_addr == 0)) {
++ if ((img_length > max_size) || (img_length == 0)) {
+ printf("ERROR: %s(): Invalid file uploaded. filesize(0x%08x)\n",
+- __func__, g_write_addr);
++ __func__, img_length);
+ return -1;
+ }
+
+@@ -398,7 +368,7 @@ static int flash_image(void)
+
+ /* write to flash area */
+ printf("Copy to Flash... ");
+- rcode = flash_write((char *)src_addr, addr_first, g_write_addr * 1);
++ rcode = flash_write((char *)src_addr, addr_first, img_length);
+ if (rcode != 0) {
+ printf("%s(): Flash copy failed(%d).\n", __func__, rcode);
+ flash_perror(rcode);
+@@ -430,10 +400,27 @@ void start_fw_update_loop(void)
+ }
+
+ if (g_fwupd_settings.start_update) {
++ printf("Starting image copy to staging area.....\n");
+ update_processing_status(IMG_VALIDATING, 0);
+-
+- rc = verify_image();
++ u8 update_intent = 0x00;
++ if ((g_fwupd_settings.options_mask &
++ g_fwupd_settings.options_value) & DEFER_BMC_RESET)
++ update_intent |= DEFER_UPDATES_TO_RESET;
++
++ ulong offset =
++ get_flash_region_offset(g_img_info.img_type);
++ ulong max_size =
++ get_image_max_size(g_img_info.img_type);
++ ulong src_addr = IMAGE_LOAD_RAM_ADDR;
++ ulong flash_addr = PFR_IMAGE_STAGING_BASE_ADDR + offset;
++
++ debug("FWUPD: offset:0x%08lx, max_size:0x%08lx, "
++ "src_addr:0x%08lx, flash_addr:0x%08lx\n",
++ offset, max_size, src_addr, flash_addr);
++
++ rc = verify_image(src_addr, g_img_info.img_length);
+ if (rc != 0) {
++ printf("Image verification failed.\n");
+ update_processing_status(UPDATE_ERROR, 100);
+ /* Adding delay to make consumer gets status */
+ mdelay(WAIT_STATE_TIMEOUT);
+@@ -441,31 +428,46 @@ void start_fw_update_loop(void)
+ reset_all_settings();
+ continue;
+ }
++ printf("Image verification success.\n");
+
+ update_processing_status(IMG_PROGRAMMING, 10);
+
+- rc = flash_image();
++ rc = flash_image(src_addr, flash_addr, max_size,
++ g_img_info.img_length);
+ if (rc == 0) {
+- /* Update successful, change the boot command */
+- boot_addr = get_flash_image_address();
+- snprintf(boot_cmd, sizeof(boot_cmd),
+- "bootm %08x", boot_addr);
+- setenv("bootcmd", boot_cmd);
+- saveenv();
++ update_processing_status(IMG_PROGRAMMING, 90);
++ } else {
++ update_processing_status(UPDATE_ERROR, 100);
++ }
+
++ printf("Image copy to staging area %s.\n",
++ ((rc == 0) ? "successful" : "failed"));
++
++ /* Set the BMC update intent BIT to CPLD register */
++ update_intent != get_update_intent(g_img_info.img_type);
++
++ /* TODO: We ned a way to protect the staging area from
++ * next write data. After setting cpld intent bit, CPLD
++ * read the stagging region for associated image types
++ * and update active/recovery area. During this stage,
++ * staging area should be protected from next write.
++ * Working with CPLD team for identifying this state. */
++ if (0 != set_cpld_reg(PFR_CPLD_BMC_UPDATE_INTENT_REG,
++ update_intent)) {
++ update_processing_status(UPDATE_ERROR, 100);
++ } else {
++ printf("CPLD: Update intent set successfully.\n");
+ update_processing_status(UPDATE_SUCCESSFUL,
+ 100);
+- } else {
+- update_processing_status(UPDATE_ERROR, 100);
++
++ if (update_intent & DEFER_UPDATES_TO_RESET)
++ printf("CPLD: Update defered to next reset.\n");
+ }
+
+ /* Adding delay to make sure consumer gets status */
+ mdelay(WAIT_STATE_TIMEOUT);
+-
+ reset_all_settings();
+
+- /* Reset BMC */
+- do_reset(NULL, 0, 0, NULL);
+ }
+ mdelay(WAIT_STATE_TIMEOUT);
+ }
+diff --git a/board/aspeed/ast-g5/fw-update.h b/board/aspeed/ast-g5/fw-update.h
+index ed033adfed..45e46ba596 100644
+--- a/board/aspeed/ast-g5/fw-update.h
++++ b/board/aspeed/ast-g5/fw-update.h
+@@ -28,6 +28,12 @@ enum update_status {
+ UPDATE_FORBIDDEN = 0x80,
+ AC_CYCLE_REQUIRED = 0x83
+ };
++enum update_options {
++ NO_DOWN_REVISION = BIT(0),
++ DEFER_BMC_RESET = BIT(1),
++ SHA32_INTEGRITY_CHECK = BIT(2),
++ CRC32_INTEGRITY_CHECK = BIT(3)
++};
+
+ struct fwupd_global_setting {
+ bool fwupd_mode_active;
+@@ -48,3 +54,4 @@ bool fwupd_settings_trylock(void);
+ void fwupd_settings_unlock(void);
+ u8 get_active_boot_image(void);
+ int generate_random_number(void);
++
+diff --git a/board/aspeed/ast-g5/ipmi-fwupd.c b/board/aspeed/ast-g5/ipmi-fwupd.c
+index 3eba056e7f..6afc8d66b7 100644
+--- a/board/aspeed/ast-g5/ipmi-fwupd.c
++++ b/board/aspeed/ast-g5/ipmi-fwupd.c
+@@ -2,10 +2,14 @@
+ // Copyright (c) 2018-2019 Intel Corporation
+
+ #include "ipmi-fwupd.h"
++#include "pfr-mgr.h"
+
+ struct fwupd_global_setting g_fwupd_settings;
+ u32 g_write_addr = 0;
+
++struct fwupd_image_info g_img_info;
++static bool block0_mapped = false;
++
+ u16 fwupd_get_execution_ctx(u8 *req, u16 req_len, u8 *res)
+ {
+ int booting_image = 0x01;
+@@ -395,6 +399,39 @@ u16 fwupd_image_write(u8 *req, u16 req_len, u8 *res)
+ memcpy(mem_addr, req, req_len);
+ g_write_addr += req_len;
+
++ /* Get the PFR block 0 data and read the uploaded image
++ * information( Image type, length, hash etc) */
++ if ((g_write_addr >= sizeof(struct pfr_image_block0)) &&
++ (!block0_mapped)) {
++ struct pfr_image_block0 *block0_data =
++ (struct pfr_image_block0 *)IMAGE_LOAD_RAM_ADDR;
++ u32 magic_num = (u32)((*block0_data->tag) |
++ LSH(*(block0_data->tag + 1), 8) |
++ LSH(*(block0_data->tag + 2), 16) |
++ LSH(*(block0_data->tag + 3), 24));
++ /* Validate the magic number */
++ if (magic_num != PFR_BLOCK0_MAGIC_NUM) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ /* Fill the image info structure for later use */
++ g_img_info.magic_num = magic_num;
++ g_img_info.img_length =
++ (u32)((*block0_data->pc_length) |
++ LSH(*(block0_data->pc_length + 1), 8) |
++ LSH(*(block0_data->pc_length + 2), 16) |
++ LSH(*(block0_data->pc_length + 3), 24));
++ g_img_info.img_type =
++ (u32)((*block0_data->pc_type) |
++ LSH(*(block0_data->pc_type + 1), 8) |
++ LSH(*(block0_data->pc_type + 2), 16) |
++ LSH(*(block0_data->pc_type + 3), 24));
++ /* Add Authentication data struct length for full image */
++ g_img_info.img_length += PFR_AUTH_DATA_STRUCT_LEN;
++ block0_mapped = true;
++ }
++
+ result->completion_code = IPMI_CC_OK;
+ result->no_of_bytes_written = (u8)req_len;
+
+diff --git a/board/aspeed/ast-g5/ipmi-fwupd.h b/board/aspeed/ast-g5/ipmi-fwupd.h
+index e490f6b527..7409d2e2f9 100644
+--- a/board/aspeed/ast-g5/ipmi-fwupd.h
++++ b/board/aspeed/ast-g5/ipmi-fwupd.h
+@@ -19,12 +19,6 @@ enum control_state_bit {
+ IMG_TRANSFER_CTRL_BIT_ABORT = (0x01 << 2),
+ USB_CTRL_BIT_ATTACH = (0x01 << 3)
+ };
+-enum update_options_bit {
+- NO_DOWN_REVISION = 0,
+- DEFER_BMC_RESET = 1,
+- SHA32_INTEGRITY_CHECK = 2,
+- CRC32_INTEGRITY_CHECK = 3
+-};
+
+ struct fwupd_get_exe_ctx_res {
+ u8 completion_code;
+diff --git a/board/aspeed/ast-g5/pfr-mgr.c b/board/aspeed/ast-g5/pfr-mgr.c
+new file mode 100644
+index 0000000000..77131688e7
+--- /dev/null
++++ b/board/aspeed/ast-g5/pfr-mgr.c
+@@ -0,0 +1,73 @@
++// SPDX-License-Identifier: GPL-2.0+
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include "pfr-mgr.h"
++
++int set_cpld_reg(u8 reg_addr, u8 value)
++{
++ int ret = 0;
++ int chip = (PFR_CPLD_SLAVE_ADDR >> 1);
++
++ /* Get current I2C bus number to restore later. */
++ int current_bus_no = i2c_get_bus_num();
++
++ /* Set I2C bus number to PFR CPLD I2C bus. */
++ ret = i2c_set_bus_num(PFR_CPLD_I2C_BUSNO);
++ if (ret) {
++ printf("Failed to change I2C bus number (%d)\n", ret);
++ goto done;
++ }
++
++ ret = i2c_write(chip, reg_addr, 1, &value, 1);
++ if (ret) {
++ printf("Error writing the chip: %d\n", ret);
++ goto done;
++ }
++
++done:
++ /* Restore I2C bus number */
++ if (i2c_set_bus_num(current_bus_no))
++ printf("Failed to restore I2C bus number.\n");
++
++ return ret;
++}
++
++ulong get_update_intent(u32 type)
++{
++ ulong intent = 0;
++ if (type == PFR_CPLD_UPDATE_CAPSULE)
++ intent = CPLD_IMAGE_UPDATE;
++ else if (type == PFR_PCH_UPDATE_CAPSULE)
++ intent = PCH_SPI_FLASH_ACTIVE;
++ else if (type == PFR_BMC_UPDATE_CAPSULE)
++ intent = BMC_SPI_FLASH_ACTIVE;
++
++ return intent;
++}
++
++ulong get_image_max_size(u32 type)
++{
++ ulong max_size = MAX_BMC_IMAGE_SIZE;
++ if (type == PFR_CPLD_UPDATE_CAPSULE)
++ max_size = MAX_CPLD_IMAGE_SIZE;
++ else if (type == PFR_PCH_UPDATE_CAPSULE)
++ max_size = MAX_BIOS_IMAGE_SIZE;
++ else if (type == PFR_BMC_UPDATE_CAPSULE)
++ max_size = MAX_BMC_IMAGE_SIZE;
++
++ return max_size;
++}
++
++ulong get_flash_region_offset(u32 type)
++{
++ ulong offset = 0;
++ if (type == PFR_CPLD_UPDATE_CAPSULE)
++ offset = PFR_CPLD_IMAGE_REGION_OFFSET;
++ else if (type == PFR_PCH_UPDATE_CAPSULE)
++ offset = PFR_BIOS_IMAGE_REGION_OFFSET;
++ else if (type == PFR_BMC_UPDATE_CAPSULE)
++ offset = PFR_BMC_IMAGE_REGION_OFFSET;
++
++ return offset;
++}
++
+diff --git a/board/aspeed/ast-g5/pfr-mgr.h b/board/aspeed/ast-g5/pfr-mgr.h
+new file mode 100644
+index 0000000000..5c5b98bbe0
+--- /dev/null
++++ b/board/aspeed/ast-g5/pfr-mgr.h
+@@ -0,0 +1,73 @@
++// SPDX-License-Identifier: GPL-2.0+
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include <common.h>
++
++/* CPLD I2C device defines */
++#define PFR_CPLD_I2C_BUSNO 4
++#define PFR_CPLD_SLAVE_ADDR 0x70
++
++/* CPLD registers */
++#define PFR_CPLD_BOOT_CHECKPOINT_REG 0x0F
++#define PFR_CPLD_BMC_UPDATE_INTENT_REG 0x13
++
++/* PFR checkpoints */
++#define PFR_CPLD_CHKPOINT_START 0x01
++#define PFR_CPLD_CHKPOINT_FFUJ 0x07
++#define PFR_CPLD_CHKPOINT_FINISHED 0x09
++
++#define PFR_BLOCK0_MAGIC_NUM 0xB6EAFD19
++#define PFR_AUTH_DATA_STRUCT_LEN 1024 /* Block0 & Block1 */
++
++/* SPI Flash MAP */
++#define PFR_IMAGE_STAGING_BASE_ADDR 0x24A00000 /* 54MB */
++#define MAX_BMC_IMAGE_SIZE 0x2000000 /* 32MB */
++#define MAX_BIOS_IMAGE_SIZE 0x1000000 /* 16MB */
++#define MAX_CPLD_IMAGE_SIZE 0x400000 /* 4MB */
++#define PFR_BMC_IMAGE_REGION_OFFSET 0
++#define PFR_BIOS_IMAGE_REGION_OFFSET \
++ (PFR_BMC_IMAGE_REGION_OFFSET + MAX_BMC_IMAGE_SIZE)
++#define PFR_CPLD_IMAGE_REGION_OFFSET \
++ (PFR_BIOS_IMAGE_REGION_OFFSET + MAX_BIOS_IMAGE_SIZE)
++
++#define LSH(data, num) ((data) << (num))
++
++/* Bit mapping for CPLD 'BMC update intent' */
++enum cpld_update_intent {
++ PCH_SPI_FLASH_ACTIVE = BIT(0),
++ PCH_SPI_FLASH_RECOVERY = BIT(1),
++ CPLD_IMAGE_UPDATE = BIT(2),
++ BMC_SPI_FLASH_ACTIVE = BIT(3),
++ BMC_SPI_FLASH_RECOVERY = BIT(4),
++ DEFER_UPDATES_TO_RESET = BIT(7)
++};
++
++enum pfr_block0_pc_type {
++ PFR_CPLD_UPDATE_CAPSULE = 0x00,
++ PFR_PCH_PFM = 0x01,
++ PFR_PCH_UPDATE_CAPSULE = 0x02,
++ PFR_BMC_PFM = 0x03,
++ PFR_BMC_UPDATE_CAPSULE = 0x04
++};
++
++/* PFR image block 0 - As defined in HAS */
++struct pfr_image_block0 {
++ u8 tag[4];
++ u8 pc_length[4];
++ u8 pc_type[4];
++ u8 reserved_1[4];
++ u8 hash_256[32];
++ u8 hash_384[48];
++ u8 reserved_2[32];
++};
++
++struct fwupd_image_info {
++ u32 magic_num;
++ u32 img_length;
++ u32 img_type;
++};
++
++int set_cpld_reg(u8 reg_addr, u8 value);
++ulong get_update_intent(u32 type);
++ulong get_flash_region_offset(u32 type);
++ulong get_image_max_size(u32 type);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0033-Reboot-into-UBOOT-on-Watchdog-Failures.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0033-Reboot-into-UBOOT-on-Watchdog-Failures.patch
new file mode 100644
index 000000000..e673da7ee
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0033-Reboot-into-UBOOT-on-Watchdog-Failures.patch
@@ -0,0 +1,110 @@
+From c82bf9de515cbbdb4ea1a350be83fb89f4a83631 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Wed, 31 Jul 2019 16:01:49 -0700
+Subject: [PATCH 1/1] Reboot into UBOOT on Watchdog Failures
+
+We use watchdog1 to reboot when there is a watchdog
+error. Reboot into u-boot as we are using that as
+safe mode.
+
+Tested: watchdog -T 0 -F /dev/watchdog1 reboots into
+uboot after 3 times
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ .../include/asm/arch-aspeed/ast-g5-intel.h | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 31 +++++++++++++++++++
+ common/autoboot.c | 2 ++
+ 3 files changed, 34 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+index a88521a1b3..64f4ed17bf 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
++++ b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+@@ -14,6 +14,7 @@
+
+ #ifndef __ASSEMBLY__
+ int intel_force_firmware_jumper_enabled(void);
++int intel_failed_boot(void);
+ void start_fw_update_loop(void);
+ #endif
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index e68ab8546a..c003d9a7bc 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -111,6 +111,24 @@ static const GPIOValue gpio_table[] = {
+ #define HOST_SERIAL_A_HIGH_SPEED (1 << 0)
+ #define HOST_SERIAL_B_HIGH_SPEED (1 << 1)
+
++#define WATCHDOG_RESET_BIT 0x8
++#define BOOT_FAILURE_LIMIT 0x3
++
++static int get_boot_failures(void)
++{
++ return getenv_ulong("bootfailures", 10, 0);
++}
++
++static void set_boot_failures(u32 count)
++{
++ if (count > BOOT_FAILURE_LIMIT)
++ return;
++
++ setenv_ulong("bootfailures", count);
++ saveenv();
++}
++
++
+ static void sgpio_init(void)
+ {
+ uint32_t value;
+@@ -270,6 +288,11 @@ int intel_force_firmware_jumper_enabled(void)
+ return gpio_get_value(GPIO_FF_UPD_JUMPER);
+ }
+
++int intel_failed_boot(void)
++{
++ return get_boot_failures() >= BOOT_FAILURE_LIMIT;
++}
++
+ void arch_preboot_os(void)
+ {
+ // last second before booting... set the LEDs
+@@ -402,6 +425,7 @@ void ast_g5_intel_late_init(void)
+ {
+ char value[32];
+ u32 reset_reason = 0;
++ u32 boot_failures = 0;
+
+ /* By default host serail A and B use normal speed */
+ uint32_t host_serial_cfg = 0;
+@@ -446,6 +470,13 @@ void ast_g5_intel_late_init(void)
+
+ update_bootargs_cmd("resetreason", value);
+
++ boot_failures = get_boot_failures();
++
++ if (reset_reason & WATCHDOG_RESET_BIT)
++ set_boot_failures(boot_failures + 1);
++ else
++ set_boot_failures(0);
++
+ /* Update the special mode in bootargs */
+ if (is_mfg_mode_phy_req())
+ update_bootargs_cmd("special", "mfg");
+diff --git a/common/autoboot.c b/common/autoboot.c
+index 45a600e663..03fd164501 100644
+--- a/common/autoboot.c
++++ b/common/autoboot.c
+@@ -263,6 +263,8 @@ static int abortboot(int bootdelay)
+ # ifdef AST_G5_INTEL
+ if (intel_force_firmware_jumper_enabled())
+ return 1;
++ if (intel_failed_boot())
++ return 1;
+ # endif
+
+ if (bootdelay >= 0)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0034-Disable-uart-debug-interface.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0034-Disable-uart-debug-interface.patch
new file mode 100644
index 000000000..941dc7d0d
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0034-Disable-uart-debug-interface.patch
@@ -0,0 +1,54 @@
+From 961561c437c8a3f3de1753c502a20c334966354e Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Tue, 20 Aug 2019 16:10:03 +0800
+Subject: [PATCH 1/2] Disable uart debug interface
+
+AST2500 SOC integrates a UART debug interface which can
+input commands to AST2500 by using simple terminal
+program without the assistance of CPU.
+
+For security requirements, we need to disable this feature,
+set SCU2C[]10 = 1 to disable it.
+
+Tested:
+Flash the u-boot.bin and dump SCU2C as below:
+md 0x1e6e202c
+1e6e202c: 00200400
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ arch/arm/include/asm/arch-aspeed/regs-scu.h | 1 +
+ board/aspeed/ast-g5/ast-g5-intel.c | 4 ++++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/regs-scu.h b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+index 8a596ceafc..8333ba1c59 100644
+--- a/arch/arm/include/asm/arch-aspeed/regs-scu.h
++++ b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+@@ -467,6 +467,7 @@
+ #define SCU_MISC_VUART_TO_CTRL (0x1 << 13)
+ #define SCU_MISC_DIV13_EN (0x1 << 12)
+ #define SCU_MISC_Y_CLK_INVERT (0x1 << 11)
++#define SCU_MISC_UART_DEBUG_DIS (0x1 << 10)
+ #define SCU_MISC_OUT_DELAY (0x1 << 9)
+ #define SCU_MISC_PCI_TO_AHB_DIS (0x1 << 8)
+ #define SCU_MISC_2D_CRT_EN (0x1 << 7)
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 324387a4bc..c58fd3591b 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -578,6 +578,10 @@ extern void espi_init(void);
+ extern void kcs_init(void);
+ void ast_g5_intel(void)
+ {
++ /* Disable uart port debug function */
++ ast_scu_write(ast_scu_read(AST_SCU_MISC1_CTRL) |
++ SCU_MISC_UART_DEBUG_DIS, AST_SCU_MISC1_CTRL);
++
+ uart_init();
+ pwm_init();
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0035-PFR-platform-EXTRST-reset-mask-selection.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0035-PFR-platform-EXTRST-reset-mask-selection.patch
new file mode 100644
index 000000000..f2d1ebdeb
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0035-PFR-platform-EXTRST-reset-mask-selection.patch
@@ -0,0 +1,124 @@
+From a5dc9fb9b33aa732858dc574f1ada22bc4cbd57c Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Thu, 5 Sep 2019 15:03:21 +0530
+Subject: [PATCH] PFR platform - EXTRST# reset mask selection
+
+This is a fix taken from Purely PFR.
+This commit will enable specific reset mask for EXTRST# signal.
+On PFR platforms, EXTRST# signal is used by PFR CPLD to put BMC
+in reset during firmware authentications, recovery and firmware
+update flow, during which certain modules of BMC should be chosen
+to be reset so that Host functionality would be intact.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ arch/arm/include/asm/arch-aspeed/ast-g5-intel.h | 31 +++++++++++++++++++++++++
+ arch/arm/include/asm/arch-aspeed/regs-scu.h | 29 +++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 9 +++++++
+ 3 files changed, 69 insertions(+)
+
+diff --git a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+index 64f4ed1..b9386b2 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
++++ b/arch/arm/include/asm/arch-aspeed/ast-g5-intel.h
+@@ -12,6 +12,37 @@
+
+ #define AST_G5_INTEL 1
+
++/* EXTRST# mask for PFR platform
++ * EXTRST# is used by PFR CPLD to keep BMC in
++ * reset during firmware authentication, updates and recovery
++ * this mask selects the modules to be reset along with BMC so that
++ * Host functions are intact.
++ * (this is fix from Purley PFR )
++ */
++#define AST_WDT_RESET_MASK ( \
++ WDT_RESET_MASK_SPI | \
++ WDT_RESET_MASK_XDMA | \
++ WDT_RESET_MASK_MCTP | \
++ WDT_RESET_MASK_ADC | \
++ WDT_RESET_MASK_JTAG | \
++ WDT_RESET_MASK_PECI | \
++ WDT_RESET_MASK_CRT | \
++ WDT_RESET_MASK_MIC | \
++ WDT_RESET_MASK_SDIO | \
++ WDT_RESET_MASK_HAC | \
++ WDT_RESET_MASK_VIDEO | \
++ WDT_RESET_MASK_HID11 | \
++ WDT_RESET_MASK_USB11 | \
++ WDT_RESET_MASK_USB20 | \
++ WDT_RESET_MASK_GRAPHICS | \
++ WDT_RESET_MASK_MAC2 | \
++ WDT_RESET_MASK_MAC1 | \
++ WDT_RESET_MASK_I2C | \
++ WDT_RESET_MASK_AHB | \
++ WDT_RESET_MASK_COPROC | \
++ WDT_RESET_MASK_ARM | \
++ 0)
++
+ #ifndef __ASSEMBLY__
+ int intel_force_firmware_jumper_enabled(void);
+ int intel_failed_boot(void);
+diff --git a/arch/arm/include/asm/arch-aspeed/regs-scu.h b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+index 1bdb1d8..0a4fb6f 100644
+--- a/arch/arm/include/asm/arch-aspeed/regs-scu.h
++++ b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+@@ -144,6 +144,35 @@
+ #define SCU_RESET_AHB (0x1 << 1)
+ #define SCU_RESET_SRAM_CTRL (0x1 << 0)
+
++/* AST_WDT/EXTRST - 0x9C selection masks */
++#define WDT_RESET_MASK_MISC (1 << 25) /* Misc. SOC controller (WDT, RTC, Timer, UART, SRAM.) */
++#define WDT_RESET_MASK_SPI (1 << 24) /* SPI controller */
++#define WDT_RESET_MASK_XDMA (1 << 23) /* X-DMA controller */
++#define WDT_RESET_MASK_MCTP (1 << 22) /* MCTP controller */
++#define WDT_RESET_MASK_GPIO (1 << 21) /* GPIO controller */
++#define WDT_RESET_MASK_ADC (1 << 20) /* ADC controller */
++#define WDT_RESET_MASK_JTAG (1 << 19) /* JTAG master controller */
++#define WDT_RESET_MASK_PECI (1 << 18) /* PECI controller */
++#define WDT_RESET_MASK_PWM (1 << 17) /* PWM controller */
++#define WDT_RESET_MASK_CRT (1 << 16) /* CRT mode 2D engine */
++#define WDT_RESET_MASK_MIC (1 << 15) /* MIC controller */
++#define WDT_RESET_MASK_SDIO (1 << 14) /* SD/SDIO controller */
++#define WDT_RESET_MASK_LPC (1 << 13) /* LPC controller */
++#define WDT_RESET_MASK_HAC (1 << 12) /* HAC engine */
++#define WDT_RESET_MASK_VIDEO (1 << 11) /* Video engine */
++#define WDT_RESET_MASK_HID11 (1 << 10) /* USB1.1 HID/USB2.0 Host EHCI2 controller */
++#define WDT_RESET_MASK_USB11 (1 << 9) /* USB1.1 Host controller */
++#define WDT_RESET_MASK_USB20 (1 << 8) /* USB2.0 Host/Hub controller */
++#define WDT_RESET_MASK_GRAPHICS (1 << 7) /* Graphics CRT controller */
++#define WDT_RESET_MASK_MAC2 (1 << 6) /* MAC#2 controller */
++#define WDT_RESET_MASK_MAC1 (1 << 5) /* MAC#1 controller */
++#define WDT_RESET_MASK_I2C (1 << 4) /* I2C controller */
++#define WDT_RESET_MASK_AHB (1 << 3) /* AHB bridges */
++#define WDT_RESET_MASK_SDRAM (1 << 2) /* SDRAM controller */
++#define WDT_RESET_MASK_COPROC (1 << 1) /* Coprocessor */
++#define WDT_RESET_MASK_ARM (1 << 0) /* ARM */
++#define WDT_RESET_MASK_ALL 0x03ffffff /* all the bits above: 0-25*/
++
+ /* AST_SCU_RESET2 0xD4 - Reset Control register set 2 */
+ #define SCU_RESET_CRT3 (0x1 << 8)
+ #define SCU_RESET_CRT2 (0x1 << 7)
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 06c6708..e6dd2e6 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -661,6 +661,15 @@ extern void espi_init(void);
+ extern void kcs_init(void);
+ void ast_g5_intel(void)
+ {
++ /* EXTRST# mask for PFR platform
++ * EXTRST# is used by PFR CPLD to keep BMC in
++ * reset during firmware authentication, updates and recovery
++ * this mask selects the modules to be reset along with BMC so that
++ * Host functions are intact.
++ * (this is fix from Purley PFR )
++ */
++ ast_scu_write(AST_WDT_RESET_MASK, AST_SCU_WDT_RESET);
++
+ /* Disable uart port debug function */
+ ast_scu_write(ast_scu_read(AST_SCU_MISC1_CTRL) |
+ SCU_MISC_UART_DEBUG_DIS, AST_SCU_MISC1_CTRL);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0036-Re-Enable-KCS.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0036-Re-Enable-KCS.patch
new file mode 100644
index 000000000..976277f9e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0036-Re-Enable-KCS.patch
@@ -0,0 +1,35 @@
+From 6bd4135cd2b8e3a95f5c29e7edaa678e0ca6eded Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 19 Sep 2019 10:15:19 -0700
+Subject: [PATCH 1/1] Re-Enable KCS
+
+Phosphor-isolation isolates too much and seems to
+make KCS not work. This removes the lines from that
+patch that seem to be of question.
+
+Tested: AC/Cycled, cmdtool.efi 20 18 1 works
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ board/aspeed/ast-g5/ast-g5.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
+index ead2e1bb63..00bd92ae5f 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -41,11 +41,6 @@ int board_init(void)
+ bool sdmc_unlocked;
+ u32 val;
+
+- /* iLPC2AHB */
+- val = readl(AST_SCU_BASE + AST_SCU_HW_STRAP1);
+- val |= SCU_HW_STRAP_LPC_DEC_SUPER_IO;
+- writel(val, AST_SCU_BASE + AST_SCU_HW_STRAP1);
+-
+ val = readl(AST_LPC_BASE + AST_LPC_HICRB);
+ val |= LPC_HICRB_ILPC2AHB;
+ writel(val, AST_LPC_BASE + AST_LPC_HICRB);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0037-aspeed-ast-scu.c-fix-MAC1LINK-and-MAC2LINK-pin-pads-.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0037-aspeed-ast-scu.c-fix-MAC1LINK-and-MAC2LINK-pin-pads-.patch
new file mode 100644
index 000000000..9c176e998
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0037-aspeed-ast-scu.c-fix-MAC1LINK-and-MAC2LINK-pin-pads-.patch
@@ -0,0 +1,80 @@
+From 4b96a19bdde82d7fed24cb70e0bcaef16d8711c3 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 4 Oct 2019 15:54:43 -0700
+Subject: [PATCH] aspeed/ast-scu.c: fix MAC1LINK and MAC2LINK pin pads setting
+
+Intel platforms don't use these pins as PHY link monitoring inputs
+so this commit disables them in SCU pin control register so that
+the pins can be used as GPIOs.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/mach-aspeed/ast-scu.c | 37 +++++++++----------------------------
+ 1 file changed, 9 insertions(+), 28 deletions(-)
+
+diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
+index 537cd4b3e1c7..28c48c115406 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -419,49 +419,30 @@ void ast_scu_multi_func_eth(u8 num)
+ {
+ switch (num) {
+ case 0:
+- if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC0_RGMII) {
++ if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC0_RGMII)
+ printf("MAC0 : RGMII\n");
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
+- SCU_FUN_PIN_MAC0_PHY_LINK,
+- AST_SCU_FUN_PIN_CTRL1);
+- } else {
++ else
+ printf("MAC0 : RMII/NCSI\n");
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
+- ~SCU_FUN_PIN_MAC0_PHY_LINK,
+- AST_SCU_FUN_PIN_CTRL1);
+- }
+-
+-#ifdef AST_SOC_G5
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
+- SCU_FUN_PIN_MAC0_PHY_LINK, AST_SCU_FUN_PIN_CTRL1);
+
+-#endif
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
++ ~SCU_FUN_PIN_MAC0_PHY_LINK,
++ AST_SCU_FUN_PIN_CTRL1);
+ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) |
+ SCU_FUN_PIN_MAC0_MDIO | SCU_FUN_PIN_MAC0_MDC,
+ AST_SCU_FUN_PIN_CTRL3);
+-
+ break;
+ case 1:
+- if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC1_RGMII) {
++ if (ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC1_RGMII)
+ printf("MAC1 : RGMII\n");
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
+- SCU_FUN_PIN_MAC1_PHY_LINK,
+- AST_SCU_FUN_PIN_CTRL1);
+- } else {
++ else
+ printf("MAC1 : RMII/NCSI\n");
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
+- ~SCU_FUN_PIN_MAC1_PHY_LINK,
+- AST_SCU_FUN_PIN_CTRL1);
+- }
+
+- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) |
+- SCU_FUN_PIN_MAC1_PHY_LINK,
++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) &
++ ~SCU_FUN_PIN_MAC1_PHY_LINK,
+ AST_SCU_FUN_PIN_CTRL1);
+-
+ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) |
+ SCU_FUC_PIN_MAC1_MDIO,
+ AST_SCU_FUN_PIN_CTRL5);
+-
+ break;
+ }
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0038-Increase-default-fan-speed-for-cooper-city.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0038-Increase-default-fan-speed-for-cooper-city.patch
new file mode 100644
index 000000000..53cdd763e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0038-Increase-default-fan-speed-for-cooper-city.patch
@@ -0,0 +1,131 @@
+From e465945672408b632d5e3c2cf7f08ade1268419e Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 24 Oct 2019 14:39:22 -0700
+Subject: [PATCH 1/1] Increase default fan speed for cooper city
+
+This increases the uboot fan speed for cooper city
+as it has high core count CPUS.
+
+Tested: In uboot fans appeared to run faster
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ board/aspeed/ast-g5/ast-g5-gpio.h | 6 ++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 46 ++++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-gpio.h b/board/aspeed/ast-g5/ast-g5-gpio.h
+index ed2499f5cc..9088cdd3e3 100644
+--- a/board/aspeed/ast-g5/ast-g5-gpio.h
++++ b/board/aspeed/ast-g5/ast-g5-gpio.h
+@@ -70,9 +70,15 @@
+ #define ID_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_6)
+ #define GRN_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_4)
+ #define AMB_LED_PORT_PIN PORT_PIN(GPIO_PORT_S, GPIO_PIN_5)
++#define PLATFORM_ID0_PORT_PIN PORT_PIN(GPIO_PORT_B, GPIO_PIN_0)
++#define PLATFORM_ID1_PORT_PIN PORT_PIN(GPIO_PORT_B, GPIO_PIN_1)
++#define PLATFORM_ID2_PORT_PIN PORT_PIN(GPIO_PORT_B, GPIO_PIN_2)
++#define PLATFORM_ID3_PORT_PIN PORT_PIN(GPIO_PORT_B, GPIO_PIN_3)
++#define PLATFORM_ID4_PORT_PIN PORT_PIN(GPIO_PORT_B, GPIO_PIN_4)
+ #define FORCE_BMC_UPDATE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_0)
+ #define TPM_EN_PULSE_PORT_PIN PORT_PIN(GPIO_PORT_D, GPIO_PIN_6)
+ #define FP_PWR_BTN_PORT_PIN PORT_PIN(GPIO_PORT_E, GPIO_PIN_2)
++#define PLATFORM_ID5_PORT_PIN PORT_PIN(GPIO_PORT_G, GPIO_PIN_5)
+
+ // GPIO Configuration Register bits
+ #define GPCFG_EVENT_TO_SMI (1 << 7) // 1 == enabled
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index c58fd3591b..9d5db68b7e 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -25,6 +25,12 @@ enum gpio_names {
+ GPIO_FF_UPD_JUMPER,
+ GPIO_ENABLE_TPM_PULSE,
+ GPIO_FP_PWR_BTN,
++ GPIO_PLATFORM_ID_0,
++ GPIO_PLATFORM_ID_1,
++ GPIO_PLATFORM_ID_2,
++ GPIO_PLATFORM_ID_3,
++ GPIO_PLATFORM_ID_4,
++ GPIO_PLATFORM_ID_5,
+ };
+
+ #define GPIO_CFG_DEFAULT (GPCFG_ACTIVE_HIGH | GPCFG_LEVEL_TRIG)
+@@ -60,6 +66,21 @@ static const GPIOValue gpio_table[] = {
+ [GPIO_FP_PWR_BTN] = {FP_PWR_BTN_PORT_PIN, GPIO_CFG_DEFAULT, 0,
+ GPIO_DEBOUNCE_8MS},
+
++ /* Platform ID Pins */
++ [GPIO_PLATFORM_ID_0] = {PLATFORM_ID0_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++ [GPIO_PLATFORM_ID_1] = {PLATFORM_ID1_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++ [GPIO_PLATFORM_ID_2] = {PLATFORM_ID2_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++ [GPIO_PLATFORM_ID_3] = {PLATFORM_ID3_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++ [GPIO_PLATFORM_ID_4] = {PLATFORM_ID4_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++ [GPIO_PLATFORM_ID_5] = {PLATFORM_ID5_PORT_PIN, GPIO_CFG_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++
++
+ };
+
+ #define LPC_SNOOP_ADDR 0x80
+@@ -114,6 +135,8 @@ static const GPIOValue gpio_table[] = {
+ #define WATCHDOG_RESET_BIT 0x8
+ #define BOOT_FAILURE_LIMIT 0x3
+
++#define COOPER_CITY_BOARD_ID 40
++
+ static int get_boot_failures(void)
+ {
+ return getenv_ulong("bootfailures", 10, 0);
+@@ -295,6 +318,26 @@ int intel_failed_boot(void)
+ return get_boot_failures() >= BOOT_FAILURE_LIMIT;
+ }
+
++int intel_get_platform_id(void)
++{
++ int id = 0;
++ int temp = 0;
++ int gpios[] = {GPIO_PLATFORM_ID_0,
++ GPIO_PLATFORM_ID_1,
++ GPIO_PLATFORM_ID_2,
++ GPIO_PLATFORM_ID_3,
++ GPIO_PLATFORM_ID_4,
++ GPIO_PLATFORM_ID_5};
++ int ii;
++ for (ii = 0; ii < ARRAY_SIZE(gpios); ii++){
++ temp = gpio_get_value(gpios[ii]);
++ if(temp < 0)
++ return temp;
++ id |= temp << ii;
++ }
++ return id;
++}
++
+ void arch_preboot_os(void)
+ {
+ // last second before booting... set the LEDs
+@@ -322,6 +365,7 @@ void arch_preboot_os(void)
+ #define PWM_CLK_ENABLE BIT(0)
+ #define PWM_DUTY(PCT) (((PCT) * 128) / 100)
+ #define DEFAULT_PWM_DUTY_VALUE PWM_DUTY(57)
++#define ELEVATED_PWM_DUTY_VALUE PWM_DUTY(80)
+
+
+ static inline uint32_t ast_scu_read(uint32_t reg)
+@@ -595,6 +639,8 @@ void ast_g5_intel(void)
+ id_led_control(GPIO_GREEN_LED, EIDLED_Off);
+ id_led_control(GPIO_AMBER_LED, EIDLED_On);
+ kcs_init();
++ if (intel_get_platform_id() == COOPER_CITY_BOARD_ID)
++ set_pwm_duty_cycle(ELEVATED_PWM_DUTY_VALUE);
+ /* TODO: need to stop the booting here. */
+ }
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0040-Initialize-the-BMC-host-mailbox-at-reset-time.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0040-Initialize-the-BMC-host-mailbox-at-reset-time.patch
new file mode 100644
index 000000000..b36627d17
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0040-Initialize-the-BMC-host-mailbox-at-reset-time.patch
@@ -0,0 +1,65 @@
+From 933d80ac82dbe1f74c653b0ac505fde406e2553c Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Mon, 27 Jan 2020 15:13:10 -0800
+Subject: [PATCH] Initialize the BMC/host mailbox at reset time
+
+When the BMC comes out of reset, the mailbox registers need to be set so
+the communications with the host can start properly.
+
+Tested: boot the BMC and take note that the mailbox registers are no
+ longer random garbage.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index ce87a46cd1..1086742045 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -575,6 +575,33 @@ static void pwm_init(void)
+ writel(val, PWM_BASE_ADDR + PWM_CONTROL);
+ }
+
++#define AST_MBX_COUNT 16
++#define MB_HINIT_BP_REG1 (0)
++#define MB_HINIT_BP_REG2 (1) // reserved for future bit definition.
++#define MB_FW_MJ_VER_REG (2)
++#define MB_FW_MN_VER_REG (3)
++#define MB_HINIT_ERR_REG (4)
++#define MB_BOOTL_BP_REG1 (5)
++#define MB_BOOTL_BP_REG2 (6) // tracks which image selected
++#define MB_BOOTL_ERR_REG (7)
++#define MB_RUNTM_BP_REG1 (8)
++#define MB_RUNTM_BP_REG2 (9) // reserved for future bit definition.
++#define MB_RUNTM_ERR_REG (10)
++static void mailbox_init(void)
++{
++ /* clear out default mbox values */
++ int i;
++ for (i = 0; i < AST_MBX_COUNT; i++)
++ {
++ writel(0, AST_MBX_BASE + 4 * i);
++ }
++ /* by the time this is called, all the hardware init is done
++ * so we can mark that as complete */
++ writel(0xff, AST_MBX_BASE + 4 * MB_HINIT_BP_REG1);
++ /* mark progress up through booting linux */
++ writel(0x1f, AST_MBX_BASE + 4 * MB_BOOTL_BP_REG1);
++}
++
+ extern void espi_init(void);
+ extern void kcs_init(void);
+ void ast_g5_intel(void)
+@@ -597,6 +624,7 @@ void ast_g5_intel(void)
+ set_cpld_reg(PFR_CPLD_BOOT_CHECKPOINT_REG, PFR_CPLD_CHKPOINT_START);
+
+ uart_init();
++ mailbox_init();
+ pwm_init();
+ gpio_init(gpio_table, ARRAY_SIZE(gpio_table));
+ espi_init();
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0041-Disabling-boot-delay.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0041-Disabling-boot-delay.patch
new file mode 100644
index 000000000..69ec33a17
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0041-Disabling-boot-delay.patch
@@ -0,0 +1,27 @@
+From e21ee4b456addc93a9afed0cb52ac2a53d3b785a Mon Sep 17 00:00:00 2001
+From: arun-pm <arun.p.m@linux.intel.com>
+Date: Thu, 30 Jan 2020 10:32:13 +0530
+Subject: [PATCH] Disabling boot delay
+
+Boot delay is changed to -2 so that BMC will not stop in u-boot by pressing
+ESC key.
+---
+ include/configs/ast-common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h
+index 0bc7f2d75f..dce6bbf5aa 100644
+--- a/include/configs/ast-common.h
++++ b/include/configs/ast-common.h
+@@ -70,7 +70,7 @@
+ /*
+ * Environment Config
+ */
+-#define CONFIG_BOOTDELAY 2
++#define CONFIG_BOOTDELAY -2
+
+ /*
+ * Miscellaneous configurable options
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0043-PFR-Skip-counting-WDT2-event-when-EXTRST-is-set.patch b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0043-PFR-Skip-counting-WDT2-event-when-EXTRST-is-set.patch
new file mode 100644
index 000000000..3833d2a31
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/files/0043-PFR-Skip-counting-WDT2-event-when-EXTRST-is-set.patch
@@ -0,0 +1,45 @@
+From 51ae3c80f20be3b8e010aa57041fa9c38076cc76 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Wed, 18 Mar 2020 21:47:11 +0530
+Subject: [PATCH] PFR- Skip counting WDT2 event when EXTRST# is set
+
+PFR CPLD drives EXTRST# of BMC to reset it during
+firmware update and during recovery. On ast2500 the
+EXTRST# is also setting WDT2/3 flags which is counted
+as boot failures by u-boot and aborts the boot if
+boot failures are more than 3. This change will skip
+counting WDT2 flag if EXTRST# is also set in SCU3C.
+
+Tested: Verified BMC updates 4 times and checked that
+ the boot is not aborted at u-boot.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 575061ff88..872c7a843a 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -145,6 +145,7 @@ static const GPIOValue gpio_table[] = {
+ #define HOST_SERIAL_B_HIGH_SPEED (1 << 1)
+
+ #define WATCHDOG_RESET_BIT 0x8
++#define EXTRST_RESET_BIT 0x2
+ #define BOOT_FAILURE_LIMIT 0x3
+
+ #define BRIGHTON_CITY_BOARD_ID 0
+@@ -572,7 +573,8 @@ void ast_g5_intel_late_init(void)
+
+ boot_failures = get_boot_failures();
+
+- if (reset_reason & WATCHDOG_RESET_BIT)
++ if ((reset_reason & WATCHDOG_RESET_BIT) &&
++ !(reset_reason & EXTRST_RESET_BIT))
+ set_boot_failures(boot_failures + 1);
+ else
+ set_boot_failures(0);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend
new file mode 100644
index 000000000..4183df7ef
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend
@@ -0,0 +1,72 @@
+COMPATIBLE_MACHINE = "intel-ast2500"
+FILESEXTRAPATHS_append_intel-ast2500:= "${THISDIR}/files:"
+
+# the meta-phosphor layer adds this patch, which conflicts
+# with the intel layout for environment
+SRC_URI_remove_intel-ast2500 = " file://0001-configs-ast-Add-redundnant-env.patch"
+
+SRC_URI_append_intel-ast2500 = " \
+ file://0001-flash-use-readX-writeX-not-udelay.patch \
+ file://0002-intel-layout-environment-addr.patch \
+ file://0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch \
+ file://0005-enable-passthrough-in-uboot.patch \
+ file://0006-Add-Aspeed-g5-interrupt-support.patch \
+ file://0007-Add-espi-support.patch \
+ file://0008-add-sgio-support-for-port80-snoop-post-LEDs.patch \
+ file://0009-Add-basic-GPIO-support.patch \
+ file://0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch \
+ file://0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch \
+ file://0012-Add-status-and-ID-LED-support.patch \
+ file://0013-aspeed-Add-Pwm-Driver.patch \
+ file://0014-Keep-interrupts-enabled-until-last-second.patch \
+ file://0015-Rewrite-memmove-to-optimize-on-word-transfers.patch \
+ file://0019-u-boot-full-platform-reset-espi-oob-ready.patch \
+ file://0020-Enable-PCIe-L1-support.patch \
+ file://0020-Add-system-reset-status-support.patch \
+ file://0021-Config-host-uart-clock-source-using-environment-vari.patch \
+ file://0022-KCS-driver-support-in-uBoot.patch \
+ file://0023-Add-TPM-enable-pulse-triggering.patch \
+ file://0024-IPMI-command-handler-implementation-in-uboot.patch \
+ file://0025-Manufacturing-mode-physical-presence-detection.patch \
+ file://0026-Aspeed-I2C-support-in-U-Boot.patch \
+ file://0027-CPLD-u-boot-commands-support-for-PFR.patch \
+ file://0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch \
+ file://0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch \
+ file://0030-Support-Get-Set-Security-mode-command.patch \
+ file://0031-Make-it-so-TFTP-port-can-be-modified.patch \
+ file://0033-Reboot-into-UBOOT-on-Watchdog-Failures.patch \
+ file://0034-Disable-uart-debug-interface.patch \
+ file://0036-Re-Enable-KCS.patch \
+ file://0037-aspeed-ast-scu.c-fix-MAC1LINK-and-MAC2LINK-pin-pads-.patch \
+ file://0038-Increase-default-fan-speed-for-cooper-city.patch \
+ file://0040-Initialize-the-BMC-host-mailbox-at-reset-time.patch \
+ "
+PFR_SRC_URI = " \
+ file://0022-u-boot-env-change-for-PFR-image.patch \
+ file://0032-PFR-FW-update-and-checkpoint-support-in-u-boot.patch \
+ file://0035-PFR-platform-EXTRST-reset-mask-selection.patch \
+ file://0043-PFR-Skip-counting-WDT2-event-when-EXTRST-is-set.patch \
+ "
+AUTOBOOT_SRC_URI = " \
+ file://0041-Disabling-boot-delay.patch \
+ "
+SRC_URI_append_intel-ast2500 += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', PFR_SRC_URI, '', d)}"
+SRC_URI_append_intel-ast2500 += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', '', AUTOBOOT_SRC_URI, d)}"
+do_install_append () {
+ install -m 0644 ${WORKDIR}/fw_env.config ${S}/tools/env/fw_env.config
+}
+
+require recipes-core/os-release/version-vars.inc
+
+python do_version () {
+ with open(d.expand('${S}/board/aspeed/ast-g5/intel-version.h'), 'w') as f:
+ f.write(d.expand('#define VER_MAJOR ${IPMI_MAJOR}\n'))
+ f.write(d.expand('#define VER_MINOR ${IPMI_MINOR}\n'))
+ f.write(d.expand('#define VER_AUX13 ${IPMI_AUX13}\n'))
+ f.write(d.expand('#define VER_AUX14 ${IPMI_AUX14}\n'))
+ f.write(d.expand('#define VER_AUX15 ${IPMI_AUX15}\n'))
+ f.write(d.expand('#define VER_AUX16 ${IPMI_AUX16}\n'))
+}
+
+do_version[vardepsexclude] = "IPMI_MAJOR IPMI_MINOR IPMI_AUX13 IPMI_AUX14 IPMI_AUX15 IPMI_AUX16 PRODUCT_GENERATION VERSION VERSION_ID BUILD_ID"
+addtask do_version after do_configure before do_compile
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend
new file mode 120000
index 000000000..f725cd47a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend
@@ -0,0 +1 @@
+./u-boot-aspeed_%.bbappend \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend
new file mode 100644
index 000000000..5d8fa34bf
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -0,0 +1,3 @@
+COMPATIBLE_MACHINE = "intel-ast2500"
+FILESEXTRAPATHS_prepend := "${THISDIR}/linux-aspeed:"
+SRC_URI += "file://intel-ast2500.cfg"
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/0001-Blacklist-DIMM-Bus.patch b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/0001-Blacklist-DIMM-Bus.patch
new file mode 100644
index 000000000..e84e79884
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/0001-Blacklist-DIMM-Bus.patch
@@ -0,0 +1,26 @@
+From c64c2d05ebd9dcb9b161320087ce205a8a674a45 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Wed, 11 Dec 2019 10:20:40 -0800
+Subject: [PATCH 1/1] Blacklist DIMM Bus
+
+The dimms error when being scanned, blacklist the bus.
+
+Change-Id: I797d144dc89b49ef7ac4f68b106a492014a4d086
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ blacklist.json | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/blacklist.json b/blacklist.json
+index f112a7b..1ae6deb 100644
+--- a/blacklist.json
++++ b/blacklist.json
+@@ -1,3 +1,4 @@
+ {
+- "buses": []
++ "buses": [9]
+ }
++
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json
new file mode 100644
index 000000000..793c790c8
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CPC-Baseboard.json
@@ -0,0 +1,1909 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "A_P12V_PSU_SCALED",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BridgeGpio": [
+ {
+ "Name": "P3VBAT_BRIDGE_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 8,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU2",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCIO_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVDQ_ABC_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 12,
+ "Name": "PVDQ_ABC_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 11,
+ "Name": "PVDQ_DEF_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVDQ_DEF_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 0,
+ "Name": "Fan 1a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 1,
+ "Name": "Fan 1b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 2,
+ "Name": "Fan 2a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 3,
+ "Name": "Fan 2b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 4,
+ "Name": "Fan 3a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 5,
+ "Name": "Fan 3b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 6,
+ "Name": "Fan 4a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 7,
+ "Name": "Fan 4b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 8,
+ "Name": "Fan 5a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 9,
+ "Name": "Fan 5b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 10,
+ "Name": "Fan 6a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 11,
+ "Name": "Fan 6b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 12,
+ "Name": "Fan 7a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 13,
+ "Name": "Fan 7b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 14,
+ "Name": "Fan 8a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 15,
+ "Name": "Fan 8b",
+ "Type": "AspeedFan"
+ },
+ {
+ "C1": 92.16,
+ "C2": 107.52,
+ "MaxCFM": 17.5,
+ "Name": "System Airflow",
+ "TachMaxPercent": 100,
+ "TachMinPercent": 20,
+ "Tachs": [
+ "Fan 1a",
+ "Fan 1b",
+ "Fan 2a",
+ "Fan 2b",
+ "Fan 3a",
+ "Fan 3b",
+ "Fan 4a",
+ "Fan 4b",
+ "Fan 5a",
+ "Fan 5b",
+ "Fan 6a",
+ "Fan 6b",
+ "Fan 7a",
+ "Fan 7b",
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Type": "CFMSensor"
+ },
+ {
+ "Name": "System Fan connector 1",
+ "Pwm": 0,
+ "Tachs": [
+ 0,
+ 1
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 2",
+ "Pwm": 1,
+ "Tachs": [
+ 2,
+ 3
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 3",
+ "Pwm": 2,
+ "Tachs": [
+ 4,
+ 5
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 4",
+ "Pwm": 3,
+ "Tachs": [
+ 6,
+ 7
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 5",
+ "Pwm": 4,
+ "Tachs": [
+ 8,
+ 9
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 6",
+ "Pwm": 5,
+ "Tachs": [
+ 10,
+ 11
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 7",
+ "Pwm": 6,
+ "Tachs": [
+ 12,
+ 13
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 8",
+ "Pwm": 7,
+ "Tachs": [
+ 14,
+ 15
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xC4",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU1 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xCC",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU2 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xD4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB0",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xEC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 7,
+ "ChannelNames": [
+ "PMBusSlot1",
+ "PMBusSlot2",
+ "PMBusSlot3",
+ "PMBusSlot4"
+ ],
+ "Name": "PMBus Mux",
+ "Type": "PCA9544Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 2 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 9,
+ "ChannelNames": [
+ "MemoryChannel1",
+ "MemoryChannel2",
+ "MemoryChannel3",
+ "MemoryChannel4"
+ ],
+ "Name": "Memory Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x74",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "Pcie_Slot_3",
+ "Pcie_Slot_4"
+ ],
+ "Name": "PCIE Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": [
+ "0x50",
+ "0x51"
+ ],
+ "Bus": 7,
+ "Name": "PSU address",
+ "Type": "PSUPresence"
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Exit Air Temp"
+ ],
+ "Name": "Exit Air Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 65.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 1a",
+ "Fan 1b"
+ ],
+ "Name": "Fan 1",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 1"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 2a",
+ "Fan 2b"
+ ],
+ "Name": "Fan 2",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 2"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 3a",
+ "Fan 3b"
+ ],
+ "Name": "Fan 3",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 3"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 4a",
+ "Fan 4b"
+ ],
+ "Name": "Fan 4",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 4"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 5a",
+ "Fan 5b"
+ ],
+ "Name": "Fan 5",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 5"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 6a",
+ "Fan 6b"
+ ],
+ "Name": "Fan 6",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 6"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 7a",
+ "Fan 7b"
+ ],
+ "Name": "Fan 7",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 7"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Name": "Fan 8",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 8"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "BMC Temp"
+ ],
+ "Name": "BMC Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Left Rear Temp"
+ ],
+ "Name": "Left Rear Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Right Rear Board"
+ ],
+ "Name": "Right Rear Board",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "SSB Temp"
+ ],
+ "Name": "SSB Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 75.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR Mem ABCD Temp"
+ ],
+ "Name": "CPU 1 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR Mem ABCD Temp"
+ ],
+ "Name": "CPU 2 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Left",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Right",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "PSU",
+ "Type": "Pid.Zone"
+ },
+ {
+ "Class": "Floor",
+ "Inputs": [
+ "BMC Temp"
+ ],
+ "Name": "BMC Temp LCC",
+ "NegativeHysteresis": 2,
+ "Output": [
+ 50.0,
+ 60.0
+ ],
+ "PositiveHysteresis": 0,
+ "Reading": [
+ 20.0,
+ 30.0
+ ],
+ "Type": "Stepwise",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Address": "0x4A",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "Right Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4E",
+ "Bus": 6,
+ "Name": "Left Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4C",
+ "Bus": 6,
+ "Name": "PCH M.2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4F",
+ "Bus": 6,
+ "Name": "Inlet BRD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "CPU 1",
+ "PresenceGpio": [
+ {
+ "Name": "CPU1_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": [
+ {
+ "Name": "CPU2_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x32",
+ "Bus": 0,
+ "CpuID": 3,
+ "Name": "CPU 3",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x33",
+ "Bus": 0,
+ "CpuID": 4,
+ "Name": "CPU 4",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x34",
+ "Bus": 0,
+ "CpuID": 5,
+ "Name": "CPU 5",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x35",
+ "Bus": 0,
+ "CpuID": 6,
+ "Name": "CPU 6",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x36",
+ "Bus": 0,
+ "CpuID": 7,
+ "Name": "CPU 7",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x37",
+ "Bus": 0,
+ "CpuID": 8,
+ "Name": "CPU 8",
+ "Type": "XeonCPU"
+ },
+ {
+ "Name": "ASD",
+ "BMC_XDP_PRST_IN": {
+ "PinType": "PIN_NONE"
+ },
+ "Type": "ASD"
+ }
+ ],
+ "Name": "CPC Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'CooperCity'})",
+ "OR",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*CPC'})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 157
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json
new file mode 100644
index 000000000..b06f1d266
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json
@@ -0,0 +1,1427 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "P12V_PSU_RIGHT",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 4,
+ "Name": "P12V_PSU_LEFT",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BridgeGpio": [
+ {
+ "Name": "P3VBAT_BRIDGE_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 8,
+ "Name": "PVCCIN_CPU0",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU2",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVDQ_ABCD_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 11,
+ "Name": "PVDQ_EFGH_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 12,
+ "Name": "PVDQ_ABCD_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVDQ_EFGH_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCIO_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Class": "Gpio",
+ "Name": "Chassis Intrusion Sensor",
+ "GpioPolarity": "Low",
+ "Type": "ChassisIntrusionSensor"
+ },
+ {
+ "Direction": "In",
+ "Index": 0,
+ "Name": "Board REV ID0",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 3,
+ "Name": "Board REV ID1",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 8,
+ "Name": "Board SKU ID0",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 9,
+ "Name": "Board SKU ID1",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 10,
+ "Name": "Board SKU ID2",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 11,
+ "Name": "Board SKU ID3",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 12,
+ "Name": "Board SKU ID4",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 18,
+ "Name": "OCP3 PRSNTB0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 19,
+ "Name": "OCP3 PRSNTB1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 20,
+ "Name": "OCP3 PRSNTB2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 21,
+ "Name": "OCP3 PRSNTB3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 24,
+ "Name": "Force BMC Update",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 26,
+ "Name": "OCP PWRGD Aux",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 42,
+ "Name": "CPU1 Memhot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 43,
+ "Name": "CPU2 Memhot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 44,
+ "Name": "Cpu Err0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 45,
+ "Name": "Cpu Err1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 46,
+ "Name": "Platform Reset",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 47,
+ "Name": "CPU PRDY",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 50,
+ "Name": "PCH Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 51,
+ "Name": "Board REV ID2",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 52,
+ "Name": "NMI Event",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 53,
+ "Name": "Board SKU ID5",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 56,
+ "Name": "Rise1 PWRGD",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 57,
+ "Name": "Rise2 PWRGD",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 61,
+ "Name": "Rise3 PWRGD",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "In",
+ "Index": 62,
+ "Name": "Rise4 PWRGD",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 63,
+ "Name": "240VA OC",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 64,
+ "Name": "SYS FAN0 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 65,
+ "Name": "SYS FAN1 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 66,
+ "Name": "SYS FAN2 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 67,
+ "Name": "SYS FAN3 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 68,
+ "Name": "SASM ROC ID0",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 69,
+ "Name": "SASM ROC ID1",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 70,
+ "Name": "Midplane Switch ID0",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 71,
+ "Name": "Midplane Switch ID1",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 137,
+ "Name": "PCA9555 Intr",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 138,
+ "Name": "SYS FAN4 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 139,
+ "Name": "SYS FAN5 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 140,
+ "Name": "SYS FAN6 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 141,
+ "Name": "SYS FAN7 PRSNT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 144,
+ "Name": "Remote Debug Enable",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 146,
+ "Name": "RSMRST",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 218,
+ "Name": "ID Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 232,
+ "Name": "CPU1 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 233,
+ "Name": "CPU1 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 234,
+ "Name": "CPU1 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 235,
+ "Name": "CPU1 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 236,
+ "Name": "CPU1 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 237,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 238,
+ "Name": "CPU1 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 239,
+ "Name": "CPU1 ID1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 240,
+ "Name": "CPU1 Mismatch",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 241,
+ "Name": "CPU1 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 242,
+ "Name": "CPU2 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 243,
+ "Name": "CPU2 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 244,
+ "Name": "CPU2 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 245,
+ "Name": "CPU2 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 246,
+ "Name": "CPU2 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 247,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 248,
+ "Name": "CPU2 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 249,
+ "Name": "CPU2 ID1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 250,
+ "Name": "CPU2 Mismatch",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 251,
+ "Name": "CPU2 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 272,
+ "Name": "PLD Minor Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 273,
+ "Name": "PLD Minor Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 274,
+ "Name": "PLD Minor Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 275,
+ "Name": "PLD Minor Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 276,
+ "Name": "PLD Minor Revison Bit 4",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 277,
+ "Name": "PLD Minor Revison Bit 5",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 278,
+ "Name": "PLD Minor Revison Bit 6",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 279,
+ "Name": "PLD Minor Revison Bit 7",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 280,
+ "Name": "Main PLD Major Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 281,
+ "Name": "Main PLD Major Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 282,
+ "Name": "Main PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 283,
+ "Name": "Main PLD Major Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 284,
+ "Name": "Main PLD Major Revison Bit 4",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 285,
+ "Name": "Main PLD Major Revison Bit 5",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 286,
+ "Name": "Main PLD Major Revison Bit 6",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 287,
+ "Name": "Main PLD Major Revison Bit 7",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 289,
+ "Name": "Memory Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 290,
+ "Name": "CPU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 291,
+ "Name": "P3V3 Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 292,
+ "Name": "PSU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 295,
+ "Name": "PCH Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2_Slot1",
+ "M2_Slot2",
+ "",
+ ""
+ ],
+ "Name": "M.2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x70",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot1",
+ "U2_Slot2",
+ "U2_Slot3",
+ "U2_Slot4"
+ ],
+ "Name": "HSBP 1 Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x74",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot5",
+ "U2_Slot6",
+ "U2_Slot7",
+ "U2_Slot8"
+ ],
+ "Name": "HSBP 1 Mux2",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x77",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot1",
+ "U2_Slot2",
+ "U2_Slot3",
+ "U2_Slot4"
+ ],
+ "Name": "HSBP 2 Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot5",
+ "U2_Slot6",
+ "U2_Slot7",
+ "U2_Slot8"
+ ],
+ "Name": "HSBP 2 Mux2",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x76",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot1",
+ "U2_Slot2",
+ "U2_Slot3",
+ "U2_Slot4"
+ ],
+ "Name": "HSBP 3 Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 4,
+ "ChannelNames": [
+ "U2_Slot5",
+ "U2_Slot6",
+ "U2_Slot7",
+ "U2_Slot8"
+ ],
+ "Name": "HSBP 3 Mux2",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x4D",
+ "Bus": 6,
+ "Name": "CPU0 VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP421"
+ },
+ {
+ "Address": "0x4F",
+ "Bus": 6,
+ "Name": "CPU1 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP421"
+ },
+ {
+ "Address": "0x4A",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "RightRear Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4E",
+ "Bus": 6,
+ "Name": "LeftRear Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4C",
+ "Bus": 6,
+ "Name": "PCH DS Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "CYP Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'M50CYP2SB2U'})",
+ "OR",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*CYP'})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 152
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json
new file mode 100644
index 000000000..84ff6f12f
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json
@@ -0,0 +1,91 @@
+[
+ {
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "FCXXPDBASSMBL Fru",
+ "Type": "24C01"
+ },
+ {
+ "Address": "0x18",
+ "Bus": "$bus",
+ "Name": "Multi Node Presence Detector",
+ "Type": "MultiNodePresence"
+ },
+ {
+ "Address": "0x48",
+ "Bus": "$bus",
+ "Name": "PDB Temp1",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x49",
+ "Bus": "$bus",
+ "Name": "PDB Temp2",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "FCXXPDBASSMBL PDB",
+ "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'FCXXPDBASSMBL', 'ADDRESS' : 85})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/J85894-HSBP.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/J85894-HSBP.json
new file mode 100644
index 000000000..792df2dcf
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/J85894-HSBP.json
@@ -0,0 +1,92 @@
+{
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "J85894 HSBP FRU",
+ "Type": "EEPROM"
+ },
+ {
+ "Address": "0x68",
+ "Bus": "$bus",
+ "Index": "$index",
+ "Name": "J85894 HSBP $index",
+ "Type": "Intel HSBP CPLD"
+ },
+ {
+ "Address": "0x74",
+ "Bus": "$bus",
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "Pcie_Slot_3",
+ "Pcie_Slot_4"
+ ],
+ "Name": "HSBP $index Mux 1",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x70",
+ "Bus": "$bus",
+ "ChannelNames": [
+ "Pcie_Slot_5",
+ "Pcie_Slot_6",
+ "Pcie_Slot_7",
+ "Pcie_Slot_8"
+ ],
+ "Name": "HSBP $index Mux 2",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x4b",
+ "Bus": "$bus",
+ "Name": "HSBP $index Temp",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 57
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 52
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 12
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 7
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "J85894 HSBP $index",
+ "PowerState": "On",
+ "Probe": [
+ "FOUND('WC Baseboard')",
+ "OR",
+ "FOUND('WP Baseboard')",
+ "OR",
+ "FOUND('CPC Baseboard')",
+ "AND",
+ "xyz.openbmc_project.Inventory.Item.I2CDevice({'Bus': 4, 'Address': 82})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json
new file mode 100644
index 000000000..53edbfe87
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json
@@ -0,0 +1,104 @@
+[
+ {
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "Midplane 1 Fru",
+ "Type": "EEPROM"
+ },
+ {
+ "Address": "0x4E",
+ "Bus": "$bus",
+ "Name": "Midplane 1 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "Midplane 1",
+ "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U2X12SWITCH', 'ADDRESS' : 86})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+ },
+ {
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "Midplane 2 Fru",
+ "Type": "EEPROM"
+ },
+ {
+ "Address": "0x4F",
+ "Bus": "$bus",
+ "Name": "Midplane 2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "Midplane 2",
+ "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U2X12SWITCH', 'ADDRESS' : 87})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+ }
+] \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json
new file mode 100644
index 000000000..a81329787
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json
@@ -0,0 +1,49 @@
+{
+ "Exposes": [
+ {
+ "Address": "0x56",
+ "Bus": 9,
+ "Class": "MCUTemp",
+ "Name": "PDB MCU Temp",
+ "Reg": "0x22",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "MCUTempSensor"
+ }
+ ],
+ "Name": "OPB2RH Chassis",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'FCXXPDBASSMBL'})"
+ ],
+ "Type": "Chassis",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "Intel Corporation",
+ "Model": "OPB2RH",
+ "PartNumber": "R1234",
+ "SerialNumber": "12345"
+ }
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json
new file mode 100644
index 000000000..24a65437e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json
@@ -0,0 +1,1777 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "Baseboard 12 Volt",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 4,
+ "Name": "P0V83_LAN_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 0.901
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 0.875
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.786
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.763
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BridgeGpio": [
+ {
+ "Name": "P3VBAT_BRIDGE_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 8,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU2",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCIO_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVDQ_ABCD_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 12,
+ "Name": "PVDQ_ABCD_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 11,
+ "Name": "PVDQ_EFGH_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVDQ_EFGH_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Direction": "Input",
+ "Index": 214,
+ "Name": "Nmi Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 232,
+ "Name": "Post Complete led0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 233,
+ "Name": "Post Complete led1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 233,
+ "Name": "CPU1 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 234,
+ "Name": "Post Complete led2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 234,
+ "Name": "CPU1 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 235,
+ "Name": "Post Complete led3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 236,
+ "Name": "Post Complete led4",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 236,
+ "Name": "CPU1 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 237,
+ "Name": "Post Complete led5",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 237,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 238,
+ "Name": "Post Complete led6",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 239,
+ "Name": "Post Complete led7",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 232,
+ "Name": "CPU1 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 235,
+ "Name": "CPU1 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 238,
+ "Name": "CPU1 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 240,
+ "Name": "CPU1 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 240,
+ "Name": "CPU1 Mismatch",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 241,
+ "Name": "CPU1 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 241,
+ "Name": "CPU1 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 242,
+ "Name": "CPU1 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 242,
+ "Name": "CPU2 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 243,
+ "Name": "CPU1 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 243,
+ "Name": "CPU2 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 244,
+ "Name": "CPU1 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 244,
+ "Name": "CPU2 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 245,
+ "Name": "CPU1 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 245,
+ "Name": "CPU2 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 246,
+ "Name": "CPU1 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 246,
+ "Name": "CPU2 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 247,
+ "Name": "CPU1 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 247,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 248,
+ "Name": "CPU1 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 248,
+ "Name": "CPU2 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 249,
+ "Name": "CPU1 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 250,
+ "Name": "CPU1 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 250,
+ "Name": "CPU2 Mismatch",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 251,
+ "Name": "CPU1 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 251,
+ "Name": "CPU2 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 252,
+ "Name": "Fan1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 253,
+ "Name": "Fan2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 254,
+ "Name": "Fan3 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 255,
+ "Name": "Fan4 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 256,
+ "Name": "Fan5 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 257,
+ "Name": "Fan6 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 258,
+ "Name": "Fan7 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 259,
+ "Name": "Fan8 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 260,
+ "Name": "CPU2 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 261,
+ "Name": "CPU2 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 262,
+ "Name": "CPU2 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 263,
+ "Name": "CPU2 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 264,
+ "Name": "CPU2 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 265,
+ "Name": "CPU2 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 266,
+ "Name": "CPU2 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 267,
+ "Name": "CPU2 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 268,
+ "Name": "CPU2 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 269,
+ "Name": "CPU2 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 270,
+ "Name": "CPU2 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 271,
+ "Name": "CPU2 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 272,
+ "Name": "CPU3 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 272,
+ "Name": "PLD Minor Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 273,
+ "Name": "CPU3 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 273,
+ "Name": "PLD Minor Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 274,
+ "Name": "CPU3 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 274,
+ "Name": "PLD Minor Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 275,
+ "Name": "CPU3 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 275,
+ "Name": "PLD Minor Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 276,
+ "Name": "CPU3 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 276,
+ "Name": "PLD Major Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 277,
+ "Name": "CPU3 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 277,
+ "Name": "PLD Major Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 278,
+ "Name": "CPU3 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 278,
+ "Name": "PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 279,
+ "Name": "CPU3 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 279,
+ "Name": "PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 280,
+ "Name": "CPU3 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 280,
+ "Name": "Main PLD Minor Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 281,
+ "Name": "CPU3 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 281,
+ "Name": "Main PLD Minor Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 282,
+ "Name": "CPU3 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 282,
+ "Name": "Main PLD Minor Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 283,
+ "Name": "CPU3 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 283,
+ "Name": "Main PLD Minor Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 284,
+ "Name": "CPU4 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 284,
+ "Name": "Main PLD Major Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 285,
+ "Name": "CPU4 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 285,
+ "Name": "Main PLD Major Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 286,
+ "Name": "CPU4 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 286,
+ "Name": "Main PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 287,
+ "Name": "CPU4 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 287,
+ "Name": "Main PLD Major Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 288,
+ "Name": "CPU4 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 289,
+ "Name": "CPU4 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 289,
+ "Name": "Memory Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 290,
+ "Name": "CPU4 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 290,
+ "Name": "CPU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 291,
+ "Name": "CPU4 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 291,
+ "Name": "P5V P3V3 Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 292,
+ "Name": "CPU4 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 292,
+ "Name": "PSU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 293,
+ "Name": "CPU4 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 293,
+ "Name": "SAS Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 294,
+ "Name": "CPU4 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 294,
+ "Name": "Lan Aux Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 295,
+ "Name": "CPU4 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 295,
+ "Name": "PCH Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 27,
+ "Name": "Node ID GPIO 0",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 26,
+ "Name": "Node ID GPIO 1",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Name": "CPU 1 Fan Connector",
+ "Pwm": 7,
+ "Status": "disabled",
+ "Tachs": [
+ 13
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "CPU 2 Fan Connector",
+ "Pwm": 8,
+ "Status": "disabled",
+ "Tachs": [
+ 14
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x7c",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x70",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x74",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem ABC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x78",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem DEF Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x9c",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x50",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x94",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem ABC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x98",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem DEF Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xAC",
+ "Class": "PxeBridgeTemp",
+ "Name": "VR P1V05 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x20",
+ "Bus": 10,
+ "Class": "NodePower",
+ "Name": "Node Power",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 255
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 250
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "MP5920"
+ },
+ {
+ "GpioPins": [
+ 27,
+ 26
+ ],
+ "Name": "Multi Node ID",
+ "Type": "MultiNodeID"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2_Slot1",
+ "M2_Slot2",
+ "",
+ ""
+ ],
+ "Name": "M.2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x4E",
+ "Bus": 6,
+ "Name": "Exit Air Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "Inlet Air Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "CPU 1",
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "TNP Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'D50TNP1SB'})",
+ "OR",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*TNP'})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 153
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
new file mode 100644
index 000000000..bfcec8c9f
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
@@ -0,0 +1,2424 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "A_P12V_PSU_SCALED",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BridgeGpio": [
+ {
+ "Name": "P3VBAT_BRIDGE_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 8,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU2",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCIO_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVDQ_ABC_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 12,
+ "Name": "PVDQ_ABC_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 11,
+ "Name": "PVDQ_DEF_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVDQ_DEF_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 0,
+ "Name": "Fan 1a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 1,
+ "Name": "Fan 1b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 2,
+ "Name": "Fan 2a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 3,
+ "Name": "Fan 2b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 4,
+ "Name": "Fan 3a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 5,
+ "Name": "Fan 3b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 6,
+ "Name": "Fan 4a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 7,
+ "Name": "Fan 4b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 8,
+ "Name": "Fan 5a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 9,
+ "Name": "Fan 5b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 10,
+ "Name": "Fan 6a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 11,
+ "Name": "Fan 6b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 12,
+ "Name": "Fan 7a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 13,
+ "Name": "Fan 7b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 14,
+ "Name": "Fan 8a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 15,
+ "Name": "Fan 8b",
+ "Type": "AspeedFan"
+ },
+ {
+ "C1": 92.16,
+ "C2": 107.52,
+ "MaxCFM": 17.5,
+ "Name": "System Airflow",
+ "TachMaxPercent": 100,
+ "TachMinPercent": 20,
+ "Tachs": [
+ "Fan 1a",
+ "Fan 1b",
+ "Fan 2a",
+ "Fan 2b",
+ "Fan 3a",
+ "Fan 3b",
+ "Fan 4a",
+ "Fan 4b",
+ "Fan 5a",
+ "Fan 5b",
+ "Fan 6a",
+ "Fan 6b",
+ "Fan 7a",
+ "Fan 7b",
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Type": "CFMSensor"
+ },
+ {
+ "Name": "System Fan connector 1",
+ "Pwm": 0,
+ "Tachs": [
+ 0,
+ 1
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 2",
+ "Pwm": 1,
+ "Tachs": [
+ 2,
+ 3
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 3",
+ "Pwm": 2,
+ "Tachs": [
+ 4,
+ 5
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 4",
+ "Pwm": 3,
+ "Tachs": [
+ 6,
+ 7
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 5",
+ "Pwm": 4,
+ "Tachs": [
+ 8,
+ 9
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 6",
+ "Pwm": 5,
+ "Tachs": [
+ 10,
+ 11
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 7",
+ "Pwm": 6,
+ "Tachs": [
+ 12,
+ 13
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 8",
+ "Pwm": 7,
+ "Tachs": [
+ 14,
+ 15
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xC4",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU1 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x4A",
+ "Class": "IRBridgeTemp",
+ "Name": "CPU1 VR P1V8",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xCC",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU2 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xD4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB0",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xEC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x4C",
+ "Class": "IRBridgeTemp",
+ "Name": "CPU2 VR P1V8",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "EthIndex": 0,
+ "Name": "Dedicated Management NIC",
+ "Type": "NIC"
+ },
+ {
+ "EthIndex": 1,
+ "Name": "Host/BMC Shared NIC",
+ "Type": "NIC"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 2 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 9,
+ "ChannelNames": [
+ "MemoryChannel1",
+ "MemoryChannel2",
+ "MemoryChannel3",
+ "MemoryChannel4"
+ ],
+ "Name": "Memory Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x74",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "Pcie_Slot_3",
+ "Pcie_Slot_4"
+ ],
+ "Name": "PCIE Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Interface": [
+ "i2c",
+ "peci"
+ ],
+ "Name": "PMEM",
+ "Pmem": [
+ {
+ "Channel": 0,
+ "DeviceID": 1,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 2,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 3,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 4,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 5,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 6,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 7,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 8,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 9,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 10,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 11,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 12,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 13,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 14,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 15,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 16,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 17,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 18,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 19,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 20,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 21,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 22,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 23,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 24,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 25,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 26,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 27,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 28,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 29,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 30,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 31,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 32,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ }
+ ],
+ "Type": "PMEM"
+ },
+ {
+ "Address": [
+ "0x50",
+ "0x51"
+ ],
+ "Bus": 7,
+ "Name": "PSU address",
+ "Type": "PSUPresence"
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Exit Air Temp"
+ ],
+ "Name": "Exit Air Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 65.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 1a",
+ "Fan 1b"
+ ],
+ "Name": "Fan 1",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 1"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 2a",
+ "Fan 2b"
+ ],
+ "Name": "Fan 2",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 2"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 3a",
+ "Fan 3b"
+ ],
+ "Name": "Fan 3",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 3"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 4a",
+ "Fan 4b"
+ ],
+ "Name": "Fan 4",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 4"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 5a",
+ "Fan 5b"
+ ],
+ "Name": "Fan 5",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 5"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 6a",
+ "Fan 6b"
+ ],
+ "Name": "Fan 6",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 6"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 7a",
+ "Fan 7b"
+ ],
+ "Name": "Fan 7",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 7"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Name": "Fan 8",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 8"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "BMC Temp"
+ ],
+ "Name": "BMC Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Left Rear Temp"
+ ],
+ "Name": "Left Rear Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Right Rear Board"
+ ],
+ "Name": "Right Rear Board",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "SSB Temp"
+ ],
+ "Name": "SSB Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 75.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR P1V8"
+ ],
+ "Name": "CPU 1 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR P1V8"
+ ],
+ "Name": "CPU 2 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Left",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Right",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "PSU",
+ "Type": "Pid.Zone"
+ },
+ {
+ "Address": "0x4A",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "Right Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4e",
+ "Bus": 6,
+ "Name": "Left Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x48",
+ "Bus": 6,
+ "Name": "PCH M.2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4f",
+ "Bus": 6,
+ "Name": "Inlet BRD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "CPU 1",
+ "PresenceGpio": [
+ {
+ "Name": "CPU1_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": [
+ {
+ "Name": "CPU2_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "WC Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'WilsonCity.*'})",
+ "OR",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*WC'})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 145
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json
new file mode 100644
index 000000000..a30626daa
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Chassis.json
@@ -0,0 +1,455 @@
+{
+ "Exposes": [
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 0,
+ "Name": "Fan 1",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 2,
+ "Name": "Fan 2",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 4,
+ "Name": "Fan 3",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 10,
+ "Name": "Fan 4",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 12,
+ "Name": "Fan 5",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 14,
+ "Name": "Fan 6",
+ "Thresholds": [
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1750
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2000
+ }
+ ],
+ "Type": "AspeedFan"
+ },
+ {
+ "C1": 92.16,
+ "C2": 107.52,
+ "MaxCFM": 17.5,
+ "Name": "System Airflow",
+ "TachMaxPercent": 100,
+ "TachMinPercent": 20,
+ "Tachs": [
+ "Fan 1",
+ "Fan 2",
+ "Fan 3",
+ "Fan 4",
+ "Fan 5",
+ "Fan 6"
+ ],
+ "Type": "CFMSensor"
+ },
+ {
+ "DisableNode": [
+ "Fan 1a",
+ "Fan 1b",
+ "Fan 2a",
+ "Fan 2b",
+ "Fan 3a",
+ "Fan 3b",
+ "Fan 4a",
+ "Fan 4b",
+ "Fan 5a",
+ "Fan 5b",
+ "Fan 6a",
+ "Fan 6b",
+ "Fan 7a",
+ "Fan 7b",
+ "Fan 8a",
+ "Fan 8b",
+ "Fan 1",
+ "Fan 2",
+ "Fan 3",
+ "Fan 4",
+ "Fan 5",
+ "Fan 6",
+ "Fan 7",
+ "Fan 8",
+ "System Airflow"
+ ],
+ "Name": "Disable Baseboard Configurations",
+ "Type": "Disable"
+ },
+ {
+ "AlphaF": 4.352,
+ "AlphaS": 0.512,
+ "Name": "Exit Air Temp",
+ "PowerFactorMax": 1.2,
+ "PowerFactorMin": 0.9,
+ "QMax": 165,
+ "QMin": 31,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 85
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 80
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "ExitAirTempSensor"
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -4.64,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Exit Air Temp"
+ ],
+ "Name": "Exit Air Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 75.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 1"
+ ],
+ "Name": "Fan 1",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 1"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 2"
+ ],
+ "Name": "Fan 2",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 2"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 3"
+ ],
+ "Name": "Fan 3",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 3"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 4"
+ ],
+ "Name": "Fan 4",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 6"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 5"
+ ],
+ "Name": "Fan 5",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 7"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 6"
+ ],
+ "Name": "Fan 6",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 8"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "Floor",
+ "Inputs": [
+ "Front Panel Temp"
+ ],
+ "Name": "Front Panel LCC",
+ "NegativeHysteresis": 2,
+ "Output": [
+ 50.0,
+ 60.0
+ ],
+ "PositiveHysteresis": 0,
+ "Reading": [
+ 20.0,
+ 30.0
+ ],
+ "Type": "Stepwise",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "Ceiling",
+ "Inputs": [
+ "Front Panel Temp"
+ ],
+ "Name": "Front Panel UCC",
+ "NegativeHysteresis": 2,
+ "Output": [
+ 70.0,
+ 80.0
+ ],
+ "PositiveHysteresis": 0,
+ "Profiles": [
+ "Acoustic"
+ ],
+ "Reading": [
+ 22.0,
+ 32.0
+ ],
+ "Type": "Stepwise",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ }
+ ],
+ "Name": "R4000 Chassis",
+ "Probe": [
+ "FOUND('Intel Front Panel')",
+ "AND",
+ "FOUND('WC Baseboard')",
+ "AND",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'WilsonCity'})"
+ ],
+ "Type": "Chassis",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ }
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
new file mode 100644
index 000000000..7b128099f
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
@@ -0,0 +1,2415 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "A_P12V_PSU_SCALED",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BridgeGpio": [
+ {
+ "Name": "P3VBAT_BRIDGE_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 8,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU2",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCIO_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVDQ_ABC_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 12,
+ "Name": "PVDQ_ABC_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 11,
+ "Name": "PVDQ_DEF_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVDQ_DEF_CPU2",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 0,
+ "Name": "Fan 1a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 1,
+ "Name": "Fan 1b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 2,
+ "Name": "Fan 2a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 3,
+ "Name": "Fan 2b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 4,
+ "Name": "Fan 3a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 5,
+ "Name": "Fan 3b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 6,
+ "Name": "Fan 4a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 7,
+ "Name": "Fan 4b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 8,
+ "Name": "Fan 5a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 9,
+ "Name": "Fan 5b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 10,
+ "Name": "Fan 6a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 11,
+ "Name": "Fan 6b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 12,
+ "Name": "Fan 7a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 13,
+ "Name": "Fan 7b",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 14,
+ "Name": "Fan 8a",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 15,
+ "Name": "Fan 8b",
+ "Type": "AspeedFan"
+ },
+ {
+ "C1": 92.16,
+ "C2": 107.52,
+ "MaxCFM": 17.5,
+ "Name": "System Airflow",
+ "TachMaxPercent": 100,
+ "TachMinPercent": 20,
+ "Tachs": [
+ "Fan 1a",
+ "Fan 1b",
+ "Fan 2a",
+ "Fan 2b",
+ "Fan 3a",
+ "Fan 3b",
+ "Fan 4a",
+ "Fan 4b",
+ "Fan 5a",
+ "Fan 5b",
+ "Fan 6a",
+ "Fan 6b",
+ "Fan 7a",
+ "Fan 7b",
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Type": "CFMSensor"
+ },
+ {
+ "Pmem": [
+ {
+ "Channel": 0,
+ "DeviceID": 1,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 2,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 3,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 4,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 0,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 5,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 6,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 7,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 8,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel1",
+ "Imc": 1,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 9,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 10,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 11,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 12,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 2,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 13,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 14,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 15,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 0,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 16,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel2",
+ "Imc": 3,
+ "Pecibus": "0x30",
+ "Slot": 1,
+ "Socket": 0,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 17,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 18,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 19,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 20,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 0,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 21,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 22,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 23,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 24,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel3",
+ "Imc": 1,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 0,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 25,
+ "I2cAddress": "0xB0",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 26,
+ "I2cAddress": "0xB2",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 27,
+ "I2cAddress": "0xB4",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 28,
+ "I2cAddress": "0xB6",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 2,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 29,
+ "I2cAddress": "0xB8",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 0,
+ "DeviceID": 30,
+ "I2cAddress": "0xBA",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 31,
+ "I2cAddress": "0xBC",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 0,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ },
+ {
+ "Channel": 1,
+ "DeviceID": 32,
+ "I2cAddress": "0xBE",
+ "I2cbus": "MemoryChannel4",
+ "Imc": 3,
+ "Pecibus": "0x31",
+ "Slot": 1,
+ "Socket": 1,
+ "Spdpcibus": "0x7E",
+ "Spdpcicmdregister": "0x80",
+ "Spdpcidataregister": "0x88",
+ "Spdpcidevice": 11,
+ "Spdpcifunction": 1,
+ "Spdpcistatusregister": "0x84"
+ }
+ ],
+ "Interface": [
+ "i2c",
+ "peci"
+ ],
+ "Name": "PMEM",
+ "Type": "PMEM"
+ },
+ {
+ "Name": "System Fan connector 1",
+ "Pwm": 0,
+ "Tachs": [
+ 0,
+ 1
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 2",
+ "Pwm": 1,
+ "Tachs": [
+ 2,
+ 3
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 3",
+ "Pwm": 2,
+ "Tachs": [
+ 4,
+ 5
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 4",
+ "Pwm": 3,
+ "Tachs": [
+ 6,
+ 7
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 5",
+ "Pwm": 4,
+ "Tachs": [
+ 8,
+ 9
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 6",
+ "Pwm": 5,
+ "Tachs": [
+ 10,
+ 11
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 7",
+ "Pwm": 6,
+ "Tachs": [
+ 12,
+ 13
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 8",
+ "Pwm": 7,
+ "Tachs": [
+ 14,
+ 15
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xC4",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU1 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xDC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x4A",
+ "Class": "IRBridgeTemp",
+ "Name": "CPU1 VR P1V8",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xCC",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU2 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xD4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xB0",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem ABCD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xEC",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem EFGH Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x4C",
+ "Class": "IRBridgeTemp",
+ "Name": "CPU2 VR P1V8",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "EthIndex": 0,
+ "Name": "Dedicated Management NIC",
+ "Type": "NIC"
+ },
+ {
+ "EthIndex": 1,
+ "Name": "Host/BMC Shared NIC",
+ "Type": "NIC"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 2 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 9,
+ "ChannelNames": [
+ "MemoryChannel1",
+ "MemoryChannel2",
+ "MemoryChannel3",
+ "MemoryChannel4"
+ ],
+ "Name": "Memory Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x74",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "Pcie_Slot_3",
+ "Pcie_Slot_4"
+ ],
+ "Name": "PCIE Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Exit Air Temp"
+ ],
+ "Name": "Exit Air Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 65.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 1a",
+ "Fan 1b"
+ ],
+ "Name": "Fan 1",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 1"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 2a",
+ "Fan 2b"
+ ],
+ "Name": "Fan 2",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 2"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 3a",
+ "Fan 3b"
+ ],
+ "Name": "Fan 3",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 3"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 4a",
+ "Fan 4b"
+ ],
+ "Name": "Fan 4",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 4"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 5a",
+ "Fan 5b"
+ ],
+ "Name": "Fan 5",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 5"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 6a",
+ "Fan 6b"
+ ],
+ "Name": "Fan 6",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 6"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 7a",
+ "Fan 7b"
+ ],
+ "Name": "Fan 7",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 7"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 8a",
+ "Fan 8b"
+ ],
+ "Name": "Fan 8",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 8"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "BMC Temp"
+ ],
+ "Name": "BMC Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Left Rear Temp"
+ ],
+ "Name": "Left Rear Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Right Rear Board"
+ ],
+ "Name": "Right Rear Board",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "SSB Temp"
+ ],
+ "Name": "SSB Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 75.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR P1V8"
+ ],
+ "Name": "CPU 1 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR P1V8"
+ ],
+ "Name": "CPU 2 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Left",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Right",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "PSU",
+ "Type": "Pid.Zone"
+ },
+ {
+ "Address": "0x4A",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "Right Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4e",
+ "Bus": 6,
+ "Name": "Left Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x48",
+ "Bus": 6,
+ "Name": "PCH M.2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4f",
+ "Bus": 6,
+ "Name": "Inlet BRD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "CPU 1",
+ "PresenceGpio": [
+ {
+ "Name": "CPU1_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": [
+ {
+ "Name": "CPU2_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "WP Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'WilsonPoint'})",
+ "OR",
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*WP'})"
+ ],
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 154
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend
new file mode 100644
index 000000000..6528bd513
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,19 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+SRC_URI_append = " file://0001-Blacklist-DIMM-Bus.patch \
+ file://WC-Baseboard.json \
+ file://WP-Baseboard.json \
+ file://TNP-baseboard.json \
+ file://FCXXPDBASSMBL_PDB.json \
+ file://OPB2RH-Chassis.json \
+ file://CYP-baseboard.json \
+ file://J85894-HSBP.json \
+ file://CPC-Baseboard.json \
+ file://MIDPLANE-2U2X12SWITCH.json \
+ file://WC-Chassis.json"
+
+RDEPENDS_${PN} += " default-fru"
+
+do_install_append() {
+ install -d ${D}/usr/share/entity-manager/configurations
+ install -m 0444 ${WORKDIR}/*.json ${D}/usr/share/entity-manager/configurations
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console.conf b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console.conf
new file mode 100644
index 000000000..1d332e2a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console.conf
@@ -0,0 +1,3 @@
+baud = 921600
+local-tty = ttyS3
+local-tty-baud = 921600
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console@.service b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console@.service
new file mode 100644
index 000000000..7fb8f79d3
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/obmc-console@.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=Phosphor Console Muxer listening on device /dev/%I
+BindsTo=dev-%i.device
+After=dev-%i.device
+
+[Service]
+ExecStartPre=/usr/bin/sol-option-check.sh
+ExecStartPre=/bin/sh -c 'echo -n "uart3" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart1'
+ExecStartPre=/bin/sh -c 'echo -n "uart1" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart3'
+ExecStartPre=/bin/sh -c 'echo -n "io1" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart4'
+ExecStartPre=/bin/sh -c 'echo -n "uart4" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/io1'
+ExecStart=/usr/bin/env obmc-console-server --config {sysconfdir}/obmc-console.conf %i
+ExecStopPost=/bin/sh -c 'echo -n "io1" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart1'
+ExecStopPost=/bin/sh -c 'echo -n "io3" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart3'
+ExecStopPost=/bin/sh -c 'echo -n "io4" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/uart4'
+ExecStopPost=/bin/sh -c 'echo -n "uart1" > /sys/bus/platform/drivers/aspeed-uart-routing/1e78909c.uart_routing/io1'
+SyslogIdentifier=obmc-console-server
+Restart=always
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/sol-option-check.sh b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/sol-option-check.sh
new file mode 100755
index 000000000..ef32fcb9a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console/sol-option-check.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+if [ $(grep 192000000 /sys/class/tty/ttyS0/uartclk | wc -l) != 0 ]; then
+ echo "hs-uart"
+ sed -i -e 's/115200/921600/g' /etc/obmc-console.conf
+else
+ echo "normal uart"
+ sed -i -e 's/921600/115200/g' /etc/obmc-console.conf
+fi
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console_%.bbappend
new file mode 100644
index 000000000..7baf1cabc
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console_%.bbappend
@@ -0,0 +1,17 @@
+FILESEXTRAPATHS_prepend_intel-ast2500 := "${THISDIR}/${PN}:"
+OBMC_CONSOLE_HOST_TTY = "ttyS2"
+SRC_URI += "file://sol-option-check.sh \
+ file://obmc-console@.service \
+ "
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE_${PN} += " \
+ ${PN}@${OBMC_CONSOLE_HOST_TTY}.service \
+ "
+
+do_install_append() {
+ rm -rf ${D}${base_libdir}/udev/rules.d/80-obmc-console-uart.rules
+ install -m 0644 ${WORKDIR}/${PN}@.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/sol-option-check.sh ${D}${bindir}
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch
new file mode 100644
index 000000000..ea7ca092c
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors/0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch
@@ -0,0 +1,36 @@
+From d06d0a8fabd699fc1cab4fbd6e4572ce0b22a905 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 23 Apr 2020 14:01:38 -0700
+Subject: [PATCH 1/1] Only allow drive sensors on bus 2 for ast2500
+
+CPLD doesn't allow multi-master, so readings wont work.
+Put in a work-around to only allow bus 2 transactions.
+
+Tested: Only valid sensors were installed.
+
+Change-Id: Ib9e75ffd0dd64cf548d15cce9a6052332ac5ec43
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ src/NVMeSensorMain.cpp | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/NVMeSensorMain.cpp b/src/NVMeSensorMain.cpp
+index 1858ea9..844f061 100644
+--- a/src/NVMeSensorMain.cpp
++++ b/src/NVMeSensorMain.cpp
+@@ -111,6 +111,12 @@ void createSensors(boost::asio::io_service& io,
+ rootBus = std::stoi(rootName.substr(0, dash));
+ }
+
++ // HACK: cpld on current products doesn't allow multi-master
++ if (rootBus != 2)
++ {
++ continue;
++ }
++
+ std::shared_ptr<NVMeContext> context;
+ auto findRoot = nvmeDeviceMap.find(rootBus);
+ if (findRoot != nvmeDeviceMap.end())
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend
new file mode 100644
index 000000000..1c8817772
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Only-allow-drive-sensors-on-bus-2-for-ast2500.patch"
diff --git a/meta-openbmc-mods/meta-ast2500/recipes.txt b/meta-openbmc-mods/meta-ast2500/recipes.txt
new file mode 100644
index 000000000..2f89155c3
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes.txt
@@ -0,0 +1,3 @@
+recipes-bsp - Anything with links to specific hardware or hardware configuration information
+recipes-kernel - The kernel and generic applications/libraries with strong kernel dependencies
+recipes-phosphor - Phosphor OpenBMC applications and configuration
diff --git a/meta-openbmc-mods/meta-ast2600/conf/layer.conf b/meta-openbmc-mods/meta-ast2600/conf/layer.conf
new file mode 100644
index 000000000..9c44d9b48
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/conf/layer.conf
@@ -0,0 +1,21 @@
+LOCALCONF_VERSION = "3"
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "ast2600"
+BBFILE_PATTERN_ast2600 = ""
+BBFILE_PRIORITY_ast2600 = "4"
+LAYERSERIES_COMPAT_ast2600 = "warrior zeus"
+
+INHERIT += "extrausers"
+#INHERIT += " cve-check"
+
+EXTRA_USERS_PARAMS_append_pn-intel-platforms = " \
+ usermod -p '\$1\$UGMqyqdG\$FZiylVFmRRfl9Z0Ue8G7e/' root; \
+ "
+
+hostname_pn-base-files = "intel-obmc"
diff --git a/meta-openbmc-mods/meta-ast2600/conf/machine/include/intel-ast2600.inc b/meta-openbmc-mods/meta-ast2600/conf/machine/include/intel-ast2600.inc
new file mode 100644
index 000000000..7f323f4e2
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/conf/machine/include/intel-ast2600.inc
@@ -0,0 +1,20 @@
+COMPATIBLE_MACHINE_intel-ast2600 = "intel-ast2600"
+KMACHINE = "aspeed"
+KERNEL_DEVICETREE = "${KMACHINE}-bmc-${COMPATIBLE_MACHINE}.dtb"
+#KERNEL_DEVICETREE = "${KMACHINE}-ast2600-evb.dtb"
+
+require conf/machine/include/ast2600.inc
+require conf/machine/include/obmc-bsp-si-common.inc
+require conf/machine/include/intel.inc
+require conf/distro/include/phosphor-tiny.inc
+
+TARGET_FPU = "hard"
+
+PREFERRED_PROVIDER_u-boot-fw-utils ?= "u-boot-fw-utils-aspeed-sdk"
+
+UBOOT_MACHINE = "ast2600_openbmc_defconfig"
+UBOOT_DEVICETREE = "ast2600-intel"
+
+VIRTUAL-RUNTIME_skeleton_workbook = "${MACHINE}-config"
+
+IMAGE_CLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'image_types_intel_pfr', '', d)}"
diff --git a/meta-openbmc-mods/meta-ast2600/conf/machine/include/obmc-bsp-si-common.inc b/meta-openbmc-mods/meta-ast2600/conf/machine/include/obmc-bsp-si-common.inc
new file mode 100644
index 000000000..f5a0d9ad0
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/conf/machine/include/obmc-bsp-si-common.inc
@@ -0,0 +1,41 @@
+#@TYPE: Machine
+#@NAME: OpenBMC
+#@DESCRIPTION: Common machine configuration for OpenBMC chips
+
+MACHINE_EXTRA_RRECOMMENDS = " kernel-modules"
+EXTRA_IMAGEDEPENDS += "u-boot"
+
+IMAGE_FSTYPES += "squashfs-xz"
+IMAGE_FSTYPES += "mtd-auto"
+EXTRA_IMAGECMD_squashfs-xz_append = "-processors ${BB_NUMBER_THREADS} -b 262144 -Xdict-size 100% -Xbcj arm"
+
+KERNEL_CLASSES ?= "kernel-fitimage"
+KERNEL_IMAGETYPES ?= "fitImage"
+KERNEL_EXTRA_ARGS += "LOADADDR=${UBOOT_ENTRYPOINT}"
+
+UBOOT_SUFFIX ?= "bin"
+
+MACHINEOVERRIDES =. "openbmc:"
+
+OBMC_PHOSPHOR_IMAGE_OVERLAY= "1"
+OBMC_IMAGE_EXTRA_INSTALL_append = "u-boot-fw-utils-aspeed-sdk"
+
+IMAGE_CLASSES += "image_types image_types_phosphor_auto qemuboot"
+
+# do not generate an initramfs; use the above squashfs-xz as an initrd instead
+INITRAMFS_FSTYPES = ""
+INITRAMFS_CTYPE = ""
+INITRAMFS_IMAGE = ""
+
+MACHINE_FEATURES_BACKFILL_CONSIDERED = "qemu-usermode"
+
+KERNEL_IMAGETYPES += "zImage"
+
+# runqemu
+QB_SYSTEM_NAME = "qemu-system-arm"
+QB_DEFAULT_FSTYPE = "mtd"
+QB_ROOTFS_OPT = "-drive file=@ROOTFS@,format=raw,if=mtd"
+QB_MACHINE = "-M intel-ast2600"
+QB_OPT_APPEND += " -nographic"
+QB_NETWORK_DEVICE = "-net nic,macaddr=C0:FF:EE:00:00:02,model=ftgmac100"
+QB_DEFAULT_KERNEL = "none"
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0001-Add-ast2600-intel-as-a-new-board.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0001-Add-ast2600-intel-as-a-new-board.patch
new file mode 100644
index 000000000..1fbb464b8
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0001-Add-ast2600-intel-as-a-new-board.patch
@@ -0,0 +1,1373 @@
+From 2cec5042f3b33c6762073deb9275a66875538d82 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Thu, 24 Oct 2019 14:06:33 -0700
+Subject: [PATCH] Add ast2600-intel as a new board
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/dts/Makefile | 3 +-
+ arch/arm/dts/ast2600-intel.dts | 197 ++++++++++++++++
+ arch/arm/lib/interrupts.c | 5 +
+ arch/arm/mach-aspeed/ast2600/Kconfig | 8 +
+ board/aspeed/ast2600_intel/Kconfig | 13 ++
+ board/aspeed/ast2600_intel/Makefile | 4 +
+ board/aspeed/ast2600_intel/ast-espi.c | 292 ++++++++++++++++++++++++
+ board/aspeed/ast2600_intel/ast-irq.c | 399 +++++++++++++++++++++++++++++++++
+ board/aspeed/ast2600_intel/ast-irq.h | 8 +
+ board/aspeed/ast2600_intel/ast-timer.c | 59 +++++
+ board/aspeed/ast2600_intel/intel.c | 192 ++++++++++++++++
+ cmd/Kconfig | 2 +-
+ common/autoboot.c | 10 +
+ configs/ast2600_openbmc_defconfig | 2 +-
+ 14 files changed, 1191 insertions(+), 3 deletions(-)
+ create mode 100644 arch/arm/dts/ast2600-intel.dts
+ create mode 100644 board/aspeed/ast2600_intel/Kconfig
+ create mode 100644 board/aspeed/ast2600_intel/Makefile
+ create mode 100644 board/aspeed/ast2600_intel/ast-espi.c
+ create mode 100644 board/aspeed/ast2600_intel/ast-irq.c
+ create mode 100644 board/aspeed/ast2600_intel/ast-irq.h
+ create mode 100644 board/aspeed/ast2600_intel/ast-timer.c
+ create mode 100644 board/aspeed/ast2600_intel/intel.c
+
+diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
+index e4dae2937968..da8903123999 100644
+--- a/arch/arm/dts/Makefile
++++ b/arch/arm/dts/Makefile
+@@ -683,7 +683,8 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
+ ast2600-fpga.dtb \
+ ast2600-rainier.dtb \
+ ast2600-slt.dtb \
+- ast2600-tacoma.dtb
++ ast2600-tacoma.dtb \
++ ast2600-intel.dtb
+
+ dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
+
+diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts
+new file mode 100644
+index 000000000000..9a15e204f83b
+--- /dev/null
++++ b/arch/arm/dts/ast2600-intel.dts
+@@ -0,0 +1,197 @@
++// SPDX-License-Identifier: GPL-2.0+
++// Copyright (c) 2019-2020 Intel Corporation
++/dts-v1/;
++
++#include "ast2600-u-boot.dtsi"
++
++/ {
++ memory {
++ device_type = "memory";
++ reg = <0x80000000 0x40000000>;
++ };
++
++ chosen {
++ stdout-path = &uart5;
++ };
++
++ aliases {
++ spi0 = &fmc;
++ ethernet1 = &mac1;
++ };
++
++ cpus {
++ cpu@0 {
++ clock-frequency = <800000000>;
++ };
++ cpu@1 {
++ clock-frequency = <800000000>;
++ };
++ };
++
++ system-leds {
++ compatible = "gpio-leds";
++ green-led {
++ label = "green";
++ gpios = <&gpio0 50 GPIO_ACTIVE_LOW>;
++ default-state = "blink";
++ };
++ amber-led {
++ label = "amber";
++ gpios = <&gpio0 51 GPIO_ACTIVE_LOW>;
++ default-state = "off";
++ };
++ id-led {
++ label = "id";
++ gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
++ default-state = "blink";
++ };
++ hb-led {
++ label = "hb";
++ gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "heartbeat";
++ };
++ };
++};
++
++&gpio0 {
++ status = "okay";
++};
++
++&uart1 {
++ status = "okay";
++};
++
++&uart2 {
++ status = "okay";
++};
++
++&uart5 {
++ u-boot,dm-pre-reloc;
++ status = "okay";
++};
++
++&sdrammc {
++ clock-frequency = <400000000>;
++};
++
++&wdt1 {
++ u-boot,dm-pre-reloc;
++ status = "okay";
++};
++
++&wdt2 {
++ u-boot,dm-pre-reloc;
++ status = "okay";
++};
++
++&wdt3 {
++ u-boot,dm-pre-reloc;
++ status = "okay";
++};
++
++&mdio {
++ status = "okay";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ ethphy1: ethernet-phy@1 {
++ reg = <0>;
++ };
++
++ ethphy2: ethernet-phy@2 {
++ reg = <0>;
++ };
++
++ ethphy3: ethernet-phy@3 {
++ reg = <0>;
++ };
++
++ ethphy4: ethernet-phy@4 {
++ reg = <0>;
++ };
++};
++
++&mac1 {
++ status = "okay";
++ phy-mode = "rgmii";
++ phy-handle = <&ethphy2>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mac2link_default &pinctrl_mdio2_default>;
++};
++
++&fmc {
++ status = "okay";
++#if 0
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_fmcquad_default>;
++#endif
++ flash@0 {
++ compatible = "spi-flash", "sst,w25q256";
++ status = "okay";
++ spi-max-frequency = <40000000>;
++ spi-tx-bus-width = <2>;
++ spi-rx-bus-width = <2>;
++ };
++};
++
++&emmc_slot0 {
++ status = "okay";
++ bus-width = <4>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_emmc_default>;
++};
++
++&i2c4 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c5_default>;
++};
++
++&i2c5 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c6_default>;
++};
++
++&i2c6 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c7_default>;
++};
++
++&i2c7 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c8_default>;
++};
++
++&i2c8 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c9_default>;
++};
++
++&i2c9 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c10_default>;
++};
++
++&i2c12 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c13_default>;
++};
++
++&i2c13 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i2c14_default>;
++};
+\ No newline at end of file
+diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
+index ee775ce5d264..8c985532afb4 100644
+--- a/arch/arm/lib/interrupts.c
++++ b/arch/arm/lib/interrupts.c
+@@ -25,6 +25,7 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
++int interrupt_init (void) __attribute__((weak));
+ int interrupt_init (void)
+ {
+ /*
+@@ -35,10 +36,13 @@ int interrupt_init (void)
+ return 0;
+ }
+
++void enable_interrupts (void) __attribute__((weak));
+ void enable_interrupts (void)
+ {
+ return;
+ }
++
++int disable_interrupts (void) __attribute__((weak));
+ int disable_interrupts (void)
+ {
+ return 0;
+@@ -189,6 +193,7 @@ void do_fiq (struct pt_regs *pt_regs)
+ bad_mode ();
+ }
+
++void do_irq (struct pt_regs *pt_regs) __attribute__((weak));
+ void do_irq (struct pt_regs *pt_regs)
+ {
+ efi_restore_gd();
+diff --git a/arch/arm/mach-aspeed/ast2600/Kconfig b/arch/arm/mach-aspeed/ast2600/Kconfig
+index dd991e87c795..7ccbb0b5e0ea 100644
+--- a/arch/arm/mach-aspeed/ast2600/Kconfig
++++ b/arch/arm/mach-aspeed/ast2600/Kconfig
+@@ -51,6 +51,13 @@ config TARGET_SLT_AST2600
+ help
+ SLT-AST2600 is Aspeed SLT board for AST2600 chip.
+
++config TARGET_AST2600_INTEL
++ bool "AST2600-INTEL"
++ depends on ASPEED_AST2600
++ help
++ AST2600-INTEL is an Intel server board with the AST2600
++ as the BMC.
++
+ endchoice
+
+ source "board/aspeed/evb_ast2600a0/Kconfig"
+@@ -59,5 +66,6 @@ source "board/aspeed/ncsi_ast2600a0/Kconfig"
+ source "board/aspeed/ncsi_ast2600a1/Kconfig"
+ source "board/aspeed/fpga_ast2600/Kconfig"
+ source "board/aspeed/slt_ast2600/Kconfig"
++source "board/aspeed/ast2600_intel/Kconfig"
+
+ endif
+diff --git a/board/aspeed/ast2600_intel/Kconfig b/board/aspeed/ast2600_intel/Kconfig
+new file mode 100644
+index 000000000000..b841dab60c76
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/Kconfig
+@@ -0,0 +1,13 @@
++if TARGET_AST2600_INTEL
++
++config SYS_BOARD
++ default "ast2600_intel"
++
++config SYS_VENDOR
++ default "aspeed"
++
++config SYS_CONFIG_NAME
++ string "board configuration name"
++ default "ast2600_intel"
++
++endif
+diff --git a/board/aspeed/ast2600_intel/Makefile b/board/aspeed/ast2600_intel/Makefile
+new file mode 100644
+index 000000000000..37d2f0064f38
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/Makefile
+@@ -0,0 +1,4 @@
++obj-y += intel.o
++obj-y += ast-espi.o
++obj-y += ast-irq.o
++obj-y += ast-timer.o
+diff --git a/board/aspeed/ast2600_intel/ast-espi.c b/board/aspeed/ast2600_intel/ast-espi.c
+new file mode 100644
+index 000000000000..0fdbf089a450
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-espi.c
+@@ -0,0 +1,292 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020, Intel Corporation.
++
++#include <common.h>
++#include <asm/io.h>
++
++#define AST_LPC_BASE 0x1e789000
++#define AST_ESPI_BASE 0x1e6ee000
++#define AST_SCU_BASE 0x1e6e2000
++#define AST_SCU_HW_STRAP2 0x510
++#define SCU_HW_STRAP_ESPI_ENABLED 0x40
++
++#define USE_HW_HANDSHAKE 0
++#define DEBUG_ESPI_ENABLED 0
++#if DEBUG_ESPI_ENABLED
++#define DBG_ESPI printf
++#else
++#define DBG_ESPI(...)
++#endif
++
++/* eSPI controller registers */
++#define ESPI000 0x000 /* Engine Control. */
++#define ESPI004 0x004 /* Engine Status. */
++#define ESPI008 0x008 /* Interrupt Status. */
++#define ESPI00C 0x00C /* Interrupt Enable. */
++#define ESPI010 0x010 /* DMA Addr of Peripheral Channel Posted Rx pkt */
++#define ESPI014 0x014 /* Control of Peripheral Channel Posted Rx pkt. */
++#define ESPI018 0x018 /* Data port of Peripheral Channel Posted Rx pkt. */
++#define ESPI020 0x020 /* DMA Addr of Peripheral Channel Posted Tx pkt. */
++#define ESPI024 0x024 /* Control of Peripheral Channel Posted Tx pkt. */
++#define ESPI028 0x028 /* Data port of Peripheral Channel Posted Tx pkt. */
++#define ESPI030 0x030 /* DMA Addr of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI034 0x034 /* Control of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI038 0x038 /* Data port of Peripheral Channel Non-Posted Tx pkt. */
++#define ESPI040 0x040 /* DMA Addr of OOB Channel Rx pkt. */
++#define ESPI044 0x044 /* Control of OOB Channel Rx pkt. */
++#define ESPI048 0x048 /* Data port of OOB Channel Rx pkt. */
++#define ESPI050 0x050 /* DMA Addr of OOB Channel Tx pkt. */
++#define ESPI054 0x054 /* Control of OOB Channel Tx pkt. */
++#define ESPI058 0x058 /* Data port of OOB Channel Tx pkt. */
++#define ESPI060 0x060 /* DMA Addr of Flash Channel Rx pkt. */
++#define ESPI064 0x064 /* Control of Flash Channel Rx pkt. */
++#define ESPI068 0x068 /* Data port of Flash Channel Rx pkt. */
++#define ESPI070 0x070 /* DMA Addr of Flash Channel Tx pkt. */
++#define ESPI074 0x074 /* Control of Flash Channel Tx pkt. */
++#define ESPI078 0x078 /* Data port of Flash Channel Tx pkt. */
++#define ESPI080 0x080 /* Engine Control 2. */
++#define ESPI084 0x084 /* Mapping Src Addr of Peripheral Channel Rx pkt. */
++#define ESPI088 0x088 /* Mapping Tgt Addr of Peripheral Channel Rx pkt. */
++#define ESPI08C 0x08C /* Mapping Addr Mask of Peripheral Channel Rx pkt. */
++#define ESPI090 0x090 /* Mapping Target Addr and Mask of Flash Channel. */
++#define ESPI094 0x094 /* Interrupt enable of System Event from Master. */
++#define ESPI098 0x098 /* System Event from and to Master. */
++#define ESPI09C 0x09C /* GPIO through Virtual Wire Channel. */
++#define ESPI0A0 0x0A0 /* General Capabilities and Configurations. */
++#define ESPI0A4 0x0A4 /* Channel 0 Capabilities and Configurations. */
++#define ESPI0A8 0x0A8 /* Channel 1 Capabilities and Configurations. */
++#define ESPI0AC 0x0AC /* Channel 2 Capabilities and Configurations. */
++#define ESPI0B0 0x0B0 /* Channel 3 Capabilities and Configurations. */
++#define ESPI0B4 0x0B4 /* GPIO Direction of Virtual Wire Channel. */
++#define ESPI0B8 0x0B8 /* GPIO Selection of Virtual Wire Channel. */
++#define ESPI0BC 0x0BC /* GPIO Reset Selection of Virtual Wire Channel. */
++#define ESPI100 0x100 /* Interrupt enable of System Event 1 from Master. */
++#define ESPI104 0x104 /* System Event 1 from and to Master. */
++#define ESPI110 0x110 /* Interrupt type 0 of System Event from Master. */
++#define ESPI114 0x114 /* Interrupt type 1 of System Event from Master. */
++#define ESPI118 0x118 /* Interrupt type 2 of System Event from Master. */
++#define ESPI11C 0x11C /* Interrupt status of System Event from Master. */
++#define ESPI120 0x120 /* Interrupt type 0 of System Event 1 from Master. */
++#define ESPI124 0x124 /* Interrupt type 1 of System Event 1 from Master. */
++#define ESPI128 0x128 /* Interrupt type 2 of System Event 1 from Master. */
++#define ESPI12C 0x12C /* Interrupt status of System Event 1 from Master. */
++#define ESPICFG004 0x004 /* Device Identification. */
++#define ESPICFG008 0x008 /* General Capabilities and Configurations. */
++#define ESPICFG010 0x010 /* Channel 0 Capabilities and Configurations. */
++#define ESPICFG020 0x020 /* Channel 1 Capabilities and Configurations. */
++#define ESPICFG030 0x030 /* Channel 2 Capabilities and Configurations. */
++#define ESPICFG040 0x040 /* Channel 3 Capabilities and Configurations. */
++#define ESPICFG044 0x044 /* Channel 3 Capabilities and Configurations 2. */
++#define ESPICFG800 0x800 /* GPIO Direction of Virtual Wire Channel. */
++#define ESPICFG804 0x804 /* GPIO Selection of Virtual Wire Channel. */
++#define ESPICFG808 0x808 /* GPIO Reset Selection of Virtual Wire Channel. */
++#define ESPICFG810 0x810 /* Mapping Src Addr of Peripheral Channel Rx pkt */
++#define ESPICFG814 0x814 /* Mapping Tgt Addr of Peripheral Channel Rx pkt */
++#define ESPICFG818 0x818 /* Mapping Addr Mask of Peripheral Channel Rx pkt */
++
++/* ESPI000 bits */
++#define AST_ESPI_OOB_CHRDY BIT(4)
++#define AST_ESPI_FLASH_SW_CHRDY BIT(7)
++#define AST_ESPI_FLASH_SW_READ BIT(10)
++
++/* ESPI00C bits (Interrupt Enable) */
++#define AST_ESPI_IEN_HW_RST BIT(31)
++#define AST_ESPI_IEN_SYS1_EV BIT(22)
++#define AST_ESPI_IEN_SYS_EV BIT(8)
++#define AST_ESPI_IEN_GPIO_EV BIT(9)
++
++/* ESPI008 bits ISR */
++#define AST_ESPI_VW_SYS_EVT BIT(8)
++#define AST_ESPI_VW_GPIO_EVT BIT(9)
++#define AST_ESPI_VW_SYS_EV1 BIT(22)
++#define AST_ESPI_HW_RST BIT(31)
++
++/* ESPI080 bits */
++#define AST_ESPI_AUTO_ACK_HOST_RST_WARN BIT(2)
++#define AST_ESPI_AUTO_ACK_OOB_RST_WARN BIT(1)
++#define AST_ESPI_AUTO_ACK_SUS_WARN BIT(0)
++
++/* ESPI098 and ESPI11C bits */
++#define AST_ESPI_OOB_RST_WARN BIT(6)
++#define AST_ESPI_HOST_RST_WARN BIT(8)
++#define AST_ESPI_PLTRSTN BIT(5)
++#define AST_ESPI_OOB_RST_ACK BIT(16)
++#define AST_ESPI_SL_BT_DONE BIT(20)
++#define AST_ESPI_SL_BT_STATUS BIT(23)
++#define AST_ESPI_HOST_RST_ACK BIT(27)
++
++/* ESPI104 bits */
++#define AST_ESPI_SUS_WARN BIT(0)
++#define AST_ESPI_SUS_ACK BIT(20)
++
++/* LPC chip ID */
++#define SCR0SIO 0x170
++#define IRQ_SRC_ESPI 74 /* IRQ 74 */
++
++static void espi_handshake_ack(void)
++{
++ /* IRQ only serviced if strapped, so no strap check */
++ if (!(readl(AST_ESPI_BASE + ESPI098) & AST_ESPI_SL_BT_STATUS)) {
++ DBG_ESPI("Setting espi slave boot done\n");
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098) |
++ AST_ESPI_SL_BT_STATUS | AST_ESPI_SL_BT_DONE;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ }
++
++ uint32_t sys1_event = readl(AST_ESPI_BASE + ESPI104);
++ if (sys1_event & AST_ESPI_SUS_WARN &&
++ !(sys1_event & AST_ESPI_SUS_ACK)) {
++ DBG_ESPI("Boot SUS_WARN, evt: 0x%08x\n", sys1_event);
++ writel(sys1_event | AST_ESPI_SUS_ACK, AST_ESPI_BASE + ESPI104);
++ DBG_ESPI("SUS_WARN sent ack\n");
++ }
++}
++
++int espi_irq_handler(struct pt_regs *regs)
++{
++ uint32_t irq_status = readl(AST_ESPI_BASE + ESPI008);
++
++ DBG_ESPI("espi_irq_handler, ESPI008=0X%x, ESPI00c=0X%x,\
++ ESPI100=0X%x, ESPI11c=0X%x, ESPI094=0X%x,\
++ ESPI12c=0X%x, irq_status=0x%x\n",
++ readl(AST_ESPI_BASE + ESPI008),
++ readl(AST_ESPI_BASE + ESPI00C),
++ readl(AST_ESPI_BASE + ESPI100),
++ readl(AST_ESPI_BASE + ESPI11C),
++ readl(AST_ESPI_BASE + ESPI094),
++ readl(AST_ESPI_BASE + ESPI12C), irq_status);
++
++ if (irq_status & AST_ESPI_VW_SYS_EVT) {
++ uint32_t sys_status = readl(AST_ESPI_BASE + ESPI11C);
++ uint32_t sys_event = readl(AST_ESPI_BASE + ESPI098);
++
++ DBG_ESPI("sys_status : 0x%08X\n", sys_status);
++ if (sys_status & AST_ESPI_HOST_RST_WARN) {
++ DBG_ESPI("HOST_RST_WARN evt: 0x%08X\n", sys_event);
++ if (sys_event & AST_ESPI_HOST_RST_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098) |
++ AST_ESPI_HOST_RST_ACK;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ DBG_ESPI("HOST_RST_WARN sent ack\n");
++ }
++ }
++ if (sys_status & AST_ESPI_OOB_RST_WARN) {
++ DBG_ESPI("OOB_RST_WARN evt: 0x%08X\n", sys_event);
++ if (sys_event & AST_ESPI_OOB_RST_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI098) |
++ AST_ESPI_OOB_RST_ACK;
++ writel(v, AST_ESPI_BASE + ESPI098);
++ DBG_ESPI("OOB_RST_WARN sent ack\n");
++ }
++ }
++ if (sys_status & AST_ESPI_PLTRSTN) {
++ DBG_ESPI("PLTRSTN: %c, evt: 0x%08X\n",
++ (sys_event & AST_ESPI_PLTRSTN) ? '1' : '0',
++ sys_event);
++ }
++ writel(sys_status, AST_ESPI_BASE + ESPI11C); /* clear status */
++ }
++
++ if (irq_status & AST_ESPI_VW_SYS_EV1) {
++ uint32_t sys1_status = readl(AST_ESPI_BASE + ESPI12C);
++ uint32_t sys1_event = readl(AST_ESPI_BASE + ESPI104);
++
++ DBG_ESPI("sys1_status : 0x%08X\n", sys1_status);
++ if (sys1_status & AST_ESPI_SUS_WARN) {
++ DBG_ESPI("SUS WARN evt: 0x%08X\n", sys1_event);
++ if (sys1_event & AST_ESPI_SUS_WARN) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI104) |
++ AST_ESPI_SUS_ACK;
++ writel(v, AST_ESPI_BASE + ESPI104);
++ DBG_ESPI("SUS_WARN sent ack\n");
++ }
++ }
++ writel(sys1_status, AST_ESPI_BASE + ESPI12C); /* clear status */
++ }
++
++ if (irq_status & AST_ESPI_HW_RST) {
++ uint32_t v = readl(AST_ESPI_BASE + ESPI000) & 0x00ffffffff;
++ writel(v, AST_ESPI_BASE + ESPI000);
++ v |= 0xff000000;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ DBG_ESPI("HW_RESET\n");
++
++ espi_handshake_ack();
++ }
++
++ writel(irq_status, AST_ESPI_BASE + ESPI008); /* clear irq_status */
++
++ DBG_ESPI("end espi_irq_handler, ESPI008=0X%x, ESPI00c=0X%x,\
++ ESPI100=0X%x, ESPI11c=0X%x, ESPI094=0X%x,\
++ ESPI12c=0X%x, irq_status=0X%x\n",
++ readl(AST_ESPI_BASE + ESPI008),
++ readl(AST_ESPI_BASE + ESPI00C),
++ readl(AST_ESPI_BASE + ESPI100),
++ readl(AST_ESPI_BASE + ESPI11C),
++ readl(AST_ESPI_BASE + ESPI094),
++ readl(AST_ESPI_BASE + ESPI12C), irq_status);
++ return 0;
++}
++
++void espi_init(void)
++{
++ if (~readl(AST_SCU_BASE + AST_SCU_HW_STRAP2) &
++ SCU_HW_STRAP_ESPI_ENABLED) {
++ uint32_t v;
++
++ DBG_ESPI("espi init\n");
++
++ writel(0xff000000, AST_SCU_BASE + 0x454); /* driving strength */
++
++ /* Block flash access from Host */
++ v = readl(AST_ESPI_BASE + ESPI000) & ~AST_ESPI_FLASH_SW_CHRDY;
++ v |= AST_ESPI_FLASH_SW_READ | AST_ESPI_OOB_CHRDY;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ /*
++ * Set SIO register 0x28 to 0xa8 as a faked ASPEED ChipID for
++ * BIOS using in eSPI mode.
++ */
++ v = readl(AST_LPC_BASE + SCR0SIO) & ~0x000000ff;
++ writel(v, AST_LPC_BASE + SCR0SIO);
++ v = readl(AST_LPC_BASE + SCR0SIO) | 0xa8;
++ writel(v, AST_LPC_BASE + SCR0SIO);
++
++#if USE_HW_HANDSHAKE
++ v = readl(AST_ESPI_BASE + ESPI098) |
++ AST_ESPI_SL_BT_STATUS | AST_ESPI_SL_BT_DONE;
++ writel(v, AST_ESPI_BASE + ESPI098);
++
++ return;
++#endif
++
++ v = readl(AST_ESPI_BASE + ESPI080);
++ v &= ~(AST_ESPI_AUTO_ACK_HOST_RST_WARN |
++ AST_ESPI_AUTO_ACK_OOB_RST_WARN |
++ AST_ESPI_AUTO_ACK_SUS_WARN);
++ writel(v, AST_ESPI_BASE + ESPI080); /* Disable auto H/W ack */
++
++ writel(0, AST_ESPI_BASE + ESPI110);
++ writel(0, AST_ESPI_BASE + ESPI114);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
++ AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI118);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
++ AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI094);
++
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE + ESPI120); /* int type 0 susp warn */
++ writel(0, AST_ESPI_BASE + ESPI124);
++ writel(0, AST_ESPI_BASE + ESPI128);
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE +
++ ESPI100); /* Enable sysev1 ints for susp warn */
++
++ writel(AST_ESPI_IEN_HW_RST | AST_ESPI_IEN_SYS1_EV |
++ AST_ESPI_IEN_SYS_EV, AST_ESPI_BASE + ESPI00C);
++
++ irq_install_handler(IRQ_SRC_ESPI, espi_irq_handler, NULL);
++ } else {
++ DBG_ESPI("No espi strap\n");
++ }
++}
+diff --git a/board/aspeed/ast2600_intel/ast-irq.c b/board/aspeed/ast2600_intel/ast-irq.c
+new file mode 100644
+index 000000000000..f817f8cd7c81
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-irq.c
+@@ -0,0 +1,399 @@
++/*
++ * Copyright 2018 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <netdev.h>
++#include <asm/io.h>
++
++DECLARE_GLOBAL_DATA_PTR;
++
++#define GIC_DISTRIBUTOR_OFFSET 0x1000
++#define GIC_CPU_OFFSET 0x2000
++#define GIC_INTERFACE_OFFSET 0x4000
++#define GIC_VIRT_OFFSET 0x6000
++
++#define VIC_STATUS_L 0x80
++#define VIC_STATUS_H 0x84
++#define VIC_IRQ_SELECTION_L 0x98
++#define VIC_IRQ_SELECTION_H 0x9C
++#define VIC_ENABLE_L 0xA0
++#define VIC_ENABLE_H 0xA4
++#define VIC_ENABLE_CLEAR_L 0xA8
++#define VIC_ENABLE_CLEAR_H 0xAC
++#define VIC_INTERRUPT_CLEAR_L 0xD8
++#define VIC_INTERRUPT_CLEAR_H 0xDC
++
++#define VIC_CLEAR_ALL (~0)
++
++/* GIC_DISTRIBUTOR_OFFSET register offsets */
++#define GICD_CTLR 0x000
++#define GICD_TYPER 0x004
++#define GICD_IIDR 0x008
++#define GICD_IGROUPRn 0x080
++#define GICD_ISENABLERn 0x100
++#define GICD_ICENABLERn 0x180
++#define GICD_ISPENDRn 0x200
++#define GICD_ICPENDRn 0x280
++#define GICD_ISACTIVERn 0x300
++#define GICD_ICACTIVERn 0x380
++#define GICD_IPRIORITYRn 0x400
++#define GICD_ITARGETSRn 0x800
++#define GICD_ICFGRn 0xc00
++#define GICD_PPISR 0xd00
++#define GICD_SPISRn 0xd04
++#define GICD_SGIR 0xf00
++#define GICD_CPENDINGIRn 0xf10
++#define GICD_SPENDINGIRn 0xf10
++#define GICD_PIDR4 0xfd0
++#define GICD_PIDR5 0xfd4
++#define GICD_PIDR6 0xfd8
++#define GICD_PIDR7 0xfdc
++#define GICD_PIDR0 0xfe0
++#define GICD_PIDR1 0xfe4
++#define GICD_PIDR2 0xfe8
++#define GICD_PIDR3 0xfec
++#define GICD_CIDR0 0xff0
++#define GICD_CIDR1 0xff4
++#define GICD_CIDR2 0xff8
++#define GICD_CIDR3 0xffc
++
++#define GIC_DISTRIBUTOR_IMPLEMENTER_MAGIC 0x0100143b
++
++/* GIC_CPU_OFFSET register offsets */
++#define GICC_CTLR 0x0000
++#define GICC_PMRn 0x0004
++#define GICC_BPR 0x0008
++#define GICC_IAR 0x000c
++#define GICC_EOIR 0x0010
++#define GICC_RPR 0x0014
++#define GICC_HPPIR 0x0018
++#define GICC_ABPR 0x001c
++#define GICC_AIAR 0x0020
++#define GICC_AEOIR 0x0024
++#define GICC_AHPPIR 0x0028
++#define GICC_APR0 0x00d0
++#define GICC_NSAPR0 0x00e0
++#define GICC_IIDR 0x00fc
++#define GICC_DIR 0x1000
++
++#define GIC_CPU_IMPLEMENTER_MAGIC 0x0102143b
++
++/* GIC_INTERFACE_OFFSET register offsets */
++#define GICH_HCR 0x000
++#define GICH_VTR 0x004
++#define GICH_VMCR 0x008
++#define GICH_MISR 0x010
++#define GICH_EISR0 0x020
++#define GICH_ELSR0 0x020
++#define GICH_APR0 0x0f0
++#define GICH_LR0 0x100
++#define GICH_LR1 0x104
++#define GICH_LR2 0x108
++#define GICH_LR3 0x10c
++
++/* GIC_VIRT_OFFSET register offsets */
++#define GICV_CTLR 0x0000
++#define GICV_PMR 0x0004
++#define GICV_BPR 0x0008
++#define GICV_IAR 0x000c
++#define GICV_EOIR 0x0010
++#define GICV_RPR 0x0014
++#define GICV_HPPIR 0x0018
++#define GICV_ABPR 0x001c
++#define GICV_AIAR 0x0020
++#define GICV_AEOIR 0x0024
++#define GICV_AHPPIR 0x0028
++#define GICV_APR0 0x00d0
++#define GICV_NSAPR0 0x00e0
++#define GICV_IIDR 0x00fc
++#define GICV_DIR 0x1000
++
++#define GIC_VIRT_CPU_IMPLEMENTER_MAGIC 0x0102143b
++
++#define GICD_CTLR_ENABLE 0x03
++
++#define GICD_INT_DEF_PRI 0xa0
++#define GICD_INT_DEF_PRI_X4 (\
++ (GICD_INT_DEF_PRI << 24) |\
++ (GICD_INT_DEF_PRI << 16) |\
++ (GICD_INT_DEF_PRI << 8) |\
++ GICD_INT_DEF_PRI)
++
++#define GICD_INT_ACTLOW_LVLTRIG 0
++#define GICD_INT_EN_CLR_X32 0xffffffff
++#define GICD_INT_EN_CLR_PPI 0xffff0000
++#define GICD_INT_EN_SET_SGI 0x0000ffff
++
++#define gicd_readl(OFFSET) readl(gbase + GIC_DISTRIBUTOR_OFFSET + (OFFSET))
++#define gicd_writel(VALUE, OFFSET) \
++ writel((VALUE), gbase + GIC_DISTRIBUTOR_OFFSET + (OFFSET))
++#define gicc_readl(OFFSET) readl(gbase + GIC_CPU_OFFSET + (OFFSET))
++#define gich_readl(OFFSET) readl(gbase + GIC_INTERFACE_OFFSET + (OFFSET))
++#define gicv_readl(OFFSET) readl(gbase + GIC_VIRT_OFFSET + (OFFSET))
++
++static size_t max_irq = 0;
++
++#define ITLINES_MASK 0x1f
++#define ITLINES_SHIFT 5
++
++#define GIC_MAX_IRQ 1020
++static interrupt_handler_t *handlers[GIC_MAX_IRQ] = {NULL};
++static unsigned long irq_total = 0;
++static unsigned long irq_counts[GIC_MAX_IRQ] = {0};
++static uint32_t gbase = 0;
++
++/* TODO: This, hard-coded, or from dts? */
++static inline uint32_t gic_base(void)
++{
++ uint32_t base;
++ /* read the base address of the private peripheral space */
++ __asm__ __volatile__("mrc p15, 4, %r0, c15, c0, 0\n\t" : "=r"(base) : );
++ return base;
++}
++
++static void enable_gic(void)
++{
++ uint32_t gicd_ctlr;
++
++ /* add GIC offset ref table 1-3 for interrupt distributor address */
++ gicd_ctlr = gicd_readl(GICD_CTLR);
++ gicd_writel(gicd_ctlr | GICD_CTLR_ENABLE, GICD_CTLR);
++}
++
++static void disable_gic(void)
++{
++ uint32_t gicd_ctlr;
++
++ /* add GIC offset ref table 1-3 for interrupt distributor address */
++ gicd_ctlr = gicd_readl(GICD_CTLR);
++ gicd_writel(gicd_ctlr & ~GICD_CTLR_ENABLE, GICD_CTLR);
++}
++
++static void enable_irq_id(unsigned int id)
++{
++ uint32_t grp = id >> ITLINES_SHIFT;
++ uint32_t grp_bit = 1 << (id & ITLINES_MASK);
++ gicd_writel(grp_bit, GICD_ISENABLERn + grp * sizeof(uint32_t));
++}
++
++static void disable_irq_id(unsigned int id)
++{
++ uint32_t grp = id >> ITLINES_SHIFT;
++ uint32_t grp_bit = 1 << (id & ITLINES_MASK);
++ gicd_writel(grp_bit, GICD_ICENABLERn + grp * sizeof(uint32_t));
++}
++
++static int gic_probe(void)
++{
++ int i;
++ gbase = gic_base();
++ enable_gic();
++
++ if (gicd_readl(GICD_IIDR) != GIC_DISTRIBUTOR_IMPLEMENTER_MAGIC &&
++ gicc_readl(GICC_IIDR) != GIC_CPU_IMPLEMENTER_MAGIC &&
++ gicv_readl(GICV_IIDR) != GIC_VIRT_CPU_IMPLEMENTER_MAGIC)
++ {
++ return 0;
++ }
++ /* GIC supports up to 1020 lines */
++ max_irq = ((gicd_readl(GICD_TYPER) & ITLINES_MASK) + 1) << ITLINES_SHIFT;
++ if (max_irq > GIC_MAX_IRQ)
++ max_irq = GIC_MAX_IRQ;
++ /* set all lines to be level triggered N-N */
++ for (i = 32; i < max_irq; i += 16)
++ gicd_writel(0, GICD_ICFGRn + i / 4);
++
++ /* Set priority on all interrupts. */
++ for (i = 0; i < max_irq; i += 4)
++ gicd_writel(GICD_INT_DEF_PRI_X4, GICD_IPRIORITYRn + i);
++
++ /* Deactivate and disable all SPIs. */
++ for (i = 32; i < max_irq; i += 32) {
++ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICACTIVERn + i / 8);
++ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICENABLERn + i / 8);
++ }
++ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICACTIVERn);
++ gicd_writel(GICD_INT_EN_CLR_PPI, GICD_ICENABLERn);
++ gicd_writel(GICD_INT_EN_SET_SGI, GICD_ISENABLERn);
++
++ return 0;
++}
++
++void irq_free_handler (int irq);
++static void gic_shutdown(void)
++{
++ int i;
++ for (i = 0; i < max_irq; i++)
++ {
++ irq_free_handler(i);
++ }
++ disable_gic();
++}
++
++int arch_interrupt_init_early(void)
++{
++ return 0;
++}
++
++int arch_interrupt_init(void)
++{
++ int i;
++ for (i = 0; i < GIC_MAX_IRQ; i++)
++ {
++ handlers[i] = NULL;
++ irq_counts[i] = 0;
++ }
++ return gic_probe();
++}
++
++int arch_interrupt_fini(void)
++{
++ gic_shutdown();
++ return 0;
++}
++
++int interrupt_init (void)
++{
++ /*
++ * setup up stacks if necessary
++ */
++ IRQ_STACK_START_IN = gd->irq_sp + 8;
++
++ printf("%s()\n", __FUNCTION__);
++ return arch_interrupt_init();
++
++ return 0;
++}
++
++int global_interrupts_enabled (void)
++{
++ unsigned long cpsr;
++ __asm__ __volatile__("mrs %0, cpsr\n"
++ : "=r" (cpsr)
++ :
++ : "memory");
++
++ return (cpsr & 0x80) == 0;
++}
++
++void enable_interrupts (void)
++{
++ unsigned long cpsr;
++ __asm__ __volatile__("mrs %0, cpsr\n"
++ "bic %0, %0, #0x80\n"
++ "msr cpsr_c, %0"
++ : "=r" (cpsr)
++ :
++ : "memory");
++
++ return;
++}
++
++int disable_interrupts (void)
++{
++ unsigned long cpsr, temp;
++ __asm__ __volatile__("mrs %0, cpsr\n"
++ "orr %1, %0, #0xc0\n"
++ "msr cpsr_c, %1"
++ : "=r" (cpsr), "=r" (temp)
++ :
++ : "memory");
++ return (cpsr & 0x80) == 0;
++}
++
++void irq_install_handler(int irq, interrupt_handler_t *handler, void *ctx)
++{
++ if (irq > max_irq) {
++ printf("irq %d out of range\n", irq);
++ return;
++ }
++ if (handlers[irq]) {
++ printf("irq %d already in use (%p)\n", irq, handlers[irq]);
++ return;
++ }
++ printf("registering handler for irq %d\n", irq);
++ handlers[irq] = handler;
++ enable_irq_id(irq);
++}
++
++void irq_free_handler (int irq)
++{
++ if (irq >= max_irq) {
++ printf("irq %d out of range\n", irq);
++ return;
++ }
++ if (handlers[irq]) {
++ handlers[irq] = NULL;
++ disable_irq_id(irq);
++ }
++}
++
++int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
++{
++ int i;
++ int enabled = global_interrupts_enabled();
++ printf("GIC base = 0x%x\n", gbase);
++ printf("interrupts %sabled\n", (enabled ? "en" : "dis"));
++ uint32_t grp_en = 0;
++ for (i = 0; i < max_irq; i++) {
++ if ((i & ITLINES_MASK) == 0)
++ grp_en = gicd_readl(GICD_ISENABLERn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ int irq_enabled = grp_en & (1 << (i & ITLINES_MASK));
++ if (!irq_enabled)
++ continue;
++ printf("% 2i (% 3s): %lu\n", i,
++ (irq_enabled ? "on" : "off"), irq_counts[i]);
++ }
++ printf("total: %lu\n", irq_total);
++ return 0;
++}
++
++void do_irq(struct pt_regs *pt_regs)
++{
++ int i;
++ if (!gbase) {
++ static int printed_msg = 0;
++ if (!printed_msg)
++ {
++ printed_msg = 1;
++ printf("interrupt before configured!\n");
++ }
++ return;
++ }
++ irq_total++;
++ uint32_t grp_pend = 0;
++ for (i = 0; i < max_irq; i++) {
++ /* limit reads of the pending register to once in 32 */
++ if ((i & ITLINES_MASK) == 0)
++ grp_pend = gicd_readl(GICD_ISPENDRn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ uint32_t pending = grp_pend & (1 << (i & ITLINES_MASK));
++ if (pending) {
++ irq_counts[i]++;
++ /* mask via GICD_ICENABLERn */
++ gicd_writel(pending, GICD_ICENABLERn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ if (handlers[i]) {
++ handlers[i](pt_regs);
++ /* unmask via GICD_ISENABLERn */
++ gicd_writel(pending, GICD_ISENABLERn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ /* clear pending via GICD_ICPENDRn */
++ gicd_writel(pending, GICD_ICPENDRn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ } else {
++ printf("unexpected interrupt %i; masking\n", i);
++ /* clear pending via GICD_ICPENDRn */
++ gicd_writel(pending, GICD_ISPENDRn +
++ (i >> ITLINES_SHIFT) * sizeof(uint32_t));
++ }
++ }
++ }
++}
+diff --git a/board/aspeed/ast2600_intel/ast-irq.h b/board/aspeed/ast2600_intel/ast-irq.h
+new file mode 100644
+index 000000000000..9957f2baa7ff
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-irq.h
+@@ -0,0 +1,8 @@
++#ifndef _AST_IRQ_H_
++#define _AST_IRQ_H_
++
++int request_irq(int irq, interrupt_handler_t *handler);
++int release_irq(int irq);
++int arch_interrupt_init_early(void);
++
++#endif
+diff --git a/board/aspeed/ast2600_intel/ast-timer.c b/board/aspeed/ast2600_intel/ast-timer.c
+new file mode 100644
+index 000000000000..cf8c69aba5d3
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-timer.c
+@@ -0,0 +1,59 @@
++/*
++ * Copyright 2019 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <common.h>
++#include <asm/io.h>
++
++static const int timer_irqs[] = {48, 49, 50, 51, 52, 53, 54, 55};
++#define AST_TIMER_BASE 0x1e782000
++/* offsets from AST_TIMER_BASE for each timer */
++static const uint32_t timer_bases[] = {0, 0x10, 0x20, 0x40,
++ 0x50, 0x60, 0x70, 0x80};
++#define TIMER_1MHZ_CLK_COUNT 1000000u
++#define TIMER_ENABLE 1
++#define TIMER_1MHZ_CLK_SEL 2
++#define TIMER_ENABLE_IRQ 4
++#define TIMER_RESET_BY_WDT 8
++#define TIMER_CONTROL 0x30
++#define TIMER_RELOAD 0x04
++#define TIMER_CONTROL_CLEAR 0x3c
++
++void timer_disable(int n)
++{
++ if (n < 0 || n > 7) {
++ return;
++ }
++ uint32_t tctrl = 0xf << (n * 4);
++ writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL_CLEAR);
++}
++
++void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler)
++{
++ if (n < 0 || n > 7) {
++ return;
++ }
++ if (!freq)
++ return;
++
++ timer_disable(n);
++
++ uint32_t v = TIMER_1MHZ_CLK_COUNT / freq;
++ writel(v, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
++
++ uint32_t tctrl = (
++ TIMER_ENABLE |
++ TIMER_1MHZ_CLK_SEL |
++ TIMER_RESET_BY_WDT) << (n * 4);
++
++ if (handler) {
++ irq_install_handler(timer_irqs[n], handler, NULL);
++ tctrl |= (TIMER_ENABLE_IRQ << (n * 4));
++ }
++ writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL);
++}
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+new file mode 100644
+index 000000000000..4a40a050c3da
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -0,0 +1,192 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2019-2020, Intel Corporation.
++
++/* Intel customizations of Das U-Boot */
++#include <common.h>
++#include <asm/gpio.h>
++#include <asm/io.h>
++
++/* use GPIOC0 on intel boards */
++#define FFUJ_GPIO "gpio@1e78000016"
++
++int read_ffuj(void)
++{
++ struct gpio_desc desc;
++ int ret;
++
++ ret = dm_gpio_lookup_name(FFUJ_GPIO, &desc);
++ if (ret)
++ return ret;
++ ret = dm_gpio_request(&desc, "ffuj");
++ if (ret)
++ return ret;
++ ret = dm_gpio_set_dir_flags(&desc, GPIOD_ACTIVE_LOW);
++ if (ret)
++ return ret;
++ ret = dm_gpio_get_value(&desc);
++ dm_gpio_free(desc.dev, &desc);
++ return ret;
++}
++
++/* gpio_abort is a weak symbol in common/autoboot.c */
++int gpio_abort(void)
++{
++ int value;
++ /* check ffuj to abort the autoboot */
++ value = read_ffuj();
++ printf("FFUJ: %d\n", value);
++ return value <= 0 ? 0 : 1;
++}
++
++#define SCU_BASE 0x1E6E2000
++int misc_init_r(void)
++{
++ /* This is called near the end of the _r init sequence */
++
++ return 0;
++}
++
++#define SCU_418 0x418 /* Multi-function Pin Control #6 */
++#define SCU_418_PBIO_MASK GENMASK(6, 5)
++#define SCU_4bc 0x4bc /* Multi-function Pin Control #20 */
++#define SCU_4bc_PASSTHRU0_MASK GENMASK(25, 24)
++#define SCU_4bc_PASSTHRU1_MASK GENMASK(27, 26)
++#define SCU_4bc_PASSTHRU2_MASK GENMASK(29, 28)
++
++static void gpio_passthru_init(void)
++{
++ writel(readl(SCU_BASE | SCU_4bc) |
++ SCU_4bc_PASSTHRU0_MASK | SCU_4bc_PASSTHRU1_MASK,
++ SCU_BASE | SCU_4bc);
++ writel(readl(SCU_BASE | SCU_418) | SCU_418_PBIO_MASK,
++ SCU_BASE | SCU_418);
++}
++
++#define AST_LPC_BASE 0x1e789000
++#define LPC_SNOOP_ADDR 0x80
++#define HICR5 0x080 /* Host Interface Control Register 5 */
++#define HICR6 0x084 /* Host Interface Control Register 6 */
++#define SNPWADR 0x090 /* LPC Snoop Address Register */
++#define HICRB 0x100 /* Host Interface Control Register B */
++
++/* HICR5 Bits */
++#define HICR5_EN_SIOGIO (1 << 31) /* Enable SIOGIO */
++#define HICR5_EN80HGIO (1 << 30) /* Enable 80hGIO */
++#define HICR5_SEL80HGIO (0x1f << 24) /* Select 80hGIO */
++#define SET_SEL80HGIO(x) ((x & 0x1f) << 24) /* Select 80hGIO Offset */
++#define HICR5_UNKVAL_MASK 0x1FFF0000 /* Bits with unknown values on reset */
++#define HICR5_ENINT_SNP0W (1 << 1) /* Enable Snooping address 0 */
++#define HICR5_EN_SNP0W (1 << 0) /* Enable Snooping address 0 */
++
++/* HRCR6 Bits */
++#define HICR6_STR_SNP0W (1 << 0) /* Interrupt Status Snoop address 0 */
++#define HICR6_STR_SNP1W (1 << 1) /* Interrupt Status Snoop address 1 */
++
++/* HICRB Bits */
++#define HICRB_EN80HSGIO (1 << 13) /* Enable 80hSGIO */
++
++static void port80h_snoop_init(void)
++{
++ uint32_t value;
++ /* enable port80h snoop and sgpio */
++ /* set lpc snoop #0 to port 0x80 */
++ value = readl(AST_LPC_BASE + SNPWADR) & 0xffff0000;
++ writel(value | LPC_SNOOP_ADDR, AST_LPC_BASE + SNPWADR);
++
++ /* clear interrupt status */
++ value = readl(AST_LPC_BASE + HICR6);
++ value |= HICR6_STR_SNP0W | HICR6_STR_SNP1W;
++ writel(value, AST_LPC_BASE + HICR6);
++
++ /* enable lpc snoop #0 and SIOGIO */
++ value = readl(AST_LPC_BASE + HICR5) & ~(HICR5_UNKVAL_MASK);
++ value |= HICR5_EN_SIOGIO | HICR5_EN_SNP0W;
++ writel(value, AST_LPC_BASE + HICR5);
++
++ /* enable port80h snoop on SGPIO */
++ value = readl(AST_LPC_BASE + HICRB) | HICRB_EN80HSGIO;
++ writel(value, AST_LPC_BASE + HICRB);
++}
++
++#define AST_GPIO_BASE 0x1e780000
++
++static void sgpio_init(void)
++{
++#define SGPIO_CLK_DIV(N) ((N) << 16)
++#define SGPIO_BYTES(N) ((N) << 6)
++#define SGPIO_ENABLE 1
++#define GPIO554 0x554
++#define SCU_414 0x414 /* Multi-function Pin Control #5 */
++#define SCU_414_SGPM_MASK GENMASK(27, 24)
++
++ uint32_t value;
++ /* set the sgpio clock to pclk/(2*(5+1)) or ~2 MHz */
++ value = SGPIO_CLK_DIV(256) | SGPIO_BYTES(10) | SGPIO_ENABLE;
++ writel(value, AST_GPIO_BASE + GPIO554);
++ writel(readl(SCU_BASE | SCU_414) | SCU_414_SGPM_MASK,
++ SCU_BASE | SCU_414);
++}
++
++static void timer_handler(void *regs)
++{
++ printf("+");
++}
++
++extern int arch_interrupt_init_early(void);
++int board_early_init_f(void)
++{
++ /* This is called before relocation; beware! */
++ /* initialize running timer? timer_init is next in the list but
++ * I am not sure if it actually does anything... */
++ arch_interrupt_init_early();
++
++ gpio_passthru_init();
++
++ port80h_snoop_init();
++
++ sgpio_init();
++
++ /* TODO: is it too late to enforce HW security registers? */
++ return 0;
++}
++
++extern void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler);
++int board_early_init_r(void)
++{
++ debug("board_early_init_r\n");
++ /* timer_enable(0, 1, timer_handler); */
++
++ return 0;
++}
++
++extern void espi_init(void);
++int board_late_init(void)
++{
++ espi_init();
++
++ return 0;
++}
++
++/* aspeed/board.c defines these functions
++int arch_early_init_r(void)
++{
++ return 0;
++}
++*/
++
++/*
++void board_init(void)
++{
++}
++*/
++
++#ifdef CONFIG_WATCHDOG
++/* watchdog stuff */
++void watchdog_init(void)
++{
++}
++
++void watchdog_reset(void)
++{
++}
++#endif
+diff --git a/cmd/Kconfig b/cmd/Kconfig
+index d5aa204290bd..89f6668b788e 100644
+--- a/cmd/Kconfig
++++ b/cmd/Kconfig
+@@ -1876,7 +1876,7 @@ config CMD_DIAG
+
+ config CMD_IRQ
+ bool "irq - Show information about interrupts"
+- depends on !ARM && !MIPS && !SH
++ depends on !MIPS && !SH
+ help
+ This enables two commands:
+
+diff --git a/common/autoboot.c b/common/autoboot.c
+index 94133eaeda78..5e69000b848b 100644
+--- a/common/autoboot.c
++++ b/common/autoboot.c
+@@ -255,10 +255,20 @@ static int __abortboot(int bootdelay)
+ }
+ # endif /* CONFIG_AUTOBOOT_KEYED */
+
++int gpio_abort(void) __attribute__((weak));
++int gpio_abort(void)
++{
++ return 0;
++}
++
+ static int abortboot(int bootdelay)
+ {
+ int abort = 0;
+
++ abort = gpio_abort();
++ if (abort)
++ return abort;
++
+ if (bootdelay >= 0)
+ abort = __abortboot(bootdelay);
+
+diff --git a/configs/ast2600_openbmc_defconfig b/configs/ast2600_openbmc_defconfig
+index 2e2df2e3a235..77c39d848312 100644
+--- a/configs/ast2600_openbmc_defconfig
++++ b/configs/ast2600_openbmc_defconfig
+@@ -13,7 +13,7 @@ CONFIG_FIT=y
+ CONFIG_USE_BOOTARGS=y
+ CONFIG_BOOTARGS="console=ttyS4,115200n8 root=/dev/ram rw"
+ CONFIG_USE_BOOTCOMMAND=y
+-CONFIG_BOOTCOMMAND="bootm 20100000"
++CONFIG_BOOTCOMMAND="bootm 20080000"
+ CONFIG_SYS_CONSOLE_ENV_OVERWRITE=y
+ CONFIG_DISPLAY_BOARDINFO_LATE=y
+ CONFIG_ARCH_EARLY_INIT_R=y
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0003-ast2600-intel-layout-environment-addr.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0003-ast2600-intel-layout-environment-addr.patch
new file mode 100644
index 000000000..326f36df1
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0003-ast2600-intel-layout-environment-addr.patch
@@ -0,0 +1,67 @@
+From 3195e1ec2d772d5e4c16ae5b60c294086cfc17be Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Thu, 12 Dec 2019 12:54:18 +0800
+Subject: [PATCH] ast2600: intel-layout-environment-addr
+
+Tested:
+Both kernel and u-boot work at the area /dev/mtd/u-boot-env
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ common/board_r.c | 13 ++++++++++---
+ include/configs/aspeed-common.h | 11 ++++++++++-
+ 2 files changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/common/board_r.c b/common/board_r.c
+index 472987d5d52f..b665d0e30262 100644
+--- a/common/board_r.c
++++ b/common/board_r.c
+@@ -433,10 +433,17 @@ static int should_load_env(void)
+ static int initr_env(void)
+ {
+ /* initialize environment */
+- if (should_load_env())
+- env_relocate();
+- else
++ if (should_load_env()) {
++ /*
++ * try again, in case the environment failed to load the first
++ * time
++ */
++ if (!gd->env_valid)
++ env_init();
++ env_relocate();
++ } else {
+ set_default_env(NULL, 0);
++ }
+ #ifdef CONFIG_OF_CONTROL
+ env_set_hex("fdtcontroladdr",
+ (unsigned long)map_to_sysmem(gd->fdt_blob));
+diff --git a/include/configs/aspeed-common.h b/include/configs/aspeed-common.h
+index cdbffc97a223..6065ec58db0a 100644
+--- a/include/configs/aspeed-common.h
++++ b/include/configs/aspeed-common.h
+@@ -65,9 +65,18 @@
+ #endif
+
+ #ifndef CONFIG_ENV_OFFSET
+-#define CONFIG_ENV_OFFSET 0xF0000
++#define CONFIG_ENV_OFFSET 0x2400000
+ #endif
+
++#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
++#define CONFIG_ENV_OVERWRITE
++
++#define AST_FMC_CS0_BASE 0x20000000 /* CS0 */
++#define CONFIG_ENV_ADDR (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET)
++#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
++#define CONFIG_ENV_ADDR_REDUND (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET_REDUND)
++#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
++
+ #define CONFIG_ENV_SECT_SIZE (4 << 10)
+
+ /*
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0004-AST2600-Adjust-default-GPIO-settings.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0004-AST2600-Adjust-default-GPIO-settings.patch
new file mode 100644
index 000000000..1b2cc83a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0004-AST2600-Adjust-default-GPIO-settings.patch
@@ -0,0 +1,86 @@
+From b6bce26bf19e74863e145e6e6e1f6e458077a31a Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 3 Jan 2020 15:14:09 -0800
+Subject: [PATCH] AST2600: Adjust default GPIO settings
+
+- Disable GPIOC3 to prevent unexpected host failures.
+- Fixed GPIOC5, GPIOG6, GPIOI0~7 and GPIOL6~7 directions and
+ default values.
+- Disabled internal pull-down of GPIOB6.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/intel.c | 50 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index d1ac8651ac6c..b1a08db91bec 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -162,6 +162,54 @@ static void sgpio_init(void)
+ SCU_BASE | SCU_414);
+ }
+
++#define SCU_410 0x410 /* Multi-function Pin Control #4 */
++#define GPIO_000 0x000 /* GPIO A/B/C/D Value */
++#define GPIO_004 0x004 /* GPIO A/B/C/D Direction */
++#define GPIO_020 0x020 /* GPIO E/F/G/H Value */
++#define GPIO_024 0x024 /* GPIO E/F/G/H Direction */
++#define GPIO_070 0x070 /* GPIO I/J/K/L Value */
++#define GPIO_074 0x074 /* GPIO I/J/K/L Direction */
++
++static void set_gpio_default_state(void)
++{
++#define SCU_410_RGMII3TXD1 BIT(19)
++#define GPIO_C3 BIT(19)
++
++ /*
++ * Set GPIOC3 as an output with value high explicitly since it doesn't
++ * have an external pull up. It uses direct register access because
++ * it's called from board_early_init_f().
++ */
++ writel(readl(SCU_BASE | SCU_410) & ~SCU_410_RGMII3TXD1,
++ SCU_BASE | SCU_410);
++ writel(readl(AST_GPIO_BASE | GPIO_004) | GPIO_C3,
++ AST_GPIO_BASE | GPIO_004);
++ writel(readl(AST_GPIO_BASE | GPIO_000) | GPIO_C3,
++ AST_GPIO_BASE | GPIO_000);
++
++#define SCU_610 0x610 /* Disable internal pull-down #0 */
++#define SCU_610_GPIOB6 BIT(14)
++ writel(readl(SCU_BASE | SCU_610) | SCU_610_GPIOB6, SCU_BASE | SCU_610);
++
++ /*
++ * GPIO C5 has a connection between BMC(3.3v) and CPU(1.0v) so if we
++ * set it as an logic high output, it will be clipped by a protection
++ * circuit in the CPU and eventually the signal will be detected as
++ * logic low. So we leave this GPIO as an input so that the signal
++ * can be pulled up by a CPU internal resister. The signal will be
++ * 1.0v logic high resultingy.
++ */
++#define GPIO_C5 BIT(21)
++ writel(readl(AST_GPIO_BASE | GPIO_004) & ~GPIO_C5,
++ AST_GPIO_BASE | GPIO_004);
++
++#define GPIO_G6 BIT(22)
++ writel(readl(AST_GPIO_BASE | GPIO_024) | GPIO_G6,
++ AST_GPIO_BASE | GPIO_024);
++ writel(readl(AST_GPIO_BASE | GPIO_020) | GPIO_G6,
++ AST_GPIO_BASE | GPIO_020);
++}
++
+ static void timer_handler(void *regs)
+ {
+ printf("+");
+@@ -175,6 +223,8 @@ int board_early_init_f(void)
+ * I am not sure if it actually does anything... */
+ arch_interrupt_init_early();
+
++ set_gpio_default_state();
++
+ gpio_passthru_init();
+
+ port80h_snoop_init();
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0005-Ast2600-Enable-interrupt-in-u-boot.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0005-Ast2600-Enable-interrupt-in-u-boot.patch
new file mode 100644
index 000000000..d5bd4a2b1
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0005-Ast2600-Enable-interrupt-in-u-boot.patch
@@ -0,0 +1,567 @@
+From c1561193296d04dd8bd06adca43edac814058367 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 3 Jan 2020 12:52:29 +0800
+Subject: [PATCH] Enable interrupt in u-boot.
+
+Ast2600 is Cortex-A7
+GIC V2 is used as the interrupt controller
+GIC includes GICD and GICC
+
+Testedby:
+1. Enable interrupt based SW handshake for ESPI
+2. Both ArcherCity and Ast2600 EVB are working well.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ Kconfig | 14 +++
+ arch/arm/lib/stack.c | 9 ++
+ arch/arm/lib/vectors.S | 30 +++++-
+ board/aspeed/ast2600_intel/ast-espi.c | 3 +-
+ board/aspeed/ast2600_intel/ast-irq.c | 185 +++++++++++++++++-----------------
+ board/aspeed/ast2600_intel/ast-irq.h | 8 --
+ board/aspeed/ast2600_intel/intel.c | 1 -
+ 7 files changed, 145 insertions(+), 105 deletions(-)
+ delete mode 100644 board/aspeed/ast2600_intel/ast-irq.h
+
+diff --git a/Kconfig b/Kconfig
+index 305b265ed713..a6f68cd13d54 100644
+--- a/Kconfig
++++ b/Kconfig
+@@ -239,6 +239,20 @@ config BUILD_TARGET
+ special image will be automatically built upon calling
+ make / buildman.
+
++config USE_IRQ
++ bool "Use interrupts"
++ default n
++
++config STACKSIZE_IRQ
++ depends on USE_IRQ
++ int "Size for IRQ stack (only if USE_IRQ enabled)"
++ default 16384
++
++config STACKSIZE_FIQ
++ depends on USE_IRQ
++ int "Size for FIQ stack (only if USE_IRQ enabled)"
++ default 16384
++
+ endmenu # General setup
+
+ menu "Boot images"
+diff --git a/arch/arm/lib/stack.c b/arch/arm/lib/stack.c
+index c89a219dd26d..d9a7f49c5623 100644
+--- a/arch/arm/lib/stack.c
++++ b/arch/arm/lib/stack.c
+@@ -24,6 +24,15 @@ int arch_reserve_stacks(void)
+ gd->irq_sp = gd->start_addr_sp;
+
+ # if !defined(CONFIG_ARM64)
++# ifdef CONFIG_USE_IRQ
++ gd->start_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ);
++ printf("Reserving %zu Bytes for IRQ stack at: %08lx\n",
++ CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ, gd->start_addr_sp);
++
++ /* 8-byte alignment for ARM ABI compliance */
++ gd->start_addr_sp &= ~0x07;
++# endif
++
+ /* leave 3 words for abort-stack, plus 1 for alignment */
+ gd->start_addr_sp -= 16;
+ # endif
+diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S
+index 2ca6e2494a7a..5a5e60dbdde4 100644
+--- a/arch/arm/lib/vectors.S
++++ b/arch/arm/lib/vectors.S
+@@ -154,6 +154,17 @@ IRQ_STACK_START_IN:
+ .word 0x0badc0de
+ #endif
+
++#ifdef CONFIG_USE_IRQ
++/* IRQ stack memory (calculated at run-time) */
++.globl IRQ_STACK_START
++IRQ_STACK_START:
++ .word 0x0badc0de
++/* IRQ stack memory (calculated at run-time) */
++.globl FIQ_STACK_START
++FIQ_STACK_START:
++ .word 0x0badc0de
++#endif
++
+ @
+ @ IRQ stack frame.
+ @
+@@ -277,17 +288,30 @@ not_used:
+ bad_save_user_regs
+ bl do_not_used
+
+-
++#ifdef CONFIG_USE_IRQ
++ .align 5
++irq:
++ get_irq_stack
++ irq_save_user_regs
++ bl do_irq
++ irq_restore_user_regs
++ .align 5
++fiq:
++ get_fiq_stack
++ /* someone ought to write a more effective fiq_save_user_regs */
++ irq_save_user_regs
++ bl do_fiq
++ irq_restore_user_regs
++#else
+ .align 5
+ irq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_irq
+-
+ .align 5
+ fiq:
+ get_bad_stack
+ bad_save_user_regs
+ bl do_fiq
+-
++#endif /* CONFIG_USE_IRQ */
+ #endif /* CONFIG_SPL_BUILD */
+diff --git a/board/aspeed/ast2600_intel/ast-espi.c b/board/aspeed/ast2600_intel/ast-espi.c
+index 0fdbf089a450..1d7ae529612d 100644
+--- a/board/aspeed/ast2600_intel/ast-espi.c
++++ b/board/aspeed/ast2600_intel/ast-espi.c
+@@ -142,7 +142,7 @@ static void espi_handshake_ack(void)
+ }
+ }
+
+-int espi_irq_handler(struct pt_regs *regs)
++static void espi_irq_handler(void *cookie)
+ {
+ uint32_t irq_status = readl(AST_ESPI_BASE + ESPI008);
+
+@@ -226,7 +226,6 @@ int espi_irq_handler(struct pt_regs *regs)
+ readl(AST_ESPI_BASE + ESPI11C),
+ readl(AST_ESPI_BASE + ESPI094),
+ readl(AST_ESPI_BASE + ESPI12C), irq_status);
+- return 0;
+ }
+
+ void espi_init(void)
+diff --git a/board/aspeed/ast2600_intel/ast-irq.c b/board/aspeed/ast2600_intel/ast-irq.c
+index f817f8cd7c81..106bb3b4ffb2 100644
+--- a/board/aspeed/ast2600_intel/ast-irq.c
++++ b/board/aspeed/ast2600_intel/ast-irq.c
+@@ -1,14 +1,7 @@
+-/*
+- * Copyright 2018 Intel Corporation
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020, Intel Corporation.
+
+ #include <common.h>
+-#include <netdev.h>
+ #include <asm/io.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+@@ -18,19 +11,6 @@ DECLARE_GLOBAL_DATA_PTR;
+ #define GIC_INTERFACE_OFFSET 0x4000
+ #define GIC_VIRT_OFFSET 0x6000
+
+-#define VIC_STATUS_L 0x80
+-#define VIC_STATUS_H 0x84
+-#define VIC_IRQ_SELECTION_L 0x98
+-#define VIC_IRQ_SELECTION_H 0x9C
+-#define VIC_ENABLE_L 0xA0
+-#define VIC_ENABLE_H 0xA4
+-#define VIC_ENABLE_CLEAR_L 0xA8
+-#define VIC_ENABLE_CLEAR_H 0xAC
+-#define VIC_INTERRUPT_CLEAR_L 0xD8
+-#define VIC_INTERRUPT_CLEAR_H 0xDC
+-
+-#define VIC_CLEAR_ALL (~0)
+-
+ /* GIC_DISTRIBUTOR_OFFSET register offsets */
+ #define GICD_CTLR 0x000
+ #define GICD_TYPER 0x004
+@@ -82,7 +62,9 @@ DECLARE_GLOBAL_DATA_PTR;
+ #define GICC_IIDR 0x00fc
+ #define GICC_DIR 0x1000
+
+-#define GIC_CPU_IMPLEMENTER_MAGIC 0x0102143b
++#define GIC_CPU_IMPLEMENTER_MAGIC 0x0102143b
++#define GICC_IAR_INT_ID_MASK 0x3ff
++#define GIC_CPU_DEACTIVATE 0x1000
+
+ /* GIC_INTERFACE_OFFSET register offsets */
+ #define GICH_HCR 0x000
+@@ -116,9 +98,10 @@ DECLARE_GLOBAL_DATA_PTR;
+
+ #define GIC_VIRT_CPU_IMPLEMENTER_MAGIC 0x0102143b
+
+-#define GICD_CTLR_ENABLE 0x03
+-
+-#define GICD_INT_DEF_PRI 0xa0
++#define GICD_CTLR_ENABLE 0x03 /*enable group 0 and 1*/
++#define GICC_CTLR_ENABLE 0x03
++#define GICD_ITARGET_ALL 0xffffffff
++#define GICD_INT_DEF_PRI 0xa0
+ #define GICD_INT_DEF_PRI_X4 (\
+ (GICD_INT_DEF_PRI << 24) |\
+ (GICD_INT_DEF_PRI << 16) |\
+@@ -129,21 +112,32 @@ DECLARE_GLOBAL_DATA_PTR;
+ #define GICD_INT_EN_CLR_X32 0xffffffff
+ #define GICD_INT_EN_CLR_PPI 0xffff0000
+ #define GICD_INT_EN_SET_SGI 0x0000ffff
++#define GICD_ICFG_LEVEL_TRIGGER 0x55555555
++#define GICC_UNMASK_ALL_PRIORITY 0xff
+
+ #define gicd_readl(OFFSET) readl(gbase + GIC_DISTRIBUTOR_OFFSET + (OFFSET))
+ #define gicd_writel(VALUE, OFFSET) \
+ writel((VALUE), gbase + GIC_DISTRIBUTOR_OFFSET + (OFFSET))
+ #define gicc_readl(OFFSET) readl(gbase + GIC_CPU_OFFSET + (OFFSET))
++#define gicc_writel(VALUE, OFFSET) \
++ writel((VALUE), gbase + GIC_CPU_OFFSET + (OFFSET))
+ #define gich_readl(OFFSET) readl(gbase + GIC_INTERFACE_OFFSET + (OFFSET))
+ #define gicv_readl(OFFSET) readl(gbase + GIC_VIRT_OFFSET + (OFFSET))
+-
+-static size_t max_irq = 0;
+-
+ #define ITLINES_MASK 0x1f
+ #define ITLINES_SHIFT 5
+-
+ #define GIC_MAX_IRQ 1020
++#define SPI_INT_NUM_MIN 32
++#define MAX_IRQ 0xfffffffe
++#define DEBUG_IRQ_ENABLED 0
++#if DEBUG_IRQ_ENABLED
++#define DBG_IRQ printf
++#else
++#define DBG_IRQ(...)
++#endif
++
++static size_t max_irq = 0;
+ static interrupt_handler_t *handlers[GIC_MAX_IRQ] = {NULL};
++static void *cookies[GIC_MAX_IRQ] = {NULL};
+ static unsigned long irq_total = 0;
+ static unsigned long irq_counts[GIC_MAX_IRQ] = {0};
+ static uint32_t gbase = 0;
+@@ -159,24 +153,31 @@ static inline uint32_t gic_base(void)
+
+ static void enable_gic(void)
+ {
+- uint32_t gicd_ctlr;
++ uint32_t gicd_ctlr, gicc_ctlr;
+
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ /* add GIC offset ref table 1-3 for interrupt distributor address */
+ gicd_ctlr = gicd_readl(GICD_CTLR);
++ gicc_ctlr = gicc_readl(GICC_CTLR);
+ gicd_writel(gicd_ctlr | GICD_CTLR_ENABLE, GICD_CTLR);
++ gicc_writel(gicc_ctlr | GICC_CTLR_ENABLE, GICC_CTLR);
+ }
+
+ static void disable_gic(void)
+ {
+- uint32_t gicd_ctlr;
+-
++ uint32_t gicd_ctlr, gicc_ctlr;
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ /* add GIC offset ref table 1-3 for interrupt distributor address */
+ gicd_ctlr = gicd_readl(GICD_CTLR);
+ gicd_writel(gicd_ctlr & ~GICD_CTLR_ENABLE, GICD_CTLR);
++ gicc_ctlr = gicc_readl(GICC_CTLR);
++ gicc_writel(gicc_ctlr & ~GICC_CTLR_ENABLE, GICC_CTLR);
+ }
+
+ static void enable_irq_id(unsigned int id)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
++
+ uint32_t grp = id >> ITLINES_SHIFT;
+ uint32_t grp_bit = 1 << (id & ITLINES_MASK);
+ gicd_writel(grp_bit, GICD_ISENABLERn + grp * sizeof(uint32_t));
+@@ -184,6 +185,7 @@ static void enable_irq_id(unsigned int id)
+
+ static void disable_irq_id(unsigned int id)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ uint32_t grp = id >> ITLINES_SHIFT;
+ uint32_t grp_bit = 1 << (id & ITLINES_MASK);
+ gicd_writel(grp_bit, GICD_ICENABLERn + grp * sizeof(uint32_t));
+@@ -193,34 +195,49 @@ static int gic_probe(void)
+ {
+ int i;
+ gbase = gic_base();
+- enable_gic();
++ DBG_IRQ("gic_probe GIC base = 0x%x, magicd=0x%x\n",
++ gbase, gicd_readl(GICD_IIDR));
+
+ if (gicd_readl(GICD_IIDR) != GIC_DISTRIBUTOR_IMPLEMENTER_MAGIC &&
+ gicc_readl(GICC_IIDR) != GIC_CPU_IMPLEMENTER_MAGIC &&
+ gicv_readl(GICV_IIDR) != GIC_VIRT_CPU_IMPLEMENTER_MAGIC)
+ {
++ printf("error: magic check \n");
+ return 0;
+ }
++
++ disable_gic();
++
+ /* GIC supports up to 1020 lines */
+- max_irq = ((gicd_readl(GICD_TYPER) & ITLINES_MASK) + 1) << ITLINES_SHIFT;
++ max_irq = ((gicd_readl(GICD_TYPER) & ITLINES_MASK) + 1) * 32;
+ if (max_irq > GIC_MAX_IRQ)
+ max_irq = GIC_MAX_IRQ;
+ /* set all lines to be level triggered N-N */
+ for (i = 32; i < max_irq; i += 16)
+- gicd_writel(0, GICD_ICFGRn + i / 4);
+-
+- /* Set priority on all interrupts. */
+- for (i = 0; i < max_irq; i += 4)
++ gicd_writel(GICD_ICFG_LEVEL_TRIGGER, GICD_ICFGRn + i / 4);
++
++ DBG_IRQ("max_irq = 0x%x, typer=0x%x, config=0x%x, maxirq=0x%x\n", max_irq,
++ (gicd_readl(GICD_TYPER) & ITLINES_MASK) + 1,
++ gicd_readl(GICD_ICFGRn + 0x8),
++ ((gicd_readl(GICD_TYPER) & ITLINES_MASK) + 1) * 0x20);
++ /* Set priority and target on all interrupts. */
++ for (i = 0; i < max_irq; i += 4) {
+ gicd_writel(GICD_INT_DEF_PRI_X4, GICD_IPRIORITYRn + i);
++ gicd_writel(GICD_ITARGET_ALL, GICD_ITARGETSRn + i);
++ }
+
+ /* Deactivate and disable all SPIs. */
+ for (i = 32; i < max_irq; i += 32) {
+ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICACTIVERn + i / 8);
+ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICENABLERn + i / 8);
+ }
+- gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICACTIVERn);
+- gicd_writel(GICD_INT_EN_CLR_PPI, GICD_ICENABLERn);
++ gicd_writel(GICD_INT_EN_CLR_X32, GICD_ICACTIVERn);
++ gicd_writel(GICD_INT_EN_CLR_PPI, GICD_ICENABLERn);
+ gicd_writel(GICD_INT_EN_SET_SGI, GICD_ISENABLERn);
++ /* unmask all priority */
++ gicc_writel(GICC_UNMASK_ALL_PRIORITY, GICC_PMRn);
++
++ enable_gic();
+
+ return 0;
+ }
+@@ -228,6 +245,7 @@ static int gic_probe(void)
+ void irq_free_handler (int irq);
+ static void gic_shutdown(void)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ int i;
+ for (i = 0; i < max_irq; i++)
+ {
+@@ -238,6 +256,7 @@ static void gic_shutdown(void)
+
+ int arch_interrupt_init_early(void)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ return 0;
+ }
+
+@@ -247,28 +266,28 @@ int arch_interrupt_init(void)
+ for (i = 0; i < GIC_MAX_IRQ; i++)
+ {
+ handlers[i] = NULL;
++ cookies[i] = NULL;
+ irq_counts[i] = 0;
+ }
++ DBG_IRQ("arch_interrupt_init\n");
+ return gic_probe();
+ }
+
+ int arch_interrupt_fini(void)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ gic_shutdown();
+ return 0;
+ }
+
+ int interrupt_init (void)
+ {
+- /*
+- * setup up stacks if necessary
+- */
++ /* setup up stacks if necessary */
++ IRQ_STACK_START = gd->irq_sp + 8;
+ IRQ_STACK_START_IN = gd->irq_sp + 8;
+
+- printf("%s()\n", __FUNCTION__);
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ return arch_interrupt_init();
+-
+- return 0;
+ }
+
+ int global_interrupts_enabled (void)
+@@ -286,12 +305,12 @@ void enable_interrupts (void)
+ {
+ unsigned long cpsr;
+ __asm__ __volatile__("mrs %0, cpsr\n"
+- "bic %0, %0, #0x80\n"
++ "bic %0, %0, #0x1c0\n"
+ "msr cpsr_c, %0"
+ : "=r" (cpsr)
+ :
+ : "memory");
+-
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ return;
+ }
+
+@@ -304,11 +323,13 @@ int disable_interrupts (void)
+ : "=r" (cpsr), "=r" (temp)
+ :
+ : "memory");
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ return (cpsr & 0x80) == 0;
+ }
+
+-void irq_install_handler(int irq, interrupt_handler_t *handler, void *ctx)
++void irq_install_handler(int irq, interrupt_handler_t *handler, void *cookie)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ if (irq > max_irq) {
+ printf("irq %d out of range\n", irq);
+ return;
+@@ -317,19 +338,22 @@ void irq_install_handler(int irq, interrupt_handler_t *handler, void *ctx)
+ printf("irq %d already in use (%p)\n", irq, handlers[irq]);
+ return;
+ }
+- printf("registering handler for irq %d\n", irq);
++ DBG_IRQ("registering handler for irq %d\n", irq);
+ handlers[irq] = handler;
++ cookies[irq] = cookie;
+ enable_irq_id(irq);
+ }
+
+ void irq_free_handler (int irq)
+ {
++ DBG_IRQ(" %s()\n", __FUNCTION__);
+ if (irq >= max_irq) {
+ printf("irq %d out of range\n", irq);
+ return;
+ }
+ if (handlers[irq]) {
+ handlers[irq] = NULL;
++ cookies[irq] = NULL;
+ disable_irq_id(irq);
+ }
+ }
+@@ -339,8 +363,10 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ int i;
+ int enabled = global_interrupts_enabled();
+ printf("GIC base = 0x%x\n", gbase);
+- printf("interrupts %sabled\n", (enabled ? "en" : "dis"));
++ printf("Number of interrupt sources = %d\n", max_irq);
++ printf("Interrupts %sabled\n", (enabled ? "en" : "dis"));
+ uint32_t grp_en = 0;
++
+ for (i = 0; i < max_irq; i++) {
+ if ((i & ITLINES_MASK) == 0)
+ grp_en = gicd_readl(GICD_ISENABLERn +
+@@ -348,52 +374,29 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+ int irq_enabled = grp_en & (1 << (i & ITLINES_MASK));
+ if (!irq_enabled)
+ continue;
+- printf("% 2i (% 3s): %lu\n", i,
++ printf("%2d (%3s): %lu\n", i,
+ (irq_enabled ? "on" : "off"), irq_counts[i]);
+ }
+- printf("total: %lu\n", irq_total);
++ printf("Total: %lu\n", irq_total);
++
+ return 0;
+ }
+
+ void do_irq(struct pt_regs *pt_regs)
+ {
+- int i;
+- if (!gbase) {
+- static int printed_msg = 0;
+- if (!printed_msg)
+- {
+- printed_msg = 1;
+- printf("interrupt before configured!\n");
+- }
+- return;
+- }
+- irq_total++;
+- uint32_t grp_pend = 0;
+- for (i = 0; i < max_irq; i++) {
+- /* limit reads of the pending register to once in 32 */
+- if ((i & ITLINES_MASK) == 0)
+- grp_pend = gicd_readl(GICD_ISPENDRn +
+- (i >> ITLINES_SHIFT) * sizeof(uint32_t));
+- uint32_t pending = grp_pend & (1 << (i & ITLINES_MASK));
+- if (pending) {
+- irq_counts[i]++;
+- /* mask via GICD_ICENABLERn */
+- gicd_writel(pending, GICD_ICENABLERn +
+- (i >> ITLINES_SHIFT) * sizeof(uint32_t));
+- if (handlers[i]) {
+- handlers[i](pt_regs);
+- /* unmask via GICD_ISENABLERn */
+- gicd_writel(pending, GICD_ISENABLERn +
+- (i >> ITLINES_SHIFT) * sizeof(uint32_t));
+- /* clear pending via GICD_ICPENDRn */
+- gicd_writel(pending, GICD_ICPENDRn +
+- (i >> ITLINES_SHIFT) * sizeof(uint32_t));
+- } else {
+- printf("unexpected interrupt %i; masking\n", i);
+- /* clear pending via GICD_ICPENDRn */
+- gicd_writel(pending, GICD_ISPENDRn +
+- (i >> ITLINES_SHIFT) * sizeof(uint32_t));
+- }
++ uint32_t irqstat, irqnr;
++
++ if (irq_total < MAX_IRQ)
++ irq_total++;
++ irqstat = gicc_readl(GICC_IAR);
++ irqnr = irqstat & GICC_IAR_INT_ID_MASK;
++
++ if (irqnr > SPI_INT_NUM_MIN && irqnr < GIC_MAX_IRQ) {
++ gicc_writel(irqnr, GICC_EOIR);
++ if (irq_counts[irqnr] < MAX_IRQ)
++ irq_counts[irqnr]++;
++ if (handlers[irqnr]) {
++ handlers[irqnr](cookies[irqnr]);
+ }
+ }
+ }
+diff --git a/board/aspeed/ast2600_intel/ast-irq.h b/board/aspeed/ast2600_intel/ast-irq.h
+deleted file mode 100644
+index 9957f2baa7ff..000000000000
+--- a/board/aspeed/ast2600_intel/ast-irq.h
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#ifndef _AST_IRQ_H_
+-#define _AST_IRQ_H_
+-
+-int request_irq(int irq, interrupt_handler_t *handler);
+-int release_irq(int irq);
+-int arch_interrupt_init_early(void);
+-
+-#endif
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index ac108c3a066c..22a377d2cb77 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -209,7 +209,6 @@ static void timer_handler(void *regs)
+ printf("+");
+ }
+
+-extern int arch_interrupt_init_early(void);
+ int board_early_init_f(void)
+ {
+ /* This is called before relocation; beware! */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0006-SPI-Quad-IO-Mode.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0006-SPI-Quad-IO-Mode.patch
new file mode 100644
index 000000000..34d8b1abb
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0006-SPI-Quad-IO-Mode.patch
@@ -0,0 +1,105 @@
+From c438edace30a3408c827faaae2d5004fe5ae010d Mon Sep 17 00:00:00 2001
+From: arun-pm <arun.p.m@linux.intel.com>
+Date: Fri, 29 Nov 2019 00:19:09 +0530
+Subject: [PATCH] SPI Quad IO Mode
+
+This commit adds quad IO mode in SPI driver for AST2600.
+
+Note:- Removed n25q00 Quad I/O support for the time being due to clock issue
+ with chip 'Micron 8UA15 - rw182 (128MB)' while enabling Quad I/O mode.
+---
+ arch/arm/dts/ast2600-intel.dts | 6 ++----
+ drivers/mtd/spi/spi-nor-ids.c | 7 ++++++-
+ drivers/spi/aspeed_spi.c | 18 +++++++++++++++++-
+ 3 files changed, 25 insertions(+), 6 deletions(-)
+ mode change 100755 => 100644 drivers/spi/aspeed_spi.c
+
+diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts
+index d16581c5811d..ab78b516b6a3 100644
+--- a/arch/arm/dts/ast2600-intel.dts
++++ b/arch/arm/dts/ast2600-intel.dts
+@@ -101,16 +101,14 @@
+
+ &fmc {
+ status = "okay";
+-#if 0
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fmcquad_default>;
+-#endif
+ flash@0 {
+ compatible = "spi-flash", "sst,w25q256";
+ status = "okay";
+ spi-max-frequency = <40000000>;
+- spi-tx-bus-width = <2>;
+- spi-rx-bus-width = <2>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ };
+ };
+
+diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
+index ad733e71988b..257ab472305c 100644
+--- a/drivers/mtd/spi/spi-nor-ids.c
++++ b/drivers/mtd/spi/spi-nor-ids.c
+@@ -164,7 +164,12 @@ const struct flash_info spi_nor_ids[] = {
+ { INFO("n25q256ax1", 0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("n25q512a", 0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("n25q512ax3", 0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+- { INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
++ /* Removed n25q00 Quad I/O support for the time being due to clock issue with chip 'Micron 8UA15 - rw182 (128MB)'
++ * while enabling Quad I/O mode. As this chip is default shipped in platforms, marking it
++ * as Not supported for the time being. Once all chips are replaced with the new model, this can be enabled
++ * back(Note:- Certain other chips having same name(n25q00) but different part number has no issues).
++ */
++ { INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | NO_CHIP_ERASE) },
+ { INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ { INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ #endif
+diff --git a/drivers/spi/aspeed_spi.c b/drivers/spi/aspeed_spi.c
+old mode 100755
+new mode 100644
+index c7b998fadfde..930b18443a48
+--- a/drivers/spi/aspeed_spi.c
++++ b/drivers/spi/aspeed_spi.c
+@@ -16,6 +16,9 @@
+ #include <linux/ioport.h>
+
+ #define ASPEED_SPI_MAX_CS 3
++#define AST2600A0 0x05000303
++#define AST2600A0_MAX_FREQ 40000000
++#define AST_MAX_FREQ 100000000
+
+ struct aspeed_spi_regs {
+ u32 conf; /* 0x00 CE Type Setting */
+@@ -1011,6 +1014,19 @@ static int aspeed_spi_bind(struct udevice *bus)
+ return 0;
+ }
+
++static int aspeed_get_max_freq(void)
++{
++ u32 rev_id = readl(ASPEED_REVISION_ID);
++
++ /*Limit max spi frequency less than 50MHz on AST2600-A0 due
++ * to FWSPICLK signal quality issue.
++ */
++ if(rev_id == AST2600A0)
++ return AST2600A0_MAX_FREQ;
++ else
++ return AST_MAX_FREQ;
++}
++
+ static int aspeed_spi_probe(struct udevice *bus)
+ {
+ struct resource res_regs, res_ahb;
+@@ -1041,7 +1057,7 @@ static int aspeed_spi_probe(struct udevice *bus)
+ clk_free(&hclk);
+
+ priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency",
+- 100000000);
++ aspeed_get_max_freq());
+
+ priv->num_cs = dev_read_u32_default(bus, "num-cs", ASPEED_SPI_MAX_CS);
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0007-ast2600-Override-OTP-strap-settings.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0007-ast2600-Override-OTP-strap-settings.patch
new file mode 100644
index 000000000..e8ffb4e72
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0007-ast2600-Override-OTP-strap-settings.patch
@@ -0,0 +1,78 @@
+From ddf356e738ab147775bf49a3a4fae179c0dde9ef Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 29 Jan 2020 14:55:44 -0800
+Subject: [PATCH] ast2600: Override OTP strap settings
+
+This commit adds settings to override OTP strap.
+Also, this commit disables SoC debug interface.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/mach-aspeed/ast2600/platform.S | 26 +++++++++++++++++++++++---
+ 1 file changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-aspeed/ast2600/platform.S b/arch/arm/mach-aspeed/ast2600/platform.S
+index d107ed80a835..eb3cb2f38cb6 100644
+--- a/arch/arm/mach-aspeed/ast2600/platform.S
++++ b/arch/arm/mach-aspeed/ast2600/platform.S
+@@ -45,7 +45,9 @@
+ #define AST_SCU_HPLL_PARAM_EXT (AST_SCU_BASE + 0x204)
+ #define AST_SCU_MFP_CTRL15 (AST_SCU_BASE + 0x454)
+ #define AST_SCU_HW_STRAP1 (AST_SCU_BASE + 0x500)
++#define AST_SCU_HW_STRAP1_CLR (AST_SCU_BASE + 0x504)
+ #define AST_SCU_HW_STRAP2 (AST_SCU_BASE + 0x510)
++#define AST_SCU_HW_STRAP2_CLR (AST_SCU_BASE + 0x514)
+ #define AST_SCU_CA7_CTRL (AST_SCU_BASE + 0x800)
+ #define AST_SCU_CA7_AXI_PREFETCH_START (AST_SCU_BASE + 0x808)
+ #define AST_SCU_CA7_AXI_PREFETCH_END (AST_SCU_BASE + 0x80C)
+@@ -146,6 +148,26 @@ do_primary_core_setup:
+ /* unlock system control unit */
+ scu_unlock
+
++ /* disable CA7 CPU boot */
++ ldr r0, =AST_SCU_HW_STRAP1_CLR
++ movw r1, #0x0001 @; Disable ARM CA7 CPU boot
++ movt r1, #0x0000
++ str r1, [r0]
++
++ /* enable eSPI, debug interface and disable UART5 boot*/
++ ldr r0, =AST_SCU_HW_STRAP2_CLR
++ movw r1, #0x0040 @; Select eSPI
++ movt r1, #0x0000
++ orr r1, #0x0010 @; Enable debug interface
++ orr r1, #0x0100 @; Disable UART5 boot
++ str r1, [r0]
++
++ /* enable ACPI */
++ ldr r0, =AST_SCU_HW_STRAP2
++ ldr r1, [r0]
++ orr r1, #0x20 @; Enable ACPI
++ str r1, [r0]
++
+ /* identify AST2600 A0/A1 */
+ ldr r0, =AST_SCU_REV_ID
+ ldr r0, [r0]
+@@ -241,19 +263,17 @@ wait_lock:
+ ldr r1, =AST_FMC_CE0_CTRL
+ str r0, [r1]
+
+-#if 0
+ /* disable UART-based SoC Debug Interface UART5 and P2A bridge*/
+ ldr r0, =AST_SCU_DEBUG_CTRL
+ ldr r1, [r0]
+ orr r1, #0x03
+ str r1, [r0]
+-
++
+ /* disable UART-based SoC Debug Interface UART1 and LPC2AHB bridge */
+ ldr r0, =AST_SCU_DEBUG_CTRL2
+ ldr r1, [r0]
+ orr r1, #0x0A
+ str r1, [r0]
+-#endif
+
+ /* Strongest LADESPID Driving Strngth */
+ ldr r0, =AST_SCU_MFP_CTRL15
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0008-AST2600-Add-TPM-pulse-trigger.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0008-AST2600-Add-TPM-pulse-trigger.patch
new file mode 100644
index 000000000..19606ee38
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0008-AST2600-Add-TPM-pulse-trigger.patch
@@ -0,0 +1,50 @@
+From b7f02c074c0dee6b5d6d1c1f632993f7b0e3e952 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 25 Mar 2020 15:04:26 -0700
+Subject: [PATCH] AST2600: Add TPM pulse trigger
+
+This commit adds TPM pulse trigger into u-boot booting.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/intel.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index 22a377d2cb77..47e5ad21d66d 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -204,6 +204,21 @@ static void set_gpio_default_state(void)
+ AST_GPIO_BASE | GPIO_020);
+ }
+
++void enable_onboard_tpm(void)
++{
++#define GPIO_C2 BIT(18)
++
++ writel(readl(AST_GPIO_BASE | GPIO_004) | GPIO_C2,
++ AST_GPIO_BASE | GPIO_004);
++ writel(readl(AST_GPIO_BASE | GPIO_000) | GPIO_C2,
++ AST_GPIO_BASE | GPIO_000);
++
++ mdelay(50);
++
++ writel(readl(AST_GPIO_BASE | GPIO_000) & ~GPIO_C2,
++ AST_GPIO_BASE | GPIO_000);
++}
++
+ static void timer_handler(void *regs)
+ {
+ printf("+");
+@@ -234,6 +249,8 @@ int board_early_init_r(void)
+ debug("board_early_init_r\n");
+ /* timer_enable(0, 1, timer_handler); */
+
++ enable_onboard_tpm();
++
+ return 0;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0009-AST2600-Disable-DMA-arbitration-options-on-MAC1-and-.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0009-AST2600-Disable-DMA-arbitration-options-on-MAC1-and-.patch
new file mode 100644
index 000000000..259afc619
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0009-AST2600-Disable-DMA-arbitration-options-on-MAC1-and-.patch
@@ -0,0 +1,57 @@
+From 363cb4a59bd21708465ad46553a098615abea1dd Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 31 Mar 2020 13:28:31 -0700
+Subject: [PATCH] AST2600: Disable DMA arbitration options on MAC1 and MAC2
+
+Aspeed added 2 new options to DMA arbitration in AST2600A1 MAC1
+and MAC2 but it has a bug in A1 so it might cause the MAC hang if
+we enable these 2 new options.
+Option 1: Round Robin, register MAC58[27]
+Option 2: Tx Valid, register MAC58[28]
+
+So this commit disables options above.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/mach-aspeed/ast2600/platform.S | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/mach-aspeed/ast2600/platform.S b/arch/arm/mach-aspeed/ast2600/platform.S
+index eb3cb2f38cb6..0316e5364b78 100644
+--- a/arch/arm/mach-aspeed/ast2600/platform.S
++++ b/arch/arm/mach-aspeed/ast2600/platform.S
+@@ -60,6 +60,12 @@
+ #define AST_FMC_WDT1_CTRL_MODE (AST_FMC_BASE + 0x060)
+ #define AST_FMC_WDT2_CTRL_MODE (AST_FMC_BASE + 0x064)
+
++#define AST_MAC1_BASE (0x1E660000)
++#define AST_MAC1_CTRL2 (AST_MAC1_BASE + 0x058)
++
++#define AST_MAC2_BASE (0x1E680000)
++#define AST_MAC2_CTRL2 (AST_MAC2_BASE + 0x058)
++
+ #define AST_GPIO_BASE (0x1E780000)
+ #define AST_GPIOYZ_DATA_VALUE (AST_GPIO_BASE + 0x1E0)
+
+@@ -228,6 +234,18 @@ wait_lock:
+ orr r1, #0x40
+ str r1, [r0]
+
++ /* disable DMA arbitration on MAC1 (A1 bug) */
++ ldr r0, =AST_MAC1_CTRL2
++ ldr r1, [r0]
++ orr r1, #0x18000000
++ str r1, [r0]
++
++ /* disable DMA arbitration on MAC2 (A1 bug) */
++ ldr r0, =AST_MAC2_CTRL2
++ ldr r1, [r0]
++ orr r1, #0x18000000
++ str r1, [r0]
++
+ 1:
+ /* release display port reset */
+ ldr r0, =AST_SCU_SYSRST_CTRL_CLR
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0010-Fix-timer-support.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0010-Fix-timer-support.patch
new file mode 100644
index 000000000..cf13a17f2
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0010-Fix-timer-support.patch
@@ -0,0 +1,173 @@
+From bd4eb78dc71529342e5d0b784731c412cf747acc Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 20 Apr 2020 10:42:05 -0700
+Subject: [PATCH] Fix timer support
+
+Timer interrupt flag should be cleared just after it gets an
+interrupt otherwise the interrupt will be called infinitely and
+main context will starve resultingly. To fix this issue, this
+commit adds the timer interrupt flag clearing logic.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/ast-timer.c | 69 ++++++++++++++++++++--------------
+ board/aspeed/ast2600_intel/intel.c | 13 ++++---
+ 2 files changed, 48 insertions(+), 34 deletions(-)
+
+diff --git a/board/aspeed/ast2600_intel/ast-timer.c b/board/aspeed/ast2600_intel/ast-timer.c
+index cf8c69aba5d3..d98ec9238e15 100644
+--- a/board/aspeed/ast2600_intel/ast-timer.c
++++ b/board/aspeed/ast2600_intel/ast-timer.c
+@@ -1,59 +1,72 @@
+-/*
+- * Copyright 2019 Intel Corporation
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2019-2020, Intel Corporation.
+
+ #include <common.h>
+ #include <asm/io.h>
+
+ static const int timer_irqs[] = {48, 49, 50, 51, 52, 53, 54, 55};
++static void (*timer_callback[ARRAY_SIZE(timer_irqs)]) (void *) = {NULL};
++static void *cb_cookie[ARRAY_SIZE(timer_irqs)] = {NULL};
++
+ #define AST_TIMER_BASE 0x1e782000
+ /* offsets from AST_TIMER_BASE for each timer */
+-static const uint32_t timer_bases[] = {0, 0x10, 0x20, 0x40,
+- 0x50, 0x60, 0x70, 0x80};
+-#define TIMER_1MHZ_CLK_COUNT 1000000u
++static const u32 timer_bases[] = {0, 0x10, 0x20, 0x40, 0x50, 0x60, 0x70, 0x80};
+ #define TIMER_ENABLE 1
+ #define TIMER_1MHZ_CLK_SEL 2
+ #define TIMER_ENABLE_IRQ 4
+ #define TIMER_RESET_BY_WDT 8
+ #define TIMER_CONTROL 0x30
++#define TIMER_INT_CLR 0x34
+ #define TIMER_RELOAD 0x04
+ #define TIMER_CONTROL_CLEAR 0x3c
+
++static void timer_irq_handler(void *cookie)
++{
++ int timer_nr = (int)cookie;
++
++ writel(1 << timer_nr, AST_TIMER_BASE + TIMER_INT_CLR);
++
++ if (timer_callback[timer_nr])
++ timer_callback[timer_nr](cb_cookie[timer_nr]);
++}
++
+ void timer_disable(int n)
+ {
+- if (n < 0 || n > 7) {
++ u32 tctrl;
++
++ if (n < 0 || n > 7)
+ return;
+- }
+- uint32_t tctrl = 0xf << (n * 4);
++
++ irq_free_handler(timer_irqs[n]);
++ timer_callback[n] = NULL;
++ cb_cookie[n] = NULL;
++
++ tctrl = 0xf << (n * 4);
+ writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL_CLEAR);
+ }
+
+-void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler)
++void timer_enable(uint n, u32 interval_us, interrupt_handler_t *handler,
++ void *cookie)
+ {
+- if (n < 0 || n > 7) {
+- return;
+- }
+- if (!freq)
++ u32 tctrl;
++
++ if (n < 0 || n > 7 || !interval_us)
+ return;
+
+ timer_disable(n);
+
+- uint32_t v = TIMER_1MHZ_CLK_COUNT / freq;
+- writel(v, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
++ writel(interval_us, AST_TIMER_BASE + timer_bases[n] + TIMER_RELOAD);
+
+- uint32_t tctrl = (
+- TIMER_ENABLE |
+- TIMER_1MHZ_CLK_SEL |
+- TIMER_RESET_BY_WDT) << (n * 4);
++ tctrl = (TIMER_ENABLE | TIMER_1MHZ_CLK_SEL |
++ TIMER_RESET_BY_WDT) << (n * 4) | TIMER_ENABLE_IRQ << (n * 4);
+
+ if (handler) {
+- irq_install_handler(timer_irqs[n], handler, NULL);
+- tctrl |= (TIMER_ENABLE_IRQ << (n * 4));
++ timer_callback[n] = handler;
++ cb_cookie[n] = cookie;
+ }
+- writel(tctrl, AST_TIMER_BASE + TIMER_CONTROL);
++
++ irq_install_handler(timer_irqs[n], timer_irq_handler, (void *)n);
++
++ writel(readl(AST_TIMER_BASE + TIMER_CONTROL) | tctrl,
++ AST_TIMER_BASE + TIMER_CONTROL);
+ }
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index 47e5ad21d66d..befeaff0a953 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -219,16 +219,14 @@ void enable_onboard_tpm(void)
+ AST_GPIO_BASE | GPIO_000);
+ }
+
+-static void timer_handler(void *regs)
++static void timer_callback(void *cookie)
+ {
+- printf("+");
++ debug("+");
+ }
+
+ int board_early_init_f(void)
+ {
+ /* This is called before relocation; beware! */
+- /* initialize running timer? timer_init is next in the list but
+- * I am not sure if it actually does anything... */
+ arch_interrupt_init_early();
+
+ set_gpio_default_state();
+@@ -243,11 +241,9 @@ int board_early_init_f(void)
+ return 0;
+ }
+
+-extern void timer_enable(int n, uint32_t freq, interrupt_handler_t *handler);
+ int board_early_init_r(void)
+ {
+ debug("board_early_init_r\n");
+- /* timer_enable(0, 1, timer_handler); */
+
+ enable_onboard_tpm();
+
+@@ -255,8 +251,13 @@ int board_early_init_r(void)
+ }
+
+ extern void espi_init(void);
++extern void timer_enable(int n, u32 interval_us, interrupt_handler_t *handler,
++ void *cookie);
+ int board_late_init(void)
+ {
++#define ONE_SEC_IN_USEC 1000000
++
++ timer_enable(0, ONE_SEC_IN_USEC, timer_callback, (void *)0);
+ espi_init();
+
+ return 0;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0011-KCS-driver-support-in-uBoot.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0011-KCS-driver-support-in-uBoot.patch
new file mode 100644
index 000000000..f446d797a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0011-KCS-driver-support-in-uBoot.patch
@@ -0,0 +1,614 @@
+From 1fbd857e2ff5396ea057f686cbd01c6db4328316 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 20 Apr 2020 11:08:22 -0700
+Subject: [PATCH] KCS driver support in uBoot
+
+Added KCS support in uBoot. This will enable
+KCS channels and set the specified registers
+to do KCS communication in uBoot. It also
+consist of read and write KCS message transations
+work flow implementation( As specified in IPMI
+specification Section 9.15). It is enabled
+only when Force Firmware Update Jumper is ON.
+
+Tested:
+Stopped booting in uBoot and sent IPMI commands
+via KCS interfaces using cmdtool.efi.
+ - Get Device ID:
+ Req: cmdtool.efi 20 18 1
+ Res: 00 23 00 12 03 02 BF 57 01 00 7B 00 00 00 00 00
+ - Get Self Test Results
+ Req: cmdtool.efi 20 18 4
+ Res: 00 56 00
+ - All other commands
+ Req: cmdtool.efi 20 18 2
+ Res: C1 (Invalid).
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/Makefile | 1 +
+ board/aspeed/ast2600_intel/ast-kcs.c | 418 +++++++++++++++++++++++++++++++++++
+ board/aspeed/ast2600_intel/ast-kcs.h | 112 ++++++++++
+ board/aspeed/ast2600_intel/intel.c | 4 +
+ 4 files changed, 535 insertions(+)
+ create mode 100644 board/aspeed/ast2600_intel/ast-kcs.c
+ create mode 100644 board/aspeed/ast2600_intel/ast-kcs.h
+
+diff --git a/board/aspeed/ast2600_intel/Makefile b/board/aspeed/ast2600_intel/Makefile
+index 37d2f0064f38..d049922719f3 100644
+--- a/board/aspeed/ast2600_intel/Makefile
++++ b/board/aspeed/ast2600_intel/Makefile
+@@ -2,3 +2,4 @@ obj-y += intel.o
+ obj-y += ast-espi.o
+ obj-y += ast-irq.o
+ obj-y += ast-timer.o
++obj-y += ast-kcs.o
+diff --git a/board/aspeed/ast2600_intel/ast-kcs.c b/board/aspeed/ast2600_intel/ast-kcs.c
+new file mode 100644
+index 000000000000..a03b7e725370
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-kcs.c
+@@ -0,0 +1,418 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020 Intel Corporation
++
++#include "ast-kcs.h"
++
++#ifdef DEBUG_KCS_ENABLED
++#define DBG_KCS printf
++#else
++#define DBG_KCS(...)
++#endif
++
++/* TODO: Move to IPMI file. */
++#define IPMI_CC_OK 0x00
++#define IPMI_CC_INVALID 0xC1
++#define IPMI_CC_UNSPECIFIED 0xFF
++
++#define KCS_CHANNEL_NO_3 3
++
++static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 };
++
++static const struct kcs_io_reg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = {
++ { .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 },
++ { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 },
++ { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 },
++ { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }
++};
++
++#define NO_OF_ENABLED_KCS_CHANNELS ARRAY_SIZE(enabled_kcs_channel)
++
++static struct kcs_packet m_kcs_pkt[NO_OF_ENABLED_KCS_CHANNELS];
++
++static u16 read_status(u16 channel_num)
++{
++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str);
++}
++
++static void write_status(u16 channel_num, u16 value)
++{
++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str);
++}
++
++static u16 read_data(u16 channel_num)
++{
++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].idr);
++}
++
++static void write_data(u16 channel_num, u16 value)
++{
++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].odr);
++}
++
++static void set_kcs_state(u16 channel_num, u16 state)
++{
++ u16 status = read_status(channel_num);
++
++ status &= ~KCS_STATE_MASK;
++ status |= KCS_STATE(state) & KCS_STATE_MASK;
++ write_status(channel_num, status);
++}
++
++static struct kcs_packet *get_kcs_packet(u16 channel_num)
++{
++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) {
++ if (channel_num == enabled_kcs_channel[idx])
++ return &m_kcs_pkt[idx];
++ }
++
++ /* very unlike code hits here. */
++ DBG_KCS("ERROR: %s error. ChannelNo: %d\n", __func__, channel_num);
++ BUG();
++}
++
++static void kcs_force_abort(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ DBG_KCS("ERROR: KCS communication aborted (Channel:%d, Error:%d)\n",
++ channel_num, kcs_pkt->error);
++ set_kcs_state(channel_num, KCS_STATE_ERROR);
++ read_data(channel_num);
++ write_data(channel_num, ZERO_DATA);
++
++ kcs_pkt->phase = KCS_PHASE_ERROR;
++ kcs_pkt->read_req_done = false;
++ kcs_pkt->data_in_idx = 0;
++}
++
++static void init_kcs_packet(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ kcs_pkt->channel = channel_num;
++ kcs_pkt->read_req_done = false;
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ kcs_pkt->error = KCS_NO_ERROR;
++ kcs_pkt->data_in_idx = 0;
++ kcs_pkt->data_out_idx = 0;
++ kcs_pkt->data_out_len = 0;
++}
++
++static void process_kcs_request(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++ int i;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++ if (!kcs_pkt->read_req_done)
++ return;
++
++ DBG_KCS("%s:- chan:%d\n", __func__, channel_num);
++
++#ifdef DEBUG_KCS_ENABLED
++ DBG_KCS("Request data(Len:%d): ", kcs_pkt->data_in_idx);
++ for (i = 0; i < kcs_pkt->data_in_idx; i++)
++ DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]);
++ DBG_KCS("\n");
++#endif
++
++ /*
++ * TODO: Move it to IPMI Command Handler
++ * Below code is added for timebeing till
++ * we implement the IPMI command handler.
++ */
++ kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */
++ kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */
++
++ if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
++ (kcs_pkt->data_in[1] == 0x01)) {
++ /* Get Device ID */
++ u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02,
++ 0xBF, 0x57, 0x01, 0x00, 0x7B,
++ 0x00, 0x00, 0x00, 0x00, 0x00 };
++ for (i = 0; i < 15; i++)
++ kcs_pkt->data_out[i + 3] = device_id[i];
++ kcs_pkt->data_out_len = 18;
++ } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
++ (kcs_pkt->data_in[1] == 0x04)) {
++ /* Get Self Test Results */
++ kcs_pkt->data_out[3] = 0x56;
++ kcs_pkt->data_out[4] = 0x00;
++ kcs_pkt->data_out_len = 5;
++ } else {
++ kcs_pkt->data_out[2] =
++ IPMI_CC_INVALID; /* Invalid or not supported. */
++ kcs_pkt->data_out_len = 3;
++ }
++ /* END: TODO */
++
++#ifdef DEBUG_KCS_ENABLED
++ DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len);
++ for (i = 0; i < kcs_pkt->data_out_len; i++)
++ DBG_KCS(" 0x%02x", kcs_pkt->data_out[i]);
++ DBG_KCS("\n");
++#endif
++
++ kcs_pkt->phase = KCS_PHASE_READ;
++ write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
++ kcs_pkt->read_req_done = false;
++}
++
++static void read_kcs_data(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++
++ switch (kcs_pkt->phase) {
++ case KCS_PHASE_WRITE_START:
++ kcs_pkt->phase = KCS_PHASE_WRITE_DATA;
++ /* fall through */
++
++ case KCS_PHASE_WRITE_DATA:
++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) {
++ kcs_pkt->error = KCS_LENGTH_ERROR;
++ kcs_force_abort(channel_num);
++ return;
++ }
++ set_kcs_state(channel_num, KCS_STATE_WRITE);
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] =
++ read_data(channel_num);
++ break;
++
++ case KCS_PHASE_WRITE_END:
++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) {
++ kcs_pkt->error = KCS_LENGTH_ERROR;
++ kcs_force_abort(channel_num);
++ return;
++ }
++ set_kcs_state(channel_num, KCS_STATE_READ);
++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] =
++ read_data(channel_num);
++ kcs_pkt->phase = KCS_PHASE_READ_WAIT;
++ kcs_pkt->read_req_done = true;
++
++ process_kcs_request(channel_num);
++ break;
++
++ case KCS_PHASE_READ:
++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len)
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++
++ u8 data = read_data(channel_num);
++ if (data != KCS_CTRL_CODE_READ) {
++ DBG_KCS("Invalid Read data. Phase:%d, Data:0x%02x\n",
++ kcs_pkt->phase, data);
++ set_kcs_state(channel_num, KCS_STATE_ERROR);
++ write_data(channel_num, ZERO_DATA);
++ break;
++ }
++
++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len) {
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ break;
++ }
++ write_data(channel_num,
++ kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
++ break;
++
++ case KCS_PHASE_ABORT_1:
++ set_kcs_state(channel_num, KCS_STATE_READ);
++ read_data(channel_num);
++ write_data(channel_num, kcs_pkt->error);
++ kcs_pkt->phase = KCS_PHASE_ABORT_2;
++ break;
++
++ case KCS_PHASE_ABORT_2:
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++ read_data(channel_num);
++ write_data(channel_num, ZERO_DATA);
++ kcs_pkt->phase = KCS_PHASE_IDLE;
++ break;
++
++ default:
++ kcs_force_abort(channel_num);
++ }
++}
++
++static void read_kcs_cmd(u16 channel_num)
++{
++ struct kcs_packet *kcs_pkt = NULL;
++
++ kcs_pkt = get_kcs_packet(channel_num);
++
++ set_kcs_state(channel_num, KCS_STATE_WRITE);
++ write_data(channel_num, ZERO_DATA);
++
++ u16 cmd = read_data(channel_num);
++ switch (cmd) {
++ case KCS_CTRL_CODE_WRITE_START:
++ init_kcs_packet(channel_num);
++ kcs_pkt->phase = KCS_PHASE_WRITE_START;
++ break;
++
++ case KCS_CTRL_CODE_WRITE_END:
++ if (kcs_pkt->error != KCS_NO_ERROR) {
++ kcs_force_abort(channel_num);
++ return;
++ }
++
++ kcs_pkt->phase = KCS_PHASE_WRITE_END;
++ break;
++
++ case KCS_CTRL_CODE_GET_STATUS_ABORT:
++ kcs_pkt->phase = KCS_PHASE_ABORT_1;
++ kcs_pkt->error = KCS_ABORT_BY_CMD;
++ break;
++
++ default:
++ kcs_pkt->error = KCS_ILLEGAL_CTRL_CMD;
++ kcs_force_abort(channel_num);
++ }
++}
++
++static void kcs_irq_handler(void *cookie)
++{
++ u32 channel_num = (u32)cookie;
++ /* Look-up the interrupted KCS channel */
++ u16 status = read_status(channel_num);
++ if (status & BIT_STATUS_IBF) {
++ if (status & BIT_STATUS_COD)
++ read_kcs_cmd(channel_num);
++ else
++ read_kcs_data(channel_num);
++ }
++
++ DBG_KCS("%s: chan_no: %d\n", __FUNC__, channel_num);
++}
++
++static void set_kcs_channel_addr(u16 channel_num)
++{
++ u32 val;
++
++ switch (channel_num) {
++ case 1:
++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_LADR12AS;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = (KCS_CHANNEL1_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR12H);
++ val = (KCS_CHANNEL1_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR12L);
++ break;
++
++ case 2:
++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_LADR12AS;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = (KCS_CHANNEL2_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR12H);
++ val = (KCS_CHANNEL2_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR12L);
++ break;
++
++ case 3:
++ val = (KCS_CHANNEL3_ADDR >> 8);
++ writel(val, AST_LPC_BASE + LPC_LADR3H);
++ val = (KCS_CHANNEL3_ADDR & 0xFF);
++ writel(val, AST_LPC_BASE + LPC_LADR3L);
++ break;
++
++ case 4:
++ val = (((KCS_CHANNEL4_ADDR + 1) << 16) | KCS_CHANNEL4_ADDR);
++ writel(val, AST_LPC_BASE + LPC_LADR4);
++ break;
++
++ default:
++ DBG_KCS("Invalid channel (%d) specified\n", channel_num);
++ break;
++ }
++}
++
++static void enable_kcs_channel(u16 channel_num, u16 enable)
++{
++ u32 val;
++
++ switch (channel_num) {
++ case 1:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE1;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC1E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC1E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE1;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 2:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE2;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC2E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC2E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE2;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 3:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE3;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC3E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_KCSENBL;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC3E;
++ writel(val, AST_LPC_BASE + LPC_HICR0);
++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_KCSENBL;
++ writel(val, AST_LPC_BASE + LPC_HICR4);
++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE3;
++ writel(val, AST_LPC_BASE + LPC_HICR2);
++ }
++ break;
++
++ case 4:
++ if (enable) {
++ val = readl(AST_LPC_BASE + LPC_HICRB) | BIT_IBFIE4 |
++ BIT_LPC4E;
++ writel(val, AST_LPC_BASE + LPC_HICRB);
++ } else {
++ val = readl(AST_LPC_BASE + LPC_HICRB) &
++ ~(BIT_IBFIE4 | BIT_LPC4E);
++ writel(val, AST_LPC_BASE + LPC_HICRB);
++ }
++ break;
++
++ default:
++ DBG_KCS("Invalid channel (%d) specified\n", channel_num);
++ }
++}
++
++void kcs_init(void)
++{
++ /* Initialize the KCS channels. */
++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) {
++ uint channel_num = (uint)enabled_kcs_channel[idx];
++ DBG_KCS("%s Channel: %d\n", __func__, channel_num);
++ set_kcs_channel_addr(channel_num);
++ enable_kcs_channel(channel_num, 1);
++
++ /* Set KCS channel state to idle */
++ set_kcs_state(channel_num, KCS_STATE_IDLE);
++ /* KCS interrupt */
++ irq_install_handler(IRQ_SRC_KCS_BASE + channel_num - 1,
++ kcs_irq_handler, (void *)channel_num);
++ }
++}
+diff --git a/board/aspeed/ast2600_intel/ast-kcs.h b/board/aspeed/ast2600_intel/ast-kcs.h
+new file mode 100644
+index 000000000000..e9b949eccf69
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ast-kcs.h
+@@ -0,0 +1,112 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018-2020 Intel Corporation */
++
++#include <asm/io.h>
++#include <common.h>
++
++#define KCS_CHANNEL_MAX 4
++#define IRQ_SRC_KCS_BASE 170 /* IRQ 170 */
++#define MAX_KCS_PKT_SIZE (64 * 1024)
++/* KCS channel addresses */
++#define KCS_CHANNEL1_ADDR 0xCA0
++#define KCS_CHANNEL2_ADDR 0xCA8
++#define KCS_CHANNEL3_ADDR 0xCA2 /* KCS SMS */
++#define KCS_CHANNEL4_ADDR 0xCA4 /* KCS SMM */
++
++#define ZERO_DATA 0x00
++
++#define AST_LPC_BASE 0x1e789000
++
++/* Aspeed KCS control registers */
++#define LPC_HICR0 0x00 /* Host Interface Control Register 0 */
++#define LPC_HICR1 0x04 /* Host Interface Control Register 1 */
++#define LPC_HICR2 0x08 /* Host Interface Control Register 2 */
++#define LPC_HICR3 0x0C /* Host Interface Control Register 3 */
++#define LPC_HICR4 0x10 /* Host Interface Control Register 4 */
++#define LPC_LADR3H 0x14 /* LPC channel #3 Address Register H */
++#define LPC_LADR3L 0x18 /* LPC channel #3 Address Register H */
++#define LPC_LADR12H 0x1C /* LPC channel #1#2 Address Register H */
++#define LPC_LADR12L 0x20 /* LPC channel #1#2 Address Register L */
++#define LPC_IDR1 0x24 /* Input Data Register 1 */
++#define LPC_IDR2 0x28 /* Input Data Register 2 */
++#define LPC_IDR3 0x2C /* Input Data Register 3 */
++#define LPC_ODR1 0x30 /* Output Data Register 1 */
++#define LPC_ODR2 0x34 /* Output Data Register 2 */
++#define LPC_ODR3 0x38 /* Output Data Register 3 */
++#define LPC_STR1 0x3C /* Status Register 1 */
++#define LPC_STR2 0x40 /* Status Register 2 */
++#define LPC_STR3 0x44 /* Status Register 3 */
++#define LPC_HICRB 0x100 /* Host Interface Control Register B */
++#define LPC_LADR4 0x110 /* LPC channel #4 Address Register */
++#define LPC_IDR4 0x114 /* Input Data Register 4 */
++#define LPC_ODR4 0x118 /* Output Data Register 4 */
++#define LPC_STR4 0x11C /* Status Data Register 4 */
++
++/* LPC Bits */
++#define BIT_LADR12AS BIT(7) /* Channel Address selection */
++#define BIT_IBFIE1 BIT(1) /* Enable IDR1 Recv completion interrupt */
++#define BIT_IBFIE2 BIT(2) /* Enable IDR2 Recv completion interrupt */
++#define BIT_IBFIE3 BIT(3) /* Enable IBF13 interrupt */
++#define BIT_LPC1E BIT(5) /* Enable LPC channel #1 */
++#define BIT_LPC2E BIT(6) /* Enable LPC channel #2 */
++#define BIT_LPC3E BIT(7) /* Enable LPC channel #2 */
++#define BIT_KCSENBL BIT(2) /* Enable KCS interface in Channel #3 */
++#define BIT_IBFIE4 BIT(1)
++#define BIT_LPC4E BIT(0)
++
++#define BIT_STATUS_OBF BIT(0) /* Output Data Register full #1/#2/#3 */
++#define BIT_STATUS_IBF BIT(1) /* Input Data Register full #1/#2/#3 */
++#define BIT_STATUS_COD BIT(3) /* Command/Data - (1=command,0=data) */
++
++#define KCS_STATE_MASK 0xC0 /* BIT[6:7] of status register */
++#define KCS_STATE(state) ((state) << 6)
++
++/* IPMI2.0(section 9.7) - KCS interface State Bits */
++#define KCS_STATE_IDLE 0x00
++#define KCS_STATE_READ 0x01
++#define KCS_STATE_WRITE 0x02
++#define KCS_STATE_ERROR 0x03
++
++/* IPMI2.0(section 9.10) - KCS interface control codes */
++#define KCS_CTRL_CODE_GET_STATUS_ABORT 0x60
++#define KCS_CTRL_CODE_WRITE_START 0x61
++#define KCS_CTRL_CODE_WRITE_END 0x62
++#define KCS_CTRL_CODE_READ 0x68
++
++struct kcs_io_reg {
++ u32 idr;
++ u32 odr;
++ u32 str;
++};
++
++enum kcs_phase {
++ KCS_PHASE_IDLE = 0,
++ KCS_PHASE_WRITE_START = 1,
++ KCS_PHASE_WRITE_DATA = 2,
++ KCS_PHASE_WRITE_END = 3,
++ KCS_PHASE_READ_WAIT = 4,
++ KCS_PHASE_READ = 5,
++ KCS_PHASE_ABORT_1 = 6,
++ KCS_PHASE_ABORT_2 = 7,
++ KCS_PHASE_ERROR = 8
++};
++
++enum kcs_error {
++ KCS_NO_ERROR = 0x00,
++ KCS_ABORT_BY_CMD = 0x01,
++ KCS_ILLEGAL_CTRL_CMD = 0x02,
++ KCS_LENGTH_ERROR = 0x06,
++ KCS_UNSPECIFIED_ERROR = 0xFF,
++};
++
++struct kcs_packet {
++ enum kcs_phase phase;
++ enum kcs_error error;
++ u16 channel;
++ bool read_req_done;
++ u16 data_in_idx;
++ u8 data_in[MAX_KCS_PKT_SIZE];
++ u16 data_out_len;
++ u16 data_out_idx;
++ u8 data_out[MAX_KCS_PKT_SIZE];
++};
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index befeaff0a953..6ac24beb930b 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -251,6 +251,7 @@ int board_early_init_r(void)
+ }
+
+ extern void espi_init(void);
++extern void kcs_init(void);
+ extern void timer_enable(int n, u32 interval_us, interrupt_handler_t *handler,
+ void *cookie);
+ int board_late_init(void)
+@@ -260,6 +261,9 @@ int board_late_init(void)
+ timer_enable(0, ONE_SEC_IN_USEC, timer_callback, (void *)0);
+ espi_init();
+
++ if (read_ffuj())
++ kcs_init();
++
+ return 0;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0012-IPMI-command-handler-implementation-in-uboot.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0012-IPMI-command-handler-implementation-in-uboot.patch
new file mode 100644
index 000000000..a4a574424
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0012-IPMI-command-handler-implementation-in-uboot.patch
@@ -0,0 +1,330 @@
+From 19bbdf59f39d295ad3e698b121a0b447b77b927c Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 20 Apr 2020 16:13:09 -0700
+Subject: [PATCH] IPMI command handler implementation in uboot
+
+IPMI command handler implementation in uBoot.
+Implemented IPMI commands:
+ 1) Get Device ID
+ 2) Get Self Test Result
+
+Tested By:
+Ran the above IPMI command Via KCS channel
+and got proper response.
+- Get Device ID
+ Req: cmdtool.efi 20 18 1
+ Res: 0x00 0x23 0x00 0x82 0x03 0x02 0x00 0x57 0x01 0x00 0x7b 0x00 0x00 0x00 0x00 0x00
+- Get Self Test Results
+ Req: cmdtool.efi 20 18 4
+ Res: 00 56 00
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/Makefile | 1 +
+ board/aspeed/ast2600_intel/ast-kcs.c | 77 +++++++++++---------
+ board/aspeed/ast2600_intel/ipmi-handler.c | 117 ++++++++++++++++++++++++++++++
+ board/aspeed/ast2600_intel/ipmi-handler.h | 39 ++++++++++
+ 4 files changed, 200 insertions(+), 34 deletions(-)
+ create mode 100644 board/aspeed/ast2600_intel/ipmi-handler.c
+ create mode 100644 board/aspeed/ast2600_intel/ipmi-handler.h
+
+diff --git a/board/aspeed/ast2600_intel/Makefile b/board/aspeed/ast2600_intel/Makefile
+index d049922719f3..a0587323afe0 100644
+--- a/board/aspeed/ast2600_intel/Makefile
++++ b/board/aspeed/ast2600_intel/Makefile
+@@ -3,3 +3,4 @@ obj-y += ast-espi.o
+ obj-y += ast-irq.o
+ obj-y += ast-timer.o
+ obj-y += ast-kcs.o
++obj-y += ipmi-handler.o
+diff --git a/board/aspeed/ast2600_intel/ast-kcs.c b/board/aspeed/ast2600_intel/ast-kcs.c
+index a03b7e725370..3889cd9222a4 100644
+--- a/board/aspeed/ast2600_intel/ast-kcs.c
++++ b/board/aspeed/ast2600_intel/ast-kcs.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ // Copyright (c) 2018-2020 Intel Corporation
+
+-#include "ast-kcs.h"
++#include "ipmi-handler.h"
+
+ #ifdef DEBUG_KCS_ENABLED
+ #define DBG_KCS printf
+@@ -9,11 +9,6 @@
+ #define DBG_KCS(...)
+ #endif
+
+-/* TODO: Move to IPMI file. */
+-#define IPMI_CC_OK 0x00
+-#define IPMI_CC_INVALID 0xC1
+-#define IPMI_CC_UNSPECIFIED 0xFF
+-
+ #define KCS_CHANNEL_NO_3 3
+
+ static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 };
+@@ -103,6 +98,7 @@ static void init_kcs_packet(u16 channel_num)
+ static void process_kcs_request(u16 channel_num)
+ {
+ struct kcs_packet *kcs_pkt = NULL;
++ struct ipmi_cmd_data ipmi_data;
+ int i;
+
+ kcs_pkt = get_kcs_packet(channel_num);
+@@ -117,37 +113,49 @@ static void process_kcs_request(u16 channel_num)
+ DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]);
+ DBG_KCS("\n");
+ #endif
++ u8 req_lun = kcs_pkt->data_in[0] & 0x03; /* LUN[1:0] */
++ ipmi_data.net_fun = (kcs_pkt->data_in[0] >> 2); /* netfn[7:2] */
++ ipmi_data.cmd = kcs_pkt->data_in[1]; /* cmd */
++ /* We support only BMC LUN 00h */
++ if (req_lun != LUN_BMC) {
++ kcs_pkt->data_out[0] =
++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_INVALID_CMD_LUN; /* CC code */
++ kcs_pkt->data_out_len = 3;
++ goto done;
++ }
+
+- /*
+- * TODO: Move it to IPMI Command Handler
+- * Below code is added for timebeing till
+- * we implement the IPMI command handler.
+- */
+- kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */
+- kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */
+- kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */
+-
+- if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
+- (kcs_pkt->data_in[1] == 0x01)) {
+- /* Get Device ID */
+- u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02,
+- 0xBF, 0x57, 0x01, 0x00, 0x7B,
+- 0x00, 0x00, 0x00, 0x00, 0x00 };
+- for (i = 0; i < 15; i++)
+- kcs_pkt->data_out[i + 3] = device_id[i];
+- kcs_pkt->data_out_len = 18;
+- } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) &&
+- (kcs_pkt->data_in[1] == 0x04)) {
+- /* Get Self Test Results */
+- kcs_pkt->data_out[3] = 0x56;
+- kcs_pkt->data_out[4] = 0x00;
+- kcs_pkt->data_out_len = 5;
+- } else {
+- kcs_pkt->data_out[2] =
+- IPMI_CC_INVALID; /* Invalid or not supported. */
++ /* Boundary check */
++ if ((kcs_pkt->data_in_idx - 2) > sizeof(ipmi_data.req_data)) {
++ kcs_pkt->data_out[0] =
++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */
++ kcs_pkt->data_out[2] = IPMI_CC_OUT_OF_SPACE; /* CC code */
+ kcs_pkt->data_out_len = 3;
++ goto done;
+ }
+- /* END: TODO */
++ /* Fill in IPMI request data */
++ ipmi_data.req_len = kcs_pkt->data_in_idx - 2;
++ for (i = 0; i < kcs_pkt->data_in_idx - 2; i++)
++ ipmi_data.req_data[i] = kcs_pkt->data_in[i + 2];
++
++ /* Call IPMI command handler */
++ ipmi_cmd_handler(&ipmi_data);
++
++ /* Get IPMI response and fill KCS out data */
++ /* First 2 bytes in KCS response are netFn, Cmd */
++ kcs_pkt->data_out[0] = GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun);
++ kcs_pkt->data_out[1] = ipmi_data.cmd;
++ if ((ipmi_data.res_len + 2) > sizeof(kcs_pkt->data_out)) {
++ kcs_pkt->data_out[2] = IPMI_CC_UNSPECIFIED; /* CC code */
++ kcs_pkt->data_out_len = 3;
++ goto done;
++ }
++ for (i = 0; i < ipmi_data.res_len; i++)
++ kcs_pkt->data_out[i + 2] = ipmi_data.res_data[i];
++
++ kcs_pkt->data_out_len = ipmi_data.res_len + 2;
+
+ #ifdef DEBUG_KCS_ENABLED
+ DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len);
+@@ -156,6 +164,7 @@ static void process_kcs_request(u16 channel_num)
+ DBG_KCS("\n");
+ #endif
+
++done:
+ kcs_pkt->phase = KCS_PHASE_READ;
+ write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]);
+ kcs_pkt->read_req_done = false;
+diff --git a/board/aspeed/ast2600_intel/ipmi-handler.c b/board/aspeed/ast2600_intel/ipmi-handler.c
+new file mode 100644
+index 000000000000..04732846ac28
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ipmi-handler.c
+@@ -0,0 +1,117 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020 Intel Corporation
++
++#include "ipmi-handler.h"
++
++/* IPMI network function codes */
++#define NETFN_APP 0x06
++
++/* IPMI command codes */
++#define CMD_GET_DEV_ID 0x01
++#define CMD_GET_SELF_TEST_RESULTS 0x04
++
++typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res);
++
++struct get_dev_id {
++ u8 completion_code;
++ u8 dev_id;
++ u8 dev_rev;
++ u8 fw_rev1;
++ u8 fw_rev2;
++ u8 ipmi_ver;
++ u8 dev_support;
++ u8 mfg_id[3];
++ u8 product_id[2];
++ u8 aux_fw_rev[4];
++};
++struct self_test_res {
++ u8 completion_code;
++ u8 res_byte[2];
++};
++
++struct ipmi_cmd_table {
++ u8 net_fun;
++ u8 cmd;
++ fun_handler process_cmd;
++};
++
++static u16 get_device_id(u8 *req, u16 req_len, u8 *res)
++{
++ /* Get Device ID */
++ bool operation = 1; /* Firmware operation */
++ u8 intel_mfg_id[3] = { 0x57, 0x01, 0x00 };
++ u8 platform_id[2] = { 0x7B, 0x00 };
++ u8 aux_fw_rev[4] = { 0x00, 0x00, 0x00, 0x00 };
++ struct get_dev_id *result = (struct get_dev_id *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ result->dev_id = 0x23;
++ result->dev_rev = 0x00; /* Not provides dev SDR */
++
++ result->ipmi_ver = 0x02; /* IPMI 2.0 */
++ result->dev_support = 0x00; /* No dev support in this mode */
++ memcpy(result->mfg_id, intel_mfg_id, sizeof(result->mfg_id));
++ memcpy(result->aux_fw_rev, aux_fw_rev, sizeof(result->aux_fw_rev));
++
++ /* TODO: Get Firmware version from flash(PFM Header) */
++ result->fw_rev1 = ((operation << 7) | (0x02 & 0x7F));
++ result->fw_rev2 = 0x03;
++ /* TODO: Read Platform ID from GPIO */
++ memcpy(result->product_id, platform_id, sizeof(result->product_id));
++
++ return sizeof(struct get_dev_id);
++}
++
++static u16 get_self_test_result(u8 *req, u16 req_len, u8 *res)
++{
++ /* Get Self Test Results */
++ struct self_test_res *result = (struct self_test_res *)res;
++
++ if (req_len != 0) {
++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH;
++ return sizeof(result->completion_code);
++ }
++
++ result->completion_code = IPMI_CC_OK;
++ result->res_byte[0] = 0x56; /* Self test function not implemented. */
++ result->res_byte[1] = 0x00;
++
++ return sizeof(struct self_test_res);
++}
++
++const struct ipmi_cmd_table cmd_info[] = {
++ { NETFN_APP, CMD_GET_DEV_ID, get_device_id },
++ { NETFN_APP, CMD_GET_SELF_TEST_RESULTS, get_self_test_result }
++};
++
++#define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info)
++
++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data)
++{
++ int i = 0;
++ for (i = 0; i < CMD_TABLE_SIZE; i++) {
++ if ((cmd_info[i].net_fun == ipmi_data->net_fun) &&
++ (cmd_info[i].cmd == ipmi_data->cmd)) {
++ break;
++ }
++ }
++
++ if (i == CMD_TABLE_SIZE) {
++ /* Invalid or not supported. */
++ ipmi_data->res_data[0] = IPMI_CC_INVALID_CMD;
++ ipmi_data->res_len = 1;
++ return;
++ }
++
++ /* Call the appropriate function handler */
++ ipmi_data->res_len =
++ cmd_info[i].process_cmd(ipmi_data->req_data, ipmi_data->req_len,
++ &ipmi_data->res_data[0]);
++
++ return;
++}
+diff --git a/board/aspeed/ast2600_intel/ipmi-handler.h b/board/aspeed/ast2600_intel/ipmi-handler.h
+new file mode 100644
+index 000000000000..11a2e91fe2c2
+--- /dev/null
++++ b/board/aspeed/ast2600_intel/ipmi-handler.h
+@@ -0,0 +1,39 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018-2020 Intel Corporation */
++
++#include "ast-kcs.h"
++
++/* IPMI completion codes */
++#define IPMI_CC_OK 0x00
++#define IPMI_CC_NODE_BUSY 0xC0
++#define IPMI_CC_INVALID_CMD 0xC1
++#define IPMI_CC_INVALID_CMD_LUN 0xC2
++#define IPMI_CC_OUT_OF_SPACE 0xC4
++#define IPMI_CC_INVALID_DATA_LENGTH 0xC7
++#define IPMI_CC_INVALID_DATA_FIELD 0xCC
++#define IPMI_CC_UNSPECIFIED 0xFF
++
++/* BMC IPMB LUNs */
++#define LUN_BMC 0x00
++#define LUN_OEM1 0x01
++#define LUN_SMS 0x02
++#define LUN_OEM2 0x01
++
++
++#define MAX_IPMI_REQ_DATA_SIZE MAX_KCS_PKT_SIZE
++#define MAX_IPMI_RES_DATA_SIZE 64
++
++/* Response netFn[7:2], Lun[1:0] */
++#define GET_RESP_NETFN_LUN(lun, netfn) \
++ ((lun & 0x03) | (((netfn + 1) << 2) & 0xFD))
++
++struct ipmi_cmd_data {
++ u8 net_fun;
++ u8 cmd;
++ u16 req_len;
++ u16 res_len;
++ u8 req_data[MAX_IPMI_REQ_DATA_SIZE];
++ u8 res_data[MAX_IPMI_RES_DATA_SIZE];
++};
++
++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0013-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0013-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch
new file mode 100644
index 000000000..7d7b450a8
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0013-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch
@@ -0,0 +1,58 @@
+From 2d0a3aff4c4aa3a764958579ed10a3aab43a7d8a Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 27 Apr 2020 12:40:01 -0700
+Subject: [PATCH] Add a workaround to cover UART interrupt bug in AST2600 A0
+
+This commit adds a workaround to cover UART interrupt bug in
+AST2600 A0 revision. It makes infinite reading on the UART +0x7c
+register for clearing abnormal interrupts in every milli-second.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/intel.c | 22 +++++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index 6ac24beb930b..ad5ab7632447 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -221,7 +221,19 @@ void enable_onboard_tpm(void)
+
+ static void timer_callback(void *cookie)
+ {
+- debug("+");
++ uint timer_nr = (uint)cookie;
++ u32 dummy;
++
++ switch (timer_nr) {
++ case 0:
++ /* WA for UART interrupt bug in A0 */
++ dummy = readl(0x1e78307c);
++ dummy = readl(0x1e78407c);
++ dummy = readl(0x1e78d07c);
++ dummy = readl(0x1e78e07c);
++ dummy = readl(0x1e78f07c);
++ break;
++ }
+ }
+
+ int board_early_init_f(void)
+@@ -256,9 +268,13 @@ extern void timer_enable(int n, u32 interval_us, interrupt_handler_t *handler,
+ void *cookie);
+ int board_late_init(void)
+ {
+-#define ONE_SEC_IN_USEC 1000000
++#define SCU_014 0x014 /* Silicon Revision ID */
++#define REV_ID_AST2600A0 0x05000303 /* AST2600 A0 */
++#define ONE_MSEC_IN_USEC 1000
++
++ if (readl(SCU_BASE | SCU_014) == REV_ID_AST2600A0)
++ timer_enable(0, ONE_MSEC_IN_USEC, timer_callback, (void *)0);
+
+- timer_enable(0, ONE_SEC_IN_USEC, timer_callback, (void *)0);
+ espi_init();
+
+ if (read_ffuj())
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0014-Add-a-workaround-to-cover-eSPI-OOB-free-bug-in-AST26.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0014-Add-a-workaround-to-cover-eSPI-OOB-free-bug-in-AST26.patch
new file mode 100644
index 000000000..0a8333e7d
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0014-Add-a-workaround-to-cover-eSPI-OOB-free-bug-in-AST26.patch
@@ -0,0 +1,138 @@
+From 40ab08221b6f8d67d154d8f91b8e55a11d412120 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 27 Apr 2020 17:05:09 -0700
+Subject: [PATCH] Add a workaround to cover eSPI OOB free bug in AST2600 A0
+
+This commit adds a workaround to cover eSPI OOB free bug in AST2600
+A0 revision. It enables GPIO W7 interrupt to catch eSPI reset signal
+and it sets when the reset signal is deasserted to manually set the
+OOB free bit in eSPI protocol.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ board/aspeed/ast2600_intel/ast-espi.c | 79 ++++++++++++++++++++++++++---------
+ 1 file changed, 59 insertions(+), 20 deletions(-)
+
+diff --git a/board/aspeed/ast2600_intel/ast-espi.c b/board/aspeed/ast2600_intel/ast-espi.c
+index 1d7ae529612d..a8b389f159ef 100644
+--- a/board/aspeed/ast2600_intel/ast-espi.c
++++ b/board/aspeed/ast2600_intel/ast-espi.c
+@@ -88,6 +88,7 @@
+ #define AST_ESPI_OOB_CHRDY BIT(4)
+ #define AST_ESPI_FLASH_SW_CHRDY BIT(7)
+ #define AST_ESPI_FLASH_SW_READ BIT(10)
++#define AST_ESPI_SW_RESET GENMASK(31, 24)
+
+ /* ESPI00C bits (Interrupt Enable) */
+ #define AST_ESPI_IEN_HW_RST BIT(31)
+@@ -122,6 +123,7 @@
+ /* LPC chip ID */
+ #define SCR0SIO 0x170
+ #define IRQ_SRC_ESPI 74 /* IRQ 74 */
++#define IRQ_SRC_GPIO 72 /* IRQ 72 */
+
+ static void espi_handshake_ack(void)
+ {
+@@ -205,9 +207,9 @@ static void espi_irq_handler(void *cookie)
+ }
+
+ if (irq_status & AST_ESPI_HW_RST) {
+- uint32_t v = readl(AST_ESPI_BASE + ESPI000) & 0x00ffffffff;
+- writel(v, AST_ESPI_BASE + ESPI000);
+- v |= 0xff000000;
++ uint32_t v;
++
++ v = readl(AST_ESPI_BASE + ESPI000) | AST_ESPI_OOB_CHRDY;
+ writel(v, AST_ESPI_BASE + ESPI000);
+
+ DBG_ESPI("HW_RESET\n");
+@@ -228,6 +230,56 @@ static void espi_irq_handler(void *cookie)
+ readl(AST_ESPI_BASE + ESPI12C), irq_status);
+ }
+
++static void espi_configure_irq(void)
++{
++ writel(0, AST_ESPI_BASE + ESPI110);
++ writel(0, AST_ESPI_BASE + ESPI114);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
++ AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI118);
++ writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
++ AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI094);
++
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE + ESPI120); /* int type 0 susp warn */
++ writel(0, AST_ESPI_BASE + ESPI124);
++ writel(0, AST_ESPI_BASE + ESPI128);
++ writel(AST_ESPI_SUS_WARN,
++ AST_ESPI_BASE +
++ ESPI100); /* Enable sysev1 ints for susp warn */
++
++ writel(AST_ESPI_IEN_HW_RST | AST_ESPI_IEN_SYS1_EV |
++ AST_ESPI_IEN_SYS_EV, AST_ESPI_BASE + ESPI00C);
++}
++
++#define AST_GPIO_BASE 0x1e780000
++#define GPIO_148 0x148 /* GPIO U/V/W/X Interrupt Enable */
++#define GPIO_W7 BIT(23)
++#define GPIO_14C 0x14c /* GPIO U/V/W/X Sensitivity Type 0 */
++#define GPIO_150 0x150 /* GPIO U/V/W/X Sensitivity Type 1 */
++#define GPIO_154 0x154 /* GPIO U/V/W/X Sensitivity Type 2 */
++#define GPIO_158 0x158 /* GPIO U/V/W/X Interrupt Status */
++
++static void espi_reset_handler(void *cookie)
++{
++ if (readl(AST_GPIO_BASE + GPIO_158) & GPIO_W7) {
++ uint32_t v;
++
++ writel(GPIO_W7, AST_GPIO_BASE + GPIO_158);
++
++ v = readl(AST_ESPI_BASE + ESPI000) & ~AST_ESPI_SW_RESET;
++ writel(v, AST_ESPI_BASE + ESPI000);
++ v |= AST_ESPI_SW_RESET;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ v = readl(AST_ESPI_BASE + ESPI000) & ~AST_ESPI_OOB_CHRDY;
++ writel(v, AST_ESPI_BASE + ESPI000);
++
++ espi_configure_irq();
++
++ DBG_ESPI("eSPI Reset\n");
++ }
++}
++
+ void espi_init(void)
+ {
+ if (~readl(AST_SCU_BASE + AST_SCU_HW_STRAP2) &
+@@ -266,25 +318,12 @@ void espi_init(void)
+ AST_ESPI_AUTO_ACK_SUS_WARN);
+ writel(v, AST_ESPI_BASE + ESPI080); /* Disable auto H/W ack */
+
+- writel(0, AST_ESPI_BASE + ESPI110);
+- writel(0, AST_ESPI_BASE + ESPI114);
+- writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
+- AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI118);
+- writel(AST_ESPI_HOST_RST_WARN | AST_ESPI_OOB_RST_WARN |
+- AST_ESPI_PLTRSTN, AST_ESPI_BASE + ESPI094);
+-
+- writel(AST_ESPI_SUS_WARN,
+- AST_ESPI_BASE + ESPI120); /* int type 0 susp warn */
+- writel(0, AST_ESPI_BASE + ESPI124);
+- writel(0, AST_ESPI_BASE + ESPI128);
+- writel(AST_ESPI_SUS_WARN,
+- AST_ESPI_BASE +
+- ESPI100); /* Enable sysev1 ints for susp warn */
+-
+- writel(AST_ESPI_IEN_HW_RST | AST_ESPI_IEN_SYS1_EV |
+- AST_ESPI_IEN_SYS_EV, AST_ESPI_BASE + ESPI00C);
++ espi_configure_irq();
+
+ irq_install_handler(IRQ_SRC_ESPI, espi_irq_handler, NULL);
++
++ irq_install_handler(IRQ_SRC_GPIO, espi_reset_handler, NULL);
++ writel(GPIO_W7, AST_GPIO_BASE + GPIO_148);
+ } else {
+ DBG_ESPI("No espi strap\n");
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0021-AST2600-Enable-host-searial-port-clock-configuration.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0021-AST2600-Enable-host-searial-port-clock-configuration.patch
new file mode 100644
index 000000000..915b0197f
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0021-AST2600-Enable-host-searial-port-clock-configuration.patch
@@ -0,0 +1,71 @@
+From c2e2496dfd8cde56e32274b11968185a77f40736 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 10 Dec 2019 14:58:10 +0800
+Subject: [PATCH] AST2600: Enable host searial port clock configuration in
+ u-boot
+
+In u-boot could read env variable "hostsearialcfg" and set the corresponding
+clock for host searail port.
+
+Tested:
+setenv hostsearialcfg 1, speed is set to 192Mhz (baud rate 921600)
+other value, speed is set to 24Mhz(baud rate 115200)
+by default is 24Mhz.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ board/aspeed/ast2600_intel/intel.c | 35 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index a02e246d0d81..eb9b3959625e 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -36,9 +36,44 @@ int gpio_abort(void)
+ }
+
+ #define SCU_BASE 0x1E6E2000
++#define SCU_338 0x338 //Generate UART 24 MHz Reference from UXCLK
++#define SCU_33C 0x33c //Generate UART 24 MHz Reference from HUXCLK
++#define SCU_338_R_VALUE_192MHZ 0x8e
++#define SCU_338_N_VALUE_192MHZ 0x3c3
++#define SCU_338_R_VALUE_24MHZ 0x06
++#define SCU_338_N_VALUE_24MHZ 0x145
++#define HOST_SERIAL_HIGH_SPEED_192MHZ 1
++#define R_VALUE_BITS 8
++#define V_VALUE_BITS 10
++#define R_V_VALUE_MASK (1 << (R_VALUE_BITS + V_VALUE_BITS))
++
+ int misc_init_r(void)
+ {
+ /* This is called near the end of the _r init sequence */
++ /* By default host serail is set 24Mhz */
++ uint32_t host_serial_cfg = 0;
++ char *host_serial_cfg_txt = NULL;
++
++ /* Config the uart clock source based on environment configuration */
++ host_serial_cfg_txt = env_get("hostserialcfg");
++
++ if (host_serial_cfg_txt != NULL)
++ host_serial_cfg = simple_strtoul(host_serial_cfg_txt, NULL, 16);
++
++ if (host_serial_cfg > HOST_SERIAL_HIGH_SPEED_192MHZ || host_serial_cfg < 0) {
++ printf("Invalid hostserialcfg %x, 24Mhz is set by default!\n", host_serial_cfg);
++ host_serial_cfg = 0;
++ }
++
++ if (host_serial_cfg & HOST_SERIAL_HIGH_SPEED_192MHZ) {
++ writel((readl(SCU_BASE | SCU_338) & R_V_VALUE_MASK) |
++ (SCU_338_N_VALUE_192MHZ << R_VALUE_BITS) | SCU_338_R_VALUE_192MHZ,
++ SCU_BASE | SCU_338);
++ } else {
++ writel((readl(SCU_BASE | SCU_338) & R_V_VALUE_MASK) |
++ (SCU_338_N_VALUE_24MHZ << R_VALUE_BITS) | SCU_338_R_VALUE_24MHZ,
++ SCU_BASE | SCU_338);
++ }
+
+ return 0;
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch
new file mode 100644
index 000000000..3d9d50c8d
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch
@@ -0,0 +1,35 @@
+From 948a92b3000120f902292b661a544e35d796784a Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Mon, 13 Apr 2020 09:30:14 +0800
+Subject: [PATCH] PFR u-boot env changes as per PFR BMC image
+
+u-boot env changes as per PFR BMC flash layout.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ include/configs/aspeed-common.h | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/include/configs/aspeed-common.h b/include/configs/aspeed-common.h
+index 6065ec58db..b13dbd02f3 100644
+--- a/include/configs/aspeed-common.h
++++ b/include/configs/aspeed-common.h
+@@ -64,9 +64,11 @@
+ #define CONFIG_ENV_SIZE 0x10000
+ #endif
+
+-#ifndef CONFIG_ENV_OFFSET
+-#define CONFIG_ENV_OFFSET 0x2400000
+-#endif
++#undef CONFIG_BOOTCOMMAND
++#define CONFIG_BOOTCOMMAND "bootm 20b00000"
++
++#undef CONFIG_ENV_OFFSET
++#define CONFIG_ENV_OFFSET 0xa0000
+
+ #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+ #define CONFIG_ENV_OVERWRITE
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/intel.cfg b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/intel.cfg
new file mode 100644
index 000000000..ceaf62800
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/intel.cfg
@@ -0,0 +1,27 @@
+CONFIG_MISC_INIT_R=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_TARGET_AST2600_INTEL=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_USE_IRQ=y
+CONFIG_CMD_IRQ=y
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x2400000
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_TARGET_EVB_AST2600A1=n
+CONFIG_PHY_NCSI=n
+CONFIG_CMD_USB=n
+CONFIG_CMD_EXT4=n
+CONFIG_CMD_EXT4_WRITE=n
+CONFIG_CMD_FAT=n
+CONFIG_CMD_FS_GENERIC=n
+CONFIG_CMD_MTDPARTS=n
+CONFIG_EFI_PARTITION=n
+CONFIG_USB=n
+CONFIG_DM_USB=n
+CONFIG_USB_EHCI_HCD=n
+CONFIG_USB_STORAGE=n \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
new file mode 100644
index 000000000..ae56f11eb
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
@@ -0,0 +1,32 @@
+COMPATIBLE_MACHINE = "intel-ast2600"
+FILESEXTRAPATHS_append_intel-ast2600:= "${THISDIR}/files:"
+
+# the meta-phosphor layer adds this patch, which conflicts
+# with the intel layout for environment
+
+SRC_URI_append_intel-ast2600 = " \
+ file://intel.cfg \
+ file://0001-Add-ast2600-intel-as-a-new-board.patch \
+ file://0021-AST2600-Enable-host-searial-port-clock-configuration.patch \
+ file://0003-ast2600-intel-layout-environment-addr.patch \
+ file://0004-AST2600-Adjust-default-GPIO-settings.patch \
+ file://0005-Ast2600-Enable-interrupt-in-u-boot.patch \
+ file://0006-SPI-Quad-IO-Mode.patch \
+ file://0007-ast2600-Override-OTP-strap-settings.patch \
+ file://0008-AST2600-Add-TPM-pulse-trigger.patch \
+ file://0009-AST2600-Disable-DMA-arbitration-options-on-MAC1-and-.patch \
+ file://0010-Fix-timer-support.patch \
+ file://0011-KCS-driver-support-in-uBoot.patch \
+ file://0012-IPMI-command-handler-implementation-in-uboot.patch \
+ file://0013-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch \
+ file://0014-Add-a-workaround-to-cover-eSPI-OOB-free-bug-in-AST26.patch \
+ "
+
+PFR_SRC_URI = " \
+ file://0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch \
+ "
+SRC_URI_append_intel-ast2600 += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', PFR_SRC_URI, '', d)}"
+
+do_install_append () {
+ install -m 0644 ${WORKDIR}/fw_env.config ${S}/tools/env/fw_env.config
+}
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-fw-utils-aspeed-sdk_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-fw-utils-aspeed-sdk_%.bbappend
new file mode 100644
index 000000000..2e230c2a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/u-boot-fw-utils-aspeed-sdk_%.bbappend
@@ -0,0 +1,18 @@
+COMPATIBLE_MACHINE = "intel-ast2600"
+FILESEXTRAPATHS_append_intel-ast2600:= "${THISDIR}/files:"
+
+SRC_URI_append_intel-ast2600 = " \
+ file://intel.cfg \
+ file://0001-Add-ast2600-intel-as-a-new-board.patch \
+ file://0003-ast2600-intel-layout-environment-addr.patch \
+ "
+PFR_SRC_URI = " \
+ file://0043-AST2600-PFR-u-boot-env-changes-as-per-PFR-BMC-image.patch \
+ "
+SRC_URI_append_intel-ast2600 += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', PFR_SRC_URI, '', d)}"
+
+do_install_append () {
+ install -m 0644 ${WORKDIR}/fw_env.config ${D}${sysconfdir}/fw_env.config
+ install -m 0644 ${WORKDIR}/fw_env.config ${S}/tools/env/fw_env.config
+}
+RDEPENDS_${PN} = "udev-aspeed-mtd-partitions"
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0001-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0001-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch
new file mode 100644
index 000000000..81e742412
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/0001-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch
@@ -0,0 +1,186 @@
+From 0177d25a23d56bca91fa7938d786b709fd7fba3e Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 27 Apr 2020 12:11:06 -0700
+Subject: [PATCH] Add a workaround to cover UART interrupt bug in AST2600 A0
+
+This commit adds a workaround to cover UART interrupt bug in
+AST2600 A0 revision. It makes infinite reading on the UART +0x7c
+register for clearing abnormal interrupts in every milli-second.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 20 ++++++-------
+ drivers/tty/serial/8250/8250_of.c | 63 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 73 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 656053386fe8..91f431e419d9 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -502,8 +502,8 @@
+ };
+
+ uart1: serial@1e783000 {
+- compatible = "ns16550a";
+- reg = <0x1e783000 0x20>;
++ compatible = "aspeed,ast2600-uart";
++ reg = <0x1e783000 0x20>, <0x1e6e2014 0x4>, <0x1e78307c 0x4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+@@ -516,8 +516,8 @@
+ };
+
+ uart5: serial@1e784000 {
+- compatible = "ns16550a";
+- reg = <0x1e784000 0x1000>;
++ compatible = "aspeed,ast2600-uart";
++ reg = <0x1e784000 0x20>, <0x1e6e2014 0x4>, <0x1e78407c 0x4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&syscon ASPEED_CLK_GATE_UART5CLK>;
+@@ -744,8 +744,8 @@
+ };
+
+ uart2: serial@1e78d000 {
+- compatible = "ns16550a";
+- reg = <0x1e78d000 0x20>;
++ compatible = "aspeed,ast2600-uart";
++ reg = <0x1e78d000 0x20>, <0x1e6e2014 0x4>, <0x1e78d07c 0x4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+@@ -758,8 +758,8 @@
+ };
+
+ uart3: serial@1e78e000 {
+- compatible = "ns16550a";
+- reg = <0x1e78e000 0x20>;
++ compatible = "aspeed,ast2600-uart";
++ reg = <0x1e78e000 0x20>, <0x1e6e2014 0x4>, <0x1e78e07c 0x4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+@@ -772,8 +772,8 @@
+ };
+
+ uart4: serial@1e78f000 {
+- compatible = "ns16550a";
+- reg = <0x1e78f000 0x20>;
++ compatible = "aspeed,ast2600-uart";
++ reg = <0x1e78f000 0x20>, <0x1e6e2014 0x4>, <0x1e78f07c 0x4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
+index 9ba31701a372..53850f859424 100644
+--- a/drivers/tty/serial/8250/8250_of.c
++++ b/drivers/tty/serial/8250/8250_of.c
+@@ -16,6 +16,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/clk.h>
+ #include <linux/reset.h>
++#include <linux/workqueue.h>
+
+ #include "8250.h"
+
+@@ -24,6 +25,9 @@ struct of_serial_info {
+ struct reset_control *rst;
+ int type;
+ int line;
++ struct workqueue_struct *work_queue;
++ struct delayed_work work_handler;
++ void __iomem *wa_base;
+ };
+
+ #ifdef CONFIG_ARCH_TEGRA
+@@ -202,6 +206,18 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
+ return ret;
+ }
+
++#define WA_DELAY_JIFFIES msecs_to_jiffies(1)
++static void clear_abnormal_int_flags(struct work_struct *work)
++{
++ struct delayed_work *dwork = to_delayed_work(work);
++ struct of_serial_info *info = container_of(dwork, struct of_serial_info,
++ work_handler);
++
++ (void) readl(info->wa_base);
++ queue_delayed_work(info->work_queue, &info->work_handler,
++ WA_DELAY_JIFFIES);
++}
++
+ /*
+ * Try to register a serial port
+ */
+@@ -250,6 +266,47 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
+ if (ret < 0)
+ goto err_dispose;
+
++ if (of_device_is_compatible(ofdev->dev.of_node,
++ "aspeed,ast2600-uart")) {
++ #define REV_ID_AST2600A0 0x05000303
++ void __iomem *chip_id_base;
++ struct resource *res = platform_get_resource(ofdev,
++ IORESOURCE_MEM, 1);
++
++ if (!res || resource_size(res) < 2)
++ goto skip_wa;
++
++ info->wa_base = devm_platform_ioremap_resource(ofdev, 2);
++ if (IS_ERR(info->wa_base))
++ goto skip_wa;
++
++ chip_id_base = devm_ioremap_resource(&ofdev->dev, res);
++ if (IS_ERR(chip_id_base))
++ goto skip_wa;
++
++ if (readl(chip_id_base) == REV_ID_AST2600A0) {
++ info->work_queue = alloc_ordered_workqueue(ofdev->name,
++ 0);
++ if (info->work_queue) {
++ INIT_DELAYED_WORK(&info->work_handler,
++ clear_abnormal_int_flags);
++ queue_delayed_work(info->work_queue,
++ &info->work_handler,
++ WA_DELAY_JIFFIES);
++ dev_info(&ofdev->dev,
++ "AST2600 A0 WA initiated\n");
++ } else {
++ dev_err(&ofdev->dev,
++ "Can't enable AST2600 A0 UART WA\n");
++ }
++ }
++
++ devm_iounmap(&ofdev->dev, chip_id_base);
++ devm_release_mem_region(&ofdev->dev, res->start,
++ resource_size(res));
++ }
++
++skip_wa:
+ info->type = port_type;
+ info->line = ret;
+ platform_set_drvdata(ofdev, info);
+@@ -271,6 +328,11 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
+ {
+ struct of_serial_info *info = platform_get_drvdata(ofdev);
+
++ if (info->work_queue) {
++ cancel_delayed_work_sync(&info->work_handler);
++ destroy_workqueue(info->work_queue);
++ }
++
+ serial8250_unregister_port(info->line);
+
+ reset_control_assert(info->rst);
+@@ -341,6 +403,7 @@ static const struct of_device_id of_platform_serial_table[] = {
+ .data = (void *)PORT_XSCALE, },
+ { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
+ { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
++ { .compatible = "aspeed,ast2600-uart", .data = (void *)PORT_16550A, },
+ { /* end of list */ },
+ };
+ MODULE_DEVICE_TABLE(of, of_platform_serial_table);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/intel-ast2600.cfg b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/intel-ast2600.cfg
new file mode 100644
index 000000000..7992be527
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed/intel-ast2600.cfg
@@ -0,0 +1,21 @@
+CONFIG_SENSORS_ASPEED=n
+CONFIG_SENSORS_ASPEED_G6=y
+CONFIG_SPI_ASPEED_SMC=y
+CONFIG_SPI_FMC=y
+CONFIG_I3C=y
+CONFIG_DW_I3C_MASTER=y
+CONFIG_ASPEED_I3C_GLOBAL=y
+CONFIG_I3CDEV=y
+CONFIG_JTAG_ASPEED=n
+CONFIG_U_SERIAL_CONSOLE=n
+CONFIG_KERNEL_LZO=y
+CONFIG_HIGHMEM=n
+CONFIG_I2C_SLAVE_MQUEUE=y
+CONFIG_PINCTRL_ASPEED_G6=y
+CONFIG_DEBUG_LL=n
+CONFIG_DEBUG_LL_UART_8250=n
+CONFIG_EARLY_PRINTK=n
+CONFIG_LOG_BUF_SHIFT=21
+CONFIG_DEBUG_PINCTRL=n
+CONFIG_SUSPEND=n
+CONFIG_ASPEED_MCTP=y
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed_%.bbappend
new file mode 100644
index 000000000..07cafe94e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -0,0 +1,7 @@
+COMPATIBLE_MACHINE = "intel-ast2600"
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://intel-ast2600.cfg \
+ file://0001-Add-a-workaround-to-cover-UART-interrupt-bug-in-AST2.patch \
+ "
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json
new file mode 100644
index 000000000..dd1c4d21a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/AC-Baseboard.json
@@ -0,0 +1,2055 @@
+{
+ "Exposes": [
+ {
+ "Index": 0,
+ "Name": "A_P12V_PSU_SCALED",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P5V",
+ "PowerState": "On",
+ "ScaleFactor": 0.2698,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 5.525
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 5.365
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 4.645
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 4.506
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 4,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_AUX",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 7,
+ "BridgeGPIO": [
+ {
+ "Name": "A_P3V_BAT_SCALED_EN",
+ "Polarity": "High"
+ }
+ ],
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 8,
+ "Name": "PVCCIN_CPU0",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 9,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 10,
+ "Name": "PVCCINFAON_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 11,
+ "Name": "PVCCINFAON_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 12,
+ "Name": "PVCCFA_EHV_FIVRA_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 13,
+ "Name": "PVCCFA_EHV_FIVRA_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 1,
+ "Index": 14,
+ "Name": "PVCCD_HV_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "CPURequired": 2,
+ "Index": 15,
+ "Name": "PVCCD_HV_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "BindConnector": "System Fan connector 1",
+ "Index": 0,
+ "Name": "Fan 1",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 2",
+ "Index": 1,
+ "Name": "Fan 2",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 3",
+ "Index": 2,
+ "Name": "Fan 3",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 4",
+ "Index": 3,
+ "Name": "Fan 4",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 5",
+ "Index": 4,
+ "Name": "Fan 5",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 6",
+ "Index": 5,
+ "Name": "Fan 6",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 7",
+ "Index": 6,
+ "Name": "Fan 7",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 8",
+ "Index": 7,
+ "Name": "Fan 8",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 9",
+ "Index": 8,
+ "Name": "Fan 9",
+ "Type": "AspeedFan"
+ },
+ {
+ "BindConnector": "System Fan connector 10",
+ "Index": 9,
+ "Name": "Fan 10",
+ "Type": "AspeedFan"
+ },
+ {
+ "C1": 92.16,
+ "C2": 107.52,
+ "MaxCFM": 17.5,
+ "Name": "System Airflow",
+ "TachMaxPercent": 100,
+ "TachMinPercent": 20,
+ "Tachs": [
+ "Fan 1",
+ "Fan 2",
+ "Fan 3",
+ "Fan 4",
+ "Fan 5",
+ "Fan 6",
+ "Fan 7",
+ "Fan 8",
+ "Fan 9",
+ "Fan 10"
+ ],
+ "Type": "CFMSensor"
+ },
+ {
+ "AllowedFailures": 1,
+ "Name": "FanRedundancy",
+ "Type": "FanRedundancy"
+ },
+ {
+ "Direction": "Input",
+ "Index": 214,
+ "Name": "SMI Input",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 218,
+ "Name": "ID Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Name": "System Fan connector 1",
+ "Pwm": 0,
+ "Tachs": [
+ 0
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 2",
+ "Pwm": 1,
+ "Tachs": [
+ 1
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 3",
+ "Pwm": 2,
+ "Tachs": [
+ 2
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 4",
+ "Pwm": 3,
+ "Tachs": [
+ 3
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 5",
+ "Pwm": 4,
+ "Tachs": [
+ 4
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 6",
+ "Pwm": 5,
+ "Tachs": [
+ 5
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 7",
+ "Pwm": 12,
+ "Tachs": [
+ 6
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 8",
+ "Pwm": 13,
+ "Tachs": [
+ 7
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 9",
+ "Pwm": 14,
+ "Tachs": [
+ 8
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "System Fan connector 10",
+ "Pwm": 15,
+ "Tachs": [
+ 9
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xC4",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU0 VCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xE0",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU0 PVCCFA_EHV_FIVRA VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xF0",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU0 PVCCD VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xC0",
+ "Class": "MpsBridgeTemp",
+ "Name": "CPU1 PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xE8",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 PVCCFA_EHV_FIVRA VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0F4",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 PVCCD VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 0,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 0,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 0,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 2 Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Address": "0x70",
+ "Bus": 2,
+ "ChannelNames": [
+ "Pcie_Slot_1",
+ "Pcie_Slot_2",
+ "Pcie_Slot_3",
+ "Pcie_Slot_4"
+ ],
+ "Name": "PCIE Mux",
+ "Type": "PCA9546Mux"
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 1"
+ ],
+ "Name": "Fan 1",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 1"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 2"
+ ],
+ "Name": "Fan 2",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 2"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 3"
+ ],
+ "Name": "Fan 3",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 3"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 4"
+ ],
+ "Name": "Fan 4",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 4"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 5"
+ ],
+ "Name": "Fan 5",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 5"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 6"
+ ],
+ "Name": "Fan 6",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 6"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 7"
+ ],
+ "Name": "Fan 7",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 12"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 8"
+ ],
+ "Name": "Fan 8",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 13"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 9"
+ ],
+ "Name": "Fan 9",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 14"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "fan",
+ "FFGainCoefficient": 1.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": 0.0,
+ "ILimitMax": 0.0,
+ "ILimitMin": 0.0,
+ "Inputs": [
+ "Fan 10"
+ ],
+ "Name": "Fan 10",
+ "NegativeHysteresis": 0.0,
+ "OutLimitMax": 100.0,
+ "OutLimitMin": 30.0,
+ "Outputs": [
+ "Pwm 15"
+ ],
+ "PCoefficient": 0.0,
+ "PositiveHysteresis": 0.0,
+ "SlewNeg": 0.0,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "BMC Temp"
+ ],
+ "Name": "BMC Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU0 North VR Temp"
+ ],
+ "Name": "CPU0 North VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU0 South VR Temp"
+ ],
+ "Name": "CPU0 South VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 North VR Temp"
+ ],
+ "Name": "CPU1 North VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 South VR Temp"
+ ],
+ "Name": "CPU1 South VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DIMM [DEF]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM DEF",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 80.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Left Rear Temp"
+ ],
+ "Name": "Left Rear Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "Right Rear Board"
+ ],
+ "Name": "Right Rear Board",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 60.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "SSB Temp"
+ ],
+ "Name": "SSB Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 75.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR Mem ABCD Temp",
+ "CPU1 VR P1V8"
+ ],
+ "Name": "CPU 1 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Left"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR Mem ABCD Temp",
+ "CPU2 VR P1V8"
+ ],
+ "Name": "CPU 2 VR Temp",
+ "NegativeHysteresis": 5.0,
+ "OutLimitMax": 100,
+ "OutLimitMin": 30,
+ "Outputs": [],
+ "PCoefficient": -0.15,
+ "PositiveHysteresis": 0.0,
+ "SetPoint": 85.0,
+ "SlewNeg": -1,
+ "SlewPos": 0.0,
+ "Type": "Pid",
+ "Zones": [
+ "Right",
+ "PSU"
+ ]
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Left",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "Right",
+ "Type": "Pid.Zone"
+ },
+ {
+ "FailSafePercent": 100,
+ "MinThermalOutput": 30,
+ "Name": "PSU",
+ "Type": "Pid.Zone"
+ },
+ {
+ "Class": "Ceiling",
+ "Inputs": [
+ "Front Panel Temp"
+ ],
+ "Name": "Front Panel UCC",
+ "NegativeHysteresis": 2,
+ "Output": [
+ 70.0,
+ 80.0
+ ],
+ "PositiveHysteresis": 0,
+ "Profiles": [
+ "Acoustic"
+ ],
+ "Reading": [
+ 22.0,
+ 32.0
+ ],
+ "Type": "Stepwise",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Class": "Floor",
+ "Inputs": [
+ "Front Panel Temp"
+ ],
+ "Name": "Front Panel LCC",
+ "NegativeHysteresis": 2,
+ "Output": [
+ 50.0,
+ 60.0
+ ],
+ "PositiveHysteresis": 0,
+ "Reading": [
+ 20.0,
+ 30.0
+ ],
+ "Type": "Stepwise",
+ "Zones": [
+ "Left",
+ "Right"
+ ]
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4C",
+ "Bus": 6,
+ "Name": "CPU0 North VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4D",
+ "Bus": 6,
+ "Name": "CPU0 South VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4E",
+ "Bus": 6,
+ "Name": "CPU1 North VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4F",
+ "Bus": 6,
+ "Name": "CPU1 South VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x49",
+ "Bus": 6,
+ "Name": "Right Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x48",
+ "Bus": 6,
+ "Name": "Left Rear Board Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x48",
+ "Bus": 0,
+ "Name": "PCH M.2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4a",
+ "Bus": 6,
+ "Name": "Inlet BRD Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "CPU 1",
+ "PresenceGpio": [
+ {
+ "Name": "CPU1_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU",
+ "UseWA": 1
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": [
+ {
+ "Name": "CPU2_PRESENCE",
+ "Polarity": "Low"
+ }
+ ],
+ "Type": "XeonCPU",
+ "UseWA": 1
+ }
+ ],
+ "Name": "AC Baseboard",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': 'ArcherCity'})"
+ ],
+ "ProductId": 154,
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ },
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag": {
+ "AssetTag": "$PRODUCT_ASSET_TAG"
+ },
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard": {
+ "ProductId": 156
+ },
+ "xyz.openbmc_project.Inventory.Item.System": {}
+}
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json
new file mode 100644
index 000000000..c3615a522
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/FCXXPDBASSMBL_PDB.json
@@ -0,0 +1,91 @@
+[
+ {
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "FCXXPDBASSMBL Fru",
+ "Type": "24C01"
+ },
+ {
+ "Address": "0x18",
+ "Bus": "$bus",
+ "Name": "Multi Node Presence Detector",
+ "Type": "MultiNodePresence"
+ },
+ {
+ "Address": "0x48",
+ "Bus": "$bus",
+ "Name": "PDB $index Temp1",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x49",
+ "Bus": "$bus",
+ "Name": "PDB $index Temp2",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "FCXXPDBASSMBL PDB $index",
+ "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'FCXXPDBASSMBL'})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+ }
+]
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json
new file mode 100644
index 000000000..e55356aba
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/MIDPLANE-2U2X12SWITCH.json
@@ -0,0 +1,53 @@
+[
+ {
+ "Exposes": [
+ {
+ "Address": "$address",
+ "Bus": "$bus",
+ "Name": "Midplane $ADDRESS % 4 + 1 Fru",
+ "Type": "EEPROM"
+ },
+ {
+ "Address": "$ADDRESS % 4 + 0x4E",
+ "Bus": "$bus",
+ "Name": "Midplane $ADDRESS % 4 + 1 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 80
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 75
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ }
+ ],
+ "Name": "Midplane $ADDRESS % 4",
+ "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U2X12SWITCH'})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$BOARD_MANUFACTURER",
+ "Model": "$BOARD_PRODUCT_NAME",
+ "PartNumber": "$BOARD_PART_NUMBER",
+ "SerialNumber": "$BOARD_SERIAL_NUMBER"
+ }
+ }
+]
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json
new file mode 100644
index 000000000..a81329787
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager/OPB2RH-Chassis.json
@@ -0,0 +1,49 @@
+{
+ "Exposes": [
+ {
+ "Address": "0x56",
+ "Bus": 9,
+ "Class": "MCUTemp",
+ "Name": "PDB MCU Temp",
+ "Reg": "0x22",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "MCUTempSensor"
+ }
+ ],
+ "Name": "OPB2RH Chassis",
+ "Probe": [
+ "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'FCXXPDBASSMBL'})"
+ ],
+ "Type": "Chassis",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "Intel Corporation",
+ "Model": "OPB2RH",
+ "PartNumber": "R1234",
+ "SerialNumber": "12345"
+ }
+}
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager_%.bbappend
new file mode 100644
index 000000000..26b41212a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,12 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+SRC_URI_append = " file://AC-Baseboard.json \
+ file://FCXXPDBASSMBL_PDB.json \
+ file://OPB2RH-Chassis.json \
+ file://MIDPLANE-2U2X12SWITCH.json"
+
+RDEPENDS_${PN} += " default-fru"
+
+do_install_append(){
+ install -d ${D}/usr/share/entity-manager/configurations
+ install -m 0444 ${WORKDIR}/*.json ${D}/usr/share/entity-manager/configurations
+}
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/obmc-console.conf b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/obmc-console.conf
new file mode 100644
index 000000000..748a26544
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/obmc-console.conf
@@ -0,0 +1,3 @@
+baud = 115200
+local-tty = ttyS2
+local-tty-baud = 115200
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/sol-option-check.sh b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/sol-option-check.sh
new file mode 100755
index 000000000..ef32fcb9a
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console/sol-option-check.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Copyright 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+if [ $(grep 192000000 /sys/class/tty/ttyS0/uartclk | wc -l) != 0 ]; then
+ echo "hs-uart"
+ sed -i -e 's/115200/921600/g' /etc/obmc-console.conf
+else
+ echo "normal uart"
+ sed -i -e 's/921600/115200/g' /etc/obmc-console.conf
+fi
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console_%.bbappend b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console_%.bbappend
new file mode 100644
index 000000000..dee302fd7
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-phosphor/console/obmc-console_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend_intel-ast2600 := "${THISDIR}/${PN}:"
+OBMC_CONSOLE_HOST_TTY = "ttyS2"
+SRC_URI += "file://sol-option-check.sh"
+
+do_install_append() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/sol-option-check.sh ${D}${bindir}
+}
diff --git a/meta-openbmc-mods/meta-ast2600/recipes.txt b/meta-openbmc-mods/meta-ast2600/recipes.txt
new file mode 100644
index 000000000..2f89155c3
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes.txt
@@ -0,0 +1,3 @@
+recipes-bsp - Anything with links to specific hardware or hardware configuration information
+recipes-kernel - The kernel and generic applications/libraries with strong kernel dependencies
+recipes-phosphor - Phosphor OpenBMC applications and configuration
diff --git a/meta-openbmc-mods/meta-common-small/conf/layer.conf b/meta-openbmc-mods/meta-common-small/conf/layer.conf
new file mode 100644
index 000000000..65569b5b2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/conf/layer.conf
@@ -0,0 +1,11 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "common-small"
+BBFILE_PATTERN_common-small = "^${LAYERDIR}/"
+BBFILE_PRIORITY_common-small = "10"
+LAYERSERIES_COMPAT_common-small = "warrior zeus"
diff --git a/meta-openbmc-mods/meta-common-small/recipes-core/systemd/systemd_%.bbappend b/meta-openbmc-mods/meta-common-small/recipes-core/systemd/systemd_%.bbappend
new file mode 100644
index 000000000..12cb9fd48
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/recipes-core/systemd/systemd_%.bbappend
@@ -0,0 +1,14 @@
+# add some configuration overrides for systemd default /usr/lib/tmpfiles.d/
+
+LICENSE = "GPL-2.0"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+# Disable udev hwdb
+RRECOMMENDS_${PN}_remove += "udev-hwdb"
+PACKAGES_remove += "udev-hwdb"
+
+do_install_append() {
+ rm -rf ${D}${rootlibexecdir}/udev/hwdb.d
+ rm -f ${D}${sysconfdir}/udev/hwdb.bin
+}
diff --git a/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/files/0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/files/0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch
new file mode 100644
index 000000000..deccc47f3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/files/0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch
@@ -0,0 +1,100 @@
+From 2ad1d60c39a2a9a08bcd29188362efba4e92e546 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Tue, 9 Apr 2019 16:18:07 -0700
+Subject: [PATCH] hw/arm/aspeed: Add an intel-ast2500 machine type
+
+Include the HW strap setting and some I2C temperature sensors.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ hw/arm/aspeed.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
+index 6f4d707..5a9d58b 100644
+--- a/hw/arm/aspeed.c
++++ b/hw/arm/aspeed.c
+@@ -64,6 +64,21 @@ struct AspeedBoardState {
+ SCU_HW_STRAP_MAC0_RGMII) & \
+ ~SCU_HW_STRAP_2ND_BOOT_WDT)
+
++/* intel ast2500 hardware value: 0xF3CCC286 */
++#define INTEL_AST2500_BMC_HW_STRAP1 (( \
++ AST2500_HW_STRAP1_DEFAULTS | \
++ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
++ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
++ SCU_AST2500_HW_STRAP_UART_DEBUG | \
++ SCU_AST2500_HW_STRAP_ESPI_ENABLE | \
++ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
++ SCU_HW_STRAP_GPIOE_PT_EN | \
++ SCU_AST2400_HW_STRAP_ACPI_DIS | \
++ SCU_HW_STRAP_CLK_48M_IN | \
++ SCU_HW_STRAP_VGA_CLASS_CODE | \
++ SCU_HW_STRAP_MAC1_RGMII) & \
++ ~SCU_HW_STRAP_2ND_BOOT_WDT)
++
+ /* Romulus hardware value: 0xF10AD206 */
+ #define ROMULUS_BMC_HW_STRAP1 ( \
+ AST2500_HW_STRAP1_DEFAULTS | \
+@@ -396,6 +411,24 @@ static void ast2600_evb_i2c_init(AspeedBoardState *bmc)
+ ast2500_evb_i2c_init(bmc);
+ }
+
++static void intel_ast2500_i2c_init(AspeedBoardState *bmc)
++{
++ AspeedSoCState *soc = &bmc->soc;
++ DeviceState *dev;
++
++ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp421", 0x4d);
++ object_property_set_int(OBJECT(dev), 50000, "temperature0", &error_abort);
++ /* The s2600wf expects a TMP75 but a TMP105 is compatible */
++ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48);
++ object_property_set_int(OBJECT(dev), 50000, "temperature", &error_abort);
++ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49);
++ object_property_set_int(OBJECT(dev), 50000, "temperature", &error_abort);
++ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x4a);
++ object_property_set_int(OBJECT(dev), 50000, "temperature", &error_abort);
++ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x4b);
++ object_property_set_int(OBJECT(dev), 50000, "temperature", &error_abort);
++}
++
+ static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
+ {
+ AspeedSoCState *soc = &bmc->soc;
+@@ -537,6 +570,21 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
+ mc->default_ram_size = 512 * MiB;
+ };
+
++static void aspeed_machine_intel_ast2500_class_init(ObjectClass *oc, void *data)
++{
++ MachineClass *mc = MACHINE_CLASS(oc);
++ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
++
++ mc->desc = "Intel AST2500 BMC (ARM1176)";
++ amc->soc_name = "ast2500-a1";
++ amc->hw_strap1 = INTEL_AST2500_BMC_HW_STRAP1;
++ amc->fmc_model = "n25q512a";
++ amc->spi_model = "n25q512a";
++ amc->num_cs = 1;
++ amc->i2c_init = intel_ast2500_i2c_init;
++ mc->default_ram_size = 512 * MiB;
++};
++
+ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
+ {
+ MachineClass *mc = MACHINE_CLASS(oc);
+@@ -624,6 +672,10 @@ static const TypeInfo aspeed_machine_types[] = {
+ .parent = TYPE_ASPEED_MACHINE,
+ .class_init = aspeed_machine_ast2500_evb_class_init,
+ }, {
++ .name = MACHINE_TYPE_NAME("intel-ast2500"),
++ .parent = TYPE_ASPEED_MACHINE,
++ .class_init = aspeed_machine_intel_ast2500_class_init,
++ }, {
+ .name = MACHINE_TYPE_NAME("romulus-bmc"),
+ .parent = TYPE_ASPEED_MACHINE,
+ .class_init = aspeed_machine_romulus_class_init,
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-native_%.bbappend b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-native_%.bbappend
new file mode 100644
index 000000000..d2855db1b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-native_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+SRC_URI = "git://github.com/openbmc/qemu.git;nobranch=1 \
+ file://0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch"
+
+QEMU_TARGETS = "arm"
+
+S = "${WORKDIR}/git"
+SRCREV = "8ab0db0624b454bd69a04ca0010f165cb7119100"
diff --git a/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-system-native_%.bbappend b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-system-native_%.bbappend
new file mode 100644
index 000000000..f8c8c66c1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu-system-native_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+SRC_URI = "git://github.com/openbmc/qemu.git;nobranch=1 \
+ file://powerpc_rom.bin \
+ file://0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch"
+
+QEMU_TARGETS = "arm"
+
+S = "${WORKDIR}/git"
+SRCREV = "8ab0db0624b454bd69a04ca0010f165cb7119100"
diff --git a/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu_%.bbappend b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu_%.bbappend
new file mode 100644
index 000000000..cfc1a3ace
--- /dev/null
+++ b/meta-openbmc-mods/meta-common-small/recipes-devtools/qemu/qemu_%.bbappend
@@ -0,0 +1,6 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+SRC_URI = "git://github.com/openbmc/qemu.git;nobranch=1 \
+ file://0001-hw-arm-aspeed-Add-an-intel-ast2500-machine-type.patch"
+
+S = "${WORKDIR}/git"
+SRCREV = "8ab0db0624b454bd69a04ca0010f165cb7119100"
diff --git a/meta-openbmc-mods/meta-common/COPYING.MIT b/meta-openbmc-mods/meta-common/COPYING.MIT
new file mode 100644
index 000000000..89de35479
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/COPYING.MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/meta-openbmc-mods/meta-common/README b/meta-openbmc-mods/meta-common/README
new file mode 100644
index 000000000..9d4a8a1e6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/README
@@ -0,0 +1,64 @@
+This README file contains information on the contents of the
+common layer.
+
+Please see the corresponding sections below for details.
+
+
+Dependencies
+============
+
+This layer depends on:
+
+ URI: git://git.openembedded.org/bitbake
+ branch: master
+
+ URI: git://git.openembedded.org/openembedded-core
+ layers: meta
+ branch: master
+
+ URI: git://git.yoctoproject.org/xxxx
+ layers: xxxx
+ branch: master
+
+
+Patches
+=======
+
+Please submit any patches against the common layer to the
+xxxx mailing list (xxxx@zzzz.org) and cc: the maintainer:
+
+Maintainer: XXX YYYYYY <xxx.yyyyyy@zzzzz.com>
+
+
+Table of Contents
+=================
+
+ I. Adding the common layer to your build
+ II. Misc
+
+
+I. Adding the common layer to your build
+=================================================
+
+--- replace with specific instructions for the common layer ---
+
+In order to use this layer, you need to make the build system aware of
+it.
+
+Assuming the common layer exists at the top-level of your
+yocto build tree, you can add it to the build system by adding the
+location of the common layer to bblayers.conf, along with any
+other layers needed. e.g.:
+
+ BBLAYERS ?= " \
+ /path/to/yocto/meta \
+ /path/to/yocto/meta-poky \
+ /path/to/yocto/meta-yocto-bsp \
+ /path/to/yocto/meta-common \
+ "
+
+
+II. Misc
+========
+
+--- replace with specific information about the common layer ---
diff --git a/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass b/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass
new file mode 100644
index 000000000..344dddd3d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/image_types_intel_pfr.bbclass
@@ -0,0 +1,131 @@
+
+
+inherit obmc-phosphor-full-fitimage
+inherit image_types_phosphor_auto
+DEPENDS += "obmc-intel-pfr-image-native python3-native intel-blocksign-native"
+
+require recipes-core/os-release/version-vars.inc
+
+IMAGE_TYPES += "intel-pfr"
+
+IMAGE_TYPEDEP_intel-pfr = "mtd-auto"
+IMAGE_TYPES_MASKED += "intel-pfr"
+
+# PFR images directory
+PFR_IMAGES_DIR = "${DEPLOY_DIR_IMAGE}/pfr_images"
+
+# PFR image generation script directory
+PFR_SCRIPT_DIR = "${STAGING_DIR_NATIVE}${bindir}"
+
+# PFR image config directory
+PFR_CFG_DIR = "${STAGING_DIR_NATIVE}${datadir}/pfrconfig"
+
+# Refer flash map in manifest.json for the addresses offset
+PFM_OFFSET = "0x80000"
+
+# 0x80000/1024 = 0x200 or 512, 1K Page size.
+PFM_OFFSET_PAGE = "512"
+
+# RC_IMAGE
+RC_IMAGE_OFFSET = "0x02a00000"
+
+# RC_IMAGE_PAGE= 0x02a00000/1024 = 0xA800 or 43008
+RC_IMAGE_PAGE = "43008"
+
+do_image_pfr () {
+ bbplain "Generating Intel PFR compliant BMC image"
+
+ bbplain "Build Version = ${build_version}"
+ bbplain "Build Number = ${build_number}"
+ bbplain "Build Hash = ${build_hash}"
+
+ mkdir -p "${PFR_IMAGES_DIR}"
+ cd "${PFR_IMAGES_DIR}"
+
+ # python script that does the creating PFM, BMC compressed and unsigned images from BMC 128MB raw binary file.
+ ${PFR_SCRIPT_DIR}/pfr_image.py ${PFR_CFG_DIR}/pfr_manifest.json ${DEPLOY_DIR_IMAGE}/image-mtd ${build_version} ${build_number} ${build_hash} ${SHA}
+
+ # sign the PFM region
+ ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/pfm_config.xml -o ${PFR_IMAGES_DIR}/pfm_signed.bin ${PFR_IMAGES_DIR}/pfm.bin -v
+
+ # Add the signed PFM to rom image
+ dd bs=1k conv=notrunc seek=${PFM_OFFSET_PAGE} if=${PFR_IMAGES_DIR}/pfm_signed.bin of=${PFR_IMAGES_DIR}/image-mtd-pfr
+
+ # Create unsigned BMC update capsule - append with 1. pfm_signed, 2. pbc, 3. bmc compressed
+ dd if=${PFR_IMAGES_DIR}/pfm_signed.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+
+ dd if=${PFR_IMAGES_DIR}/pbc.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+
+ dd if=${PFR_IMAGES_DIR}/bmc_compressed.bin bs=1k >> ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin
+
+ # Sign the BMC update capsule
+ ${PFR_SCRIPT_DIR}/blocksign -c ${PFR_CFG_DIR}/bmc_config.xml -o ${PFR_IMAGES_DIR}/bmc_signed_cap.bin ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin -v
+
+ # Add the signed bmc update capsule to full rom image @ 0x2a00000
+ dd bs=1k conv=notrunc seek=${RC_IMAGE_PAGE} if=${PFR_IMAGES_DIR}/bmc_signed_cap.bin of=${PFR_IMAGES_DIR}/image-mtd-pfr
+
+ # Append date and time to all the PFR images
+ mv ${PFR_IMAGES_DIR}/pfm_signed.bin ${PFR_IMAGES_DIR}/pfm_signed-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/pfm.bin ${PFR_IMAGES_DIR}/pfm-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/pbc.bin ${PFR_IMAGES_DIR}/pbc-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/bmc_compressed.bin ${PFR_IMAGES_DIR}/bmc_compressed-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/bmc_unsigned_cap.bin ${PFR_IMAGES_DIR}/bmc_unsigned_cap-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/bmc_signed_cap.bin ${PFR_IMAGES_DIR}/bmc_signed_cap-${DATETIME}.bin
+ mv ${PFR_IMAGES_DIR}/image-mtd-pfr ${PFR_IMAGES_DIR}/image-mtd-pfr-${DATETIME}.bin
+
+ # Use relative links. The build process removes some of the build
+ # artifacts and that makes fully qualified pathes break. Relative links
+ # work because of the 'cd "${PFR_IMAGES_DIR}"' at the start of this section.
+ ln -sf image-mtd-pfr-${DATETIME}.bin ${PFR_IMAGES_DIR}/image-mtd-pfr.bin
+ ln -sf bmc_signed_cap-${DATETIME}.bin ${PFR_IMAGES_DIR}/bmc_signed_cap.bin
+}
+
+do_image_pfr[vardepsexclude] += "DATE DATETIME"
+do_image_pfr[vardeps] += "IPMI_MAJOR IPMI_MINOR IPMI_AUX13 IPMI_AUX14 IPMI_AUX15 IPMI_AUX16"
+do_image_pfr[depends] += " \
+ obmc-intel-pfr-image-native:do_populate_sysroot \
+ intel-blocksign-native:do_populate_sysroot \
+ "
+
+python() {
+ product_gen = d.getVar('PRODUCT_GENERATION', True)
+ if product_gen == "wht":
+ d.setVar('SHA', "1")# 1- SHA256
+
+ types = d.getVar('IMAGE_FSTYPES', True).split()
+
+ if 'intel-pfr' in types:
+
+ bld_ver1 = d.getVar('IPMI_MAJOR', True)
+ bld_ver1 = int(bld_ver1) << 8
+
+ bld_ver2 = d.getVar('IPMI_MINOR', True)
+ bld_ver2 = int(bld_ver2)
+
+ bld_ver = bld_ver1 | bld_ver2
+ d.setVar('build_version', str(bld_ver))
+
+ bld_num = d.getVar('IPMI_AUX13', True)
+
+ d.setVar('build_number', bld_num)
+
+ bld_hash1 = d.getVar('IPMI_AUX14', True)
+ bld_hash2 = d.getVar('IPMI_AUX15', True)
+ bld_hash3 = d.getVar('IPMI_AUX16', True)
+
+ bld_hash1 = int(bld_hash1, 16)
+ bld_hash2 = int(bld_hash2, 16)
+ bld_hash3 = int(bld_hash3, 16)
+
+ bld_hash = bld_hash3 << 16
+ bld_hash |= bld_hash2 << 8
+ bld_hash |= bld_hash1
+
+ d.setVar('build_hash', str(bld_hash))
+
+ bb.build.addtask(# task, depends_on_task, task_depends_on, d )
+ 'do_image_pfr',
+ 'do_build',
+ 'do_generate_auto', d)
+}
+
diff --git a/meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass b/meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass
new file mode 100644
index 000000000..f90a19c4b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass
@@ -0,0 +1,79 @@
+# Base image class extension, inlined into every image.
+
+# Phosphor image types
+#
+# New image types based on DTS partition information
+#
+inherit logging
+
+# Image composition
+FLASH_FULL_IMAGE ?= "fitImage-rootfs-${MACHINE}.bin"
+
+IMAGE_BASETYPE ?= "squashfs-xz"
+OVERLAY_BASETYPE ?= "jffs2"
+
+IMAGE_TYPES += "mtd-auto"
+
+IMAGE_TYPEDEP_mtd-auto = "${IMAGE_BASETYPE}"
+IMAGE_TYPES_MASKED += "mtd-auto"
+
+# Flash characteristics in KB unless otherwise noted
+python() {
+ types = d.getVar('IMAGE_FSTYPES', True).split()
+
+ # TODO: find partition list in DTS
+ d.setVar('FLASH_UBOOT_OFFSET', str(0))
+ if 'intel-pfr' in types:
+ d.setVar('FLASH_SIZE', str(128*1024))
+ DTB_FULL_FIT_IMAGE_OFFSETS = [0xb00000]
+ else:
+ d.setVar('FLASH_SIZE', str(64*1024))
+ DTB_FULL_FIT_IMAGE_OFFSETS = [0x80000, 0x2480000]
+
+ d.setVar('FLASH_RUNTIME_OFFSETS', ' '.join(
+ [str(int(x/1024)) for x in DTB_FULL_FIT_IMAGE_OFFSETS]
+ )
+ )
+}
+
+mk_nor_image() {
+ image_dst="$1"
+ image_size_kb=$2
+ dd if=/dev/zero bs=1k count=$image_size_kb \
+ | tr '\000' '\377' > $image_dst
+}
+
+do_generate_auto() {
+ bbdebug 1 "do_generate_auto IMAGE_TYPES=${IMAGE_TYPES} size=${FLASH_SIZE}KB (${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.auto.mtd)"
+ # Assemble the flash image
+ mk_nor_image ${IMGDEPLOYDIR}/${IMAGE_NAME}.auto.mtd ${FLASH_SIZE}
+ dd bs=1k conv=notrunc seek=${FLASH_UBOOT_OFFSET} \
+ if=${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX} \
+ of=${IMGDEPLOYDIR}/${IMAGE_NAME}.auto.mtd
+
+ for OFFSET in ${FLASH_RUNTIME_OFFSETS}; do
+ dd bs=1k conv=notrunc seek=${OFFSET} \
+ if=${DEPLOY_DIR_IMAGE}/${FLASH_FULL_IMAGE} \
+ of=${IMGDEPLOYDIR}/${IMAGE_NAME}.auto.mtd
+ done
+
+ ln ${IMGDEPLOYDIR}/${IMAGE_NAME}.auto.mtd \
+ ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.auto.mtd
+ ln -sf ${IMAGE_NAME}.auto.mtd ${DEPLOY_DIR_IMAGE}/image-mtd
+}
+do_generate_auto[dirs] = "${S}/auto"
+do_generate_auto[depends] += " \
+ ${PN}:do_image_${@d.getVar('IMAGE_BASETYPE', True).replace('-', '_')} \
+ virtual/kernel:do_deploy \
+ u-boot:do_populate_sysroot \
+ "
+
+python() {
+ types = d.getVar('IMAGE_FSTYPES', True).split()
+
+ if 'mtd-auto' in types:
+ bb.build.addtask(# task, depends_on_task, task_depends_on, d )
+ 'do_generate_auto',
+ 'do_build',
+ 'do_image_complete', d)
+}
diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
new file mode 100644
index 000000000..26c895951
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
@@ -0,0 +1,532 @@
+inherit uboot-sign logging
+
+DEPENDS += "u-boot-mkimage-native"
+
+SIGNING_KEY ?= "${STAGING_DIR_NATIVE}${datadir}/OpenBMC.priv"
+INSECURE_KEY = "${@'${SIGNING_KEY}' == '${STAGING_DIR_NATIVE}${datadir}/OpenBMC.priv'}"
+SIGNING_KEY_DEPENDS = "${@oe.utils.conditional('INSECURE_KEY', 'True', 'phosphor-insecure-signing-key-native:do_populate_sysroot', '', d)}"
+
+DEPS = " ${PN}:do_image_${@d.getVar('IMAGE_BASETYPE', True).replace('-', '_')} \
+ virtual/kernel:do_deploy \
+ u-boot:do_populate_sysroot "
+
+# Options for the device tree compiler passed to mkimage '-D' feature:
+UBOOT_MKIMAGE_DTCOPTS ??= ""
+
+#
+# Emit the fitImage ITS header
+#
+# $1 ... .its filename
+fitimage_emit_fit_header() {
+ cat << EOF >> ${1}
+/dts-v1/;
+
+/ {
+ description = "U-Boot fitImage for ${DISTRO_NAME}/${PV}/${MACHINE}";
+ #address-cells = <1>;
+EOF
+}
+
+#
+# Emit the fitImage section bits
+#
+# $1 ... .its filename
+# $2 ... Section bit type: imagestart - image section start
+# confstart - configuration section start
+# sectend - section end
+# fitend - fitimage end
+#
+fitimage_emit_section_maint() {
+ case $2 in
+ imagestart)
+ cat << EOF >> ${1}
+
+ images {
+EOF
+ ;;
+ confstart)
+ cat << EOF >> ${1}
+
+ configurations {
+EOF
+ ;;
+ sectend)
+ cat << EOF >> ${1}
+ };
+EOF
+ ;;
+ fitend)
+ cat << EOF >> ${1}
+};
+EOF
+ ;;
+ esac
+}
+
+#
+# Emit the fitImage ITS kernel section
+#
+# $1 ... .its filename
+# $2 ... Image counter
+# $3 ... Path to kernel image
+# $4 ... Compression type
+# $5 ... Hash type
+fitimage_emit_section_kernel() {
+
+ kernel_csum="${5}"
+
+ if [ -n "${kernel_csum}" ]; then
+ hash_blk=$(cat << EOF
+ hash@1 {
+ algo = "${kernel_csum}";
+ };
+EOF
+ )
+ fi
+
+ ENTRYPOINT=${UBOOT_ENTRYPOINT}
+ if [ -n "${UBOOT_ENTRYSYMBOL}" ]; then
+ ENTRYPOINT=`${HOST_PREFIX}nm vmlinux | \
+ awk '$3=="${UBOOT_ENTRYSYMBOL}" {print "0x"$1;exit}'`
+ fi
+
+ cat << EOF >> ${1}
+ kernel@${2} {
+ description = "Linux kernel";
+ data = /incbin/("${3}");
+ type = "kernel";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "${4}";
+ load = <${UBOOT_LOADADDRESS}>;
+ entry = <${ENTRYPOINT}>;
+ ${hash_blk}
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS DTB section
+#
+# $1 ... .its filename
+# $2 ... Image counter
+# $3 ... Path to DTB image
+# $4 ... Hash type
+fitimage_emit_section_dtb() {
+
+ dtb_csum="${4}"
+ if [ -n "${dtb_csum}" ]; then
+ hash_blk=$(cat << EOF
+ hash@1 {
+ algo = "${dtb_csum}";
+ };
+EOF
+ )
+ fi
+
+ cat << EOF >> ${1}
+ fdt@${2} {
+ description = "Flattened Device Tree blob";
+ data = /incbin/("${3}");
+ type = "flat_dt";
+ arch = "${UBOOT_ARCH}";
+ compression = "none";
+ ${hash_blk}
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS setup section
+#
+# $1 ... .its filename
+# $2 ... Image counter
+# $3 ... Path to setup image
+# $4 ... Hash type
+fitimage_emit_section_setup() {
+
+ setup_csum="${4}"
+ if [ -n "${setup_csum}" ]; then
+ hash_blk=$(cat << EOF
+ hash@1 {
+ algo = "${setup_csum}";
+ };
+EOF
+ )
+ fi
+
+ cat << EOF >> ${1}
+ setup@${2} {
+ description = "Linux setup.bin";
+ data = /incbin/("${3}");
+ type = "x86_setup";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "none";
+ load = <0x00090000>;
+ entry = <0x00090000>;
+ ${hash_blk}
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS ramdisk section
+#
+# $1 ... .its filename
+# $2 ... Image counter
+# $3 ... Path to ramdisk image
+# $4 ... Hash type
+fitimage_emit_section_ramdisk() {
+
+ ramdisk_csum="${4}"
+ if [ -n "${ramdisk_csum}" ]; then
+ hash_blk=$(cat << EOF
+ hash@1 {
+ algo = "${ramdisk_csum}";
+ };
+EOF
+ )
+ fi
+ ramdisk_ctype="none"
+ ramdisk_loadline=""
+ ramdisk_entryline=""
+
+ if [ -n "${UBOOT_RD_LOADADDRESS}" ]; then
+ ramdisk_loadline="load = <${UBOOT_RD_LOADADDRESS}>;"
+ fi
+ if [ -n "${UBOOT_RD_ENTRYPOINT}" ]; then
+ ramdisk_entryline="entry = <${UBOOT_RD_ENTRYPOINT}>;"
+ fi
+
+ case $3 in
+ *.gz)
+ ramdisk_ctype="gzip"
+ ;;
+ *.bz2)
+ ramdisk_ctype="bzip2"
+ ;;
+ *.lzma)
+ ramdisk_ctype="lzma"
+ ;;
+ *.lzo)
+ ramdisk_ctype="lzo"
+ ;;
+ *.lz4)
+ ramdisk_ctype="lz4"
+ ;;
+ esac
+
+ cat << EOF >> ${1}
+ ramdisk@${2} {
+ description = "${INITRAMFS_IMAGE}";
+ data = /incbin/("${3}");
+ type = "ramdisk";
+ arch = "${UBOOT_ARCH}";
+ os = "linux";
+ compression = "${ramdisk_ctype}";
+ ${ramdisk_loadline}
+ ${ramdisk_entryline}
+ ${hash_blk}
+ };
+EOF
+}
+
+#
+# Emit the fitImage ITS configuration section
+#
+# $1 ... .its filename
+# $2 ... Linux kernel ID
+# $3 ... DTB image name
+# $4 ... ramdisk ID
+# $5 ... config ID
+# $6 ... default flag
+# $7 ... Hash type
+fitimage_emit_section_config() {
+
+ conf_csum="${7}"
+ if [ -n "${conf_csum}" ]; then
+ hash_blk=$(cat << EOF
+ hash@1 {
+ algo = "${conf_csum}";
+ };
+EOF
+ )
+ fi
+ if [ -n "${UBOOT_SIGN_ENABLE}" ] ; then
+ conf_sign_keyname="${UBOOT_SIGN_KEYNAME}"
+ fi
+
+ # Test if we have any DTBs at all
+ conf_desc="Linux kernel"
+ kernel_line="kernel = \"kernel@${2}\";"
+ fdt_line=""
+ ramdisk_line=""
+ setup_line=""
+ default_line=""
+
+ if [ -n "${3}" ]; then
+ conf_desc="${conf_desc}, FDT blob"
+ fdt_line="fdt = \"fdt@${3}\";"
+ fi
+
+ if [ -n "${4}" ]; then
+ conf_desc="${conf_desc}, ramdisk"
+ ramdisk_line="ramdisk = \"ramdisk@${4}\";"
+ fi
+
+ if [ -n "${5}" ]; then
+ conf_desc="${conf_desc}, setup"
+ setup_line="setup = \"setup@${5}\";"
+ fi
+
+ if [ "${6}" = "1" ]; then
+ default_line="default = \"conf@${3}\";"
+ fi
+
+ cat << EOF >> ${1}
+ ${default_line}
+ conf@${3} {
+ description = "${6} ${conf_desc}";
+ ${kernel_line}
+ ${fdt_line}
+ ${ramdisk_line}
+ ${setup_line}
+ ${hash_blk}
+EOF
+
+ if [ ! -z "${conf_sign_keyname}" ] ; then
+
+ sign_line="sign-images = \"kernel\""
+
+ if [ -n "${3}" ]; then
+ sign_line="${sign_line}, \"fdt\""
+ fi
+
+ if [ -n "${4}" ]; then
+ sign_line="${sign_line}, \"ramdisk\""
+ fi
+
+ if [ -n "${5}" ]; then
+ sign_line="${sign_line}, \"setup\""
+ fi
+
+ sign_line="${sign_line};"
+
+ cat << EOF >> ${1}
+ signature@1 {
+ algo = "${conf_csum},rsa2048";
+ key-name-hint = "${conf_sign_keyname}";
+ ${sign_line}
+ };
+EOF
+ fi
+
+ cat << EOF >> ${1}
+ };
+EOF
+}
+
+#
+# Assemble fitImage
+#
+# $1 ... .its filename
+# $2 ... fitImage name
+# $3 ... include rootfs
+fitimage_assemble() {
+ kernelcount=1
+ dtbcount=""
+ DTBS=""
+ ramdiskcount=${3}
+ setupcount=""
+ #hash_type="sha256"
+ hash_type=""
+ rm -f ${1} ${2}
+
+ #
+ # Step 0: find the kernel image in the deploy/images/$machine dir
+ #
+ KIMG=""
+ for KTYPE in zImage bzImage vmlinuz; do
+ if [ -e "${DEPLOY_DIR_IMAGE}/${ktype}" ]; then
+ KIMG="${DEPLOY_DIR_IMAGE}/${KTYPE}"
+ break
+ fi
+ done
+ if [ -z "${KIMG}" ]; then
+ bbdebug 1 "Failed to find kernel image to pack into full fitimage"
+ return 1
+ fi
+
+ fitimage_emit_fit_header ${1}
+
+ #
+ # Step 1: Prepare a kernel image section.
+ #
+ fitimage_emit_section_maint ${1} imagestart
+
+ fitimage_emit_section_kernel ${1} "${kernelcount}" "${KIMG}" "none" "${hash_type}"
+
+ #
+ # Step 2: Prepare a DTB image section
+ #
+ if [ -n "${KERNEL_DEVICETREE}" ]; then
+ dtbcount=1
+ for DTB in ${KERNEL_DEVICETREE}; do
+ if echo ${DTB} | grep -q '/dts/'; then
+ bberror "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+ DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+ fi
+ DTB_PATH="${DEPLOY_DIR_IMAGE}/${DTB}"
+ if [ ! -e "${DTB_PATH}" ]; then
+ bbwarn "${DTB_PATH} does not exist"
+ continue
+ fi
+
+ DTB=$(echo "${DTB}" | tr '/' '_')
+ DTBS="${DTBS} ${DTB}"
+ fitimage_emit_section_dtb ${1} ${DTB} ${DTB_PATH} "${hash_type}"
+ done
+ fi
+
+ #
+ # Step 3: Prepare a setup section. (For x86)
+ #
+ if [ -e arch/${ARCH}/boot/setup.bin ]; then
+ setupcount=1
+ fitimage_emit_section_setup ${1} "${setupcount}" arch/${ARCH}/boot/setup.bin "${hash_type}"
+ fi
+
+ #
+ # Step 4: Prepare a ramdisk section.
+ #
+ if [ "x${ramdiskcount}" = "x1" ] ; then
+ bbdebug 1 "searching for requested rootfs"
+ # Find and use the first initramfs image archive type we find
+ for img in squashfs-lz4 squashfs-xz squashfs cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.gz cpio; do
+ initramfs_path="${DEPLOY_DIR_IMAGE}/${IMAGE_BASENAME}-${MACHINE}.${img}"
+ bbdebug 1 "looking for ${initramfs_path}"
+ if [ -e "${initramfs_path}" ]; then
+ bbdebug 1 "Found ${initramfs_path}"
+ fitimage_emit_section_ramdisk ${1} "${ramdiskcount}" "${initramfs_path}" "${hash_type}"
+ break
+ fi
+ done
+ fi
+
+ fitimage_emit_section_maint ${1} sectend
+
+ # Force the first Kernel and DTB in the default config
+ kernelcount=1
+ if [ -n "${dtbcount}" ]; then
+ dtbcount=1
+ fi
+
+ #
+ # Step 5: Prepare a configurations section
+ #
+ fitimage_emit_section_maint ${1} confstart
+
+ if [ -n "${DTBS}" ]; then
+ i=1
+ for DTB in ${DTBS}; do
+ fitimage_emit_section_config ${1} "${kernelcount}" "${DTB}" "${ramdiskcount}" "${setupcount}" "`expr ${i} = ${dtbcount}`" "${hash_type}"
+ i=`expr ${i} + 1`
+ done
+ fi
+
+ fitimage_emit_section_maint ${1} sectend
+
+ fitimage_emit_section_maint ${1} fitend
+
+ #
+ # Step 6: Assemble the image
+ #
+ uboot-mkimage \
+ ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
+ -f ${1} ${2}
+
+ #
+ # Step 7: Sign the image and add public key to U-Boot dtb
+ #
+ if [ "x${UBOOT_SIGN_ENABLE}" = "x1" ] ; then
+ uboot-mkimage \
+ ${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
+ -F -k "${UBOOT_SIGN_KEYDIR}" \
+ -K "${DEPLOY_DIR_IMAGE}/${UBOOT_DTB_BINARY}" \
+ -r ${2}
+ fi
+}
+
+python do_generate_phosphor_manifest() {
+ import os.path
+ b = d.getVar('B', True)
+ manifest_filename = os.path.join(b, "MANIFEST")
+ version = do_get_version(d)
+ with open(manifest_filename, 'w') as fd:
+ fd.write('purpose=xyz.openbmc_project.Software.Version.VersionPurpose.BMC\n')
+ fd.write('version={}\n'.format(version.strip('"')))
+ fd.write('KeyType={}\n'.format("OpenBMC"))
+ fd.write('HashType=RSA-SHA256\n')
+}
+
+def get_pubkey_type(d):
+ return os.listdir(get_pubkey_basedir(d))[0]
+
+def get_pubkey_path(d):
+ return os.path.join(
+ get_pubkey_basedir(d),
+ get_pubkey_type(d),
+ 'publickey')
+python do_copy_signing_pubkey() {
+ with open(get_pubkey_path(d), 'r') as read_fd:
+ with open('publickey', 'w') as write_fd:
+ write_fd.write(read_fd.read())
+}
+
+do_copy_signing_pubkey[dirs] = "${S}"
+do_copy_signing_pubkey[depends] += " \
+ phosphor-image-signing:do_populate_sysroot \
+ "
+
+do_image_fitimage_rootfs() {
+ bbdebug 1 "check for rootfs phosphor fitimage"
+ cd ${B}
+ bbdebug 1 "building rootfs phosphor fitimage"
+ fitimage_assemble fitImage-rootfs-${MACHINE}-${DATETIME}.its \
+ fitImage-rootfs-${MACHINE}-${DATETIME}.bin 1
+
+ for SFX in its bin; do
+ SRC="fitImage-rootfs-${MACHINE}-${DATETIME}.${SFX}"
+ SYM="fitImage-rootfs-${MACHINE}.${SFX}"
+ if [ -e "${B}/${SRC}" ]; then
+ install -m 0644 "${B}/${SRC}" "${DEPLOY_DIR_IMAGE}/${SRC}"
+ ln -sf "${SRC}" "${DEPLOY_DIR_IMAGE}/${SYM}"
+ fi
+ done
+ ln -sf "${DEPLOY_DIR_IMAGE}/fitImage-rootfs-${MACHINE}.bin" "image-runtime"
+ # build a tarball with the right parts: MANIFEST, signatures, etc.
+ # create a directory for the tarball
+ mkdir -p "${B}/img"
+ cd "${B}/img"
+ # add symlinks for the contents
+ ln -sf "${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX}" "image-u-boot"
+ ln -sf "${DEPLOY_DIR_IMAGE}/fitImage-rootfs-${MACHINE}.bin" "image-runtime"
+ # add the manifest
+ bbdebug 1 "Manifest file: ${B}/MANIFEST"
+ ln -sf ${B}/MANIFEST .
+ # touch the required files to minimize change
+ touch image-kernel image-rofs image-rwfs
+
+ tar -h -cvf "${DEPLOY_DIR_IMAGE}/${PN}-image-update-${MACHINE}-${DATETIME}.tar" MANIFEST image-u-boot image-runtime image-kernel image-rofs image-rwfs
+ # make a symlink
+ ln -sf "${PN}-image-update-${MACHINE}-${DATETIME}.tar" "${DEPLOY_DIR_IMAGE}/image-update-${MACHINE}"
+ ln -sf "image-update-${MACHINE}" "${DEPLOY_DIR_IMAGE}/image-update"
+}
+
+do_image_fitimage_rootfs[vardepsexclude] = "DATETIME"
+do_image_fitimage_rootfs[depends] += " ${DEPS}"
+
+
+addtask do_image_fitimage_rootfs before do_generate_auto after do_image_complete
+addtask do_generate_phosphor_manifest before do_image_fitimage_rootfs after do_image_complete
diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
new file mode 100644
index 000000000..1e6bc05af
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
@@ -0,0 +1,55 @@
+inherit obmc-phosphor-image
+inherit systemd-watchdog
+
+IMAGE_INSTALL_append = " \
+ bmcweb \
+ dbus-broker \
+ entity-manager \
+ ipmitool \
+ intel-ipmi-oem \
+ phosphor-ipmi-ipmb \
+ phosphor-node-manager-proxy \
+ dbus-sensors \
+ phosphor-webui \
+ at-scale-debug \
+ phosphor-pid-control \
+ phosphor-host-postd \
+ phosphor-certificate-manager \
+ phosphor-sel-logger \
+ smbios-mdrv2 \
+ obmc-ikvm \
+ system-watchdog \
+ frb2-watchdog \
+ srvcfg-manager \
+ callback-manager \
+ phosphor-post-code-manager \
+ preinit-mounts \
+ mtd-utils-ubifs \
+ special-mode-mgr \
+ rsyslog \
+ static-mac-addr \
+ phosphor-u-boot-mgr \
+ prov-mode-mgr \
+ ac-boot-check \
+ host-error-monitor \
+ beepcode-mgr \
+ psu-manager \
+ kernel-panic-check \
+ id-led-off \
+ hsbp-manager \
+ security-registers-check \
+ pch-time-sync \
+ nv-sync \
+ security-manager \
+ multi-node-nl \
+ virtual-media \
+ enable-nics \
+ host-misc-comm-manager \
+ "
+
+IMAGE_INSTALL_append = "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'intel-pfr-manager', '', d)}"
+
+# this package was flagged as a security risk
+IMAGE_INSTALL_remove += " lrzsz"
+
+BAD_RECOMMENDATIONS += "phosphor-settings-manager"
diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-dev.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-dev.bbclass
new file mode 100644
index 000000000..6a1ac3f14
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-dev.bbclass
@@ -0,0 +1,7 @@
+IMAGE_INSTALL_append = " \
+ mtd-util \
+ io-app \
+ intel-fw-update \
+ lpc-cmds \
+ beeper-test \
+ "
diff --git a/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass b/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass
new file mode 100644
index 000000000..c088fec34
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/systemd-watchdog.bbclass
@@ -0,0 +1,35 @@
+add_watchdog_confs() {
+
+ interval=10 # minutes
+ count=5 # allowed reboots
+
+ for service in $(ls $D/lib/systemd/system | grep -o ".*service"); do
+ if [[ "$service" == *"mapper-wait"* ]]; then
+ continue
+ fi
+
+ if [ "$service" = "system-watchdog.service" ]; then
+ continue
+ fi
+
+ if [ "$service" = "systemd-coredump@.service" ]; then
+ continue
+ fi
+
+ if cat $D/lib/systemd/system/${service} | grep oneshot > /dev/null; then
+ continue
+ fi
+
+ folder="$D/etc/systemd/system/${service}.d"
+ mkdir -p "${folder}"
+ fname="${folder}/watchdog.conf"
+ echo "[Unit]" > ${fname}
+ echo "OnFailure=watchdog-reset@${service}.service" >> ${fname}
+ echo "[Service]" >> "${fname}"
+ echo "StartLimitInterval=${interval}min" >> "${fname}"
+ echo "StartLimitBurst=${count}" >> "${fname}"
+ done
+
+}
+
+ROOTFS_POSTINSTALL_COMMAND += "add_watchdog_confs"
diff --git a/meta-openbmc-mods/meta-common/conf/layer.conf b/meta-openbmc-mods/meta-common/conf/layer.conf
new file mode 100644
index 000000000..4c640e868
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/conf/layer.conf
@@ -0,0 +1,11 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "common"
+BBFILE_PATTERN_common = "^${LAYERDIR}/"
+BBFILE_PRIORITY_common = "10"
+LAYERSERIES_COMPAT_common = "warrior zeus"
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/fw_env.config b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/fw_env.config
new file mode 100644
index 000000000..19ace4b88
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/fw_env.config
@@ -0,0 +1,25 @@
+# Configuration file for fw_(printenv/setenv) utility.
+# Up to two entries are valid, in this case the redundant
+# environment sector is assumed present.
+# Notice, that the "Number of sectors" is ignored on NOR and SPI-dataflash.
+# Furthermore, if the Flash sector size is omitted, this value is assumed to
+# be the same as the Environment size, which is valid for NOR and SPI-dataflash
+
+# NOR example
+# MTD device name Device offset Env. size Flash sector size Number of sectors
+#/dev/mtd1 0x0000 0x20000 0x20000
+#/dev/mtd2 0x0000 0x4000 0x4000
+
+# MTD SPI-dataflash example
+# MTD device name Device offset Env. size Flash sector size Number of sectors
+#/dev/mtd2 0x00000 0x20000
+/dev/mtd/u-boot-env 0x00000 0x10000
+/dev/mtd/u-boot-env 0x10000 0x10000
+#/dev/mtd5 0x4200 0x4200
+#/dev/mtd6 0x4200 0x4200
+
+# NAND example
+#/dev/mtd0 0x4000 0x4000 0x20000 2
+
+# Block device example
+#/dev/mmcblk0 0xc0000 0x20000
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-%.bbappend b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-%.bbappend
new file mode 100644
index 000000000..eee5194fb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += " \
+ file://fw_env.config \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/files/environment.d-openssl.sh b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/files/environment.d-openssl.sh
new file mode 100644
index 000000000..b9cc24a7a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/files/environment.d-openssl.sh
@@ -0,0 +1 @@
+export OPENSSL_CONF="$OECORE_NATIVE_SYSROOT/usr/lib/ssl/openssl.cnf"
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch
new file mode 100644
index 000000000..949c78834
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch
@@ -0,0 +1,76 @@
+From 3e1d00481093e10775eaf69d619c45b32a4aa7dc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= <martin@geanix.com>
+Date: Tue, 6 Nov 2018 14:50:47 +0100
+Subject: [PATCH] buildinfo: strip sysroot and debug-prefix-map from compiler
+ info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The openssl build system generates buildinf.h containing the full
+compiler command line used to compile objects. This breaks
+reproducibility, as the compile command is baked into libcrypto, where
+it is used when running `openssl version -f`.
+
+Add stripped build variables for the compiler and cflags lines, and use
+those when generating buildinfo.h.
+
+This is based on a similar patch for older openssl versions:
+https://patchwork.openembedded.org/patch/147229/
+
+Upstream-Status: Inappropriate [OE specific]
+Signed-off-by: Martin Hundebøll <martin@geanix.com>
+
+
+Update to fix buildpaths qa issue for '-fmacro-prefix-map'.
+
+Signed-off-by: Kai Kang <kai.kang@windriver.com>
+---
+ Configurations/unix-Makefile.tmpl | 10 +++++++++-
+ crypto/build.info | 2 +-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl
+index 16af4d2087..54c162784c 100644
+--- a/Configurations/unix-Makefile.tmpl
++++ b/Configurations/unix-Makefile.tmpl
+@@ -317,13 +317,22 @@ BIN_LDFLAGS={- join(' ', $target{bin_lflags} || (),
+ '$(CNF_LDFLAGS)', '$(LDFLAGS)') -}
+ BIN_EX_LIBS=$(CNF_EX_LIBS) $(EX_LIBS)
+
+-# CPPFLAGS_Q is used for one thing only: to build up buildinf.h
++# *_Q variables are used for one thing only: to build up buildinf.h
+ CPPFLAGS_Q={- $cppflags1 =~ s|([\\"])|\\$1|g;
+ $cppflags2 =~ s|([\\"])|\\$1|g;
+ $lib_cppflags =~ s|([\\"])|\\$1|g;
+ join(' ', $lib_cppflags || (), $cppflags2 || (),
+ $cppflags1 || ()) -}
+
++CFLAGS_Q={- for (@{$config{CFLAGS}}) {
++ s|-fdebug-prefix-map=[^ ]+|-fdebug-prefix-map=|g;
++ s|-fmacro-prefix-map=[^ ]+|-fmacro-prefix-map=|g;
++ }
++ join(' ', @{$config{CFLAGS}}) -}
++
++CC_Q={- $config{CC} =~ s|--sysroot=[^ ]+|--sysroot=recipe-sysroot|g;
++ join(' ', $config{CC}) -}
++
+ PERLASM_SCHEME= {- $target{perlasm_scheme} -}
+
+ # For x86 assembler: Set PROCESSOR to 386 if you want to support
+diff --git a/crypto/build.info b/crypto/build.info
+index b515b7318e..8c9cee2a09 100644
+--- a/crypto/build.info
++++ b/crypto/build.info
+@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
+ ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
+
+ DEPEND[cversion.o]=buildinf.h
+-GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)"
++GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC_Q) $(CFLAGS_Q) $(CPPFLAGS_Q)" "$(PLATFORM)"
+ DEPEND[buildinf.h]=../configdata.pm
+
+ GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME)
+--
+2.19.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-skip-test_symbol_presence.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-skip-test_symbol_presence.patch
new file mode 100644
index 000000000..d8d9651b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0001-skip-test_symbol_presence.patch
@@ -0,0 +1,46 @@
+From a9401b2289656c5a36dd1b0ecebf0d23e291ce70 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Tue, 2 Oct 2018 23:58:24 +0800
+Subject: [PATCH] skip test_symbol_presence
+
+We cannot skip `01-test_symbol_presence.t' by configuring option `no-shared'
+as INSTALL told us the shared libraries will not be built.
+
+[INSTALL snip]
+ Notes on shared libraries
+ -------------------------
+
+ For most systems the OpenSSL Configure script knows what is needed to
+ build shared libraries for libcrypto and libssl. On these systems
+ the shared libraries will be created by default. This can be suppressed and
+ only static libraries created by using the "no-shared" option. On systems
+ where OpenSSL does not know how to build shared libraries the "no-shared"
+ option will be forced and only static libraries will be created.
+[INSTALL snip]
+
+Hence directly modification the case to skip it.
+
+Upstream-Status: Inappropriate [OE Specific]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ test/recipes/01-test_symbol_presence.t | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/test/recipes/01-test_symbol_presence.t b/test/recipes/01-test_symbol_presence.t
+index 7f2a2d7..0b93745 100644
+--- a/test/recipes/01-test_symbol_presence.t
++++ b/test/recipes/01-test_symbol_presence.t
+@@ -14,8 +14,7 @@ use OpenSSL::Test::Utils;
+
+ setup("test_symbol_presence");
+
+-plan skip_all => "Only useful when building shared libraries"
+- if disabled("shared");
++plan skip_all => "The case needs debug symbols then we just disable it";
+
+ my @libnames = ("crypto", "ssl");
+ my $testcount = scalar @libnames;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/afalg.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/afalg.patch
new file mode 100644
index 000000000..b7c0e9697
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/afalg.patch
@@ -0,0 +1,31 @@
+Don't refuse to build afalgeng if cross-compiling or the host kernel is too old.
+
+Upstream-Status: Submitted [hhttps://github.com/openssl/openssl/pull/7688]
+Signed-off-by: Ross Burton <ross.burton@intel.com>
+
+diff --git a/Configure b/Configure
+index 3baa8ce..9ef52ed 100755
+--- a/Configure
++++ b/Configure
+@@ -1550,20 +1550,7 @@ unless ($disabled{"crypto-mdebug-backtrace"})
+ unless ($disabled{afalgeng}) {
+ $config{afalgeng}="";
+ if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
+- my $minver = 4*10000 + 1*100 + 0;
+- if ($config{CROSS_COMPILE} eq "") {
+- my $verstr = `uname -r`;
+- my ($ma, $mi1, $mi2) = split("\\.", $verstr);
+- ($mi2) = $mi2 =~ /(\d+)/;
+- my $ver = $ma*10000 + $mi1*100 + $mi2;
+- if ($ver < $minver) {
+- disable('too-old-kernel', 'afalgeng');
+- } else {
+- push @{$config{engdirs}}, "afalg";
+- }
+- } else {
+- disable('cross-compiling', 'afalgeng');
+- }
++ push @{$config{engdirs}}, "afalg";
+ } else {
+ disable('not-linux', 'afalgeng');
+ }
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/reproducible.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/reproducible.patch
new file mode 100644
index 000000000..a24260c95
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/reproducible.patch
@@ -0,0 +1,32 @@
+The value for perl_archname can vary depending on the host, e.g.
+x86_64-linux-gnu-thread-multi or x86_64-linux-thread-multi which
+makes the ptest package non-reproducible. Its unused other than
+these references so drop it.
+
+RP 2020/2/6
+
+Upstream-Status: Pending
+Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
+
+Index: openssl-1.1.1d/Configure
+===================================================================
+--- openssl-1.1.1d.orig/Configure
++++ openssl-1.1.1d/Configure
+@@ -286,7 +286,7 @@ if (defined env($local_config_envname))
+ # Save away perl command information
+ $config{perl_cmd} = $^X;
+ $config{perl_version} = $Config{version};
+-$config{perl_archname} = $Config{archname};
++#$config{perl_archname} = $Config{archname};
+
+ $config{prefix}="";
+ $config{openssldir}="";
+@@ -2517,7 +2517,7 @@ _____
+ @{$config{perlargv}}), "\n";
+ print "\nPerl information:\n\n";
+ print ' ',$config{perl_cmd},"\n";
+- print ' ',$config{perl_version},' for ',$config{perl_archname},"\n";
++ print ' ',$config{perl_version},"\n";
+ }
+ if ($dump || $options) {
+ my $longest = 0;
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/run-ptest b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/run-ptest
new file mode 100644
index 000000000..3fb22471f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/run-ptest
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+# Optional arguments are 'list' to lists all tests, or the test name (base name
+# ie test_evp, not 03_test_evp.t).
+
+export TOP=.
+# OPENSSL_ENGINES is relative from the test binaries
+export OPENSSL_ENGINES=../engines
+
+perl ./test/run_tests.pl $* | perl -0pe 's#(.*) \.*.ok#PASS: \1#g; s#(.*) \.*.skipped: (.*)#SKIP: \1 (\2)#g; s#(.*) \.*.\nDubious#FAIL: \1#;'
diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1g.bb b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1g.bb
new file mode 100644
index 000000000..66fa8f7d0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1g.bb
@@ -0,0 +1,211 @@
+SUMMARY = "Secure Socket Layer"
+DESCRIPTION = "Secure Socket Layer (SSL) binary and related cryptographic tools."
+HOMEPAGE = "http://www.openssl.org/"
+BUGTRACKER = "http://www.openssl.org/news/vulnerabilities.html"
+SECTION = "libs/network"
+
+# "openssl" here actually means both OpenSSL and SSLeay licenses apply
+# (see meta/files/common-licenses/OpenSSL to which "openssl" is SPDXLICENSEMAPped)
+LICENSE = "openssl"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=d343e62fc9c833710bbbed25f27364c8"
+
+DEPENDS = "hostperl-runtime-native"
+
+SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz \
+ file://run-ptest \
+ file://0001-skip-test_symbol_presence.patch \
+ file://0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch \
+ file://afalg.patch \
+ file://reproducible.patch \
+ "
+
+SRC_URI_append_class-nativesdk = " \
+ file://environment.d-openssl.sh \
+ "
+
+SRC_URI[sha256sum] = "ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46"
+
+inherit lib_package multilib_header multilib_script ptest
+MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash"
+
+PACKAGECONFIG ?= ""
+PACKAGECONFIG_class-native = ""
+PACKAGECONFIG_class-nativesdk = ""
+
+PACKAGECONFIG[cryptodev-linux] = "enable-devcryptoeng,disable-devcryptoeng,cryptodev-linux,,cryptodev-module"
+
+B = "${WORKDIR}/build"
+do_configure[cleandirs] = "${B}"
+
+#| ./libcrypto.so: undefined reference to `getcontext'
+#| ./libcrypto.so: undefined reference to `setcontext'
+#| ./libcrypto.so: undefined reference to `makecontext'
+EXTRA_OECONF_append_libc-musl = " no-async"
+EXTRA_OECONF_append_libc-musl_powerpc64 = " no-asm"
+
+# adding devrandom prevents openssl from using getrandom() which is not available on older glibc versions
+# (native versions can be built with newer glibc, but then relocated onto a system with older glibc)
+EXTRA_OECONF_class-native = "--with-rand-seed=os,devrandom"
+EXTRA_OECONF_class-nativesdk = "--with-rand-seed=os,devrandom"
+
+# Relying on hardcoded built-in paths causes openssl-native to not be relocateable from sstate.
+CFLAGS_append_class-native = " -DOPENSSLDIR=/not/builtin -DENGINESDIR=/not/builtin"
+CFLAGS_append_class-nativesdk = " -DOPENSSLDIR=/not/builtin -DENGINESDIR=/not/builtin"
+
+do_configure () {
+ os=${HOST_OS}
+ case $os in
+ linux-gnueabi |\
+ linux-gnuspe |\
+ linux-musleabi |\
+ linux-muslspe |\
+ linux-musl )
+ os=linux
+ ;;
+ *)
+ ;;
+ esac
+ target="$os-${HOST_ARCH}"
+ case $target in
+ linux-arm*)
+ target=linux-armv4
+ ;;
+ linux-aarch64*)
+ target=linux-aarch64
+ ;;
+ linux-i?86 | linux-viac3)
+ target=linux-x86
+ ;;
+ linux-gnux32-x86_64 | linux-muslx32-x86_64 )
+ target=linux-x32
+ ;;
+ linux-gnu64-x86_64)
+ target=linux-x86_64
+ ;;
+ linux-mips | linux-mipsel)
+ # specifying TARGET_CC_ARCH prevents openssl from (incorrectly) adding target architecture flags
+ target="linux-mips32 ${TARGET_CC_ARCH}"
+ ;;
+ linux-gnun32-mips*)
+ target=linux-mips64
+ ;;
+ linux-*-mips64 | linux-mips64 | linux-*-mips64el | linux-mips64el)
+ target=linux64-mips64
+ ;;
+ linux-microblaze* | linux-nios2* | linux-sh3 | linux-sh4 | linux-arc*)
+ target=linux-generic32
+ ;;
+ linux-powerpc)
+ target=linux-ppc
+ ;;
+ linux-powerpc64)
+ target=linux-ppc64
+ ;;
+ linux-powerpc64le)
+ target=linux-ppc64le
+ ;;
+ linux-riscv32)
+ target=linux-generic32
+ ;;
+ linux-riscv64)
+ target=linux-generic64
+ ;;
+ linux-sparc | linux-supersparc)
+ target=linux-sparcv9
+ ;;
+ esac
+
+ useprefix=${prefix}
+ if [ "x$useprefix" = "x" ]; then
+ useprefix=/
+ fi
+ # WARNING: do not set compiler/linker flags (-I/-D etc.) in EXTRA_OECONF, as they will fully replace the
+ # environment variables set by bitbake. Adjust the environment variables instead.
+ HASHBANGPERL="/usr/bin/env perl" PERL=perl PERL5LIB="${S}/external/perl/Text-Template-1.46/lib/" \
+ perl ${S}/Configure ${EXTRA_OECONF} ${PACKAGECONFIG_CONFARGS} --prefix=$useprefix --openssldir=${libdir}/ssl-1.1 --libdir=${libdir} $target
+ perl ${B}/configdata.pm --dump
+}
+
+do_install () {
+ oe_runmake DESTDIR="${D}" MANDIR="${mandir}" MANSUFFIX=ssl install
+
+ oe_multilib_header openssl/opensslconf.h
+
+ # Create SSL structure for packages such as ca-certificates which
+ # contain hard-coded paths to /etc/ssl. Debian does the same.
+ install -d ${D}${sysconfdir}/ssl
+ mv ${D}${libdir}/ssl-1.1/certs \
+ ${D}${libdir}/ssl-1.1/private \
+ ${D}${libdir}/ssl-1.1/openssl.cnf \
+ ${D}${sysconfdir}/ssl/
+
+ # Although absolute symlinks would be OK for the target, they become
+ # invalid if native or nativesdk are relocated from sstate.
+ ln -sf ${@oe.path.relative('${libdir}/ssl-1.1', '${sysconfdir}/ssl/certs')} ${D}${libdir}/ssl-1.1/certs
+ ln -sf ${@oe.path.relative('${libdir}/ssl-1.1', '${sysconfdir}/ssl/private')} ${D}${libdir}/ssl-1.1/private
+ ln -sf ${@oe.path.relative('${libdir}/ssl-1.1', '${sysconfdir}/ssl/openssl.cnf')} ${D}${libdir}/ssl-1.1/openssl.cnf
+}
+
+do_install_append_class-native () {
+ create_wrapper ${D}${bindir}/openssl \
+ OPENSSL_CONF=${libdir}/ssl-1.1/openssl.cnf \
+ SSL_CERT_DIR=${libdir}/ssl-1.1/certs \
+ SSL_CERT_FILE=${libdir}/ssl-1.1/cert.pem \
+ OPENSSL_ENGINES=${libdir}/engines-1.1
+}
+
+do_install_append_class-nativesdk () {
+ mkdir -p ${D}${SDKPATHNATIVE}/environment-setup.d
+ install -m 644 ${WORKDIR}/environment.d-openssl.sh ${D}${SDKPATHNATIVE}/environment-setup.d/openssl.sh
+ sed 's|/usr/lib/ssl/|/usr/lib/ssl-1.1/|g' -i ${D}${SDKPATHNATIVE}/environment-setup.d/openssl.sh
+}
+
+PTEST_BUILD_HOST_FILES += "configdata.pm"
+PTEST_BUILD_HOST_PATTERN = "perl_version ="
+do_install_ptest () {
+ # Prune the build tree
+ rm -f ${B}/fuzz/*.* ${B}/test/*.*
+
+ cp ${S}/Configure ${B}/configdata.pm ${D}${PTEST_PATH}
+ cp -r ${S}/external ${B}/test ${S}/test ${B}/fuzz ${S}/util ${B}/util ${D}${PTEST_PATH}
+
+ # For test_shlibload
+ ln -s ${libdir}/libcrypto.so.1.1 ${D}${PTEST_PATH}/
+ ln -s ${libdir}/libssl.so.1.1 ${D}${PTEST_PATH}/
+
+ install -d ${D}${PTEST_PATH}/apps
+ ln -s ${bindir}/openssl ${D}${PTEST_PATH}/apps
+ install -m644 ${S}/apps/*.pem ${S}/apps/*.srl ${S}/apps/openssl.cnf ${D}${PTEST_PATH}/apps
+ install -m755 ${B}/apps/CA.pl ${D}${PTEST_PATH}/apps
+
+ install -d ${D}${PTEST_PATH}/engines
+ install -m755 ${B}/engines/ossltest.so ${D}${PTEST_PATH}/engines
+}
+
+# Add the openssl.cnf file to the openssl-conf package. Make the libcrypto
+# package RRECOMMENDS on this package. This will enable the configuration
+# file to be installed for both the openssl-bin package and the libcrypto
+# package since the openssl-bin package depends on the libcrypto package.
+
+PACKAGES =+ "libcrypto libssl openssl-conf ${PN}-engines ${PN}-misc"
+
+FILES_libcrypto = "${libdir}/libcrypto${SOLIBS}"
+FILES_libssl = "${libdir}/libssl${SOLIBS}"
+FILES_openssl-conf = "${sysconfdir}/ssl/openssl.cnf"
+FILES_${PN}-engines = "${libdir}/engines-1.1"
+FILES_${PN}-misc = "${libdir}/ssl-1.1/misc"
+FILES_${PN} =+ "${libdir}/ssl-1.1/*"
+FILES_${PN}_append_class-nativesdk = " ${SDKPATHNATIVE}/environment-setup.d/openssl.sh"
+
+CONFFILES_openssl-conf = "${sysconfdir}/ssl/openssl.cnf"
+
+RRECOMMENDS_libcrypto += "openssl-conf"
+RDEPENDS_${PN}-ptest += "openssl-bin perl perl-modules bash"
+
+BBCLASSEXTEND = "native nativesdk"
+
+CVE_PRODUCT = "openssl:openssl"
+
+# Only affects OpenSSL >= 1.1.1 in combination with Apache < 2.4.37
+# Apache in meta-webserver is already recent enough
+CVE_CHECK_WHITELIST += "CVE-2019-0190"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.service b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.service
new file mode 100644
index 000000000..e8b563850
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Check for AC boot
+After=xyz.openbmc_project.Settings.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/ac-boot-check.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.sh b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.sh
new file mode 100644
index 000000000..38728b512
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check/ac-boot-check.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [[ `cat /proc/cmdline` =~ "resetreason=0x11" ]]
+then
+ busctl set-property xyz.openbmc_project.Settings /xyz/openbmc_project/control/host0/ac_boot xyz.openbmc_project.Common.ACBoot ACBoot s "True"
+else
+ busctl set-property xyz.openbmc_project.Settings /xyz/openbmc_project/control/host0/ac_boot xyz.openbmc_project.Common.ACBoot ACBoot s "False"
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check_git.bb b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check_git.bb
new file mode 100644
index 000000000..2a30696dc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ac-boot-check/ac-boot-check_git.bb
@@ -0,0 +1,24 @@
+SUMMARY = "AC Boot Check"
+DESCRIPTION = "Script to check the resetreason for AC boot"
+
+S = "${WORKDIR}"
+SRC_URI = "file://ac-boot-check.sh \
+ file://ac-boot-check.service \
+"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+RDEPENDS_${PN} += "bash"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/ac-boot-check.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/ac-boot-check.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/ac-boot-check.sh ${D}/${bindir}/ac-boot-check.sh
+}
+
+SYSTEMD_SERVICE_${PN} += " ac-boot-check.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug_git.bb b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug_git.bb
new file mode 100644
index 000000000..6e3e0c4de
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug_git.bb
@@ -0,0 +1,33 @@
+inherit obmc-phosphor-systemd
+
+SUMMARY = "At Scale Debug Service"
+DESCRIPTION = "At Scale Debug Service exposes remote JTAG target debug capabilities"
+
+LICENSE = "BSD"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=0d1c657b2ba1e8877940a8d1614ec560"
+
+
+inherit cmake
+DEPENDS = "sdbusplus openssl libpam libgpiod safec"
+
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
+
+SRC_URI = "git://github.com/Intel-BMC/asd;protocol=git"
+SRCREV = "1.4.3"
+
+inherit useradd
+
+USERADD_PACKAGES = "${PN}"
+
+# add a special user asdbg
+USERADD_PARAM_${PN} = "-u 999 asdbg"
+
+S = "${WORKDIR}/git"
+
+SYSTEMD_SERVICE_${PN} += "com.intel.AtScaleDebug.service"
+
+# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
+EXTRA_OECMAKE = "-DBUILD_UT=OFF"
+
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service
new file mode 100644
index 000000000..4411de11c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Intel BMC At Scale Debug
+Requires=network-online.target
+
+[Service]
+Restart=always
+RestartSec=30
+ExecStart={bindir}/asd
+Type=simple
+SyslogIdentifier=asd
+
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebugJtagTest.service b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebugJtagTest.service
new file mode 100644
index 000000000..281d1a993
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebugJtagTest.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Intel BMC At Scale Debug JTAG test to check if remote debug setting is enabled
+
+[Service]
+Type=oneshot
+ExecStartPre=/bin/sleep 10
+ExecStart={bindir}/jtag_test
+SyslogIdentifier=jtag_test
+RemainAfterExit=true
+
+[Install]
+WantedBy=obmc-host-start@0.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files/fstab b/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files/fstab
new file mode 100644
index 000000000..0b53093ae
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files/fstab
@@ -0,0 +1,10 @@
+/dev/root / auto defaults 1 1
+proc /proc proc defaults 0 0
+devpts /dev/pts devpts mode=0620,gid=5 0 0
+tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0
+tmpfs /var/lib/systemd/coredump tmpfs rw,nosuid,nodev,size=67108864 0 0
+tmpfs /media tmpfs rw 0 0
+
+# uncomment this if your device has a SD/MMC/Transflash slot
+#/dev/mmcblk0p1 /media/card auto defaults,sync,noauto 0 0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files_%.bbappend
new file mode 100644
index 000000000..79e529179
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/base-files/base-files_%.bbappend
@@ -0,0 +1,2 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI_append = " file://fstab"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/dev-only.cfg b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/dev-only.cfg
new file mode 100644
index 000000000..f8f49e001
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/dev-only.cfg
@@ -0,0 +1,4 @@
+CONFIG_NC=y
+CONFIG_NETSTAT=y
+CONFIG_TFTP=y
+CONFIG_WGET=y
diff --git a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/disable.cfg b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/disable.cfg
new file mode 100644
index 000000000..2550ffaf5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/disable.cfg
@@ -0,0 +1,6 @@
+CONFIG_NC=n
+CONFIG_NETSTAT=n
+CONFIG_TELNET=n
+CONFIG_TFTP=n
+CONFIG_WGET=n
+CONFIG_UDHCPD=n
diff --git a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend
new file mode 100644
index 000000000..deb9ccbf8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += "file://disable.cfg"
+
+SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks','file://dev-only.cfg','',d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
new file mode 100644
index 000000000..b4875c332
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
@@ -0,0 +1,28 @@
+inherit obmc-phosphor-dbus-service
+inherit obmc-phosphor-systemd
+
+SUMMARY = "CPU Crashdump"
+DESCRIPTION = "CPU utilities for dumping CPU Crashdump and registers over PECI"
+
+DEPENDS = "boost cjson sdbusplus safec gtest libpeci"
+inherit cmake
+
+EXTRA_OECMAKE = "-DCRASHDUMP_BUILD_UT=ON"
+
+LICENSE = "Proprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=43c09494f6b77f344027eea0a1c22830"
+
+SRC_URI = "git://github.com/Intel-BMC/crashdump;protocol=git"
+SRCREV = "wht-0.65"
+
+S = "${WORKDIR}/git"
+
+SYSTEMD_SERVICE_${PN} += "com.intel.crashdump.service"
+DBUS_SERVICE_${PN} += "com.intel.crashdump.service"
+
+# linux-libc-headers guides this way to include custom uapi headers
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/crashdump/files/com.intel.crashdump.service b/meta-openbmc-mods/meta-common/recipes-core/crashdump/files/com.intel.crashdump.service
new file mode 100644
index 000000000..6f79573f0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/crashdump/files/com.intel.crashdump.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Intel BMC CPU Crashdump
+
+[Service]
+Restart=always
+ExecStart={bindir}/crashdump
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/dropbear/dropbear_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/dropbear/dropbear_%.bbappend
new file mode 100644
index 000000000..cfa1d0711
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/dropbear/dropbear_%.bbappend
@@ -0,0 +1,22 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://enable-ssh.sh"
+
+add_manual_ssh_enable() {
+ install -d ${D}/usr/share/misc
+ install -m 0755 ${D}/${systemd_unitdir}/system/dropbear@.service ${D}/usr/share/misc/dropbear@.service
+ install -m 0755 ${D}/${systemd_unitdir}/system/dropbear.socket ${D}/usr/share/misc/dropbear.socket
+ install -m 0755 ${WORKDIR}/enable-ssh.sh ${D}${bindir}/enable-ssh.sh
+ # Remove dropbear service and socket by default, if debug-tweaks is disabled
+ rm ${D}/${systemd_unitdir}/system/dropbear@.service
+ rm ${D}/${systemd_unitdir}/system/dropbear.socket
+}
+
+do_install_append() {
+ # Add manual ssh enable script if debug-tweaks is disabled
+ ${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', '', 'add_manual_ssh_enable', d)}
+}
+
+FILES_${PN} += "/usr/share/misc"
+SYSTEMD_SERVICE_${PN} += "dropbearkey.service"
+SYSTEMD_SERVICE_${PN}_remove += " ${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', '', 'dropbear.socket', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/dropbear/files/enable-ssh.sh b/meta-openbmc-mods/meta-common/recipes-core/dropbear/files/enable-ssh.sh
new file mode 100755
index 000000000..e97995cc1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/dropbear/files/enable-ssh.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if [ -e /etc/systemd/system/dropbear@.service ] && \
+ [ -e /etc/systemd/system/sockets.target.wants/dropbear.socket ]
+then
+ echo "SSH is already enabled"
+else
+ cp /usr/share/misc/dropbear@.service /etc/systemd/system/dropbear@.service
+ cp /usr/share/misc/dropbear.socket /etc/systemd/system/dropbear.socket
+ ln -s /etc/systemd/system/dropbear.socket /etc/systemd/system/sockets.target.wants/dropbear.socket
+ groupmems -g priv-admin -a root
+ systemctl daemon-reload
+ systemctl restart dropbear.socket
+ echo "Enabled SSH service for root user successful"
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh
new file mode 100644
index 000000000..917e7ab09
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh
@@ -0,0 +1,366 @@
+#!/bin/sh
+
+log() {
+ echo "$@"
+}
+
+FWTYPE=""
+FWVER=""
+redfish_log_fw_evt() {
+ local evt=$1
+ local sev=""
+ local msg=""
+ [ -z "$FWTYPE" ] && return
+ [ -z "$FWVER" ] && return
+ case "$evt" in
+ start)
+ evt=OpenBMC.0.1.FirmwareUpdateStarted
+ msg="${FWTYPE} firmware update to version ${FWVER} started."
+ sev=OK
+ ;;
+ success)
+ evt=OpenBMC.0.1.FirmwareUpdateCompleted
+ msg="${FWTYPE} firmware update to version ${FWVER} completed successfully."
+ sev=OK
+ ;;
+ abort)
+ evt=OpenBMC.0.1.FirmwareUpdateFailed
+ msg="${FWTYPE} firmware update to version ${FWVER} failed."
+ sev=Warning
+ ;;
+ *) return ;;
+ esac
+ logger-systemd --journald <<-EOF
+ MESSAGE=$msg
+ PRIORITY=2
+ SEVERITY=${sev}
+ REDFISH_MESSAGE_ID=${evt}
+ REDFISH_MESSAGE_ARGS=${FWTYPE},${FWVER}
+ EOF
+}
+
+wait_for_log_sync()
+{
+ sync
+ sleep 5
+}
+
+PFR_BUS=4
+PFR_ADDR=0x38
+PFR_ID_REG=0x00
+PFR_STATE_REG=0x03
+PFR_PROV_REG=0x0a
+PFR_INTENT_REG=0x13
+pfr_read() {
+ [ $# -ne 1 ] && return 1
+ local reg=$1
+ i2cget -y $PFR_BUS $PFR_ADDR $reg 2>/dev/null
+}
+
+pfr_write() {
+ [ $# -ne 2 ] && return 1
+ local reg=$1
+ local val=$2
+ i2cset -y $PFR_BUS $PFR_ADDR $reg $val >&/dev/null
+}
+
+pfr_active_update() {
+ local factory_reset=""
+ local recovery_offset=0x2a00000
+ systemctl stop nv-sync.service || \
+ log "BMC NV sync failed to stop"
+ # transition from non-PFR to PFR image requires factory reset
+ if [ ! -e /usr/share/pfr ]; then
+ factory_reset="-r"
+ mtd-util pfr stage $LOCAL_PATH $recovery_offset
+ fi
+ mtd-util $factory_reset pfr write $LOCAL_PATH
+ redfish_log_fw_evt success
+ # only wait for logging if not transitioning from non-PFR to PFR
+ if [ -e /usr/share/pfr ]; then
+ # exit bmc no nv mode
+ systemctl start nv-sync.service || log "failed to start nv-sync"
+ wait_for_log_sync
+ fi
+ reboot
+}
+
+pfr_staging_update() {
+ log "Updating $(basename $TGT)"
+ flash_erase $TGT $erase_offset $blk_cnt
+ log "Writing $(stat -c "%s" "$LOCAL_PATH") bytes"
+ # cat "$LOCAL_PATH" > "$TGT"
+ dd bs=4k seek=$(($erase_offset / 0x1000)) if=$LOCAL_PATH of=$TGT 2>/dev/null
+
+ # remove the updated image from /tmp
+ rm -f $LOCAL_PATH
+ redfish_log_fw_evt success
+ log "Setting update intent in PFR CPLD"
+ wait_for_log_sync
+
+ # write to PFRCPLD about BMC update intent.
+ pfr_write 0x13 $upd_intent_val
+}
+
+pfr_active_mode() {
+ # check for 0xde in register file 0
+ local id=$(pfr_read $PFR_ID_REG) || return 1
+ [ "$id" == "0xde" ] || return 1
+ local state=$(pfr_read $PFR_STATE_REG) || return 1
+ local prov=$(pfr_read $PFR_PROV_REG) || return 1
+ prov=$((prov & 0x20))
+ [ "$prov" == "32" ] && return 0
+ return 1
+}
+
+blk0blk1_update() {
+ # PFR-style image update section
+ # read the image type from the uploaded image
+ # Byte at location 0x8 gives image type
+ TGT="/dev/mtd/image-stg"
+ img_type=$(hexdump -s 8 -n 1 -e '/1 "%02x\n"' $LOCAL_PATH)
+ log "image-type=$img_type"
+
+ if [ $local_file -eq 0 ]; then
+ img_type_str=$(busctl get-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$img_obj xyz.openbmc_project.Software.Version Purpose | cut -d " " -f 2 | cut -d "." -f 6 | sed 's/.\{1\}$//')
+ img_target=$(busctl get-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$img_obj xyz.openbmc_project.Software.Activation RequestedActivation | cut -d " " -f 2| cut -d "." -f 6 | sed 's/.\{1\}$//')
+ else
+ img_type_str='BMC'
+ img_target='Active'
+ fi
+
+ apply_time=$(busctl get-property xyz.openbmc_project.Settings /xyz/openbmc_project/software/apply_time xyz.openbmc_project.Software.ApplyTime RequestedApplyTime | cut -d " " -f 2 | cut -d "." -f 6 | sed 's/.\{1\}$//')
+ log "image-name=$img_type_str"
+ log "image-target=$img_target"
+ log "apply_time=$apply_time"
+
+ case "$img_type" in
+ 04)
+ if [ "$img_type_str" == 'BMC' ]; then
+ # BMC image - max size 32MB
+ log "BMC firmware image"
+ img_size=33554432
+ if [ "$img_target" == 'StandbySpare' ]; then
+ upd_intent_val=0x10
+ else
+ upd_intent_val=0x08
+ fi
+ erase_offset=0
+ FWTYPE="BMC"
+ FWVER="${RANDOM}-fixme"
+ else
+ # log error the image selected for update is not same as downloaded.
+ log "Mismatch: image selected for update and image parsed are different"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ ;;
+ 00)
+ if [ "$img_type_str" == 'Other' ]; then
+ log "CPLD firmware image"
+ # CPLD image- max size 1MB
+ img_size=1048576
+ if [ "$img_target" == 'StandbySpare' ]; then
+ upd_intent_val=0x20
+ else
+ upd_intent_val=0x04
+ fi
+ erase_offset=0x3000000
+ FWTYPE="CPLD"
+ FWVER="${RANDOM}-fixme"
+ else
+ # log error the image selected for update is not same as downloaded.
+ log "Mismatch: image selected for update and image parsed are different"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ ;;
+ 02)
+ if [ "$img_type_str" = 'Host' ]; then
+ # BIOS image- max size 16MB
+ log "BIOS firmware image"
+ img_size=16777216
+ if [ "$img_target" == 'StandbySpare' ]; then
+ upd_intent_val=0x02
+ else
+ upd_intent_val=0x41
+ fi
+ erase_offset=0x2000000
+ # TODO: parse out the fwtype and fwver once that is specified
+ FWTYPE="BIOS"
+ FWVER="${RANDOM}-fixme"
+ else
+ # log error the image selected for update is not same as downloaded.
+ log "Mismatch: image selected for update and image parsed are different"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ ;;
+ *)
+ log "Unknown image type ${img_type}"
+ return 1
+ ;;
+ esac
+
+ # For deferred updates
+ if [ "$apply_time" == 'OnReset' ]; then
+ upd_intent_val=$(( "$upd_intent_val"|0x80 ))
+ fi
+
+ # do a quick sanity check on the image
+ if [ $(stat -c "%s" "$LOCAL_PATH") -gt $img_size ]; then
+ log "Update file "$LOCAL_PATH" is bigger than the supported image size"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ blk_cnt=$((img_size / 0x10000))
+
+ if pfr_active_mode; then
+ # pfr enforcing mode; any b0b1 image type
+ pfr_staging_update
+ elif [ "$img_type" == '04' ]; then
+ # legacy mode; pfr is not present but we got a pfr image
+ log "Updating BMC active firmware- PFR unprovisioned mode"
+ pfr_active_update
+ else
+ # error; pfr is not present but we got a pfr image,
+ # an invalid image, or nonBMC image
+ log "PFR inactive or invalid image type:${img_type}, cowardly refusing to process image"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+}
+
+ping_pong_update() {
+ # if some one tries to update with non-PFR on PFR image
+ # just exit
+ if [ -e /usr/share/pfr ]; then
+ log "Update exited as non-PFR image is tried onto PFR image"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ # do a quick sanity check on the image
+ if [ $(stat -c "%s" "$LOCAL_PATH") -lt 10000000 ]; then
+ log "Update file "$LOCAL_PATH" seems to be too small"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+ dtc -I dtb -O dtb "$LOCAL_PATH" > /dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ log "Update file $LOCAL_PATH doesn't seem to be in the proper format"
+ redfish_log_fw_evt abort
+ return 1
+ fi
+
+ # guess based on fw_env which partition we booted from
+ local BOOTADDR=$(fw_printenv bootcmd | awk '{print $2}')
+ local TGT="/dev/mtd/image-a"
+ case "$BOOTADDR" in
+ 20080000) TGT="/dev/mtd/image-b"; BOOTADDR="22480000" ;;
+ 22480000) TGT="/dev/mtd/image-a"; BOOTADDR="20080000" ;;
+ *) TGT="/dev/mtd/image-a"; BOOTADDR="20080000" ;;
+ esac
+ log "Updating $(basename $TGT) (use bootm $BOOTADDR)"
+ flash_erase $TGT 0 0
+ log "Writing $(stat -c "%s" "$LOCAL_PATH") bytes"
+ cat "$LOCAL_PATH" > "$TGT"
+ fw_setenv "bootcmd" "bootm ${BOOTADDR}"
+ redfish_log_fw_evt success
+ wait_for_log_sync
+ # reboot
+ reboot
+}
+
+fetch_fw() {
+ PROTO=$(echo "$URI" | sed 's,\([a-z]*\)://.*$,\1,')
+ REMOTE=$(echo "$URI" | sed 's,.*://\(.*\)$,\1,')
+ REMOTE_HOST=$(echo "$REMOTE" | sed 's,\([^/]*\)/.*$,\1,')
+ if [ "$PROTO" = 'scp' ]; then
+ REMOTE_PATH=$(echo "$REMOTE" | cut -d':' -f2)
+ else
+ REMOTE_PATH=$(echo "$REMOTE" | sed 's,[^/]*/\(.*\)$,\1,')
+ fi
+ LOCAL_PATH="/tmp/$(basename $REMOTE_PATH)"
+ log "PROTO=$PROTO"
+ log "REMOTE=$REMOTE"
+ log "REMOTE_HOST=$REMOTE_HOST"
+ log "REMOTE_PATH=$REMOTE_PATH"
+ if [ ! -e $LOCAL_PATH ] || [ $(stat -c %s $LOCAL_PATH) -eq 0 ]; then
+ log "Download '$REMOTE_PATH' from $PROTO $REMOTE_HOST $REMOTE_PATH"
+ case "$PROTO" in
+ scp)
+ mkdir -p $HOME/.ssh
+ if [ -e "$SSH_ID" ]; then
+ ARG_ID="-i $SSH_ID"
+ fi
+ scp $ARG_ID $REMOTE_HOST$REMOTE_PATH $LOCAL_PATH
+ if [ $? -ne 0 ]; then
+ log "scp $REMOTE $LOCAL_PATH failed!"
+ return 1
+ fi
+ ;;
+ tftp)
+ cd /tmp
+ tftp -g -r "$REMOTE_PATH" "$REMOTE_HOST"
+ if [ $? -ne 0 ]; then
+ log "tftp -g -r \"$REMOTE_PATH\" \"$REMOTE_HOST\" failed!"
+ return 1
+ fi
+ ;;
+ http|https|ftp)
+ wget --no-check-certificate "$URI" -O "$LOCAL_PATH"
+ if [ $? -ne 0 ]; then
+ log "wget $URI failed!"
+ return 1
+ fi
+ ;;
+ file)
+ LOCAL_PATH=$(echo $URI | sed 's,^file://,,')
+ ;;
+ *)
+ log "Invalid URI $URI"
+ return 1
+ ;;
+ esac
+ fi
+}
+
+update_fw() {
+ redfish_log_fw_evt start
+ # determine firmware file type
+ local magic=$(hexdump -n 4 -v -e '/1 "%02x"' "$LOCAL_PATH")
+ case "$magic" in
+ d00dfeed) ping_pong_update ;;
+ 19fdeab6) blk0blk1_update ;;
+ *) log "Uknown file type ${magic}"
+ esac
+}
+
+# if this script was sourced, just return without executing anything
+[ "$_" != "$0" ] && return 0 >&/dev/null
+
+usage() {
+ echo "usage: $(basename $0) uri"
+ echo " uri is something like: file:///path/to/fw"
+ echo " tftp://tftp.server.ip.addr/path/to/fw"
+ echo " scp://[user@]scp.server.ip.addr:/path/to/fw"
+ echo " http[s]://web.server.ip.addr/path/to/fw"
+ echo " ftp://[user@]ftp.server.ip.addr/path/to/fw"
+ exit 1
+}
+
+if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then usage; fi
+if [ $# -eq 0 ]; then
+ # set DEFURI in $HOME/.fwupd.defaults
+ URI="$DEFURI"
+else
+ if [[ "$1" == *"/"* ]]; then
+ URI=$1 # local file
+ local_file=1 ;
+ else
+ URI="file:////tmp/images/$1/image-runtime"
+ img_obj=$1
+ local_file=0 ;
+ fi
+fi
+fetch_fw && update_fw
diff --git a/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl
new file mode 100644
index 000000000..ae9f54263
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl
@@ -0,0 +1,136 @@
+#!/bin/sh
+
+setup_image()
+{
+ set -x
+ local storage="$1"
+ local sz_mb="$2"
+ # create the backing store
+ dd if=/dev/zero of=$storage bs=1M seek=$sz_mb count=0 2>/dev/null
+ # this shows up as 23FC-F676 in /dev/disk/by-uuid
+ local diskid=0x23FCF676
+ mkdosfs -n 'OPENBMC-FW' -i $diskid -I $storage >/dev/null 2>&1
+}
+
+mount_image()
+{
+ set -x
+ local storage="$1"
+ local stormnt="$2"
+ mkdir -p $stormnt || exit 1
+ mount -o loop -t vfat $storage $stormnt
+}
+
+cleanup_image()
+{
+ set -x
+ local storage="$1"
+ local stormnt="$2"
+ umount -f "$stormnt"
+ rm -f "$storage"
+ rmdir "$stormnt"
+}
+
+GADGET_BASE=/sys/kernel/config/usb_gadget
+
+which_dev()
+{
+ local in_use=$(cat $GADGET_BASE/*/UDC)
+ cd /sys/class/udc
+ for D in *; do
+ case "$in_use" in
+ *"$D"*) ;;
+ *) echo "$D"; return 0;;
+ esac
+ done
+ return 1
+}
+
+usb_ms_insert()
+{
+ local name="$1"
+ local storage="$2"
+
+ if [ -d $GADGET_BASE/$name ]; then
+ echo "device $name already exists" >&2
+ return 1
+ fi
+ mkdir $GADGET_BASE/$name
+ cd $GADGET_BASE/$name
+
+ echo 0x1d6b > idVendor # Linux Foundation
+ echo 0x0105 > idProduct # FunctionFS Gadget
+ mkdir strings/0x409
+ local machineid=$(cat /etc/machine-id)
+ local data="OpenBMC USB mass storage gadget device serial number"
+ local serial=$( echo -n "${machineid}${data}${machineid}" | \
+ sha256sum | cut -b 0-12 )
+ echo $serial > strings/0x409/serialnumber
+ echo OpenBMC > strings/0x409/manufacturer
+ echo "OpenBMC Mass Storage" > strings/0x409/product
+
+ mkdir configs/c.1
+ mkdir functions/mass_storage.$name
+ echo $storage > functions/mass_storage.$name/lun.0/file
+ echo 0 > functions/mass_storage.$name/lun.0/removable
+ mkdir configs/c.1/strings/0x409
+
+ echo "Conf 1" > configs/c.1/strings/0x409/configuration
+ echo 120 > configs/c.1/MaxPower
+ ln -s functions/mass_storage.$name configs/c.1
+ local dev=$(which_dev)
+ echo $dev > UDC
+}
+
+usb_ms_eject()
+{
+ local name="$1"
+
+ echo '' > $GADGET_BASE/$name/UDC
+
+ rm -f $GADGET_BASE/$name/configs/c.1/mass_storage.$name
+ rmdir $GADGET_BASE/$name/configs/c.1/strings/0x409
+ rmdir $GADGET_BASE/$name/configs/c.1
+ rmdir $GADGET_BASE/$name/functions/mass_storage.$name
+ rmdir $GADGET_BASE/$name/strings/0x409
+ rmdir $GADGET_BASE/$name
+}
+
+usage()
+{
+ echo "Usage: $0 <action> ..."
+ echo " $0 setup <file> <sizeMB>"
+ echo " $0 insert <name> <file>"
+ echo " $0 eject <name>"
+ echo " $0 mount <file> <mnt>"
+ echo " $0 cleanup <file> <mnt>"
+ exit 1
+}
+
+echo "$#: $0 $@"
+case "$1" in
+ insert)
+ shift
+ usb_ms_insert "$@"
+ ;;
+ eject)
+ shift
+ usb_ms_eject "$@"
+ ;;
+ setup)
+ shift
+ setup_image "$@"
+ ;;
+ mount)
+ shift
+ mount_image "$@"
+ ;;
+ cleanup)
+ shift
+ cleanup_image "$@"
+ ;;
+ *)
+ usage
+ ;;
+esac
+exit $?
diff --git a/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb b/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb
new file mode 100644
index 000000000..007a4aece
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb
@@ -0,0 +1,30 @@
+SUMMARY = "Temporary intel-fw-update script"
+DESCRIPTION = "At runtime, perform a firmware update and reboot"
+PR = "r1"
+
+# flash_eraseall
+RDEPENDS_intel-fw-update += "mtd-utils"
+# wget tftp scp
+RDEPENDS_intel-fw-update += "busybox dropbear"
+# mkfs.vfat, parted
+RDEPENDS_intel-fw-update += "dosfstools dtc"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+PFR_EN = "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'pfr', '', d)}"
+
+SRC_URI += "file://fwupd.sh"
+SRC_URI += "file://usb-ctrl"
+
+FILES_${PN} += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '${datadir}/pfr', '', d)}"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/fwupd.sh ${D}${bindir}
+ install -m 0755 ${WORKDIR}/usb-ctrl ${D}${bindir}
+
+ if [ "${PFR_EN}" = "pfr" ]; then
+ install -d ${D}${datadir}
+ touch ${D}${datadir}/pfr
+ fi
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
new file mode 100644
index 000000000..81462b2d3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/host-error-monitor/host-error-monitor_%.bbappend
@@ -0,0 +1,3 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/host-error-monitor"
+SRCREV = "53099c49b89c22cfe09c7217679ae1fb20e019eb"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format
new file mode 100644
index 000000000..86a2a9d63
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/.clang-format
@@ -0,0 +1,21 @@
+---
+BasedOnStyle: LLVM
+Language: Cpp
+IndentWidth: 8
+UseTab: Always
+BreakBeforeBraces: Linux
+AlwaysBreakBeforeMultilineStrings: true
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+IndentCaseLabels: false
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AlignAfterOpenBracket: true
+SpaceAfterCStyleCast: false
+MaxEmptyLinesToKeep: 2
+BreakBeforeBinaryOperators: NonAssignment
+BreakStringLiterals: false
+SortIncludes: true
+ContinuationIndentWidth: 8
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch
new file mode 100644
index 000000000..05bd4c055
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/0001-Smbus-changes-for-libmctp.patch
@@ -0,0 +1,119 @@
+From 1f14ea50ece39c59d23690690dc7c8b1059a35f6 Mon Sep 17 00:00:00 2001
+From: Nikhil Potade <nikhil.potade@linux.intel.com>
+Date: Tue, 19 Feb 2019 14:16:20 +0800
+Subject: [PATCH 1/1] Smbus changes for libmctp
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ core.c | 2 ++
+ libmctp.h | 40 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+)
+
+diff --git a/core.c b/core.c
+index e7f5689..3732e8a 100644
+--- a/core.c
++++ b/core.c
+@@ -17,6 +17,7 @@
+
+ /* Internal data structures */
+
++/* clang-format off */
+ struct mctp_bus {
+ mctp_eid_t eid;
+ struct mctp_binding *binding;
+@@ -56,6 +57,7 @@ struct mctp {
+ ROUTE_BRIDGE,
+ } route_policy;
+ };
++/* clang-format on */
+
+ #ifndef BUILD_ASSERT
+ #define BUILD_ASSERT(x) \
+diff --git a/libmctp.h b/libmctp.h
+index 69ec46a..b7212be 100644
+--- a/libmctp.h
++++ b/libmctp.h
+@@ -15,6 +15,7 @@ extern "C" {
+ typedef uint8_t mctp_eid_t;
+
+ /* MCTP packet definitions */
++/* clang-format off */
+ struct mctp_hdr {
+ uint8_t ver;
+ uint8_t dest;
+@@ -30,19 +31,56 @@ struct mctp_hdr {
+ #define MCTP_HDR_SEQ_MASK (0x3)
+ #define MCTP_HDR_TAG_SHIFT (0)
+ #define MCTP_HDR_TAG_MASK (0x7)
++/* clang-format on */
+
+ /* Baseline Transmission Unit and packet size */
+ #define MCTP_BTU 64
+ #define MCTP_PACKET_SIZE(unit) ((unit) + sizeof(struct mctp_hdr))
+
++#define MCTP_CONTROL_MESSAGE_TYPE 0x00
++
++enum MCTP_COMMAND_CODE {
++ MCTP_COMMAND_CODE_SET_EID = 0x01,
++ MCTP_COMMAND_CODE_GET_EID = 0x02,
++ MCTP_COMMAND_CODE_GET_ENDPOINT_UUID = 0x03,
++ MCTP_COMMAND_CODE_GET_MCTP_VERSION_SUPPORT = 0x04,
++ MCTP_COMMAND_CODE_GET_MESSAGE_TYPE_SUPPORT = 0x05,
++ MCTP_COMMAND_CODE_GET_VENDOR_DEFINED_MSG_SUPPORT= 0x06,
++ MCTP_COMMAND_CODE_RESOLVE_ENDPOINT_ID = 0x07,
++ MCTP_COMMAND_CODE_ALLOCATE_ENDPOINT_IDS = 0x08,
++ MCTP_COMMAND_CODE_ROUTING_INFORMATION_UPDATE = 0x09,
++ MCTP_COMMAND_CODE_GET_ROUTING_TABLE_ENTRIES = 0x0A,
++ MCTP_COMMAND_CODE_PREPARE_FOR_ENDPOINT_DISCOVERY= 0x0B,
++ MCTP_COMMAND_CODE_ENDPOINT_DISCOVERY = 0x0C,
++ MCTP_COMMAND_CODE_DISCOVERY_NOTIFY = 0x0D,
++ MCTP_COMMAND_CODE_GET_NETWORK_ID = 0x0E,
++ MCTP_COMMAND_CODE_QUERY_HOP = 0x0F,
++ MCTP_COMMAND_CODE_RESOLVE_UUID = 0x10,
++ MCTP_COMMAND_CODE_QUERY_RATE_LIMIT = 0x11,
++ MCTP_COMMAND_CODE_REQUEST_TX_RATE_LIMIT = 0x12,
++ MCTP_COMMAND_CODE_UPDATE_RATE_LIMIT = 0x13,
++ MCTP_COMMAND_CODE_QUERY_SUPPORTED_INTERFACES = 0x14
++};
++
++enum MCTP_CONTROL_MSG_COMPLETION_CODE {
++ MCTP_CONTROL_MSG_STATUS_SUCCESS = 0x00,
++ MCTP_CONTROL_MSG_STATUS_ERROR = 0x01,
++ MCTP_CONTROL_MSG_STATUS_ERROR_INVALID_DATA = 0x02,
++ MCTP_CONTROL_MSG_STATUS_ERROR_INVALID_LENGTH = 0x03,
++ MCTP_CONTROL_MSG_STATUS_ERROR_NOT_READY = 0x04,
++ MCTP_CONTROL_MSG_STATUS_ERROR_UNSUPPORTED_CMD = 0x05
++};
++
+ /* packet buffers */
+
++/* clang-format off */
+ struct mctp_pktbuf {
+ size_t start, end, size;
+ size_t mctp_hdr_off;
+ struct mctp_pktbuf *next;
+ unsigned char data[];
+ };
++/* clang-format on */
+
+ struct mctp_binding;
+
+@@ -90,6 +128,7 @@ int mctp_message_tx(struct mctp *mctp, mctp_eid_t eid,
+ void *msg, size_t msg_len);
+
+ /* hardware bindings */
++/* clang-format off */
+ struct mctp_binding {
+ const char *name;
+ uint8_t version;
+@@ -101,6 +140,7 @@ struct mctp_binding {
+ int (*tx)(struct mctp_binding *binding,
+ struct mctp_pktbuf *pkt);
+ };
++/* clang-format on */
+
+ void mctp_binding_set_tx_enabled(struct mctp_binding *binding, bool enable);
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt
new file mode 100644
index 000000000..28354123e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+add_definitions(-DMCTP_LOG_STDERR)
+add_definitions(-DMCTP_HAVE_FILEIO)
+add_definitions(-DMCTP_HAVE_STDIO)
+add_definitions(-DMCTP_DEFAULT_ALLOC)
+
+add_library(
+ libmctp STATIC alloc.c core.c log.c libmctp.h serial.c smbus.c crc32c.c)
+
+target_include_directories(libmctp
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:include/libmctp)
+
+enable_testing()
+
+add_executable(test_eid tests/test_eid.c tests/test-utils.c)
+target_link_libraries(test_eid libmctp)
+
+add_executable(test_seq tests/test_seq.c tests/test-utils.c)
+target_link_libraries(test_seq libmctp)
+
+install(TARGETS libmctp DESTINATION lib)
+install(
+ FILES libmctp.h libmctp-smbus.h libmctp-serial.h crc32c.h DESTINATION include)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c
new file mode 100644
index 000000000..0d5090e2c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.c
@@ -0,0 +1,93 @@
+#include "crc32c.h"
+/*****************************************************************/
+/* */
+/* CRC LOOKUP TABLE */
+/* ================ */
+/* The following CRC lookup table was generated automagically */
+/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+/* Program V1.0 using the following model parameters: */
+/* */
+/* Width : 4 bytes. */
+/* Poly : 0x1EDC6F41L */
+/* Reverse : TRUE. */
+/* */
+/* For more information on the Rocksoft^tm Model CRC Algorithm, */
+/* see the document titled "A Painless Guide to CRC Error */
+/* Detection Algorithms" by Ross Williams */
+/* (ross@guest.adelaide.edu.au.). This document is likely to be */
+/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/*****************************************************************/
+
+unsigned long crctable[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL,
+ 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL,
+ 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L,
+ 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L,
+ 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL,
+ 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L,
+ 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL,
+ 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L,
+ 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L,
+ 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL,
+ 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L,
+ 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L,
+ 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL,
+ 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL,
+ 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L,
+ 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL,
+ 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L,
+ 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL,
+ 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL,
+ 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL,
+ 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L,
+ 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L,
+ 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL,
+ 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL,
+ 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L,
+ 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL,
+ 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L,
+ 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L,
+ 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL,
+ 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L,
+ 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L,
+ 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L,
+ 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L,
+ 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL,
+ 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L,
+ 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L,
+ 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL,
+ 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L,
+ 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L,
+ 0xAD7D5351L};
+
+/*****************************************************************/
+/* End of CRC Lookup Table */
+/*****************************************************************/
+
+uint32_t crc32c(uint8_t *data, int length)
+{
+ const uint32_t CRC_INIT = 0xffffffffL;
+ const uint32_t XO_ROT = 0xffffffffL;
+
+ uint32_t crc = CRC_INIT;
+
+ while (length--) {
+ crc = crctable[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
+ }
+ crc = crc ^ XO_ROT;
+
+ return crc;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h
new file mode 100644
index 000000000..4586547e6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/crc32c.h
@@ -0,0 +1,16 @@
+#ifndef CRC32C_H
+#define CRC32C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t crc32c(uint8_t *buf, int len);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* CRC32C_H */
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h
new file mode 100644
index 000000000..67690bcb3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/libmctp-smbus.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef _LIBMCTP_SMBUS_H
+#define _LIBMCTP_SMBUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "libmctp.h"
+
+struct mctp_binding_smbus;
+
+struct mctp_binding_smbus *mctp_smbus_init(void);
+int mctp_smbus_get_out_fd(struct mctp_binding_smbus *smbus);
+int mctp_smbus_get_in_fd(struct mctp_binding_smbus *smbus);
+void mctp_smbus_register_bus(struct mctp_binding_smbus *smbus,
+ struct mctp *mctp, mctp_eid_t eid);
+int mctp_smbus_read(struct mctp_binding_smbus *smbus);
+int mctp_smbus_open_bus(struct mctp_binding_smbus *smbus, int out_bus_num,
+ int root_bus_num);
+void mctp_smbus_free(struct mctp_binding_smbus *smbus);
+int mctp_smbus_open_in_bus(struct mctp_binding_smbus *smbus, int in_bus);
+int mctp_smbus_open_out_bus(struct mctp_binding_smbus *smbus, int out_bus);
+int mctp_smbus_set_in_fd(struct mctp_binding_smbus *smbus, int fd);
+int mctp_smbus_set_out_fd(struct mctp_binding_smbus *smbus, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _LIBMCTP_SMBUS_H */
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c
new file mode 100644
index 000000000..2f099a7e5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp/smbus.c
@@ -0,0 +1,467 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef MCTP_HAVE_FILEIO
+#include <fcntl.h>
+#endif
+
+#define pr_fmt(x) "smbus: " x
+
+#include <i2c/smbus.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+
+#include "libmctp-alloc.h"
+#include "libmctp-log.h"
+#include "libmctp-smbus.h"
+#include "libmctp.h"
+
+struct mctp_binding_smbus {
+ struct mctp_binding binding;
+ int out_fd;
+ int in_fd;
+
+ unsigned long bus_id;
+
+ /* receive buffer */
+ uint8_t rxbuf[1024];
+ struct mctp_pktbuf *rx_pkt;
+
+ /* temporary transmit buffer */
+ uint8_t txbuf[256];
+};
+
+#ifndef container_of
+#define container_of(ptr, type, member) \
+ (type *)((char *)(ptr) - (char *)&((type *)0)->member)
+#endif
+
+#define binding_to_smbus(b) container_of(b, struct mctp_binding_smbus, binding)
+
+#define MCTP_COMMAND_CODE 0x0F
+#define MCTP_SLAVE_ADDRESS 0x1d
+#define MCTP_SOURCE_SLAVE_ADDRESS 0x21
+
+#define SMBUS_PEC_BYTE_SIZE 1
+#define SMBUS_COMMAND_CODE_SIZE 1
+#define SMBUS_LENGTH_FIELD_SIZE 1
+#define SMBUS_ADDR_OFFSET_SLAVE 0x1000
+
+struct mctp_smbus_header_tx {
+ uint8_t source_slave_address;
+};
+
+struct mctp_smbus_header_rx {
+ uint8_t destination_slave_address;
+ uint8_t command_code;
+ uint8_t byte_count;
+ uint8_t source_slave_address;
+};
+
+#define POLYCHECK (0x1070U << 3)
+static uint8_t crc8_calculate(uint16_t d)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (d & 0x8000) {
+ d = d ^ POLYCHECK;
+ }
+ d = d << 1;
+ }
+
+ return (uint8_t)(d >> 8);
+}
+
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static uint8_t pec_calculate(uint8_t crc, uint8_t *p, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ crc = crc8_calculate((crc ^ p[i]) << 8);
+ }
+
+ return crc;
+}
+
+static uint8_t calculate_pec_byte(uint8_t *buf, size_t len, uint8_t address,
+ uint16_t flags)
+{
+ uint8_t addr = (address << 1) | (flags & I2C_M_RD ? 1 : 0);
+ uint8_t pec = pec_calculate(0, &addr, 1);
+ pec = pec_calculate(pec, buf, len);
+
+ return pec;
+}
+
+static int mctp_smbus_tx(struct mctp_binding_smbus *smbus, uint8_t len)
+{
+
+#ifdef I2C_M_HOLD
+ /* Hold message */
+ static uint16_t holdtimeout = 1000; // timeout in ms.
+ struct i2c_msg msg[2] =
+#else // !I2C_M_HOLD
+ struct i2c_msg msg[1] =
+#endif // I2C_M_HOLD
+ {{.addr = MCTP_SLAVE_ADDRESS,
+ .flags = 0,
+ .len = len,
+ .buf = (__uint8_t *)smbus->txbuf}
+#ifdef I2C_M_HOLD
+ ,
+ {.addr = 0,
+ .flags = I2C_M_HOLD,
+ .len = sizeof(holdtimeout),
+ .buf = (__uint8_t *)&holdtimeout}
+#endif // I2C_M_HOLD
+ };
+
+#ifdef I2C_M_HOLD
+ struct i2c_rdwr_ioctl_data msgrdwr = {&msg, 2};
+#else // !I2C_M_HOLD
+ struct i2c_rdwr_ioctl_data msgrdwr = {&msg, 1};
+#endif // I2C_M_HOLD
+
+ return ioctl(smbus->out_fd, I2C_RDWR, &msgrdwr);
+}
+
+#ifdef I2C_M_HOLD
+static int mctp_smbus_unhold_bus(struct mctp_binding_smbus *smbus)
+{
+ /* Unhold message */
+ static uint16_t holdtimeout = 0; // unhold
+ struct i2c_msg holdmsg = {0, I2C_M_HOLD, sizeof(holdtimeout),
+ (__uint8_t *)&holdtimeout};
+
+ struct i2c_rdwr_ioctl_data msgrdwr = {&holdmsg, 1};
+
+ return ioctl(smbus->out_fd, I2C_RDWR, &msgrdwr);
+}
+#endif // I2C_M_HOLD
+
+static int mctp_binding_smbus_tx(struct mctp_binding *b,
+ struct mctp_pktbuf *pkt)
+{
+ struct mctp_binding_smbus *smbus = binding_to_smbus(b);
+ struct mctp_smbus_header_tx *hdr;
+ size_t pkt_length;
+
+ uint8_t i2c_message_buf[256];
+ uint8_t *buf_ptr;
+ uint8_t i2c_message_len;
+
+ uint16_t timeout = 1000;
+
+ /* the length field in the header excludes smbus framing
+ * and escape sequences */
+ pkt_length = mctp_pktbuf_size(pkt);
+
+ buf_ptr = (void *)smbus->txbuf;
+ *buf_ptr = MCTP_COMMAND_CODE;
+ buf_ptr++;
+ *buf_ptr = pkt_length + sizeof(*hdr);
+ buf_ptr++;
+
+ hdr = (void *)buf_ptr;
+ hdr->source_slave_address = MCTP_SOURCE_SLAVE_ADDRESS;
+ buf_ptr = (buf_ptr + sizeof(*hdr));
+ memcpy(buf_ptr, &pkt->data[pkt->start], pkt_length);
+ buf_ptr = buf_ptr + pkt_length;
+
+ uint8_t pec_byte = calculate_pec_byte(
+ smbus->txbuf,
+ SMBUS_COMMAND_CODE_SIZE + SMBUS_LENGTH_FIELD_SIZE + sizeof(*hdr)
+ + pkt_length,
+ MCTP_SLAVE_ADDRESS, 0);
+
+ *buf_ptr = pec_byte;
+
+ i2c_message_len = SMBUS_COMMAND_CODE_SIZE + SMBUS_LENGTH_FIELD_SIZE
+ + sizeof(*hdr) + pkt_length
+ + SMBUS_PEC_BYTE_SIZE; // command code, length,
+ // header, data, pec byte
+
+ if (mctp_smbus_tx(smbus, i2c_message_len)) {
+ mctp_prerr("Can't hold mux");
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef MCTP_HAVE_FILEIO
+int mctp_smbus_read(struct mctp_binding_smbus *smbus)
+{
+ ssize_t len = 0;
+ struct mctp_smbus_header_rx *hdr;
+ int ret = 0;
+
+ do {
+ ret = lseek(smbus->in_fd, 0, SEEK_SET);
+ if (ret < 0) {
+ mctp_prerr("Failed to seek");
+ ret = -1;
+ }
+
+ len = read(smbus->in_fd, smbus->rxbuf, sizeof(smbus->rxbuf));
+ if (len < sizeof(*hdr)) {
+ // This condition hits from from time to time, even with
+ // a properly written poll loop, although it's not clear
+ // why. Return an error so that the upper layer can
+ // retry.
+ ret = 0;
+ break;
+ }
+
+ hdr = (void *)smbus->rxbuf;
+ if (hdr->destination_slave_address
+ != (MCTP_SOURCE_SLAVE_ADDRESS & ~1)) {
+ mctp_prerr("Got bad slave address %d",
+ hdr->destination_slave_address);
+ ret = 0;
+ break;
+ }
+ if (hdr->command_code != MCTP_COMMAND_CODE) {
+ mctp_prerr("Got bad command code %d",
+ hdr->command_code);
+ // Not a payload intended for us
+ ret = 0;
+ break;
+ }
+
+ if (hdr->byte_count != (len - sizeof(*hdr))) {
+ // Got an incorrectly sized payload
+ mctp_prerr("Got smbus payload sized %d, expecting %d",
+ hdr->byte_count, len - sizeof(*hdr));
+ ret = 0;
+ break;
+ }
+
+ if (len < 0) {
+ mctp_prerr("can't read from smbus device: %m");
+ ret = -1;
+ break;
+ }
+
+ smbus->rx_pkt = mctp_pktbuf_alloc(&(smbus->binding), 0);
+ assert(smbus->rx_pkt);
+
+ if (mctp_pktbuf_push(smbus->rx_pkt, &smbus->rxbuf[sizeof(*hdr)],
+ len - sizeof(*hdr) - SMBUS_PEC_BYTE_SIZE)
+ != 0) {
+ mctp_prerr("Can't push tok pktbuf: %m");
+ ret = -1;
+ break;
+ }
+
+ mctp_bus_rx(&(smbus->binding), smbus->rx_pkt);
+
+ smbus->rx_pkt = NULL;
+
+ } while (0);
+
+#ifdef I2C_M_HOLD
+ if (mctp_smbus_unhold_bus(smbus)) {
+ mctp_prerr("Can't hold mux");
+ ret = -1;
+ }
+#endif // I2C_M_HOLD
+
+ return ret;
+}
+
+int mctp_smbus_get_in_fd(struct mctp_binding_smbus *smbus)
+{
+ return smbus->in_fd;
+}
+
+
+int mctp_smbus_set_in_fd(struct mctp_binding_smbus *smbus, int fd)
+{
+ smbus->in_fd = fd;
+}
+
+int mctp_smbus_set_out_fd(struct mctp_binding_smbus *smbus, int fd)
+{
+ smbus->out_fd = fd;
+}
+
+int mctp_smbus_get_out_fd(struct mctp_binding_smbus *smbus)
+{
+ return smbus->out_fd;
+}
+
+int mctp_smbus_open_in_bus(struct mctp_binding_smbus *smbus, int in_bus)
+{
+ char filename[60];
+ size_t filename_size = 0;
+ char slave_mqueue[20];
+ size_t mqueue_size = 0;
+ int fd = 0;
+ size_t size = sizeof(filename);
+ int address_7_bit = MCTP_SOURCE_SLAVE_ADDRESS >> 1;
+ int ret = -1;
+
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue", in_bus,
+ in_bus, SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ ret = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ // Device doesn't exist. Create it.
+ filename_size = sizeof(filename);
+ snprintf(filename, filename_size,
+ "/sys/bus/i2c/devices/i2c-%d/new_device", in_bus);
+ filename[filename_size - 1] = '\0';
+
+ fd = open(filename, O_WRONLY);
+ if (fd < 0) {
+ mctp_prerr("can't open root device %s: %m", filename);
+ return -1;
+ }
+
+ mqueue_size = sizeof(slave_mqueue);
+ snprintf(slave_mqueue, mqueue_size, "slave-mqueue %#04x",
+ SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ size = write(fd, slave_mqueue, mqueue_size);
+ close(fd);
+ if (size != mqueue_size) {
+ mctp_prerr("can't create mqueue device on %s: %m", filename);
+ return -1;
+ }
+
+ size = sizeof(filename);
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue", in_bus,
+ in_bus, SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ return open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+}
+
+int mctp_smbus_open_out_bus(struct mctp_binding_smbus *smbus, int out_bus)
+{
+ char filename[60];
+ size_t size = sizeof(filename);
+ snprintf(filename, size, "/dev/i2c-%d", out_bus);
+ filename[size - 1] = '\0';
+
+ return open(filename, O_RDWR | O_NONBLOCK);
+}
+
+/*
+int mctp_smbus_open_bus(struct mctp_binding_smbus *smbus, int out_bus_num,
+ int root_bus_num)
+{
+ char filename[60];
+ size_t filename_size = 0;
+ char slave_mqueue[20];
+ size_t mqueue_size = 0;
+ int fd = 0;
+ size_t size = sizeof(filename);
+ int address_7_bit = MCTP_SOURCE_SLAVE_ADDRESS >> 1;
+
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue",
+ root_bus_num, root_bus_num,
+ SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ smbus->in_fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (smbus->in_fd < 0) {
+ // Device doesn't exist. Create it.
+ filename_size = sizeof(filename);
+ snprintf(filename, filename_size,
+ "/sys/bus/i2c/devices/i2c-%d/new_device",
+ root_bus_num);
+ filename[filename_size - 1] = '\0';
+
+ fd = open(filename, O_WRONLY);
+ if (fd < 0) {
+ mctp_prerr("can't open root device %s: %m", filename);
+ return -1;
+ }
+
+ mqueue_size = sizeof(slave_mqueue);
+ snprintf(slave_mqueue, mqueue_size, "slave-mqueue %#04x",
+ SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ size = write(fd, slave_mqueue, mqueue_size);
+ close(fd);
+ if (size != mqueue_size) {
+ mctp_prerr("can't create mqueue device on %s: %m",
+ filename);
+ return -1;
+ }
+
+ size = sizeof(filename);
+ snprintf(filename, size,
+ "/sys/bus/i2c/devices/i2c-%d/%d-%04x/slave-mqueue",
+ root_bus_num, root_bus_num,
+ SMBUS_ADDR_OFFSET_SLAVE | address_7_bit);
+
+ smbus->in_fd =
+ open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (smbus->in_fd < 0) {
+ mctp_prerr("can't open mqueue device on %s: %m",
+ filename);
+ return -2;
+ }
+ }
+
+ size = sizeof(filename);
+ snprintf(filename, size, "/dev/i2c-%d", out_bus_num);
+ filename[size - 1] = '\0';
+
+ smbus->out_fd = open(filename, O_RDWR | O_NONBLOCK);
+ if (smbus->out_fd < 0) {
+ close(smbus->in_fd);
+ mctp_prerr("can't open device %s: %m", filename);
+ }
+
+ return 0;
+}
+*/
+#endif
+
+void mctp_smbus_register_bus(struct mctp_binding_smbus *smbus,
+ struct mctp *mctp, mctp_eid_t eid)
+{
+ smbus->bus_id = mctp_register_bus(mctp, &smbus->binding, eid);
+ mctp_binding_set_tx_enabled(&smbus->binding, true);
+}
+
+struct mctp_binding_smbus *mctp_smbus_init(void)
+{
+ struct mctp_binding_smbus *smbus;
+
+ smbus = __mctp_alloc(sizeof(*smbus));
+ memset(&(smbus->binding), 0, sizeof(smbus->binding));
+
+ smbus->in_fd = -1;
+ smbus->out_fd = -1;
+
+ smbus->rx_pkt = NULL;
+ smbus->binding.name = "smbus";
+ smbus->binding.version = 1;
+ smbus->binding.pkt_size = sizeof(smbus->rxbuf);
+
+ smbus->binding.tx = mctp_binding_smbus_tx;
+ return smbus;
+}
+
+void mctp_smbus_free(struct mctp_binding_smbus *smbus)
+{
+ __mctp_free(smbus);
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
new file mode 100644
index 000000000..2f3b48cb3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
@@ -0,0 +1,42 @@
+SUMMARY = "libmctp"
+DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
+
+SRC_URI = "git://github.com/openbmc/libmctp.git"
+SRCREV = "f5afcd7e6597dcdeaa475aa7194ecfae2e82d114"
+
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0 | GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=0d30807bb7a4f16d36e96b78f9ed8fae"
+
+inherit cmake
+
+S = "${WORKDIR}/git"
+
+DEPENDS += "i2c-tools"
+
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Smbus-changes-for-libmctp.patch \
+ file://CMakeLists.txt \
+ file://crc32c.c \
+ file://crc32c.h \
+ file://libmctp-smbus.h \
+ file://smbus.c"
+
+do_configure_prepend() {
+ cp -f ${WORKDIR}/*.c ${S}
+ cp -f ${WORKDIR}/*.h ${S}
+ cp -f ${WORKDIR}/CMakeLists.txt ${S}
+}
+
+# linux-libc-headers guides this way to include custom uapi headers
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
new file mode 100644
index 000000000..de57d5e19
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
@@ -0,0 +1,5 @@
+EXTRA_OECMAKE += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-DINTEL_PFR_ENABLED=ON', '', d)}"
+EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMC_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
+EXTRA_OECMAKE += "-DUSING_ENTITY_MANAGER_DECORATORS=OFF"
+SRC_URI = "git://github.com/openbmc/intel-ipmi-oem.git"
+SRCREV = "358e7dfa41d4f297d33670c5caceda3629748cfe"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check.bb b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check.bb
new file mode 100644
index 000000000..955ed1921
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check.bb
@@ -0,0 +1,26 @@
+SUMMARY = "Kernel panic Check"
+DESCRIPTION = "script tool to check if the reboot is caused by kernel panic \
+ log the kernel panic to systemd journal, and also log to redfish \
+ "
+
+S = "${WORKDIR}"
+SRC_URI = "file://kernel-panic-check.sh \
+ file://kernel-panic-check.service \
+"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+RDEPENDS_${PN} += "bash logger-systemd"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/kernel-panic-check.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/kernel-panic-check.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/kernel-panic-check.sh ${D}/${bindir}/kernel-panic-check.sh
+}
+
+SYSTEMD_SERVICE_${PN} += " kernel-panic-check.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.service b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.service
new file mode 100644
index 000000000..afe017baf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Check for kernel panic
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/kernel-panic-check.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.sh b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.sh
new file mode 100755
index 000000000..815f50b71
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/kernel-panic-check/kernel-panic-check/kernel-panic-check.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+panicFile="/sys/fs/pstore/dmesg-ramoops-0"
+if [ -f $panicFile ]
+then
+ # log the detailed last kernel panic messages
+ logger -t kernel-panic-check "Reboot from kernel panic! Log as following:"
+ cat $panicFile | logger
+ # Also log it to redfish
+ cat <<EOF | logger-systemd --journald
+REDFISH_MESSAGE_ID=OpenBMC.0.1.BMCKernelPanic
+PRIORITY=4
+MESSAGE=BMC rebooted due to kernel panic
+EOF
+
+ rm -rf $panicFile
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-core/libpeci/libpeci_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/libpeci/libpeci_%.bbappend
new file mode 100644
index 000000000..ba549b324
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/libpeci/libpeci_%.bbappend
@@ -0,0 +1,3 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/libpeci"
+SRCREV = "a2ceec2aa139277cebb62e1eda449ef60fa4c962"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/libxcrypt/libxcrypt_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/libxcrypt/libxcrypt_%.bbappend
new file mode 100644
index 000000000..ee414efb8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/libxcrypt/libxcrypt_%.bbappend
@@ -0,0 +1,5 @@
+# libxcrypt fails to compile under gcc with the -Os flag. Because we want to
+# be able to compile the rest of the system with -Os, override the global
+# setting here to fall back to -O3
+CFLAGS_append = "--param max-inline-insns-single=1000"
+FULL_OPTIMIZATION = "-O3 -pipe ${DEBUG_FLAGS}"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd.inc b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd.inc
new file mode 100644
index 000000000..abad9d12d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd.inc
@@ -0,0 +1,43 @@
+SUMMARY = "logger tool in util-linux with systemd support"
+HOMEPAGE = "http://userweb.kernel.org/~kzak/util-linux/"
+DESCRIPTION = "logger tool with systemd support, used to add log to systemd journald."
+
+SECTION = "base"
+
+LICENSE = "GPLv2+ & LGPLv2.1+ & BSD-3-Clause & BSD-4-Clause"
+
+LIC_FILES_CHKSUM = "file://README.licensing;md5=972a134f1e14b2b060e365df2fab0099 \
+ file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+ file://Documentation/licenses/COPYING.GPL-2.0-or-later;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+ file://Documentation/licenses/COPYING.LGPL-2.1-or-later;md5=4fbd65380cdd255951079008b364516c \
+ file://Documentation/licenses/COPYING.BSD-3-Clause;md5=58dcd8452651fc8b07d1f65ce07ca8af \
+ file://Documentation/licenses/COPYING.BSD-4-Clause-UC;md5=263860f8968d8bafa5392cab74285262 \
+ file://libuuid/COPYING;md5=6d2cafc999feb2c2de84d4d24b23290c \
+ file://libmount/COPYING;md5=7c7e39fb7d70ffe5d693a643e29987c2 \
+ file://libblkid/COPYING;md5=693bcbbe16d3a4a4b37bc906bc01cc04"
+
+inherit autotools gettext pkgconfig
+DEPENDS = "libcap-ng ncurses virtual/crypt zlib systemd "
+#DEPENDS_intel-ast2500 += " systemd "
+#RDEPENDS_${PN} += " libsystemd"
+
+MAJOR_VERSION = "${@'.'.join(d.getVar('PV').split('.')[0:2])}"
+SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-linux-${MAJOR_VERSION}.tar.xz \
+ "
+
+S = "${WORKDIR}/util-linux-${MAJOR_VERSION}"
+
+EXTRA_OECONF = " --disable-nls --disable-all-programs \
+ --disable-libuuid --disable-libblkid --disable-libmount \
+ --disable-libsmartcols --disable-libfdisk --disable-pylibmount \
+ --with-systemd \
+ --enable-logger \
+ "
+
+do_install_append () {
+ mv ${D}${bindir}/logger ${D}${bindir}/logger-systemd
+ rm -rf ${D}${sbindir}
+ rm -rf ${D}${base_libdir}
+ rm -rf ${D}${libdir}
+ rm -rf ${D}${datadir}
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/avoid_parallel_tests.patch b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/avoid_parallel_tests.patch
new file mode 100644
index 000000000..748b6ef09
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/avoid_parallel_tests.patch
@@ -0,0 +1,20 @@
+Ptest needs buildtest-TESTS and runtest-TESTS targets.
+serial-tests is required to generate those targets.
+Revert run.sh script accordingly to serialize running tests
+
+Signed-off-by: Tudor Florea <tudor.florea@enea.com>
+Upstream-Status: Inappropriate
+
+Index: util-linux-2.32/configure.ac
+===================================================================
+--- util-linux-2.32.orig/configure.ac
++++ util-linux-2.32/configure.ac
+@@ -11,7 +11,7 @@ AC_CONFIG_MACRO_DIR([m4])
+ dnl AC_USE_SYSTEM_EXTENSIONS must be called before any macros that run
+ dnl the compiler (like AC_PROG_LIBTOOL) to avoid autoconf errors.
+ AC_USE_SYSTEM_EXTENSIONS
+-AM_INIT_AUTOMAKE([-Wall foreign 1.10 tar-pax no-dist-gzip dist-xz subdir-objects])
++AM_INIT_AUTOMAKE([-Wall foreign 1.10 tar-pax no-dist-gzip dist-xz subdir-objects serial-tests])
+
+ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
+ [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/configure-sbindir.patch b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/configure-sbindir.patch
new file mode 100644
index 000000000..e475289f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/configure-sbindir.patch
@@ -0,0 +1,23 @@
+util-linux: take ${sbindir} from the environment if it is set there
+fix the test, the [ ] syntax was getting eaten by autoconf
+
+Signed-off-by: Phil Blundell <pb@pbcl.net>
+Signed-off-by: Saul Wold <sgw@linux.intel.com
+Upstream-Status: Inappropriate [configuration]
+
+Index: util-linux-2.31/configure.ac
+===================================================================
+--- util-linux-2.31.orig/configure.ac
++++ util-linux-2.31/configure.ac
+@@ -89,7 +89,10 @@ AC_SUBST([runstatedir])
+ usrbin_execdir='${exec_prefix}/bin'
+ AC_SUBST([usrbin_execdir])
+
+-usrsbin_execdir='${exec_prefix}/sbin'
++if test -z "$usrsbin_execdir" ;
++then
++ usrsbin_execdir='${exec_prefix}/sbin'
++fi
+ AC_SUBST([usrsbin_execdir])
+
+ AS_CASE([$libdir],
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/display_testname_for_subtest.patch b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/display_testname_for_subtest.patch
new file mode 100644
index 000000000..417ca1d98
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/display_testname_for_subtest.patch
@@ -0,0 +1,25 @@
+Display testname for subtest
+
+Signed-off-by: Tudor Florea <tudor.florea@enea.com>
+Upstream-Status: Pending
+
+---
+ tests/functions.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/functions.sh b/tests/functions.sh
+index 5246605..b24dc15 100644
+--- a/tests/functions.sh
++++ b/tests/functions.sh
+@@ -320,7 +320,7 @@ function ts_init_subtest {
+
+ if [ "$TS_PARSABLE" != "yes" ]; then
+ [ $TS_NSUBTESTS -eq 1 ] && echo
+- printf "%16s: %-27s ..." "" "$TS_SUBNAME"
++ printf "%13s: %-30s ..." "$TS_COMPONENT" "$TS_SUBNAME"
+ fi
+ }
+
+--
+2.8.3
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/ptest.patch b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/ptest.patch
new file mode 100644
index 000000000..0537f7d85
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/ptest.patch
@@ -0,0 +1,23 @@
+Define TESTS variable
+
+Signed-off-by: Tudor Florea <tudor.florea@enea.com>
+Upstream-Status: Pending
+---
+ Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Makefile.am b/Makefile.am
+index bbaccb1..7d5a6bb 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -48,6 +48,7 @@ systemdsystemunit_DATA =
+ dist_bashcompletion_DATA =
+ check_PROGRAMS =
+ dist_check_SCRIPTS =
++TESTS = $(check_PROGRAMS)
+
+ PATHFILES =
+
+--
+2.8.3
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/run-ptest b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/run-ptest
new file mode 100644
index 000000000..e135ee583
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/run-ptest
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+
+# When udevd (from eudev) is running most eject/mount tests will fail because
+# of automount. We need to stop udevd before executing util-linux's tests.
+# The systemd-udevd daemon doesn't change the outcome of util-linux's tests.
+UDEV_PID="`pidof "@base_sbindir@/udevd"`"
+if [ "x$UDEV_PID" != "x" ]; then
+ /etc/init.d/udev stop
+fi
+
+current_path=$(readlink -f $0)
+export bindir=$(dirname $current_path)
+export PATH=$bindir/bin:$PATH
+
+cd tests || exit 1
+
+comps=$(find ts/ -type f -perm -111 -regex ".*/[^\.~]*" | sort)
+
+
+echo
+echo "-------------------- util-linux regression tests --------------------"
+echo
+echo " For development purpose only. "
+echo " Don't execute on production system! "
+echo
+
+res=0
+count=0
+for ts in $comps;
+do
+ $ts | sed -u '{
+ s/^\(.*\):\(.*\) \.\.\. OK$/PASS: \1:\2/
+ s/^\(.*\):\(.*\) \.\.\. FAILED \(.*\)$/FAIL: \1:\2 \3/
+ s/^\(.*\):\(.*\) \.\.\. SKIPPED \(.*\)$/SKIP: \1:\2 \3/
+ }'
+done
+
+
+if [ "x$UDEV_PID" != "x" ]; then
+ /etc/init.d/udev start
+fi
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser-l.pamd b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser-l.pamd
new file mode 100644
index 000000000..4b368ccf5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser-l.pamd
@@ -0,0 +1,3 @@
+auth include runuser
+session optional pam_keyinit.so force revoke
+session include runuser
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser.pamd b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser.pamd
new file mode 100644
index 000000000..48d133b9e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd/runuser.pamd
@@ -0,0 +1,4 @@
+auth sufficient pam_rootok.so
+session optional pam_keyinit.so revoke
+session required pam_limits.so
+session required pam_unix.so
diff --git a/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd_2.34.bb b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd_2.34.bb
new file mode 100644
index 000000000..b58628667
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/logger-systemd/logger-systemd_2.34.bb
@@ -0,0 +1,12 @@
+require logger-systemd.inc
+
+SRC_URI += "file://configure-sbindir.patch \
+ file://runuser.pamd \
+ file://runuser-l.pamd \
+ file://ptest.patch \
+ file://run-ptest \
+ file://display_testname_for_subtest.patch \
+ file://avoid_parallel_tests.patch \
+"
+SRC_URI[md5sum] = "a78cbeaed9c39094b96a48ba8f891d50"
+SRC_URI[sha256sum] = "743f9d0c7252b6db246b659c1e1ce0bd45d8d4508b4dfa427bbb4a3e9b9f62b5" \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-core/microsoft-gsl/microsoft-gsl.bb b/meta-openbmc-mods/meta-common/recipes-core/microsoft-gsl/microsoft-gsl.bb
new file mode 100644
index 000000000..f8e5505ef
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/microsoft-gsl/microsoft-gsl.bb
@@ -0,0 +1,24 @@
+# Add GSL: Guideline Support Library for c++
+# https://github.com/Microsoft/GSL
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=363055e71e77071107ba2bb9a54bd9a7"
+
+SRC_URI = "git://github.com/Microsoft/GSL.git;protocol=https;nobranch=1"
+
+# Modify these as desired
+PV = "1.0+git${SRCPV}"
+#SRCREV = "${AUTOREV}"
+SRCREV = "be43c79742dc36ee55b21c5d531a5ff301d0ef8d"
+
+S = "${WORKDIR}/git"
+
+do_install () {
+ install -d ${D}/usr/include
+ install -d ${D}/usr/include/gsl
+ for F in ${S}/include/gsl/*; do
+ install -m 0644 ${F} ${D}/usr/include/gsl
+ done
+}
+
+ALLOW_EMPTY_${PN} = "1"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service
new file mode 100644
index 000000000..bad3329d3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync/nv-sync.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Overlay sync to NV storage
+
+[Service]
+# Run rsync periodically to sync the overlay to NV storage
+ExecStart=bash -c 'while true; do rsync -a --delete /tmp/.overlay/ /tmp/.rwfs/.overlay; sync /tmp/.rwfs/.overlay; sleep 10; done'
+# On shutdown, archive the bash history so we don't lose it and run one last sync
+ExecStop=bash -c 'history -a; rsync -a --delete /tmp/.overlay/ /tmp/.rwfs/.overlay; sync /tmp/.rwfs/.overlay; sleep 5'
+# Due to sync delay stopping this service will take more than default 10 seconds
+TimeoutStopSec=20
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb
new file mode 100644
index 000000000..0ee70e880
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/nv-sync/nv-sync_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "NV Overlay Sync"
+DESCRIPTION = "Script to periodically sync the overlay to NV storage"
+
+S = "${WORKDIR}"
+SRC_URI = "file://nv-sync.service \
+"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/nv-sync.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/nv-sync.service ${D}${systemd_system_unitdir}
+}
+
+SYSTEMD_SERVICE_${PN} += " nv-sync.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/os-release/os-release.bbappend b/meta-openbmc-mods/meta-common/recipes-core/os-release/os-release.bbappend
new file mode 100644
index 000000000..a47d923f8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/os-release/os-release.bbappend
@@ -0,0 +1,34 @@
+# WARNING!
+#
+# These modifications to os-release disable the bitbake parse
+# cache (for the os-release recipe only). Before copying
+# and pasting into another recipe ensure it is understood
+# what that means!
+
+require version-vars.inc
+
+OS_RELEASE_FIELDS_append = " OPENBMC_VERSION IPMI_MAJOR IPMI_MINOR IPMI_AUX13 IPMI_AUX14 IPMI_AUX15 IPMI_AUX16"
+
+python do_compile_append () {
+ import glob
+ with open(d.expand('${B}/os-release'), 'a') as f:
+ corebase = d.getVar('COREBASE', True)
+ f.write('\n# Build Configuration Details\n')
+ repo_status(d, f, corebase, '')
+ repo_status(d, f, os.path.join(corebase, 'meta-openbmc-mods'), '--tags')
+ appends_dir = os.path.join(d.getVar('TOPDIR', True), 'workspace', 'appends')
+
+ for fn in glob.glob(os.path.join(appends_dir, '*.bbappend')):
+ with open(fn, 'r') as bb_f:
+ for line in bb_f:
+ if line.startswith('# srctreebase: '):
+ srctreebase = line.split(':', 1)[1].strip()
+ repo_status(d, f, srctreebase, '--tags')
+}
+
+
+# Ensure the git commands run every time bitbake is invoked.
+BB_DONT_CACHE = "1"
+
+# Make os-release available to other recipes.
+SYSROOT_DIRS_append = " ${sysconfdir}"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc b/meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc
new file mode 100644
index 000000000..95061a570
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc
@@ -0,0 +1,81 @@
+def irun_git(d, oeroot, git_cmd, **kwargs):
+ err = None
+ try:
+ cmd = 'git --work-tree {} --git-dir {}/.git {}'.format(oeroot, oeroot, git_cmd)
+ ret, err = bb.process.run(cmd, **kwargs)
+ if err is not None:
+ ret += err
+ except bb.process.ExecutionError as e:
+ ret = ''
+ if e.stdout is not None:
+ ret += e.stdout
+ if e.stderr is not None:
+ ret += e.stderr
+ except Exception as e:
+ ret = str(e)
+ return ret.strip('\n')
+
+def repo_status(d, f, repo, tagargs):
+ import subprocess
+
+ cmd_list = [['HEAD', 'rev-parse HEAD'],
+ ['TAG', 'describe {} --dirty --long'.format(tagargs)],
+ ['STATUS', 'status -sb']]
+
+ f.write(('\n# REPOSITORY: {} '.format(os.path.basename(repo))).ljust(80, '+') + '\n')
+ for item in cmd_list:
+ f.write('# {}: '.format(item[0]))
+ sb = irun_git(d, repo, item[1])
+ if sb:
+ sb_lines = sb.split('\n')
+ if len(sb_lines) == 1:
+ f.write(sb_lines[0])
+ else:
+ f.write('\n# ' + '\n# '.join(sb_lines))
+ f.write('\n')
+
+python() {
+ import re
+
+ gen = d.getVar('PRODUCT_GENERATION', True)
+ if gen is None:
+ gen = 'unknown'
+
+ corebase = d.getVar('COREBASE', True)
+ mibase = os.path.join(corebase, 'meta-openbmc-mods')
+ obmc_vers = irun_git(d, corebase, 'describe --dirty --long')
+ if obmc_vers is None:
+ raise bb.build.FuncFailed("Missing version tag for openbmc-openbmc")
+ d.setVar('OPENBMC_VERSION', obmc_vers)
+
+ obmc_hash = irun_git(d, corebase, 'rev-parse HEAD')
+ meta_vers = irun_git(d, mibase,
+ 'describe --long --abbrev=6 ' +
+ '--match \'{}-[0-9]*\.[0-9]*\''.format(gen))
+
+ # If no tag in meta-openbmc-mods, provide default version
+ if meta_vers.startswith('fatal:'):
+ meta_vers = '{}-0.0-0'.format(gen)
+
+ meta_hash = irun_git(d, mibase, 'rev-parse HEAD')
+ # If no hash from meta-openbmc-mods, provide default
+ if meta_hash.startswith('fatal:'):
+ meta_hash = '00000000'
+ version_id = '{}-{}'.format(meta_vers, obmc_hash[0:7])
+ if version_id:
+ d.setVar('VERSION_ID', version_id)
+ versionList = version_id.split('-')
+ versionList = re.split('-|\.', version_id)
+ version = '{}.{}-{}'.format(versionList[0], versionList[1], versionList[2])
+ d.setVar('VERSION', version)
+ d.setVar('IPMI_MAJOR', versionList[1])
+ d.setVar('IPMI_MINOR', versionList[2])
+ d.setVar('IPMI_AUX13', hex(min(int(versionList[3]), 0xff)))
+ d.setVar('IPMI_AUX14', '0x{}'.format(meta_hash[0:2]))
+ d.setVar('IPMI_AUX15', '0x{}'.format(meta_hash[2:4]))
+ d.setVar('IPMI_AUX16', '0x{}'.format(meta_hash[4:6]))
+
+ build_id = irun_git(d, mibase, 'describe --abbrev=0')
+ if build_id:
+ d.setVar('BUILD_ID', build_id)
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/packagegroups/packagegroup-core-standalone-sdk-target.bbappend b/meta-openbmc-mods/meta-common/recipes-core/packagegroups/packagegroup-core-standalone-sdk-target.bbappend
new file mode 100644
index 000000000..87a4c8503
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/packagegroups/packagegroup-core-standalone-sdk-target.bbappend
@@ -0,0 +1 @@
+RRECOMMENDS_${PN}_append = " vim cmake sdbusplus"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb b/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb
new file mode 100644
index 000000000..4bf1c9548
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb
@@ -0,0 +1,24 @@
+# NOTE: LICENSE is being set to "CLOSED" for now. The PCIe reads over PECI expose
+# more information than is accessible from the BIOS or OS, so we need to keep this
+# internal to Intel until it's resolved.
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = ""
+inherit cmake systemd
+
+SRC_URI = "git://github.com/Intel-BMC/at-scale-debug;protocol=ssh"
+
+DEPENDS = "boost sdbusplus libpeci"
+
+PV = "0.1+git${SRCPV}"
+SRCREV = "98c33cdb7d704a387edee4ac8f0ef98ea771b222"
+
+S = "${WORKDIR}/git/peci_pcie"
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.PCIe.service"
+
+# linux-libc-headers guides this way to include custom uapi headers
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include"
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/readline/readline/inputrc b/meta-openbmc-mods/meta-common/recipes-core/readline/readline/inputrc
new file mode 100644
index 000000000..7b84c9916
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/readline/readline/inputrc
@@ -0,0 +1,61 @@
+# /etc/inputrc - global inputrc for libreadline
+# See readline(3readline) and `info rluserman' for more information.
+
+# Be 8 bit clean.
+set input-meta on
+set output-meta on
+
+# To allow the use of 8bit-characters like the german umlauts, comment out
+# the line below. However this makes the meta key not work as a meta key,
+# which is annoying to those which don't need to type in 8-bit characters.
+
+# set convert-meta off
+
+# try to enable the application keypad when it is called. Some systems
+# need this to enable the arrow keys.
+# set enable-keypad on
+
+# see /usr/share/doc/bash/inputrc.arrows for other codes of arrow keys
+
+# do not bell on tab-completion
+# set bell-style none
+
+# some defaults / modifications for the emacs mode
+$if mode=emacs
+
+# allow the use of the Home/End keys
+ "\e[1~": beginning-of-line
+ "\e[4~": end-of-line
+
+# allow the use of the Delete/Insert keys
+ "\e[3~": delete-char
+# "\e[2~": quoted-insert
+
+# mappings for "page up" and "page down" to step to the beginning/end
+# of the history
+# "\e[5~": beginning-of-history
+# "\e[6~": end-of-history
+
+# alternate mappings for "page up" and "page down" to search the history
+# "\e[5~": history-search-backward
+# "\e[6~": history-search-forward
+
+# # mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving
+# "\e[5C": forward-word
+# "\e[5D": backward-word
+# "\e\e[C": forward-word
+# "\e\e[D": backward-word
+
+# $if term=rxvt
+# "\e[8~": end-of-line
+# $endif
+
+# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
+# "\eOH": beginning-of-line
+# "\eOF": end-of-line
+
+# for freebsd console
+# "\e[H": beginning-of-line
+# "\e[F": end-of-line
+
+$endif
diff --git a/meta-openbmc-mods/meta-common/recipes-core/readline/readline_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/readline/readline_%.bbappend
new file mode 100644
index 000000000..c63a45dd4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/readline/readline_%.bbappend
@@ -0,0 +1,2 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI_append = " file://inputrc"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/rest-dbus/rest-dbus-static.bb b/meta-openbmc-mods/meta-common/recipes-core/rest-dbus/rest-dbus-static.bb
new file mode 100644
index 000000000..429d5b4b4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/rest-dbus/rest-dbus-static.bb
@@ -0,0 +1,23 @@
+SUMMARY = "Phosphor OpenBMC REST framework"
+DESCRIPTION = "Phosphor OpenBMC REST to DBUS daemon."
+HOMEPAGE = "http://github.com/openbmc/rest-dbus"
+PR = "r1"
+
+inherit allarch
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI += "git://github.com/openbmc/rest-dbus.git"
+
+SRCREV = "9273a302e8f2b3c3e939dff77758e90f163bf6a1"
+
+S = "${WORKDIR}/git"
+
+FILES_${PN} += "${datadir}/www/rest-dbus/*"
+
+do_install () {
+ install -d ${D}${datadir}/www/rest-dbus/res
+ install -m 644 ${S}/resources/** ${D}${datadir}/www/rest-dbus/res
+ install -m 644 ${S}/resources/index.html ${D}${datadir}/www/rest-dbus/index.html
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/safec/safec_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_%.bbappend
new file mode 100644
index 000000000..4ce29534d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_%.bbappend
@@ -0,0 +1,11 @@
+RDEPENDS_${PN} = ""
+do_install_append() {
+ F=$(find ${D} -name check_for_unsafe_apis)
+ if [ -n "${F}" ]; then
+ # remove the unused perl script
+ rm -f "${F}"
+ # remove the script's destination directory, only if it is empty
+ rmdir "$(dirname ${F})" 2>/dev/null || :
+ fi
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb
new file mode 100644
index 000000000..449dcf04d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb
@@ -0,0 +1,15 @@
+SUMMARY = "Safe C Library"
+
+LICENSE = "safec"
+LIC_FILES_CHKSUM = "file://COPYING;md5=6d0eb7dfc57806a006fcbc4e389cf164"
+SECTION = "lib"
+
+inherit autotools pkgconfig
+
+S = "${WORKDIR}/git"
+SRCREV = "a7da29dadadde04feec174f595b59d67a64f3956"
+SRC_URI = "git://github.com/rurban/safeclib.git"
+
+COMPATIBLE_HOST = '(x86_64|i.86|powerpc|powerpc64|arm|aarch64).*-linux'
+
+RDEPENDS_${PN} = "perl"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check.bb b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check.bb
new file mode 100644
index 000000000..cfea1a910
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check.bb
@@ -0,0 +1,26 @@
+SUMMARY = "Security registers check"
+DESCRIPTION = "script tool to check if registers value are security \
+ log the security event to systemd journal, and also log to redfish \
+ "
+
+S = "${WORKDIR}"
+SRC_URI = "file://security-registers-check.sh \
+ file://security-registers-check.service \
+"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+RDEPENDS_${PN} += "bash logger-systemd"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/security-registers-check.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/security-registers-check.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/security-registers-check.sh ${D}/${bindir}/security-registers-check.sh
+}
+
+SYSTEMD_SERVICE_${PN} += " security-registers-check.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.service b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.service
new file mode 100644
index 000000000..b824dbe3e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Check for security registers
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/security-registers-check.sh
+Nice=5
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.sh b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.sh
new file mode 100644
index 000000000..211120c78
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/security-registers-check/security-registers-check/security-registers-check.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+value=`cat /sys/devices/platform/ahb/ahb:apb/1e6e2000.syscon/1e6e2000.syscon:misc_control/uart_port_debug`
+if [ $value == 0 ]
+ then
+ # log the detailed last security registers check messages
+ logger -t security-registers-check "Uart port debug is enabled! Log as following:"
+ echo "Uart port debug is enabled." | logger
+ # Also log it to redfish
+ cat <<EOF | logger-systemd --journald
+REDFISH_MESSAGE_ID=OpenBMC.0.1.SecurityUartPortDebugEnabled
+PRIORITY=4
+MESSAGE=BMC Uart port debug is enabled
+EOF
+fi
+
+value=`cat /sys/devices/platform/ahb/ahb:apb/1e6e2000.syscon/1e6e2000.syscon:misc_control/p2a-bridge`
+if [ $value == 1 ]
+ then
+ # log the detailed last security registers check messages
+ logger -t security-registers-check "P2A(PCIe to AHB) bridge is enabled! Log as following:"
+ echo "P2A(PCIe to AHB) bridge is enabled." | logger
+ # Also log it to redfish
+ cat <<EOF | logger-systemd --journald
+REDFISH_MESSAGE_ID=OpenBMC.0.1.SecurityP2aBridgeEnabled
+PRIORITY=4
+MESSAGE=BMC P2A(PCIe to AHB) bridge is enabled
+EOF
+fi
+
+value=`cat /sys/devices/platform/ahb/ahb:apb/1e6e2000.syscon/1e6e2000.syscon:misc_control/boot-2nd-flash`
+if [ $value == 1 ]
+ then
+ # log the detailed last security registers check messages
+ logger -t security-registers-check "BMC 2nd boot flash is enabled! Log as following:"
+ echo "BMC 2nd boot flash is enabled." | logger
+ # Also log it to redfish
+ cat <<EOF | logger-systemd --journald
+REDFISH_MESSAGE_ID=OpenBMC.0.1.SecurityBoot2ndFlashEnabled
+PRIORITY=4
+MESSAGE=BMC 2nd boot flash is enabled
+EOF
+fi
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/obmc-targets.bbappend b/meta-openbmc-mods/meta-common/recipes-core/systemd/obmc-targets.bbappend
new file mode 100644
index 000000000..3d4e594a4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/obmc-targets.bbappend
@@ -0,0 +1,10 @@
+# Remove these files since they are provided by obmc-intel-targets
+SYSTEMD_SERVICE_${PN}_remove += " obmc-host-start@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-host-stop@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-host-shutdown@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-host-reboot@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-host-startmin@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-chassis-poweron@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-chassis-poweroff@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-chassis-hard-poweroff@.target"
+SYSTEMD_SERVICE_${PN}_remove += " obmc-chassis-powerreset@.target"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/journald.conf b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/journald.conf
new file mode 100644
index 000000000..48c60d36b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/journald.conf
@@ -0,0 +1,42 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# Entries in this file show the compile time defaults.
+# You can change settings by editing this file.
+# Defaults can be restored by simply deleting this file.
+#
+# See journald.conf(5) for details.
+
+[Journal]
+Storage=volatile
+#Compress=yes
+#Seal=yes
+#SplitMode=uid
+#SyncIntervalSec=5m
+#RateLimitIntervalSec=30s
+#RateLimitBurst=10000
+#SystemMaxUse=6M
+#SystemKeepFree=
+#SystemMaxFileSize=512K
+#SystemMaxFiles=32
+RuntimeMaxUse=32M
+#RuntimeKeepFree=
+#RuntimeMaxFileSize=
+#RuntimeMaxFiles=4
+#MaxRetentionSec=
+#MaxFileSec=1month
+#ForwardToSyslog=no
+#ForwardToKMsg=no
+#ForwardToConsole=no
+#ForwardToWall=yes
+#TTYPath=/dev/console
+#MaxLevelStore=notice
+#MaxLevelSyslog=debug
+#MaxLevelKMsg=notice
+#MaxLevelConsole=info
+#MaxLevelWall=emerg
+#LineMax=48K
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/systemd-timesyncd-save-time.conf b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/systemd-timesyncd-save-time.conf
new file mode 100644
index 000000000..aa455cbcb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf/systemd-timesyncd-save-time.conf
@@ -0,0 +1,2 @@
+[Service]
+ExecStop=touch /var/lib/systemd/timesync/clock \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf_%.bbappend
new file mode 100644
index 000000000..b3c318e15
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd-conf_%.bbappend
@@ -0,0 +1,11 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://journald.conf \
+ file://systemd-timesyncd-save-time.conf \
+ "
+
+FILES_${PN} += " ${systemd_system_unitdir}/systemd-timesyncd.service.d/systemd-timesyncd-save-time.conf"
+
+do_install_append() {
+ install -m 644 -D ${WORKDIR}/systemd-timesyncd-save-time.conf ${D}${systemd_system_unitdir}/systemd-timesyncd.service.d/systemd-timesyncd-save-time.conf
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch
new file mode 100644
index 000000000..5b9f17006
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch
@@ -0,0 +1,28 @@
+From e02932693f92d6230b5520f431e127f7b6e2183e Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Tue, 6 Mar 2018 16:06:33 -0800
+Subject: [PATCH 1/1] Modfiy system.conf DefaultTimeoutStopSec
+
+Current time is 5 minutes, change it to 10 seconds.
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ src/core/system.conf.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/system.conf.in b/src/core/system.conf.in
+index 8112125468..f7a35a56bb 100644
+--- a/src/core/system.conf.in
++++ b/src/core/system.conf.in
+@@ -39,7 +39,7 @@
+ #DefaultStandardOutput=journal
+ #DefaultStandardError=inherit
+ #DefaultTimeoutStartSec=90s
+-#DefaultTimeoutStopSec=90s
++DefaultTimeoutStopSec=10s
+ #DefaultTimeoutAbortSec=
+ #DefaultRestartSec=100ms
+ #DefaultStartLimitIntervalSec=10s
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0002-Disable-LLMNR-port-5355.patch b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0002-Disable-LLMNR-port-5355.patch
new file mode 100644
index 000000000..8b978e4fb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0002-Disable-LLMNR-port-5355.patch
@@ -0,0 +1,26 @@
+From 9fb05323291ccdfbf19ac0d9428e366d6023b408 Mon Sep 17 00:00:00 2001
+From: Karthick Sundarrajan <karthick.sundarrajan@intel.com>
+Date: Fri, 3 Apr 2020 10:23:41 -0700
+Subject: [PATCH] Disable LLMNR (port 5355)
+
+As part of OS hardening process, the port has to be
+disabled.
+
+Signed-off-by: Karthick Sundarrajan <karthick.sundarrajan@intel.com>
+---
+ src/resolve/resolved.conf.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
+index 6898c78..a9125fd 100644
+--- a/src/resolve/resolved.conf.in
++++ b/src/resolve/resolved.conf.in
+@@ -15,7 +15,7 @@
+ #DNS=
+ #FallbackDNS=@DNS_SERVERS@
+ #Domains=
+-#LLMNR=yes
++LLMNR=no
+ #MulticastDNS=yes
+ #DNSSEC=@DEFAULT_DNSSEC_MODE@
+ #DNSOverTLS=@DEFAULT_DNS_OVER_TLS_MODE@
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-time-wait-sync.service b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-time-wait-sync.service
new file mode 100644
index 000000000..f71aea39d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-time-wait-sync.service
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Wait Until Kernel Time Synchronized
+Documentation=man:systemd-time-wait-sync.service(8)
+
+# Note that this tool doesn't need CAP_SYS_TIME itself, but it's primary
+# usecase is to run in conjunction with a local NTP service such as
+# systemd-timesyncd.service, which is conditioned this way. There might be
+# niche usecases where running this service independently is desired, but let's
+# make this all "just work" for the general case, and leave it to local
+# modifications to make it work in the remaining cases.
+
+ConditionCapability=CAP_SYS_TIME
+ConditionVirtualization=!container
+
+DefaultDependencies=no
+Before=time-sync.target shutdown.target
+Wants=time-sync.target
+Conflicts=shutdown.target
+
+[Service]
+Type=oneshot
+ExecStart=/lib/systemd/systemd-time-wait-sync
+TimeoutStartSec=10
+RemainAfterExit=yes
+
+[Install]
+WantedBy=sysinit.target
diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend
new file mode 100644
index 000000000..17f423dc3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend
@@ -0,0 +1,16 @@
+# add some configuration overrides for systemd default /usr/lib/tmpfiles.d/
+
+LICENSE = "GPL-2.0"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch \
+ file://0002-Disable-LLMNR-port-5355.patch \
+ file://systemd-time-wait-sync.service \
+ "
+
+USERADD_PACKAGES_remove = "${PN}-journal-gateway ${PN}-journal-upload ${PN}-journal-remote"
+
+do_install_append(){
+ cp -f ${WORKDIR}/systemd-time-wait-sync.service ${D}/lib/systemd/system/
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb b/meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb
new file mode 100644
index 000000000..32bfba4b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb
@@ -0,0 +1,21 @@
+DESCRIPTION = "OpenBMC mtd-util"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b77c43ae4eaf67bd73fb6452b2f113a3"
+
+SRC_URI = "git://github.com/Intel-BMC/mtd-util;protocol=ssh"
+
+PV = "1.0+git${SRCPV}"
+SRCREV = "69016601a521a95732cc49a3f4c8c7fe4b0ee058"
+
+
+S = "${WORKDIR}/git"
+
+DEPENDS += "dbus systemd sdbusplus openssl zlib boost microsoft-gsl i2c-tools"
+
+inherit cmake pkgconfig
+
+# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
+EXTRA_OECMAKE = ""
+
+EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', '-DDEVELOPER_OPTIONS=ON', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-devtools/python/python_%.bbappend b/meta-openbmc-mods/meta-common/recipes-devtools/python/python_%.bbappend
new file mode 100644
index 000000000..00815c173
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-devtools/python/python_%.bbappend
@@ -0,0 +1,7 @@
+# This commit pulls in the python world, and adds a very large chunk to our
+# image size. I suspect we can make most of our things rely on python-core
+# instead of full python, but this is a temporary fix.
+# https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?id=f384e39ad1ca1514fb7b5d7fa0d63e0c863761ca
+
+RPROVIDES_${PN}-core = "${PN}"
+RPROVIDES_${PN}-modules = ""
diff --git a/meta-openbmc-mods/meta-common/recipes-devtools/template-recipe/template-recipe.bb b/meta-openbmc-mods/meta-common/recipes-devtools/template-recipe/template-recipe.bb
new file mode 100644
index 000000000..50476715e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-devtools/template-recipe/template-recipe.bb
@@ -0,0 +1,18 @@
+SUMMARY = "HelloWorld app with phosphor-logging usage example."
+DESCRIPTION = "NOTE: Phosphor-logging has dependencies on systemd and sdbusplus."
+
+SRC_URI = "git://github.com/Intel-BMC/template-recipe;protocol=ssh"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+# Modify these as desired
+PV = "1.0+git${SRCPV}"
+SRCREV = "2d5d731254319de8b42d6438b0ce3908dd5b0dec"
+
+S = "${WORKDIR}/git"
+
+inherit cmake
+
+DEPENDS = "systemd sdbusplus phosphor-logging"
+RDEPENDS_${PN} = "libsystemd sdbusplus phosphor-logging"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/pam-ipmi_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/pam/pam-ipmi_%.bbappend
new file mode 100644
index 000000000..08f8c58b0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/pam-ipmi_%.bbappend
@@ -0,0 +1,7 @@
+do_install_append () {
+# Remove ipmi_pass from image, if debug-tweaks is not enabled
+ ${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', '', 'rm ${D}/${sysconfdir}/ipmi_pass', d)}
+}
+
+# latest upstream HEAD until meta-phosphor autobumps
+SRCREV = "c2ef3319b42d86862b479e08e652ab36a26a14db"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.service b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.service
new file mode 100644
index 000000000..8f3a2bc31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Rotate the event logs
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/rotate-event-logs.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.sh b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.sh
new file mode 100644
index 000000000..5a8c5cc10
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+while true; do
+ sleep 60
+ /usr/sbin/logrotate /etc/logrotate.d/logrotate.rsyslog
+ ec=$?
+ if [ $ec -ne 0 ] ; then
+ echo "logrotate failed ($ec)"
+ fi
+done
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend
new file mode 100644
index 000000000..78c3b31af
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend
@@ -0,0 +1,13 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://rotate-event-logs.service \
+ file://rotate-event-logs.sh \
+"
+
+do_install_append() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/rotate-event-logs.sh ${D}/${bindir}/rotate-event-logs.sh
+ rm ${D}${systemd_system_unitdir}/rotate-event-logs.timer
+}
+
+SYSTEMD_SERVICE_${PN}_remove = "rotate-event-logs.timer"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/pam.d/login b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/pam.d/login
new file mode 100644
index 000000000..51dd3a83b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/pam.d/login
@@ -0,0 +1,90 @@
+#
+# The PAM configuration file for the Shadow `login' service
+#
+
+# Enforce a minimal delay in case of failure (in microseconds).
+# (Replaces the `FAIL_DELAY' setting from login.defs)
+# Note that other modules may require another minimal delay. (for example,
+# to disable any delay, you should add the nodelay option to pam_unix)
+auth optional pam_faildelay.so delay=3000000
+
+# Outputs an issue file prior to each login prompt (Replaces the
+# ISSUE_FILE option from login.defs). Uncomment for use
+# auth required pam_issue.so issue=/etc/issue
+
+# Disallows root logins except on tty's listed in /etc/securetty
+# (Replaces the `CONSOLE' setting from login.defs)
+# Note that it is included as a "requisite" module. No password prompts will
+# be displayed if this module fails to avoid having the root password
+# transmitted on unsecure ttys.
+# You can change it to a "required" module if you think it permits to
+# guess valid user names of your system (invalid user names are considered
+# as possibly being root).
+auth [success=ok ignore=ignore user_unknown=ignore default=die] pam_securetty.so
+
+# Disallows other than root logins when /etc/nologin exists
+# (Replaces the `NOLOGINS_FILE' option from login.defs)
+auth requisite pam_nologin.so
+
+# This module parses environment configuration file(s)
+# and also allows you to use an extended config
+# file /etc/security/pam_env.conf.
+#
+# parsing /etc/environment needs "readenv=1"
+session required pam_env.so readenv=1
+
+# Allow only uid 0 for login prompt authentication
+auth required pam_succeed_if.so uid eq 0
+
+# Do regular pam unix based authentication. Allow null password.
+auth [success=2 default=ignore] pam_unix.so quiet nullok_secure
+# here's the fallback if no module succeeds
+auth requisite pam_deny.so
+# prime the stack with a positive return value if there isn't one already;
+# this avoids us returning an error just because nothing sets a success code
+# since the modules above will each just jump around
+auth required pam_permit.so
+
+# This allows certain extra groups to be granted to a user
+# based on things like time of day, tty, service, and user.
+# Please edit /etc/security/group.conf to fit your needs
+# (Replaces the `CONSOLE_GROUPS' option in login.defs)
+auth optional pam_group.so
+
+# Uncomment and edit /etc/security/time.conf if you need to set
+# time restrainst on logins.
+# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
+# as well as /etc/porttime)
+# account requisite pam_time.so
+
+# Uncomment and edit /etc/security/access.conf if you need to
+# set access limits.
+# (Replaces /etc/login.access file)
+# account required pam_access.so
+
+# Sets up user limits according to /etc/security/limits.conf
+# (Replaces the use of /etc/limits in old login)
+session required pam_limits.so
+
+# Prints the last login info upon succesful login
+# (Replaces the `LASTLOG_ENAB' option from login.defs)
+session optional pam_lastlog.so
+
+# Prints the motd upon succesful login
+# (Replaces the `MOTD_FILE' option in login.defs)
+session optional pam_motd.so
+
+# Prints the status of the user's mailbox upon succesful login
+# (Replaces the `MAIL_CHECK_ENAB' option from login.defs).
+#
+# This also defines the MAIL environment variable
+# However, userdel also needs MAIL_DIR and MAIL_FILE variables
+# in /etc/login.defs to make sure that removing a user
+# also removes the user's mail spool file.
+# See comments in /etc/login.defs
+session optional pam_mail.so standard
+
+# Standard Un*x account and session
+account include common-account
+password include common-password
+session include common-session
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend
new file mode 100644
index 000000000..283d787e5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+PAM_SRC_URI += "file://pam.d/login \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
new file mode 100644
index 000000000..2f877ed53
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+# Use the latest to support obmc-ikvm properly
+SRC_URI = "git://github.com/LibVNC/libvncserver;nobranch=1"
+SRCREV = "ce9ae99b370d76521add190a8ca593aa6e3114dd"
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch
new file mode 100644
index 000000000..43600ac8a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch
@@ -0,0 +1,162 @@
+From 0c0b7b5da551c99161bda98820a529ba29cbaac1 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+Date: Wed, 21 Aug 2019 16:52:30 -0700
+Subject: [PATCH] Fix keyboard and mouse input events dropping issue
+
+Restarting of HID input devices causes input events dropping issue
+which is critical for BMC KVM uses. For an example, user can't enter
+to BIOS by doing keep pressing 'F2' or 'Del' key because of this issue.
+
+To fix the issue, this commit removes the input device restarting
+logic and refines error log journaling logic using errno checking.
+
+Tested:
+ 1. Open BMCweb -> Server control -> KVM.
+ 2. Make a host reset and keep pressing 'F2' key.
+ 3. Was able to enter to BIOS using the key press.
+
+Change-Id: Iec1bfad1d9e5825858844cab658bbfa3e6bc24f6
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+---
+ ikvm_input.cpp | 58 +++++++---------------------------------------------------
+ ikvm_input.hpp | 4 ----
+ ikvm_video.cpp | 3 +--
+ 3 files changed, 8 insertions(+), 57 deletions(-)
+
+diff --git a/ikvm_input.cpp b/ikvm_input.cpp
+index d95e6313f62c..df12f2715585 100644
+--- a/ikvm_input.cpp
++++ b/ikvm_input.cpp
+@@ -23,9 +23,9 @@ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
+
+ Input::Input(const std::string& kbdPath, const std::string& ptrPath) :
+- pointerError(false), sendKeyboard(false), sendPointer(false),
+- keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0},
+- keyboardPath(kbdPath), pointerPath(ptrPath)
++ sendKeyboard(false), sendPointer(false), keyboardFd(-1), pointerFd(-1),
++ keyboardReport{0}, pointerReport{0}, keyboardPath(kbdPath),
++ pointerPath(ptrPath)
+ {
+ if (!keyboardPath.empty())
+ {
+@@ -156,36 +156,6 @@ void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+ rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
+ }
+
+-void Input::restart()
+-{
+- if (!keyboardPath.empty() && keyboardFd < 0)
+- {
+- keyboardFd = open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC);
+- if (keyboardFd < 0)
+- {
+- log<level::ERR>("Failed to open input device",
+- entry("PATH=%s", keyboardPath.c_str()),
+- entry("ERROR=%s", strerror(errno)));
+- }
+-
+- sendKeyboard = false;
+- }
+-
+- if (!pointerPath.empty() && pointerFd < 0)
+- {
+- pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
+- if (pointerFd < 0)
+- {
+- log<level::ERR>("Failed to open input device",
+- entry("PATH=%s", pointerPath.c_str()),
+- entry("ERROR=%s", strerror(errno)));
+- }
+-
+- pointerError = false;
+- sendPointer = false;
+- }
+-}
+-
+ void Input::sendWakeupPacket()
+ {
+ uint8_t wakeupReport[KEY_REPORT_LENGTH] = {0};
+@@ -459,13 +429,10 @@ bool Input::writeKeyboard(const uint8_t *report)
+ {
+ if (write(keyboardFd, report, KEY_REPORT_LENGTH) != KEY_REPORT_LENGTH)
+ {
+- log<level::ERR>("Failed to write keyboard report",
+- entry("ERROR=%s", strerror(errno)));
+-
+- if (errno == ESHUTDOWN)
++ if (errno != ESHUTDOWN && errno != EAGAIN)
+ {
+- close(keyboardFd);
+- keyboardFd = -1;
++ log<level::ERR>("Failed to write keyboard report",
++ entry("ERROR=%s", strerror(errno)));
+ }
+
+ return false;
+@@ -478,23 +445,12 @@ void Input::writePointer(const uint8_t *report)
+ {
+ if (write(pointerFd, report, PTR_REPORT_LENGTH) != PTR_REPORT_LENGTH)
+ {
+- if (!pointerError)
++ if (errno != ESHUTDOWN && errno != EAGAIN)
+ {
+ log<level::ERR>("Failed to write pointer report",
+ entry("ERROR=%s", strerror(errno)));
+- pointerError = true;
+- }
+-
+- if (errno == ESHUTDOWN)
+- {
+- close(pointerFd);
+- pointerFd = -1;
+ }
+ }
+- else
+- {
+- pointerError = false;
+- }
+ }
+
+ } // namespace ikvm
+diff --git a/ikvm_input.hpp b/ikvm_input.hpp
+index 953333263e2d..2adc7c106755 100644
+--- a/ikvm_input.hpp
++++ b/ikvm_input.hpp
+@@ -48,8 +48,6 @@ class Input
+ */
+ static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl);
+
+- /* @brief Re-opens USB device in case the endpoint shutdown */
+- void restart();
+ /* @brief Sends a wakeup data packet to the USB input device */
+ void sendWakeupPacket();
+ /* @brief Sends an HID report to the USB input device */
+@@ -90,8 +88,6 @@ class Input
+ bool writeKeyboard(const uint8_t *report);
+ void writePointer(const uint8_t *report);
+
+- /* @brief Indicates whether or not a pointer report error has occurred */
+- bool pointerError;
+ /* @brief Indicates whether or not to send a keyboard report */
+ bool sendKeyboard;
+ /* @brief Indicates whether or not to send a pointer report */
+diff --git a/ikvm_video.cpp b/ikvm_video.cpp
+index 6a5aa6c10927..7bd4b4eb6c98 100644
+--- a/ikvm_video.cpp
++++ b/ikvm_video.cpp
+@@ -163,10 +163,9 @@ bool Video::needsResize()
+ restart();
+ return false;
+ }
+- else if (timingsError)
++ else
+ {
+ timingsError = false;
+- input.restart();
+ }
+
+ if (timings.bt.width != width || timings.bt.height != height)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
new file mode 100644
index 000000000..8de421d18
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+#SRC_URI = "git://github.com/openbmc/obmc-ikvm"
+SRCREV = "861337e8ec92767c4c88237ec5db494a2a67fa8d"
+
+SRC_URI += " \
+ file://0003-Fix-keyboard-and-mouse-input-events-dropping-issue.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb
new file mode 100644
index 000000000..0a07f5ab0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/host-misc-comm-manager/host-misc-comm-manager_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Miscellaneous host interface communication manager"
+DESCRIPTION = "Daemon exposes Miscellaneous host interface communications like \
+ platform reset, mail box & scratch pad"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/host-misc-comm-manager.git;protocol=ssh"
+
+SRCREV = "7e14ddf805cda0cdf3db564081144d9532e555cd"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.Host.Misc.Manager.service"
+
+DEPENDS = "boost sdbusplus phosphor-logging"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb
new file mode 100644
index 000000000..47e2d7c46
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/hsbp/hsbp-manager_git.bb
@@ -0,0 +1,21 @@
+SUMMARY = "HSBP Manager"
+DESCRIPTION = "HSBP Manager monitors HSBPs through SMBUS"
+
+SRC_URI = "git://github.com/openbmc/s2600wf-misc.git"
+SRCREV = "d86629cedb04607301eef6220688c53f0b29ea0e"
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+SYSTEMD_SERVICE_${PN} = "hsbp-manager.service"
+
+DEPENDS = "boost \
+ i2c-tools \
+ sdbusplus"
+
+S = "${WORKDIR}/git/hsbp-manager"
+inherit cmake systemd
+
+EXTRA_OECMAKE = "-DYOCTO=1"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb b/meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb
new file mode 100644
index 000000000..71245ac50
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb
@@ -0,0 +1,18 @@
+DESCRIPTION = "Image with Intel content based upon Phosphor, an OpenBMC framework."
+
+inherit obmc-phosphor-full-fitimage
+inherit obmc-phosphor-image-common
+inherit obmc-phosphor-image-dev
+inherit ${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'image_types_intel_pfr', '', d)}
+
+DEPENDS += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'obmc-intel-pfr-image-native', '', d)}"
+DEPENDS += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'intel-pfr-manager', '', d)}"
+
+FEATURE_PACKAGES_obmc-sensors = ""
+FEATURE_PACKAGES_obmc-debug-collector = ""
+
+fix_shadow_perms() {
+ chgrp shadow ${IMAGE_ROOTFS}${sysconfdir}/shadow
+ chmod u=rw,g+r ${IMAGE_ROOTFS}${sysconfdir}/shadow
+}
+ROOTFS_POSTPROCESS_COMMAND += "fix_shadow_perms ; "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py
new file mode 100755
index 000000000..438a3b91f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/pfr_image.py
@@ -0,0 +1,385 @@
+#!/usr/bin/env python3
+# coding: utf-8
+# our image is contained as parts, including the hash
+# then it gets zipped up and signed again
+
+# this internal signature is for boot and recovery, but
+# will be checked prior to writing to flash as well.
+
+# the internal signature format is a PFR-specific block
+# including a hash bitmap, certificates (public keys),
+# and the actual signature data as well, for both active
+# and recovery images
+
+# TODO: figure out if active and recovery actually have different sigs
+# TODO: build hashmap from payload manifest
+# TODO: figure out exact struct layout for PFR metadata
+import os, hashlib, struct, json, sys, subprocess, mmap, io, array, binascii, copy, shutil, re
+from array import array
+from binascii import unhexlify
+from hashlib import sha1, sha256, sha384, sha512
+from shutil import copyfile
+# Flash Map
+# -----------------------------------------------
+# Start addr Contents
+# 0x00000000 S U-Boot
+# 0x00080000 S+ PFM
+# 0x000a0000 U U-boot Env
+# 0x000C0000 U SOFS
+# 0x002c0000 U RWFS
+# 0x00b00000 S fit-image
+# 0x02a00000 S+ rc-image
+# 0x04a00000 U staging-image
+# * partially signed (not full 64k page)
+# + unsigned, owned by pfr
+
+# TODO: The below defines should go to manifest files.
+# Keeping it here hard coded for now.
+# The pages to be skipped for HASH and PBC
+# Pages: 0x80 to 0x9f - starting PFM region until end of pfm
+# Pages: 0x2a00 to 0x7FFF - starting RC-image until end of flash
+EXCLUDE_PAGES =[[0x80, 0x9f],[0x2a00,0x7fff]]
+
+# SPI PFM globals
+PFM_OFFSET = 0x80000
+PFM_SPI = 0x1
+PFM_I2C = 0x2
+SHA = 0x1
+PFM_DEF_SIZE = 32 # 32 bytes of PFM header
+PFM_SPI_SIZE_DEF = 16 # 16 bytes of SPI PFM
+PFM_SPI_SIZE_HASH = 32 # 32 bytes of SPI region HASH
+PFM_I2C_SIZE = 40 # 40 bytes of i2c rules region in PFM
+
+PAGE_SIZE = 0x1000 # 4KB size of page
+
+def load_manifest(fname):
+ manifest = {}
+ with open(fname, 'r') as fd:
+ manifest = json.load(fd)
+ return manifest
+
+class pfm_spi(object):
+
+ def __init__(self, prot_mask, start_addr, end_addr, hash, hash_pres):
+ self.spi_pfm = PFM_SPI
+ self.spi_prot_mask = prot_mask
+ self.spi_hash_pres = hash_pres
+ if hash_pres != 0:
+ self.spi_hash = hash
+ self.spi_pfm_rsvd = 0xffffffff # b'\xff'*4
+ self.spi_start_addr = start_addr
+ self.spi_end_addr = end_addr
+
+class pfm_i2c(object):
+
+ def __init__(self, bus_id, rule_id, address, cmd_map):
+ self.i2c_pfm = PFM_I2C
+ self.i2c_pfm_rsvd = 0xffffffff # b'\xff'*4
+ self.i2c_bus_id = bus_id
+ self.i2c_rule_id = rule_id
+ self.i2c_address = address
+ self.i2c_cmd_whitelist = cmd_map
+
+class pfr_bmc_image(object):
+
+# json_file, firmware_file
+ def __init__(self, manifest, firmware_file, build_ver, build_num, build_hash, sha):
+
+ self.manifest = load_manifest(manifest)
+ self.firmware_file = firmware_file
+ self.build_version = build_ver
+ self.build_number = build_num
+ self.build_hash = build_hash
+ self.sha = sha
+ if self.sha == "2":
+ SHA = 0x2
+ PFM_SPI_SIZE_HASH = 48
+ if self.sha == "1":
+ PFM_SPI_SIZE_HASH = 32
+ SHA = 0x1
+ self.pfr_rom_file = 'image-mtd-pfr'
+ open(self.pfr_rom_file, 'a').close()
+
+ self.page_size = PAGE_SIZE
+ self.empty = b'\xff' * self.page_size
+
+ self.image_parts = []
+ for p in self.manifest['image-parts']:
+ # the json should have in the order- filename, index, offset, size and protection byte
+ self.image_parts.append((p['name'], p['index'], p['offset'], p['size'], p['prot_mask'], p['pfm'], p['hash'], p['compress']))
+ if self.sha == "1":
+ self.act_dgst = hashlib.sha256()
+ if self.sha == "2":
+ self.act_dgst = hashlib.sha384()
+ # SPI regions PFM array
+ self.pfm_spi_regions = []
+ self.pfm_bytes = PFM_DEF_SIZE # PFM definition bytes (SPI regions + SMBUS)
+
+ # hash, erase and compression bit maps for 128MB
+ self.pbc_erase_bitmap = bytearray(4096)
+ self.pbc_comp_bitmap = bytearray(4096)
+
+ self.pbc_comp_payload = 0
+ self.sec_rev = 1
+
+ # fill in the calculated data
+ self.hash_and_map()
+
+ self.i2c_rules = []
+ for i in self.manifest['i2c-rules']:
+ # the json should have in the order- bus-id, rule-id, address, size and cmd-whitelist
+ self.i2c_rules.append((i['bus-id'], i['rule-id'], i['address'], i['cmd-whitelist']))
+
+ # I2C rules PFM array
+ self.pfm_i2c_rules = []
+
+ # Generate the i2c rules
+ self.build_i2c_rules()
+
+ # Generate PFM region binary - pfm.bin
+ self.build_pfm()
+ print("PFM build done")
+
+ # Generate PBC region - pbc.bin
+ self.pbc_hdr()
+ print("PBC build done")
+
+ def hash_compress_regions(self, p, upd):
+
+ # JSON format as below
+ # 0. "name": <image region name>
+ # 1. "index": 1,
+ # 2. "offset": <start addr>,
+ # 3. "size": <size of the region>,
+ # 4. "prot_mask": <PFR protection mask>,
+ # 5. "pfm": <1|0 -add in PFM or not>,
+ # 6. "hash": <hashing of the region needed>,
+ # 7. "compress": <region to be compressed>
+
+ image_name = p[0]
+ start_addr = int(p[2],16) #image part start address
+ size = int(p[3],16) #size of the image part
+ pfm_prot_mask = p[4] # pfm protection mask
+ pfm_flag = p[5] # pfm needed?
+ hash_flag = p[6] #to be hashed?
+ compress = p[7] #compress flag
+ index = p[1] # image part index
+ # 1 page is 4KB
+ page = start_addr >> 12
+
+ with open(self.firmware_file, "rb") as f:
+ f.seek(start_addr)
+ skip = False
+
+ if hash_flag == 1:
+ if self.sha == "1":
+ hash_dgst = hashlib.sha256()
+ if self.sha == "2":
+ hash_dgst = hashlib.sha384()
+ for chunk in iter(lambda: f.read(self.page_size), b''):
+ chunk_len = len(chunk)
+ if chunk_len != self.page_size:
+ chunk = b''.join([chunk, b'\xff' * (self.page_size - chunk_len)])
+
+ for p in EXCLUDE_PAGES:
+ if (page >= p[0]) and (page <= p[1]):
+ #print("Exclude page={}".format(page))
+ skip = True
+ break
+
+ if not skip:
+ # add to the hash
+ if hash_flag == 1:
+ # HASH for the region
+ self.act_dgst.update(chunk)
+ hash_dgst.update(chunk)
+
+ if compress == 1:
+ self.pbc_erase_bitmap[page >> 3] |= 1 << (7- (page % 8)) # Big endian bit map
+ # add to the pbc map
+ if chunk != self.empty:
+ #print("compressed page ={}".format(page))
+ upd.write(chunk)
+ self.pbc_comp_bitmap[page >> 3] |= 1 << (7- (page % 8)) # Big Endian bit map
+ self.pbc_comp_payload += chunk_len # compressed payload bytes
+
+ page += 1
+
+ if (page * self.page_size) >= (size + start_addr):
+ break
+
+ if pfm_flag == 1:
+ self.pfm_bytes += PFM_SPI_SIZE_DEF
+
+ hash = bytearray(PFM_SPI_SIZE_HASH)
+ hash_pres = 0
+
+ if hash_flag == 1:
+ # region's hash
+ hash = hash_dgst.hexdigest()
+ hash_pres = SHA
+ self.pfm_bytes += PFM_SPI_SIZE_HASH
+
+ # append to SPI regions in PFM
+ self.pfm_spi_regions.append(pfm_spi(pfm_prot_mask, start_addr, (start_addr+size), hash, hash_pres))
+
+ def add_i2c_rules(self, i):
+ bus_id = i[0] # I2C Bus number
+ rule_id = i[1] # I2C rule number
+ addr = i[2] # I2C device address
+ cmds = i[3] # I2C white listed commands for which i2c write to be allowed
+ whitelist_map = bytearray(32)
+
+ self.pfm_bytes += PFM_I2C_SIZE # add upto PFM size
+
+ for c in cmds:
+ if c == "all":
+ for i in range(32):
+ whitelist_map[i] = 0xff
+ break
+ else:
+ idx = int(c,16) // 8 # index in the 32 bytes of white list i2c cmds
+ bit = int(c,16) % 8 # bit position to set
+ whitelist_map[idx] |= (1 << bit)
+
+ # append to I2C rules in PFM
+ self.pfm_i2c_rules.append(pfm_i2c(bus_id, rule_id, addr, whitelist_map))
+
+ def build_i2c_rules(self):
+ for i in self.i2c_rules:
+ self.add_i2c_rules(i)
+
+ def hash_and_map(self):
+
+ # have copy of the update file for appending with PFR meta and compression
+ copyfile(self.firmware_file, self.pfr_rom_file)
+ with open("bmc_compressed.bin", "wb+") as upd:
+ for p in self.image_parts:
+ #filename, index, offset, size, protection.
+ print(p[0], p[1], p[2], p[3], p[4])
+ self.hash_compress_regions(p, upd)
+
+ def pbc_hdr(self):
+ '''
+ typedef struct {
+ uint8_t tag[4]; /* PBC tag */
+ uint32_t version; /* PBC Version- 0x0000_0002 */
+ uint32_t page_size; /* NOR Flash page size = 0x0000_1000 */
+ uint32_t pattern_size; /* 0xFF as pattern 1byte = 0x0000_0001 */
+ uint32_t pattern; /* 0xFF pattern = 0x0000_00FF */
+ uint32_t bitmap_size; /* 32768 pages for 128MB- 0x0000_8000 */
+ uint32_t payload_length /* payload */
+ uint8_t reserved[100]; /* Reserved 100bytes */
+ uint8_t erase_bitmap[4096]; /* erase bit map for 32768 pages */
+ uint8_t comp_bitmap[4096]; /* compression bit map for 32768 pages */
+ uint8_t comp_payload; /* compressed payload */
+ '''
+ names = [
+ 'tag', 'pbc_ver', 'page_sz', 'pattern_sz', 'pattern', 'bitmap_sz',
+ 'payload_size', 'resvd0', 'erase_bitmap', 'comp_bitmap',
+ ]
+ parts = {
+ 'tag': b'CBP_',
+ 'pbc_ver': struct.pack('<i',0x00000002),
+ 'page_sz': struct.pack('<i',0x00001000),
+ 'pattern_sz': struct.pack('<i',0x00000001),
+ 'pattern': struct.pack('<i',0x000000FF),
+ 'bitmap_sz': struct.pack('<i',0x00008000),
+ 'payload_size': struct.pack('<i',self.pbc_comp_payload),
+ 'resvd0' : b'\x00'*100,
+ 'erase_bitmap': bytes(self.pbc_erase_bitmap),
+ 'comp_bitmap': bytes(self.pbc_comp_bitmap),
+ }
+
+ with open("pbc.bin", "wb+") as pbf:
+ pbf.write(b''.join([parts[n] for n in names]))
+ pbf.seek(0) # rewind to beginning of PBC file
+ self.act_dgst.update(pbf.read()) # add up PBC data for hashing
+
+ def build_pfm(self):
+ '''
+ typedef struct {
+ uint32_t tag; /* PFM_HDR_TAG above, no terminating null */
+ uint8_t SVN; /* SVN- security revision of associated image data */
+ uint8_t bkc; /* bkc */
+ uint8_t pfm_ver_major; /* PFM revision */
+ uint8_t pfm_ver_minor;
+ uint8_t reserved0[4];
+ uint8_t build_num;
+ uint8_t build_hash[3];
+ uint8_t reserved1[12]; /* reserved */
+ uint32_t pfm_length; /* PFM size in bytes */
+ pfm_spi pfm_spi[2]; /* PFM SPI regions - u-boot & fit-image */
+ pfm_smbus pfm_smbus[4]; /* defined smbus rules for PSUs and HSBP */
+ } __attribute__((packed)) pfm_hdr;
+ '''
+ names = [
+ 'tag', 'sec_rev', 'bkc', 'pfm_ver_major', 'pfm_ver_minor', 'resvd0', 'build_num', 'build_hash1', 'build_hash2', 'build_hash3', 'resvd1', 'pfm_len',
+ ]
+ parts = {
+ 'tag': struct.pack("<I", 0x02b3ce1d),
+ 'sec_rev': struct.pack('<B', self.sec_rev),
+ 'bkc': struct.pack('<B', 0x01),
+ 'pfm_ver_major': struct.pack('<B', ((int(self.build_version) >> 8) & 0xff)),
+ 'pfm_ver_minor': struct.pack('<B', (int(self.build_version) & 0x00ff)),
+ 'resvd0': b'\xff'* 4,
+ 'build_num': struct.pack('<B', int(self.build_number,16)),
+ 'build_hash1': struct.pack('<B', (int(self.build_hash) & 0xff)),
+ 'build_hash2': struct.pack('<B', ((int(self.build_hash) >> 8) & 0xff)),
+ 'build_hash3': struct.pack('<B', ((int(self.build_hash) >> 16) & 0xff)),
+ 'resvd1': b'\xff'* 12,
+ 'pfm_len': ''
+ }
+
+ # PFM should be 128bytes aligned, find the padding bytes
+ padding_bytes = 0
+ if (self.pfm_bytes % 128) != 0:
+ padding_bytes = 128 - (self.pfm_bytes % 128)
+
+ print("padding={}".format(padding_bytes))
+ print("PFM size1={}".format(self.pfm_bytes))
+ self.pfm_bytes += padding_bytes
+ parts['pfm_len'] = struct.pack('<I', self.pfm_bytes)
+ print("PFM size2={}".format(self.pfm_bytes))
+
+ with open("pfm.bin", "wb+") as f:
+ f.write(b''.join([parts[n] for n in names]))
+ for i in self.pfm_spi_regions:
+ f.write(struct.pack('<B', int(i.spi_pfm)))
+ f.write(struct.pack('<B', int(i.spi_prot_mask)))
+ f.write(struct.pack('<h', int(i.spi_hash_pres)))
+ f.write(struct.pack('<I', int(i.spi_pfm_rsvd)))
+ f.write(struct.pack('<I', int(i.spi_start_addr)))
+ f.write(struct.pack('<I', int(i.spi_end_addr)))
+
+ if i.spi_hash_pres != 0:
+ f.write(bytearray.fromhex(i.spi_hash))
+
+ for r in self.pfm_i2c_rules:
+ f.write(struct.pack('<B', int(r.i2c_pfm)))
+ f.write(struct.pack('<I', int(r.i2c_pfm_rsvd)))
+ f.write(struct.pack('<B', int(r.i2c_bus_id)))
+ f.write(struct.pack('<B', int(r.i2c_rule_id)))
+ f.write(struct.pack('<B', int(r.i2c_address, 16)))
+ f.write(r.i2c_cmd_whitelist)
+
+ # write the padding bytes at the end
+ f.write(b'\xff' * padding_bytes)
+
+def main():
+ if len(sys.argv) != 7: #< pfr_image.py manifest.json> <update.bin> <build_version> <build_number> <build_hash> <sha>
+ print('usage: {} <manifest.json> <firmware.bin> <build_version> <build_number> <build_hash> <sha>'.format(sys.argv[0]))
+ return
+
+ json_file = sys.argv[1]
+ firmware_file = sys.argv[2]
+ build_ver = sys.argv[3]
+ build_num = sys.argv[4]
+ build_hash = sys.argv[5]
+ sha = sys.argv[6]
+
+ # function to generate BMC PFM, PBC header and BMC compressed image
+ pfr_bmc_image(json_file, firmware_file, build_ver, build_num, build_hash, sha)
+
+if __name__ == '__main__':
+ main()
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/bmc_config.xml b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/bmc_config.xml
new file mode 100644
index 000000000..9e7d3f82d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/bmc_config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- XML file for Block Sign Tool -->
+<blocksign>
+ <version>1</version>
+ <!-- Block 0 -->
+ <block0>
+ <magic>0xB6EAFD19</magic>
+ <pctype>4</pctype>
+ </block0>
+ <!-- Block 1 -->
+ <block1>
+ <magic>0xF27F28D7</magic>
+ <!-- Root key -->
+ <rkey>
+ <magic>0xA757A046</magic>
+ <curvemagic>0xC7B88C74</curvemagic>
+ <permissions>-1</permissions>
+ <keyid>-1</keyid>
+ <pubkey>rk_pub.pem</pubkey>
+ </rkey>
+ <!-- Code signing key -->
+ <cskey>
+ <magic>0x14711C2F</magic>
+ <curvemagic>0xC7B88C74</curvemagic>
+ <permissions>8</permissions>
+ <keyid>1</keyid>
+ <pubkey>csk_pub.pem</pubkey>
+ <sigmagic>0xDE64437D</sigmagic>
+ <hashalg>sha256</hashalg>
+ <signkey>rk_prv.pem</signkey>
+ <!--<script>./sign_external.sh</script>-->
+ </cskey>
+ <!-- Signature over Block 0 -->
+ <b0_sig>
+ <magic>0x15364367</magic>
+ <sigmagic>0xDE64437D</sigmagic>
+ <hashalg>sha256</hashalg>
+ <signkey>csk_prv.pem</signkey>
+ </b0_sig>
+ </block1>
+ <!-- CPLD Bitstream Specific -->
+ <padding>
+ <!-- Pad block1 such that combined block length is 1024b -->
+ <blockpad>1024</blockpad>
+ <!-- Align total package to 128 bytes -->
+ <align>128</align>
+ </padding>
+</blocksign>
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_prv.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_prv.pem
new file mode 100644
index 000000000..a46fa2a2b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_prv.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIFjPqxcb6tfFWyFVaQCVjeN9MtcISpYIbNlkQoODrHTUoAoGCCqGSM49
+AwEHoUQDQgAERGJveRnhIp7I5cvmjO74MJLbUJjTfvTDKlzK0hJB0WRBEFScpb9d
+xWLrwj9TNcO+EexnNcjEkF1RYNs6lHavRQ==
+-----END EC PRIVATE KEY-----
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_pub.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_pub.pem
new file mode 100644
index 000000000..cc70d6e28
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/csk_pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERGJveRnhIp7I5cvmjO74MJLbUJjT
+fvTDKlzK0hJB0WRBEFScpb9dxWLrwj9TNcO+EexnNcjEkF1RYNs6lHavRQ==
+-----END PUBLIC KEY-----
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfm_config.xml b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfm_config.xml
new file mode 100644
index 000000000..19378d1b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfm_config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- XML file for Block Sign Tool -->
+<blocksign>
+ <version>1</version>
+ <!-- Block 0 -->
+ <block0>
+ <magic>0xB6EAFD19</magic>
+ <pctype>3</pctype>
+ </block0>
+ <!-- Block 1 -->
+ <block1>
+ <magic>0xF27F28D7</magic>
+ <!-- Root key -->
+ <rkey>
+ <magic>0xA757A046</magic>
+ <curvemagic>0xC7B88C74</curvemagic>
+ <permissions>-1</permissions>
+ <keyid>-1</keyid>
+ <pubkey>rk_pub.pem</pubkey>
+ </rkey>
+ <!-- Code signing key -->
+ <cskey>
+ <magic>0x14711C2F</magic>
+ <curvemagic>0xC7B88C74</curvemagic>
+ <permissions>4</permissions>
+ <keyid>1</keyid>
+ <pubkey>csk_pub.pem</pubkey>
+ <sigmagic>0xDE64437D</sigmagic>
+ <hashalg>sha256</hashalg>
+ <signkey>rk_prv.pem</signkey>
+ <!--<script>./sign_external.sh</script>-->
+ </cskey>
+ <!-- Signature over Block 0 -->
+ <b0_sig>
+ <magic>0x15364367</magic>
+ <sigmagic>0xDE64437D</sigmagic>
+ <hashalg>sha256</hashalg>
+ <signkey>csk_prv.pem</signkey>
+ </b0_sig>
+ </block1>
+ <!-- CPLD Bitstream Specific -->
+ <padding>
+ <!-- Pad block1 such that combined block length is 1024b -->
+ <blockpad>1024</blockpad>
+ <!-- Align total package to 128 bytes -->
+ <align>128</align>
+ </padding>
+</blocksign>
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfr_manifest.json b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfr_manifest.json
new file mode 100644
index 000000000..c79b7f343
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/pfr_manifest.json
@@ -0,0 +1,196 @@
+{
+ "image-parts": [{
+ "name": "u-boot",
+ "index": 0,
+ "offset": "0",
+ "size": "0x80000",
+ "prot_mask": 29,
+ "pfm": 1,
+ "hash": 1,
+ "compress": 1
+ },
+ {
+ "name": "pfm",
+ "index": 1,
+ "offset": "0x80000",
+ "size": "0x20000",
+ "prot_mask": 0,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 0
+ },
+ {
+ "name": "u-boot-env",
+ "index": 2,
+ "offset": "0xa0000",
+ "size": "0x20000",
+ "prot_mask": 31,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 1
+ },
+ {
+ "name": "sofs",
+ "index": 3,
+ "offset": "0xc0000",
+ "size": "0x200000",
+ "prot_mask": 31,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 1
+ },
+ {
+ "name": "rwfs",
+ "index": 4,
+ "offset": "0x2c0000",
+ "size": "0x840000",
+ "prot_mask": 31,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 1
+ },
+ {
+ "name": "fit-image-a",
+ "index": 5,
+ "offset": "0xb00000",
+ "size": "0x1f00000",
+ "prot_mask": 29,
+ "pfm": 1,
+ "hash": 1,
+ "compress": 1
+ },
+ {
+ "name": "rc-image",
+ "index": 6,
+ "offset": "0x2a00000",
+ "size": "0x2000000",
+ "prot_mask": 0,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 0
+ },
+ {
+ "name": "image-stg",
+ "index": 7,
+ "offset": "0x4a00000",
+ "size": "0x3500000",
+ "prot_mask": 3,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 0
+ },
+ {
+ "name": "cpld-rc",
+ "index": 8,
+ "offset": "0x7f00000",
+ "size": "0x100000",
+ "prot_mask": 0,
+ "pfm": 1,
+ "hash": 0,
+ "compress": 0
+ }
+ ],
+ "i2c-rules": [{
+ "bus-id": 3,
+ "rule-id": 3,
+ "address": "0xD0",
+ "cmd-whitelist": ["0x00", "0x01", "0x02", "0x03", "0x04", "0x09", "0x0A", "0x0B", "0x0C", "0x0D", "0x0E", "0x0F",
+ "0x10", "0x13", "0x17", "0x1B", "0x1C", "0x1D", "0x02", "0x021", "0x22", "0x23", "0x25", "0x30",
+ "0x31", "0x32", "0x33", "0x035", "0x36", "0x37", "0x38", "0x39", "0x3A", "0x3B", "0x3C", "0x3D"]
+ },
+ {
+ "bus-id": 3,
+ "rule-id": 4,
+ "address": "0xD8",
+ "cmd-whitelist": ["0x00", "0x01", "0x02", "0x03", "0x04", "0x09", "0x0A", "0x0B", "0x0C", "0x0D", "0x0E", "0x0F",
+ "0x10", "0x13", "0x17", "0x1B", "0x1C", "0x1D", "0x02", "0x021", "0x22", "0x23", "0x25", "0x30",
+ "0x31", "0x32", "0x33", "0x035", "0x36", "0x37", "0x38", "0x39", "0x3A", "0x3B", "0x3C", "0x3D"]
+ },
+ {
+ "bus-id": 1,
+ "rule-id": 6,
+ "address": "0xB0",
+ "cmd-whitelist": ["0x00", "0x03", "0x05", "0x06", "0x19", "0x1A", "0x30", "0x3A", "0x3B", "0x3C", "0x3D", "0x3E", "0x3F",
+ "0x79", "0x7A", "0x7B", "0x7C", "0x7D", "0x7E", "0x7F", "0x81", "0x82", "0x86", "0x87", "0x88",
+ "0x89", "0x8C", "0x8D", "0x8E", "0x8F", "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96",
+ "0x97", "0x98", "0x9A", "0xA6", "0xA7", "0xD0", "0xD3", "0xD4", "0xD5", "0xD6", "0xD7", "0xD8",
+ "0xD9", "0xDC", "0xDD", "0xDE", "0xDE"]
+ },
+ {
+ "bus-id": 1,
+ "rule-id": 4,
+ "address": "0xB2",
+ "cmd-whitelist": ["0x00", "0x03", "0x05", "0x06", "0x19", "0x1A", "0x30", "0x3A", "0x3B", "0x3C", "0x3D", "0x3E", "0x3F",
+ "0x79", "0x7A", "0x7B", "0x7C", "0x7D", "0x7E", "0x7F", "0x81", "0x82", "0x86", "0x87", "0x88",
+ "0x89", "0x8C", "0x8D", "0x8E", "0x8F", "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96",
+ "0x97", "0x98", "0x9A", "0xA6", "0xA7", "0xD0", "0xD3", "0xD4", "0xD5", "0xD6", "0xD7", "0xD8",
+ "0xD9", "0xDC", "0xDD", "0xDE", "0xDE"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 1,
+ "address": "0xB4",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 2,
+ "address": "0xD4",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 3,
+ "address": "0x4A",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 4,
+ "address": "0x4C",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 5,
+ "address": "0xDC",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 6,
+ "address": "0xEC",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 7,
+ "address": "0xE0",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 8,
+ "address": "0xB0",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 9,
+ "address": "0xC4",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 10,
+ "address": "0xCC",
+ "cmd-whitelist": ["0x00"]
+ },
+ {
+ "bus-id": 2,
+ "rule-id": 11,
+ "address": "0xE4",
+ "cmd-whitelist": ["0x00"]
+ }
+ ]
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_prv.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_prv.pem
new file mode 100644
index 000000000..9e8616795
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_prv.pem
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIHVbq5CmT4Vr4Jb0eJK0+KhUxDOWy1kh9QYAClV5MH1GoAoGCCqGSM49
+AwEHoUQDQgAEZUL6ZcF0YN590Pq/bKPYjfa3F4E44XiKcqvS6+l2GfSdCLRhXWHw
+iV803vFkTsZ1CfpzFdZGwfbwg7nvG5UpSQ==
+-----END EC PRIVATE KEY-----
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_pub.pem b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_pub.pem
new file mode 100644
index 000000000..117e08bae
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/files/wht/rk_pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZUL6ZcF0YN590Pq/bKPYjfa3F4E4
+4XiKcqvS6+l2GfSdCLRhXWHwiV803vFkTsZ1CfpzFdZGwfbwg7nvG5UpSQ==
+-----END PUBLIC KEY-----
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-blocksign-native.bb b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-blocksign-native.bb
new file mode 100644
index 000000000..7acc19f46
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-blocksign-native.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Intel Blocksign tool for PFR image"
+DESCRIPTION = "Image signing tool for BMC PFR image"
+
+inherit native cmake
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+DEPENDS = "openssl-native libxml2-native "
+
+SRC_URI = "git://git@github.com/Intel-BMC/blocksign;protocol=ssh"
+
+SRCREV = "966d16f680c1b14c338640d35a12d5e2f9a6937a"
+
+S = "${WORKDIR}/git/"
+
+do_install_append() {
+ install -d ${D}/${bindir}
+ install -m 775 ${B}/blocksign ${D}/${bindir}
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb
new file mode 100644
index 000000000..d48ffb1a5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/intel-pfr-manager_git.bb
@@ -0,0 +1,22 @@
+SUMMARY = "Intel PFR Manager Service"
+DESCRIPTION = "Daemon to handle all PFR functionalities"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/intel-pfr-manager"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.PFR.Manager.service"
+
+DEPENDS += " \
+ sdbusplus \
+ phosphor-logging \
+ boost \
+ i2c-tools \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb
new file mode 100644
index 000000000..bb8684ac2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/obmc-intel-pfr-image-native.bb
@@ -0,0 +1,37 @@
+SUMMARY = "Intel PFR image manifest and image signing keys"
+DESCRIPTION = "This copies PFR image generation scripts and image signing keys to staging area"
+
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+inherit native
+
+DEPENDS += " intel-blocksign-native"
+
+SRC_URI = " \
+ file://pfr_image.py \
+ file://${PRODUCT_GENERATION}/pfr_manifest.json \
+ file://${PRODUCT_GENERATION}/pfm_config.xml \
+ file://${PRODUCT_GENERATION}/bmc_config.xml \
+ file://${PRODUCT_GENERATION}/csk_prv.pem \
+ file://${PRODUCT_GENERATION}/csk_pub.pem \
+ file://${PRODUCT_GENERATION}/rk_pub.pem \
+ file://${PRODUCT_GENERATION}/rk_prv.pem \
+ "
+
+do_install () {
+ bbplain "Copying intel pfr image generation scripts and image signing keys"
+
+ install -d ${D}${bindir}
+ install -d ${D}/${datadir}/pfrconfig
+ install -m 775 ${WORKDIR}/pfr_image.py ${D}${bindir}/pfr_image.py
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/pfr_manifest.json ${D}/${datadir}/pfrconfig
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/pfm_config.xml ${D}/${datadir}/pfrconfig/pfm_config.xml
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/bmc_config.xml ${D}/${datadir}/pfrconfig/bmc_config.xml
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/csk_prv.pem ${D}/${datadir}/pfrconfig/csk_prv.pem
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/csk_pub.pem ${D}/${datadir}/pfrconfig/csk_pub.pem
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/rk_pub.pem ${D}/${datadir}/pfrconfig/rk_pub.pem
+ install -m 400 ${WORKDIR}/${PRODUCT_GENERATION}/rk_prv.pem ${D}/${datadir}/pfrconfig/rk_prv.pem
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics.bb b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics.bb
new file mode 100644
index 000000000..50c8bd63e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics.bb
@@ -0,0 +1,24 @@
+SUMMARY = "One time automatically enable every NIC"
+DESCRIPTION = "Re-enable NIC accidentally disabled by earlier BMC firmware."
+
+S = "${WORKDIR}"
+SRC_URI = "file://enable-nics.sh \
+ file://enable-nics.service \
+ "
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+RDEPENDS_${PN} += "bash"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/enable-nics.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/enable-nics.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/enable-nics.sh ${D}/${bindir}/enable-nics.sh
+}
+
+SYSTEMD_SERVICE_${PN} += " enable-nics.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service
new file mode 100644
index 000000000..531b5d86e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Re-enable NICs mistakenly disabled by earlier BMC firmware
+Wants=multi-user.target
+After=multi-user.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/enable-nics.sh
+
+[Install]
+WantedBy=network.target
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.sh b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.sh
new file mode 100755
index 000000000..ce1473be1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/nic/enable-nics/enable-nics.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+SEMAPHORE_FILE=/var/cache/private/nic_fixup_complete
+
+if [ -a $SEMAPHORE_FILE ]; then
+ exit 0
+fi
+
+for nicFile in /etc/systemd/network/*.network
+do
+ sed -i -e"/Unmanaged/d" $nicFile
+done
+
+touch $SEMAPHORE_FILE
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb
new file mode 100644
index 000000000..4d91ac673
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb
@@ -0,0 +1,38 @@
+SUMMARY = "OpenBMC for Intel - Applications"
+PR = "r1"
+
+inherit packagegroup
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+PROVIDES = "${PACKAGES}"
+PACKAGES = " \
+ ${PN}-chassis \
+ ${PN}-fans \
+ ${PN}-flash \
+ ${PN}-system \
+ "
+
+PROVIDES += "virtual/obmc-chassis-mgmt"
+PROVIDES += "virtual/obmc-fan-mgmt"
+PROVIDES += "virtual/obmc-flash-mgmt"
+PROVIDES += "virtual/obmc-system-mgmt"
+
+RPROVIDES_${PN}-chassis += "virtual-obmc-chassis-mgmt"
+RPROVIDES_${PN}-fans += "virtual-obmc-fan-mgmt"
+RPROVIDES_${PN}-flash += "virtual-obmc-flash-mgmt"
+RPROVIDES_${PN}-system += "virtual-obmc-system-mgmt"
+
+SUMMARY_${PN}-chassis = "Intel Chassis"
+RDEPENDS_${PN}-chassis = " \
+ x86-power-control \
+ "
+
+SUMMARY_${PN}-fans = "Intel Fans"
+RDEPENDS_${PN}-fans = " \
+ phosphor-pid-control \
+ "
+
+SUMMARY_${PN}-flash = "Intel Flash"
+RDEPENDS_${PN}-flash = ""
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend
new file mode 100644
index 000000000..1921d8e3a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend
@@ -0,0 +1,4 @@
+RDEPENDS_${PN}-extrasdevtools = "libgpiod-tools"
+RDEPENDS_${PN}-chassis-state-mgmt_remove = "obmc-phosphor-power"
+
+RDEPENDS_${PN}-settings = "settings"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/psu-manager/psu-manager.bb b/meta-openbmc-mods/meta-common/recipes-intel/psu-manager/psu-manager.bb
new file mode 100644
index 000000000..daeced419
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/psu-manager/psu-manager.bb
@@ -0,0 +1,26 @@
+SUMMARY = "Power supply manager for Intel based platform"
+DESCRIPTION = "Power supply manager which include PSU Cold Redundancy service"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+S = "${WORKDIR}/git/psu-manager/"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+inherit cmake
+inherit systemd
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.coldredundancy.service"
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ phosphor-dbus-interfaces \
+ phosphor-logging \
+ boost \
+ i2c-tools \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb
new file mode 100644
index 000000000..97866ba4e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb
@@ -0,0 +1,33 @@
+SUMMARY = "SMBIOS MDR version 1 service for Intel based platform"
+DESCRIPTION = "SMBIOS MDR version 1 service for Intel based platfrom"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh;nobranch=1"
+SRCREV = "6aab8bcc8fd0550753c87265036b1b7c4c8a9f71"
+
+S = "${WORKDIR}/git/services/smbios/"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+inherit cmake pkgconfig pythonnative
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE_${PN} += "smbios-mdrv1.service"
+
+DEPENDS += " \
+ autoconf-archive-native \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ phosphor-logging \
+ "
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-dbus-interfaces \
+ phosphor-logging \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1/smbios-mdrv1.service b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1/smbios-mdrv1.service
new file mode 100644
index 000000000..edfd3bf70
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1/smbios-mdrv1.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Intel BMC SMBIOS MDR V1
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+ExecStartPre=/bin/mkdir -p /etc/smbios
+ExecStart=/usr/bin/env smbiosapp
+SyslogIdentifier=smbiosapp
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
new file mode 100644
index 000000000..f921704f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
@@ -0,0 +1,30 @@
+SUMMARY = "SMBIOS MDR version 2 service for Intel based platform"
+DESCRIPTION = "SMBIOS MDR version 2 service for Intel based platfrom"
+
+SRC_URI = "git://github.com/Intel-BMC/mdrv2.git;protocol=ssh"
+SRCREV = "e1d574504a16282fe86a0ca02a821ebdcd220774"
+
+S = "${WORKDIR}/git"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+inherit cmake pkgconfig pythonnative
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE_${PN} += "smbios-mdrv2.service"
+
+DEPENDS += " \
+ autoconf-archive-native \
+ boost \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ phosphor-logging \
+ "
+
+EXTRA_OECMAKE += "-DDIMM_DBUS=OFF"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service
new file mode 100644
index 000000000..342d17b13
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Intel BMC SMBIOS MDR V2
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+ExecStartPre=/bin/mkdir -p /var/lib/smbios
+ExecStart=/usr/bin/env smbiosmdrv2app
+SyslogIdentifier=smbiosmdrv2app
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
new file mode 100644
index 000000000..5c4fb8a25
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
@@ -0,0 +1,510 @@
+From 2399c5d353e4b8dc55bd7c56bb3f1d01918bccd9 Mon Sep 17 00:00:00 2001
+From: Yuan Li <yuan.li@linux.intel.com>
+Date: Tue, 19 Sep 2017 15:55:39 +0800
+Subject: [PATCH] arm: dts: add DTS for Intel ast2500 platforms
+
+Add the DTS file for Intel ast2500-based systems.
+
+Signed-off-by: Yuan Li <yuan.li@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+Signed-off-by: Zhu, Yunge <yunge.zhu@linux.intel.com>
+Signed-off-by: Qiang XU <qiang.xu@linux.intel.com>
+Signed-off-by: Chen Yugang <yugang.chen@linux.intel.com>
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+---
+ .../arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 477 ++++++++++++++++++
+ 1 file changed, 477 insertions(+)
+ create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+new file mode 100644
+index 000000000000..980e2b55a09a
+--- /dev/null
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+@@ -0,0 +1,477 @@
++/dts-v1/;
++
++#include "aspeed-g5.dtsi"
++#include <dt-bindings/gpio/aspeed-gpio.h>
++#include <dt-bindings/i2c/i2c.h>
++
++/ {
++ model = "Intel AST2500 BMC";
++ compatible = "intel,ast2500-bmc", "aspeed,ast2500";
++
++ aliases {
++ serial4 = &uart5;
++ };
++
++ chosen {
++ stdout-path = &uart5;
++ bootargs = "console=ttyS4,115200 earlyprintk";
++ };
++
++ memory@80000000 {
++ reg = <0x80000000 0x20000000>;
++ };
++
++ reserved-memory {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ vga_memory: framebuffer@7f000000 {
++ no-map;
++ reg = <0x7f000000 0x01000000>;
++ };
++
++ gfx_memory: framebuffer {
++ size = <0x01000000>;
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++
++ video_engine_memory: jpegbuffer {
++ size = <0x02000000>; /* 32M */
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++
++ ramoops@9eff0000{
++ compatible = "ramoops";
++ reg = <0x9eff0000 0x10000>;
++ record-size = <0x2000>;
++ console-size = <0x2000>;
++ };
++ };
++
++ vga-shared-memory {
++ compatible = "aspeed,ast2500-vga-sharedmem";
++ reg = <0x9ff00000 0x100000>;
++ };
++
++ iio-hwmon {
++ compatible = "iio-hwmon";
++ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
++ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>,
++ <&adc 8>, <&adc 9>, <&adc 10>, <&adc 11>,
++ <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ identify {
++ default-state = "on";
++ gpios = <&gpio ASPEED_GPIO(S, 6) GPIO_ACTIVE_LOW>;
++ };
++
++ status_amber {
++ default-state = "off";
++ gpios = <&gpio ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>;
++ };
++
++ status_green {
++ default-state = "keep";
++ gpios = <&gpio ASPEED_GPIO(S, 4) GPIO_ACTIVE_LOW>;
++ };
++ };
++
++ beeper {
++ compatible = "pwm-beeper";
++ pwms = <&timer 6 1000000 0>;
++ };
++};
++
++&fmc {
++ status = "okay";
++ flash@0 {
++ status = "okay";
++ m25p,fast-read;
++#include "openbmc-flash-layout-intel-64MB.dtsi"
++ };
++};
++
++&espi {
++ status = "okay";
++};
++
++&jtag {
++ status = "okay";
++};
++
++&peci0 {
++ status = "okay";
++ gpios = <&gpio ASPEED_GPIO(F, 6) 0>;
++};
++
++&syscon {
++ uart-clock-high-speed;
++ status = "okay";
++
++ misc_control {
++ compatible = "aspeed,bmc-misc";
++ uart_port_debug {
++ offset = <0x2c>;
++ bit-mask = <0x1>;
++ bit-shift = <10>;
++ read-only;
++ };
++ p2a-bridge {
++ offset = <0x180>;
++ bit-mask = <0x1>;
++ bit-shift = <1>;
++ read-only;
++ };
++ boot-2nd-flash {
++ offset = <0x70>;
++ bit-mask = <0x1>;
++ bit-shift = <17>;
++ read-only;
++ };
++ chip_id {
++ offset = <0x150>;
++ bit-mask = <0x0fffffff 0xffffffff>;
++ bit-shift = <0>;
++ read-only;
++ reg-width = <64>;
++ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474";
++ };
++ };
++};
++
++&adc {
++ status = "okay";
++};
++
++&gpio {
++ status = "okay";
++ gpio-line-names =
++ /*A0-A7*/ "","","","","","","","",
++ /*B0-B7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","","","",
++ /*C0-C7*/ "","","","","","","","",
++ /*D0-D7*/ "","","","","","","","",
++ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","DEBUG_EN_N","","",
++ /*F0-F7*/ "NMI_OUT","","","","CPU_ERR0","CPU_ERR1","PLTRST_N","PRDY_N",
++ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","LCP_ENTER_BUTTON","LCP_LEFT_BUTTON","FM_BMC_BOARD_SKU_ID5_N","","",
++ /*H0-H7*/ "","","","FM_NODE_ID_1","FM_NODE_ID_2","FM_NODE_ID_3","FM_NODE_ID_4","FM_240VA_STATUS",
++ /*I0-I7*/ "FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N","FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","",
++ /*J0-J7*/ "","","","","","","","",
++ /*K0-K7*/ "","","","","","","","",
++ /*L0-L7*/ "","","","","","","","",
++ /*M0-M7*/ "","","","","","","","",
++ /*N0-N7*/ "","","","","","","","",
++ /*O0-O7*/ "","","","","","","","",
++ /*P0-P7*/ "","","","","","","","",
++ /*Q0-Q7*/ "","","","","","","","PWR_DEBUG_N",
++ /*R0-R7*/ "","XDP_PRST_N","","","","","","CHASSIS_INTRUSION",
++ /*S0-S7*/ "REMOTE_DEBUG_ENABLE","SYSPWROK","RSMRST_N","","","","","",
++ /*T0-T7*/ "","","","","","","","",
++ /*U0-U7*/ "","","","","","","","",
++ /*V0-V7*/ "","","","","","","","",
++ /*W0-W7*/ "","","","","","","","",
++ /*X0-X7*/ "","","","","","","","",
++ /*Y0-Y7*/ "SIO_S3","SIO_S5","","SIO_ONCONTROL","","","","",
++ /*Z0-Z7*/ "","SIO_POWER_GOOD","","","","","","",
++ /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE",
++ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","",
++ /*AC0-AC7*/ "","","","","","","","";
++};
++
++&sgpio {
++ status = "okay";
++ gpio-line-names =
++ /* SGPIO output lines */
++ /*OA0-OA7*/ "","","","","","","","",
++ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT",
++ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT",
++ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT",
++ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT",
++ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT",
++ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT",
++ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT",
++ /*OI0-OI7*/ "","","","","","","","",
++ /*OJ0-OJ7*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
++
++ /* SGPIO input lines */
++ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_ABCD_VRHOT","CPU1_MEM_EFGH_VRHOT","","",
++ /*IB0-IB7*/ "CPU1_MISMATCH","CPU1_MEM_THERM_EVENT","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT",
++ /*IC0-IC7*/ "","","CPU2_MISMATCH","CPU2_MEM_THERM_EVENT","","","","",
++ /*ID0-ID7*/ "","","","","","","","",
++ /*IE0-IE7*/ "","","","","","","","",
++ /*IF0-IF7*/ "","","","","","","","",
++ /*IG0-IG7*/ "","","","","","","","",
++ /*IH0-IH7*/ "","","","","","","","",
++ /*II0-II7*/ "","","","","","","","",
++ /*IJ0-IJ7*/ "","","","","","","","";
++};
++
++&kcs3 {
++ kcs_addr = <0xCA2>;
++ status = "okay";
++};
++
++&kcs4 {
++ kcs_addr = <0xCA4>;
++ status = "okay";
++};
++
++&sio_regs {
++ status = "okay";
++ sio_status {
++ offset = <0x8C>;
++ bit-mask = <0x1F>;
++ bit-shift = <4>;
++ };
++};
++
++&lpc_sio {
++ status = "okay";
++};
++
++&lpc_snoop {
++ snoop-ports = <0x80>;
++ status = "okay";
++};
++
++&mbox {
++ status = "okay";
++};
++
++&uart_routing {
++ status = "okay";
++};
++
++/**
++ * SAFS through SPI1 is available only on Wilson Point.
++ * These pins are used as fan presence checking gpios in WFP
++ * so commenting it out for now.
++ * &spi1 {
++ * status = "okay";
++ *
++ * flash@0 {
++ * m25p,fast-read;
++ * status = "okay";
++ * };
++ *};
++ */
++
++&uart1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_txd1_default
++ &pinctrl_rxd1_default
++ &pinctrl_nrts1_default
++ &pinctrl_ndtr1_default
++ &pinctrl_ndsr1_default
++ &pinctrl_ncts1_default
++ &pinctrl_ndcd1_default
++ &pinctrl_nri1_default>;
++};
++
++&uart2 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_txd2_default
++ &pinctrl_rxd2_default
++ &pinctrl_nrts2_default
++ &pinctrl_ndtr2_default
++ &pinctrl_ndsr2_default
++ &pinctrl_ncts2_default
++ &pinctrl_ndcd2_default
++ &pinctrl_nri2_default>;
++};
++
++&uart3 {
++ status = "okay";
++};
++
++&uart4 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <>;
++};
++
++&uart5 {
++ status = "okay";
++};
++
++&mac1 {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
++};
++
++&mac0 {
++ status = "okay";
++ use-ncsi;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_rmii1_default>;
++};
++
++&i2c0 {
++ multi-master;
++ general-call;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c1 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c2 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c3 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c4 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c5 {
++ bus-frequency = <1000000>;
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c6 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c7 {
++ multi-master;
++ #retries = <3>;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c9 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c11 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&i2c13 {
++ multi-master;
++ aspeed,dma-buf-size = <4095>;
++ aspeed,hw-timeout-ms = <300>;
++ status = "okay";
++};
++
++&gfx {
++ status = "okay";
++ memory-region = <&gfx_memory>;
++};
++
++&vuart {
++ status = "okay";
++};
++
++&pwm_tacho {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
++ &pinctrl_pwm2_default &pinctrl_pwm3_default
++ &pinctrl_pwm4_default &pinctrl_pwm5_default
++ &pinctrl_pwm6_default &pinctrl_pwm7_default>;
++
++ fan@0 {
++ reg = <0x00>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x00 0x01>;
++ };
++ fan@1 {
++ reg = <0x01>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x02 0x03>;
++ };
++ fan@2 {
++ reg = <0x02>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x04 0x05>;
++ };
++ fan@3 {
++ reg = <0x03>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x06 0x07>;
++ };
++ fan@4 {
++ reg = <0x04>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x08 0x09>;
++ };
++ fan@5 {
++ reg = <0x05>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0A 0x0B>;
++ };
++ fan@6 {
++ reg = <0x06>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0C 0x0D>;
++ };
++ fan@7 {
++ reg = <0x07>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x0E 0x0F>;
++ };
++
++};
++
++&timer {
++/*
++ * Available settings:
++ * fttmr010,pwm-outputs = <5>, <6>, <7>, <8>;
++ * pinctrl-0 = <&pinctrl_timer5_default &pinctrl_timer6_default
++ * &pinctrl_timer7_default &pinctrl_timer8_default>;
++ */
++ fttmr010,pwm-outputs = <6>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_timer6_default>;
++ #pwm-cells = <3>;
++ status = "okay";
++};
++
++&video {
++ status = "okay";
++ memory-region = <&video_engine_memory>;
++};
++
++&vhub {
++ status = "okay";
++};
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch
new file mode 100644
index 000000000..8ad7b3c0a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch
@@ -0,0 +1,557 @@
+From 498b7829800ec27c7787b3ae77ee59e7b10ec40e Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Tue, 19 Sep 2017 15:55:39 +0800
+Subject: [PATCH] arm: dts: add DTS for Intel ast2600 platforms
+
+Add the DTS file for Intel ast2600-based systems.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+Signed-off-by: Chen Yugang <yugang.chen@linux.intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: arun-pm <arun.p.m@linux.intel.com>
+Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com>
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
+---
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 528 +++++++++++++++++++++++++
+ 1 file changed, 528 insertions(+)
+ create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+new file mode 100644
+index 000000000000..c68314d3901b
+--- /dev/null
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+@@ -0,0 +1,528 @@
++// SPDX-License-Identifier: GPL-2.0+
++/dts-v1/;
++
++#include "aspeed-g6.dtsi"
++#include <dt-bindings/gpio/aspeed-gpio.h>
++#include <dt-bindings/i2c/i2c.h>
++
++/ {
++ model = "AST2600 EVB";
++ compatible = "aspeed,ast2600";
++
++ chosen {
++ stdout-path = &uart5;
++ bootargs = "console=tty0 console=ttyS4,115200n8 root=/dev/ram rw init=/linuxrc";
++ };
++
++ memory@80000000 {
++ device_type = "memory";
++ reg = <0x80000000 0x40000000>;
++ };
++
++ reserved-memory {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ gfx_memory: framebuffer {
++ size = <0x01000000>;
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++
++ video_engine_memory: jpegbuffer {
++ size = <0x02000000>; /* 32M */
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ reusable;
++ };
++ };
++
++ reserved-memory {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++ video_memory: video {
++ size = <0x04000000>;
++ alignment = <0x01000000>;
++ compatible = "shared-dma-pool";
++ no-map;
++ };
++ };
++
++ iio-hwmon {
++ compatible = "iio-hwmon";
++ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
++ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
++ <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>,
++ <&adc1 4>, <&adc1 5>, <&adc1 6>, <&adc1 7>;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ identify {
++ default-state = "off";
++ gpios = <&gpio1 ASPEED_GPIO(B, 7) GPIO_ACTIVE_LOW>;
++ };
++
++ status_amber {
++ default-state = "off";
++ gpios = <&gpio1 ASPEED_GPIO(G, 3) GPIO_ACTIVE_LOW>;
++ };
++
++ status_green {
++ default-state = "keep";
++ gpios = <&gpio1 ASPEED_GPIO(G, 2) GPIO_ACTIVE_LOW>;
++ };
++ };
++/*
++ beeper {
++ compatible = "pwm-beeper";
++ pwms = <&timer 7 1000000 0>;
++ }; */
++};
++
++&fmc {
++ status = "okay";
++ flash@0 {
++ status = "okay";
++ spi-max-frequency = <50000000>;
++ spi-tx-bus-width = <4>;
++ m25p,fast-read;
++#include "openbmc-flash-layout-intel-64MB.dtsi"
++ };
++};
++
++&espi {
++ status = "okay";
++};
++
++&mctp {
++ status = "okay";
++};
++
++&peci0 {
++ status = "okay";
++ gpios = <&gpio0 ASPEED_GPIO(F, 6) 0>;
++};
++
++&syscon {
++ uart-clock-high-speed;
++ status = "okay";
++
++ misc_control {
++ compatible = "aspeed,bmc-misc";
++ chip_id {
++ offset = <0x5b0>;
++ bit-mask = <0xffffffff 0xffffffff>;
++ bit-shift = <0>;
++ read-only;
++ reg-width = <64>;
++ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474";
++ };
++ };
++};
++
++#if 0
++ GPIO Alias: (runtime alias -> schematic name)
++ ID_BUTTON -> FP_ID_BTN_N
++ CPU_CATERR -> FM_PLT_BMC_THERMTRIP_N
++ PCH_BMC_THERMTRIP -> FM_PLT_BMC_THERMTRIP_N
++ RESET_BUTTON -> FP_BMC_RST_BTN_N
++ RESET_OUT -> RST_BMC_RSTBTN_OUT_R_N
++ POWER_BUTTON -> FP_BMC_PWR_BTN_R_N
++ POWER_OUT -> FM_BMC_PWR_BTN_N
++ PREQ_N -> DBP_ASD_BMC_PREQ_R_N
++ POST_COMPLETE -> FM_BIOS_POST_CMPLT_BMC_N
++ CPU_ERR0 -> FM_CPU_ERR0_LVT3_N
++ CPU_ERR1 -> FM_CPU_ERR1_LVT3_N
++ CPU_ERR2 -> FM_CPU_ERR2_LVT3_N
++ DEBUG_EN_N -> FM_JTAG_TCK_MUX_SEL_R
++ NMI_OUT -> IRQ_BMC_CPU_NMI_R
++ PLTRST_N -> RST_PLTRST_BMC_N
++ PRDY_N -> DBP_ASD_BMC_PRDY_R_N
++ PWR_DEBUG_N ->
++ XDP_PRST_N ->
++ SYSPWROK ->
++ RSMRST_N ->
++ SIO_S3 -> FM_SLPS3_R_N
++ SIO_S5 -> FM_SLPS4_R_N
++ SIO_ONCONTROL -> FM_BMC_ONCTL_R_N
++ SIO_POWER_GOOD -> PWRGD_CPU0_LVC3_R
++ PS_PWROK -> PWRGD_BMC_PS_PWROK_R
++ P3VBAT_BRIDGE_EN ->
++ TCK_MUX_SEL ->
++ SMI -> IRQ_SMI_ACTIVE_BMC_N
++ NMI_BUTTON -> FP_NMI_BTN_N
++#endif
++&gpio0 {
++ status = "okay";
++ /* Enable GPIOP0 and GPIOP2 pass-through by default */
++ /* pinctrl-names = "pass-through";
++ pinctrl-0 = <&pinctrl_thru0_default
++ &pinctrl_thru1_default>; */
++ gpio-line-names =
++ /*A0-A7*/ "","","","","SMB_CPU_PIROM_SCL","SMB_CPU_PIROM_SDA","SMB_IPMB_STBY_LVC3_R_SCL","SMB_IPMB_STBY_LVC3_R_SDA",
++ /*B0-B7*/ "FM_1200VA_OC","NMI_OUT","IRQ_SMB3_M2_ALERT_N","","RGMII_BMC_RMM4_LVC3_R_MDC","RGMII_BMC_RMM4_LVC3_R_MDIO","FM_BMC_BMCINIT_R","FP_ID_LED_N",
++ /*C0-C7*/ "FM_FORCE_BMC_UPDATE_N","RST_RGMII_PHYRST_N","FM_TPM_EN_PULSE","FM_BMC_CRASHLOG_TRIG_N","IRQ_BMC_PCH_NMI_R","FM_CPU1_DISABLE_COD_N","FM_4S_8S_N_MODE","FM_STANDALONE_MODE_N",
++ /*D0-D7*/ "CPU_ERR0","CPU_ERR1","CPU_ERR2","PRDY_N","FM_SPD_SWITCH_CTRL_N","","","",
++ /*E0-E7*/ "FM_SKT1_FAULT_LED","FM_SKT0_FAULT_LED","CLK_50M_CKMNG_BMCB","FM_BMC_BOARD_REV_ID2_N","","","","",
++ /*F0-F7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","FM_BMC_BOARD_SKU_ID5_N","ID_BUTTON","PS_PWROK",
++ /*G0-G7*/ "FM_SMB_BMC_NVME_LVC3_ALERT_N","RST_BMC_I2C_M2_R_N","FP_LED_STATUS_GREEN_N","FP_LED_STATUS_AMBER_N","FM_BMC_BOARD_REV_ID0_N","FM_BMC_BOARD_REV_ID1_N","FM_BMC_CPU_FBRK_OUT_R_N","DBP_PRESENT_IN_R2_N",
++ /*H0-H7*/ "SGPIO_BMC_CLK_R","SGPIO_BMC_LD_R","SGPIO_BMC_DOUT_R","SGPIO_BMC_DIN","PLTRST_N","CPU_CATERR","PCH_BMC_THERMTRIP","",
++ /*I0-I7*/ "JTAG_ASD_NTRST_R_N","JTAG_ASD_TDI_R","JTAG_ASD_TCK_R","JTAG_ASD_TMS_R","JTAG_ASD_TDO","FM_BMC_PWRBTN_OUT_R_N","FM_BMC_PWR_BTN_N","",
++ /*J0-J7*/ "SMB_CHASSENSOR_STBY_LVC3_SCL","SMB_CHASSENSOR_STBY_LVC3_SDA","FM_NODE_ID0","FM_NODE_ID1","","","","",
++ /*K0-K7*/ "SMB_HSBP_STBY_LVC3_R_SCL","SMB_HSBP_STBY_LVC3_R_SDA","SMB_SMLINK0_STBY_LVC3_R2_SCL","SMB_SMLINK0_STBY_LVC3_R2_SDA","SMB_TEMPSENSOR_STBY_LVC3_R_SCL","SMB_TEMPSENSOR_STBY_LVC3_R_SDA","SMB_PMBUS_SML1_STBY_LVC3_R_SCL","SMB_PMBUS_SML1_STBY_LVC3_R_SDA",
++ /*L0-L7*/ "SMB_PCIE_STBY_LVC3_R_SCL","SMB_PCIE_STBY_LVC3_R_SDA","SMB_HOST_STBY_BMC_LVC3_R_SCL","SMB_HOST_STBY_BMC_LVC3_R_SDA","PREQ_N","TCK_MUX_SEL","V_BMC_GFX_HSYNC_R","V_BMC_GFX_VSYNC_R",
++ /*M0-M7*/ "SPA_CTS_N","SPA_DCD_N","SPA_DSR_N","PU_SPA_RI_N","SPA_DTR_N","SPA_RTS_N","SPA_SOUT","SPA_SIN",
++ /*N0-N7*/ "SPB_CTS_N","SPB_DCD_N","SPB_DSR_N","PU_SPB_RI_N","SPB_DTR_N","SPB_RTS_N","SPB_SOUT","SPB_SIN",
++ /*O0-O7*/ "FAN_BMC_PWM0","FAN_BMC_PWM1","FAN_BMC_PWM2","FAN_BMC_PWM3","FAN_BMC_PWM4","FAN_BMC_PWM5","NMI_BUTTON","SPEAKER_BMC_R",
++ /*P0-P7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","FAN_BMC_PWM6","FAN_BMC_PWM7","FAN_BMC_PWM8","FAN_BMC_PWM9",
++ /*Q0-Q7*/ "FAN_BMC_TACH0","FAN_BMC_TACH1","FAN_BMC_TACH2","FAN_BMC_TACH3","FAN_BMC_TACH4","FAN_BMC_TACH5","FAN_BMC_TACH6","FAN_BMC_TACH7",
++ /*R0-R7*/ "FAN_BMC_TACH8","FAN_BMC_TACH9","","","","","","",
++ /*S0-S7*/ "RST_BMC_PCIE_MUX_N","FM_BMC_EUP_LOT6_N","","","","A_P3V_BAT_SCALED_EN","REMOTE_DEBUG_ENABLE","FM_PCHHOT_N",
++ /*T0-T7*/ "A_P12V_PSU_SCALED","A_P12V_AUX_SCALED","A_P3V3_SCALED","A_P5V_SCALED","A_PVNN_PCH_AUX_SENSOR","A_P1V05_PCH_AUX_SENSOR","A_P1V8_AUX_SENSOR","A_P3V_BAT_SCALED",
++ /*U0-U7*/ "A_PVCCIN_CPU0_SENSOR","A_PVCCIN_CPU1_SENSOR","A_PVCCINFAON_CPU0_SENSOR","A_PVCCINFAON_CPU1_SENSOR","A_PVCCFA_EHV_FIVRA_CPU0_SENSOR","A_PVCCFA_EHV_FIVRA_CPU1_SENSOR","A_PVCCD_HV_CPU0_SENSOR","A_PVCCD_HV_CPU1_SENSOR",
++ /*V0-V7*/ "SIO_S3","SIO_S5","TP_BMC_SIO_PWREQ_N","SIO_ONCONTROL","SIO_POWER_GOOD","LED_BMC_HB_LED_N","FM_BMC_SUSACK_N","",
++ /*W0-W7*/ "LPC_LAD0_ESPI_R_IO0","LPC_LAD1_ESPI_R_IO1","LPC_LAD2_ESPI_R_IO2","LPC_LAD3_ESPI_R_IO3","CLK_24M_66M_LPC0_ESPI_BMC","LPC_LFRAME_N_ESPI_CS0_BMC_N","IRQ_LPC_SERIRQ_ESPI_ALERT_N","RST_LPC_LRST_ESPI_RST_BMC_R_N",
++ /*X0-X7*/ "","SMI","POST_COMPLETE","","","","","",
++ /*Y0-Y7*/ "","IRQ_SML0_ALERT_BMC_R2_N","","IRQ_SML1_PMBUS_BMC_ALERT_N","SPI_BMC_BOOT_R_IO2","SPI_BMC_BOOT_R_IO3","PU_SPI_BMC_BOOT_ABR","PU_SPI_BMC_BOOT_WP_N",
++ /*Z0-Z7*/ "PWRGD_P3V3_RISER1","PWRGD_P3V3_RISER2","","HW_STRAP_5","HW_STRAP_6","HW_STRAP_7","HW_STRAP_2","HW_STRAP_3";
++};
++
++&gpio1 {
++ status = "disabled";
++ gpio-line-names = /* GPIO18 A-E */
++ /*A0-A7*/ "","","RST_EMMC_BMC_R_N","FM_SYS_FAN6_PRSNT_D_N","FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N",
++ /*B0-B7*/ "FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","FM_SYS_FAN7_PRSNT_D_N","RGMII_BMC_RMM4_TX_R_CLK","RGMII_BMC_RMM4_TX_R_CTRL","RGMII_BMC_RMM4_R_TXD0","RGMII_BMC_RMM4_R_TXD1",
++ /*C0-C7*/ "RGMII_BMC_RMM4_R_TXD2","RGMII_BMC_RMM4_R_TXD3","RGMII_BMC_RMM4_RX_CLK","RGMII_BMC_RMM4_RX_CTRL","RGMII_BMC_RMM4_RXD0","RGMII_BMC_RMM4_RXD1","RGMII_BMC_RMM4_RXD2","RGMII_BMC_RMM4_RXD3",
++ /*D0-D7*/ "EMMC_BMC_R_CLK","EMMC_BMC_R_CMD","EMMC_BMC_R_DATA0","EMMC_BMC_R_DATA1","EMMC_BMC_R_DATA2","EMMC_BMC_R_DATA3","EMMC_BMC_CD_N","EMMC_BMC_WP_N",
++ /*E0-E3*/ "EMMC_BMC_R_DATA4","EMMC_BMC_R_DATA5","EMMC_BMC_R_DATA6","EMMC_BMC_R_DATA7";
++};
++
++&sgpio {
++ status = "okay";
++ gpio-line-names =
++ /* SGPIO output lines */
++ /*OA0-OA7*/ "","","","","","","","",
++ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT",
++ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT",
++ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT",
++ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT",
++ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT",
++ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT",
++ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT",
++ /*OI0-OI7*/ "","","","","","","","",
++ /*OJ0-OJ7*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
++ /*DUMMY*/ "","","","","","","","",
++
++ /* SGPIO input lines */
++ /* Some lines have been renamed from the net names:
++ CPU1_PRESENCE -> FM_CPU0_SKTOCC_LVT3_N
++ CPU1_THERMTRIP -> H_CPU0_THERMTRIP_LVC1_N
++ CPU1_VRHOT -> IRQ_CPU0_VRHOT_N
++ CPU1_FIVR_FAULT -> H_CPU0_MON_FAIL_PLD_LVC1_N
++ CPU1_MEM_ABCD_VRHOT -> ??
++ CPU1_MEM_EFGH_VRHOT -> ??
++ CPU2_PRESENCE -> FM_CPU1_SKTOCC_LVT3_N
++ CPU2_THERMTRIP -> H_CPU1_THERMTRIP_LVC1_N
++ CPU2_VRHOT -> IRQ_CPU1_VRHOT_N
++ CPU2_FIVR_FAULT -> H_CPU1_MON_FAIL_PLD_LVC1_N
++ CPU2_MEM_ABCD_VRHOT -> ??
++ CPU2_MEM_EFGH_VRHOT -> ??
++
++ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","IRQ_CPU0_MEM_VRHOT_N","H_CPU0_MEMHOT_OUT_LVC1_N","FM_CPU0_PROC_ID0","FM_CPU0_PROC_ID1",
++ /*IB0-IB7*/ "WCPU_MISMATCH","IRQ_PSYS_CRIT_N","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","IRQ_CPU1_MEM_VRHOT_N","H_CPU1_MEMHOT_OUT_LVC1_N",
++ /*IC0-IC7*/ "FM_CPU1_PROC_ID0","FM_CPU1_PROC_ID1","","","","","","",
++ /*ID0-ID7*/ "","","","","","","","",
++ /*IE0-IE7*/ "","","","","","","","",
++ /*IF0-IF7*/ "FPGA_REV_TEST_0","FPGA_REV_TEST_1","FPGA_REV_TEST_2","FPGA_REV_TEST_3","FPGA_REV_TEST_4","FPGA_REV_TEST_5","FPGA_REV_TEST_6","FPGA_REV_TEST_7",
++ /*IG0-IG7*/ "FPGA_REV_0","FPGA_REV_1","FPGA_REV_2","FPGA_REV_3","FPGA_REV_4","FPGA_REV_5","FPGA_REV_6","FPGA_REV_7",
++ /*IH0-IH7*/ "","WMEMX_PWR_FLT","WCPUX_MEM_PWR_FLT","PWRGD_P3V3_FF","WPSU_PWR_FLT","","","WPCH_PWR_FLT",
++ /*II0-II7*/ "FM_CPU0_PKGID0","FM_CPU0_PKGID1","FM_CPU0_PKGID2","H_CPU0_MEMTRIP_LVC1_N","FM_CPU1_PKGID0","FM_CPU1_PKGID1","FM_CPU1_PKGID2","H_CPU1_MEMTRIP_LVC1_N",
++ /*IJ0-IJ7*/ "","","","","","","","";
++};
++
++&kcs3 {
++ kcs_addr = <0xCA2>;
++ status = "okay";
++};
++
++&kcs4 {
++ kcs_addr = <0xCA4>;
++ status = "okay";
++};
++
++&sio_regs {
++ status = "okay";
++ sio_status {
++ offset = <0x8C>;
++ bit-mask = <0x1F>;
++ bit-shift = <4>;
++ };
++};
++
++&lpc_sio {
++ status = "okay";
++};
++
++&lpc_snoop {
++ snoop-ports = <0x80>;
++ status = "okay";
++};
++
++&mbox {
++ status = "okay";
++};
++
++&mdio1 {
++ status = "okay";
++
++ ethphy1: ethernet-phy@0 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <0>;
++ };
++};
++
++&mac1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_rgmii2_default>;
++ clocks = <&syscon ASPEED_CLK_GATE_MAC2CLK>,
++ <&syscon ASPEED_CLK_MAC2RCLK>;
++ clock-names = "MACCLK", "RCLK";
++ phy-mode = "rgmii";
++ phy-handle = <&ethphy1>;
++};
++
++&mdio2 {
++ status = "okay";
++
++ ethphy2: ethernet-phy@1 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <0>;
++ };
++};
++
++&adc0 {
++ status = "okay";
++};
++
++&adc1 {
++ status = "okay";
++};
++
++&uart1 {
++ status = "okay";
++ pinctrl-0 = <&pinctrl_txd1_default
++ &pinctrl_rxd1_default
++ &pinctrl_nrts1_default
++ &pinctrl_ndtr1_default
++ &pinctrl_ndsr1_default
++ &pinctrl_ncts1_default
++ &pinctrl_ndcd1_default
++ &pinctrl_nri1_default>;
++};
++
++&uart2 {
++ status = "okay";
++ pinctrl-0 = <&pinctrl_txd2_default
++ &pinctrl_rxd2_default
++ &pinctrl_nrts2_default
++ &pinctrl_ndtr2_default
++ &pinctrl_ndsr2_default
++ &pinctrl_ncts2_default
++ &pinctrl_ndcd2_default
++ &pinctrl_nri2_default>;
++};
++
++&uart3 {
++ status = "okay";
++ pinctrl-0 = <>;
++};
++
++&uart4 {
++ status = "okay";
++ pinctrl-0 = <>;
++};
++
++&uart5 {
++ status = "okay";
++ // Workaround for A0
++ compatible = "snps,dw-apb-uart";
++};
++
++&uart_routing {
++ status = "okay";
++};
++
++&emmc_controller{
++ status = "okay";
++};
++
++&emmc {
++ non-removable;
++ bus-width = <4>;
++ max-frequency = <52000000>;
++};
++
++&i2c0 {
++ /* SMB_CHASSENSOR_STBY_LVC3 */
++ multi-master;
++ status = "okay";
++};
++
++&i2c4 {
++ /* SMB_HSBP_STBY_LVC3_R */
++ multi-master;
++ status = "okay";
++};
++
++&i2c5 {
++ /* SMB_SMLINK0_STBY_LVC3_R2 */
++ bus-frequency = <1000000>;
++ multi-master;
++ status = "okay";
++};
++
++&i2c6 {
++ /* SMB_TEMPSENSOR_STBY_LVC3_R */
++ multi-master;
++ status = "okay";
++};
++
++&i2c7 {
++ /* SMB_PMBUS_SML1_STBY_LVC3_R */
++ multi-master;
++ #retries = <3>;
++ status = "okay";
++};
++
++&i2c8 {
++ /* SMB_PCIE_STBY_LVC3_R */
++ multi-master;
++ status = "okay";
++};
++
++&i2c9 {
++ /* SMB_HOST_STBY_BMC_LVC3_R */
++ multi-master;
++ status = "okay";
++};
++
++&i2c12 {
++ /* SMB_CPU_PIROM */
++ multi-master;
++ status = "okay";
++};
++
++&i2c13 {
++ /* SMB_IPMB_STBY_LVC3_R */
++ multi-master;
++ status = "okay";
++};
++
++&i3cglobal {
++ status = "okay";
++};
++
++&i3c0 {
++ /* I3C_SPD_DDRABCD_CPU0_BMC */
++ status = "okay";
++};
++
++&i3c1 {
++ /* I3C_SPD_DDREFGH_CPU0_BMC */
++ status = "okay";
++};
++
++&i3c2 {
++ /* I3C_SPD_DDRABCD_CPU1_BMC */
++ status = "okay";
++};
++
++&i3c3 {
++ /* I3C_SPD_DDREFGH_CPU1_BMC */
++ status = "okay";
++};
++
++&gfx {
++ status = "okay";
++ memory-region = <&gfx_memory>;
++};
++
++&pcieh {
++ status = "okay";
++};
++
++&pwm_tacho {
++ status = "disabled";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_tach0_default
++ &pinctrl_pwm1_default &pinctrl_tach1_default
++ &pinctrl_pwm2_default &pinctrl_tach2_default
++ &pinctrl_pwm3_default &pinctrl_tach3_default
++ &pinctrl_pwm4_default &pinctrl_tach4_default
++ &pinctrl_pwm5_default &pinctrl_tach5_default
++ &pinctrl_pwm12g1_default &pinctrl_tach6_default
++ &pinctrl_pwm13g1_default &pinctrl_tach7_default
++ &pinctrl_pwm14g1_default &pinctrl_tach8_default
++ &pinctrl_pwm15g1_default &pinctrl_tach9_default>; /*pwm 6-11 used for some other functionality*/
++
++ fan@0 {
++ reg = <0x00>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
++ };
++ fan@1 {
++ reg = <0x01>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
++ };
++ fan@2 {
++ reg = <0x02>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x02>;
++ };
++ fan@3 {
++ reg = <0x03>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x03>;
++ };
++ fan@4 {
++ reg = <0x04>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x04>;
++ };
++ fan@5 {
++ reg = <0x05>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x05>;
++ };
++ fan@6 {
++ reg = <0x06>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x06>;
++ };
++ fan@7 {
++ reg = <0x07>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x07>;
++ };
++ fan@8 {
++ reg = <0x08>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x08>;
++ };
++ fan@9 {
++ reg = <0x09>;
++ aspeed,fan-tach-ch = /bits/ 8 <0x09>;
++ };
++};
++
++&video {
++ status = "okay";
++ memory-region = <&video_engine_memory>;
++};
++
++&vhub {
++ status = "okay";
++};
++
++&jtag1 {
++ status = "okay";
++};
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch
new file mode 100644
index 000000000..d75229a15
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch
@@ -0,0 +1,212 @@
+From 5e5758fe5929766a9b4677b86f9343a777526fe8 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Thu, 12 Sep 2019 15:55:39 +0800
+Subject: [PATCH] arm: dts: base aspeed g6 dtsi fixups
+
+Additions to the base g6 dtsi file for Aspeed ast2600 systems.
+This mostly includes entries for the drivers that are not upstream.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 129 +++++++++++++++++++++++++++++-
+ include/dt-bindings/clock/ast2600-clock.h | 8 ++
+ 2 files changed, 135 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 2af9efa1faa1..54add29d8217 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -28,6 +28,12 @@
+ i2c13 = &i2c13;
+ i2c14 = &i2c14;
+ i2c15 = &i2c15;
++ i3c0 = &i3c0;
++ i3c1 = &i3c1;
++ i3c2 = &i3c2;
++ i3c3 = &i3c3;
++ i3c4 = &i3c4;
++ i3c5 = &i3c5;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+@@ -297,11 +303,21 @@
+ quality = <100>;
+ };
+
++ adc: adc@1e6e9000 {
++ compatible = "aspeed,ast2500-adc";
++ reg = <0x1e6e9000 0x100>;
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
++ resets = <&syscon ASPEED_RESET_ADC>;
++ #io-channel-cells = <1>;
++ status = "disabled";
++ };
++
+ gpio0: gpio@1e780000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2600-gpio";
+- reg = <0x1e780000 0x800>;
++ reg = <0x1e780000 0x200>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&pinctrl 0 0 208>;
+ ngpios = <208>;
+@@ -314,7 +330,7 @@
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2600-gpio";
+- reg = <0x1e780800 0x800>;
++ reg = <0x1e780800 0x200>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&pinctrl 0 208 36>;
+ ngpios = <36>;
+@@ -398,6 +414,13 @@
+ ranges = <0x0 0x1e78b000 0x100>;
+ };
+
++ i3c: bus@1e7a0000 {
++ compatible = "simple-bus";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0 0x1e7a0000 0x8000>;
++ };
++
+ lpc: lpc@1e789000 {
+ compatible = "aspeed,ast2600-lpc", "simple-mfd";
+ reg = <0x1e789000 0x1000>;
+@@ -486,6 +509,20 @@
+ sio_regs: regs {
+ compatible = "aspeed,bmc-misc";
+ };
++
++ lpc_sio: lpc-sio@100 {
++ compatible = "aspeed,ast2500-lpc-sio";
++ reg = <0x100 0x20>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++
++ mbox: mbox@180 {
++ compatible = "aspeed,ast2600-mbox";
++ reg = <0x180 0x5c>;
++ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
++ #mbox-cells = <1>;
++ };
+ };
+ };
+
+@@ -871,3 +908,91 @@
+ status = "disabled";
+ };
+ };
++
++&i3c {
++ i3c0: i3c0@2000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x2000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C0>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ };
++
++ i3c1: i3c1@3000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x3000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C1>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ };
++
++ i3c2: i3c2@4000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x4000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C2>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i3c3_default>;
++ status = "disabled";
++ };
++
++ i3c3: i3c3@5000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x5000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C3>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i3c4_default>;
++ status = "disabled";
++ };
++
++ i3c4: i3c4@6000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x6000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C4>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i3c5_default>;
++ status = "disabled";
++ };
++
++ i3c5: i3c5@7000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x7000 0x1000>;
++ compatible = "snps,dw-i3c-master-1.00a";
++ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_I3C5>;
++ bus-frequency = <100000>;
++ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_i3c6_default>;
++ status = "disabled";
++ };
++};
+diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
+index 62b9520a00fd..3d90582a813f 100644
+--- a/include/dt-bindings/clock/ast2600-clock.h
++++ b/include/dt-bindings/clock/ast2600-clock.h
+@@ -91,6 +91,14 @@
+ /* Only list resets here that are not part of a gate */
+ #define ASPEED_RESET_ADC 55
+ #define ASPEED_RESET_JTAG_MASTER2 54
++#define ASPEED_RESET_I3C7 47
++#define ASPEED_RESET_I3C6 46
++#define ASPEED_RESET_I3C5 45
++#define ASPEED_RESET_I3C4 44
++#define ASPEED_RESET_I3C3 43
++#define ASPEED_RESET_I3C2 42
++#define ASPEED_RESET_I3C1 41
++#define ASPEED_RESET_I3C0 40
+ #define ASPEED_RESET_I3C_DMA 39
+ #define ASPEED_RESET_PWM 37
+ #define ASPEED_RESET_PECI 36
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch
new file mode 100644
index 000000000..08e350c15
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch
@@ -0,0 +1,645 @@
+From 1365492683b47f63d470d0666fee258a5c7ca3c3 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Thu, 12 Sep 2019 15:26:08 -0700
+Subject: [PATCH 04/52] Add Aspeed fmc-spi driver
+
+Add the Aspeed fmc-spi driver from the Apeed SDK v5.02
+
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 43 ++-
+ drivers/spi/Kconfig | 6 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/fmc_spi.c | 530 +++++++++++++++++++++++++++++++
+ 4 files changed, 579 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/spi/fmc_spi.c
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 42f644ac8111..1aab48fbf49e 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -90,7 +90,7 @@
+ <0x40464000 0x2000>,
+ <0x40466000 0x2000>;
+ };
+-
++#if 1
+ fmc: spi@1e620000 {
+ reg = < 0x1e620000 0xc4
+ 0x20000000 0x10000000 >;
+@@ -169,6 +169,47 @@
+ status = "disabled";
+ };
+ };
++#else
++ spi0: spi@1e620000 {
++ /* reg : cs0 : cs1 : cs2 */
++ reg = <0x1e620000 0x100
++ 0x20000000 0x40
++ 0x28000000 0x40>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "aspeed,fmc-spi";
++ clocks = <&syscon ASPEED_CLK_AHB>;
++ status = "disable";
++ number_of_chip_select = /bits/ 16 <2>;
++ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ spi1: spi1@1e630000 {
++ /* reg : cs0 : cs1 */
++ reg = <0x1e630000 0x100
++ 0x30000000 0x20
++ 0x32000000 0x20>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "aspeed,fmc-spi";
++ clocks = <&syscon ASPEED_CLK_AHB>;
++ status = "disable";
++ number_of_chip_select = /bits/ 16 <2>;
++ };
++
++ spi2: spi2@1e631000 {
++ /* reg : cs0 : cs1 */
++ reg = <0x1e631000 0x100
++ 0x38000000 0x20
++ 0x3A000000 0x20>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "aspeed,fmc-spi";
++ clocks = <&syscon ASPEED_CLK_AHB>;
++ status = "disable";
++ number_of_chip_select = /bits/ 16 <2>;
++ };
++#endif
+
+ mdio0: mdio@1e650000 {
+ compatible = "aspeed,ast2600-mdio";
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 6ee514fd0920..9f32c31ffa3c 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -57,6 +57,12 @@ config SPI_MEM
+
+ comment "SPI Master Controller Drivers"
+
++config SPI_FMC
++ tristate "Aspeed FMC SPI Controller"
++ depends on ARCH_ASPEED
++ help
++ This selects a driver for the AST FMC SPI Controller
++
+ config SPI_ALTERA
+ tristate "Altera SPI Controller"
+ help
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index adbebee93a75..224b9b71e29c 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_SPI_SPIDEV) += spidev.o
+ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o
+
+ # SPI master controller drivers (bus)
++obj-$(CONFIG_SPI_FMC) += fmc_spi.o
+ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
+ obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
+ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+diff --git a/drivers/spi/fmc_spi.c b/drivers/spi/fmc_spi.c
+new file mode 100644
+index 000000000000..f21f7a00496e
+--- /dev/null
++++ b/drivers/spi/fmc_spi.c
+@@ -0,0 +1,530 @@
++/*
++ * fmc_spi.c - FMC SPI driver for the Aspeed SoC
++ *
++ * Copyright (C) ASPEED Technology Inc.
++ * Ryan Chen <ryan_chen@aspeedtech.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/errno.h>
++#include <linux/wait.h>
++#include <linux/delay.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++
++/******************************************************************************/
++/* AST_SPI_CONFIG 0x00 : SPI00 CE Type Setting Register */
++#define AST_G5_SPI_CONF_CE1_WEN (0x1 << 17)
++#define AST_G5_SPI_CONF_CE0_WEN (0x1 << 16)
++
++#define SPI_CONF_CE0_WEN (0x1)
++
++/* Register offsets */
++#define FMC_SPI_CONFIG 0x00
++#define FMC_SPI_CTRL 0x04
++#define FMC_SPI_DMA_STS 0x08
++
++#define FMC_SPI_CE0_CTRL 0x10
++#define FMC_SPI_CE1_CTRL 0x14
++
++#define AST_SPI_DMA_CTRL 0x80
++#define AST_SPI_DMA_FLASH_BASE 0x84
++#define AST_SPI_DMA_DRAM_BASE 0x88
++#define AST_SPI_DMA_LENGTH 0x8c
++
++/* AST_FMC_CONFIG 0x00 : FMC00 CE Type Setting Register */
++#define FMC_CONF_LAGACY_DIS (0x1 << 31)
++#define FMC_CONF_CE1_WEN (0x1 << 17)
++#define FMC_CONF_CE0_WEN (0x1 << 16)
++#define FMC_CONF_CE1_SPI (0x2 << 2)
++#define FMC_CONF_CE0_SPI (0x2)
++
++/* FMC_SPI_CTRL : 0x04 : FMC04 CE Control Register */
++#define FMC_CTRL_CE1_4BYTE_MODE (0x1 << 1)
++#define FMC_CTRL_CE0_4BYTE_MODE (0x1)
++
++/* FMC_SPI_DMA_STS : 0x08 : FMC08 Interrupt Control and Status Register */
++#define FMC_STS_DMA_READY 0x0800
++#define FMC_STS_DMA_CLEAR 0x0800
++
++/* FMC_CE0_CTRL for SPI 0x10, 0x14, 0x18, 0x1c, 0x20 */
++#define SPI_IO_MODE_MASK (3 << 28)
++#define SPI_SINGLE_BIT (0 << 28)
++#define SPI_DUAL_MODE (0x2 << 28)
++#define SPI_DUAL_IO_MODE (0x3 << 28)
++#define SPI_QUAD_MODE (0x4 << 28)
++#define SPI_QUAD_IO_MODE (0x5 << 28)
++
++#define SPI_CE_WIDTH(x) (x << 24)
++#define SPI_CMD_DATA_MASK (0xff << 16)
++#define SPI_CMD_DATA(x) (x << 16)
++#define SPI_DUMMY_CMD (1 << 15)
++#define SPI_DUMMY_HIGH (1 << 14)
++//#define SPI_CLK_DIV (1 << 13) ?? TODO ask....
++//#define SPI_ADDR_CYCLE (1 << 13) ?? TODO ask....
++#define SPI_CMD_MERGE_DIS (1 << 12)
++#define SPI_CLK_DIV(x) (x << 8)
++#define SPI_CLK_DIV_MASK (0xf << 8)
++
++#define SPI_DUMMY_LOW_MASK (0x3 << 6)
++#define SPI_DUMMY_LOW(x) ((x) << 6)
++#define SPI_LSB_FIRST_CTRL (1 << 5)
++#define SPI_CPOL_1 (1 << 4)
++#define SPI_DUAL_DATA (1 << 3)
++#define SPI_CE_INACTIVE (1 << 2)
++#define SPI_CMD_MODE_MASK (0x3)
++#define SPI_CMD_NORMAL_READ_MODE 0
++#define SPI_CMD_READ_CMD_MODE 1
++#define SPI_CMD_WRITE_CMD_MODE 2
++#define SPI_CMD_USER_MODE 3
++
++/* AST_SPI_DMA_CTRL 0x80 */
++#define FMC_DMA_ENABLE (0x1)
++
++/******************************************************************************/
++struct fmc_spi_host {
++ void __iomem *base;
++ void __iomem *ctrl_reg;
++ u32 buff[5];
++ struct spi_master *master;
++ struct spi_device *spi_dev;
++ struct device *dev;
++ u32 ahb_clk;
++ spinlock_t lock;
++};
++
++static u32 ast_spi_calculate_divisor(struct fmc_spi_host *host,
++ u32 max_speed_hz)
++{
++ // [0] ->15 : HCLK , HCLK/16
++ u8 SPI_DIV[16] = {
++ 16, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0
++ };
++ u32 i, spi_cdvr = 0;
++
++ for (i = 1; i < 17; i++) {
++ if (max_speed_hz >= (host->ahb_clk / i)) {
++ spi_cdvr = SPI_DIV[i - 1];
++ break;
++ }
++ }
++
++ // printk("hclk is %d, divisor is %d, target :%d , cal speed %d\n", host->ahb_clk, spi_cdvr, spi->max_speed_hz, hclk/i);
++ return spi_cdvr;
++}
++
++/* the spi->mode bits understood by this driver: */
++#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH)
++
++static int fmc_spi_setup(struct spi_device *spi)
++{
++ struct fmc_spi_host *host =
++ (struct fmc_spi_host *)spi_master_get_devdata(spi->master);
++ unsigned int bits = spi->bits_per_word;
++ u32 fmc_config = 0;
++ u32 spi_ctrl = 0;
++ u32 divisor;
++
++ // dev_dbg(host->dev, "fmc_spi_setup() cs: %d, spi->mode %d \n", spi->chip_select, spi->mode);
++ // printk("fmc_spi_setup() cs: %d, spi->mode %d spi->max_speed_hz %d , spi->bits_per_word %d \n", spi->chip_select, spi->mode, spi->max_speed_hz, spi->bits_per_word);
++
++ switch (spi->chip_select) {
++ case 0:
++ fmc_config |= FMC_CONF_CE0_WEN | FMC_CONF_CE0_SPI;
++ host->ctrl_reg = host->base + FMC_SPI_CE0_CTRL;
++ break;
++ case 1:
++ fmc_config |= FMC_CONF_CE1_WEN | FMC_CONF_CE1_SPI;
++ host->ctrl_reg = host->base + FMC_SPI_CE0_CTRL;
++ break;
++ default:
++ dev_dbg(&spi->dev,
++ "setup: invalid chipselect %u (%u defined)\n",
++ spi->chip_select, spi->master->num_chipselect);
++ return -EINVAL;
++ break;
++ }
++ writel(fmc_config, host->base);
++
++ if (bits == 0)
++ bits = 8;
++
++ if (bits < 8 || bits > 16) {
++ dev_dbg(&spi->dev,
++ "setup: invalid bits_per_word %u (8 to 16)\n", bits);
++ return -EINVAL;
++ }
++
++ if (spi->mode & ~MODEBITS) {
++ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
++ spi->mode & ~MODEBITS);
++ return -EINVAL;
++ }
++
++ /* see notes above re chipselect */
++ if ((spi->chip_select == 0) && (spi->mode & SPI_CS_HIGH)) {
++ dev_dbg(&spi->dev, "setup: can't be active-high\n");
++ return -EINVAL;
++ }
++
++ /*
++ * Pre-new_1 chips start out at half the peripheral
++ * bus speed.
++ */
++
++ if (spi->max_speed_hz) {
++ /* Set the SPI slaves select and characteristic control register */
++ divisor = ast_spi_calculate_divisor(host, spi->max_speed_hz);
++ } else {
++ /* speed zero means "as slow as possible" */
++ divisor = 15;
++ }
++
++ spi_ctrl &= ~SPI_CLK_DIV_MASK;
++ // printk("set div %x \n",divisor);
++ //TODO MASK first
++ spi_ctrl |= SPI_CLK_DIV(divisor);
++
++ /* only support mode 0 (CPOL=0, CPHA=0) and cannot support mode 1 ~ mode 3 */
++
++#if 0
++ if (SPI_CPHA & spi->mode)
++ cpha = SPI_CPHA_1;
++ else
++ cpha = SPI_CPHA_0;
++#endif
++
++ // if (SPI_CPOL & spi->mode)
++ // spi_ctrl |= SPI_CPOL_1;
++ // else
++ // spi_ctrl &= ~SPI_CPOL_1;
++
++ //ISSUE : ast spi ctrl couldn't use mode 3, so fix mode 0
++ spi_ctrl &= ~SPI_CPOL_1;
++
++ if (SPI_LSB_FIRST & spi->mode)
++ spi_ctrl |= SPI_LSB_FIRST_CTRL;
++ else
++ spi_ctrl &= ~SPI_LSB_FIRST_CTRL;
++
++ /* Configure SPI controller */
++ writel(spi_ctrl, host->ctrl_reg);
++
++ // printk("ctrl %x, ", spi_ctrl);
++ return 0;
++}
++
++static int fmc_spi_transfer(struct spi_device *spi, struct spi_message *msg)
++{
++ struct fmc_spi_host *host =
++ (struct fmc_spi_host *)spi_master_get_devdata(spi->master);
++ struct spi_transfer *xfer;
++ const u8 *tx_buf;
++ u8 *rx_buf;
++ unsigned long flags;
++
++ int i = 0, j = 0;
++
++ // dev_dbg(host->dev, "xfer %s \n", dev_name(&spi->dev));
++ // printk("xfer spi->chip_select %d \n", spi->chip_select);
++
++ host->spi_dev = spi;
++ spin_lock_irqsave(&host->lock, flags);
++
++ writel(readl(host->ctrl_reg) | SPI_CMD_USER_MODE, host->ctrl_reg);
++ msg->actual_length = 0;
++ msg->status = 0;
++
++ list_for_each_entry (xfer, &msg->transfers, transfer_list) {
++ dev_dbg(host->dev,
++ "xfer[%d] %p: width %d, len %u, tx %p/%08x, rx %p/%08x\n",
++ j, xfer, xfer->bits_per_word, xfer->len, xfer->tx_buf,
++ xfer->tx_dma, xfer->rx_buf, xfer->rx_dma);
++
++ tx_buf = xfer->tx_buf;
++ rx_buf = xfer->rx_buf;
++
++ if (tx_buf != 0) {
++#if 0
++ printk("tx : ");
++ if(xfer->len > 10) {
++ for(i=0;i<10;i++)
++ printk("%x ",tx_buf[i]);
++ } else {
++ for(i=0;i<xfer->len;i++)
++ printk("%x ",tx_buf[i]);
++ }
++ printk("\n");
++#endif
++ for (i = 0; i < xfer->len; i++) {
++ writeb(tx_buf[i],
++ (void *)host->buff
++ [host->spi_dev->chip_select]);
++ }
++ }
++ //Issue need clarify
++ udelay(1);
++ if (rx_buf != 0) {
++ for (i = 0; i < xfer->len; i++) {
++ rx_buf[i] = readb(
++ (void *)host->buff
++ [host->spi_dev->chip_select]);
++ }
++#if 0
++ printk("rx : ");
++ if(xfer->len > 10) {
++ for(i=0;i<10;i++)
++ printk(" %x",rx_buf[i]);
++ } else {
++ for(i=0;i<xfer->len;i++)
++ printk(" %x",rx_buf[i]);
++ }
++ printk("\n");
++#endif
++ }
++ dev_dbg(host->dev, "old msg->actual_length %d , +len %d \n",
++ msg->actual_length, xfer->len);
++ msg->actual_length += xfer->len;
++ dev_dbg(host->dev, "new msg->actual_length %d \n",
++ msg->actual_length);
++ // j++;
++ }
++
++ // writel( SPI_CE_INACTIVE | readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg);
++ writel(readl(host->ctrl_reg) & ~SPI_CMD_USER_MODE, host->ctrl_reg);
++ msg->status = 0;
++
++ msg->complete(msg->context);
++
++ // spin_unlock(&host->lock);
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return 0;
++}
++
++static void fmc_spi_cleanup(struct spi_device *spi)
++{
++ struct fmc_spi_host *host = spi_master_get_devdata(spi->master);
++ unsigned long flags;
++ dev_dbg(host->dev, "fmc_spi_cleanup() \n");
++
++ spin_lock_irqsave(&host->lock, flags);
++ // if (host->stay == spi) {
++ // host->stay = NULL;
++ // cs_deactivate(host, spi);
++ // }
++ spin_unlock_irqrestore(&host->lock, flags);
++}
++
++#if 0
++static int fmc_spi_flash_read(struct spi_device *spi,
++ struct spi_flash_read_message *msg)
++{
++// struct fmc_spi_host *host = spi_master_get_devdata(spi->master);
++ int ret = 0;
++
++// printk("read msg->from %x, msg->len %x , msg->buf %x , msg->addr_width %d , msg->dummy_bytes %x , msg->read_opcode %x \n", msg->from, msg->len, msg->buf, msg->addr_width, msg->dummy_bytes, msg->read_opcode);
++
++// memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len);
++ msg->retlen = msg->len;
++
++ return ret;
++}
++#endif
++
++static int fmc_spi_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ struct fmc_spi_host *host;
++ struct spi_master *master;
++ struct clk *clk;
++ int cs_num = 0;
++ int err = 0;
++
++ dev_dbg(&pdev->dev, "fmc_spi_probe() \n");
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct fmc_spi_host));
++ if (NULL == master) {
++ dev_err(&pdev->dev, "No memory for spi_master\n");
++ err = -ENOMEM;
++ goto err_nomem;
++ }
++
++ /* the spi->mode bits understood by this driver: */
++ master->mode_bits =
++ SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_RX_DUAL | SPI_TX_DUAL;
++ master->bits_per_word_mask = SPI_BPW_MASK(8);
++
++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_RX_DUAL;
++ // master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
++ master->dev.of_node = pdev->dev.of_node;
++ master->bus_num = pdev->id;
++ // master->num_chipselect = master->dev.of_node ? 0 : 4;
++ platform_set_drvdata(pdev, master);
++
++ host = spi_master_get_devdata(master);
++ memset(host, 0, sizeof(struct fmc_spi_host));
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM 0\n");
++ err = -ENXIO;
++ goto err_no_io_res;
++ }
++
++ host->base = devm_ioremap_resource(&pdev->dev, res);
++ if (!host->base) {
++ dev_err(&pdev->dev, "cannot remap register\n");
++ err = -EIO;
++ goto err_no_io_res;
++ }
++
++ clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "no clock defined\n");
++ return -ENODEV;
++ }
++ host->ahb_clk = clk_get_rate(clk);
++
++ dev_dbg(&pdev->dev, "remap phy %x, virt %x \n", (u32)res->start,
++ (u32)host->base);
++
++ host->master = spi_master_get(master);
++
++ if (of_property_read_u16(pdev->dev.of_node, "number_of_chip_select",
++ &host->master->num_chipselect))
++ goto err_register;
++
++ for (cs_num = 0; cs_num < host->master->num_chipselect; cs_num++) {
++ res = platform_get_resource(pdev, IORESOURCE_MEM, cs_num + 1);
++ if (!res) {
++ dev_err(&pdev->dev, "cannot get IORESOURCE_IO 0\n");
++ return -ENXIO;
++ }
++
++ host->buff[cs_num] =
++ (u32)devm_ioremap_resource(&pdev->dev, res);
++ if (!host->buff[cs_num]) {
++ dev_err(&pdev->dev, "cannot remap buffer \n");
++ err = -EIO;
++ goto err_no_io_res;
++ }
++
++ dev_dbg(&pdev->dev, "remap io phy %x, virt %x \n",
++ (u32)res->start, (u32)host->buff[cs_num]);
++ }
++
++ host->master->bus_num = pdev->id;
++ host->dev = &pdev->dev;
++
++ /* Setup the state for bitbang driver */
++ host->master->setup = fmc_spi_setup;
++ host->master->transfer = fmc_spi_transfer;
++ host->master->cleanup = fmc_spi_cleanup;
++ // host->master->spi_flash_read = fmc_spi_flash_read;
++
++ platform_set_drvdata(pdev, host);
++
++ /* Register our spi controller */
++ err = devm_spi_register_master(&pdev->dev, host->master);
++ if (err) {
++ dev_err(&pdev->dev, "failed to register SPI master\n");
++ goto err_register;
++ }
++
++ dev_dbg(&pdev->dev, "fmc_spi : driver load \n");
++
++ return 0;
++
++err_register:
++ spi_master_put(host->master);
++ iounmap(host->base);
++ for (cs_num = 0; cs_num < host->master->num_chipselect; cs_num++) {
++ iounmap((void *)host->buff[cs_num]);
++ }
++
++err_no_io_res:
++ kfree(master);
++ kfree(host);
++
++err_nomem:
++ return err;
++}
++
++static int fmc_spi_remove(struct platform_device *pdev)
++{
++ struct resource *res0;
++ struct fmc_spi_host *host = platform_get_drvdata(pdev);
++
++ dev_dbg(host->dev, "fmc_spi_remove()\n");
++
++ if (!host)
++ return -1;
++
++ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res0->start, res0->end - res0->start + 1);
++ iounmap(host->base);
++ iounmap(host->buff);
++
++ platform_set_drvdata(pdev, NULL);
++ spi_unregister_master(host->master);
++ spi_master_put(host->master);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int fmc_spi_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ return 0;
++}
++
++static int fmc_spi_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++#else
++#define fmc_spi_suspend NULL
++#define fmc_spi_resume NULL
++#endif
++
++static const struct of_device_id fmc_spi_of_match[] = {
++ { .compatible = "aspeed,fmc-spi" },
++ {},
++};
++
++static struct platform_driver fmc_spi_driver = {
++ .probe = fmc_spi_probe,
++ .remove = fmc_spi_remove,
++#ifdef CONFIG_PM
++ .suspend = fmc_spi_suspend,
++ .resume = fmc_spi_resume,
++#endif
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = fmc_spi_of_match,
++ },
++};
++
++module_platform_driver(fmc_spi_driver);
++
++MODULE_DESCRIPTION("FMC SPI Driver");
++MODULE_AUTHOR("Ryan Chen");
++MODULE_LICENSE("GPL");
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch
new file mode 100644
index 000000000..6123b8701
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch
@@ -0,0 +1,173 @@
+From 12ef9a4189cd44212a5a5bd2e1c6fce0756ace9f Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Fri, 3 May 2019 16:12:39 -0700
+Subject: [PATCH] Enable pass-through on GPIOE1 and GPIOE3 free
+
+This change adds a gpio_disable_free() implementation that checks
+if the GPIO being freed is GPIOE1 (33) or GPIOE3 (35) and will
+re-enable the pass-through mux.
+
+Tested:
+Requested GPIOs 33 and 35 and used devmem to check that pass-through
+was disabled. Then freed them and checked that pass-through was
+enabled again.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 17 ++++++++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c | 17 ++++++++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed.c | 53 ++++++++++++++++++++++++++++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed.h | 3 ++
+ 4 files changed, 90 insertions(+)
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+index 0cab4c2576e2..c5406e2da320 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+@@ -2780,6 +2780,22 @@ static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx,
+ return 0;
+ }
+
++#define GPIOE1 33
++#define GPIOE3 35
++static void aspeed_g5_gpio_disable_free(struct pinctrl_dev *pctldev,
++ struct pinctrl_gpio_range *range,
++ unsigned int offset)
++{
++ /*
++ * If we're freeing GPIOE1 (33) or GPIOE3 (35) then re-enable the
++ * pass-through mux setting; otherwise, do nothing.
++ */
++ if (offset != GPIOE1 && offset != GPIOE3)
++ return;
++
++ aspeed_gpio_disable_free(pctldev, range, offset);
++}
++
+ static const struct aspeed_pin_config_map aspeed_g5_pin_config_map[] = {
+ { PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)},
+ { PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)},
+@@ -2815,6 +2831,7 @@ static const struct pinmux_ops aspeed_g5_pinmux_ops = {
+ .get_function_groups = aspeed_pinmux_get_fn_groups,
+ .set_mux = aspeed_pinmux_set_mux,
+ .gpio_request_enable = aspeed_gpio_request_enable,
++ .gpio_disable_free = aspeed_g5_gpio_disable_free,
+ .strict = true,
+ };
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+index fb96e8d2e6c8..bcd8c5656265 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+@@ -2655,6 +2655,22 @@ static int aspeed_g6_sig_expr_set(struct aspeed_pinmux_data *ctx,
+ return 0;
+ }
+
++#define GPIOP1 121
++#define GPIOP3 123
++static void aspeed_g6_gpio_disable_free(struct pinctrl_dev *pctldev,
++ struct pinctrl_gpio_range *range,
++ unsigned int offset)
++{
++ /*
++ * If we're freeing GPIOP1 (121) or GPIOP3 (123) then re-enable the
++ * pass-through mux setting; otherwise, do nothing.
++ */
++ if (offset != GPIOP1 && offset != GPIOP3)
++ return;
++
++ aspeed_gpio_disable_free(pctldev, range, offset);
++}
++
+ static const struct aspeed_pin_config_map aspeed_g6_pin_config_map[] = {
+ { PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)},
+ { PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)},
+@@ -2695,6 +2711,7 @@ static const struct pinmux_ops aspeed_g6_pinmux_ops = {
+ .get_function_groups = aspeed_pinmux_get_fn_groups,
+ .set_mux = aspeed_pinmux_set_mux,
+ .gpio_request_enable = aspeed_gpio_request_enable,
++ .gpio_disable_free = aspeed_g6_gpio_disable_free,
+ .strict = true,
+ };
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+index 53f3f8aec695..ca53f3743d16 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+@@ -375,6 +375,59 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
+ return 0;
+ }
+
++void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev,
++ struct pinctrl_gpio_range *range,
++ unsigned int offset)
++{
++ struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
++ const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
++ const struct aspeed_sig_expr ***prios, **funcs, *expr;
++ int ret;
++
++ if (!pdesc)
++ return;
++
++ dev_dbg(pctldev->dev,
++ "Freeing pass-through pin %s (%d). Re-enabling pass-through.\n",
++ pdesc->name, offset);
++
++ prios = pdesc->prios;
++
++ if (!prios)
++ return;
++
++ /* Disable any functions of higher priority than GPIO just in case */
++ while ((funcs = *prios)) {
++ if (aspeed_gpio_in_exprs(funcs))
++ break;
++
++ ret = aspeed_disable_sig(&pdata->pinmux, funcs);
++ if (ret)
++ return;
++
++ prios++;
++ }
++
++ if (!funcs) {
++ char *signals = get_defined_signals(pdesc);
++
++ pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n",
++ pdesc->name, offset, signals);
++ kfree(signals);
++
++ return;
++ }
++
++ /*
++ * Pass-through should be one priority higher than the GPIO function,
++ * so decrement our prios and enable that function
++ */
++ prios--;
++ funcs = *prios;
++ expr = *funcs;
++ aspeed_sig_expr_enable(&pdata->pinmux, expr);
++}
++
+ int aspeed_pinctrl_probe(struct platform_device *pdev,
+ struct pinctrl_desc *pdesc,
+ struct aspeed_pinctrl_data *pdata)
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+index 4dcde3bc29c8..bd497c20a15f 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+@@ -101,6 +101,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
+ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset);
++void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev,
++ struct pinctrl_gpio_range *range,
++ unsigned int offset);
+ int aspeed_pinctrl_probe(struct platform_device *pdev,
+ struct pinctrl_desc *pdesc,
+ struct aspeed_pinctrl_data *pdata);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch
new file mode 100644
index 000000000..1ee1c68de
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch
@@ -0,0 +1,70 @@
+From b34fdedc21c98db698150d5014e12927a017b07f Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 6 May 2019 14:18:27 -0700
+Subject: [PATCH] Enable GPIOE0 and GPIOE2 pass-through by default
+
+This change sets the gpio DT pinctrl default configuration to
+enable GPIOE0 and GPIOE2 pass-through. Since this causes
+pinctrl_get_select_default() to be called automatically for
+the gpio driver to claim the GPIO pins in those groups, we
+also need to call pinctrl_put() to release claim on the
+pass-through GPIOs so they can be requested at runtime.
+
+Tested:
+Disabled pass-through in uboot and confirmed that after booting
+Linux, pass-through is enabled and 'cat /sys/kernel/debug/pinctrl/
+1e6e2000.syscon\:pinctrl-aspeed-g5-pinctrl/pinmux-pins' shows that
+the pass-through GPIOs are UNCLAIMED.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 4 ++++
+ drivers/gpio/gpio-aspeed.c | 10 ++++++++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+index 72bb1b3..ea1d9cd3 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+@@ -134,6 +134,10 @@
+
+ &gpio {
+ status = "okay";
++ /* Enable GPIOE0 and GPIOE2 pass-through by default */
++ pinctrl-names = "pass-through";
++ pinctrl-0 = <&pinctrl_gpie0_default
++ &pinctrl_gpie2_default>;
+ gpio-line-names =
+ /*A0-A7*/ "","","","","","","","",
+ /*B0-B7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","","","",
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 09e53c5..6165b44 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -1140,6 +1140,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ {
+ const struct of_device_id *gpio_id;
+ struct aspeed_gpio *gpio;
++ struct pinctrl *pinctrl;
+ int rc, i, banks, err;
+ u32 ngpio;
+
+@@ -1190,6 +1191,15 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ /*
++ * Select the pass-through pinctrl config to enable the pass-through
++ * mux for GPIOs marked as pass-through. Then call pinctrl_put() to
++ * release claim of the GPIO pins, so they can be requested at runtime.
++ */
++ pinctrl = pinctrl_get_select(&pdev->dev, "pass-through");
++ if (!IS_ERR(pinctrl))
++ pinctrl_put(pinctrl);
++
++ /*
+ * Populate it with initial values read from the HW and switch
+ * all command sources to the ARM by default
+ */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch
new file mode 100755
index 000000000..7dd9990a9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch
@@ -0,0 +1,45 @@
+From ca0fa975d066b15637188e8fe37dd6d12e0e2bc4 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 28 Apr 2020 22:32:41 +0800
+Subject: [PATCH] Selecting 128MB for PFR
+
+PFR platforms requires 128MB flash mapping.
+This will override the existing 64MB flash map
+and loads 128MB flash map.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 2 +-
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+index 13b94bdf5d62..2cab5fb38d4f 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
+@@ -96,7 +96,7 @@
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+-#include "openbmc-flash-layout-intel-64MB.dtsi"
++#include "openbmc-flash-layout-intel-128MB.dtsi"
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+index a95b5ac828b3..bf66e1b6c0fd 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
+@@ -94,7 +94,7 @@
+ spi-max-frequency = <40000000>;
+ spi-tx-bus-width = <4>;
+ m25p,fast-read;
+-#include "openbmc-flash-layout-intel-64MB.dtsi"
++#include "openbmc-flash-layout-intel-128MB.dtsi"
+ };
+ };
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch
new file mode 100644
index 000000000..b9c14c1ac
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch
@@ -0,0 +1,123 @@
+From 5f984831a3f451e299ecaf42d65dee36ff0ffeee Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Fri, 24 May 2019 12:42:59 -0700
+Subject: [PATCH] Allow monitoring of power control input GPIOs
+
+The pass-through input GPIOs cannot be monitored because when
+requested, pass-through is disabled which causes a change on the
+pass-through output.
+
+The SIO GPIOs cannot be monitored because when requested, the
+request is rejected based on the value of the ACPI strap.
+
+This change removes the register check condition from the pass-
+through and desired SIO GPIOs so they can be requsted and
+monitored from power control.
+
+Tested:
+For pass-through, I used gpioset to hold a request on the input
+GPIOs and confirmed that pass-through remained enabled.
+
+For SIO, I used gpioget to confirm that I can successfully request
+and read the GPIO value.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 10 +++++-----
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c | 10 +++++-----
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+index c5406e2da320..fde74c23ca7f 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+@@ -279,7 +279,7 @@ FUNC_GROUP_DECL(SD2, F19, E21, F20, D20, D21, E20, G18, C21);
+
+ #define B20 32
+ SIG_EXPR_LIST_DECL_SINGLE(B20, NCTS3, NCTS3, SIG_DESC_SET(SCU80, 16));
+-SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE0, GPIE0_DESC);
++SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE0);
+ SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE, GPIE_DESC);
+ SIG_EXPR_LIST_DECL_DUAL(B20, GPIE0IN, GPIE0, GPIE);
+ PIN_DECL_2(B20, GPIOE0, NCTS3, GPIE0IN);
+@@ -299,7 +299,7 @@ FUNC_GROUP_DECL(GPIE0, B20, C20);
+
+ #define F18 34
+ SIG_EXPR_LIST_DECL_SINGLE(F18, NDSR3, NDSR3, SIG_DESC_SET(SCU80, 18));
+-SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE2, GPIE2_DESC);
++SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE2);
+ SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE, GPIE_DESC);
+ SIG_EXPR_LIST_DECL_DUAL(F18, GPIE2IN, GPIE2, GPIE);
+ PIN_DECL_2(F18, GPIOE2, NDSR3, GPIE2IN);
+@@ -1412,7 +1412,7 @@ FUNC_GROUP_DECL(ADC15, H4);
+
+ #define R22 192
+ SIG_EXPR_DECL_SINGLE(SIOS3, SIOS3, SIG_DESC_SET(SCUA4, 8));
+-SIG_EXPR_DECL_SINGLE(SIOS3, ACPI, ACPI_DESC);
++SIG_EXPR_DECL_SINGLE(SIOS3, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(R22, SIOS3, SIOS3, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(R22, DASHR22, DASHR22, SIG_DESC_SET(SCU94, 10));
+ PIN_DECL_2(R22, GPIOY0, SIOS3, DASHR22);
+@@ -1420,7 +1420,7 @@ FUNC_GROUP_DECL(SIOS3, R22);
+
+ #define R21 193
+ SIG_EXPR_DECL_SINGLE(SIOS5, SIOS5, SIG_DESC_SET(SCUA4, 9));
+-SIG_EXPR_DECL_SINGLE(SIOS5, ACPI, ACPI_DESC);
++SIG_EXPR_DECL_SINGLE(SIOS5, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(R21, SIOS5, SIOS5, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(R21, DASHR21, DASHR21, SIG_DESC_SET(SCU94, 10));
+ PIN_DECL_2(R21, GPIOY1, SIOS5, DASHR21);
+@@ -1436,7 +1436,7 @@ FUNC_GROUP_DECL(SIOPWREQ, P22);
+
+ #define P21 195
+ SIG_EXPR_DECL_SINGLE(SIOONCTRL, SIOONCTRL, SIG_DESC_SET(SCUA4, 11));
+-SIG_EXPR_DECL_SINGLE(SIOONCTRL, ACPI, ACPI_DESC);
++SIG_EXPR_DECL_SINGLE(SIOONCTRL, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(P21, SIOONCTRL, SIOONCTRL, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(P21, DASHP21, DASHP21, SIG_DESC_SET(SCU94, 11));
+ PIN_DECL_2(P21, GPIOY3, SIOONCTRL, DASHP21);
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+index bcd8c5656265..c18ceb52c289 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+@@ -762,7 +762,7 @@ SSSF_PIN_DECL(AC23, GPIOO7, PWM7, SIG_DESC_SET(SCU41C, 23));
+
+ #define AB22 120
+ SIG_EXPR_LIST_DECL_SEMG(AB22, PWM8, PWM8G1, PWM8, SIG_DESC_SET(SCU41C, 24));
+-SIG_EXPR_LIST_DECL_SESG(AB22, THRUIN0, THRU0, SIG_DESC_SET(SCU4BC, 24));
++SIG_EXPR_LIST_DECL_SESG(AB22, THRUIN0, THRU0);
+ PIN_DECL_2(AB22, GPIOP0, PWM8, THRUIN0);
+ GROUP_DECL(PWM8G1, AB22);
+ FUNC_DECL_2(PWM8, PWM8G0, PWM8G1);
+@@ -779,7 +779,7 @@ FUNC_DECL_2(PWM9, PWM9G0, PWM9G1);
+
+ #define AA23 122
+ SIG_EXPR_LIST_DECL_SEMG(AA23, PWM10, PWM10G1, PWM10, SIG_DESC_SET(SCU41C, 26));
+-SIG_EXPR_LIST_DECL_SESG(AA23, THRUIN1, THRU1, SIG_DESC_SET(SCU4BC, 26));
++SIG_EXPR_LIST_DECL_SESG(AA23, THRUIN1, THRU1);
+ PIN_DECL_2(AA23, GPIOP2, PWM10, THRUIN1);
+ GROUP_DECL(PWM10G1, AA23);
+ FUNC_DECL_2(PWM10, PWM10G0, PWM10G1);
+@@ -1070,16 +1070,16 @@ FUNC_GROUP_DECL(GPIU7, AC17);
+ FUNC_GROUP_DECL(ADC15, AC17);
+
+ #define AB15 168
+-SSSF_PIN_DECL(AB15, GPIOV0, SIOS3, SIG_DESC_SET(SCU434, 8));
++SSSF_PIN_DECL(AB15, GPIOV0, SIOS3);
+
+ #define AF14 169
+-SSSF_PIN_DECL(AF14, GPIOV1, SIOS5, SIG_DESC_SET(SCU434, 9));
++SSSF_PIN_DECL(AF14, GPIOV1, SIOS5);
+
+ #define AD14 170
+ SSSF_PIN_DECL(AD14, GPIOV2, SIOPWREQ, SIG_DESC_SET(SCU434, 10));
+
+ #define AC15 171
+-SSSF_PIN_DECL(AC15, GPIOV3, SIOONCTRL, SIG_DESC_SET(SCU434, 11));
++SSSF_PIN_DECL(AC15, GPIOV3, SIOONCTRL);
+
+ #define AE15 172
+ SSSF_PIN_DECL(AE15, GPIOV4, SIOPWRGD, SIG_DESC_SET(SCU434, 12));
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch
new file mode 100644
index 000000000..476a07043
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch
@@ -0,0 +1,28 @@
+From b7e8941cf3b1c1c42330207600c91fb23781a77b Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Tue, 2 Jul 2019 10:14:59 -0700
+Subject: [PATCH] aspeed-pwm-tacho: change default fan speed
+
+Change it from max to 58%
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ drivers/hwmon/aspeed-pwm-tacho.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
+index 40c489be62ea..ae5771f881b5 100644
+--- a/drivers/hwmon/aspeed-pwm-tacho.c
++++ b/drivers/hwmon/aspeed-pwm-tacho.c
+@@ -160,7 +160,7 @@
+ */
+ #define M_TACH_MODE 0x02 /* 10b */
+ #define M_TACH_UNIT 0x0210
+-#define INIT_FAN_CTRL 0xFF
++#define INIT_FAN_CTRL 150 /* 58% */
+
+ /* How long we sleep in us while waiting for an RPM result. */
+ #define ASPEED_RPM_STATUS_SLEEP_USEC 500
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch
new file mode 100644
index 000000000..993beb9ec
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch
@@ -0,0 +1,31 @@
+From ea37c85db4d2a593d4f3392e21ec2cc108b111e5 Mon Sep 17 00:00:00 2001
+From: Juston Li <juston.li@intel.com>
+Date: Mon, 27 Mar 2017 11:16:00 -0700
+Subject: [PATCH] arm: dts: aspeed-g5: add espi
+
+Signed-off-by: Juston Li <juston.li@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g5.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 6580b232771e..452ec323534f 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -408,6 +408,13 @@
+ status = "disabled";
+ };
+
++ espi: espi@1e6ee000 {
++ compatible = "aspeed,ast2500-espi-slave";
++ reg = <0x1e6ee000 0x100>;
++ interrupts = <23>;
++ status = "disabled";
++ };
++
+ lpc: lpc@1e789000 {
+ compatible = "aspeed,ast2500-lpc", "simple-mfd";
+ reg = <0x1e789000 0x1000>;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch
new file mode 100644
index 000000000..b9de9f5a9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch
@@ -0,0 +1,117 @@
+From f57d473a30f208754457bdb63512c307f7499ac8 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Mon, 4 Jun 2018 13:45:42 -0700
+Subject: [PATCH] New flash map for intel
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ .../boot/dts/openbmc-flash-layout-intel-128MB.dtsi | 50 ++++++++++++++++++++++
+ .../boot/dts/openbmc-flash-layout-intel-64MB.dtsi | 38 ++++++++++++++++
+ 2 files changed, 88 insertions(+)
+ create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
+ create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
+
+diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
+new file mode 100644
+index 000000000000..0d3794423aed
+--- /dev/null
++++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
+@@ -0,0 +1,50 @@
++// SPDX-License-Identifier: GPL-2.0+
++// 128MB flash layout: PFR (active + tmp1/tmp2 + extra)
++// image with common RW partition
++
++partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ u-boot@0 {
++ reg = <0x0 0x80000>;
++ label = "u-boot";
++ };
++
++ pfm@80000 {
++ reg = <0x80000 0x20000>;
++ label = "pfm";
++ };
++
++ u-boot-env@a0000 {
++ reg = <0xa0000 0x20000>;
++ label = "u-boot-env";
++ };
++
++ sofs@c0000 {
++ reg = <0xc0000 0x200000>;
++ label = "sofs";
++ };
++
++ rwfs@2c0000 {
++ reg = <0x2c0000 0x840000>;
++ label = "rwfs";
++ };
++
++ fit-image-a@b00000 {
++ reg = <0xb00000 0x1f00000>;
++ label = "image-a";
++ };
++
++ rc-image@2a00000 {
++ reg = <0x2a00000 0x2000000>;
++ label = "rc-image";
++ };
++
++ image-staging@4a00000 {
++ reg = <0x4a00000 0x3600000>;
++ label = "image-stg";
++ };
++
++};
+diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
+new file mode 100644
+index 000000000000..092708f5021f
+--- /dev/null
++++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
+@@ -0,0 +1,38 @@
++// SPDX-License-Identifier: GPL-2.0+
++// 64MB flash layout: redundant image with common RW partition
++
++partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ u-boot@0 {
++ reg = <0x0 0x80000>;
++ label = "u-boot";
++ };
++
++ fit-image-a@80000 {
++ reg = <0x80000 0x1b80000>;
++ label = "image-a";
++ };
++
++ sofs@1c00000 {
++ reg = <0x1c00000 0x200000>;
++ label = "sofs";
++ };
++
++ rwfs@1e00000 {
++ reg = <0x1e00000 0x600000>;
++ label = "rwfs";
++ };
++
++ u-boot-env@2400000 {
++ reg = <0x2400000 0x20000>;
++ label = "u-boot-env";
++ };
++
++ fit-image-b@2480000 {
++ reg = <0x2480000 0x1b80000>;
++ label = "image-b";
++ };
++};
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch
new file mode 100644
index 000000000..950272e1b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch
@@ -0,0 +1,760 @@
+From a49e262cca260d15dc245fdd1870c89068042063 Mon Sep 17 00:00:00 2001
+From: "Feist, James" <james.feist@intel.com>
+Date: Tue, 4 Jun 2019 14:00:39 -0700
+Subject: [PATCH] Add ASPEED SGPIO driver
+
+Add SGPIO driver support for Aspeed SoCs.
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/gpio/Kconfig | 8 +
+ drivers/gpio/Makefile | 1 +
+ drivers/gpio/sgpio-aspeed.c | 704 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 713 insertions(+)
+ create mode 100644 drivers/gpio/sgpio-aspeed.c
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 7138290cdd36..0235b20a95f6 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -128,6 +128,14 @@ config GPIO_ASPEED_SGPIO
+ help
+ Say Y here to support Aspeed AST2500 SGPIO functionality.
+
++config SGPIO_ASPEED
++ tristate "ASPEED SGPIO support"
++ depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO
++ select GPIO_GENERIC
++ select GPIOLIB_IRQCHIP
++ help
++ Say Y here to support ASPEED SGPIO functionality.
++
+ config GPIO_ATH79
+ tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
+ default y if ATH79
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index e4599f90f702..0e80c8cd5ae7 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
+ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
+ obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
+ obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio-aspeed-sgpio.o
++obj-$(CONFIG_SGPIO_ASPEED) += sgpio-aspeed.o
+ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
+ obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+ obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
+diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c
+new file mode 100644
+index 000000000000..5028e9144a75
+--- /dev/null
++++ b/drivers/gpio/sgpio-aspeed.c
+@@ -0,0 +1,704 @@
++// SPDX-License-Identifier: GPL-2.0+
++// Copyright (c) 2019 Intel Corporation
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/gpio/driver.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++
++#define ASPEED_SGPIO_CTRL 0x54
++#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
++#define ASPEED_SGPIO_CLK_DIV_MIN 1
++#define ASPEED_SGPIO_CLK_DIV_MAX 65535
++#define ASPEED_SGPIO_PINBYTES_MASK GENMASK(9, 6)
++#define ASPEED_SGPIO_PINBYTES_MIN 1
++#define ASPEED_SGPIO_PINBYTES_MAX 10
++#define ASPEED_SGPIO_ENABLE BIT(0)
++
++#define ASPEED_SGPIO_BUS_FREQ_DEFAULT 1000000
++
++struct aspeed_bank_props {
++ unsigned int bank;
++ u32 input;
++ u32 output;
++};
++
++struct aspeed_sgpio_config {
++ unsigned int nr_pgpios;
++ unsigned int nr_gpios;
++ const struct aspeed_bank_props *props;
++};
++
++struct aspeed_sgpio {
++ struct gpio_chip chip;
++ struct irq_chip irqc;
++ spinlock_t lock;
++ void __iomem *base;
++ int irq;
++ const struct aspeed_sgpio_config *config;
++};
++
++struct aspeed_sgpio_bank {
++ uint16_t val_reg;
++ uint16_t rdata_reg;
++ uint16_t tolerance_reg;
++ uint16_t irq_regs;
++ bool support_irq;
++ const char names[4][3];
++};
++
++/*
++ * Note: The "val" register returns the input value sampled on the line.
++ * Or, it can be used for writing a value on the line.
++ *
++ * The "rdata" register returns the content of the write latch and thus
++ * can be used to read back what was last written reliably.
++ */
++
++static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
++ {
++ .val_reg = 0x0000,
++ .rdata_reg = 0x0070,
++ .tolerance_reg = 0x0018,
++ .irq_regs = 0x0004,
++ .support_irq = false,
++ .names = { "OA", "OB", "OC", "OD" },
++ },
++ {
++ .val_reg = 0x001C,
++ .rdata_reg = 0x0074,
++ .tolerance_reg = 0x0034,
++ .irq_regs = 0x0020,
++ .support_irq = false,
++ .names = { "OE", "OF", "OG", "OH" },
++ },
++ {
++ .val_reg = 0x0038,
++ .rdata_reg = 0x0078,
++ .tolerance_reg = 0x0050,
++ .irq_regs = 0x003C,
++ .support_irq = false,
++ .names = { "OI", "OJ" },
++ },
++ {
++ .val_reg = 0x0000,
++ .rdata_reg = 0x0070,
++ .tolerance_reg = 0x0018,
++ .irq_regs = 0x0004,
++ .support_irq = true,
++ .names = { "IA", "IB", "IC", "ID" },
++ },
++ {
++ .val_reg = 0x001C,
++ .rdata_reg = 0x0074,
++ .tolerance_reg = 0x0034,
++ .irq_regs = 0x0020,
++ .support_irq = true,
++ .names = { "IE", "IF", "IG", "IH" },
++ },
++ {
++ .val_reg = 0x0038,
++ .rdata_reg = 0x0078,
++ .tolerance_reg = 0x0050,
++ .irq_regs = 0x003C,
++ .support_irq = true,
++ .names = { "II", "IJ" },
++ },
++};
++
++enum aspeed_sgpio_reg {
++ reg_val,
++ reg_rdata,
++ reg_irq_enable,
++ reg_irq_type0,
++ reg_irq_type1,
++ reg_irq_type2,
++ reg_irq_status,
++ reg_tolerance,
++};
++
++#define GPIO_IRQ_ENABLE 0x00
++#define GPIO_IRQ_TYPE0 0x04
++#define GPIO_IRQ_TYPE1 0x08
++#define GPIO_IRQ_TYPE2 0x0c
++#define GPIO_IRQ_STATUS 0x10
++
++/* This will be resolved at compile time */
++static inline void __iomem *bank_reg(struct aspeed_sgpio *gpio,
++ const struct aspeed_sgpio_bank *bank,
++ const enum aspeed_sgpio_reg reg)
++{
++ switch (reg) {
++ case reg_val:
++ return gpio->base + bank->val_reg;
++ case reg_rdata:
++ return gpio->base + bank->rdata_reg;
++ case reg_irq_enable:
++ return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE;
++ case reg_irq_type0:
++ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0;
++ case reg_irq_type1:
++ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1;
++ case reg_irq_type2:
++ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
++ case reg_irq_status:
++ return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
++ case reg_tolerance:
++ return gpio->base + bank->tolerance_reg;
++ default:
++ WARN_ON(1);
++ }
++
++ return NULL;
++}
++
++#define GPIO_BANK(x) ((x) >> 5)
++#define GPIO_OFFSET(x) ((x) & 0x1f)
++#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
++
++static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
++{
++ unsigned int bank = GPIO_BANK(offset);
++
++ WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
++ return &aspeed_sgpio_banks[bank];
++}
++
++static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props)
++{
++ return !(props->input || props->output);
++}
++
++static inline const struct aspeed_bank_props *find_bank_props(
++ struct aspeed_sgpio *gpio, unsigned int offset)
++{
++ const struct aspeed_bank_props *props = gpio->config->props;
++
++ while (!is_bank_props_sentinel(props)) {
++ if (props->bank == GPIO_BANK(offset))
++ return props;
++ props++;
++ }
++
++ return NULL;
++}
++
++static inline bool have_input(struct aspeed_sgpio *gpio, unsigned int offset)
++{
++ const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
++
++ return !props || (props->input & GPIO_BIT(offset));
++}
++
++static inline bool have_output(struct aspeed_sgpio *gpio, unsigned int offset)
++{
++ const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
++
++ return !props || (props->output & GPIO_BIT(offset));
++}
++
++static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++ const struct aspeed_sgpio_bank *bank = to_bank(offset);
++ enum aspeed_sgpio_reg reg;
++
++ if (have_output(gpio, offset))
++ reg = reg_rdata;
++ else
++ reg = reg_val;
++
++ return !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
++}
++
++static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
++{
++ const struct aspeed_sgpio_bank *bank = to_bank(offset);
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++ unsigned long flags;
++ u32 reg;
++
++ if (!have_output(gpio, offset))
++ return;
++
++ spin_lock_irqsave(&gpio->lock, flags);
++
++ reg = ioread32(bank_reg(gpio, bank, reg_rdata));
++
++ if (val)
++ reg |= GPIO_BIT(offset);
++ else
++ reg &= ~GPIO_BIT(offset);
++
++ iowrite32(reg, bank_reg(gpio, bank, reg_val));
++
++ spin_unlock_irqrestore(&gpio->lock, flags);
++}
++
++static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++
++ if (!have_input(gpio, offset))
++ return -ENOTSUPP;
++
++ return 0;
++}
++
++static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset,
++ int val)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++
++ if (!have_output(gpio, offset))
++ return -ENOTSUPP;
++
++ aspeed_sgpio_set(gc, offset, val);
++
++ return 0;
++}
++
++static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++
++ if (have_output(gpio, offset))
++ return 0;
++ else if (have_input(gpio, offset))
++ return 1;
++
++ return -ENOTSUPP;
++}
++
++static inline int
++irqd_to_aspeed_sgpio_data(struct irq_data *d, struct aspeed_sgpio **gpio,
++ const struct aspeed_sgpio_bank **bank,
++ u32 *bit, int *offset)
++{
++ struct aspeed_sgpio *internal;
++
++ *offset = irqd_to_hwirq(d);
++
++ internal = irq_data_get_irq_chip_data(d);
++
++ *gpio = internal;
++ *bank = to_bank(*offset);
++ *bit = GPIO_BIT(*offset);
++
++ return 0;
++}
++
++static void aspeed_sgpio_irq_ack(struct irq_data *d)
++{
++ const struct aspeed_sgpio_bank *bank;
++ struct aspeed_sgpio *gpio;
++ void __iomem *status_addr;
++ unsigned long flags;
++ int rc, offset;
++ u32 bit;
++
++ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
++ if (rc)
++ return;
++
++ status_addr = bank_reg(gpio, bank, reg_irq_status);
++
++ spin_lock_irqsave(&gpio->lock, flags);
++
++ iowrite32(bit, status_addr);
++
++ spin_unlock_irqrestore(&gpio->lock, flags);
++}
++
++static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
++{
++ const struct aspeed_sgpio_bank *bank;
++ struct aspeed_sgpio *gpio;
++ unsigned long flags;
++ u32 reg, bit;
++ void __iomem *addr;
++ int rc, offset;
++
++ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
++ if (rc)
++ return;
++
++ if (!bank->support_irq)
++ return;
++
++ addr = bank_reg(gpio, bank, reg_irq_enable);
++
++ spin_lock_irqsave(&gpio->lock, flags);
++
++ reg = ioread32(addr);
++ if (set)
++ reg |= bit;
++ else
++ reg &= ~bit;
++
++ iowrite32(reg, addr);
++
++ spin_unlock_irqrestore(&gpio->lock, flags);
++}
++
++static void aspeed_sgpio_irq_mask(struct irq_data *d)
++{
++ aspeed_sgpio_irq_set_mask(d, false);
++}
++
++static void aspeed_sgpio_irq_unmask(struct irq_data *d)
++{
++ aspeed_sgpio_irq_set_mask(d, true);
++}
++
++static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
++{
++ u32 type0 = 0;
++ u32 type1 = 0;
++ u32 type2 = 0;
++ u32 bit, reg;
++ const struct aspeed_sgpio_bank *bank;
++ irq_flow_handler_t handler;
++ struct aspeed_sgpio *gpio;
++ unsigned long flags;
++ void __iomem *addr;
++ int rc, offset;
++
++ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
++ if (rc)
++ return -EINVAL;
++
++ if (!bank->support_irq)
++ return -ENOTSUPP;
++
++ switch (type & IRQ_TYPE_SENSE_MASK) {
++ case IRQ_TYPE_EDGE_BOTH:
++ type2 |= bit;
++ /* fall through */
++ case IRQ_TYPE_EDGE_RISING:
++ type0 |= bit;
++ /* fall through */
++ case IRQ_TYPE_EDGE_FALLING:
++ handler = handle_edge_irq;
++ break;
++ case IRQ_TYPE_LEVEL_HIGH:
++ type0 |= bit;
++ /* fall through */
++ case IRQ_TYPE_LEVEL_LOW:
++ type1 |= bit;
++ handler = handle_level_irq;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&gpio->lock, flags);
++
++ addr = bank_reg(gpio, bank, reg_irq_type0);
++ reg = ioread32(addr);
++ reg = (reg & ~bit) | type0;
++ iowrite32(reg, addr);
++
++ addr = bank_reg(gpio, bank, reg_irq_type1);
++ reg = ioread32(addr);
++ reg = (reg & ~bit) | type1;
++ iowrite32(reg, addr);
++
++ addr = bank_reg(gpio, bank, reg_irq_type2);
++ reg = ioread32(addr);
++ reg = (reg & ~bit) | type2;
++ iowrite32(reg, addr);
++
++ spin_unlock_irqrestore(&gpio->lock, flags);
++
++ irq_set_handler_locked(d, handler);
++
++ return 0;
++}
++
++static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
++{
++ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
++ struct aspeed_sgpio *data = gpiochip_get_data(gc);
++ struct irq_chip *ic = irq_desc_get_chip(desc);
++ unsigned int i, p, girq;
++ unsigned long reg;
++
++ chained_irq_enter(ic, desc);
++
++ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
++ const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i];
++
++ if (!bank->support_irq)
++ continue;
++
++ reg = ioread32(bank_reg(data, bank, reg_irq_status));
++
++ for_each_set_bit(p, &reg, 32) {
++ girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
++ generic_handle_irq(girq);
++ }
++ }
++
++ chained_irq_exit(ic, desc);
++}
++
++static void aspeed_sgpio_init_irq_valid_mask(struct gpio_chip *gc,
++ unsigned long *valid_mask,
++ unsigned int ngpios)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
++ const struct aspeed_bank_props *props = gpio->config->props;
++
++ while (!is_bank_props_sentinel(props)) {
++ unsigned int offset;
++ const unsigned long int input = props->input;
++
++ /* Pretty crummy approach, but similar to GPIO core */
++ for_each_clear_bit(offset, &input, 32) {
++ unsigned int i = props->bank * 32 + offset;
++
++ if (i >= gpio->chip.ngpio)
++ break;
++
++ clear_bit(i, valid_mask);
++ }
++
++ props++;
++ }
++}
++
++static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
++ struct platform_device *pdev)
++{
++ const struct aspeed_sgpio_bank *bank;
++ struct gpio_irq_chip *girq;
++ int rc, i;
++
++ /* Initialize IRQ and tolerant settings */
++ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
++ bank = &aspeed_sgpio_banks[i];
++
++ /* Value will be reset by WDT reset */
++ iowrite32(0x00000000, bank_reg(gpio, bank, reg_tolerance));
++
++ if (!bank->support_irq)
++ continue;
++
++ /* disable irq enable bits */
++ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable));
++ /* clear status bits */
++ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
++ /* set rising or level-high irq */
++ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type0));
++ /* trigger type is level */
++ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type1));
++ /* single trigger mode */
++ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
++ }
++
++ rc = platform_get_irq(pdev, 0);
++ if (rc < 0)
++ return rc;
++
++ gpio->irq = rc;
++ girq = &gpio->chip.irq;
++ girq->chip = &gpio->irqc;
++ girq->chip->name = dev_name(&pdev->dev);
++ girq->chip->irq_ack = aspeed_sgpio_irq_ack;
++ girq->chip->irq_mask = aspeed_sgpio_irq_mask;
++ girq->chip->irq_unmask = aspeed_sgpio_irq_unmask;
++ girq->chip->irq_set_type = aspeed_sgpio_set_type;
++ girq->parent_handler = aspeed_sgpio_irq_handler;
++ girq->num_parents = 1;
++ girq->parents = devm_kcalloc(&pdev->dev, 1,
++ sizeof(*girq->parents),
++ GFP_KERNEL);
++ if (!girq->parents)
++ return -ENOMEM;
++ girq->parents[0] = gpio->irq;
++ girq->default_type = IRQ_TYPE_NONE;
++ girq->handler = handle_bad_irq;
++ girq->init_valid_mask = aspeed_sgpio_init_irq_valid_mask;
++
++ return 0;
++}
++
++static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
++ unsigned int offset, bool enable)
++{
++ struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
++ unsigned long flags;
++ void __iomem *treg;
++ u32 val;
++
++ treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
++
++ spin_lock_irqsave(&gpio->lock, flags);
++
++ val = readl(treg);
++
++ if (enable)
++ val |= GPIO_BIT(offset);
++ else
++ val &= ~GPIO_BIT(offset);
++
++ writel(val, treg);
++
++ spin_unlock_irqrestore(&gpio->lock, flags);
++
++ return 0;
++}
++
++static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
++ unsigned long config)
++{
++ unsigned long param = pinconf_to_config_param(config);
++ u32 arg = pinconf_to_config_argument(config);
++
++ if (param == PIN_CONFIG_PERSIST_STATE)
++ return aspeed_sgpio_reset_tolerance(chip, offset, arg);
++
++ return -ENOTSUPP;
++}
++
++/*
++ * Any banks not specified in a struct aspeed_bank_props array are assumed to
++ * have the properties:
++ *
++ * { .input = 0xffffffff, .output = 0xffffffff }
++ */
++
++static const struct aspeed_bank_props ast_sgpio_bank_props[] = {
++ /* input output */
++ { 0, 0x00000000, 0xffffffff }, /* OA/OB/OC/OD */
++ { 1, 0x00000000, 0xffffffff }, /* OE/OF/OG/OH */
++ { 2, 0x00000000, 0x0000ffff }, /* OI/OJ */
++ { 3, 0xffffffff, 0x00000000 }, /* IA/IB/IC/ID */
++ { 4, 0xffffffff, 0x00000000 }, /* IE/IF/IG/IH */
++ { 5, 0x0000ffff, 0x00000000 }, /* II/IJ */
++ { }
++};
++
++/*
++ * This H/W has 80 bidirectional lines so this driver provides total 160 lines
++ * for 80 outputs and 80 inputs. To simplify bank register manipulation, it
++ * uses 96 lines per each input and output set so total 192 lines it has.
++ */
++static const struct aspeed_sgpio_config ast2400_config =
++ { .nr_pgpios = 224, .nr_gpios = 192, .props = ast_sgpio_bank_props };
++
++static const struct aspeed_sgpio_config ast2500_config =
++ { .nr_pgpios = 232, .nr_gpios = 192, .props = ast_sgpio_bank_props };
++
++static const struct of_device_id aspeed_sgpio_of_table[] = {
++ { .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_config },
++ { .compatible = "aspeed,ast2500-sgpio", .data = &ast2500_config },
++ { .compatible = "aspeed,ast2600-sgpio", .data = &ast2500_config },
++ { }
++};
++MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
++
++static int __init aspeed_sgpio_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *gpio_id;
++ u32 sgpio_freq, clk_div, nb_gpios;
++ struct aspeed_sgpio *gpio;
++ unsigned long src_freq;
++ struct clk *clk;
++ int rc;
++
++ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
++ if (!gpio)
++ return -ENOMEM;
++
++ gpio->base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(gpio->base))
++ return PTR_ERR(gpio->base);
++
++ spin_lock_init(&gpio->lock);
++
++ gpio_id = of_match_node(aspeed_sgpio_of_table, pdev->dev.of_node);
++ if (!gpio_id)
++ return -EINVAL;
++
++ gpio->config = gpio_id->data;
++
++ rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq);
++ if (rc < 0) {
++ dev_warn(&pdev->dev, "Could not read bus-frequency property. Use default.\n");
++ sgpio_freq = ASPEED_SGPIO_BUS_FREQ_DEFAULT;
++ }
++
++ clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(clk)) {
++ rc = PTR_ERR(clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(&pdev->dev, "Failed to get clk source.\n");
++ return rc;
++ }
++
++ /*
++ * There is a limitation that SGPIO clock division has to be larger or
++ * equal to 1. And a read back value of clock division is 1-bit left
++ * shifted from the actual value.
++ *
++ * GPIO254[31:16] - Serial GPIO clock division:
++ * Serial GPIO clock period = period of PCLK * 2 * (GPIO254[31:16] + 1)
++ *
++ * SGPIO master controller updates every data input when SGPMLD is low.
++ * For an example, SGPIO clock is 1MHz and number of SGPIO is 80. Each
++ * SGPIO will be updated every 80us.
++ */
++ src_freq = clk_get_rate(clk);
++ clk_div = src_freq / (2 * sgpio_freq) - 1;
++ if (clk_div < ASPEED_SGPIO_CLK_DIV_MIN)
++ clk_div = ASPEED_SGPIO_CLK_DIV_MIN;
++ else if (clk_div > ASPEED_SGPIO_CLK_DIV_MAX)
++ clk_div = ASPEED_SGPIO_CLK_DIV_MAX;
++
++ nb_gpios = gpio->config->nr_gpios / 16;
++ if (nb_gpios < ASPEED_SGPIO_PINBYTES_MIN)
++ nb_gpios = ASPEED_SGPIO_PINBYTES_MIN;
++ else if (nb_gpios > ASPEED_SGPIO_PINBYTES_MAX)
++ nb_gpios = ASPEED_SGPIO_PINBYTES_MAX;
++
++ iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, clk_div) |
++ FIELD_PREP(ASPEED_SGPIO_PINBYTES_MASK, nb_gpios) |
++ ASPEED_SGPIO_ENABLE,
++ gpio->base + ASPEED_SGPIO_CTRL);
++
++ gpio->chip.parent = &pdev->dev;
++ gpio->chip.ngpio = gpio->config->nr_gpios;
++
++ gpio->chip.direction_input = aspeed_sgpio_dir_in;
++ gpio->chip.direction_output = aspeed_sgpio_dir_out;
++ gpio->chip.get_direction = aspeed_sgpio_get_direction;
++ gpio->chip.get = aspeed_sgpio_get;
++ gpio->chip.set = aspeed_sgpio_set;
++ gpio->chip.set_config = aspeed_sgpio_set_config;
++ gpio->chip.label = dev_name(&pdev->dev);
++ gpio->chip.base = -1;
++
++ rc = aspeed_sgpio_setup_irqs(gpio, pdev);
++ if (rc < 0)
++ return rc;
++
++ return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
++}
++
++static struct platform_driver aspeed_sgpio_driver = {
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = aspeed_sgpio_of_table,
++ },
++};
++
++module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe);
++
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("Aspeed SGPIO Master Driver");
++MODULE_LICENSE("GPL v2");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch
new file mode 100644
index 000000000..50c31f625
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch
@@ -0,0 +1,227 @@
+From 89b5ebd26fc44b4bf820aa507bc88eec028ba218 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Wed, 16 May 2018 10:03:14 -0700
+Subject: [PATCH] SGPIO DT and pinctrl fixup
+
+This commit fixes DT and pinctrl for SGPIO use.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 56 +++++++++++-------------------
+ arch/arm/boot/dts/aspeed-g5.dtsi | 3 +-
+ arch/arm/boot/dts/aspeed-g6.dtsi | 15 ++++++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c | 48 ++++++++++++-------------
+ 4 files changed, 60 insertions(+), 62 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index b875c0785833..e9fd66ab3099 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -254,6 +254,20 @@
+ #interrupt-cells = <2>;
+ };
+
++ sgpio: sgpio@1e780200 {
++ #gpio-cells = <2>;
++ gpio-controller;
++ compatible = "aspeed,ast2400-sgpio";
++ reg = <0x1e780200 0x0100>;
++ interrupts = <40>;
++ interrupt-controller;
++ clocks = <&syscon ASPEED_CLK_APB>;
++ bus-frequency = <1000000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_sgpm_default>;
++ status = "disabled";
++ };
++
+ timer: timer@1e782000 {
+ /* This timer is a Faraday FTTMR010 derivative */
+ compatible = "aspeed,ast2400-timer";
+@@ -1227,44 +1241,14 @@
+ groups = "SD2";
+ };
+
+- pinctrl_sgpmck_default: sgpmck_default {
+- function = "SGPMCK";
+- groups = "SGPMCK";
+- };
+-
+- pinctrl_sgpmi_default: sgpmi_default {
+- function = "SGPMI";
+- groups = "SGPMI";
+- };
+-
+- pinctrl_sgpmld_default: sgpmld_default {
+- function = "SGPMLD";
+- groups = "SGPMLD";
+- };
+-
+- pinctrl_sgpmo_default: sgpmo_default {
+- function = "SGPMO";
+- groups = "SGPMO";
+- };
+-
+- pinctrl_sgpsck_default: sgpsck_default {
+- function = "SGPSCK";
+- groups = "SGPSCK";
+- };
+-
+- pinctrl_sgpsi0_default: sgpsi0_default {
+- function = "SGPSI0";
+- groups = "SGPSI0";
+- };
+-
+- pinctrl_sgpsi1_default: sgpsi1_default {
+- function = "SGPSI1";
+- groups = "SGPSI1";
++ pinctrl_sgpm_default: sgpm_default {
++ function = "SGPM";
++ groups = "SGPM";
+ };
+
+- pinctrl_sgpsld_default: sgpsld_default {
+- function = "SGPSLD";
+- groups = "SGPSLD";
++ pinctrl_sgps_default: sgps_default {
++ function = "SGPS";
++ groups = "SGPS";
+ };
+
+ pinctrl_sioonctrl_default: sioonctrl_default {
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 452ec323534f..20b2eb8052b7 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -326,8 +326,7 @@
+ reg = <0x1e780200 0x0100>;
+ clocks = <&syscon ASPEED_CLK_APB>;
+ interrupt-controller;
+- ngpios = <8>;
+- bus-frequency = <12000000>;
++ bus-frequency = <1000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgpm_default>;
+ status = "disabled";
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 54add29d8217..459070693aba 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -339,6 +339,21 @@
+ #interrupt-cells = <2>;
+ };
+
++ sgpio: sgpio@1e780500 {
++ #gpio-cells = <2>;
++ gpio-controller;
++ compatible = "aspeed,ast2600-sgpio";
++ reg = <0x1e780500 0x0100>;
++ #interrupt-cells = <2>;
++ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-controller;
++ bus-frequency = <1000000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_sgpm1_default>;
++ clocks = <&syscon ASPEED_CLK_APB1>;
++ status = "disabled";
++ };
++
+ rtc: rtc@1e781000 {
+ compatible = "aspeed,ast2600-rtc";
+ reg = <0x1e781000 0x18>;
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+index bfed0e274643..10dadfd0e6e1 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+@@ -430,16 +430,22 @@ SSSF_PIN_DECL(E16, GPIOF6, TXD4, SIG_DESC_SET(SCU80, 30));
+ SSSF_PIN_DECL(C17, GPIOF7, RXD4, SIG_DESC_SET(SCU80, 31));
+
+ #define A14 48
+-SSSF_PIN_DECL(A14, GPIOG0, SGPSCK, SIG_DESC_SET(SCU84, 0));
++SIG_EXPR_LIST_DECL_SINGLE(A14, SGPSCK, SGPS, SIG_DESC_SET(SCU84, 0));
++PIN_DECL_1(A14, GPIOG0, SGPSCK);
+
+ #define E13 49
+-SSSF_PIN_DECL(E13, GPIOG1, SGPSLD, SIG_DESC_SET(SCU84, 1));
++SIG_EXPR_LIST_DECL_SINGLE(E13, SGPSLD, SGPS, SIG_DESC_SET(SCU84, 1));
++PIN_DECL_1(E13, GPIOG1, SGPSLD);
+
+ #define D13 50
+-SSSF_PIN_DECL(D13, GPIOG2, SGPSI0, SIG_DESC_SET(SCU84, 2));
++SIG_EXPR_LIST_DECL_SINGLE(D13, SGPSIO, SGPS, SIG_DESC_SET(SCU84, 2));
++PIN_DECL_1(D13, GPIOG2, SGPSIO);
+
+ #define C13 51
+-SSSF_PIN_DECL(C13, GPIOG3, SGPSI1, SIG_DESC_SET(SCU84, 3));
++SIG_EXPR_LIST_DECL_SINGLE(C13, SGPSI1, SGPS, SIG_DESC_SET(SCU84, 3));
++PIN_DECL_1(C13, GPIOG3, SGPSI1);
++
++FUNC_GROUP_DECL(SGPS, A14, E13, D13, C13);
+
+ #define B13 52
+ SIG_EXPR_LIST_DECL_SINGLE(B13, OSCCLK, OSCCLK, SIG_DESC_SET(SCU2C, 1));
+@@ -613,16 +619,22 @@ FUNC_GROUP_DECL(SPI1PASSTHRU, C22, G18, D19, C20, B22, G19, C18, E20);
+ FUNC_GROUP_DECL(VGABIOS_ROM, B22, G19, C18, E20);
+
+ #define J5 72
+-SSSF_PIN_DECL(J5, GPIOJ0, SGPMCK, SIG_DESC_SET(SCU84, 8));
++SIG_EXPR_LIST_DECL_SINGLE(J5, SGPMCK, SGPM, SIG_DESC_SET(SCU84, 8));
++PIN_DECL_1(J5, GPIOJ0, SGPMCK);
+
+ #define J4 73
+-SSSF_PIN_DECL(J4, GPIOJ1, SGPMLD, SIG_DESC_SET(SCU84, 9));
++SIG_EXPR_LIST_DECL_SINGLE(J4, SGPMLD, SGPM, SIG_DESC_SET(SCU84, 9));
++PIN_DECL_1(J4, GPIOJ1, SGPMLD);
+
+ #define K5 74
+-SSSF_PIN_DECL(K5, GPIOJ2, SGPMO, SIG_DESC_SET(SCU84, 10));
++SIG_EXPR_LIST_DECL_SINGLE(K5, SGPMO, SGPM, SIG_DESC_SET(SCU84, 10));
++PIN_DECL_1(K5, GPIOJ2, SGPMO);
+
+ #define J3 75
+-SSSF_PIN_DECL(J3, GPIOJ3, SGPMI, SIG_DESC_SET(SCU84, 11));
++SIG_EXPR_LIST_DECL_SINGLE(J3, SGPMI, SGPM, SIG_DESC_SET(SCU84, 11));
++PIN_DECL_1(J3, GPIOJ3, SGPMI);
++
++FUNC_GROUP_DECL(SGPM, J5, J4, K5, J3);
+
+ #define T4 76
+ SSSF_PIN_DECL(T4, GPIOJ4, VGAHS, SIG_DESC_SET(SCU84, 12));
+@@ -2234,14 +2246,8 @@ static const struct aspeed_pin_group aspeed_g4_groups[] = {
+ ASPEED_PINCTRL_GROUP(SALT4),
+ ASPEED_PINCTRL_GROUP(SD1),
+ ASPEED_PINCTRL_GROUP(SD2),
+- ASPEED_PINCTRL_GROUP(SGPMCK),
+- ASPEED_PINCTRL_GROUP(SGPMI),
+- ASPEED_PINCTRL_GROUP(SGPMLD),
+- ASPEED_PINCTRL_GROUP(SGPMO),
+- ASPEED_PINCTRL_GROUP(SGPSCK),
+- ASPEED_PINCTRL_GROUP(SGPSI0),
+- ASPEED_PINCTRL_GROUP(SGPSI1),
+- ASPEED_PINCTRL_GROUP(SGPSLD),
++ ASPEED_PINCTRL_GROUP(SGPM),
++ ASPEED_PINCTRL_GROUP(SGPS),
+ ASPEED_PINCTRL_GROUP(SIOONCTRL),
+ ASPEED_PINCTRL_GROUP(SIOPBI),
+ ASPEED_PINCTRL_GROUP(SIOPBO),
+@@ -2389,14 +2395,8 @@ static const struct aspeed_pin_function aspeed_g4_functions[] = {
+ ASPEED_PINCTRL_FUNC(SALT4),
+ ASPEED_PINCTRL_FUNC(SD1),
+ ASPEED_PINCTRL_FUNC(SD2),
+- ASPEED_PINCTRL_FUNC(SGPMCK),
+- ASPEED_PINCTRL_FUNC(SGPMI),
+- ASPEED_PINCTRL_FUNC(SGPMLD),
+- ASPEED_PINCTRL_FUNC(SGPMO),
+- ASPEED_PINCTRL_FUNC(SGPSCK),
+- ASPEED_PINCTRL_FUNC(SGPSI0),
+- ASPEED_PINCTRL_FUNC(SGPSI1),
+- ASPEED_PINCTRL_FUNC(SGPSLD),
++ ASPEED_PINCTRL_FUNC(SGPM),
++ ASPEED_PINCTRL_FUNC(SGPS),
+ ASPEED_PINCTRL_FUNC(SIOONCTRL),
+ ASPEED_PINCTRL_FUNC(SIOPBI),
+ ASPEED_PINCTRL_FUNC(SIOPBO),
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch
new file mode 100644
index 000000000..128b11ecf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch
@@ -0,0 +1,425 @@
+From f588865f8180a6370ac639bdfc186ffc5b926246 Mon Sep 17 00:00:00 2001
+From: Haiyue Wang <haiyue.wang@linux.intel.com>
+Date: Tue, 13 Feb 2018 14:28:12 +0800
+Subject: [PATCH] Add I2C IPMB support
+
+Some protocols over I2C are designed for bi-directional transferring
+messages by using I2C Master Write protocol. Like the MCTP (Management
+Component Transport Protocol) and IPMB (Intelligent Platform Management
+Bus), they both require that the userspace can receive messages from
+I2C dirvers under slave mode.
+
+This new slave mqueue backend is used to receive and queue messages, it
+will exposes these messages to userspace by sysfs bin file.
+
+Signed-off-by: Haiyue Wang <haiyue.wang@linux.intel.com>
+---
+ Documentation/i2c/slave-mqueue-backend.rst | 124 +++++++++++++++++
+ drivers/i2c/Kconfig | 23 +++
+ drivers/i2c/Makefile | 1 +
+ drivers/i2c/i2c-slave-mqueue.c | 217 +++++++++++++++++++++++++++++
+ 4 files changed, 365 insertions(+)
+ create mode 100644 Documentation/i2c/slave-mqueue-backend.rst
+ create mode 100644 drivers/i2c/i2c-slave-mqueue.c
+
+diff --git a/Documentation/i2c/slave-mqueue-backend.rst b/Documentation/i2c/slave-mqueue-backend.rst
+new file mode 100644
+index 000000000000..2d0d06d8df9d
+--- /dev/null
++++ b/Documentation/i2c/slave-mqueue-backend.rst
+@@ -0,0 +1,124 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++=====================================
++Linux I2C slave message queue backend
++=====================================
++
++:Author: Haiyue Wang <haiyue.wang@linux.intel.com>
++
++Some protocols over I2C/SMBus are designed for bi-directional transferring
++messages by using I2C Master Write protocol. This requires that both sides
++of the communication have slave addresses.
++
++Like MCTP (Management Component Transport Protocol) and IPMB (Intelligent
++Platform Management Bus), they both require that the userspace can receive
++messages from i2c dirvers under slave mode.
++
++This I2C slave mqueue (message queue) backend is used to receive and queue
++messages from the remote i2c intelligent device; and it will add the target
++slave address (with R/W# bit is always 0) into the message at the first byte,
++so that userspace can use this byte to dispatch the messages into different
++handling modules. Also, like IPMB, the address byte is in its message format,
++it needs it to do checksum.
++
++For messages are time related, so this backend will flush the oldest message
++to queue the newest one.
++
++Link
++----
++`Intelligent Platform Management Bus
++Communications Protocol Specification
++<https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmp-spec-v1.0.pdf>`_
++
++`Management Component Transport Protocol (MCTP)
++SMBus/I2C Transport Binding Specification
++<https://www.dmtf.org/sites/default/files/standards/documents/DSP0237_1.1.0.pdf>`_
++
++How to use
++----------
++For example, the I2C5 bus has slave address 0x10, the below command will create
++the related message queue interface:
++
++ echo slave-mqueue 0x1010 > /sys/bus/i2c/devices/i2c-5/new_device
++
++Then you can dump the messages like this:
++
++ hexdump -C /sys/bus/i2c/devices/5-1010/slave-mqueue
++
++Code Example
++------------
++*Note: call 'lseek' before 'read', this is a requirement from kernfs' design.*
++
++::
++
++ #include <sys/types.h>
++ #include <sys/stat.h>
++ #include <unistd.h>
++ #include <poll.h>
++ #include <time.h>
++ #include <fcntl.h>
++ #include <stdio.h>
++
++ int main(int argc, char *argv[])
++ {
++ int i, r;
++ struct pollfd pfd;
++ struct timespec ts;
++ unsigned char data[256];
++
++ pfd.fd = open(argv[1], O_RDONLY | O_NONBLOCK);
++ if (pfd.fd < 0)
++ return -1;
++
++ pfd.events = POLLPRI;
++
++ while (1) {
++ r = poll(&pfd, 1, 5000);
++
++ if (r < 0)
++ break;
++
++ if (r == 0 || !(pfd.revents & POLLPRI))
++ continue;
++
++ lseek(pfd.fd, 0, SEEK_SET);
++ r = read(pfd.fd, data, sizeof(data));
++ if (r <= 0)
++ continue;
++
++ clock_gettime(CLOCK_MONOTONIC, &ts);
++ printf("[%ld.%.9ld] :", ts.tv_sec, ts.tv_nsec);
++ for (i = 0; i < r; i++)
++ printf(" %02x", data[i]);
++ printf("\n");
++ }
++
++ close(pfd.fd);
++
++ return 0;
++ }
++
++Result
++------
++*./a.out "/sys/bus/i2c/devices/5-1010/slave-mqueue"*
++
++::
++
++ [10183.232500449] : 20 18 c8 2c 78 01 5b
++ [10183.479358348] : 20 18 c8 2c 78 01 5b
++ [10183.726556812] : 20 18 c8 2c 78 01 5b
++ [10183.972605863] : 20 18 c8 2c 78 01 5b
++ [10184.220124772] : 20 18 c8 2c 78 01 5b
++ [10184.467764166] : 20 18 c8 2c 78 01 5b
++ [10193.233421784] : 20 18 c8 2c 7c 01 57
++ [10193.480273460] : 20 18 c8 2c 7c 01 57
++ [10193.726788733] : 20 18 c8 2c 7c 01 57
++ [10193.972781945] : 20 18 c8 2c 7c 01 57
++ [10194.220487360] : 20 18 c8 2c 7c 01 57
++ [10194.468089259] : 20 18 c8 2c 7c 01 57
++ [10203.233433099] : 20 18 c8 2c 80 01 53
++ [10203.481058715] : 20 18 c8 2c 80 01 53
++ [10203.727610472] : 20 18 c8 2c 80 01 53
++ [10203.974044856] : 20 18 c8 2c 80 01 53
++ [10204.220734634] : 20 18 c8 2c 80 01 53
++ [10204.468461664] : 20 18 c8 2c 80 01 53
+diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
+index abedd55a1264..49a2379876c6 100644
+--- a/drivers/i2c/Kconfig
++++ b/drivers/i2c/Kconfig
+@@ -119,6 +119,29 @@ if I2C_SLAVE
+ config I2C_SLAVE_EEPROM
+ tristate "I2C eeprom slave driver"
+
++config I2C_SLAVE_MQUEUE_MESSAGE_SIZE
++ int "The message size of I2C mqueue slave"
++ default 120
++
++config I2C_SLAVE_MQUEUE_QUEUE_SIZE
++ int "The queue size of I2C mqueue slave"
++ default 32
++ help
++ This number MUST be power of 2.
++
++config I2C_SLAVE_MQUEUE
++ tristate "I2C mqueue (message queue) slave driver"
++ help
++ Some protocols over I2C are designed for bi-directional transferring
++ messages by using I2C Master Write protocol. This driver is used to
++ receive and queue messages from the remote I2C device.
++
++ Userspace can get the messages by reading sysfs file that this driver
++ exposes.
++
++ This support is also available as a module. If so, the module will be
++ called i2c-slave-mqueue.
++
+ endif
+
+ config I2C_DEBUG_CORE
+diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
+index bed6ba63c983..9a31bc75a446 100644
+--- a/drivers/i2c/Makefile
++++ b/drivers/i2c/Makefile
+@@ -16,5 +16,6 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o
+ obj-y += algos/ busses/ muxes/
+ obj-$(CONFIG_I2C_STUB) += i2c-stub.o
+ obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o
++obj-$(CONFIG_I2C_SLAVE_MQUEUE) += i2c-slave-mqueue.o
+
+ ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
+diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c
+new file mode 100644
+index 000000000000..6014bca0ff2a
+--- /dev/null
++++ b/drivers/i2c/i2c-slave-mqueue.c
+@@ -0,0 +1,217 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2017 - 2018, Intel Corporation.
++
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/sysfs.h>
++
++#define MQ_MSGBUF_SIZE CONFIG_I2C_SLAVE_MQUEUE_MESSAGE_SIZE
++#define MQ_QUEUE_SIZE CONFIG_I2C_SLAVE_MQUEUE_QUEUE_SIZE
++#define MQ_QUEUE_NEXT(x) (((x) + 1) & (MQ_QUEUE_SIZE - 1))
++
++struct mq_msg {
++ int len;
++ u8 *buf;
++};
++
++struct mq_queue {
++ struct bin_attribute bin;
++ struct kernfs_node *kn;
++
++ spinlock_t lock; /* spinlock for queue index handling */
++ int in;
++ int out;
++
++ struct mq_msg *curr;
++ int truncated; /* drop current if truncated */
++ struct mq_msg *queue;
++};
++
++static int i2c_slave_mqueue_callback(struct i2c_client *client,
++ enum i2c_slave_event event, u8 *val)
++{
++ struct mq_queue *mq = i2c_get_clientdata(client);
++ struct mq_msg *msg = mq->curr;
++ int ret = 0;
++
++ switch (event) {
++ case I2C_SLAVE_WRITE_REQUESTED:
++ mq->truncated = 0;
++
++ msg->len = 1;
++ msg->buf[0] = client->addr << 1;
++ break;
++
++ case I2C_SLAVE_WRITE_RECEIVED:
++ if (msg->len < MQ_MSGBUF_SIZE) {
++ msg->buf[msg->len++] = *val;
++ } else {
++ dev_err(&client->dev, "message is truncated!\n");
++ mq->truncated = 1;
++ ret = -EINVAL;
++ }
++ break;
++
++ case I2C_SLAVE_STOP:
++ if (unlikely(mq->truncated || msg->len < 2))
++ break;
++
++ spin_lock(&mq->lock);
++ mq->in = MQ_QUEUE_NEXT(mq->in);
++ mq->curr = &mq->queue[mq->in];
++ mq->curr->len = 0;
++
++ /* Flush the oldest message */
++ if (mq->out == mq->in)
++ mq->out = MQ_QUEUE_NEXT(mq->out);
++ spin_unlock(&mq->lock);
++
++ kernfs_notify(mq->kn);
++ break;
++
++ default:
++ *val = 0xFF;
++ break;
++ }
++
++ return ret;
++}
++
++static ssize_t i2c_slave_mqueue_bin_read(struct file *filp,
++ struct kobject *kobj,
++ struct bin_attribute *attr,
++ char *buf, loff_t pos, size_t count)
++{
++ struct mq_queue *mq;
++ struct mq_msg *msg;
++ unsigned long flags;
++ bool more = false;
++ ssize_t ret = 0;
++
++ mq = dev_get_drvdata(container_of(kobj, struct device, kobj));
++
++ spin_lock_irqsave(&mq->lock, flags);
++ if (mq->out != mq->in) {
++ msg = &mq->queue[mq->out];
++
++ if (msg->len <= count) {
++ ret = msg->len;
++ memcpy(buf, msg->buf, ret);
++ } else {
++ ret = -EOVERFLOW; /* Drop this HUGE one. */
++ }
++
++ mq->out = MQ_QUEUE_NEXT(mq->out);
++ if (mq->out != mq->in)
++ more = true;
++ }
++ spin_unlock_irqrestore(&mq->lock, flags);
++
++ if (more)
++ kernfs_notify(mq->kn);
++
++ return ret;
++}
++
++static int i2c_slave_mqueue_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct device *dev = &client->dev;
++ struct mq_queue *mq;
++ int ret, i;
++ void *buf;
++
++ mq = devm_kzalloc(dev, sizeof(*mq), GFP_KERNEL);
++ if (!mq)
++ return -ENOMEM;
++
++ BUILD_BUG_ON(!is_power_of_2(MQ_QUEUE_SIZE));
++
++ buf = devm_kmalloc_array(dev, MQ_QUEUE_SIZE, MQ_MSGBUF_SIZE,
++ GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ mq->queue = devm_kzalloc(dev, sizeof(*mq->queue) * MQ_QUEUE_SIZE,
++ GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ for (i = 0; i < MQ_QUEUE_SIZE; i++)
++ mq->queue[i].buf = buf + i * MQ_MSGBUF_SIZE;
++
++ i2c_set_clientdata(client, mq);
++
++ spin_lock_init(&mq->lock);
++ mq->curr = &mq->queue[0];
++
++ sysfs_bin_attr_init(&mq->bin);
++ mq->bin.attr.name = "slave-mqueue";
++ mq->bin.attr.mode = 0400;
++ mq->bin.read = i2c_slave_mqueue_bin_read;
++ mq->bin.size = MQ_MSGBUF_SIZE * MQ_QUEUE_SIZE;
++
++ ret = sysfs_create_bin_file(&dev->kobj, &mq->bin);
++ if (ret)
++ return ret;
++
++ mq->kn = kernfs_find_and_get(dev->kobj.sd, mq->bin.attr.name);
++ if (!mq->kn) {
++ sysfs_remove_bin_file(&dev->kobj, &mq->bin);
++ return -EFAULT;
++ }
++
++ ret = i2c_slave_register(client, i2c_slave_mqueue_callback);
++ if (ret) {
++ kernfs_put(mq->kn);
++ sysfs_remove_bin_file(&dev->kobj, &mq->bin);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int i2c_slave_mqueue_remove(struct i2c_client *client)
++{
++ struct mq_queue *mq = i2c_get_clientdata(client);
++
++ i2c_slave_unregister(client);
++
++ kernfs_put(mq->kn);
++ sysfs_remove_bin_file(&client->dev.kobj, &mq->bin);
++
++ return 0;
++}
++
++static const struct i2c_device_id i2c_slave_mqueue_id[] = {
++ { "slave-mqueue", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, i2c_slave_mqueue_id);
++
++#if IS_ENABLED(CONFIG_OF)
++static const struct of_device_id i2c_slave_mqueue_of_match[] = {
++ { .compatible = "slave-mqueue", .data = (void *)0 },
++ { },
++};
++MODULE_DEVICE_TABLE(of, i2c_slave_mqueue_of_match);
++#endif
++
++static struct i2c_driver i2c_slave_mqueue_driver = {
++ .driver = {
++ .name = "i2c-slave-mqueue",
++ .of_match_table = of_match_ptr(i2c_slave_mqueue_of_match),
++ },
++ .probe = i2c_slave_mqueue_probe,
++ .remove = i2c_slave_mqueue_remove,
++ .id_table = i2c_slave_mqueue_id,
++};
++module_i2c_driver(i2c_slave_mqueue_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
++MODULE_DESCRIPTION("I2C slave mode for receiving and queuing messages");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch
new file mode 100644
index 000000000..c5add2dd5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch
@@ -0,0 +1,491 @@
+From 42326dfecd45c52918272cf6b65e6eb5b8499c46 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 10 Jul 2019 16:19:33 -0700
+Subject: [PATCH] misc: aspeed: add lpc mbox driver
+
+This commit adds back the lpc mbox driver which was removed from
+the openbmc linux dev-5.2 tree.
+
+This driver should be rewritten later.
+
+Signed-off-by: Cyril Bur <cyrilbur@gmail.com>"
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 9 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 9 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 1 +
+ drivers/soc/aspeed/Kconfig | 7 +
+ drivers/soc/aspeed/Makefile | 1 +
+ drivers/soc/aspeed/aspeed-lpc-mbox.c | 377 +++++++++++++++++++++++++++
+ 6 files changed, 404 insertions(+)
+ create mode 100644 drivers/soc/aspeed/aspeed-lpc-mbox.c
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index e9fd66ab3099..f3edda4ae477 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -393,6 +393,15 @@
+ sio_regs: regs {
+ compatible = "aspeed,bmc-misc";
+ };
++
++ mbox: mbox@180 {
++ compatible = "aspeed,ast2400-mbox";
++ reg = <0x180 0x5c>;
++ interrupts = <46>;
++ #mbox-cells = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index b4ae3827ed1d..b69110b9eab9 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -522,6 +522,15 @@
+ sio_regs: regs {
+ compatible = "aspeed,bmc-misc";
+ };
++
++ mbox: mbox@180 {
++ compatible = "aspeed,ast2500-mbox";
++ reg = <0x180 0x5c>;
++ interrupts = <46>;
++ #mbox-cells = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 825e64ce317a..183869eaf79a 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -594,6 +594,7 @@
+ reg = <0x180 0x5c>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ };
+ };
+ };
+diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
+index a4b3cac87ce2..464a55c7eb39 100644
+--- a/drivers/soc/aspeed/Kconfig
++++ b/drivers/soc/aspeed/Kconfig
+@@ -21,6 +21,13 @@ config ASPEED_LPC_CTRL
+ ioctl()s, the driver also provides a read/write interface to a BMC ram
+ region where the host LPC read/write region can be buffered.
+
++config ASPEED_LPC_MBOX
++ tristate "Aspeed LPC Mailbox Controller"
++ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
++ ---help---
++ Expose the ASPEED LPC MBOX registers found on Aspeed SOCs (AST2400
++ and AST2500) to userspace.
++
+ config ASPEED_LPC_SNOOP
+ tristate "Aspeed ast2500 HOST LPC snoop support"
+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
+index 217d876fec25..26924c111af3 100644
+--- a/drivers/soc/aspeed/Makefile
++++ b/drivers/soc/aspeed/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_ASPEED_BMC_MISC) += aspeed-bmc-misc.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
++obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
+ obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o
+diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c
+new file mode 100644
+index 000000000000..583feecc4f18
+--- /dev/null
++++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c
+@@ -0,0 +1,377 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++// Copyright 2017 IBM Corporation
++// TODO: Rewrite this driver
++
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/mfd/syscon.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/of_irq.h>
++#include <linux/platform_device.h>
++#include <linux/poll.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++
++#define DEVICE_NAME "aspeed-mbox"
++
++#define MBX_USE_INTERRUPT 0
++
++#define ASPEED_MBOX_NUM_REGS 16
++
++#define ASPEED_MBOX_DATA_0 0x00
++#define ASPEED_MBOX_STATUS_0 0x40
++#define ASPEED_MBOX_STATUS_1 0x44
++#define ASPEED_MBOX_BMC_CTRL 0x48
++#define ASPEED_MBOX_CTRL_RECV BIT(7)
++#define ASPEED_MBOX_CTRL_MASK BIT(1)
++#define ASPEED_MBOX_CTRL_SEND BIT(0)
++#define ASPEED_MBOX_HOST_CTRL 0x4c
++#define ASPEED_MBOX_INTERRUPT_0 0x50
++#define ASPEED_MBOX_INTERRUPT_1 0x54
++
++struct aspeed_mbox {
++ struct miscdevice miscdev;
++ struct regmap *regmap;
++ struct clk *clk;
++ unsigned int base;
++ int irq;
++ wait_queue_head_t queue;
++ struct mutex mutex;
++};
++
++static atomic_t aspeed_mbox_open_count = ATOMIC_INIT(0);
++
++static u8 aspeed_mbox_inb(struct aspeed_mbox *mbox, int reg)
++{
++ /*
++ * The mbox registers are actually only one byte but are addressed
++ * four bytes apart. The other three bytes are marked 'reserved',
++ * they *should* be zero but lets not rely on it.
++ * I am going to rely on the fact we can casually read/write to them...
++ */
++ unsigned int val = 0xff; /* If regmap throws an error return 0xff */
++ int rc = regmap_read(mbox->regmap, mbox->base + reg, &val);
++
++ if (rc)
++ dev_err(mbox->miscdev.parent, "regmap_read() failed with "
++ "%d (reg: 0x%08x)\n", rc, reg);
++
++ return val & 0xff;
++}
++
++static void aspeed_mbox_outb(struct aspeed_mbox *mbox, u8 data, int reg)
++{
++ int rc = regmap_write(mbox->regmap, mbox->base + reg, data);
++
++ if (rc)
++ dev_err(mbox->miscdev.parent, "regmap_write() failed with "
++ "%d (data: %u reg: 0x%08x)\n", rc, data, reg);
++}
++
++static struct aspeed_mbox *file_mbox(struct file *file)
++{
++ return container_of(file->private_data, struct aspeed_mbox, miscdev);
++}
++
++static int aspeed_mbox_open(struct inode *inode, struct file *file)
++{
++#if MBX_USE_INTERRUPT
++ struct aspeed_mbox *mbox = file_mbox(file);
++#endif
++
++ if (atomic_inc_return(&aspeed_mbox_open_count) == 1) {
++#if MBX_USE_INTERRUPT
++ /*
++ * Clear the interrupt status bit if it was left on and unmask
++ * interrupts.
++ * ASPEED_MBOX_CTRL_RECV bit is W1C, this also unmasks in 1 step
++ */
++ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
++#endif
++ return 0;
++ }
++
++ atomic_dec(&aspeed_mbox_open_count);
++ return -EBUSY;
++}
++
++static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct aspeed_mbox *mbox = file_mbox(file);
++ char __user *p = buf;
++ ssize_t ret;
++ int i;
++
++ if (!access_ok(buf, count))
++ return -EFAULT;
++
++ if (count + *ppos > ASPEED_MBOX_NUM_REGS)
++ return -EINVAL;
++
++#if MBX_USE_INTERRUPT
++ if (file->f_flags & O_NONBLOCK) {
++ if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) &
++ ASPEED_MBOX_CTRL_RECV))
++ return -EAGAIN;
++ } else if (wait_event_interruptible(mbox->queue,
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) &
++ ASPEED_MBOX_CTRL_RECV)) {
++ return -ERESTARTSYS;
++ }
++#endif
++
++ mutex_lock(&mbox->mutex);
++
++ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) {
++ uint8_t reg = aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4));
++
++ ret = __put_user(reg, p);
++ if (ret)
++ goto out_unlock;
++
++ p++;
++ count--;
++ }
++
++#if MBX_USE_INTERRUPT
++ /* ASPEED_MBOX_CTRL_RECV bit is write to clear, this also unmasks in 1 step */
++ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
++#endif
++ ret = p - buf;
++
++out_unlock:
++ mutex_unlock(&mbox->mutex);
++ return ret;
++}
++
++static ssize_t aspeed_mbox_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct aspeed_mbox *mbox = file_mbox(file);
++ const char __user *p = buf;
++ ssize_t ret;
++ char c;
++ int i;
++
++ if (!access_ok(buf, count))
++ return -EFAULT;
++
++ if (count + *ppos > ASPEED_MBOX_NUM_REGS)
++ return -EINVAL;
++
++ mutex_lock(&mbox->mutex);
++
++ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) {
++ ret = __get_user(c, p);
++ if (ret)
++ goto out_unlock;
++
++ aspeed_mbox_outb(mbox, c, ASPEED_MBOX_DATA_0 + (i * 4));
++ p++;
++ count--;
++ }
++
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0);
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1);
++ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV | ASPEED_MBOX_CTRL_MASK | ASPEED_MBOX_CTRL_SEND, ASPEED_MBOX_BMC_CTRL);
++ ret = p - buf;
++
++out_unlock:
++ mutex_unlock(&mbox->mutex);
++ return ret;
++}
++
++static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait)
++{
++ struct aspeed_mbox *mbox = file_mbox(file);
++ unsigned int mask = 0;
++
++ poll_wait(file, &mbox->queue, wait);
++
++#if MBX_USE_INTERRUPT
++ if (aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV)
++#endif
++ mask |= POLLIN;
++
++ return mask;
++}
++
++static int aspeed_mbox_release(struct inode *inode, struct file *file)
++{
++ atomic_dec(&aspeed_mbox_open_count);
++ return 0;
++}
++
++static const struct file_operations aspeed_mbox_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_seek_end_llseek,
++ .read = aspeed_mbox_read,
++ .write = aspeed_mbox_write,
++ .open = aspeed_mbox_open,
++ .release = aspeed_mbox_release,
++ .poll = aspeed_mbox_poll,
++};
++
++static irqreturn_t aspeed_mbox_irq(int irq, void *arg)
++{
++ struct aspeed_mbox *mbox = arg;
++#if MBX_USE_INTERRUPT
++ int i;
++
++// if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV))
++// return IRQ_NONE;
++
++ printk(KERN_ERR "BMC_CTRL: 0x%02x\n",
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL));
++ printk(KERN_ERR "STATUS_0: 0x%02x\n",
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_0));
++ printk(KERN_ERR "STATUS_1: 0x%02x\n",
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_1));
++ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) {
++ printk(KERN_ERR "DATA_%d: 0x%02x\n", i,
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)));
++ }
++#endif
++
++ /* Clear interrupt status */
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0);
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1);
++ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
++
++ wake_up(&mbox->queue);
++ return IRQ_HANDLED;
++}
++
++static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox,
++ struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ int rc;
++
++ mbox->irq = platform_get_irq(pdev, 0);
++ if (!mbox->irq)
++ return -ENODEV;
++
++ rc = devm_request_irq(dev, mbox->irq, aspeed_mbox_irq,
++ IRQF_SHARED, DEVICE_NAME, mbox);
++ if (rc < 0) {
++ dev_err(dev, "Unable to request IRQ %d\n", mbox->irq);
++ return rc;
++ }
++
++ /* Disable all register based interrupts. */
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_0); /* regs 0 - 7 */
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_1); /* regs 8 - 15 */
++
++ /* These registers are write one to clear. Clear them. */
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0);
++ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1);
++
++ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
++ return 0;
++}
++
++static int aspeed_mbox_probe(struct platform_device *pdev)
++{
++ struct aspeed_mbox *mbox;
++ struct device *dev;
++ int rc;
++
++ dev = &pdev->dev;
++
++ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
++ if (!mbox)
++ return -ENOMEM;
++
++ dev_set_drvdata(&pdev->dev, mbox);
++
++ rc = of_property_read_u32(dev->of_node, "reg", &mbox->base);
++ if (rc) {
++ dev_err(dev, "Couldn't read reg device-tree property\n");
++ return rc;
++ }
++
++ mbox->regmap = syscon_node_to_regmap(
++ pdev->dev.parent->of_node);
++ if (IS_ERR(mbox->regmap)) {
++ dev_err(dev, "Couldn't get regmap\n");
++ return -ENODEV;
++ }
++
++ mutex_init(&mbox->mutex);
++ init_waitqueue_head(&mbox->queue);
++
++ mbox->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(mbox->clk)) {
++ rc = PTR_ERR(mbox->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
++ }
++ rc = clk_prepare_enable(mbox->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
++ mbox->miscdev.minor = MISC_DYNAMIC_MINOR;
++ mbox->miscdev.name = DEVICE_NAME;
++ mbox->miscdev.fops = &aspeed_mbox_fops;
++ mbox->miscdev.parent = dev;
++ rc = misc_register(&mbox->miscdev);
++ if (rc) {
++ dev_err(dev, "Unable to register device\n");
++ goto err;
++ }
++
++ rc = aspeed_mbox_config_irq(mbox, pdev);
++ if (rc) {
++ dev_err(dev, "Failed to configure IRQ\n");
++ misc_deregister(&mbox->miscdev);
++ goto err;
++ }
++
++ dev_info(&pdev->dev, "LPC mbox registered, irq %d\n", mbox->irq);
++
++ return 0;
++
++err:
++ clk_disable_unprepare(mbox->clk);
++
++ return rc;
++}
++
++static int aspeed_mbox_remove(struct platform_device *pdev)
++{
++ struct aspeed_mbox *mbox = dev_get_drvdata(&pdev->dev);
++
++ misc_deregister(&mbox->miscdev);
++ clk_disable_unprepare(mbox->clk);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_mbox_match[] = {
++ { .compatible = "aspeed,ast2400-mbox" },
++ { .compatible = "aspeed,ast2500-mbox" },
++ { .compatible = "aspeed,ast2600-mbox" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, aspeed_mbox_match);
++
++static struct platform_driver aspeed_mbox_driver = {
++ .driver = {
++ .name = DEVICE_NAME,
++ .of_match_table = aspeed_mbox_match,
++ },
++ .probe = aspeed_mbox_probe,
++ .remove = aspeed_mbox_remove,
++};
++
++module_platform_driver(aspeed_mbox_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>");
++MODULE_DESCRIPTION("Aspeed mailbox device driver");
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch
new file mode 100644
index 000000000..b4b1bcad8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch
@@ -0,0 +1,580 @@
+From 39f76bd49fd481999cf51fbdfbea3e820efc7227 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@intel.com>
+Date: Mon, 13 Nov 2017 16:29:44 +0800
+Subject: [PATCH] Aspeed LPC SIO driver
+
+Add lpc sio device driver for AST2500/2400
+
+Signed-off-by: Yong Li <yong.b.li@intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../bindings/soc/aspeed/aspeed-lpc-sio.txt | 17 +
+ arch/arm/boot/dts/aspeed-g4.dtsi | 7 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 7 +
+ drivers/soc/aspeed/Kconfig | 7 +
+ drivers/soc/aspeed/Makefile | 1 +
+ drivers/soc/aspeed/aspeed-lpc-sio.c | 410 +++++++++++++++++++++
+ include/uapi/linux/aspeed-lpc-sio.h | 45 +++
+ 7 files changed, 494 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt
+ create mode 100644 drivers/soc/aspeed/aspeed-lpc-sio.c
+ create mode 100644 include/uapi/linux/aspeed-lpc-sio.h
+
+diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt
+new file mode 100644
+index 000000000000..c74ea3a4e5ac
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt
+@@ -0,0 +1,17 @@
++* Aspeed LPC SIO driver.
++
++Required properties:
++- compatible : Should be one of:
++ "aspeed,ast2400-lpc-sio"
++ "aspeed,ast2500-lpc-sio"
++- reg : Should contain lpc-sio registers location and length
++- clocks: contains a phandle to the syscon node describing the clocks.
++ There should then be one cell representing the clock to use.
++
++Example:
++lpc_sio: lpc-sio@100 {
++ compatible = "aspeed,ast2500-lpc-sio";
++ reg = <0x100 0x20>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++};
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index f3edda4ae477..a70bee24d058 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -394,6 +394,13 @@
+ compatible = "aspeed,bmc-misc";
+ };
+
++ lpc_sio: lpc-sio@100 {
++ compatible = "aspeed,ast2400-lpc-sio";
++ reg = <0x100 0x20>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++
+ mbox: mbox@180 {
+ compatible = "aspeed,ast2400-mbox";
+ reg = <0x180 0x5c>;
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index bd6d1461e4bd..c15be82c3a9d 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -503,6 +503,13 @@
+ compatible = "aspeed,bmc-misc";
+ };
+
++ lpc_sio: lpc-sio@100 {
++ compatible = "aspeed,ast2500-lpc-sio";
++ reg = <0x100 0x20>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++
+ mbox: mbox@180 {
+ compatible = "aspeed,ast2500-mbox";
+ reg = <0x180 0x5c>;
+diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
+index a4be8e566bc7..285c19042c65 100644
+--- a/drivers/soc/aspeed/Kconfig
++++ b/drivers/soc/aspeed/Kconfig
+@@ -28,6 +28,13 @@ config ASPEED_LPC_MBOX
+ Expose the ASPEED LPC MBOX registers found on Aspeed SOCs (AST2400
+ and AST2500) to userspace.
+
++config ASPEED_LPC_SIO
++ tristate "Aspeed ast2400/2500 HOST LPC SIO support"
++ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
++ help
++ Provides a driver to control the LPC SIO interface on ASPEED platform
++ through ioctl()s.
++
+ config ASPEED_LPC_SNOOP
+ tristate "Aspeed ast2500 HOST LPC snoop support"
+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
+index f3ff29b874ed..2e547cc47e62 100644
+--- a/drivers/soc/aspeed/Makefile
++++ b/drivers/soc/aspeed/Makefile
+@@ -2,5 +2,6 @@
+ obj-$(CONFIG_ASPEED_BMC_MISC) += aspeed-bmc-misc.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+ obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
++obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
+diff --git a/drivers/soc/aspeed/aspeed-lpc-sio.c b/drivers/soc/aspeed/aspeed-lpc-sio.c
+new file mode 100644
+index 000000000000..d4a4da112ff4
+--- /dev/null
++++ b/drivers/soc/aspeed/aspeed-lpc-sio.c
+@@ -0,0 +1,410 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (C) 2012-2017 ASPEED Technology Inc.
++// Copyright (c) 2017-2020 Intel Corporation
++
++#include <linux/aspeed-lpc-sio.h>
++#include <linux/clk.h>
++#include <linux/mfd/syscon.h>
++#include <linux/miscdevice.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/poll.h>
++#include <linux/regmap.h>
++
++#define SOC_NAME "aspeed"
++#define DEVICE_NAME "lpc-sio"
++
++#define AST_LPC_SWCR0300 0x00
++#define LPC_PWRGD_STS BIT(30)
++#define LPC_PWRGD_RISING_EVT_STS BIT(29)
++#define LPC_PWRGD_FALLING_EVT_STS BIT(28)
++#define LPC_PWRBTN_STS BIT(27)
++#define LPC_PWRBTN_RISING_EVT_STS BIT(26)
++#define LPC_PWRBTN_FALLING_EVT_STS BIT(25)
++#define LPC_S5N_STS BIT(21)
++#define LPC_S5N_RISING_EVT_STS BIT(20)
++#define LPC_S5N_FALLING_EVT_STS BIT(19)
++#define LPC_S3N_STS BIT(18)
++#define LPC_S3N_RISING_EVT_STS BIT(17)
++#define LPC_S3N_FALLING_EVT_STS BIT(16)
++#define LPC_PWBTO_RAW_STS BIT(15)
++#define LPC_LAST_ONCTL_STS BIT(14)
++#define LPC_WAS_PFAIL_STS BIT(13)
++#define LPC_POWER_UP_FAIL_STS BIT(12) /* Crowbar */
++#define LPC_PWRBTN_OVERRIDE_STS BIT(11)
++#define LPC_BMC_TRIG_WAKEUP_EVT_STS BIT(8)
++
++#define AST_LPC_SWCR0704 0x04
++#define LPC_BMC_TRIG_WAKEUP_EVT_EN BIT(8)
++
++#define AST_LPC_SWCR0B08 0x08
++#define LPC_PWREQ_OUTPUT_LEVEL BIT(25)
++#define LPC_PWBTO_OUTPUT_LEVEL BIT(24)
++#define LPC_ONCTL_STS BIT(15)
++#define LPC_ONCTL_GPIO_LEVEL BIT(14)
++#define LPC_ONCTL_EN_GPIO_OUTPUT BIT(13)
++#define LPC_ONCTL_EN_GPIO_MODE BIT(12)
++#define LPC_BMC_TRIG_WAKEUP_EVT BIT(6)
++
++#define AST_LPC_SWCR0F0C 0x0C
++#define AST_LPC_SWCR1310 0x10
++#define AST_LPC_SWCR1714 0x14
++#define AST_LPC_SWCR1B18 0x18
++#define AST_LPC_SWCR1F1C 0x1C
++#define AST_LPC_ACPIE3E0 0x20
++#define AST_LPC_ACPIC1C0 0x24
++
++#define AST_LPC_ACPIB3B0 0x28
++#define LPC_BMC_TRIG_SCI_EVT_STS BIT(8)
++
++#define AST_LPC_ACPIB7B4 0x2C
++#define LPC_BMC_TRIG_SCI_EVT_EN BIT(8)
++
++struct aspeed_lpc_sio {
++ struct miscdevice miscdev;
++ struct regmap *regmap;
++ struct clk *clk;
++ struct semaphore lock;
++ unsigned int reg_base;
++};
++
++static struct aspeed_lpc_sio *file_aspeed_lpc_sio(struct file *file)
++{
++ return container_of(file->private_data, struct aspeed_lpc_sio,
++ miscdev);
++}
++
++static int aspeed_lpc_sio_open(struct inode *inode, struct file *filp)
++{
++ return 0;
++}
++
++#define LPC_SLP3N5N_EVENT_STATUS (\
++ LPC_S5N_RISING_EVT_STS | \
++ LPC_S5N_FALLING_EVT_STS | \
++ LPC_S3N_RISING_EVT_STS | \
++ LPC_S3N_FALLING_EVT_STS)
++
++/*
++ * SLPS3n SLPS5n State
++ * ---------------------------------
++ * 1 1 S12
++ * 0 1 S3I
++ * x 0 S45
++ *************************************
++ */
++
++static void sio_get_acpi_state(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ /* update the ACPI state event status */
++ if (sio_data->param != 0) {
++ if (val & LPC_SLP3N5N_EVENT_STATUS) {
++ sio_data->param = 1;
++ regmap_write(lpc_sio->regmap, reg,
++ LPC_SLP3N5N_EVENT_STATUS);
++ } else {
++ sio_data->param = 0;
++ }
++ }
++
++ if ((val & LPC_S3N_STS) && (val & LPC_S5N_STS))
++ sio_data->data = ACPI_STATE_S12;
++ else if ((val & LPC_S3N_STS) == 0 && (val & LPC_S5N_STS))
++ sio_data->data = ACPI_STATE_S3I;
++ else
++ sio_data->data = ACPI_STATE_S45;
++}
++
++#define LPC_PWRGD_EVENT_STATUS ( \
++ LPC_PWRGD_RISING_EVT_STS | \
++ LPC_PWRGD_FALLING_EVT_STS)
++
++static void sio_get_pwrgd_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ /* update the PWRGD event status */
++ if (sio_data->param != 0) {
++ if (val & LPC_PWRGD_EVENT_STATUS) {
++ sio_data->param = 1;
++ regmap_write(lpc_sio->regmap, reg,
++ LPC_PWRGD_EVENT_STATUS);
++ } else {
++ sio_data->param = 0;
++ }
++ }
++
++ sio_data->data = (val & LPC_PWRGD_STS) != 0 ? 1 : 0;
++}
++
++static void sio_get_onctl_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ sio_data->data = (val & LPC_ONCTL_STS) != 0 ? 1 : 0;
++}
++
++static void sio_set_onctl_gpio(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ /* Enable ONCTL GPIO mode */
++ if (sio_data->param != 0) {
++ val |= LPC_ONCTL_EN_GPIO_MODE;
++ val |= LPC_ONCTL_EN_GPIO_OUTPUT;
++
++ if (sio_data->data != 0)
++ val |= LPC_ONCTL_GPIO_LEVEL;
++ else
++ val &= ~LPC_ONCTL_GPIO_LEVEL;
++
++ regmap_write(lpc_sio->regmap, reg, val);
++ } else {
++ val &= ~LPC_ONCTL_EN_GPIO_MODE;
++ regmap_write(lpc_sio->regmap, reg, val);
++ }
++}
++
++static void sio_get_pwrbtn_override(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ /* clear the PWRBTN OVERRIDE status */
++ if (sio_data->param != 0 && val & LPC_PWRBTN_OVERRIDE_STS)
++ regmap_write(lpc_sio->regmap, reg, LPC_PWRBTN_OVERRIDE_STS);
++
++ sio_data->data = (val & LPC_PWRBTN_OVERRIDE_STS) != 0 ? 1 : 0;
++}
++
++static void sio_get_pfail_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg, val;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_read(lpc_sio->regmap, reg, &val);
++
++ /* [ASPEED]: SWCR_03_00[13] (Was_pfail: default 1) is used to identify
++ * this current booting is from AC loss (not DC loss) if FW cleans this
++ * bit after booting successfully every time.
++ **********************************************************************/
++ if (val & LPC_WAS_PFAIL_STS) {
++ regmap_write(lpc_sio->regmap, reg, 0); /* W0C */
++ sio_data->data = 1;
++ } else {
++ sio_data->data = 0;
++ }
++}
++
++static void sio_set_bmc_sci_event(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++
++ if (sio_data->param) {
++ reg = lpc_sio->reg_base + AST_LPC_ACPIB7B4;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_SCI_EVT_EN,
++ LPC_BMC_TRIG_SCI_EVT_EN);
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0704;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT_EN,
++ LPC_BMC_TRIG_WAKEUP_EVT_EN);
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT,
++ LPC_BMC_TRIG_WAKEUP_EVT);
++ } else {
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT_STS,
++ LPC_BMC_TRIG_WAKEUP_EVT_STS);
++
++ reg = lpc_sio->reg_base + AST_LPC_ACPIB3B0;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_SCI_EVT_STS,
++ LPC_BMC_TRIG_SCI_EVT_STS);
++ }
++
++ sio_data->data = sio_data->param;
++}
++
++typedef void (*sio_cmd_fn) (struct aspeed_lpc_sio *sio_dev,
++ struct sio_ioctl_data *sio_data);
++
++static sio_cmd_fn sio_cmd_handle[SIO_MAX_CMD] = {
++ [SIO_GET_ACPI_STATE] = sio_get_acpi_state,
++ [SIO_GET_PWRGD_STATUS] = sio_get_pwrgd_status,
++ [SIO_GET_ONCTL_STATUS] = sio_get_onctl_status,
++ [SIO_SET_ONCTL_GPIO] = sio_set_onctl_gpio,
++ [SIO_GET_PWRBTN_OVERRIDE] = sio_get_pwrbtn_override,
++ [SIO_GET_PFAIL_STATUS] = sio_get_pfail_status,
++ [SIO_SET_BMC_SCI_EVENT] = sio_set_bmc_sci_event,
++};
++
++static long aspeed_lpc_sio_ioctl(struct file *file, unsigned int cmd,
++ unsigned long param)
++{
++ struct aspeed_lpc_sio *lpc_sio = file_aspeed_lpc_sio(file);
++ struct sio_ioctl_data sio_data;
++ sio_cmd_fn cmd_fn;
++ long ret;
++
++ if (copy_from_user(&sio_data, (void __user *)param, sizeof(sio_data)))
++ return -EFAULT;
++
++ if (cmd != SIO_IOC_COMMAND || sio_data.sio_cmd >= SIO_MAX_CMD)
++ return -EINVAL;
++
++ cmd_fn = sio_cmd_handle[sio_data.sio_cmd];
++ if (!cmd_fn)
++ return -EINVAL;
++
++ if (down_interruptible(&lpc_sio->lock) != 0)
++ return -ERESTARTSYS;
++
++ cmd_fn(lpc_sio, &sio_data);
++ ret = copy_to_user((void __user *)param, &sio_data, sizeof(sio_data));
++
++ up(&lpc_sio->lock);
++
++ return ret;
++}
++
++static const struct file_operations aspeed_lpc_sio_fops = {
++ .owner = THIS_MODULE,
++ .open = aspeed_lpc_sio_open,
++ .unlocked_ioctl = aspeed_lpc_sio_ioctl,
++};
++
++static int aspeed_lpc_sio_probe(struct platform_device *pdev)
++{
++ struct aspeed_lpc_sio *lpc_sio;
++ struct device *dev;
++ u32 val;
++ int ret;
++
++ dev = &pdev->dev;
++
++ lpc_sio = devm_kzalloc(dev, sizeof(*lpc_sio), GFP_KERNEL);
++ if (!lpc_sio)
++ return -ENOMEM;
++
++ dev_set_drvdata(&pdev->dev, lpc_sio);
++
++ ret = of_property_read_u32(dev->of_node, "reg", &lpc_sio->reg_base);
++ if (ret) {
++ dev_err(dev, "Couldn't read reg device-tree property\n");
++ return ret;
++ }
++
++ lpc_sio->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
++ if (IS_ERR(lpc_sio->regmap)) {
++ dev_err(dev, "Couldn't get regmap\n");
++ return -ENODEV;
++ }
++
++ /*
++ * We check that the regmap works on this very first access,
++ * but as this is an MMIO-backed regmap, subsequent regmap
++ * access is not going to fail and we skip error checks from
++ * this point.
++ */
++ ret = regmap_read(lpc_sio->regmap, AST_LPC_SWCR0300, &val);
++ if (ret) {
++ dev_err(dev, "failed to read regmap\n");
++ return ret;
++ }
++
++ sema_init(&lpc_sio->lock, 1);
++
++ lpc_sio->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(lpc_sio->clk)) {
++ ret = PTR_ERR(lpc_sio->clk);
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return ret;
++ }
++ ret = clk_prepare_enable(lpc_sio->clk);
++ if (ret) {
++ dev_err(dev, "couldn't enable clock\n");
++ return ret;
++ }
++
++ lpc_sio->miscdev.minor = MISC_DYNAMIC_MINOR;
++ lpc_sio->miscdev.name = DEVICE_NAME;
++ lpc_sio->miscdev.fops = &aspeed_lpc_sio_fops;
++ lpc_sio->miscdev.parent = dev;
++ ret = misc_register(&lpc_sio->miscdev);
++ if (ret) {
++ dev_err(dev, "Unable to register device\n");
++ goto err;
++ }
++
++ dev_info(dev, "Loaded at %pap (0x%08x)\n", &lpc_sio->regmap,
++ lpc_sio->reg_base);
++
++ return 0;
++
++err:
++ clk_disable_unprepare(lpc_sio->clk);
++
++ return ret;
++}
++
++static int aspeed_lpc_sio_remove(struct platform_device *pdev)
++{
++ struct aspeed_lpc_sio *lpc_sio = dev_get_drvdata(&pdev->dev);
++
++ misc_deregister(&lpc_sio->miscdev);
++ clk_disable_unprepare(lpc_sio->clk);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_lpc_sio_match[] = {
++ { .compatible = "aspeed,ast2500-lpc-sio" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, aspeed_lpc_sio_match);
++
++static struct platform_driver aspeed_lpc_sio_driver = {
++ .driver = {
++ .name = SOC_NAME "-" DEVICE_NAME,
++ .of_match_table = of_match_ptr(aspeed_lpc_sio_match),
++ },
++ .probe = aspeed_lpc_sio_probe,
++ .remove = aspeed_lpc_sio_remove,
++};
++module_platform_driver(aspeed_lpc_sio_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_AUTHOR("Yong Li <yong.blli@linux.intel.com>");
++MODULE_DESCRIPTION("ASPEED AST LPC SIO device driver");
+diff --git a/include/uapi/linux/aspeed-lpc-sio.h b/include/uapi/linux/aspeed-lpc-sio.h
+new file mode 100644
+index 000000000000..acf89a7d2b4a
+--- /dev/null
++++ b/include/uapi/linux/aspeed-lpc-sio.h
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (C) 2012-2020 ASPEED Technology Inc.
++ * Copyright (c) 2017 Intel Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#ifndef _UAPI_LINUX_ASPEED_LPC_SIO_H
++#define _UAPI_LINUX_ASPEED_LPC_SIO_H
++
++#include <linux/ioctl.h>
++
++enum ACPI_SLP_STATE {
++ ACPI_STATE_S12 = 1,
++ ACPI_STATE_S3I,
++ ACPI_STATE_S45
++};
++
++/* SWC & ACPI for SuperIO IOCTL */
++enum SIO_CMD {
++ SIO_GET_ACPI_STATE = 0,
++ SIO_GET_PWRGD_STATUS,
++ SIO_GET_ONCTL_STATUS,
++ SIO_SET_ONCTL_GPIO,
++ SIO_GET_PWRBTN_OVERRIDE,
++ SIO_GET_PFAIL_STATUS, /* Start from AC Loss */
++ SIO_SET_BMC_SCI_EVENT,
++
++ SIO_MAX_CMD
++};
++
++struct sio_ioctl_data {
++ unsigned short sio_cmd;
++ unsigned short param;
++ unsigned int data;
++};
++
++#define SIO_IOC_BASE 'P'
++#define SIO_IOC_COMMAND _IOWR(SIO_IOC_BASE, 1, struct sio_ioctl_data)
++
++#endif /* _UAPI_LINUX_ASPEED_LPC_SIO_H */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
new file mode 100644
index 000000000..c409dec50
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
@@ -0,0 +1,762 @@
+From e6e186acacc16fd95251b2d0fb024993a66ffa0a Mon Sep 17 00:00:00 2001
+From: Haiyue Wang <haiyue.wang@linux.intel.com>
+Date: Sat, 24 Feb 2018 11:12:32 +0800
+Subject: [PATCH] Add AST2500 eSPI driver
+
+When PCH works under eSPI mode, the PMC (Power Management Controller) in
+PCH is waiting for SUS_ACK from BMC after it alerts SUS_WARN. It is in
+dead loop if no SUS_ACK assert. This is the basic requirement for the BMC
+works as eSPI slave.
+
+Also for the host power on / off actions, from BMC side, the following VW
+(Virtual Wire) messages are done in firmware:
+1. SLAVE_BOOT_LOAD_DONE / SLAVE_BOOT_LOAD_STATUS
+2. SUS_ACK
+3. OOB_RESET_ACK
+4. HOST_RESET_ACK
+
+Also, it provides monitoring interface of PLTRST_N signal through
+/dev/espi-pltrstn
+
+Signed-off-by: Haiyue Wang <haiyue.wang@linux.intel.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ .../devicetree/bindings/misc/aspeed,espi-slave.txt | 20 +
+ Documentation/misc-devices/espi-slave.rst | 118 ++++++
+ arch/arm/boot/dts/aspeed-g5.dtsi | 4 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 14 +
+ drivers/misc/Kconfig | 8 +
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-espi-slave.c | 468 +++++++++++++++++++++
+ include/dt-bindings/clock/ast2600-clock.h | 1 +
+ 8 files changed, 634 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt
+ create mode 100644 Documentation/misc-devices/espi-slave.rst
+ create mode 100644 drivers/misc/aspeed-espi-slave.c
+
+diff --git a/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt b/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt
+new file mode 100644
+index 000000000000..f72d9ae32f3e
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt
+@@ -0,0 +1,20 @@
++ASPEED eSPI Slave Controller
++
++Required properties:
++ - compatible: must be one of:
++ - "aspeed,ast2500-espi-slave"
++ - "aspeed,ast2600-espi-slave"
++
++ - reg: physical base address of the controller and length of memory mapped
++ region
++
++ - interrupts: interrupt generated by the controller
++
++Example:
++
++ espi: espi@1e6ee000 {
++ compatible = "aspeed,ast2500-espi-slave";
++ reg = <0x1e6ee000 0x100>;
++ interrupts = <23>;
++ status = "disabled";
++};
+diff --git a/Documentation/misc-devices/espi-slave.rst b/Documentation/misc-devices/espi-slave.rst
+new file mode 100644
+index 000000000000..887a69a7130a
+--- /dev/null
++++ b/Documentation/misc-devices/espi-slave.rst
+@@ -0,0 +1,118 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++==========
++eSPI Slave
++==========
++
++:Author: Haiyue Wang <haiyue.wang@linux.intel.com>
++
++The PCH (**eSPI master**) provides the eSPI to support connection of a
++BMC (**eSPI slave**) to the platform.
++
++The LPC and eSPI interfaces are mutually exclusive. Both use the same
++pins, but on power-up, a HW strap determines if the eSPI or the LPC bus
++is operational. Once selected, it’s not possible to change to the other
++interface.
++
++``eSPI Channels and Supported Transactions``
++ +------+---------------------+----------------------+--------------------+
++ | CH # | Channel | Posted Cycles | Non-Posted Cycles |
++ +======+=====================+======================+====================+
++ | 0 | Peripheral | Memory Write, | Memory Read, |
++ | | | Completions | I/O Read/Write |
++ +------+---------------------+----------------------+--------------------+
++ | 1 | Virtual Wire | Virtual Wire GET/PUT | N/A |
++ +------+---------------------+----------------------+--------------------+
++ | 2 | Out-of-Band Message | SMBus Packet GET/PUT | N/A |
++ +------+---------------------+----------------------+--------------------+
++ | 3 | Flash Access | N/A | Flash Read, Write, |
++ | | | | Erase |
++ +------+---------------------+----------------------+--------------------+
++ | N/A | General | Register Accesses | N/A |
++ +------+---------------------+----------------------+--------------------+
++
++Virtual Wire Channel (Channel 1) Overview
++-----------------------------------------
++
++The Virtual Wire channel uses a standard message format to communicate
++several types of signals between the components on the platform::
++
++ - Sideband and GPIO Pins: System events and other dedicated signals
++ between the PCH and eSPI slave. These signals are tunneled between the
++ two components over eSPI.
++
++ - Serial IRQ Interrupts: Interrupts are tunneled from the eSPI slave to
++ the PCH. Both edge and triggered interrupts are supported.
++
++When PCH runs on eSPI mode, from BMC side, the following VW messages are
++done in firmware::
++
++ 1. SLAVE_BOOT_LOAD_DONE / SLAVE_BOOT_LOAD_STATUS
++ 2. SUS_ACK
++ 3. OOB_RESET_ACK
++ 4. HOST_RESET_ACK
++
++``eSPI Virtual Wires (VW)``
++ +----------------------+---------+---------------------------------------+
++ |Virtual Wire |PCH Pin |Comments |
++ | |Direction| |
++ +======================+=========+=======================================+
++ |SUS_WARN# |Output |PCH pin is a GPIO when eSPI is enabled.|
++ | | |eSPI controller receives as VW message.|
++ +----------------------+---------+---------------------------------------+
++ |SUS_ACK# |Input |PCH pin is a GPIO when eSPI is enabled.|
++ | | |eSPI controller receives as VW message.|
++ +----------------------+---------+---------------------------------------+
++ |SLAVE_BOOT_LOAD_DONE |Input |Sent when the BMC has completed its |
++ | | |boot process as an indication to |
++ | | |eSPI-MC to continue with the G3 to S0 |
++ | | |exit. |
++ | | |The eSPI Master waits for the assertion|
++ | | |of this virtual wire before proceeding |
++ | | |with the SLP_S5# deassertion. |
++ | | |The intent is that it is never changed |
++ | | |except on a G3 exit - it is reset on a |
++ | | |G3 entry. |
++ +----------------------+---------+---------------------------------------+
++ |SLAVE_BOOT_LOAD_STATUS|Input |Sent upon completion of the Slave Boot |
++ | | |Load from the attached flash. A stat of|
++ | | |1 indicates that the boot code load was|
++ | | |successful and that the integrity of |
++ | | |the image is intact. |
++ +----------------------+---------+---------------------------------------+
++ |HOST_RESET_WARN |Output |Sent from the MC just before the Host |
++ | | |is about to enter reset. Upon receiving|
++ | | |, the BMC must flush and quiesce its |
++ | | |upstream Peripheral Channel request |
++ | | |queues and assert HOST_RESET_ACK VWire.|
++ | | |The MC subsequently completes any |
++ | | |outstanding posted transactions or |
++ | | |completions and then disables the |
++ | | |Peripheral Channel via a write to |
++ | | |the Slave's Configuration Register. |
++ +----------------------+---------+---------------------------------------+
++ |HOST_RESET_ACK |Input |ACK for the HOST_RESET_WARN message |
++ +----------------------+---------+---------------------------------------+
++ |OOB_RESET_WARN |Output |Sent from the MC just before the OOB |
++ | | |processor is about to enter reset. Upon|
++ | | |receiving, the BMC must flush and |
++ | | |quiesce its OOB Channel upstream |
++ | | |request queues and assert OOB_RESET_ACK|
++ | | |VWire. The-MC subsequently completes |
++ | | |any outstanding posted transactions or |
++ | | |completions and then disables the OOB |
++ | | |Channel via a write to the Slave's |
++ | | |Configuration Register. |
++ +----------------------+---------+---------------------------------------+
++ |OOB_RESET_ACK |Input |ACK for OOB_RESET_WARN message |
++ +----------------------+---------+---------------------------------------+
++
++`Intel C620 Series Chipset Platform Controller Hub
++<https://www.intel.com/content/www/us/en/chipsets/c620-series-chipset-datasheet.html>`_
++
++ -- 17. Enhanced Serial Peripheral Interface
++
++
++`Enhanced Serial Peripheral Interface (eSPI)
++- Interface Base Specification (for Client and Server Platforms)
++<https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf>`_
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 26d885d2bd8a..7b798c49cb95 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -336,6 +336,7 @@
+ clocks = <&syscon ASPEED_CLK_APB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
++ status = "disabled";
+ };
+
+ sgpio: sgpio@1e780200 {
+@@ -432,6 +433,9 @@
+ reg = <0x1e6ee000 0x100>;
+ interrupts = <23>;
+ status = "disabled";
++ clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_espi_default>;
+ };
+
+ lpc: lpc@1e789000 {
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 825e64ce317a..315d35c15208 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -4,6 +4,7 @@
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/ast2600-clock.h>
+ #include <dt-bindings/interrupt-controller/aspeed-scu-ic.h>
++#include <dt-bindings/gpio/aspeed-gpio.h>
+
+ / {
+ model = "Aspeed BMC";
+@@ -708,6 +709,19 @@
+ status = "disabled";
+ };
+
++ espi: espi@1e6ee000 {
++ compatible = "aspeed,ast2600-espi-slave";
++ reg = <0x1e6ee000 0x200>;
++ interrupts-extended = <&gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
++ <&gpio0 ASPEED_GPIO(W, 7) IRQ_TYPE_EDGE_FALLING>;
++ status = "disabled";
++ clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>;
++ resets = <&syscon ASPEED_RESET_ESPI>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_espi_default>,
++ <&pinctrl_espialt_default>;
++ };
++
+ i2c: bus@1e78a000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 06a2b753cc7c..0f9b5a356c93 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -433,6 +433,14 @@ config VEXPRESS_SYSCFG
+ bus. System Configuration interface is one of the possible means
+ of generating transactions on this bus.
+
++config ASPEED_ESPI_SLAVE
++ depends on ARCH_ASPEED || COMPILE_TEST
++ depends on REGMAP_MMIO
++ tristate "Aspeed ast2500 eSPI slave device driver"
++ ---help---
++ Control Aspeed ast2500 eSPI slave controller to handle event
++ which needs the firmware's processing.
++
+ config PCI_ENDPOINT_TEST
+ depends on PCI
+ select CRC32
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index b9e6d4c3e906..53864687e8fd 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
+ obj-$(CONFIG_ECHO) += echo/
+ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
+ obj-$(CONFIG_CXL_BASE) += cxl/
++obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o
+ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
+ obj-$(CONFIG_OCXL) += ocxl/
+ obj-y += cardreader/
+diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c
+new file mode 100644
+index 000000000000..87bc81948694
+--- /dev/null
++++ b/drivers/misc/aspeed-espi-slave.c
+@@ -0,0 +1,468 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2015-2019, Intel Corporation.
++
++#include <linux/clk.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <linux/sched/signal.h>
++#include <linux/spinlock.h>
++#include <linux/uaccess.h>
++
++#define ASPEED_ESPI_CTRL 0x00
++#define ASPEED_ESPI_CTRL_SW_RESET GENMASK(31, 24)
++#define ASPEED_ESPI_CTRL_OOB_CHRDY BIT(4)
++#define ASPEED_ESPI_INT_STS 0x08
++#define ASPEED_ESPI_HW_RESET BIT(31)
++#define ASPEED_ESPI_VW_SYSEVT1 BIT(22)
++#define ASPEED_ESPI_VW_SYSEVT BIT(8)
++#define ASPEED_ESPI_INT_EN 0x0C
++#define ASPEED_ESPI_DATA_PORT 0x28
++#define ASPEED_ESPI_SYSEVT_INT_EN 0x94
++#define ASPEED_ESPI_SYSEVT 0x98
++#define ASPEED_ESPI_SYSEVT_HOST_RST_ACK BIT(27)
++#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS BIT(23)
++#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE BIT(20)
++#define ASPEED_ESPI_SYSEVT_OOB_RST_ACK BIT(16)
++#define ASPEED_ESPI_SYSEVT_INT_T0 0x110
++#define ASPEED_ESPI_SYSEVT_INT_T1 0x114
++#define ASPEED_ESPI_SYSEVT_INT_T2 0x118
++#define ASPEED_ESPI_SYSEVT_INT_STS 0x11C
++#define ASPEED_ESPI_SYSEVT_HOST_RST_WARN BIT(8)
++#define ASPEED_ESPI_SYSEVT_OOB_RST_WARN BIT(6)
++#define ASPEED_ESPI_SYSEVT_PLTRSTN BIT(5)
++#define ASPEED_ESPI_SYSEVT1_INT_EN 0x100
++#define ASPEED_ESPI_SYSEVT1 0x104
++#define ASPEED_ESPI_SYSEVT1_SUS_ACK BIT(20)
++#define ASPEED_ESPI_SYSEVT1_INT_T0 0x120
++#define ASPEED_ESPI_SYSEVT1_INT_T1 0x124
++#define ASPEED_ESPI_SYSEVT1_INT_T2 0x128
++#define ASPEED_ESPI_SYSEVT1_INT_STS 0x12C
++#define ASPEED_ESPI_SYSEVT1_SUS_WARN BIT(0)
++
++#define ASPEED_ESPI_INT_MASK \
++ (ASPEED_ESPI_HW_RESET | \
++ ASPEED_ESPI_VW_SYSEVT1 | \
++ ASPEED_ESPI_VW_SYSEVT)
++
++/*
++ * Setup Interrupt Type / Enable of System Event from Master
++ * T2 T1 T0
++ * 1) HOST_RST_WARN : Dual Edge 1 0 0
++ * 2) OOB_RST_WARN : Dual Edge 1 0 0
++ * 3) PLTRSTN : Dual Edge 1 0 0
++ */
++#define ASPEED_ESPI_SYSEVT_INT_T0_MASK 0
++#define ASPEED_ESPI_SYSEVT_INT_T1_MASK 0
++#define ASPEED_ESPI_SYSEVT_INT_T2_MASK \
++ (ASPEED_ESPI_SYSEVT_HOST_RST_WARN | \
++ ASPEED_ESPI_SYSEVT_OOB_RST_WARN | \
++ ASPEED_ESPI_SYSEVT_PLTRSTN)
++#define ASPEED_ESPI_SYSEVT_INT_MASK \
++ (ASPEED_ESPI_SYSEVT_INT_T0_MASK | \
++ ASPEED_ESPI_SYSEVT_INT_T1_MASK | \
++ ASPEED_ESPI_SYSEVT_INT_T2_MASK)
++
++/*
++ * Setup Interrupt Type / Enable of System Event 1 from Master
++ * T2 T1 T0
++ * 1) SUS_WARN : Rising Edge 0 0 1
++ */
++#define ASPEED_ESPI_SYSEVT1_INT_T0_MASK ASPEED_ESPI_SYSEVT1_SUS_WARN
++#define ASPEED_ESPI_SYSEVT1_INT_T1_MASK 0
++#define ASPEED_ESPI_SYSEVT1_INT_T2_MASK 0
++#define ASPEED_ESPI_SYSEVT1_INT_MASK \
++ (ASPEED_ESPI_SYSEVT1_INT_T0_MASK | \
++ ASPEED_ESPI_SYSEVT1_INT_T1_MASK | \
++ ASPEED_ESPI_SYSEVT1_INT_T2_MASK)
++
++struct aspeed_espi {
++ struct regmap *map;
++ struct clk *clk;
++ struct device *dev;
++ struct reset_control *reset;
++ int irq;
++ int rst_irq;
++
++ /* for PLTRST_N signal monitoring interface */
++ struct miscdevice pltrstn_miscdev;
++ spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */
++ wait_queue_head_t pltrstn_waitq;
++ char pltrstn;
++};
++
++static void aspeed_espi_sys_event(struct aspeed_espi *priv)
++{
++ u32 sts, evt;
++
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, &sts);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt);
++
++ dev_dbg(priv->dev, "sys: sts = %08x, evt = %08x\n", sts, evt);
++
++ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT,
++ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ dev_dbg(priv->dev, "Setting espi slave boot done\n");
++ }
++ if (sts & ASPEED_ESPI_SYSEVT_HOST_RST_WARN &&
++ evt & ASPEED_ESPI_SYSEVT_HOST_RST_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT,
++ ASPEED_ESPI_SYSEVT_HOST_RST_ACK,
++ ASPEED_ESPI_SYSEVT_HOST_RST_ACK);
++ dev_dbg(priv->dev, "SYSEVT_HOST_RST_WARN: acked\n");
++ }
++ if (sts & ASPEED_ESPI_SYSEVT_OOB_RST_WARN &&
++ evt & ASPEED_ESPI_SYSEVT_OOB_RST_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT,
++ ASPEED_ESPI_SYSEVT_OOB_RST_ACK,
++ ASPEED_ESPI_SYSEVT_OOB_RST_ACK);
++ dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n");
++ }
++ if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') {
++ priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0';
++ wake_up_interruptible(&priv->pltrstn_waitq);
++ dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn);
++ }
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, sts);
++}
++
++static void aspeed_espi_sys_event1(struct aspeed_espi *priv)
++{
++ u32 sts, evt;
++
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, &sts);
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt);
++
++ dev_dbg(priv->dev, "sys event1: sts = %08x, evt = %08x\n", sts, evt);
++
++ if (sts & ASPEED_ESPI_SYSEVT1_SUS_WARN &&
++ evt & ASPEED_ESPI_SYSEVT1_SUS_WARN) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT1,
++ ASPEED_ESPI_SYSEVT1_SUS_ACK,
++ ASPEED_ESPI_SYSEVT1_SUS_ACK);
++ dev_dbg(priv->dev, "SYSEVT1_SUS_WARN: acked\n");
++ }
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, sts);
++}
++
++static void aspeed_espi_boot_ack(struct aspeed_espi *priv)
++{
++ u32 evt;
++
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt);
++ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT,
++ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ dev_dbg(priv->dev, "Setting espi slave boot done\n");
++ }
++
++ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt);
++ if (evt & ASPEED_ESPI_SYSEVT1_SUS_WARN &&
++ !(evt & ASPEED_ESPI_SYSEVT1_SUS_ACK)) {
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1,
++ evt | ASPEED_ESPI_SYSEVT1_SUS_ACK);
++ dev_dbg(priv->dev, "Boot SYSEVT1_SUS_WARN: acked\n");
++ }
++}
++
++static irqreturn_t aspeed_espi_irq(int irq, void *arg)
++{
++ struct aspeed_espi *priv = arg;
++ u32 sts, sts_handled = 0;
++
++ regmap_read(priv->map, ASPEED_ESPI_INT_STS, &sts);
++
++ dev_dbg(priv->dev, "INT_STS: 0x%08x\n", sts);
++
++ if (sts & ASPEED_ESPI_VW_SYSEVT) {
++ aspeed_espi_sys_event(priv);
++ sts_handled |= ASPEED_ESPI_VW_SYSEVT;
++ }
++
++ if (sts & ASPEED_ESPI_VW_SYSEVT1) {
++ aspeed_espi_sys_event1(priv);
++ sts_handled |= ASPEED_ESPI_VW_SYSEVT1;
++ }
++
++ if (sts & ASPEED_ESPI_HW_RESET) {
++ if (priv->rst_irq < 0) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET,
++ ASPEED_ESPI_CTRL_SW_RESET);
++ }
++
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_OOB_CHRDY,
++ ASPEED_ESPI_CTRL_OOB_CHRDY);
++ aspeed_espi_boot_ack(priv);
++ sts_handled |= ASPEED_ESPI_HW_RESET;
++ }
++
++ regmap_write(priv->map, ASPEED_ESPI_INT_STS, sts);
++
++ return sts != sts_handled ? IRQ_NONE : IRQ_HANDLED;
++}
++
++static void aspeed_espi_config_irq(struct aspeed_espi *priv)
++{
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T0,
++ ASPEED_ESPI_SYSEVT_INT_T0_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T1,
++ ASPEED_ESPI_SYSEVT_INT_T1_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T2,
++ ASPEED_ESPI_SYSEVT_INT_T2_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_EN,
++ ASPEED_ESPI_SYSEVT_INT_MASK);
++
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T0,
++ ASPEED_ESPI_SYSEVT1_INT_T0_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T1,
++ ASPEED_ESPI_SYSEVT1_INT_T1_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T2,
++ ASPEED_ESPI_SYSEVT1_INT_T2_MASK);
++ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_EN,
++ ASPEED_ESPI_SYSEVT1_INT_MASK);
++
++ regmap_write(priv->map, ASPEED_ESPI_INT_EN, ASPEED_ESPI_INT_MASK);
++}
++
++static irqreturn_t aspeed_espi_reset_isr(int irq, void *arg)
++{
++ struct aspeed_espi *priv = arg;
++
++ reset_control_assert(priv->reset);
++ reset_control_deassert(priv->reset);
++
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, ASPEED_ESPI_CTRL_SW_RESET);
++
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_OOB_CHRDY, 0);
++
++ aspeed_espi_config_irq(priv);
++
++ return IRQ_HANDLED;
++}
++
++static inline struct aspeed_espi *to_aspeed_espi(struct file *filp)
++{
++ return container_of(filp->private_data, struct aspeed_espi,
++ pltrstn_miscdev);
++}
++
++static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp)
++{
++ if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
++ return -EACCES;
++
++ return 0;
++}
++
++static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf,
++ size_t count, loff_t *offset)
++{
++ struct aspeed_espi *priv = to_aspeed_espi(filp);
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long flags;
++ char old_sample;
++ int ret = 0;
++
++ spin_lock_irqsave(&priv->pltrstn_lock, flags);
++
++ add_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ old_sample = priv->pltrstn;
++
++ do {
++ char new_sample = priv->pltrstn;
++
++ if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) {
++ ret = put_user(new_sample, (unsigned long __user *)buf);
++ if (!ret)
++ ret = sizeof(new_sample);
++ } else if (signal_pending(current)) {
++ ret = -ERESTARTSYS;
++ }
++
++ if (!ret) {
++ spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
++ schedule();
++ spin_lock_irqsave(&priv->pltrstn_lock, flags);
++ }
++ } while (!ret);
++
++ remove_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_RUNNING);
++
++ spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
++
++ return ret;
++}
++
++static const struct file_operations aspeed_espi_pltrstn_fops = {
++ .owner = THIS_MODULE,
++ .open = aspeed_espi_pltrstn_open,
++ .read = aspeed_espi_pltrstn_read,
++};
++
++static const struct regmap_config aspeed_espi_regmap_cfg = {
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .max_register = ASPEED_ESPI_SYSEVT1_INT_STS,
++};
++
++static int aspeed_espi_probe(struct platform_device *pdev)
++{
++ struct aspeed_espi *priv;
++ struct resource *res;
++ void __iomem *regs;
++ u32 ctrl;
++ int ret;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ regs = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(regs))
++ return PTR_ERR(regs);
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ dev_set_drvdata(&pdev->dev, priv);
++ priv->dev = &pdev->dev;
++
++ priv->map = devm_regmap_init_mmio(&pdev->dev, regs,
++ &aspeed_espi_regmap_cfg);
++ if (IS_ERR(priv->map))
++ return PTR_ERR(priv->map);
++
++ spin_lock_init(&priv->pltrstn_lock);
++ init_waitqueue_head(&priv->pltrstn_waitq);
++ priv->pltrstn = 'U'; /* means it's not reported yet from master */
++
++ priv->irq = platform_get_irq(pdev, 0);
++ if (priv->irq < 0)
++ return priv->irq;
++
++ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_espi_irq, 0,
++ "aspeed-espi-irq", priv);
++ if (ret)
++ return ret;
++
++ if (of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2600-espi-slave")) {
++ priv->rst_irq = platform_get_irq(pdev, 1);
++ if (priv->rst_irq < 0)
++ return priv->rst_irq;
++
++ ret = devm_request_irq(&pdev->dev, priv->rst_irq,
++ aspeed_espi_reset_isr, 0,
++ "aspeed-espi-rst-irq", priv);
++ if (ret)
++ return ret;
++
++ priv->reset = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->reset))
++ return PTR_ERR(priv->reset);
++ } else {
++ priv->rst_irq = -ENOTSUPP;
++ }
++
++ priv->clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ ret = PTR_ERR(priv->clk);
++ if (ret != -EPROBE_DEFER)
++ dev_err(&pdev->dev, "couldn't get clock\n");
++ return ret;
++ }
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(&pdev->dev, "couldn't enable clock\n");
++ return ret;
++ }
++
++ /*
++ * We check that the regmap works on this very first access, but as this
++ * is an MMIO-backed regmap, subsequent regmap access is not going to
++ * fail and we skip error checks from this point.
++ */
++ ret = regmap_read(priv->map, ASPEED_ESPI_CTRL, &ctrl);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to read ctrl register\n");
++ goto err_clk_disable_out;
++ }
++ regmap_write(priv->map, ASPEED_ESPI_CTRL,
++ ctrl | ASPEED_ESPI_CTRL_OOB_CHRDY);
++
++ priv->pltrstn_miscdev.minor = MISC_DYNAMIC_MINOR;
++ priv->pltrstn_miscdev.name = "espi-pltrstn";
++ priv->pltrstn_miscdev.fops = &aspeed_espi_pltrstn_fops;
++ priv->pltrstn_miscdev.parent = &pdev->dev;
++
++ ret = misc_register(&priv->pltrstn_miscdev);
++ if (ret) {
++ dev_err(&pdev->dev, "Unable to register device\n");
++ goto err_clk_disable_out;
++ }
++
++ aspeed_espi_config_irq(priv);
++ aspeed_espi_boot_ack(priv);
++
++ dev_info(&pdev->dev, "eSPI registered, irq %d\n", priv->irq);
++
++ return 0;
++
++err_clk_disable_out:
++ clk_disable_unprepare(priv->clk);
++
++ return ret;
++}
++
++static int aspeed_espi_remove(struct platform_device *pdev)
++{
++ struct aspeed_espi *priv = dev_get_drvdata(&pdev->dev);
++
++ misc_deregister(&priv->pltrstn_miscdev);
++ clk_disable_unprepare(priv->clk);
++
++ return 0;
++}
++
++static const struct of_device_id of_espi_match_table[] = {
++ { .compatible = "aspeed,ast2500-espi-slave" },
++ { .compatible = "aspeed,ast2600-espi-slave" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, of_espi_match_table);
++
++static struct platform_driver aspeed_espi_driver = {
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = of_match_ptr(of_espi_match_table),
++ },
++ .probe = aspeed_espi_probe,
++ .remove = aspeed_espi_remove,
++};
++module_platform_driver(aspeed_espi_driver);
++
++MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("Aspeed eSPI driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
+index 3d90582a813f..1e18364de03d 100644
+--- a/include/dt-bindings/clock/ast2600-clock.h
++++ b/include/dt-bindings/clock/ast2600-clock.h
+@@ -104,6 +104,7 @@
+ #define ASPEED_RESET_PECI 36
+ #define ASPEED_RESET_MII 35
+ #define ASPEED_RESET_I2C 34
++#define ASPEED_RESET_ESPI 32
+ #define ASPEED_RESET_H2X 31
+ #define ASPEED_RESET_GP_MCU 30
+ #define ASPEED_RESET_DP_MCU 29
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
new file mode 100644
index 000000000..45dec5b20
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
@@ -0,0 +1,95 @@
+From a4413fe3ba94906243b632e0b9e0e9a91620dd22 Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Fri, 1 Mar 2019 11:46:09 -0700
+Subject: [PATCH] Add AST2500 JTAG driver
+
+Update AST2500 JTAG driver. Remove Legacy driver but keep headers.
+
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+---
+ include/uapi/linux/jtag_drv.h | 73 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 73 insertions(+)
+ create mode 100644 include/uapi/linux/jtag_drv.h
+
+diff --git a/include/uapi/linux/jtag_drv.h b/include/uapi/linux/jtag_drv.h
+new file mode 100644
+index 000000000000..4df638f8fa43
+--- /dev/null
++++ b/include/uapi/linux/jtag_drv.h
+@@ -0,0 +1,73 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (C) 2012-2017 ASPEED Technology Inc. */
++/* Copyright (c) 2018 Intel Corporation */
++
++#ifndef __JTAG_DRV_H__
++#define __JTAG_DRV_H__
++
++enum xfer_mode {
++ HW_MODE = 0,
++ SW_MODE
++} xfer_mode;
++
++struct tck_bitbang {
++ __u8 tms;
++ __u8 tdi;
++ __u8 tdo;
++} __attribute__((__packed__));
++
++struct scan_xfer {
++ __u8 mode;
++ __u32 tap_state;
++ __u32 length;
++ __u8 *tdi;
++ __u32 tdi_bytes;
++ __u8 *tdo;
++ __u32 tdo_bytes;
++ __u32 end_tap_state;
++} __attribute__((__packed__));
++
++struct set_tck_param {
++ __u8 mode;
++ __u32 tck;
++} __attribute__((__packed__));
++
++struct get_tck_param {
++ __u8 mode;
++ __u32 tck;
++} __attribute__((__packed__));
++
++struct tap_state_param {
++ __u8 mode;
++ __u32 from_state;
++ __u32 to_state;
++} __attribute__((__packed__));
++
++enum jtag_states {
++ jtag_tlr,
++ jtag_rti,
++ jtag_sel_dr,
++ jtag_cap_dr,
++ jtag_shf_dr,
++ jtag_ex1_dr,
++ jtag_pau_dr,
++ jtag_ex2_dr,
++ jtag_upd_dr,
++ jtag_sel_ir,
++ jtag_cap_ir,
++ jtag_shf_ir,
++ jtag_ex1_ir,
++ jtag_pau_ir,
++ jtag_ex2_ir,
++ jtag_upd_ir
++} jtag_states;
++
++#define JTAGIOC_BASE 'T'
++
++#define AST_JTAG_SET_TCK _IOW(JTAGIOC_BASE, 3, struct set_tck_param)
++#define AST_JTAG_GET_TCK _IOR(JTAGIOC_BASE, 4, struct get_tck_param)
++#define AST_JTAG_BITBANG _IOWR(JTAGIOC_BASE, 5, struct tck_bitbang)
++#define AST_JTAG_SET_TAPSTATE _IOW(JTAGIOC_BASE, 6, struct tap_state_param)
++#define AST_JTAG_READWRITESCAN _IOWR(JTAGIOC_BASE, 7, struct scan_xfer)
++
++#endif
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch
new file mode 100644
index 000000000..c9844e1bd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch
@@ -0,0 +1,145 @@
+From a57f401058e452f9abb6f3233e7f2776af1e6b8d Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 29 Jun 2018 11:00:02 -0700
+Subject: [PATCH] Add dump debug code into I2C drivers
+
+This commit enables dump debug of master and slave I2C drivers.
+This is only for downstream debug purpose so it shouldn't go to
+the upstream.
+
+Usage (in case of bus 5 for an example):
+echo 5 > /sys/module/i2c_aspeed/parameters/dump_debug_bus_id
+echo 1 > /sys/module/i2c_aspeed/parameters/dump_debug
+echo 5 > /sys/module/i2c_slave_mqueue/parameters/dump_debug_bus_id
+echo 1 > /sys/module/i2c_slave_mqueue/parameters/dump_debug
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 26 ++++++++++++++++++++++++++
+ drivers/i2c/i2c-slave-mqueue.c | 24 ++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index a7be6f24450b..c113ffa8d5df 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -169,6 +169,21 @@ struct aspeed_i2c_bus {
+ #endif /* CONFIG_I2C_SLAVE */
+ };
+
++static bool dump_debug __read_mostly;
++static int dump_debug_bus_id __read_mostly;
++
++#define I2C_HEX_DUMP(bus, addr, flags, buf, len) \
++ do { \
++ if (dump_debug && (bus)->adap.nr == dump_debug_bus_id) { \
++ char dump_info[100] = {0,}; \
++ snprintf(dump_info, sizeof(dump_info), \
++ "bus_id:%d, addr:0x%02x, flags:0x%02x: ", \
++ (bus)->adap.nr, addr, flags); \
++ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, \
++ 16, 1, buf, len, true); \
++ } \
++ } while (0)
++
+ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
+
+ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+@@ -657,6 +672,7 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
+ {
+ struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap);
+ unsigned long time_left, flags;
++ int i;
+
+ spin_lock_irqsave(&bus->lock, flags);
+ bus->cmd_err = 0;
+@@ -708,6 +724,11 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
+ return -ETIMEDOUT;
+ }
+
++ for (i = 0; i < num; i++) {
++ I2C_HEX_DUMP(bus, msgs[i].addr, msgs[i].flags,
++ msgs[i].buf, msgs[i].len);
++ }
++
+ return bus->master_xfer_result;
+ }
+
+@@ -1079,6 +1100,11 @@ static struct platform_driver aspeed_i2c_bus_driver = {
+ };
+ module_platform_driver(aspeed_i2c_bus_driver);
+
++module_param_named(dump_debug, dump_debug, bool, 0644);
++MODULE_PARM_DESC(dump_debug, "debug flag for dump printing");
++module_param_named(dump_debug_bus_id, dump_debug_bus_id, int, 0644);
++MODULE_PARM_DESC(dump_debug_bus_id, "bus id for dump debug printing");
++
+ MODULE_AUTHOR("Brendan Higgins <brendanhiggins@google.com>");
+ MODULE_DESCRIPTION("Aspeed I2C Bus Driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c
+index 6014bca0ff2a..2c7a6038409c 100644
+--- a/drivers/i2c/i2c-slave-mqueue.c
++++ b/drivers/i2c/i2c-slave-mqueue.c
+@@ -21,6 +21,7 @@ struct mq_msg {
+ struct mq_queue {
+ struct bin_attribute bin;
+ struct kernfs_node *kn;
++ struct i2c_client *client;
+
+ spinlock_t lock; /* spinlock for queue index handling */
+ int in;
+@@ -31,6 +32,21 @@ struct mq_queue {
+ struct mq_msg *queue;
+ };
+
++static bool dump_debug __read_mostly;
++static int dump_debug_bus_id __read_mostly;
++
++#define I2C_HEX_DUMP(client, buf, len) \
++ do { \
++ if (dump_debug && \
++ (client)->adapter->nr == dump_debug_bus_id) { \
++ char dump_info[100] = {0,}; \
++ snprintf(dump_info, sizeof(dump_info), \
++ "bus_id:%d: ", (client)->adapter->nr); \
++ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, \
++ 16, 1, buf, len, true); \
++ } \
++ } while (0)
++
+ static int i2c_slave_mqueue_callback(struct i2c_client *client,
+ enum i2c_slave_event event, u8 *val)
+ {
+@@ -101,6 +117,7 @@ static ssize_t i2c_slave_mqueue_bin_read(struct file *filp,
+ if (msg->len <= count) {
+ ret = msg->len;
+ memcpy(buf, msg->buf, ret);
++ I2C_HEX_DUMP(mq->client, buf, ret);
+ } else {
+ ret = -EOVERFLOW; /* Drop this HUGE one. */
+ }
+@@ -131,6 +148,8 @@ static int i2c_slave_mqueue_probe(struct i2c_client *client,
+
+ BUILD_BUG_ON(!is_power_of_2(MQ_QUEUE_SIZE));
+
++ mq->client = client;
++
+ buf = devm_kmalloc_array(dev, MQ_QUEUE_SIZE, MQ_MSGBUF_SIZE,
+ GFP_KERNEL);
+ if (!buf)
+@@ -212,6 +231,11 @@ static struct i2c_driver i2c_slave_mqueue_driver = {
+ };
+ module_i2c_driver(i2c_slave_mqueue_driver);
+
++module_param_named(dump_debug, dump_debug, bool, 0644);
++MODULE_PARM_DESC(dump_debug, "debug flag for dump printing");
++module_param_named(dump_debug_bus_id, dump_debug_bus_id, int, 0644);
++MODULE_PARM_DESC(dump_debug_bus_id, "bus id for dump debug printing");
++
+ MODULE_LICENSE("GPL v2");
+ MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
+ MODULE_DESCRIPTION("I2C slave mode for receiving and queuing messages");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch
new file mode 100644
index 000000000..5240a05f5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch
@@ -0,0 +1,135 @@
+From 0bc792097e73c07bc324e2c9b0172fb27b51a087 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Wed, 2 Jan 2019 15:06:43 +0800
+Subject: [PATCH] Add high speed baud rate support for UART
+
+In order to support high speed baud rate(921600 bps),
+the default UART clock(24MHz) needs to be switched
+to 192MHz(from USB2.0 port1 PHY).
+
+Create a new 192M Hz clock and assign it to uart,
+based on uart clock source configuration in SCU4C.
+
+bootloader(u-boot) will set SCU4C based on the environment configuration
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ drivers/clk/clk-aspeed.c | 44 +++++++++++++++++++++++++++-----
+ include/dt-bindings/clock/aspeed-clock.h | 2 ++
+ 2 files changed, 39 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c
+index 411ff5fb2c07..5e1c87bc8a99 100644
+--- a/drivers/clk/clk-aspeed.c
++++ b/drivers/clk/clk-aspeed.c
+@@ -14,7 +14,9 @@
+
+ #include "clk-aspeed.h"
+
+-#define ASPEED_NUM_CLKS 38
++#define ASPEED_NUM_CLKS ASPEED_CLK_MAX
++#define UART_HIGH_SPEED_CLK 192000000
++#define UART_LOW_SPEED_CLK 24000000
+
+ #define ASPEED_RESET2_OFFSET 32
+
+@@ -29,6 +31,12 @@
+ #define ASPEED_MISC_CTRL 0x2c
+ #define UART_DIV13_EN BIT(12)
+ #define ASPEED_MAC_CLK_DLY 0x48
++#define ASPEED_MISC2_CTRL 0x4c
++#define UART1_HS_CLK_EN BIT(24)
++#define UART2_HS_CLK_EN BIT(25)
++#define UART3_HS_CLK_EN BIT(26)
++#define UART4_HS_CLK_EN BIT(27)
++#define UART5_HS_CLK_EN BIT(28)
+ #define ASPEED_STRAP 0x70
+ #define CLKIN_25MHZ_EN BIT(23)
+ #define AST2400_CLK_SOURCE_SEL BIT(18)
+@@ -386,7 +394,7 @@ static int aspeed_clk_probe(struct platform_device *pdev)
+ struct aspeed_reset *ar;
+ struct regmap *map;
+ struct clk_hw *hw;
+- u32 val, rate;
++ u32 val, rate, rate_hi;
+ int i, ret;
+
+ map = syscon_node_to_regmap(dev->of_node);
+@@ -420,16 +428,25 @@ static int aspeed_clk_probe(struct platform_device *pdev)
+
+ /* UART clock div13 setting */
+ regmap_read(map, ASPEED_MISC_CTRL, &val);
+- if (val & UART_DIV13_EN)
+- rate = 24000000 / 13;
+- else
+- rate = 24000000;
++ if (val & UART_DIV13_EN) {
++ rate = UART_LOW_SPEED_CLK / 13;
++ rate_hi = UART_HIGH_SPEED_CLK / 13;
++ } else {
++ rate = UART_LOW_SPEED_CLK;
++ rate_hi = UART_HIGH_SPEED_CLK;
++ }
+ /* TODO: Find the parent data for the uart clock */
+ hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ aspeed_clk_data->hws[ASPEED_CLK_UART] = hw;
+
++ hw = clk_hw_register_fixed_rate(dev, "uart-hs", "usb-port1-gate", 0,
++ rate_hi);
++ if (IS_ERR(hw))
++ return PTR_ERR(hw);
++ aspeed_clk_data->hws[ASPEED_CLK_UART_HS] = hw;
++
+ /*
+ * Memory controller (M-PLL) PLL. This clock is configured by the
+ * bootloader, and is exposed to Linux as a read-only clock rate.
+@@ -539,9 +556,22 @@ static int aspeed_clk_probe(struct platform_device *pdev)
+ * UART[1..5] clock source mux
+ */
+
++ /* Get the uart clock source configuration from SCU4C*/
++ regmap_read(map, ASPEED_MISC2_CTRL, &val);
+ for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) {
+ const struct aspeed_gate_data *gd = &aspeed_gates[i];
+ u32 gate_flags;
++ char *parent_name;
++
++ /* For uart, needs to adjust the clock based on SCU4C value */
++ if ((i == ASPEED_CLK_GATE_UART1CLK && (val & UART1_HS_CLK_EN)) ||
++ (i == ASPEED_CLK_GATE_UART2CLK && (val & UART2_HS_CLK_EN)) ||
++ (i == ASPEED_CLK_GATE_UART5CLK && (val & UART5_HS_CLK_EN)) ||
++ (i == ASPEED_CLK_GATE_UART3CLK && (val & UART3_HS_CLK_EN)) ||
++ (i == ASPEED_CLK_GATE_UART4CLK && (val & UART4_HS_CLK_EN)))
++ parent_name = "uart-hs";
++ else
++ parent_name = gd->parent_name;
+
+ /* Special case: the USB port 1 clock (bit 14) is always
+ * working the opposite way from the other ones.
+@@ -549,7 +579,7 @@ static int aspeed_clk_probe(struct platform_device *pdev)
+ gate_flags = (gd->clock_idx == 14) ? 0 : CLK_GATE_SET_TO_DISABLE;
+ hw = aspeed_clk_hw_register_gate(dev,
+ gd->name,
+- gd->parent_name,
++ parent_name,
+ gd->flags,
+ map,
+ gd->clock_idx,
+diff --git a/include/dt-bindings/clock/aspeed-clock.h b/include/dt-bindings/clock/aspeed-clock.h
+index 9ff4f6e4558c..41d531dd0b48 100644
+--- a/include/dt-bindings/clock/aspeed-clock.h
++++ b/include/dt-bindings/clock/aspeed-clock.h
+@@ -41,6 +41,8 @@
+ #define ASPEED_CLK_24M 35
+ #define ASPEED_CLK_MAC1RCLK 36
+ #define ASPEED_CLK_MAC2RCLK 37
++#define ASPEED_CLK_UART_HS 38
++#define ASPEED_CLK_MAX 39
+
+ #define ASPEED_RESET_XDMA 0
+ #define ASPEED_RESET_MCTP 1
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch
new file mode 100644
index 000000000..2ba9e5002
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch
@@ -0,0 +1,559 @@
+From 09aa5d5af94823f100fb515d45b0a04fc8d7ee4f Mon Sep 17 00:00:00 2001
+From: Oskar Senft <osk@google.com>
+Date: Wed, 8 Aug 2018 10:15:05 -0400
+Subject: [PATCH] misc: aspeed: Add Aspeed UART routing control driver.
+
+This driver adds sysfs files that allow the BMC userspace to configure
+how UARTs and physical serial I/O ports are routed.
+
+Tested: Checked correct behavior (both read & write) on TYAN S7106
+board by manually changing routing settings and confirming that bits
+flow as expected. Tested for UART1 and UART3 as this board doesn't have
+the other UARTs wired up in a testable way.
+
+Signed-off-by: Oskar Senft <osk@google.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ .../ABI/stable/sysfs-driver-aspeed-uart-routing | 14 +
+ Documentation/misc-devices/aspeed-uart-routing.txt | 49 +++
+ arch/arm/boot/dts/aspeed-g5.dtsi | 6 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 6 +
+ drivers/misc/Kconfig | 6 +
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-uart-routing.c | 383 +++++++++++++++++++++
+ 7 files changed, 465 insertions(+)
+ create mode 100644 Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing
+ create mode 100644 Documentation/misc-devices/aspeed-uart-routing.txt
+ create mode 100644 drivers/misc/aspeed-uart-routing.c
+
+diff --git a/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing b/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing
+new file mode 100644
+index 000000000000..5068737d9c12
+--- /dev/null
++++ b/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing
+@@ -0,0 +1,14 @@
++What: /sys/bus/platform/drivers/aspeed-uart-routing/*/io*
++Date: August 2018
++Contact: Oskar Senft <osk@google.com>
++Description: Configures the input source for the specific physical
++ serial I/O port.
++Users: OpenBMC. Proposed changes should be mailed to
++ openbmc@lists.ozlabs.org
++
++What: /sys/bus/platform/drivers/aspeed-uart-routing/*/uart*
++Date: August 2018
++Contact: Oskar Senft <osk@google.com>
++Description: Configures the input source for the specific UART.
++Users: OpenBMC. Proposed changes should be mailed to
++ openbmc@lists.ozlabs.org
+diff --git a/Documentation/misc-devices/aspeed-uart-routing.txt b/Documentation/misc-devices/aspeed-uart-routing.txt
+new file mode 100644
+index 000000000000..cf1c2a466875
+--- /dev/null
++++ b/Documentation/misc-devices/aspeed-uart-routing.txt
+@@ -0,0 +1,49 @@
++Kernel driver aspeed-uart-routing
++=================================
++
++Supported chips:
++ASPEED AST2500/AST2600
++
++Author:
++Google LLC
++
++Description
++-----------
++
++The Aspeed AST2500/AST2600 allows to dynamically route the inputs for the
++built-in UARTS and physical serial I/O ports.
++
++This allows, for example, to connect the output of UART to another UART.
++This can be used to enable host<->BMC communication via UARTs, e.g. to allow
++access to the host's serial console.
++
++This driver is for the BMC side. The sysfs files allow the BMC userspace
++which owns the system configuration policy, to configure how UARTs and
++physical serial I/O ports are routed.
++
++The driver provides the following files in sysfs:
++uart1 Configure the input signal to UART1.
++uart2 Configure the input signal to UART2.
++uart3 Configure the input signal to UART3.
++uart4 Configure the input signal to UART4.
++uart5 Configure the input signal to UART5.
++io1 Configure the input signal to physical serial port 1.
++io2 Configure the input signal to physical serial port 2.
++io3 Configure the input signal to physical serial port 3.
++io4 Configure the input signal to physical serial port 4.
++io5 Configure the input signal to physical serial port 5.
++
++When read, each file shows the list of available options with the currently
++selected option marked by square brackets "[]". The list of available options
++depends on the selected file.
++
++Example:
++$ cat /sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1
++[io1] io2 io3 io4 uart2 uart3 uart4 io6
++
++In this case, UART1 gets its input signal from IO1 (physical serial port 1).
++
++$ echo -n "uart3" \
++ >/sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1
++$ cat /sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1
++io1 io2 io3 io4 uart2 [uart3] uart4 io6
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index bd2037e52a94..797013debaa7 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -523,6 +523,12 @@
+ status = "disabled";
+ };
+ };
++
++ uart_routing: uart_routing@9c {
++ compatible = "aspeed,ast2500-uart-routing";
++ reg = <0x9c 0x4>;
++ status = "disabled";
++ };
+ };
+
+ peci: bus@1e78b000 {
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index e4c1ab3d274e..8cc978058f16 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -291,6 +291,12 @@
+ compatible = "aspeed,ast2600-pinctrl";
+ };
+
++ uart_routing: uart_routing@9c {
++ compatible = "aspeed,ast2500-uart-routing";
++ reg = <0x9c 0x4>;
++ status = "disabled";
++ };
++
+ smp-memram@180 {
+ compatible = "aspeed,ast2600-smpmem";
+ reg = <0x180 0x40>;
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 0f9b5a356c93..8af817694648 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -441,6 +441,12 @@ config ASPEED_ESPI_SLAVE
+ Control Aspeed ast2500 eSPI slave controller to handle event
+ which needs the firmware's processing.
+
++config ASPEED_UART_ROUTING
++ tristate "Aspeed ast2500 UART routing control"
++ help
++ If you want to configure UART routing on Aspeed BMC platforms, enable
++ this option.
++
+ config PCI_ENDPOINT_TEST
+ depends on PCI
+ select CRC32
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 53864687e8fd..a4372208f4de 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -52,6 +52,7 @@ obj-$(CONFIG_ECHO) += echo/
+ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
+ obj-$(CONFIG_CXL_BASE) += cxl/
+ obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o
++obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
+ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
+ obj-$(CONFIG_OCXL) += ocxl/
+ obj-y += cardreader/
+diff --git a/drivers/misc/aspeed-uart-routing.c b/drivers/misc/aspeed-uart-routing.c
+new file mode 100644
+index 000000000000..21ef5d98c317
+--- /dev/null
++++ b/drivers/misc/aspeed-uart-routing.c
+@@ -0,0 +1,383 @@
++/*
++ * UART Routing driver for Aspeed AST2500
++ *
++ * Copyright (c) 2018 Google LLC
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_platform.h>
++
++/* The Aspeed AST2500 allows to dynamically route the inputs for the built-in
++ * UARTS and physical serial I/O ports.
++ *
++ * This allows, for example, to connect the output of UART to another UART.
++ * This can be used to enable host<->BMC communication via UARTs, e.g. to allow
++ * access to the host's serial console.
++ *
++ * This driver is for the BMC side. The sysfs files allow the BMC userspace
++ * which owns the system configuration policy, to configure how UARTs and
++ * physical serial I/O ports are routed.
++ */
++
++#define ASPEED_HICRA_IO1 "io1"
++#define ASPEED_HICRA_IO2 "io2"
++#define ASPEED_HICRA_IO3 "io3"
++#define ASPEED_HICRA_IO4 "io4"
++#define ASPEED_HICRA_IO5 "io5"
++#define ASPEED_HICRA_IO6 "io6"
++#define ASPEED_HICRA_UART1 "uart1"
++#define ASPEED_HICRA_UART2 "uart2"
++#define ASPEED_HICRA_UART3 "uart3"
++#define ASPEED_HICRA_UART4 "uart4"
++#define ASPEED_HICRA_UART5 "uart5"
++
++struct aspeed_uart_routing {
++ struct device *dev;
++ void __iomem *regs;
++ spinlock_t lock;
++};
++
++struct aspeed_uart_routing_selector {
++ struct device_attribute dev_attr;
++ int shift;
++ int mask;
++ const char * const options[];
++};
++
++#define to_routing_selector(_dev_attr) \
++ container_of(_dev_attr, struct aspeed_uart_routing_selector, dev_attr)
++
++
++static ssize_t aspeed_uart_routing_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf);
++
++static ssize_t aspeed_uart_routing_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count);
++
++#define ROUTING_ATTR(_name) { \
++ .attr = {.name = _name, \
++ .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \
++ .show = aspeed_uart_routing_show, \
++ .store = aspeed_uart_routing_store, \
++}
++
++static struct aspeed_uart_routing_selector uart5_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART5),
++ .shift = 28,
++ .mask = 0xf,
++ .options = {
++ ASPEED_HICRA_IO5, // 0
++ ASPEED_HICRA_IO1, // 1
++ ASPEED_HICRA_IO2, // 2
++ ASPEED_HICRA_IO3, // 3
++ ASPEED_HICRA_IO4, // 4
++ ASPEED_HICRA_UART1, // 5
++ ASPEED_HICRA_UART2, // 6
++ ASPEED_HICRA_UART3, // 7
++ ASPEED_HICRA_UART4, // 8
++ ASPEED_HICRA_IO6, // 9
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector uart4_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART4),
++ .shift = 25,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_IO4, // 0
++ ASPEED_HICRA_IO1, // 1
++ ASPEED_HICRA_IO2, // 2
++ ASPEED_HICRA_IO3, // 3
++ ASPEED_HICRA_UART1, // 4
++ ASPEED_HICRA_UART2, // 5
++ ASPEED_HICRA_UART3, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector uart3_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART3),
++ .shift = 22,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_IO3, // 0
++ ASPEED_HICRA_IO4, // 1
++ ASPEED_HICRA_IO1, // 2
++ ASPEED_HICRA_IO2, // 3
++ ASPEED_HICRA_UART4, // 4
++ ASPEED_HICRA_UART1, // 5
++ ASPEED_HICRA_UART2, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector uart2_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART2),
++ .shift = 19,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_IO2, // 0
++ ASPEED_HICRA_IO3, // 1
++ ASPEED_HICRA_IO4, // 2
++ ASPEED_HICRA_IO1, // 3
++ ASPEED_HICRA_UART3, // 4
++ ASPEED_HICRA_UART4, // 5
++ ASPEED_HICRA_UART1, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector uart1_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART1),
++ .shift = 16,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_IO1, // 0
++ ASPEED_HICRA_IO2, // 1
++ ASPEED_HICRA_IO3, // 2
++ ASPEED_HICRA_IO4, // 3
++ ASPEED_HICRA_UART2, // 4
++ ASPEED_HICRA_UART3, // 5
++ ASPEED_HICRA_UART4, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector io5_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO5),
++ .shift = 12,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_UART5, // 0
++ ASPEED_HICRA_UART1, // 1
++ ASPEED_HICRA_UART2, // 2
++ ASPEED_HICRA_UART3, // 3
++ ASPEED_HICRA_UART4, // 4
++ ASPEED_HICRA_IO1, // 5
++ ASPEED_HICRA_IO3, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector io4_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO4),
++ .shift = 9,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_UART4, // 0
++ ASPEED_HICRA_UART5, // 1
++ ASPEED_HICRA_UART1, // 2
++ ASPEED_HICRA_UART2, // 3
++ ASPEED_HICRA_UART3, // 4
++ ASPEED_HICRA_IO1, // 5
++ ASPEED_HICRA_IO2, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector io3_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO3),
++ .shift = 6,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_UART3, // 0
++ ASPEED_HICRA_UART4, // 1
++ ASPEED_HICRA_UART5, // 2
++ ASPEED_HICRA_UART1, // 3
++ ASPEED_HICRA_UART2, // 4
++ ASPEED_HICRA_IO1, // 5
++ ASPEED_HICRA_IO2, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector io2_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO2),
++ .shift = 3,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_UART2, // 0
++ ASPEED_HICRA_UART3, // 1
++ ASPEED_HICRA_UART4, // 2
++ ASPEED_HICRA_UART5, // 3
++ ASPEED_HICRA_UART1, // 4
++ ASPEED_HICRA_IO3, // 5
++ ASPEED_HICRA_IO4, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++static struct aspeed_uart_routing_selector io1_sel = {
++ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO1),
++ .shift = 0,
++ .mask = 0x7,
++ .options = {
++ ASPEED_HICRA_UART1, // 0
++ ASPEED_HICRA_UART2, // 1
++ ASPEED_HICRA_UART3, // 2
++ ASPEED_HICRA_UART4, // 3
++ ASPEED_HICRA_UART5, // 4
++ ASPEED_HICRA_IO3, // 5
++ ASPEED_HICRA_IO4, // 6
++ ASPEED_HICRA_IO6, // 7
++ NULL, // NULL termination
++ },
++};
++
++
++static struct attribute *aspeed_uart_routing_attrs[] = {
++ &uart1_sel.dev_attr.attr,
++ &uart2_sel.dev_attr.attr,
++ &uart3_sel.dev_attr.attr,
++ &uart4_sel.dev_attr.attr,
++ &uart5_sel.dev_attr.attr,
++ &io1_sel.dev_attr.attr,
++ &io2_sel.dev_attr.attr,
++ &io3_sel.dev_attr.attr,
++ &io4_sel.dev_attr.attr,
++ &io5_sel.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group aspeed_uart_routing_attr_group = {
++ .attrs = aspeed_uart_routing_attrs,
++};
++
++static ssize_t aspeed_uart_routing_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
++ struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
++ int val, pos, len;
++
++ val = (readl(uart_routing->regs) >> sel->shift) & sel->mask;
++
++ len = 0;
++ for (pos = 0; sel->options[pos] != NULL; ++pos) {
++ if (pos == val) {
++ len += snprintf(buf + len, PAGE_SIZE - 1 - len,
++ "[%s] ", sel->options[pos]);
++ } else {
++ len += snprintf(buf + len, PAGE_SIZE - 1 - len,
++ "%s ", sel->options[pos]);
++ }
++ }
++
++ if (val >= pos) {
++ len += snprintf(buf + len, PAGE_SIZE - 1 - len,
++ "[unknown(%d)]", val);
++ }
++
++ len += snprintf(buf + len, PAGE_SIZE - 1 - len, "\n");
++
++ return len;
++}
++
++static ssize_t aspeed_uart_routing_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev);
++ struct aspeed_uart_routing_selector *sel = to_routing_selector(attr);
++ int val;
++ u32 reg;
++
++ val = match_string(sel->options, -1, buf);
++ if (val < 0) {
++ dev_err(dev, "invalid value \"%s\"\n", buf);
++ return -EINVAL;
++ }
++
++ spin_lock(&uart_routing->lock);
++ reg = readl(uart_routing->regs);
++ // Zero out existing value in specified bits.
++ reg &= ~(sel->mask << sel->shift);
++ // Set new value in specified bits.
++ reg |= (val & sel->mask) << sel->shift;
++ writel(reg, uart_routing->regs);
++ spin_unlock(&uart_routing->lock);
++
++ return count;
++}
++
++static int aspeed_uart_routing_probe(struct platform_device *pdev)
++{
++ struct aspeed_uart_routing *uart_routing;
++ struct resource *res;
++ int rc;
++
++ uart_routing = devm_kzalloc(&pdev->dev,
++ sizeof(*uart_routing),
++ GFP_KERNEL);
++ if (!uart_routing)
++ return -ENOMEM;
++
++ spin_lock_init(&uart_routing->lock);
++ uart_routing->dev = &pdev->dev;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ uart_routing->regs = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(uart_routing->regs))
++ return PTR_ERR(uart_routing->regs);
++
++ rc = sysfs_create_group(&uart_routing->dev->kobj,
++ &aspeed_uart_routing_attr_group);
++ if (rc < 0)
++ return rc;
++
++ platform_set_drvdata(pdev, uart_routing);
++
++ return 0;
++}
++
++static int aspeed_uart_routing_remove(struct platform_device *pdev)
++{
++ struct aspeed_uart_routing *uart_routing = platform_get_drvdata(pdev);
++
++ sysfs_remove_group(&uart_routing->dev->kobj,
++ &aspeed_uart_routing_attr_group);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_uart_routing_table[] = {
++ { .compatible = "aspeed,ast2500-uart-routing" },
++ { },
++};
++
++static struct platform_driver aspeed_uart_routing_driver = {
++ .driver = {
++ .name = "aspeed-uart-routing",
++ .of_match_table = aspeed_uart_routing_table,
++ },
++ .probe = aspeed_uart_routing_probe,
++ .remove = aspeed_uart_routing_remove,
++};
++
++module_platform_driver(aspeed_uart_routing_driver);
++
++MODULE_AUTHOR("Oskar Senft <osk@google.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("Driver to configure Aspeed UART routing");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch
new file mode 100644
index 000000000..2f0fd3a31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch
@@ -0,0 +1,85 @@
+From 65c8090f2b418892aee9f239729fa417bd508a00 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 3 Oct 2018 10:17:58 -0700
+Subject: [PATCH] arm: dts: aspeed: Swap the mac nodes numbering
+
+This patch swaps the numbering of mac0 and mac1 to make a dedicated
+nic get assigned the first ethernet device number.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 16 ++++++++--------
+ arch/arm/boot/dts/aspeed-g5.dtsi | 16 ++++++++--------
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index a70bee24d058..054d97229626 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -120,14 +120,6 @@
+ reg = <0x1e6c2000 0x80>;
+ };
+
+- mac0: ethernet@1e660000 {
+- compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
+- reg = <0x1e660000 0x180>;
+- interrupts = <2>;
+- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>;
+- status = "disabled";
+- };
+-
+ mac1: ethernet@1e680000 {
+ compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
+ reg = <0x1e680000 0x180>;
+@@ -136,6 +128,14 @@
+ status = "disabled";
+ };
+
++ mac0: ethernet@1e660000 {
++ compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
++ reg = <0x1e660000 0x180>;
++ interrupts = <2>;
++ clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>;
++ status = "disabled";
++ };
++
+ ehci0: usb@1e6a1000 {
+ compatible = "aspeed,ast2400-ehci", "generic-ehci";
+ reg = <0x1e6a1000 0x100>;
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 797013debaa7..27ed188296a1 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -148,14 +148,6 @@
+ reg = <0x1e6c2000 0x80>;
+ };
+
+- mac0: ethernet@1e660000 {
+- compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
+- reg = <0x1e660000 0x180>;
+- interrupts = <2>;
+- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>;
+- status = "disabled";
+- };
+-
+ mac1: ethernet@1e680000 {
+ compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
+ reg = <0x1e680000 0x180>;
+@@ -164,6 +156,14 @@
+ status = "disabled";
+ };
+
++ mac0: ethernet@1e660000 {
++ compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
++ reg = <0x1e660000 0x180>;
++ interrupts = <2>;
++ clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>;
++ status = "disabled";
++ };
++
+ ehci0: usb@1e6a1000 {
+ compatible = "aspeed,ast2500-ehci", "generic-ehci";
+ reg = <0x1e6a1000 0x100>;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
new file mode 100644
index 000000000..741b44462
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
@@ -0,0 +1,245 @@
+From 9be0e8ccde0e096cc494aad6f15e7d7d3de3e46f Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Fri, 9 Nov 2018 10:24:37 +0800
+Subject: [PATCH] Implement a memory driver share memory
+
+Implement a memory driver for BMC to access VGA share memory.
+The driver is used by MDRV2. In MDRV2 BIOS will send whole
+SMBIOS table to VGA memory and BMC can get the table from VGA
+memory through this driver.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ .../bindings/soc/aspeed/aspeed-vga-sharedmem.txt | 20 +++
+ drivers/soc/aspeed/Kconfig | 9 ++
+ drivers/soc/aspeed/Makefile | 1 +
+ drivers/soc/aspeed/aspeed-vga-sharedmem.c | 163 +++++++++++++++++++++
+ 4 files changed, 193 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt
+ create mode 100644 drivers/soc/aspeed/aspeed-vga-sharedmem.c
+
+diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt
+new file mode 100644
+index 000000000000..03f57c53e844
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt
+@@ -0,0 +1,20 @@
++* Aspeed VGA shared memory driver
++
++Aspeed VGA shared memory driver allow user to read data from AST2500
++VGA memory. This driver is required by ManagedDataRegionlV2
++specification. In the spec, BIOS will transfer whole SMBIOS table to
++VGA memroy and BMC get the table from VGA memory. 0penBMC project do
++not allow to use /dev/mem for security concerns. To get the data in
++VGA shared memory in user space, implement this driver only allowed
++user to mmap limited memory area.
++
++Required properties:
++- compatible: "aspeed,ast2500-vga-sharedmem"
++ - aspeed,ast2500-vga-sharedmem: Aspeed AST2500 family
++- reg: Should contain VGA shared memory start address and length
++
++Example:
++vga-shared-memory {
++ compatible = "aspeed,ast2500-vga-sharedmem";
++ reg = <0x9ff00000 0x100000>;
++};
+diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
+index cb85917b8c6f..13cd9fbabbf1 100644
+--- a/drivers/soc/aspeed/Kconfig
++++ b/drivers/soc/aspeed/Kconfig
+@@ -59,4 +59,13 @@ config ASPEED_XDMA
+ SOCs. The XDMA engine can perform automatic PCI DMA operations
+ between the AST2XXX (acting as a BMC) and a host processor.
+
++config ASPEED_VGA_SHAREDMEM
++ tristate "Aspeed VGA Shared memory"
++ depends on SOC_ASPEED
++ help
++ To access VGA shared memory on Aspeed BMC, enable this option.
++ This driver used by ManagedDataRegionlV2 specification. In the
++ specification, BIOS will transfer whole SMBIOS table to VGA memory,
++ and BMC can get the table from VGA memory through this driver.
++
+ endmenu
+diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
+index 56c5de5eeabe..875f0d9e7866 100644
+--- a/drivers/soc/aspeed/Makefile
++++ b/drivers/soc/aspeed/Makefile
+@@ -6,3 +6,4 @@ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
+ obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o
++obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o
+diff --git a/drivers/soc/aspeed/aspeed-vga-sharedmem.c b/drivers/soc/aspeed/aspeed-vga-sharedmem.c
+new file mode 100644
+index 000000000000..cd1f5431378c
+--- /dev/null
++++ b/drivers/soc/aspeed/aspeed-vga-sharedmem.c
+@@ -0,0 +1,163 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2018 Intel Corporation
++ * VGA Shared Memory driver for Aspeed AST2500
++ */
++
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++
++#define SHAREDMEM_NAME "vgasharedmem"
++
++struct aspeed_vga_sharedmem {
++ struct miscdevice miscdev;
++ unsigned int addr;
++ unsigned int size;
++ bool mmap_enable;
++};
++
++static struct aspeed_vga_sharedmem *file_sharemem(struct file *file)
++{
++ return container_of(file->private_data,
++ struct aspeed_vga_sharedmem, miscdev);
++}
++
++static int vga_open(struct inode *inode, struct file *file)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file);
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ if (!vga_sharedmem->mmap_enable)
++ return -EPERM;
++
++ return 0;
++}
++
++static int vga_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file);
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ vma->vm_flags = (vma->vm_flags & (~VM_WRITE));
++ remap_pfn_range(vma, vma->vm_start, vga_sharedmem->addr >> PAGE_SHIFT,
++ vga_sharedmem->size, vma->vm_page_prot);
++ return 0;
++}
++
++static ssize_t enable_mmap_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%u\n", vga_sharedmem->mmap_enable);
++}
++
++static ssize_t enable_mmap_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem =
++ dev_get_drvdata(dev);
++ bool val;
++
++ if (kstrtobool(buf, &val))
++ return -EINVAL;
++
++ vga_sharedmem->mmap_enable = val;
++
++ return count;
++}
++static DEVICE_ATTR_RW(enable_mmap);
++
++static struct attribute *sharedmem_attrs[] = {
++ &dev_attr_enable_mmap.attr,
++ NULL
++};
++
++static const struct attribute_group sharedmem_attr_group = {
++ .attrs = sharedmem_attrs,
++};
++
++static const struct attribute_group *sharedmem_attr_groups[] = {
++ &sharedmem_attr_group,
++ NULL
++};
++
++static const struct file_operations vga_sharedmem_fops = {
++ .owner = THIS_MODULE,
++ .open = vga_open,
++ .mmap = vga_mmap,
++};
++
++static struct miscdevice vga_sharedmem_miscdev = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = SHAREDMEM_NAME,
++ .fops = &vga_sharedmem_fops,
++ .groups = sharedmem_attr_groups,
++};
++
++static int vga_sharedmem_probe(struct platform_device *pdev)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem;
++ struct device *dev = &pdev->dev;
++ struct resource *rc;
++
++ vga_sharedmem = devm_kzalloc(dev, sizeof(*vga_sharedmem), GFP_KERNEL);
++ if (!vga_sharedmem)
++ return -ENOMEM;
++
++ dev_set_drvdata(&pdev->dev, vga_sharedmem);
++
++ rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!rc) {
++ dev_err(dev, "Couldn't read size device-tree property\n");
++ return -ENXIO;
++ }
++
++ vga_sharedmem->addr = rc->start;
++ vga_sharedmem->size = resource_size(rc);
++ vga_sharedmem->mmap_enable = true;
++
++ vga_sharedmem->miscdev = vga_sharedmem_miscdev;
++
++ return misc_register(&vga_sharedmem->miscdev);
++}
++
++static int vga_sharedmem_remove(struct platform_device *pdev)
++{
++ struct aspeed_vga_sharedmem *vga_sharedmem =
++ dev_get_drvdata(&pdev->dev);
++
++ misc_deregister(&vga_sharedmem->miscdev);
++
++ return 0;
++}
++
++static const struct of_device_id vga_sharedmem_match[] = {
++ { .compatible = "aspeed,ast2500-vga-sharedmem", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, vga_sharedmem_match);
++
++static struct platform_driver vga_sharedmem_driver = {
++ .driver = {
++ .name = "VGA-SHAREDMEM",
++ .of_match_table = vga_sharedmem_match,
++ },
++ .probe = vga_sharedmem_probe,
++ .remove = vga_sharedmem_remove,
++};
++
++module_platform_driver(vga_sharedmem_driver);
++
++MODULE_AUTHOR("Yang Cheng <cheng.c.yang@intel.com>");
++MODULE_DESCRIPTION("Shared VGA memory");
++MODULE_LICENSE("GPL v2");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch
new file mode 100644
index 000000000..0fdd40d77
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch
@@ -0,0 +1,514 @@
+From b20b1ce81f4451d9e906b84e7edcc22d4e70e7df Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 11 Feb 2019 17:02:35 -0800
+Subject: [PATCH] Add Aspeed PWM driver which uses FTTMR010 timer IP
+
+This commit adds Aspeed PWM driver which uses timer pulse output
+feature in Aspeed SoCs. The timer IP is derived from Faraday
+Technologies FTTMR010 IP but has some customized register
+structure changes only for Aspeed SoCs.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g5.dtsi | 2 +-
+ drivers/pwm/Kconfig | 9 +
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm-fttmr010.c | 441 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 452 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pwm/pwm-fttmr010.c
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 27ed188296a1..45202bc3d60c 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -341,7 +341,7 @@
+
+ timer: timer@1e782000 {
+ /* This timer is a Faraday FTTMR010 derivative */
+- compatible = "aspeed,ast2400-timer";
++ compatible = "aspeed,ast2500-timer";
+ reg = <0x1e782000 0x90>;
+ interrupts = <16 17 18 35 36 37 38 39>;
+ clocks = <&syscon ASPEED_CLK_APB>;
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index e3a2518503ed..21def8cd5af6 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -171,6 +171,15 @@ config PWM_FSL_FTM
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-fsl-ftm.
+
++config PWM_FTTMR010
++ tristate "Faraday Technology FTTMR010 timer PWM support"
++ help
++ Generic PWM framework driver for Faraday Technology FTTMR010 Timer
++ PWM output
++
++ To compile this driver as a module, choose M here: the module
++ will be called pwm-fttmr010
++
+ config PWM_HIBVT
+ tristate "HiSilicon BVT PWM support"
+ depends on ARCH_HISI || COMPILE_TEST
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index 26326adf71d7..3a9e9840b5ae 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_CRC) += pwm-crc.o
+ obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
+ obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
+ obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
++obj-$(CONFIG_PWM_FTTMR010) += pwm-fttmr010.o
+ obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o
+ obj-$(CONFIG_PWM_IMG) += pwm-img.o
+ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o
+diff --git a/drivers/pwm/pwm-fttmr010.c b/drivers/pwm/pwm-fttmr010.c
+new file mode 100644
+index 000000000000..283ded6906f1
+--- /dev/null
++++ b/drivers/pwm/pwm-fttmr010.c
+@@ -0,0 +1,441 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2019 Intel Corporation
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/pwm.h>
++
++#define TIMER_CR 0x30
++
++#define TIMER5_ASPEED_COUNT 0x50
++#define TIMER5_ASPEED_LOAD 0x54
++#define TIMER5_ASPEED_MATCH1 0x58
++#define TIMER5_ASPEED_MATCH2 0x5c
++#define TIMER6_ASPEED_COUNT 0x60
++#define TIMER6_ASPEED_LOAD 0x64
++#define TIMER6_ASPEED_MATCH1 0x68
++#define TIMER6_ASPEED_MATCH2 0x6c
++#define TIMER7_ASPEED_COUNT 0x70
++#define TIMER7_ASPEED_LOAD 0x74
++#define TIMER7_ASPEED_MATCH1 0x78
++#define TIMER7_ASPEED_MATCH2 0x7c
++#define TIMER8_ASPEED_COUNT 0x80
++#define TIMER8_ASPEED_LOAD 0x84
++#define TIMER8_ASPEED_MATCH1 0x88
++#define TIMER8_ASPEED_MATCH2 0x8c
++
++#define TIMER_5_CR_ASPEED_ENABLE BIT(16)
++#define TIMER_5_CR_ASPEED_CLOCK BIT(17)
++#define TIMER_5_CR_ASPEED_INT BIT(18)
++#define TIMER_5_CR_ASPEED_PULSE_OUT BIT(19)
++#define TIMER_6_CR_ASPEED_ENABLE BIT(20)
++#define TIMER_6_CR_ASPEED_CLOCK BIT(21)
++#define TIMER_6_CR_ASPEED_INT BIT(22)
++#define TIMER_6_CR_ASPEED_PULSE_OUT BIT(23)
++#define TIMER_7_CR_ASPEED_ENABLE BIT(24)
++#define TIMER_7_CR_ASPEED_CLOCK BIT(25)
++#define TIMER_7_CR_ASPEED_INT BIT(26)
++#define TIMER_7_CR_ASPEED_PULSE_OUT BIT(27)
++#define TIMER_8_CR_ASPEED_ENABLE BIT(28)
++#define TIMER_8_CR_ASPEED_CLOCK BIT(29)
++#define TIMER_8_CR_ASPEED_INT BIT(30)
++#define TIMER_8_CR_ASPEED_PULSE_OUT BIT(31)
++
++/**
++ * struct pwm_fttmr010_variant - variant data depends on SoC
++ * @bits: timer counter resolution
++ * @chan_min: lowest timer channel which has pwm pulse output
++ * @chan_max: highest timer channel which has pwm pulse output
++ * @output_mask: pwm pulse output mask which is defined in device tree
++ */
++struct pwm_fttmr010_variant {
++ u8 bits;
++ u8 chan_min;
++ u8 chan_max;
++ u8 output_mask;
++};
++
++/**
++ * struct pwm_fttmr010_chan - private data of FTTMR010 PWM channel
++ * @period_ns: current period in nanoseconds programmed to the hardware
++ * @duty_ns: current duty time in nanoseconds programmed to the hardware
++ */
++struct pwm_fttmr010_chan {
++ u32 period_ns;
++ u32 duty_ns;
++};
++
++/**
++ * struct pwm_fttmr010 - private data of FTTMR010 PWM
++ * @chip: generic PWM chip
++ * @variant: local copy of hardware variant data
++ * @disabled_mask: disabled status for all channels - one bit per channel
++ * @base: base address of mapped PWM registers
++ * @clk: clock used to drive the timers
++ */
++struct pwm_fttmr010 {
++ struct pwm_chip chip;
++ struct pwm_fttmr010_variant variant;
++ u8 disabled_mask;
++ void __iomem *base;
++ struct clk *clk;
++ u32 clk_tick_ns;
++};
++
++static inline
++struct pwm_fttmr010 *to_pwm_fttmr010(struct pwm_chip *chip)
++{
++ return container_of(chip, struct pwm_fttmr010, chip);
++}
++
++static int pwm_fttmr010_request(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip);
++ struct pwm_fttmr010_chan *chan;
++
++ if (!(priv->variant.output_mask & BIT(pwm->hwpwm))) {
++ dev_warn(chip->dev,
++ "tried to request PWM channel %d without output\n",
++ pwm->hwpwm);
++ return -EINVAL;
++ }
++
++ chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL);
++ if (!chan)
++ return -ENOMEM;
++
++ pwm_set_chip_data(pwm, chan);
++
++ return 0;
++}
++
++static void pwm_fttmr010_free(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ devm_kfree(chip->dev, pwm_get_chip_data(pwm));
++ pwm_set_chip_data(pwm, NULL);
++}
++
++static int pwm_fttmr010_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip);
++ u32 cr;
++
++ cr = readl(priv->base + TIMER_CR);
++
++ switch (pwm->hwpwm) {
++ case 5:
++ cr |= (TIMER_5_CR_ASPEED_ENABLE | TIMER_5_CR_ASPEED_PULSE_OUT);
++ break;
++ case 6:
++ cr |= (TIMER_6_CR_ASPEED_ENABLE | TIMER_6_CR_ASPEED_PULSE_OUT);
++ break;
++ case 7:
++ cr |= (TIMER_7_CR_ASPEED_ENABLE | TIMER_7_CR_ASPEED_PULSE_OUT);
++ break;
++ case 8:
++ cr |= (TIMER_8_CR_ASPEED_ENABLE | TIMER_8_CR_ASPEED_PULSE_OUT);
++ break;
++ default:
++ return -ERANGE;
++ }
++
++ writel(cr, priv->base + TIMER_CR);
++ priv->disabled_mask &= ~BIT(pwm->hwpwm);
++
++ return 0;
++}
++
++static void pwm_fttmr010_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip);
++ u32 cr;
++
++ cr = readl(priv->base + TIMER_CR);
++
++ switch (pwm->hwpwm) {
++ case 5:
++ cr &= ~(TIMER_5_CR_ASPEED_ENABLE | TIMER_5_CR_ASPEED_PULSE_OUT);
++ break;
++ case 6:
++ cr &= ~(TIMER_6_CR_ASPEED_ENABLE | TIMER_6_CR_ASPEED_PULSE_OUT);
++ break;
++ case 7:
++ cr &= ~(TIMER_7_CR_ASPEED_ENABLE | TIMER_7_CR_ASPEED_PULSE_OUT);
++ break;
++ case 8:
++ cr &= ~(TIMER_8_CR_ASPEED_ENABLE | TIMER_8_CR_ASPEED_PULSE_OUT);
++ break;
++ default:
++ return;
++ }
++
++ writel(cr, priv->base + TIMER_CR);
++ priv->disabled_mask |= BIT(pwm->hwpwm);
++}
++
++static int pwm_fttmr010_config(struct pwm_chip *chip, struct pwm_device *pwm,
++ int duty_ns, int period_ns)
++{
++ u32 tload, tmatch, creg_offset, lreg_offset, mreg_offset;
++ struct pwm_fttmr010_chan *chan = pwm_get_chip_data(pwm);
++ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip);
++
++ /*
++ * We currently avoid using 64bit arithmetic by using the
++ * fact that anything faster than 1Hz is easily representable
++ * by 32bits.
++ */
++ if (period_ns > NSEC_PER_SEC)
++ return -ERANGE;
++
++ /* No need to update */
++ if (chan->period_ns == period_ns || chan->duty_ns == duty_ns)
++ return 0;
++
++ tload = period_ns / priv->clk_tick_ns;
++
++ /* Period is too short */
++ if (tload <= 1)
++ return -ERANGE;
++
++ tmatch = duty_ns / priv->clk_tick_ns;
++
++ /* 0% duty is not available */
++ if (!tmatch)
++ ++tmatch;
++
++ tmatch = tload - tmatch;
++
++ /* Decrement to get tick numbers, instead of tick counts */
++ --tload;
++ --tmatch;
++
++ if (tload == 0 || tmatch == 0)
++ return -ERANGE;
++
++ dev_dbg(priv->chip.dev, "clk_tick_ns:%u, tload:%u, tmatch:%u\n",
++ priv->clk_tick_ns, tload, tmatch);
++
++ switch (pwm->hwpwm) {
++ case 5:
++ creg_offset = TIMER5_ASPEED_COUNT;
++ lreg_offset = TIMER5_ASPEED_LOAD;
++ mreg_offset = TIMER5_ASPEED_MATCH1;
++ break;
++ case 6:
++ creg_offset = TIMER6_ASPEED_COUNT;
++ lreg_offset = TIMER6_ASPEED_LOAD;
++ mreg_offset = TIMER6_ASPEED_MATCH1;
++ break;
++ case 7:
++ creg_offset = TIMER7_ASPEED_COUNT;
++ lreg_offset = TIMER7_ASPEED_LOAD;
++ mreg_offset = TIMER7_ASPEED_MATCH1;
++ break;
++ case 8:
++ creg_offset = TIMER8_ASPEED_COUNT;
++ lreg_offset = TIMER8_ASPEED_LOAD;
++ mreg_offset = TIMER8_ASPEED_MATCH1;
++ break;
++ default:
++ return -ERANGE;
++ }
++
++ writel(tload, priv->base + creg_offset);
++ writel(tload, priv->base + lreg_offset);
++ writel(tmatch, priv->base + mreg_offset);
++
++ chan->period_ns = period_ns;
++ chan->duty_ns = duty_ns;
++
++ return 0;
++}
++
++static const struct pwm_ops pwm_fttmr010_ops = {
++ .request = pwm_fttmr010_request,
++ .free = pwm_fttmr010_free,
++ .enable = pwm_fttmr010_enable,
++ .disable = pwm_fttmr010_disable,
++ .config = pwm_fttmr010_config,
++ .owner = THIS_MODULE,
++};
++
++#ifdef CONFIG_OF
++static const struct pwm_fttmr010_variant aspeed_variant = {
++ .bits = 32,
++ .chan_min = 5,
++ .chan_max = 8,
++};
++
++static const struct of_device_id pwm_fttmr010_matches[] = {
++ { .compatible = "aspeed,ast2400-timer", .data = &aspeed_variant },
++ { .compatible = "aspeed,ast2500-timer", .data = &aspeed_variant },
++ { },
++};
++MODULE_DEVICE_TABLE(of, pwm_fttmr010_matches);
++
++static int pwm_fttmr010_parse_dt(struct pwm_fttmr010 *priv)
++{
++ struct device_node *np = priv->chip.dev->of_node;
++ const struct of_device_id *match;
++ struct property *prop;
++ const __be32 *cur;
++ u32 val;
++
++ match = of_match_node(pwm_fttmr010_matches, np);
++ if (!match)
++ return -ENODEV;
++
++ memcpy(&priv->variant, match->data, sizeof(priv->variant));
++
++ of_property_for_each_u32(np, "fttmr010,pwm-outputs", prop, cur, val) {
++ if (val < priv->variant.chan_min ||
++ val > priv->variant.chan_max) {
++ dev_err(priv->chip.dev,
++ "invalid channel index in fttmr010,pwm-outputs property\n");
++ continue;
++ }
++ priv->variant.output_mask |= BIT(val);
++ }
++
++ return 0;
++}
++#else
++static int pwm_fttmr010_parse_dt(struct pwm_fttmr010 *priv)
++{
++ return -ENODEV;
++}
++#endif
++
++static int pwm_fttmr010_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct pwm_fttmr010 *priv;
++ struct resource *res;
++ ulong clk_rate;
++ int ret;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->chip.dev = &pdev->dev;
++ priv->chip.ops = &pwm_fttmr010_ops;
++ priv->chip.base = -1;
++
++ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
++ ret = pwm_fttmr010_parse_dt(priv);
++ if (ret)
++ return ret;
++
++ priv->chip.of_xlate = of_pwm_xlate_with_flags;
++ priv->chip.of_pwm_n_cells = 3;
++ } else {
++ if (!pdev->dev.platform_data) {
++ dev_err(&pdev->dev, "no platform data specified\n");
++ return -EINVAL;
++ }
++
++ memcpy(&priv->variant, pdev->dev.platform_data,
++ sizeof(priv->variant));
++ }
++
++ priv->chip.npwm = priv->variant.chan_max + 1;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ priv->clk = devm_clk_get(&pdev->dev, "PCLK");
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev, "failed to get timer base clk\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ ret = clk_prepare_enable(priv->clk);
++ if (ret < 0) {
++ dev_err(dev, "failed to enable base clock\n");
++ return ret;
++ }
++
++ clk_rate = clk_get_rate(priv->clk);
++ priv->clk_tick_ns = NSEC_PER_SEC / clk_rate;
++
++ platform_set_drvdata(pdev, priv);
++
++ ret = pwmchip_add(&priv->chip);
++ if (ret < 0) {
++ dev_err(dev, "failed to register PWM chip\n");
++ clk_disable_unprepare(priv->clk);
++ return ret;
++ }
++
++ dev_dbg(dev, "clk at %lu\n", clk_rate);
++
++ return 0;
++}
++
++static int pwm_fttmr010_remove(struct platform_device *pdev)
++{
++ struct pwm_fttmr010 *priv = platform_get_drvdata(pdev);
++ int ret;
++
++ ret = pwmchip_remove(&priv->chip);
++ if (ret < 0)
++ return ret;
++
++ clk_disable_unprepare(priv->clk);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int pwm_fttmr010_resume(struct device *dev)
++{
++ struct pwm_fttmr010 *priv = dev_get_drvdata(dev);
++ struct pwm_chip *chip = &priv->chip;
++ unsigned int i;
++
++ for (i = priv->variant.chan_min; i < priv->variant.chan_max; i++) {
++ struct pwm_device *pwm = &chip->pwms[i];
++ struct pwm_fttmr010_chan *chan = pwm_get_chip_data(pwm);
++
++ if (!chan)
++ continue;
++
++ if (chan->period_ns) {
++ pwm_fttmr010_config(chip, pwm, chan->duty_ns,
++ chan->period_ns);
++ }
++
++ if (priv->disabled_mask & BIT(i))
++ pwm_fttmr010_disable(chip, pwm);
++ else
++ pwm_fttmr010_enable(chip, pwm);
++ }
++
++ return 0;
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(pwm_fttmr010_pm_ops, NULL, pwm_fttmr010_resume);
++
++static struct platform_driver pwm_fttmr010_driver = {
++ .driver = {
++ .name = "fttmr010-timer-pwm",
++ .pm = &pwm_fttmr010_pm_ops,
++ .of_match_table = of_match_ptr(pwm_fttmr010_matches),
++ },
++ .probe = pwm_fttmr010_probe,
++ .remove = pwm_fttmr010_remove,
++};
++module_platform_driver(pwm_fttmr010_driver);
++
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("FTTMR010 PWM Driver for timer pulse outputs");
++MODULE_LICENSE("GPL v2");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch
new file mode 100644
index 000000000..198beaa93
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch
@@ -0,0 +1,488 @@
+From ee9cee93b96b791f52295d7763985fdb10903e2b Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 15 Feb 2019 16:05:09 -0800
+Subject: [PATCH] i2c: Add mux hold/unhold msg types
+
+This commit adds mux hold/unhold message types to support extended
+mux control for IPMB and MCTP devices. A hold or an unhold message
+can be added at the end of I2C message stream wrapped by
+repeated-start, also can be used as a single message independantly.
+
+This mux hold/unhold message will be delivered throughout all mux
+levels in the path. Means that if it goes to multi-level mux path,
+all muxes will be held/unheld by this message.
+
+1. Hold message
+ struct i2c_msg msg;
+ uint16_t timeout = 5000; // timeout in ms. 5 secs in this example.
+
+ msg.addr = 0x0; // any value can be used. addr will be ignored in this packet.
+ msg.flags = I2C_M_HOLD; // set this flag to indicate it's a hold message.
+ msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer.
+ msg.buf = (uint8_t *)&timeout; // set timeout value.
+
+2. Unhold message
+ struct i2c_msg msg;
+ uint16_t timeout = 0; // set 0 for an unhold message.
+
+ msg.addr = 0x0; // any value can be used. addr will be ignored in this packet.
+ msg.flags = I2C_M_HOLD; // set this flag to indicate it's an unhold message.
+ msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer.
+ msg.buf = (uint8_t *)&timeout; // set timeout value.
+
+ This unhold message can be delivered to a mux adapter even when
+ a bus is locked so that any holding state can be unheld
+ immediately by invoking this unhold message.
+
+This patch would not be welcomed from upstream so it should be kept
+in downstream only.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/i2c-core-base.c | 70 +++++++++++++++++++++++++--
+ drivers/i2c/i2c-core-smbus.c | 22 +++++++--
+ drivers/i2c/i2c-mux.c | 109 +++++++++++++++++++++++++++++++++++++++----
+ include/linux/i2c-mux.h | 3 ++
+ include/linux/i2c.h | 25 ++++++++++
+ include/uapi/linux/i2c.h | 1 +
+ 6 files changed, 214 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
+index 5f6a4985f2bc..d1cd7afe4068 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1297,6 +1297,25 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
+ }
+ EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
+
++static void i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout)
++{
++ mutex_lock(&adapter->hold_lock);
++ mod_timer(&adapter->hold_timer, jiffies + timeout);
++}
++
++static void i2c_adapter_unhold(struct i2c_adapter *adapter)
++{
++ del_timer_sync(&adapter->hold_timer);
++ mutex_unlock(&adapter->hold_lock);
++}
++
++static void i2c_adapter_hold_timer_callback(struct timer_list *t)
++{
++ struct i2c_adapter *adapter = from_timer(adapter, t, hold_timer);
++
++ i2c_adapter_unhold(adapter);
++}
++
+ static int i2c_register_adapter(struct i2c_adapter *adap)
+ {
+ int res = -EINVAL;
+@@ -1379,6 +1398,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+ bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
+ mutex_unlock(&core_lock);
+
++ mutex_init(&adap->hold_lock);
++ timer_setup(&adap->hold_timer, i2c_adapter_hold_timer_callback, 0);
++
+ return 0;
+
+ out_reg:
+@@ -1599,6 +1621,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
+ idr_remove(&i2c_adapter_idr, adap->nr);
+ mutex_unlock(&core_lock);
+
++ i2c_adapter_unhold(adap);
++
+ /* Clear the device structure in case this adapter is ever going to be
+ added again */
+ memset(&adap->dev, 0, sizeof(adap->dev));
+@@ -1948,7 +1972,9 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ */
+ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ {
++ enum i2c_hold_msg_type hold_msg = I2C_HOLD_MSG_NONE;
+ unsigned long orig_jiffies;
++ unsigned long timeout;
+ int ret, try;
+
+ if (WARN_ON(!msgs || num < 1))
+@@ -1961,6 +1987,25 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
+ return -EOPNOTSUPP;
+
++ /* Do not deliver a mux hold msg to root bus adapter */
++ if (!i2c_parent_is_i2c_adapter(adap)) {
++ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags,
++ msgs[num - 1].len,
++ (u16 *)msgs[num - 1].buf);
++ if (hold_msg == I2C_HOLD_MSG_SET) {
++ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
++ i2c_adapter_hold(adap, timeout);
++
++ if (--num == 0)
++ return 0;
++ } else if (hold_msg == I2C_HOLD_MSG_RESET) {
++ i2c_adapter_unhold(adap);
++ return 0;
++ } else if (hold_msg == I2C_HOLD_MSG_NONE) {
++ mutex_lock(&adap->hold_lock);
++ }
++ }
++
+ /*
+ * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets
+ * enabled. This is an efficient way of keeping the for-loop from
+@@ -1997,6 +2042,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ trace_i2c_result(adap, num, ret);
+ }
+
++ if (!i2c_parent_is_i2c_adapter(adap) && hold_msg == I2C_HOLD_MSG_NONE)
++ mutex_unlock(&adap->hold_lock);
++
+ return ret;
+ }
+ EXPORT_SYMBOL(__i2c_transfer);
+@@ -2015,6 +2063,7 @@ EXPORT_SYMBOL(__i2c_transfer);
+ */
+ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ {
++ bool do_bus_lock = true;
+ int ret;
+
+ if (!adap->algo->master_xfer) {
+@@ -2038,12 +2087,25 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ * one (discarding status on the second message) or errno
+ * (discarding status on the first one).
+ */
+- ret = __i2c_lock_bus_helper(adap);
+- if (ret)
+- return ret;
++ /*
++ * Do not lock a bus for delivering an unhold msg to a mux
++ * adpater. This is just for a single length unhold msg case.
++ */
++ if (num == 1 && i2c_parent_is_i2c_adapter(adap) &&
++ i2c_check_hold_msg(msgs[0].flags, msgs[0].len,
++ (u16 *)msgs[0].buf) ==
++ I2C_HOLD_MSG_RESET)
++ do_bus_lock = false;
++
++ if (do_bus_lock) {
++ ret = __i2c_lock_bus_helper(adap);
++ if (ret)
++ return ret;
++ }
+
+ ret = __i2c_transfer(adap, msgs, num);
+- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
++ if (do_bus_lock)
++ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
+
+ return ret;
+ }
+diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
+index 3ac426a8ab5a..f7bf95101e34 100644
+--- a/drivers/i2c/i2c-core-smbus.c
++++ b/drivers/i2c/i2c-core-smbus.c
+@@ -526,15 +526,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int protocol, union i2c_smbus_data *data)
+ {
++ bool do_bus_lock = true;
+ s32 res;
+
+- res = __i2c_lock_bus_helper(adapter);
+- if (res)
+- return res;
++ /*
++ * Do not lock a bus for delivering an unhold msg to a mux adpater.
++ * This is just for a single length unhold msg case.
++ */
++ if (i2c_parent_is_i2c_adapter(adapter) &&
++ i2c_check_hold_msg(flags,
++ protocol == I2C_SMBUS_WORD_DATA ? 2 : 0,
++ &data->word) == I2C_HOLD_MSG_RESET)
++ do_bus_lock = false;
++
++ if (do_bus_lock) {
++ res = __i2c_lock_bus_helper(adapter);
++ if (res)
++ return res;
++ }
+
+ res = __i2c_smbus_xfer(adapter, addr, flags, read_write,
+ command, protocol, data);
+- i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
++ if (do_bus_lock)
++ i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
+
+ return res;
+ }
+diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
+index 774507b54b57..c6e433238b22 100644
+--- a/drivers/i2c/i2c-mux.c
++++ b/drivers/i2c/i2c-mux.c
+@@ -27,6 +27,7 @@
+ #include <linux/of.h>
+ #include <linux/slab.h>
+ #include <linux/sysfs.h>
++#include <linux/timer.h>
+
+ /* multiplexer per channel data */
+ struct i2c_mux_priv {
+@@ -36,21 +37,57 @@ struct i2c_mux_priv {
+ u32 chan_id;
+ };
+
++static void i2c_mux_hold(struct i2c_mux_core *muxc, unsigned long timeout)
++{
++ mutex_lock(&muxc->hold_lock);
++ mod_timer(&muxc->hold_timer, jiffies + timeout);
++}
++
++static void i2c_mux_unhold(struct i2c_mux_core *muxc)
++{
++ del_timer_sync(&muxc->hold_timer);
++ mutex_unlock(&muxc->hold_lock);
++}
++
++static void i2c_mux_hold_timer_callback(struct timer_list *t)
++{
++ struct i2c_mux_core *muxc = from_timer(muxc, t, hold_timer);
++
++ i2c_mux_unhold(muxc);
++}
++
+ static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msgs[], int num)
+ {
+ struct i2c_mux_priv *priv = adap->algo_data;
+ struct i2c_mux_core *muxc = priv->muxc;
+ struct i2c_adapter *parent = muxc->parent;
++ enum i2c_hold_msg_type hold_msg;
++ unsigned long timeout;
+ int ret;
+
+ /* Switch to the right mux port and perform the transfer. */
+
++ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags,
++ msgs[num - 1].len,
++ (u16 *)msgs[num - 1].buf);
++ if (hold_msg == I2C_HOLD_MSG_SET) {
++ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
++ i2c_mux_hold(muxc, timeout);
++ } else if (hold_msg == I2C_HOLD_MSG_NONE) {
++ mutex_lock(&muxc->hold_lock);
++ }
+ ret = muxc->select(muxc, priv->chan_id);
+ if (ret >= 0)
+ ret = __i2c_transfer(parent, msgs, num);
+- if (muxc->deselect)
+- muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg != I2C_HOLD_MSG_SET) {
++ if (muxc->deselect)
++ muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg == I2C_HOLD_MSG_RESET)
++ i2c_mux_unhold(muxc);
++ else
++ mutex_unlock(&muxc->hold_lock);
++ }
+
+ return ret;
+ }
+@@ -61,15 +98,32 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
+ struct i2c_mux_priv *priv = adap->algo_data;
+ struct i2c_mux_core *muxc = priv->muxc;
+ struct i2c_adapter *parent = muxc->parent;
++ enum i2c_hold_msg_type hold_msg;
++ unsigned long timeout;
+ int ret;
+
+ /* Switch to the right mux port and perform the transfer. */
+
++ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags,
++ msgs[num - 1].len,
++ (u16 *)msgs[num - 1].buf);
++ if (hold_msg == I2C_HOLD_MSG_SET) {
++ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf);
++ i2c_mux_hold(muxc, timeout);
++ } else if (hold_msg == I2C_HOLD_MSG_NONE) {
++ mutex_lock(&muxc->hold_lock);
++ }
+ ret = muxc->select(muxc, priv->chan_id);
+ if (ret >= 0)
+ ret = i2c_transfer(parent, msgs, num);
+- if (muxc->deselect)
+- muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg != I2C_HOLD_MSG_SET) {
++ if (muxc->deselect)
++ muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg == I2C_HOLD_MSG_RESET)
++ i2c_mux_unhold(muxc);
++ else
++ mutex_unlock(&muxc->hold_lock);
++ }
+
+ return ret;
+ }
+@@ -82,16 +136,33 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
+ struct i2c_mux_priv *priv = adap->algo_data;
+ struct i2c_mux_core *muxc = priv->muxc;
+ struct i2c_adapter *parent = muxc->parent;
++ enum i2c_hold_msg_type hold_msg;
++ unsigned long timeout;
+ int ret;
+
+ /* Select the right mux port and perform the transfer. */
+
++ hold_msg = i2c_check_hold_msg(flags,
++ size == I2C_SMBUS_WORD_DATA ? 2 : 0,
++ &data->word);
++ if (hold_msg == I2C_HOLD_MSG_SET) {
++ timeout = msecs_to_jiffies(data->word);
++ i2c_mux_hold(muxc, timeout);
++ } else if (hold_msg == I2C_HOLD_MSG_NONE) {
++ mutex_lock(&muxc->hold_lock);
++ }
+ ret = muxc->select(muxc, priv->chan_id);
+ if (ret >= 0)
+ ret = __i2c_smbus_xfer(parent, addr, flags,
+ read_write, command, size, data);
+- if (muxc->deselect)
+- muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg != I2C_HOLD_MSG_SET) {
++ if (muxc->deselect)
++ muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg == I2C_HOLD_MSG_RESET)
++ i2c_mux_unhold(muxc);
++ else
++ mutex_unlock(&muxc->hold_lock);
++ }
+
+ return ret;
+ }
+@@ -104,16 +175,33 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
+ struct i2c_mux_priv *priv = adap->algo_data;
+ struct i2c_mux_core *muxc = priv->muxc;
+ struct i2c_adapter *parent = muxc->parent;
++ enum i2c_hold_msg_type hold_msg;
++ unsigned long timeout;
+ int ret;
+
+ /* Select the right mux port and perform the transfer. */
+
++ hold_msg = i2c_check_hold_msg(flags,
++ size == I2C_SMBUS_WORD_DATA ? 2 : 0,
++ &data->word);
++ if (hold_msg == I2C_HOLD_MSG_SET) {
++ timeout = msecs_to_jiffies(data->word);
++ i2c_mux_hold(muxc, timeout);
++ } else if (hold_msg == I2C_HOLD_MSG_NONE) {
++ mutex_lock(&muxc->hold_lock);
++ }
+ ret = muxc->select(muxc, priv->chan_id);
+ if (ret >= 0)
+ ret = i2c_smbus_xfer(parent, addr, flags,
+ read_write, command, size, data);
+- if (muxc->deselect)
+- muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg != I2C_HOLD_MSG_SET) {
++ if (muxc->deselect)
++ muxc->deselect(muxc, priv->chan_id);
++ if (hold_msg == I2C_HOLD_MSG_RESET)
++ i2c_mux_unhold(muxc);
++ else
++ mutex_unlock(&muxc->hold_lock);
++ }
+
+ return ret;
+ }
+@@ -263,6 +351,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
+ muxc->deselect = deselect;
+ muxc->max_adapters = max_adapters;
+
++ mutex_init(&muxc->hold_lock);
++ timer_setup(&muxc->hold_timer, i2c_mux_hold_timer_callback, 0);
++
+ return muxc;
+ }
+ EXPORT_SYMBOL_GPL(i2c_mux_alloc);
+@@ -441,6 +532,8 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
+ {
+ char symlink_name[20];
+
++ i2c_mux_unhold(muxc);
++
+ while (muxc->num_adapters) {
+ struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
+ struct i2c_mux_priv *priv = adap->algo_data;
+diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
+index c5a977320f82..47f8763d6ed2 100644
+--- a/include/linux/i2c-mux.h
++++ b/include/linux/i2c-mux.h
+@@ -27,6 +27,9 @@ struct i2c_mux_core {
+ int (*select)(struct i2c_mux_core *, u32 chan_id);
+ int (*deselect)(struct i2c_mux_core *, u32 chan_id);
+
++ struct mutex hold_lock; /* mutex for channel holding */
++ struct timer_list hold_timer;
++
+ int num_adapters;
+ int max_adapters;
+ struct i2c_adapter *adapter[0];
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 1361637c369d..b4055d133338 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -711,6 +711,13 @@ struct i2c_adapter {
+ const struct i2c_adapter_quirks *quirks;
+
+ struct irq_domain *host_notify_domain;
++
++ /*
++ * These will be used by root adpaters only. For muxes, each mux core
++ * has these individually.
++ */
++ struct mutex hold_lock; /* mutex for bus holding */
++ struct timer_list hold_timer;
+ };
+ #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
+
+@@ -1005,4 +1012,22 @@ static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle ha
+ }
+ #endif /* CONFIG_ACPI */
+
++enum i2c_hold_msg_type {
++ I2C_HOLD_MSG_NONE,
++ I2C_HOLD_MSG_SET,
++ I2C_HOLD_MSG_RESET
++};
++
++static inline enum i2c_hold_msg_type i2c_check_hold_msg(u16 flags, u16 len, u16 *buf)
++{
++ if (flags & I2C_M_HOLD && len == sizeof(u16)) {
++ if (*buf)
++ return I2C_HOLD_MSG_SET;
++
++ return I2C_HOLD_MSG_RESET;
++ }
++
++ return I2C_HOLD_MSG_NONE;
++}
++
+ #endif /* _LINUX_I2C_H */
+diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h
+index f71a1751cacf..a1db9b17ed36 100644
+--- a/include/uapi/linux/i2c.h
++++ b/include/uapi/linux/i2c.h
+@@ -72,6 +72,7 @@ struct i2c_msg {
+ #define I2C_M_RD 0x0001 /* read data, from slave to master */
+ /* I2C_M_RD is guaranteed to be 0x0001! */
+ #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
++#define I2C_M_HOLD 0x0100 /* for holding a mux path */
+ #define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */
+ /* makes only sense in kernelspace */
+ /* userspace buffers are copied anyway */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch
new file mode 100644
index 000000000..5b9d4ef8b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch
@@ -0,0 +1,105 @@
+From 37e7896bf297edef4f2877998ca7a5c086015591 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 7 Mar 2019 15:17:40 -0800
+Subject: [PATCH] Add bus-timeout-ms and #retries device tree properties
+
+BMC uses I2C bus 7 as a PMBus channel to communicate with PSUs,
+also ME uses this bus as SMLink to control PSUs so this bus is
+managed by multi-masters. In this use case, some arbitration errors
+are expected so we need to add retry logic. And PMBus subsystem
+uses I2C bus in kernel internally so retry logic should be
+supported in kernel level.
+
+To support the use case, this commit adds 'bus-timeout-ms' and
+'#retries' device tree properties to set the bus specific
+parameters at kernel boot time without using any additional ioctls
+from user space.
+
+This patch would not be accepted by I2C maintainer in linux
+upstream because he doesn't like adding these legacy properties
+into device tree, so keep it only in downstream.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ Documentation/devicetree/bindings/i2c/i2c-aspeed.txt | 3 +++
+ Documentation/devicetree/bindings/i2c/i2c.txt | 6 ++++++
+ drivers/i2c/busses/i2c-aspeed.c | 1 -
+ drivers/i2c/i2c-core-base.c | 12 ++++++++++--
+ 4 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+index 8fbd8633a387..7da7e813b2b0 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+@@ -16,6 +16,9 @@ Optional Properties:
+ - bus-frequency : frequency of the bus clock in Hz defaults to 100 kHz when not
+ specified
+ - multi-master : states that there is another master active on this bus.
++- bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not
++ specified.
++- #retries : Number of retries for master transfer.
+
+ Example:
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt
+index 44efafdfd7f5..e382931cf3d6 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c.txt
+@@ -80,6 +80,12 @@ wants to support one of the below features, it should adapt the bindings below.
+ Names of map programmable addresses.
+ It can contain any map needing another address than default one.
+
++- bus-timeout-ms
++ Bus timeout in milliseconds.
++
++- #retries
++ Number of retries for master transfer.
++
+ Binding may contain optional "interrupts" property, describing interrupts
+ used by the device. I2C core will assign "irq" interrupt (or the very first
+ interrupt if not using interrupt names) as primary interrupt for the slave.
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index c113ffa8d5df..7becfcd67142 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -1032,7 +1032,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ spin_lock_init(&bus->lock);
+ init_completion(&bus->cmd_complete);
+ bus->adap.owner = THIS_MODULE;
+- bus->adap.retries = 0;
+ bus->adap.algo = &aspeed_i2c_algo;
+ bus->adap.dev.parent = &pdev->dev;
+ bus->adap.dev.of_node = pdev->dev.of_node;
+diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
+index d1cd7afe4068..1db991220fae 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1318,6 +1318,7 @@ static void i2c_adapter_hold_timer_callback(struct timer_list *t)
+
+ static int i2c_register_adapter(struct i2c_adapter *adap)
+ {
++ u32 bus_timeout_ms = 0;
+ int res = -EINVAL;
+
+ /* Can't register until after driver model init */
+@@ -1345,8 +1346,15 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+ INIT_LIST_HEAD(&adap->userspace_clients);
+
+ /* Set default timeout to 1 second if not already set */
+- if (adap->timeout == 0)
+- adap->timeout = HZ;
++ if (adap->timeout == 0) {
++ device_property_read_u32(&adap->dev, "bus-timeout-ms",
++ &bus_timeout_ms);
++ adap->timeout = bus_timeout_ms ?
++ msecs_to_jiffies(bus_timeout_ms) : HZ;
++ }
++
++ /* Set retries count if it has the property setting */
++ device_property_read_u32(&adap->dev, "#retries", &adap->retries);
+
+ /* register soft irqs for Host Notify */
+ res = i2c_setup_host_notify_irq_domain(adap);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch
new file mode 100644
index 000000000..6cc7d1138
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch
@@ -0,0 +1,154 @@
+From 301c1aaba9e59eb593406d878451e3ea4fe355bb Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 13 Mar 2019 15:04:16 -0700
+Subject: [PATCH] char: ipmi: Add clock control logic into Aspeed LPC BT driver
+
+If LPC BT driver is registered ahead of lpc-ctrl module, LPC BT
+block will be enabled without heart beating of LCLK until lpc-ctrl
+enables the LCLK. This issue causes improper handling on host
+interrupts when the host sends interrupt in that time frame. Then
+kernel eventually forcibly disables the interrupt with dumping
+stack and printing a 'nobody cared this irq' message out.
+
+To prevent this issue, all LPC sub-nodes should enable LCLK
+individually so this patch adds clock control logic into the LPC
+BT driver.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ .../bindings/ipmi/aspeed,ast2400-ibt-bmc.txt | 3 +++
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 1 +
+ drivers/char/ipmi/bt-bmc.c | 24 +++++++++++++++++++++-
+ 5 files changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
+index 028268fd99ee..d13887d60f19 100644
+--- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
++++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt
+@@ -10,6 +10,8 @@ Required properties:
+ "aspeed,ast2400-ibt-bmc"
+ "aspeed,ast2500-ibt-bmc"
+ - reg: physical address and size of the registers
++- clocks: contains a phandle to the syscon node describing the clocks.
++ There should then be one cell representing the clock to use.
+
+ Optional properties:
+
+@@ -22,4 +24,5 @@ Example:
+ compatible = "aspeed,ast2400-ibt-bmc";
+ reg = <0x1e789140 0x18>;
+ interrupts = <8>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ };
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 054d97229626..db962ab435af 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -386,6 +386,7 @@
+ ibt: ibt@c0 {
+ compatible = "aspeed,ast2400-ibt-bmc";
+ reg = <0xc0 0x18>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
+ status = "disabled";
+ };
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 45202bc3d60c..c4724ec27041 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -499,6 +499,7 @@
+ ibt: ibt@c0 {
+ compatible = "aspeed,ast2500-ibt-bmc";
+ reg = <0xc0 0x18>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
+ status = "disabled";
+ };
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 8cc978058f16..a557a7e6fe8d 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -524,6 +524,7 @@
+ ibt: ibt@c0 {
+ compatible = "aspeed,ast2600-ibt-bmc";
+ reg = <0xc0 0x18>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
+index 0e600449931b..87bf3ff28542 100644
+--- a/drivers/char/ipmi/bt-bmc.c
++++ b/drivers/char/ipmi/bt-bmc.c
+@@ -5,6 +5,7 @@
+
+ #include <linux/atomic.h>
+ #include <linux/bt-bmc.h>
++#include <linux/clk.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -60,6 +61,7 @@ struct bt_bmc {
+ struct device dev;
+ struct miscdevice miscdev;
+ struct regmap *map;
++ struct clk *clk;
+ int offset;
+ int irq;
+ wait_queue_head_t queue;
+@@ -467,6 +469,19 @@ static int bt_bmc_probe(struct platform_device *pdev)
+ mutex_init(&bt_bmc->mutex);
+ init_waitqueue_head(&bt_bmc->queue);
+
++ bt_bmc->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(bt_bmc->clk)) {
++ rc = PTR_ERR(bt_bmc->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
++ }
++ rc = clk_prepare_enable(bt_bmc->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
+ bt_bmc->miscdev.minor = MISC_DYNAMIC_MINOR,
+ bt_bmc->miscdev.name = DEVICE_NAME,
+ bt_bmc->miscdev.fops = &bt_bmc_fops,
+@@ -474,7 +489,7 @@ static int bt_bmc_probe(struct platform_device *pdev)
+ rc = misc_register(&bt_bmc->miscdev);
+ if (rc) {
+ dev_err(dev, "Unable to register misc device\n");
+- return rc;
++ goto err;
+ }
+
+ bt_bmc_config_irq(bt_bmc, pdev);
+@@ -498,6 +513,11 @@ static int bt_bmc_probe(struct platform_device *pdev)
+ clr_b_busy(bt_bmc);
+
+ return 0;
++
++err:
++ clk_disable_unprepare(bt_bmc->clk);
++
++ return rc;
+ }
+
+ static int bt_bmc_remove(struct platform_device *pdev)
+@@ -507,6 +527,8 @@ static int bt_bmc_remove(struct platform_device *pdev)
+ misc_deregister(&bt_bmc->miscdev);
+ if (!bt_bmc->irq)
+ del_timer_sync(&bt_bmc->poll_timer);
++ clk_disable_unprepare(bt_bmc->clk);
++
+ return 0;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch
new file mode 100644
index 000000000..b3ace73f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch
@@ -0,0 +1,139 @@
+From 404f73827714e324a21250b1a855fdc10fcfaf51 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 13 Mar 2019 15:27:48 -0700
+Subject: [PATCH] misc: Add clock control logic into Aspeed LPC SNOOP driver
+
+If LPC SNOOP driver is registered ahead of lpc-ctrl module, LPC
+SNOOP block will be enabled without heart beating of LCLK until
+lpc-ctrl enables the LCLK. This issue causes improper handling on
+host interrupts when the host sends interrupt in that time frame.
+Then kernel eventually forcibly disables the interrupt with
+dumping stack and printing a 'nobody cared this irq' message out.
+
+To prevent this issue, all LPC sub-nodes should enable LCLK
+individually so this patch adds clock control logic into the LPC
+SNOOP driver.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 1 +
+ drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +++++++++++++++++++++++++++---
+ 4 files changed, 30 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index db962ab435af..24a20384b5e8 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -369,6 +369,7 @@
+ compatible = "aspeed,ast2400-lpc-snoop";
+ reg = <0x0 0x80>;
+ interrupts = <8>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index c4724ec27041..18d2a465c0ed 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -482,6 +482,7 @@
+ compatible = "aspeed,ast2500-lpc-snoop";
+ reg = <0x0 0x80>;
+ interrupts = <8>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index a557a7e6fe8d..4035d7bd647e 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -507,6 +507,7 @@
+ compatible = "aspeed,ast2600-lpc-snoop";
+ reg = <0x0 0x80>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
+index c7b4ac066b40..ed272677fc82 100644
+--- a/drivers/soc/aspeed/aspeed-lpc-snoop.c
++++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c
+@@ -11,6 +11,7 @@
+ */
+
+ #include <linux/bitops.h>
++#include <linux/clk.h>
+ #include <linux/interrupt.h>
+ #include <linux/fs.h>
+ #include <linux/kfifo.h>
+@@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel {
+ struct aspeed_lpc_snoop {
+ struct regmap *regmap;
+ int irq;
++ struct clk *clk;
+ struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS];
+ };
+
+@@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
++ lpc_snoop->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(lpc_snoop->clk)) {
++ rc = PTR_ERR(lpc_snoop->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
++ }
++ rc = clk_prepare_enable(lpc_snoop->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
+ rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev);
+ if (rc)
+- return rc;
++ goto err;
+
+ rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port);
+ if (rc)
+- return rc;
++ goto err;
+
+ /* Configuration of 2nd snoop channel port is optional */
+ if (of_property_read_u32_index(dev->of_node, "snoop-ports",
+ 1, &port) == 0) {
+ rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port);
+- if (rc)
++ if (rc) {
+ aspeed_lpc_disable_snoop(lpc_snoop, 0);
++ goto err;
++ }
+ }
+
++ return 0;
++
++err:
++ clk_disable_unprepare(lpc_snoop->clk);
++
+ return rc;
+ }
+
+@@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev)
+ aspeed_lpc_disable_snoop(lpc_snoop, 0);
+ aspeed_lpc_disable_snoop(lpc_snoop, 1);
+
++ clk_disable_unprepare(lpc_snoop->clk);
++
+ return 0;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch
new file mode 100644
index 000000000..1c0903d71
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch
@@ -0,0 +1,273 @@
+From cd62ca008a771bd6b7aeb06526c37d8435f86648 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 13 Mar 2019 15:36:34 -0700
+Subject: [PATCH] char: ipmi: Add clock control logic into Aspeed LPC KCS
+ driver
+
+If LPC KCS driver is registered ahead of lpc-ctrl module, LPC KCS
+block will be enabled without heart beating of LCLK until lpc-ctrl
+enables the LCLK. This issue causes improper handling on host
+interrupts when the host sends interrupt in that time frame. Then
+kernel eventually forcibly disables the interrupt with dumping
+stack and printing a 'nobody cared this irq' message out.
+
+To prevent this issue, all LPC sub-nodes should enable LCLK
+individually so this patch adds clock control logic into the LPC
+KCS driver.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ .../devicetree/bindings/ipmi/aspeed-kcs-bmc.txt | 3 ++
+ arch/arm/boot/dts/aspeed-g4.dtsi | 35 ++++++++++++++++++++
+ arch/arm/boot/dts/aspeed-g5.dtsi | 6 +++-
+ arch/arm/boot/dts/aspeed-g6.dtsi | 6 ++++
+ drivers/char/ipmi/kcs_bmc_aspeed.c | 37 ++++++++++++++++++----
+ 5 files changed, 79 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt
+index d98a9bf45d6c..3453eb0bf8f2 100644
+--- a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt
++++ b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt
+@@ -9,6 +9,8 @@ Required properties:
+ "aspeed,ast2400-kcs-bmc"
+ "aspeed,ast2500-kcs-bmc"
+ - interrupts : interrupt generated by the controller
++- clocks: contains a phandle to the syscon node describing the clocks.
++ There should then be one cell representing the clock to use.
+ - kcs_chan : The LPC channel number in the controller
+ - kcs_addr : The host CPU IO map address
+
+@@ -19,6 +21,7 @@ Example:
+ compatible = "aspeed,ast2500-kcs-bmc";
+ reg = <0x0 0x80>;
+ interrupts = <8>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ kcs_chan = <3>;
+ kcs_addr = <0xCA2>;
+ status = "okay";
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 24a20384b5e8..fc6f4e009db7 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -347,6 +347,33 @@
+ lpc_bmc: lpc-bmc@0 {
+ compatible = "aspeed,ast2400-lpc-bmc";
+ reg = <0x0 0x80>;
++ reg-io-width = <4>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x0 0x80>;
++
++ kcs1: kcs1@0 {
++ compatible = "aspeed,ast2400-kcs-bmc";
++ interrupts = <8>;
++ kcs_chan = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++ kcs2: kcs2@0 {
++ compatible = "aspeed,ast2400-kcs-bmc";
++ interrupts = <8>;
++ kcs_chan = <2>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++ kcs3: kcs3@0 {
++ compatible = "aspeed,ast2400-kcs-bmc";
++ interrupts = <8>;
++ kcs_chan = <3>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
+ };
+
+ lpc_host: lpc-host@80 {
+@@ -358,6 +385,14 @@
+ #size-cells = <1>;
+ ranges = <0x0 0x80 0x1e0>;
+
++ kcs4: kcs4@0 {
++ compatible = "aspeed,ast2400-kcs-bmc";
++ interrupts = <8>;
++ kcs_chan = <4>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
++ status = "disabled";
++ };
++
+ lpc_ctrl: lpc-ctrl@0 {
+ compatible = "aspeed,ast2400-lpc-ctrl";
+ reg = <0x0 0x80>;
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 18d2a465c0ed..751a8f0316d6 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -134,7 +134,7 @@
+ };
+
+ vic: interrupt-controller@1e6c0080 {
+- compatible = "aspeed,ast2400-vic";
++ compatible = "aspeed,ast2500-vic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ valid-sources = <0xfefff7ff 0x0807ffff>;
+@@ -439,18 +439,21 @@
+ compatible = "aspeed,ast2500-kcs-bmc";
+ interrupts = <8>;
+ kcs_chan = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+ kcs2: kcs2@0 {
+ compatible = "aspeed,ast2500-kcs-bmc";
+ interrupts = <8>;
+ kcs_chan = <2>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+ kcs3: kcs3@0 {
+ compatible = "aspeed,ast2500-kcs-bmc";
+ interrupts = <8>;
+ kcs_chan = <3>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+ };
+@@ -468,6 +471,7 @@
+ compatible = "aspeed,ast2500-kcs-bmc";
+ interrupts = <8>;
+ kcs_chan = <4>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 4035d7bd647e..0e35c4598df5 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -463,18 +463,23 @@
+ kcs1: kcs1@0 {
+ compatible = "aspeed,ast2600-kcs-bmc";
+ interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ kcs_chan = <1>;
+ status = "disabled";
+ };
++
+ kcs2: kcs2@0 {
+ compatible = "aspeed,ast2600-kcs-bmc";
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ kcs_chan = <2>;
+ status = "disabled";
+ };
++
+ kcs3: kcs3@0 {
+ compatible = "aspeed,ast2600-kcs-bmc";
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ kcs_chan = <3>;
+ status = "disabled";
+ };
+@@ -492,6 +497,7 @@
+ kcs4: kcs4@0 {
+ compatible = "aspeed,ast2600-kcs-bmc";
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ kcs_chan = <4>;
+ status = "disabled";
+ };
+diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c
+index a0a8bb89c9b3..94cfb879f520 100644
+--- a/drivers/char/ipmi/kcs_bmc_aspeed.c
++++ b/drivers/char/ipmi/kcs_bmc_aspeed.c
+@@ -1,11 +1,10 @@
+ // SPDX-License-Identifier: GPL-2.0
+-/*
+- * Copyright (c) 2015-2018, Intel Corporation.
+- */
++// Copyright (c) 2015-2019, Intel Corporation.
+
+ #define pr_fmt(fmt) "aspeed-kcs-bmc: " fmt
+
+ #include <linux/atomic.h>
++#include <linux/clk.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -63,6 +62,7 @@
+
+ struct aspeed_kcs_bmc {
+ struct regmap *map;
++ struct clk *clk;
+ };
+
+
+@@ -264,36 +264,59 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
++ priv->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ rc = PTR_ERR(priv->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
++ }
++ rc = clk_prepare_enable(priv->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
+ kcs_bmc->ioreg = ast_kcs_bmc_ioregs[chan - 1];
+ kcs_bmc->io_inputb = aspeed_kcs_inb;
+ kcs_bmc->io_outputb = aspeed_kcs_outb;
+
+ dev_set_drvdata(dev, kcs_bmc);
+
+- aspeed_kcs_set_address(kcs_bmc, addr);
+- aspeed_kcs_enable_channel(kcs_bmc, true);
+ rc = aspeed_kcs_config_irq(kcs_bmc, pdev);
+ if (rc)
+- return rc;
++ goto err;
+
+ rc = misc_register(&kcs_bmc->miscdev);
+ if (rc) {
+ dev_err(dev, "Unable to register device\n");
+- return rc;
++ goto err;
+ }
+
++ aspeed_kcs_set_address(kcs_bmc, addr);
++ aspeed_kcs_enable_channel(kcs_bmc, true);
++
+ pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n",
+ chan, addr,
+ kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str);
+
+ return 0;
++
++err:
++ aspeed_kcs_enable_channel(kcs_bmc, false);
++ clk_disable_unprepare(priv->clk);
++
++ return rc;
+ }
+
+ static int aspeed_kcs_remove(struct platform_device *pdev)
+ {
+ struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev);
++ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc);
+
+ misc_deregister(&kcs_bmc->miscdev);
++ aspeed_kcs_enable_channel(kcs_bmc, false);
++ clk_disable_unprepare(priv->clk);
+
+ return 0;
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch
new file mode 100644
index 000000000..8e9c793ba
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch
@@ -0,0 +1,43 @@
+From 5473931df3348b7284c16fac3e7d336c9d0c4294 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 13 Mar 2019 15:57:08 -0700
+Subject: [PATCH] misc: Block error printing on probe defer case in Aspeed LPC
+ ctrl
+
+This commit adds a checking code when it gets -EPROBE_DEFER while
+getting a clock resource. In this case it doesn't need to print
+out an error message because the probing will be re-visited.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/soc/aspeed/aspeed-lpc-ctrl.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
+index f4ac14c40518..432128b8db87 100644
+--- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c
++++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
+@@ -265,8 +265,10 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
+
+ lpc_ctrl->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(lpc_ctrl->clk)) {
+- dev_err(dev, "couldn't get clock\n");
+- return PTR_ERR(lpc_ctrl->clk);
++ rc = PTR_ERR(lpc_ctrl->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
+ }
+ rc = clk_prepare_enable(lpc_ctrl->clk);
+ if (rc) {
+@@ -288,6 +290,7 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev)
+
+ err:
+ clk_disable_unprepare(lpc_ctrl->clk);
++
+ return rc;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch
new file mode 100644
index 000000000..4a87f2d76
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch
@@ -0,0 +1,52 @@
+From 5b9ec5081492b461710cb82e7ecc93fd3af8ad34 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 18 Mar 2019 14:06:36 -0700
+Subject: [PATCH] Suppress excessive HID gadget error logs
+
+HID events can be sent even when the host disconnects the HID
+device according to the current graphic mode. For an example, if
+KVM mouse events are sent when the host is in text mode, queueing
+of end point messages will be dropped with this message:
+
+configfs-gadget gadget: usb_ep_queue error on int endpoint -108
+
+This case is very usual case in BMC since BMC can control power
+status of the host, so this commit suppress the error printing outs
+with making HID gadget driver drop events quietly in the case.
+
+This should be a downstream only customization. Do not upstream it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/usb/gadget/function/f_hid.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
+index f3816a5c861e..c96c0f6f1df0 100644
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -320,7 +320,7 @@ static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
+ struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
+ unsigned long flags;
+
+- if (req->status != 0) {
++ if (req->status != 0 && req->status != -ESHUTDOWN) {
+ ERROR(hidg->func.config->cdev,
+ "End Point Request ERROR: %d\n", req->status);
+ }
+@@ -395,8 +395,10 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
+
+ status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
+ if (status < 0) {
+- ERROR(hidg->func.config->cdev,
+- "usb_ep_queue error on int endpoint %zd\n", status);
++ if (status != -ESHUTDOWN)
++ ERROR(hidg->func.config->cdev,
++ "usb_ep_queue error on int endpoint %zd\n",
++ status);
+ goto release_write_pending;
+ } else {
+ status = count;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch
new file mode 100644
index 000000000..db94b13fd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch
@@ -0,0 +1,67 @@
+From 79d407327558f27a7df9d04b1d66cbe63129b622 Mon Sep 17 00:00:00 2001
+From: "Hunt, Bryan" <bryan.hunt@intel.com>
+Date: Mon, 6 May 2019 10:02:14 -0700
+Subject: [PATCH] Add AST2500 JTAG device
+
+Adding aspeed jtag device
+
+Signed-off-by: Hunt, Bryan <bryan.hunt@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g5.dtsi | 9 +++++++++
+ arch/arm/boot/dts/aspeed-g6.dtsi | 20 ++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index f5c25dab5337..5999cd5e0f2e 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -438,6 +438,15 @@
+ pinctrl-0 = <&pinctrl_espi_default>;
+ };
+
++ jtag: jtag@1e6e4000 {
++ compatible = "aspeed,ast2500-jtag";
++ reg = <0x1e6e4000 0x1c>;
++ clocks = <&syscon ASPEED_CLK_APB>;
++ resets = <&syscon ASPEED_RESET_JTAG_MASTER>;
++ interrupts = <43>;
++ status = "disabled";
++ };
++
+ lpc: lpc@1e789000 {
+ compatible = "aspeed,ast2500-lpc", "simple-mfd";
+ reg = <0x1e789000 0x1000>;
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 09f50afea11b..4d8b561fe582 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -367,6 +367,26 @@
+ status = "disabled";
+ };
+
++ jtag0: jtag@1e6e4000 {
++ compatible = "aspeed,ast2600-jtag";
++ reg = <0x1e6e4000 0x40>;
++ clocks = <&syscon ASPEED_CLK_APB1>;
++ resets = <&syscon ASPEED_RESET_JTAG_MASTER>;
++ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ };
++
++ jtag1: jtag@1e6e4100 {
++ compatible = "aspeed,ast2600-jtag";
++ reg = <0x1e6e4100 0x40>;
++ clocks = <&syscon ASPEED_CLK_APB1>;
++ resets = <&syscon ASPEED_RESET_JTAG_MASTER2>;
++ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_jtagm_default>;
++ status = "disabled";
++ };
++
+ adc: adc@1e6e9000 {
+ compatible = "aspeed,ast2500-adc";
+ reg = <0x1e6e9000 0x100>;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch
new file mode 100644
index 000000000..484c576b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch
@@ -0,0 +1,920 @@
+From ea6fa8fd6e36c776d560b4f69d1ede4a3bbe5f6b Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Fri, 7 Jun 2019 07:37:39 -0800
+Subject: [PATCH v29 1/6] drivers: jtag: Add JTAG core driver
+
+JTAG class driver provide infrastructure to support hardware/software
+JTAG platform drivers. It provide user layer API interface for flashing
+and debugging external devices which equipped with JTAG interface
+using standard transactions.
+
+Driver exposes set of IOCTL to user space for:
+- XFER:
+ SIR (Scan Instruction Register, IEEE 1149.1 Data Register scan);
+ SDR (Scan Data Register, IEEE 1149.1 Instruction Register scan);
+- GIOCSTATUS read the current TAPC state of the JTAG controller
+- SIOCSTATE Forces the JTAG TAPC to go into a particular state.
+- SIOCFREQ/GIOCFREQ for setting and reading JTAG frequency.
+- IOCBITBANG for low level control of JTAG signals.
+
+Driver core provides set of internal APIs for allocation and
+registration:
+- jtag_register;
+- jtag_unregister;
+- jtag_alloc;
+- jtag_free;
+
+Platform driver on registration with jtag-core creates the next
+entry in dev folder:
+/dev/jtagX
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Philippe Ombredanne <pombredanne@nexb.com>
+Cc: Vadim Pasternak <vadimp@mellanox.com>
+Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
+Cc: Paul Burton <paul.burton@mips.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Boris Brezillon <bbrezillon@kernel.org>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Johan Hovold <johan@kernel.org>
+Cc: Jens Axboe <axboe@kernel.dk>
+Cc: Joel Stanley <joel@jms.id.au>
+Cc: Palmer Dabbelt <palmer@sifive.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+v28->v29
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Expand bitbang function to accept multiples bitbang operations within a
+ single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS
+ values and it is expected that driver fills TDO fields with its
+ corresponding output value for every transaction.
+- Always setup JTAG controller to master mode but disable JTAG output when
+ the driver is not in use to allow other HW to own the JTAG bus. Remove SCU
+ register accesses. This register controls the JTAG controller mode
+ (master/slave).
+- Fix static analysis issues
+- Add support for multichain. Set tap state and xfer operations now include
+ two tap state arguments: current state and end state.
+
+v27->v28
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC
+ end states in SW mode using a lookup table to navigate across states.
+- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER).
+- Support for switching JTAG controller mode between slave and master
+ mode.
+- Setup JTAG controller mode to master only when the driver is opened,
+ letting
+ other HW to own the JTAG bus when it isn't in use.
+- Include JTAG bit bang IOCTL for low level JTAG control usage
+ (JTAG_IOCBITBANG).
+
+v24->v25
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- set values to enums in jtag.h
+
+v23->v24
+Notifications from kbuild test robot <lkp@intel.com>
+- Add include types.h header to jtag.h
+- remove unecessary jtag_release
+
+v22->v23
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- remove restriction of allocated JTAG devs-
+- add validation fo idle values
+- remove unnecessary blank line
+- change retcode for xfer
+- remove unecessary jtag_release callback
+- remove unecessary defined fron jtag.h
+- align in one line define JTAG_IOCRUNTEST
+
+v21->v22
+Comments pointed by Andy Shevchenko <andy.shevchenko@gmail.com>
+- Fix 0x0f -> 0x0F in ioctl-number.txt
+- Add description to #define MAX_JTAG_NAME_LEN
+- Remove unnecessary entry *dev from struct jtag
+- Remove redundant parens
+- Described mandatory callbacks and removed unnecessary
+- Set JTAG_MAX_XFER_DATA_LEN to power of 2
+- rework driver alloc/register to devm_ variant
+- increasing line length up to 84 in order to improve readability.
+
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- fix spell in ABI doccumentation
+
+v20->v21
+ Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+ - Fix JTAG dirver help in Kconfig
+
+v19->v20
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- Fix JTAG dirver help in Kconfig
+
+Notifications from kbuild test robot <lkp@intel.com>
+- fix incompatible type casts
+
+v18->v19
+Comments pointed by Julia Cartwright <juliac@eso.teric.us>
+- Fix memory leak on jtag_alloc exit
+
+v17->v18
+Comments pointed by Julia Cartwright <juliac@eso.teric.us>
+- Change to return -EOPNOTSUPP in case of error in JTAG_GIOCFREQ
+- Add ops callbacks check to jtag_alloc
+- Add err check for copy_to_user
+- Move the kfree() above the if (err) in JTAG_IOCXFER
+- remove unnecessary check for error after put_user
+- add padding to struct jtag_xfer
+
+v16->v17
+Comments pointed by Julia Cartwright <juliac@eso.teric.us>
+- Fix memory allocation on jtag alloc
+- Move out unnecessary form lock on jtag open
+- Rework jtag register behavior
+
+v15->v16
+Comments pointed by Florian Fainelli <f.fainelli@gmail.com>
+- move check jtag->ops->* in ioctl before get_user()
+- change error type -EINVAL --> -EBUSY on open already opened jtag
+- remove unnecessary ARCH_DMA_MINALIGN flag from kzalloc
+- remove define ARCH_DMA_MINALIGN
+
+v14->v15
+v13->v14
+Comments pointed by Philippe Ombredanne <pombredanne@nexb.com>
+- Change style of head block comment from /**/ to //
+
+v12->v13
+Comments pointed by Philippe Ombredanne <pombredanne@nexb.com>
+- Change jtag.c licence type to
+ SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ and reorder line with license in description
+
+v11->v12
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- Change jtag.h licence type to
+ SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ and reorder line with license in description
+
+Comments pointed by Chip Bilbrey <chip@bilbrey.org>
+- Remove Apeed reference from uapi jtag.h header
+- Remove access mode from xfer and idle transactions
+- Add new ioctl JTAG_SIOCMODE for set hw mode
+- Add single open per device blocking
+
+v10->v11
+Notifications from kbuild test robot <lkp@intel.com>
+- Add include types.h header to jtag.h
+- fix incompatible type of xfer callback
+- remove rdundant class defination
+- Fix return order in case of xfer error
+
+V9->v10
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- remove unnecessary alignment for pirv data
+- move jtag_copy_to_user and jtag_copy_from_user code just to ioctl
+- move int jtag_run_test_idle_op and jtag_xfer_op code
+ just to ioctl
+- change return error codes to more applicable
+- add missing error checks
+- fix error check order in ioctl
+- remove unnecessary blank lines
+- add param validation to ioctl
+- remove compat_ioctl
+- remove only one open per JTAG port blocking.
+ User will care about this.
+- Fix idr memory leak on jtag_exit
+- change cdev device type to misc
+
+V8->v9
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- use get_user() instead of __get_user().
+- change jtag->open type from int to atomic_t
+- remove spinlock on jtg_open
+- remove mutex on jtag_register
+- add unregister_chrdev_region on jtag_init err
+- add unregister_chrdev_region on jtag_exit
+- remove unnecessary pointer casts
+- add *data parameter to xfer function prototype
+
+v7->v8
+Comments pointed by Moritz Fischer <moritz.fischer@ettus.com>
+- Fix misspelling s/friver/driver
+
+v6->v7
+Notifications from kbuild test robot <lkp@intel.com>
+- Remove include asm/types.h from jtag.h
+- Add include <linux/types.h> to jtag.c
+
+v5->v6
+v4->v5
+
+v3->v4
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- change transaction pointer tdio type to __u64
+- change internal status type from enum to __u32
+- reorder jtag_xfer members to avoid the implied padding
+- add __packed attribute to jtag_xfer and jtag_run_test_idle
+
+v2->v3
+Notifications from kbuild test robot <lkp@intel.com>
+- Change include path to <linux/types.h> in jtag.h
+
+v1->v2
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- Change license type from GPLv2/BSD to GPLv2
+- Change type of variables which crossed user/kernel to __type
+- Remove "default n" from Kconfig
+
+Comments pointed by Andrew Lunn <andrew@lunn.ch>
+- Change list_add_tail in jtag_unregister to list_del
+
+Comments pointed by Neil Armstrong <narmstrong@baylibre.com>
+- Add SPDX-License-Identifier instead of license text
+
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- Change __copy_to_user to memdup_user
+- Change __put_user to put_user
+- Change type of variables to __type for compatible 32 and 64-bit systems
+- Add check for maximum xfer data size
+- Change lookup data mechanism to get jtag data from inode
+- Add .compat_ioctl to file ops
+- Add mem alignment for jtag priv data
+
+Comments pointed by Tobias Klauser <tklauser@distanz.ch>
+- Change function names to avoid match with variable types
+- Fix description for jtag_ru_test_idle in uapi jtag.h
+- Fix misprints IDEL/IDLE, trough/through
+---
+ drivers/Kconfig | 1 +
+ drivers/Makefile | 1 +
+ drivers/jtag/Kconfig | 17 +++
+ drivers/jtag/Makefile | 1 +
+ drivers/jtag/jtag.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/jtag.h | 47 +++++++
+ include/uapi/linux/jtag.h | 214 +++++++++++++++++++++++++++++++
+ 7 files changed, 602 insertions(+)
+ create mode 100644 drivers/jtag/Kconfig
+ create mode 100644 drivers/jtag/Makefile
+ create mode 100644 drivers/jtag/jtag.c
+ create mode 100644 include/linux/jtag.h
+ create mode 100644 include/uapi/linux/jtag.h
+
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index 4322efa37732..e5e4fe21b5d9 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -230,4 +230,5 @@ source "drivers/counter/Kconfig"
+
+ source "drivers/peci/Kconfig"
+
++source "drivers/jtag/Kconfig"
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 82f78cfedf69..297047d4ed9b 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -187,3 +187,4 @@ obj-$(CONFIG_GNSS) += gnss/
+ obj-$(CONFIG_INTERCONNECT) += interconnect/
+ obj-$(CONFIG_COUNTER) += counter/
+ obj-$(CONFIG_PECI) += peci/
++obj-$(CONFIG_JTAG_ASPEED) += jtag/
+diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig
+new file mode 100644
+index 000000000000..47771fcd3c5b
+--- /dev/null
++++ b/drivers/jtag/Kconfig
+@@ -0,0 +1,17 @@
++menuconfig JTAG
++ tristate "JTAG support"
++ help
++ This provides basic core functionality support for JTAG class devices.
++ Hardware that is equipped with a JTAG microcontroller can be
++ supported by using this driver's interfaces.
++ This driver exposes a set of IOCTLs to the user space for
++ the following commands:
++ SDR: Performs an IEEE 1149.1 Data Register scan
++ SIR: Performs an IEEE 1149.1 Instruction Register scan.
++ RUNTEST: Forces the IEEE 1149.1 bus to a run state for a specified
++ number of clocks or a specified time period.
++
++ If you want this support, you should say Y here.
++
++ To compile this driver as a module, choose M here: the module will
++ be called jtag.
+diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile
+new file mode 100644
+index 000000000000..af374939a9e6
+--- /dev/null
++++ b/drivers/jtag/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_JTAG) += jtag.o
+diff --git a/drivers/jtag/jtag.c b/drivers/jtag/jtag.c
+new file mode 100644
+index 000000000000..39a4d88a9c21
+--- /dev/null
++++ b/drivers/jtag/jtag.c
+@@ -0,0 +1,321 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Copyright (c) 2018 Mellanox Technologies. All rights reserved.
++// Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com>
++// Copyright (c) 2019 Intel Corporation
++
++#include <linux/cdev.h>
++#include <linux/device.h>
++#include <linux/jtag.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/rtnetlink.h>
++#include <linux/spinlock.h>
++#include <linux/types.h>
++#include <uapi/linux/jtag.h>
++
++struct jtag {
++ struct miscdevice miscdev;
++ const struct jtag_ops *ops;
++ int id;
++ unsigned long priv[0];
++};
++
++static DEFINE_IDA(jtag_ida);
++
++void *jtag_priv(struct jtag *jtag)
++{
++ return jtag->priv;
++}
++EXPORT_SYMBOL_GPL(jtag_priv);
++
++static long jtag_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct jtag *jtag = file->private_data;
++ struct jtag_tap_state tapstate;
++ struct jtag_xfer xfer;
++ struct bitbang_packet bitbang;
++ struct tck_bitbang *bitbang_data;
++ struct jtag_mode mode;
++ u8 *xfer_data;
++ u32 data_size;
++ u32 value;
++ int err;
++
++ if (!arg)
++ return -EINVAL;
++
++ switch (cmd) {
++ case JTAG_GIOCFREQ:
++ if (!jtag->ops->freq_get)
++ return -EOPNOTSUPP;
++
++ err = jtag->ops->freq_get(jtag, &value);
++ if (err)
++ break;
++
++ if (put_user(value, (__u32 __user *)arg))
++ err = -EFAULT;
++ break;
++
++ case JTAG_SIOCFREQ:
++ if (!jtag->ops->freq_set)
++ return -EOPNOTSUPP;
++
++ if (get_user(value, (__u32 __user *)arg))
++ return -EFAULT;
++ if (value == 0)
++ return -EINVAL;
++
++ err = jtag->ops->freq_set(jtag, value);
++ break;
++
++ case JTAG_SIOCSTATE:
++ if (copy_from_user(&tapstate, (const void __user *)arg,
++ sizeof(struct jtag_tap_state)))
++ return -EFAULT;
++
++ if (tapstate.from > JTAG_STATE_CURRENT)
++ return -EINVAL;
++
++ if (tapstate.endstate > JTAG_STATE_CURRENT)
++ return -EINVAL;
++
++ if (tapstate.reset > JTAG_FORCE_RESET)
++ return -EINVAL;
++
++ err = jtag->ops->status_set(jtag, &tapstate);
++ break;
++
++ case JTAG_IOCXFER:
++ if (copy_from_user(&xfer, (const void __user *)arg,
++ sizeof(struct jtag_xfer)))
++ return -EFAULT;
++
++ if (xfer.length >= JTAG_MAX_XFER_DATA_LEN)
++ return -EINVAL;
++
++ if (xfer.type > JTAG_SDR_XFER)
++ return -EINVAL;
++
++ if (xfer.direction > JTAG_READ_WRITE_XFER)
++ return -EINVAL;
++
++ if (xfer.from > JTAG_STATE_CURRENT)
++ return -EINVAL;
++
++ if (xfer.endstate > JTAG_STATE_CURRENT)
++ return -EINVAL;
++
++ data_size = DIV_ROUND_UP(xfer.length, BITS_PER_BYTE);
++ xfer_data = memdup_user(u64_to_user_ptr(xfer.tdio), data_size);
++ if (IS_ERR(xfer_data))
++ return -EFAULT;
++
++ err = jtag->ops->xfer(jtag, &xfer, xfer_data);
++ if (err) {
++ kfree(xfer_data);
++ return err;
++ }
++
++ err = copy_to_user(u64_to_user_ptr(xfer.tdio),
++ (void *)xfer_data, data_size);
++ kfree(xfer_data);
++ if (err)
++ return -EFAULT;
++
++ if (copy_to_user((void __user *)arg, (void *)&xfer,
++ sizeof(struct jtag_xfer)))
++ return -EFAULT;
++ break;
++
++ case JTAG_GIOCSTATUS:
++ err = jtag->ops->status_get(jtag, &value);
++ if (err)
++ break;
++
++ err = put_user(value, (__u32 __user *)arg);
++ break;
++ case JTAG_IOCBITBANG:
++ if (copy_from_user(&bitbang, (const void __user *)arg,
++ sizeof(struct bitbang_packet)))
++ return -EFAULT;
++
++ if (bitbang.length >= JTAG_MAX_XFER_DATA_LEN)
++ return -EINVAL;
++
++ data_size = bitbang.length * sizeof(struct tck_bitbang);
++ bitbang_data = memdup_user((void __user *)bitbang.data,
++ data_size);
++ if (IS_ERR(bitbang_data))
++ return -EFAULT;
++
++ err = jtag->ops->bitbang(jtag, &bitbang, bitbang_data);
++ if (err) {
++ kfree(bitbang_data);
++ return err;
++ }
++ err = copy_to_user((void __user *)bitbang.data,
++ (void *)bitbang_data, data_size);
++ kfree(bitbang_data);
++ if (err)
++ return -EFAULT;
++ break;
++ case JTAG_SIOCMODE:
++ if (!jtag->ops->mode_set)
++ return -EOPNOTSUPP;
++
++ if (copy_from_user(&mode, (const void __user *)arg,
++ sizeof(struct jtag_mode)))
++ return -EFAULT;
++
++ err = jtag->ops->mode_set(jtag, &mode);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ return err;
++}
++
++static int jtag_open(struct inode *inode, struct file *file)
++{
++ struct jtag *jtag = container_of(file->private_data,
++ struct jtag,
++ miscdev);
++
++ file->private_data = jtag;
++ if (jtag->ops->enable(jtag))
++ return -EBUSY;
++ return nonseekable_open(inode, file);
++}
++
++static int jtag_release(struct inode *inode, struct file *file)
++{
++ struct jtag *jtag = file->private_data;
++
++ if (jtag->ops->disable(jtag))
++ return -EBUSY;
++ return 0;
++}
++
++static const struct file_operations jtag_fops = {
++ .owner = THIS_MODULE,
++ .open = jtag_open,
++ .llseek = noop_llseek,
++ .unlocked_ioctl = jtag_ioctl,
++ .release = jtag_release,
++};
++
++struct jtag *jtag_alloc(struct device *host, size_t priv_size,
++ const struct jtag_ops *ops)
++{
++ struct jtag *jtag;
++
++ if (!host)
++ return NULL;
++
++ if (!ops)
++ return NULL;
++
++ if (!ops->status_set || !ops->status_get || !ops->xfer)
++ return NULL;
++
++ jtag = kzalloc(sizeof(*jtag) + priv_size, GFP_KERNEL);
++ if (!jtag)
++ return NULL;
++
++ jtag->ops = ops;
++ jtag->miscdev.parent = host;
++
++ return jtag;
++}
++EXPORT_SYMBOL_GPL(jtag_alloc);
++
++void jtag_free(struct jtag *jtag)
++{
++ kfree(jtag);
++}
++EXPORT_SYMBOL_GPL(jtag_free);
++
++static int jtag_register(struct jtag *jtag)
++{
++ struct device *dev = jtag->miscdev.parent;
++ int err;
++ int id;
++
++ if (!dev)
++ return -ENODEV;
++
++ id = ida_simple_get(&jtag_ida, 0, 0, GFP_KERNEL);
++ if (id < 0)
++ return id;
++
++ jtag->id = id;
++
++ jtag->miscdev.fops = &jtag_fops;
++ jtag->miscdev.minor = MISC_DYNAMIC_MINOR;
++ jtag->miscdev.name = kasprintf(GFP_KERNEL, "jtag%d", id);
++ if (!jtag->miscdev.name) {
++ err = -ENOMEM;
++ goto err_jtag_alloc;
++ }
++
++ err = misc_register(&jtag->miscdev);
++ if (err) {
++ dev_err(jtag->miscdev.parent, "Unable to register device\n");
++ goto err_jtag_name;
++ }
++ return 0;
++
++err_jtag_name:
++ kfree(jtag->miscdev.name);
++err_jtag_alloc:
++ ida_simple_remove(&jtag_ida, id);
++ return err;
++}
++
++static void jtag_unregister(struct jtag *jtag)
++{
++ misc_deregister(&jtag->miscdev);
++ kfree(jtag->miscdev.name);
++ ida_simple_remove(&jtag_ida, jtag->id);
++}
++
++static void devm_jtag_unregister(struct device *dev, void *res)
++{
++ jtag_unregister(*(struct jtag **)res);
++}
++
++int devm_jtag_register(struct device *dev, struct jtag *jtag)
++{
++ struct jtag **ptr;
++ int ret;
++
++ ptr = devres_alloc(devm_jtag_unregister, sizeof(struct jtag *),
++ GFP_KERNEL);
++ if (!ptr)
++ return -ENOMEM;
++
++ ret = jtag_register(jtag);
++ if (!ret) {
++ *ptr = jtag;
++ devres_add(dev, ptr);
++ } else {
++ devres_free(ptr);
++ }
++ return ret;
++}
++EXPORT_SYMBOL_GPL(devm_jtag_register);
++
++static void __exit jtag_exit(void)
++{
++ ida_destroy(&jtag_ida);
++}
++
++module_exit(jtag_exit);
++
++MODULE_AUTHOR("Oleksandr Shamray <oleksandrs@mellanox.com>");
++MODULE_DESCRIPTION("Generic jtag support");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/jtag.h b/include/linux/jtag.h
+new file mode 100644
+index 000000000000..fab12dc4fc5e
+--- /dev/null
++++ b/include/linux/jtag.h
+@@ -0,0 +1,47 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */
++/* Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com> */
++/* Copyright (c) 2019 Intel Corporation */
++
++#ifndef __LINUX_JTAG_H
++#define __LINUX_JTAG_H
++
++#include <linux/types.h>
++#include <uapi/linux/jtag.h>
++
++#define JTAG_MAX_XFER_DATA_LEN 65535
++
++struct jtag;
++/**
++ * struct jtag_ops - callbacks for JTAG control functions:
++ *
++ * @freq_get: get frequency function. Filled by dev driver
++ * @freq_set: set frequency function. Filled by dev driver
++ * @status_get: get JTAG TAPC state function. Mandatory, Filled by dev driver
++ * @status_set: set JTAG TAPC state function. Mandatory, Filled by dev driver
++ * @xfer: send JTAG xfer function. Mandatory func. Filled by dev driver
++ * @mode_set: set specific work mode for JTAG. Filled by dev driver
++ * @bitbang: set low level bitbang operations. Filled by dev driver
++ * @enable: enables JTAG interface in master mode. Filled by dev driver
++ * @disable: disables JTAG interface master mode. Filled by dev driver
++ */
++struct jtag_ops {
++ int (*freq_get)(struct jtag *jtag, u32 *freq);
++ int (*freq_set)(struct jtag *jtag, u32 freq);
++ int (*status_get)(struct jtag *jtag, u32 *state);
++ int (*status_set)(struct jtag *jtag, struct jtag_tap_state *endst);
++ int (*xfer)(struct jtag *jtag, struct jtag_xfer *xfer, u8 *xfer_data);
++ int (*mode_set)(struct jtag *jtag, struct jtag_mode *jtag_mode);
++ int (*bitbang)(struct jtag *jtag, struct bitbang_packet *bitbang,
++ struct tck_bitbang *bitbang_data);
++ int (*enable)(struct jtag *jtag);
++ int (*disable)(struct jtag *jtag);
++};
++
++void *jtag_priv(struct jtag *jtag);
++int devm_jtag_register(struct device *dev, struct jtag *jtag);
++struct jtag *jtag_alloc(struct device *host, size_t priv_size,
++ const struct jtag_ops *ops);
++void jtag_free(struct jtag *jtag);
++
++#endif /* __LINUX_JTAG_H */
+diff --git a/include/uapi/linux/jtag.h b/include/uapi/linux/jtag.h
+new file mode 100644
+index 000000000000..315e59577a17
+--- /dev/null
++++ b/include/uapi/linux/jtag.h
+@@ -0,0 +1,214 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */
++/* Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com> */
++/* Copyright (c) 2019 Intel Corporation */
++
++#ifndef __UAPI_LINUX_JTAG_H
++#define __UAPI_LINUX_JTAG_H
++
++/*
++ * JTAG_XFER_MODE: JTAG transfer mode. Used to set JTAG controller transfer mode
++ * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_XFER_MODE 0
++/*
++ * JTAG_CONTROL_MODE: JTAG controller mode. Used to set JTAG controller mode
++ * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_CONTROL_MODE 1
++/*
++ * JTAG_MASTER_OUTPUT_DISABLE: JTAG master mode output disable, it is used to
++ * enable other devices to own the JTAG bus.
++ * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_MASTER_OUTPUT_DISABLE 0
++/*
++ * JTAG_MASTER_MODE: JTAG master mode. Used to set JTAG controller master mode
++ * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_MASTER_MODE 1
++/*
++ * JTAG_XFER_HW_MODE: JTAG hardware mode. Used to set HW drived or bitbang
++ * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_XFER_HW_MODE 1
++/*
++ * JTAG_XFER_SW_MODE: JTAG software mode. Used to set SW drived or bitbang
++ * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
++ */
++#define JTAG_XFER_SW_MODE 0
++
++/**
++ * enum jtag_tapstate:
++ *
++ * @JTAG_STATE_TLRESET: JTAG state machine Test Logic Reset state
++ * @JTAG_STATE_IDLE: JTAG state machine IDLE state
++ * @JTAG_STATE_SELECTDR: JTAG state machine SELECT_DR state
++ * @JTAG_STATE_CAPTUREDR: JTAG state machine CAPTURE_DR state
++ * @JTAG_STATE_SHIFTDR: JTAG state machine SHIFT_DR state
++ * @JTAG_STATE_EXIT1DR: JTAG state machine EXIT-1 DR state
++ * @JTAG_STATE_PAUSEDR: JTAG state machine PAUSE_DR state
++ * @JTAG_STATE_EXIT2DR: JTAG state machine EXIT-2 DR state
++ * @JTAG_STATE_UPDATEDR: JTAG state machine UPDATE DR state
++ * @JTAG_STATE_SELECTIR: JTAG state machine SELECT_IR state
++ * @JTAG_STATE_CAPTUREIR: JTAG state machine CAPTURE_IR state
++ * @JTAG_STATE_SHIFTIR: JTAG state machine SHIFT_IR state
++ * @JTAG_STATE_EXIT1IR: JTAG state machine EXIT-1 IR state
++ * @JTAG_STATE_PAUSEIR: JTAG state machine PAUSE_IR state
++ * @JTAG_STATE_EXIT2IR: JTAG state machine EXIT-2 IR state
++ * @JTAG_STATE_UPDATEIR: JTAG state machine UPDATE IR state
++ * @JTAG_STATE_CURRENT: JTAG current state, saved by driver
++ */
++enum jtag_tapstate {
++ JTAG_STATE_TLRESET,
++ JTAG_STATE_IDLE,
++ JTAG_STATE_SELECTDR,
++ JTAG_STATE_CAPTUREDR,
++ JTAG_STATE_SHIFTDR,
++ JTAG_STATE_EXIT1DR,
++ JTAG_STATE_PAUSEDR,
++ JTAG_STATE_EXIT2DR,
++ JTAG_STATE_UPDATEDR,
++ JTAG_STATE_SELECTIR,
++ JTAG_STATE_CAPTUREIR,
++ JTAG_STATE_SHIFTIR,
++ JTAG_STATE_EXIT1IR,
++ JTAG_STATE_PAUSEIR,
++ JTAG_STATE_EXIT2IR,
++ JTAG_STATE_UPDATEIR,
++ JTAG_STATE_CURRENT
++};
++
++/**
++ * enum jtag_reset:
++ *
++ * @JTAG_NO_RESET: JTAG run TAP from current state
++ * @JTAG_FORCE_RESET: JTAG force TAP to reset state
++ */
++enum jtag_reset {
++ JTAG_NO_RESET = 0,
++ JTAG_FORCE_RESET = 1,
++};
++
++/**
++ * enum jtag_xfer_type:
++ *
++ * @JTAG_SIR_XFER: SIR transfer
++ * @JTAG_SDR_XFER: SDR transfer
++ */
++enum jtag_xfer_type {
++ JTAG_SIR_XFER = 0,
++ JTAG_SDR_XFER = 1,
++};
++
++/**
++ * enum jtag_xfer_direction:
++ *
++ * @JTAG_READ_XFER: read transfer
++ * @JTAG_WRITE_XFER: write transfer
++ * @JTAG_READ_WRITE_XFER: read & write transfer
++ */
++enum jtag_xfer_direction {
++ JTAG_READ_XFER = 1,
++ JTAG_WRITE_XFER = 2,
++ JTAG_READ_WRITE_XFER = 3,
++};
++
++/**
++ * struct jtag_tap_state - forces JTAG state machine to go into a TAPC
++ * state
++ *
++ * @reset: 0 - run IDLE/PAUSE from current state
++ * 1 - go through TEST_LOGIC/RESET state before IDLE/PAUSE
++ * @end: completion flag
++ * @tck: clock counter
++ *
++ * Structure provide interface to JTAG device for JTAG set state execution.
++ */
++struct jtag_tap_state {
++ __u8 reset;
++ __u8 from;
++ __u8 endstate;
++ __u8 tck;
++};
++
++/**
++ * struct jtag_xfer - jtag xfer:
++ *
++ * @type: transfer type
++ * @direction: xfer direction
++ * @from: xfer current state
++ * @endstate: xfer end state
++ * @padding: xfer padding
++ * @length: xfer bits length
++ * @tdio : xfer data array
++ *
++ * Structure provide interface to JTAG device for JTAG SDR/SIR xfer execution.
++ */
++struct jtag_xfer {
++ __u8 type;
++ __u8 direction;
++ __u8 from;
++ __u8 endstate;
++ __u8 padding;
++ __u32 length;
++ __u64 tdio;
++};
++
++/**
++ * struct bitbang_packet - jtag bitbang array packet:
++ *
++ * @data: JTAG Bitbang struct array pointer(input/output)
++ * @length: array size (input)
++ *
++ * Structure provide interface to JTAG device for JTAG bitbang bundle execution
++ */
++struct bitbang_packet {
++ struct tck_bitbang *data;
++ __u32 length;
++} __attribute__((__packed__));
++
++/**
++ * struct jtag_bitbang - jtag bitbang:
++ *
++ * @tms: JTAG TMS
++ * @tdi: JTAG TDI (input)
++ * @tdo: JTAG TDO (output)
++ *
++ * Structure provide interface to JTAG device for JTAG bitbang execution.
++ */
++struct tck_bitbang {
++ __u8 tms;
++ __u8 tdi;
++ __u8 tdo;
++} __attribute__((__packed__));
++
++/**
++ * struct jtag_mode - jtag mode:
++ *
++ * @feature: 0 - JTAG feature setting selector for JTAG controller HW/SW
++ * 1 - JTAG feature setting selector for controller bus master
++ * mode output (enable / disable).
++ * @mode: (0 - SW / 1 - HW) for JTAG_XFER_MODE feature(0)
++ * (0 - output disable / 1 - output enable) for JTAG_CONTROL_MODE
++ * feature(1)
++ *
++ * Structure provide configuration modes to JTAG device.
++ */
++struct jtag_mode {
++ __u32 feature;
++ __u32 mode;
++};
++
++/* ioctl interface */
++#define __JTAG_IOCTL_MAGIC 0xb2
++
++#define JTAG_SIOCSTATE _IOW(__JTAG_IOCTL_MAGIC, 0, struct jtag_tap_state)
++#define JTAG_SIOCFREQ _IOW(__JTAG_IOCTL_MAGIC, 1, unsigned int)
++#define JTAG_GIOCFREQ _IOR(__JTAG_IOCTL_MAGIC, 2, unsigned int)
++#define JTAG_IOCXFER _IOWR(__JTAG_IOCTL_MAGIC, 3, struct jtag_xfer)
++#define JTAG_GIOCSTATUS _IOWR(__JTAG_IOCTL_MAGIC, 4, enum jtag_tapstate)
++#define JTAG_SIOCMODE _IOW(__JTAG_IOCTL_MAGIC, 5, unsigned int)
++#define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int)
++
++#endif /* __UAPI_LINUX_JTAG_H */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch
new file mode 100644
index 000000000..b70629f18
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch
@@ -0,0 +1,1466 @@
+From e01c562db28797e3b6be9030f1f52507115c6765 Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Mon, 6 Apr 2020 09:48:32 -0700
+Subject: [PATCH] Add Aspeed SoC 24xx and 25xx families JTAG
+
+Driver adds support of Aspeed 2400-2600 series SOC JTAG master controller.
+
+Driver implements the following jtag ops:
+- freq_get;
+- freq_set;
+- status_get;
+- status_set
+- xfer;
+- mode_set;
+- bitbang;
+- enable;
+- disable;
+
+It has been tested on Mellanox system with BMC equipped with
+Aspeed 2520 SoC for programming CPLD devices.
+
+It has also been tested on Intel system using Aspeed 25xx SoC
+for JTAG communication.
+
+Tested on Intel system using Aspeed 26xx SoC for JTAG communication.
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Philippe Ombredanne <pombredanne@nexb.com>
+Acked-by: Joel Stanley <joel@jms.id.au>
+Cc: Vadim Pasternak <vadimp@mellanox.com>
+Cc: Andrew Jeffery <andrew@aj.id.au>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+v29->v30
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Add Suport for 26xx series
+
+v28->v29
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Expand bitbang function to accept multiples bitbang operations within a
+ single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS
+ values and it is expected that driver fills TDO fields with its
+ corresponding output value for every transaction.
+- Always setup JTAG controller to master mode but disable JTAG output when
+ the driver is not in use to allow other HW to own the JTAG bus. Remove SCU
+ register accesses. This register controls the JTAG controller mode
+ (master/slave).
+- Encansulate dev_dgb message into DEBUG_JTAG macros to improve driver's JTAG
+ performace.
+- Add support for multichain. Set tap state and xfer operations now include
+ two tap state arguments: current state and end state.
+
+v27->v28
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC
+ end states in SW mode using a lookup table to navigate across states.
+- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER).
+- Support for switching JTAG controller mode between slave and master
+ mode.
+- Setup JTAG controller mode to master only when the driver is opened,
+ letting other HW to own the JTAG bus when it isn't in use.
+- Include JTAG bit bang IOCTL for low level JTAG control usage
+ (JTAG_IOCBITBANG).
+- Add debug traces.
+- Add support for register polling (default) due it is 3 times faster than
+ interrupt mode. Define USE_INTERRUPTS macro to enable interrupt usage.
+- Remove unnecessary delays for aspeed_jtag_status_set function. It makes
+ SW mode 4 times faster.
+- Clean data buffer on aspeed_jtag_xfer_sw before tdo writes to avoid data
+ output corruption for read operations in SW mode.
+- Correct register settings for HW mode transfer operations.
+- Propagate ret codes all the way from low level functions up to
+ JTAG_IOCXFER call.
+- Support for partitioned transfers. Single JTAG transfer through
+ multiples JTAG_IOCXFER calls. Now end transmission(scan_end) also
+ evaluates transfer end state.
+
+v26->v27
+Changes made by Oleksandr Shamray <oleksandrs@mellamnox.com>
+- change aspeed_jtag_sw_delay to udelay function in bit-bang operation
+
+v25->v26
+v24->v25
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- reduced debug printouts
+
+v23->v24
+v22->v23
+v21->v22
+Comments pointed by Andy Shevchenko <andy.shevchenko@gmail.com>
+- rearrange ASPEED register defines
+- simplified JTAG divider calculation formula
+- change delay function in bit-bang operation
+- add helper functions for TAP states switching
+- remove unnecessary comments
+- remove redundant debug messages
+- make dines for repetative register bit sets
+- fixed indentation
+- change checks from negative to positive
+- add error check for clk_prepare_enable
+- rework driver alloc/register to devm_ variant
+- Increasing line length up to 85 in order to improve readability
+
+v20->v21
+v19->v20
+Notifications from kbuild test robot <lkp@intel.com>
+- add static declaration to 'aspeed_jtag_init' and
+ 'aspeed_jtag_deinit' functions
+
+v18->v19
+v17->v18
+v16->v17
+v15->v16
+Comments pointed by Joel Stanley <joel.stan@gmail.com>
+- Add reset_control on Jtag init/deinit
+
+v14->v15
+Comments pointed by Joel Stanley <joel.stan@gmail.com>
+- Add ARCH_ASPEED || COMPILE_TEST to Kconfig
+- remove unused offset variable
+- remove "aspeed_jtag" from dev_err and dev_dbg messages
+- change clk_prepare_enable initialisation order
+
+v13->v14
+Comments pointed by Philippe Ombredanne <pombredanne@nexb.com>
+- Change style of head block comment from /**/ to //
+
+v12->v13
+Comments pointed by Philippe Ombredanne <pombredanne@nexb.com>
+- Change jtag-aspeed.c licence type to
+ SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ and reorder line with license- add reset descriptions in bndings file
+ in description
+Comments pointed by Kun Yi <kunyi@google.com>
+- Changed capability check for aspeed,ast2400-jtag/ast200-jtag
+
+v11->v12
+Comments pointed by Chip Bilbrey <chip@bilbrey.org>
+- Remove access mode from xfer and idle transactions
+- Add new ioctl JTAG_SIOCMODE for set hw mode
+
+v10->v11
+v9->v10
+V8->v9
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- add *data parameter to xfer function prototype
+
+v7->v8
+Comments pointed by Joel Stanley <joel.stan@gmail.com>
+- aspeed_jtag_init replace goto to return;
+- change input variables type from __u32 to u32
+ in functios freq_get, freq_set, status_get
+- change sm_ variables type from char to u8
+- in jatg_init add disable clocks on error case
+- remove release_mem_region on error case
+- remove devm_free_irq on jtag_deinit
+- Fix misspelling Disabe/Disable
+- Change compatible string to ast2400 and ast2000
+
+v6->v7
+Notifications from kbuild test robot <lkp@intel.com>
+- Add include <linux/types.h> to jtag-asapeed.c
+
+v5->v6
+v4->v5
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- Added HAS_IOMEM dependence in Kconfig to avoid
+ "undefined reference to `devm_ioremap_resource'" error,
+ because in some arch this not supported
+
+v3->v4
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- change transaction pointer tdio type to __u64
+- change internal status type from enum to __u32
+
+v2->v3
+
+v1->v2
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- change license type from GPLv2/BSD to GPLv2
+
+Comments pointed by Neil Armstrong <narmstrong@baylibre.com>
+- Add clk_prepare_enable/clk_disable_unprepare in clock init/deinit
+- Change .compatible to soc-specific compatible names
+ aspeed,aspeed4000-jtag/aspeed5000-jtag
+- Added dt-bindings
+
+Comments pointed by Arnd Bergmann <arnd@arndb.de>
+- Reorder functions and removed the forward declarations
+- Add static const qualifier to state machine states transitions
+- Change .compatible to soc-specific compatible names
+ aspeed,aspeed4000-jtag/aspeed5000-jtag
+- Add dt-bindings
+
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- Change module name jtag-aspeed in description in Kconfig
+
+Comments pointed by kbuild test robot <lkp@intel.com>
+- Remove invalid include <asm/mach-types.h>
+- add resource_size instead of calculation
+---
+ drivers/jtag/Kconfig | 14 +
+ drivers/jtag/Makefile | 1 +
+ drivers/jtag/jtag-aspeed.c | 1217 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1232 insertions(+)
+ create mode 100644 drivers/jtag/jtag-aspeed.c
+
+diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig
+index 47771fc..0cc163f 100644
+--- a/drivers/jtag/Kconfig
++++ b/drivers/jtag/Kconfig
+@@ -15,3 +15,17 @@ menuconfig JTAG
+
+ To compile this driver as a module, choose M here: the module will
+ be called jtag.
++
++menuconfig JTAG_ASPEED
++ tristate "Aspeed SoC JTAG controller support"
++ depends on JTAG && HAS_IOMEM
++ depends on ARCH_ASPEED || COMPILE_TEST
++ help
++ This provides a support for Aspeed JTAG device, equipped on
++ Aspeed SoC 24xx and 25xx families. Drivers allows programming
++ of hardware devices, connected to SoC through the JTAG interface.
++
++ If you want this support, you should say Y here.
++
++ To compile this driver as a module, choose M here: the module will
++ be called jtag-aspeed.
+diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile
+index af37493..04a855e 100644
+--- a/drivers/jtag/Makefile
++++ b/drivers/jtag/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_JTAG) += jtag.o
++obj-$(CONFIG_JTAG_ASPEED) += jtag-aspeed.o
+diff --git a/drivers/jtag/jtag-aspeed.c b/drivers/jtag/jtag-aspeed.c
+new file mode 100644
+index 0000000..1e6ace6
+--- /dev/null
++++ b/drivers/jtag/jtag-aspeed.c
+@@ -0,0 +1,1217 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018 Mellanox Technologies. All rights reserved.
++// Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com>
++// Copyright (c) 2019 Intel Corporation
++
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/jtag.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <uapi/linux/jtag.h>
++
++#define ASPEED_SCU_RESET_JTAG BIT(22)
++
++#define ASPEED_JTAG_DATA 0x00
++#define ASPEED_JTAG_INST 0x04
++#define ASPEED_JTAG_CTRL 0x08
++#define ASPEED_JTAG_ISR 0x0C
++#define ASPEED_JTAG_SW 0x10
++#define ASPEED_JTAG_TCK 0x14
++#define ASPEED_JTAG_EC 0x18
++
++#define ASPEED_JTAG_DATA_MSB 0x01
++#define ASPEED_JTAG_DATA_CHUNK_SIZE 0x20
++
++/* ASPEED_JTAG_CTRL: Engine Control 24xx and 25xx series*/
++#define ASPEED_JTAG_CTL_ENG_EN BIT(31)
++#define ASPEED_JTAG_CTL_ENG_OUT_EN BIT(30)
++#define ASPEED_JTAG_CTL_FORCE_TMS BIT(29)
++#define ASPEED_JTAG_CTL_IR_UPDATE BIT(26)
++#define ASPEED_JTAG_CTL_INST_LEN(x) ((x) << 20)
++#define ASPEED_JTAG_CTL_LASPEED_INST BIT(17)
++#define ASPEED_JTAG_CTL_INST_EN BIT(16)
++#define ASPEED_JTAG_CTL_DR_UPDATE BIT(10)
++#define ASPEED_JTAG_CTL_DATA_LEN(x) ((x) << 4)
++#define ASPEED_JTAG_CTL_LASPEED_DATA BIT(1)
++#define ASPEED_JTAG_CTL_DATA_EN BIT(0)
++
++/* ASPEED_JTAG_CTRL: Engine Control 26xx series*/
++#define ASPEED_JTAG_CTL_26XX_RESET_FIFO BIT(21)
++#define ASPEED_JTAG_CTL_26XX_FIFO_MODE_CTRL BIT(20)
++#define ASPEED_JTAG_CTL_26XX_TRANS_LEN(x) ((x) << 8)
++#define ASPEED_JTAG_CTL_26XX_MSB_FIRST BIT(6)
++#define ASPEED_JTAG_CTL_26XX_TERM_TRANS BIT(5)
++#define ASPEED_JTAG_CTL_26XX_LASPEED_TRANS BIT(4)
++#define ASPEED_JTAG_CTL_26XX_INST_EN BIT(1)
++
++/* ASPEED_JTAG_ISR : Interrupt status and enable */
++#define ASPEED_JTAG_ISR_INST_PAUSE BIT(19)
++#define ASPEED_JTAG_ISR_INST_COMPLETE BIT(18)
++#define ASPEED_JTAG_ISR_DATA_PAUSE BIT(17)
++#define ASPEED_JTAG_ISR_DATA_COMPLETE BIT(16)
++#define ASPEED_JTAG_ISR_INST_PAUSE_EN BIT(3)
++#define ASPEED_JTAG_ISR_INST_COMPLETE_EN BIT(2)
++#define ASPEED_JTAG_ISR_DATA_PAUSE_EN BIT(1)
++#define ASPEED_JTAG_ISR_DATA_COMPLETE_EN BIT(0)
++#define ASPEED_JTAG_ISR_INT_EN_MASK GENMASK(3, 0)
++#define ASPEED_JTAG_ISR_INT_MASK GENMASK(19, 16)
++
++/* ASPEED_JTAG_SW : Software Mode and Status */
++#define ASPEED_JTAG_SW_MODE_EN BIT(19)
++#define ASPEED_JTAG_SW_MODE_TCK BIT(18)
++#define ASPEED_JTAG_SW_MODE_TMS BIT(17)
++#define ASPEED_JTAG_SW_MODE_TDIO BIT(16)
++
++/* ASPEED_JTAG_TCK : TCK Control */
++#define ASPEED_JTAG_TCK_DIVISOR_MASK GENMASK(10, 0)
++#define ASPEED_JTAG_TCK_GET_DIV(x) ((x) & ASPEED_JTAG_TCK_DIVISOR_MASK)
++
++/* ASPEED_JTAG_EC : Controller set for go to IDLE */
++#define ASPEED_JTAG_EC_GO_IDLE BIT(0)
++
++#define ASPEED_JTAG_IOUT_LEN(len) \
++ (ASPEED_JTAG_CTL_ENG_EN | \
++ ASPEED_JTAG_CTL_ENG_OUT_EN | \
++ ASPEED_JTAG_CTL_INST_LEN(len))
++
++#define ASPEED_JTAG_DOUT_LEN(len) \
++ (ASPEED_JTAG_CTL_ENG_EN | \
++ ASPEED_JTAG_CTL_ENG_OUT_EN | \
++ ASPEED_JTAG_CTL_DATA_LEN(len))
++
++#define ASPEED_JTAG_TRANS_LEN(len) \
++ (ASPEED_JTAG_CTL_ENG_EN | \
++ ASPEED_JTAG_CTL_ENG_OUT_EN | \
++ ASPEED_JTAG_CTL_26XX_TRANS_LEN(len))
++
++#define ASPEED_JTAG_SW_TDIO (ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TDIO)
++
++#define ASPEED_JTAG_GET_TDI(direction, byte) \
++ (((direction) & JTAG_WRITE_XFER) ? byte : UINT_MAX)
++
++#define ASPEED_JTAG_TCK_WAIT 10
++#define ASPEED_JTAG_RESET_CNTR 10
++#define WAIT_ITERATIONS 75
++
++/* ASPEED JTAG HW MODE 2 (Only supported in AST26xx series) */
++#define ASPEED_JTAG_SHDATA0 0x20
++#define ASPEED_JTAG_SHDATA1 0x24
++#define ASPEED_JTAG_PADCTRL0 0x28
++#define ASPEED_JTAG_PADCTRL1 0x2C
++#define ASPEED_JTAG_SHCTRL 0x30
++#define ASPEED_JTAG_GBLCTRL 0x34
++#define ASPEED_JTAG_INTCTRL 0x38
++#define ASPEED_JTAG_STAT 0x3C
++
++/* ASPEED_JTAG_PADCTRLx : Padding control 0 and 1 */
++#define ASPEED_JTAG_PADCTRL_PAD_DATA BIT(24)
++#define ASPEED_JTAG_PADCTRL_POSTPAD(x) (((x) & GENMASK(8, 0)) << 12)
++#define ASPEED_JTAG_PADCTRL_PREPAD(x) (((x) & GENMASK(8, 0)) << 0)
++
++/* ASPEED_JTAG_SHCTRL: Shift Control */
++#define ASPEED_JTAG_SHCTRL_FRUN_TCK_EN BIT(31)
++#define ASPEED_JTAG_SHCTRL_STSHIFT_EN BIT(30)
++#define ASPEED_JTAG_SHCTRL_TMS(x) (((x) & GENMASK(13, 0)) << 16)
++#define ASPEED_JTAG_SHCTRL_POST_TMS(x) (((x) & GENMASK(3, 0)) << 13)
++#define ASPEED_JTAG_SHCTRL_PRE_TMS(x) (((x) & GENMASK(3, 0)) << 10)
++#define ASPEED_JTAG_SHCTRL_PAD_SEL0 (0)
++#define ASPEED_JTAG_SHCTRL_PAD_SEL1 BIT(9)
++#define ASPEED_JTAG_SHCTRL_END_SHIFT BIT(8)
++#define ASPEED_JTAG_SHCTRL_START_SHIFT BIT(7)
++#define ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(x) ((x) & GENMASK(6, 0))
++
++/* ASPEED_JTAG_GBLCTRL : Global Control */
++#define ASPEED_JTAG_GBLCTRL_ENG_MODE_EN BIT(31)
++#define ASPEED_JTAG_GBLCTRL_ENG_OUT_EN BIT(30)
++#define ASPEED_JTAG_GBLCTRL_FORCE_TMS BIT(29)
++#define ASPEED_JTAG_GBLCTRL_SHIFT_COMPLETE BIT(28)
++#define ASPEED_JTAG_GBLCTRL_RESET_FIFO BIT(25)
++#define ASPEED_JTAG_GBLCTRL_FIFO_MODE BIT(24)
++#define ASPEED_JTAG_GBLCTRL_UPDT_SHIFT(x) (((x) & GENMASK(3, 0)) << 20)
++#define ASPEED_JTAG_GBLCTRL_STSHIFT(x) (((x) & GENMASK(0, 0)) << 16)
++#define ASPEED_JTAG_GBLCTRL_TRST BIT(15)
++#define ASPEED_JTAG_CLK_DIVISOR_MASK GENMASK(11, 0)
++#define ASPEED_JTAG_CLK_GET_DIV(x) ((x) & ASPEED_JTAG_CLK_DIVISOR_MASK)
++
++/* ASPEED_JTAG_INTCTRL: Interrupt Control */
++#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN BIT(16)
++#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT BIT(0)
++
++/* ASPEED_JTAG_STAT: JTAG HW mode 2 status */
++#define ASPEED_JTAG_STAT_ENG_IDLE BIT(0)
++
++/*#define USE_INTERRUPTS*/
++#define DEBUG_JTAG
++
++static const char * const regnames[] = {
++ [ASPEED_JTAG_DATA] = "ASPEED_JTAG_DATA",
++ [ASPEED_JTAG_INST] = "ASPEED_JTAG_INST",
++ [ASPEED_JTAG_CTRL] = "ASPEED_JTAG_CTRL",
++ [ASPEED_JTAG_ISR] = "ASPEED_JTAG_ISR",
++ [ASPEED_JTAG_SW] = "ASPEED_JTAG_SW",
++ [ASPEED_JTAG_TCK] = "ASPEED_JTAG_TCK",
++ [ASPEED_JTAG_EC] = "ASPEED_JTAG_EC",
++ [ASPEED_JTAG_SHDATA0] = "ASPEED_JTAG_SHDATA0",
++ [ASPEED_JTAG_SHDATA1] = "ASPEED_JTAG_SHDATA1",
++ [ASPEED_JTAG_PADCTRL0] = "ASPEED_JTAG_PADCTRL0",
++ [ASPEED_JTAG_PADCTRL1] = "ASPEED_JTAG_PADCTRL1",
++ [ASPEED_JTAG_SHCTRL] = "ASPEED_JTAG_SHCTRL",
++ [ASPEED_JTAG_GBLCTRL] = "ASPEED_JTAG_GBLCTRL",
++ [ASPEED_JTAG_INTCTRL] = "ASPEED_JTAG_INTCTRL",
++ [ASPEED_JTAG_STAT] = "ASPEED_JTAG_STAT",
++};
++
++#define ASPEED_JTAG_NAME "jtag-aspeed"
++
++struct aspeed_jtag {
++ void __iomem *reg_base;
++ struct device *dev;
++ struct clk *pclk;
++ enum jtag_tapstate status;
++ int irq;
++ struct reset_control *rst;
++ u32 flag;
++ wait_queue_head_t jtag_wq;
++ u32 mode;
++ struct jtag_low_level_functions *llops;
++};
++
++/* Multi generation support is enabled by fops and low level assped function
++ * mapping using asped_jtag_functions struct as config mechanism.
++ */
++
++struct jtag_low_level_functions {
++ void (*output_disable)(struct aspeed_jtag *aspeed_jtag);
++ int (*xfer_push_data)(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type, u32 bits_len);
++ int (*xfer_push_data_last)(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type, u32 bits_len);
++};
++
++struct aspeed_jtag_functions {
++ struct jtag_ops *aspeed_jtag_ops;
++ struct jtag_low_level_functions *aspeed_jtag_llops;
++};
++
++/*
++ * This structure represents a TMS cycle, as expressed in a set of bits and a
++ * count of bits (note: there are no start->end state transitions that require
++ * more than 1 byte of TMS cycles)
++ */
++struct tms_cycle {
++ unsigned char tmsbits;
++ unsigned char count;
++};
++
++/*
++ * This is the complete set TMS cycles for going from any TAP state to any
++ * other TAP state, following a "shortest path" rule.
++ */
++static const struct tms_cycle _tms_cycle_lookup[][16] = {
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* TLR */{{0x00, 0}, {0x00, 1}, {0x02, 2}, {0x02, 3}, {0x02, 4}, {0x0a, 4},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x0a, 5}, {0x2a, 6}, {0x1a, 5}, {0x06, 3}, {0x06, 4}, {0x06, 5},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x16, 5}, {0x16, 6}, {0x56, 7}, {0x36, 6} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* RTI */{{0x07, 3}, {0x00, 0}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* SelDR*/{{0x03, 2}, {0x03, 3}, {0x00, 0}, {0x00, 1}, {0x00, 2}, {0x02, 2},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x02, 3}, {0x0a, 4}, {0x06, 3}, {0x01, 1}, {0x01, 2}, {0x01, 3},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x0d, 4} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* CapDR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x00, 0}, {0x00, 1}, {0x01, 1},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* SDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x00, 0}, {0x01, 1},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* Ex1DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x02, 3}, {0x00, 0},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x00, 1}, {0x02, 2}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* PDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x01, 2}, {0x05, 3},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x00, 0}, {0x01, 1}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* Ex2DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x00, 1}, {0x02, 2},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x02, 3}, {0x00, 0}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* UpdDR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x05, 4}, {0x15, 5}, {0x00, 0}, {0x03, 2}, {0x03, 3}, {0x03, 4},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* SelIR*/{{0x01, 1}, {0x01, 2}, {0x05, 3}, {0x05, 4}, {0x05, 5}, {0x15, 5},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x15, 6}, {0x55, 7}, {0x35, 6}, {0x00, 0}, {0x00, 1}, {0x00, 2},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x02, 2}, {0x02, 3}, {0x0a, 4}, {0x06, 3} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* CapIR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x00, 0}, {0x00, 1},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* SIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x00, 0},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* Ex1IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x02, 3},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x00, 0}, {0x00, 1}, {0x02, 2}, {0x01, 1} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* PIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x01, 2},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x05, 3}, {0x00, 0}, {0x01, 1}, {0x03, 2} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* Ex2IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x00, 1},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x02, 2}, {0x02, 3}, {0x00, 0}, {0x01, 1} },
++
++/* TLR RTI SelDR CapDR SDR Ex1DR*/
++/* UpdIR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3},
++/* PDR Ex2DR UpdDR SelIR CapIR SIR*/
++ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4},
++/* Ex1IR PIR Ex2IR UpdIR*/
++ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x00, 0} },
++};
++
++#ifdef DEBUG_JTAG
++static char *end_status_str[] = {
++ "tlr", "idle", "selDR", "capDR", "sDR", "ex1DR", "pDR", "ex2DR",
++ "updDR", "selIR", "capIR", "sIR", "ex1IR", "pIR", "ex2IR", "updIR"
++};
++#endif
++
++static u32 aspeed_jtag_read(struct aspeed_jtag *aspeed_jtag, u32 reg)
++{
++ u32 val = readl(aspeed_jtag->reg_base + reg);
++
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "read:%s val = 0x%08x\n", regnames[reg], val);
++#endif
++ return val;
++}
++
++static void
++aspeed_jtag_write(struct aspeed_jtag *aspeed_jtag, u32 val, u32 reg)
++{
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "write:%s val = 0x%08x\n",
++ regnames[reg], val);
++#endif
++ writel(val, aspeed_jtag->reg_base + reg);
++}
++
++static int aspeed_jtag_freq_set(struct jtag *jtag, u32 freq)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++ unsigned long apb_frq;
++ u32 tck_val;
++ u16 div;
++
++ apb_frq = clk_get_rate(aspeed_jtag->pclk);
++ if (!apb_frq)
++ return -ENOTSUPP;
++
++ div = (apb_frq - 1) / freq;
++ tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK);
++ aspeed_jtag_write(aspeed_jtag,
++ (tck_val & ~ASPEED_JTAG_TCK_DIVISOR_MASK) | div,
++ ASPEED_JTAG_TCK);
++ return 0;
++}
++
++static int aspeed_jtag_freq_get(struct jtag *jtag, u32 *frq)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++ u32 pclk;
++ u32 tck;
++
++ pclk = clk_get_rate(aspeed_jtag->pclk);
++ tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK);
++ *frq = pclk / (ASPEED_JTAG_TCK_GET_DIV(tck) + 1);
++
++ return 0;
++}
++
++static inline void aspeed_jtag_output_disable(struct aspeed_jtag *aspeed_jtag)
++{
++ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL);
++}
++
++static inline void aspeed_jtag_master(struct aspeed_jtag *aspeed_jtag)
++{
++ aspeed_jtag_write(aspeed_jtag, (ASPEED_JTAG_CTL_ENG_EN |
++ ASPEED_JTAG_CTL_ENG_OUT_EN),
++ ASPEED_JTAG_CTRL);
++
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
++ ASPEED_JTAG_SW_MODE_TDIO,
++ ASPEED_JTAG_SW);
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_ISR_INST_PAUSE |
++ ASPEED_JTAG_ISR_INST_COMPLETE |
++ ASPEED_JTAG_ISR_DATA_PAUSE |
++ ASPEED_JTAG_ISR_DATA_COMPLETE |
++ ASPEED_JTAG_ISR_INST_PAUSE_EN |
++ ASPEED_JTAG_ISR_INST_COMPLETE_EN |
++ ASPEED_JTAG_ISR_DATA_PAUSE_EN |
++ ASPEED_JTAG_ISR_DATA_COMPLETE_EN,
++ ASPEED_JTAG_ISR); /* Enable Interrupt */
++}
++
++static int aspeed_jtag_mode_set(struct jtag *jtag, struct jtag_mode *jtag_mode)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++ switch (jtag_mode->feature) {
++ case JTAG_XFER_MODE:
++ aspeed_jtag->mode = jtag_mode->mode;
++ break;
++ case JTAG_CONTROL_MODE:
++ if (jtag_mode->mode == JTAG_MASTER_OUTPUT_DISABLE)
++ aspeed_jtag_output_disable(aspeed_jtag);
++ else if (jtag_mode->mode == JTAG_MASTER_MODE)
++ aspeed_jtag_master(aspeed_jtag);
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static char aspeed_jtag_tck_cycle(struct aspeed_jtag *aspeed_jtag,
++ u8 tms, u8 tdi)
++{
++ char tdo = 0;
++
++ /* TCK = 0 */
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
++ (tms * ASPEED_JTAG_SW_MODE_TMS) |
++ (tdi * ASPEED_JTAG_SW_MODE_TDIO), ASPEED_JTAG_SW);
++
++ aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW);
++
++ /* TCK = 1 */
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_MODE_EN |
++ ASPEED_JTAG_SW_MODE_TCK |
++ (tms * ASPEED_JTAG_SW_MODE_TMS) |
++ (tdi * ASPEED_JTAG_SW_MODE_TDIO), ASPEED_JTAG_SW);
++
++ if (aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW) &
++ ASPEED_JTAG_SW_MODE_TDIO)
++ tdo = 1;
++
++ return tdo;
++}
++
++static int aspeed_jtag_bitbang(struct jtag *jtag,
++ struct bitbang_packet *bitbang,
++ struct tck_bitbang *bitbang_data)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++ int i = 0;
++
++ for (i = 0; i < bitbang->length; i++) {
++ bitbang_data[i].tdo =
++ aspeed_jtag_tck_cycle(aspeed_jtag, bitbang_data[i].tms,
++ bitbang_data[i].tdi);
++ }
++ return 0;
++}
++
++static int aspeed_jtag_wait_instruction_pause(struct aspeed_jtag *aspeed_jtag)
++{
++ int res = 0;
++#ifdef USE_INTERRUPTS
++ res = wait_event_interruptible(aspeed_jtag->jtag_wq,
++ aspeed_jtag->flag &
++ ASPEED_JTAG_ISR_INST_PAUSE);
++ aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_INST_PAUSE;
++#else
++ u32 status = 0;
++ u32 iterations = 0;
++
++ while ((status & ASPEED_JTAG_ISR_INST_PAUSE) == 0) {
++ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status);
++#endif
++ iterations++;
++ if (iterations > WAIT_ITERATIONS) {
++ dev_err(aspeed_jtag->dev,
++ "aspeed_jtag driver timed out waiting for instruction pause complete\n");
++ res = -EFAULT;
++ break;
++ }
++ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) {
++ if (iterations % 25 == 0)
++ usleep_range(1, 5);
++ else
++ udelay(1);
++ }
++ }
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_ISR_INST_PAUSE |
++ (status & 0xf),
++ ASPEED_JTAG_ISR);
++#endif
++ return res;
++}
++
++static int
++aspeed_jtag_wait_instruction_complete(struct aspeed_jtag *aspeed_jtag)
++{
++ int res = 0;
++#ifdef USE_INTERRUPTS
++ res = wait_event_interruptible(aspeed_jtag->jtag_wq,
++ aspeed_jtag->flag &
++ ASPEED_JTAG_ISR_INST_COMPLETE);
++ aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_INST_COMPLETE;
++#else
++ u32 status = 0;
++ u32 iterations = 0;
++
++ while ((status & ASPEED_JTAG_ISR_INST_COMPLETE) == 0) {
++ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status);
++#endif
++ iterations++;
++ if (iterations > WAIT_ITERATIONS) {
++ dev_err(aspeed_jtag->dev,
++ "aspeed_jtag driver timed out waiting for instruction complete\n");
++ res = -EFAULT;
++ break;
++ }
++ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) {
++ if (iterations % 25 == 0)
++ usleep_range(1, 5);
++ else
++ udelay(1);
++ }
++ }
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_ISR_INST_COMPLETE |
++ (status & 0xf),
++ ASPEED_JTAG_ISR);
++#endif
++ return res;
++}
++
++static int
++aspeed_jtag_wait_data_pause_complete(struct aspeed_jtag *aspeed_jtag)
++{
++ int res = 0;
++#ifdef USE_INTERRUPTS
++ res = wait_event_interruptible(aspeed_jtag->jtag_wq,
++ aspeed_jtag->flag &
++ ASPEED_JTAG_ISR_DATA_PAUSE);
++ aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_DATA_PAUSE;
++#else
++ u32 status = 0;
++ u32 iterations = 0;
++
++ while ((status & ASPEED_JTAG_ISR_DATA_PAUSE) == 0) {
++ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status);
++#endif
++ iterations++;
++ if (iterations > WAIT_ITERATIONS) {
++ dev_err(aspeed_jtag->dev,
++ "aspeed_jtag driver timed out waiting for data pause complete\n");
++ res = -EFAULT;
++ break;
++ }
++ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) {
++ if (iterations % 25 == 0)
++ usleep_range(1, 5);
++ else
++ udelay(1);
++ }
++ }
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_ISR_DATA_PAUSE |
++ (status & 0xf), ASPEED_JTAG_ISR);
++#endif
++ return res;
++}
++
++static int aspeed_jtag_wait_data_complete(struct aspeed_jtag *aspeed_jtag)
++{
++ int res = 0;
++#ifdef USE_INTERRUPTS
++ res = wait_event_interruptible(aspeed_jtag->jtag_wq,
++ aspeed_jtag->flag &
++ ASPEED_JTAG_ISR_DATA_COMPLETE);
++ aspeed_jtag->flag &= ~ASPEED_JTAG_ISR_DATA_COMPLETE;
++#else
++ u32 status = 0;
++ u32 iterations = 0;
++
++ while ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) {
++ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status);
++#endif
++ iterations++;
++ if (iterations > WAIT_ITERATIONS) {
++ dev_err(aspeed_jtag->dev,
++ "ast_jtag driver timed out waiting for data complete\n");
++ res = -EFAULT;
++ break;
++ }
++ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) {
++ if (iterations % 25 == 0)
++ usleep_range(1, 5);
++ else
++ udelay(1);
++ }
++ }
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_ISR_DATA_COMPLETE | (status & 0xf),
++ ASPEED_JTAG_ISR);
++#endif
++ return res;
++}
++
++static void aspeed_jtag_set_tap_state(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_tapstate from_state,
++ enum jtag_tapstate end_state)
++{
++ int i = 0;
++ enum jtag_tapstate from, to;
++
++ from = from_state;
++ to = end_state;
++
++ if (from == JTAG_STATE_CURRENT)
++ from = aspeed_jtag->status;
++
++ for (i = 0; i < _tms_cycle_lookup[from][to].count; i++)
++ aspeed_jtag_tck_cycle(aspeed_jtag,
++ ((_tms_cycle_lookup[from][to].tmsbits >> i) & 0x1), 0);
++ aspeed_jtag->status = end_state;
++}
++
++static void aspeed_jtag_set_tap_state_sw(struct aspeed_jtag *aspeed_jtag,
++ struct jtag_tap_state *tapstate)
++{
++ /* SW mode from curent tap state -> to end_state */
++ if (tapstate->reset) {
++ int i = 0;
++
++ for (i = 0; i < ASPEED_JTAG_RESET_CNTR; i++)
++ aspeed_jtag_tck_cycle(aspeed_jtag, 1, 0);
++ aspeed_jtag->status = JTAG_STATE_TLRESET;
++ }
++
++ aspeed_jtag_set_tap_state(aspeed_jtag, tapstate->from,
++ tapstate->endstate);
++}
++
++static int aspeed_jtag_status_set(struct jtag *jtag,
++ struct jtag_tap_state *tapstate)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "Set TAP state: %s\n",
++ end_status_str[tapstate->endstate]);
++#endif
++
++ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) {
++ aspeed_jtag_set_tap_state_sw(aspeed_jtag, tapstate);
++ return 0;
++ }
++
++ /* x TMS high + 1 TMS low */
++ if (tapstate->reset) {
++ /* Disable sw mode */
++ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW);
++ mdelay(1);
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_CTL_ENG_EN |
++ ASPEED_JTAG_CTL_ENG_OUT_EN |
++ ASPEED_JTAG_CTL_FORCE_TMS, ASPEED_JTAG_CTRL);
++ mdelay(1);
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_SW_TDIO, ASPEED_JTAG_SW);
++ aspeed_jtag->status = JTAG_STATE_TLRESET;
++ }
++
++ return 0;
++}
++
++static void aspeed_jtag_xfer_sw(struct aspeed_jtag *aspeed_jtag,
++ struct jtag_xfer *xfer, u32 *data)
++{
++ unsigned long remain_xfer = xfer->length;
++ unsigned long shift_bits = 0;
++ unsigned long index = 0;
++ unsigned long tdi;
++ char tdo;
++
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "SW JTAG SHIFT %s, length = %d\n",
++ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length);
++#endif
++
++ if (xfer->type == JTAG_SIR_XFER)
++ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from,
++ JTAG_STATE_SHIFTIR);
++ else
++ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from,
++ JTAG_STATE_SHIFTDR);
++
++ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]);
++ data[index] = 0;
++ while (remain_xfer > 1) {
++ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0,
++ tdi & ASPEED_JTAG_DATA_MSB);
++ data[index] |= tdo << (shift_bits %
++ ASPEED_JTAG_DATA_CHUNK_SIZE);
++ tdi >>= 1;
++ shift_bits++;
++ remain_xfer--;
++
++ if (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE == 0) {
++ tdo = 0;
++ index++;
++ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]);
++ data[index] = 0;
++ }
++ }
++
++ if ((xfer->endstate == (xfer->type == JTAG_SIR_XFER ?
++ JTAG_STATE_SHIFTIR : JTAG_STATE_SHIFTDR))) {
++ /* Stay in Shift IR/DR*/
++ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0,
++ tdi & ASPEED_JTAG_DATA_MSB);
++ data[index] |= tdo << (shift_bits %
++ ASPEED_JTAG_DATA_CHUNK_SIZE);
++ } else {
++ /* Goto end state */
++ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 1,
++ tdi & ASPEED_JTAG_DATA_MSB);
++ data[index] |= tdo << (shift_bits %
++ ASPEED_JTAG_DATA_CHUNK_SIZE);
++ aspeed_jtag->status = (xfer->type == JTAG_SIR_XFER) ?
++ JTAG_STATE_EXIT1IR : JTAG_STATE_EXIT1DR;
++ aspeed_jtag_set_tap_state(aspeed_jtag, aspeed_jtag->status,
++ xfer->endstate);
++ }
++}
++
++static int aspeed_jtag_xfer_push_data_26xx(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type, u32 bits_len)
++{
++ int res = 0;
++
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(bits_len),
++ ASPEED_JTAG_CTRL);
++ if (type == JTAG_SIR_XFER) {
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(bits_len) |
++ ASPEED_JTAG_CTL_26XX_INST_EN,
++ ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_instruction_pause(aspeed_jtag);
++ } else {
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(bits_len) |
++ ASPEED_JTAG_CTL_DATA_EN, ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_data_pause_complete(aspeed_jtag);
++ }
++ return res;
++}
++
++static int aspeed_jtag_xfer_push_data(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type, u32 bits_len)
++{
++ int res = 0;
++
++ if (type == JTAG_SIR_XFER) {
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_IOUT_LEN(bits_len),
++ ASPEED_JTAG_CTRL);
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_IOUT_LEN(bits_len) |
++ ASPEED_JTAG_CTL_INST_EN, ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_instruction_pause(aspeed_jtag);
++ } else {
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len),
++ ASPEED_JTAG_CTRL);
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len) |
++ ASPEED_JTAG_CTL_DATA_EN, ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_data_pause_complete(aspeed_jtag);
++ }
++ return res;
++}
++
++static int aspeed_jtag_xfer_push_data_last_26xx(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type,
++ u32 shift_bits)
++{
++ int res = 0;
++
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS, ASPEED_JTAG_CTRL);
++ if (type == JTAG_SIR_XFER) {
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_TRANS_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS |
++ ASPEED_JTAG_CTL_26XX_INST_EN,
++ ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_instruction_complete(aspeed_jtag);
++ } else {
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_TRANS_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS |
++ ASPEED_JTAG_CTL_DATA_EN,
++ ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_data_complete(aspeed_jtag);
++ }
++ return res;
++}
++
++static int aspeed_jtag_xfer_push_data_last(struct aspeed_jtag *aspeed_jtag,
++ enum jtag_xfer_type type,
++ u32 shift_bits)
++{
++ int res = 0;
++
++ if (type == JTAG_SIR_XFER) {
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_IOUT_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_LASPEED_INST,
++ ASPEED_JTAG_CTRL);
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_IOUT_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_LASPEED_INST |
++ ASPEED_JTAG_CTL_INST_EN,
++ ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_instruction_complete(aspeed_jtag);
++ } else {
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_DOUT_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_LASPEED_DATA,
++ ASPEED_JTAG_CTRL);
++ aspeed_jtag_write(aspeed_jtag,
++ ASPEED_JTAG_DOUT_LEN(shift_bits) |
++ ASPEED_JTAG_CTL_LASPEED_DATA |
++ ASPEED_JTAG_CTL_DATA_EN,
++ ASPEED_JTAG_CTRL);
++ res = aspeed_jtag_wait_data_complete(aspeed_jtag);
++ }
++ return res;
++}
++
++static int aspeed_jtag_xfer_hw(struct aspeed_jtag *aspeed_jtag,
++ struct jtag_xfer *xfer, u32 *data)
++{
++ unsigned long remain_xfer = xfer->length;
++ unsigned long index = 0;
++ char shift_bits;
++ u32 data_reg;
++ u32 scan_end;
++
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev, "HW JTAG SHIFT %s, length = %d\n",
++ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length);
++#endif
++ data_reg = xfer->type == JTAG_SIR_XFER ?
++ ASPEED_JTAG_INST : ASPEED_JTAG_DATA;
++ if (xfer->endstate == JTAG_STATE_SHIFTIR ||
++ xfer->endstate == JTAG_STATE_SHIFTDR ||
++ xfer->endstate == JTAG_STATE_PAUSEIR ||
++ xfer->endstate == JTAG_STATE_PAUSEDR) {
++ scan_end = 0;
++ } else {
++ scan_end = 1;
++ }
++
++ while (remain_xfer) {
++ if (xfer->direction & JTAG_WRITE_XFER)
++ aspeed_jtag_write(aspeed_jtag, data[index], data_reg);
++ else
++ aspeed_jtag_write(aspeed_jtag, 0, data_reg);
++
++ if (remain_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) {
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev,
++ "Chunk len=%d chunk_size=%d remain_xfer=%lu\n",
++ xfer->length, ASPEED_JTAG_DATA_CHUNK_SIZE,
++ remain_xfer);
++#endif
++ shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE;
++
++ /*
++ * Transmit bytes that were not equals to column length
++ * and after the transfer go to Pause IR/DR.
++ */
++ if (aspeed_jtag->llops->xfer_push_data(aspeed_jtag,
++ xfer->type, shift_bits) != 0) {
++ return -EFAULT;
++ }
++ } else {
++ /*
++ * Read bytes equals to column length
++ */
++ shift_bits = remain_xfer;
++ if (scan_end) {
++ /*
++ * If this data is the end of the transmission
++ * send remaining bits and go to endstate
++ */
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev,
++ "Last len=%d chunk_size=%d remain_xfer=%lu\n",
++ xfer->length,
++ ASPEED_JTAG_DATA_CHUNK_SIZE,
++ remain_xfer);
++#endif
++ if (aspeed_jtag->llops->xfer_push_data_last(
++ aspeed_jtag,
++ xfer->type,
++ shift_bits) != 0) {
++ return -EFAULT;
++ }
++ } else {
++ /*
++ * If transmission is waiting for additional
++ * data send remaining bits and then go to
++ * Pause IR/DR.
++ */
++#ifdef DEBUG_JTAG
++ dev_dbg(aspeed_jtag->dev,
++ "Tail len=%d chunk_size=%d remain_xfer=%lu\n",
++ xfer->length,
++ ASPEED_JTAG_DATA_CHUNK_SIZE,
++ remain_xfer);
++#endif
++ if (aspeed_jtag->llops->xfer_push_data(
++ aspeed_jtag,
++ xfer->type,
++ shift_bits)
++ != 0) {
++ return -EFAULT;
++ }
++ }
++ }
++
++ if (xfer->direction & JTAG_READ_XFER) {
++ if (shift_bits < ASPEED_JTAG_DATA_CHUNK_SIZE) {
++ data[index] = aspeed_jtag_read(aspeed_jtag,
++ data_reg);
++
++ data[index] >>= ASPEED_JTAG_DATA_CHUNK_SIZE -
++ shift_bits;
++ } else {
++ data[index] = aspeed_jtag_read(aspeed_jtag,
++ data_reg);
++ }
++ }
++
++ remain_xfer = remain_xfer - shift_bits;
++ index++;
++ }
++ return 0;
++}
++
++static int aspeed_jtag_xfer(struct jtag *jtag, struct jtag_xfer *xfer,
++ u8 *xfer_data)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) {
++ /* SW mode */
++ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_TDIO,
++ ASPEED_JTAG_SW);
++
++ aspeed_jtag_xfer_sw(aspeed_jtag, xfer, (u32 *)xfer_data);
++ } else {
++ /* HW mode */
++ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW);
++ if (aspeed_jtag_xfer_hw(aspeed_jtag, xfer,
++ (u32 *)xfer_data) != 0)
++ return -EFAULT;
++ }
++
++ aspeed_jtag->status = xfer->endstate;
++ return 0;
++}
++
++static int aspeed_jtag_status_get(struct jtag *jtag, u32 *status)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++ *status = aspeed_jtag->status;
++ return 0;
++}
++
++#ifdef USE_INTERRUPTS
++static irqreturn_t aspeed_jtag_interrupt(s32 this_irq, void *dev_id)
++{
++ struct aspeed_jtag *aspeed_jtag = dev_id;
++ irqreturn_t ret = IRQ_HANDLED;
++ u32 status;
++
++ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR);
++
++ if (status & ASPEED_JTAG_ISR_INT_MASK) {
++ aspeed_jtag_write(aspeed_jtag,
++ (status & ASPEED_JTAG_ISR_INT_MASK)
++ | (status & ASPEED_JTAG_ISR_INT_EN_MASK),
++ ASPEED_JTAG_ISR);
++ aspeed_jtag->flag |= status & ASPEED_JTAG_ISR_INT_MASK;
++ }
++
++ if (aspeed_jtag->flag) {
++ wake_up_interruptible(&aspeed_jtag->jtag_wq);
++ ret = IRQ_HANDLED;
++ } else {
++ dev_err(aspeed_jtag->dev, "irq status:%x\n",
++ status);
++ ret = IRQ_NONE;
++ }
++ return ret;
++}
++#endif
++
++static int aspeed_jtag_enable(struct jtag *jtag)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++ aspeed_jtag_master(aspeed_jtag);
++ return 0;
++}
++
++static int aspeed_jtag_disable(struct jtag *jtag)
++{
++ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
++
++ aspeed_jtag_output_disable(aspeed_jtag);
++ return 0;
++}
++
++static int aspeed_jtag_init(struct platform_device *pdev,
++ struct aspeed_jtag *aspeed_jtag)
++{
++ struct resource *res;
++#ifdef USE_INTERRUPTS
++ int err;
++#endif
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ aspeed_jtag->reg_base = devm_ioremap_resource(aspeed_jtag->dev, res);
++ if (IS_ERR(aspeed_jtag->reg_base))
++ return -ENOMEM;
++
++ aspeed_jtag->pclk = devm_clk_get(aspeed_jtag->dev, NULL);
++ if (IS_ERR(aspeed_jtag->pclk)) {
++ dev_err(aspeed_jtag->dev, "devm_clk_get failed\n");
++ return PTR_ERR(aspeed_jtag->pclk);
++ }
++
++#ifdef USE_INTERRUPTS
++ aspeed_jtag->irq = platform_get_irq(pdev, 0);
++ if (aspeed_jtag->irq < 0) {
++ dev_err(aspeed_jtag->dev, "no irq specified\n");
++ return -ENOENT;
++ }
++#endif
++
++ if (clk_prepare_enable(aspeed_jtag->pclk)) {
++ dev_err(aspeed_jtag->dev, "no irq specified\n");
++ return -ENOENT;
++ }
++
++ aspeed_jtag->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
++ if (IS_ERR(aspeed_jtag->rst)) {
++ dev_err(aspeed_jtag->dev,
++ "missing or invalid reset controller device tree entry");
++ return PTR_ERR(aspeed_jtag->rst);
++ }
++ reset_control_deassert(aspeed_jtag->rst);
++
++#ifdef USE_INTERRUPTS
++ err = devm_request_irq(aspeed_jtag->dev, aspeed_jtag->irq,
++ aspeed_jtag_interrupt, 0,
++ "aspeed-jtag", aspeed_jtag);
++ if (err) {
++ dev_err(aspeed_jtag->dev, "unable to get IRQ");
++ clk_disable_unprepare(aspeed_jtag->pclk);
++ return err;
++ }
++#endif
++
++ aspeed_jtag_output_disable(aspeed_jtag);
++
++ aspeed_jtag->flag = 0;
++ aspeed_jtag->mode = 0;
++ init_waitqueue_head(&aspeed_jtag->jtag_wq);
++ return 0;
++}
++
++static int aspeed_jtag_deinit(struct platform_device *pdev,
++ struct aspeed_jtag *aspeed_jtag)
++{
++ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_ISR);
++ /* Disable clock */
++ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL);
++ reset_control_assert(aspeed_jtag->rst);
++ clk_disable_unprepare(aspeed_jtag->pclk);
++ return 0;
++}
++
++static const struct jtag_ops aspeed_jtag_ops = {
++ .freq_get = aspeed_jtag_freq_get,
++ .freq_set = aspeed_jtag_freq_set,
++ .status_get = aspeed_jtag_status_get,
++ .status_set = aspeed_jtag_status_set,
++ .xfer = aspeed_jtag_xfer,
++ .mode_set = aspeed_jtag_mode_set,
++ .bitbang = aspeed_jtag_bitbang,
++ .enable = aspeed_jtag_enable,
++ .disable = aspeed_jtag_disable
++};
++
++static const struct jtag_low_level_functions ast25xx_llops = {
++ .output_disable = aspeed_jtag_output_disable,
++ .xfer_push_data = aspeed_jtag_xfer_push_data,
++ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last
++};
++
++static struct aspeed_jtag_functions ast25xx_functions = {
++ .aspeed_jtag_ops = &aspeed_jtag_ops,
++ .aspeed_jtag_llops = &ast25xx_llops
++};
++
++static const struct jtag_low_level_functions ast26xx_llops = {
++ .output_disable = aspeed_jtag_output_disable,
++ .xfer_push_data = aspeed_jtag_xfer_push_data_26xx,
++ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last_26xx
++};
++
++static struct aspeed_jtag_functions ast26xx_functions = {
++ .aspeed_jtag_ops = &aspeed_jtag_ops,
++ .aspeed_jtag_llops = &ast26xx_llops
++};
++
++static const struct of_device_id aspeed_jtag_of_match[] = {
++ { .compatible = "aspeed,ast2400-jtag", .data = &ast25xx_functions },
++ { .compatible = "aspeed,ast2500-jtag", .data = &ast25xx_functions },
++ { .compatible = "aspeed,ast2600-jtag", .data = &ast26xx_functions },
++ {}
++};
++
++static int aspeed_jtag_probe(struct platform_device *pdev)
++{
++ struct aspeed_jtag *aspeed_jtag;
++ struct jtag *jtag;
++ const struct of_device_id *match;
++ struct aspeed_jtag_functions *jtag_functions;
++ int err;
++
++ match = of_match_node(aspeed_jtag_of_match, pdev->dev.of_node);
++ if (!match)
++ return -ENODEV;
++ jtag_functions = match->data;
++
++ jtag = jtag_alloc(&pdev->dev, sizeof(*aspeed_jtag),
++ jtag_functions->aspeed_jtag_ops);
++ if (!jtag)
++ return -ENOMEM;
++
++ platform_set_drvdata(pdev, jtag);
++ aspeed_jtag = jtag_priv(jtag);
++ aspeed_jtag->dev = &pdev->dev;
++
++ aspeed_jtag->llops = jtag_functions->aspeed_jtag_llops;
++
++ /* Initialize device*/
++ err = aspeed_jtag_init(pdev, aspeed_jtag);
++ if (err)
++ goto err_jtag_init;
++
++ /* Initialize JTAG core structure*/
++ err = devm_jtag_register(aspeed_jtag->dev, jtag);
++ if (err)
++ goto err_jtag_register;
++
++ return 0;
++
++err_jtag_register:
++ aspeed_jtag_deinit(pdev, aspeed_jtag);
++err_jtag_init:
++ jtag_free(jtag);
++ return err;
++}
++
++static int aspeed_jtag_remove(struct platform_device *pdev)
++{
++ struct jtag *jtag = platform_get_drvdata(pdev);
++
++ aspeed_jtag_deinit(pdev, jtag_priv(jtag));
++ return 0;
++}
++
++static struct platform_driver aspeed_jtag_driver = {
++ .probe = aspeed_jtag_probe,
++ .remove = aspeed_jtag_remove,
++ .driver = {
++ .name = ASPEED_JTAG_NAME,
++ .of_match_table = aspeed_jtag_of_match,
++ },
++};
++module_platform_driver(aspeed_jtag_driver);
++
++MODULE_AUTHOR("Oleksandr Shamray <oleksandrs@mellanox.com>");
++MODULE_DESCRIPTION("ASPEED JTAG driver");
++MODULE_LICENSE("GPL v2");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch
new file mode 100644
index 000000000..12073da02
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch
@@ -0,0 +1,107 @@
+From 2a22feac440070b7feaf0a6fe7e7e555d57ca19b Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Wed, 10 Mar 2019 11:45:04 -0800
+Subject: [PATCH] Documentation: jtag: Add bindings for Aspeed SoC
+
+It has been tested on Mellanox system with BMC equipped with
+Aspeed 2520 SoC for programming CPLD devices.
+
+It also has been tested on Intel systems with BMC equipped with
+Aspeed 25x0 SoC for JTAG board communication.
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Jiri Pirko <jiri@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Joel Stanley <joel@jms.id.au>
+Cc: Andrew Jeffery <andrew@aj.id.au>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+v28->v29
+v27->v28
+v26->v27
+v25->v26
+v24->v25
+v23->v24
+v22->v23
+v21->v22
+v20->v21
+v19->v20
+v18->v19
+
+v17->v18
+v16->v17
+v15->v16
+Comments pointed by Joel Stanley <joel.stan@gmail.com>
+- change clocks = <&clk_apb> to proper clocks = <&syscon ASPEED_CLK_APB>
+- add reset descriptions in bindings file
+
+v14->v15
+v13->v14
+v12->v13
+v11->v12
+v10->v11
+v9->v10
+v8->v9
+v7->v8
+Comments pointed by pointed by Joel Stanley <joel.stan@gmail.com>
+- Change compatible string to ast2400 and ast2000
+
+V6->v7
+Comments pointed by Tobias Klauser <tklauser@distanz.ch>
+ - Fix spell "Doccumentation" -> "Documentation"
+
+v5->v6
+Comments pointed by Tobias Klauser <tklauser@distanz.ch>
+- Small nit: s/documentation/Documentation/
+
+v4->v5
+
+V3->v4
+Comments pointed by Rob Herring <robh@kernel.org>
+- delete unnecessary "status" and "reg-shift" descriptions in
+ bindings file
+
+v2->v3
+Comments pointed by Rob Herring <robh@kernel.org>
+- split Aspeed jtag driver and binding to separate patches
+- delete unnecessary "status" and "reg-shift" descriptions in
+ bindings file
+---
+ .../devicetree/bindings/jtag/aspeed-jtag.txt | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/jtag/aspeed-jtag.txt
+
+diff --git a/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt b/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt
+new file mode 100644
+index 0000000..7c36eb6
+--- /dev/null
++++ b/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt
+@@ -0,0 +1,22 @@
++Aspeed JTAG driver for ast2400 and ast2500 SoC
++
++Required properties:
++- compatible: Should be one of
++ - "aspeed,ast2400-jtag"
++ - "aspeed,ast2500-jtag"
++- reg contains the offset and length of the JTAG memory
++ region
++- clocks root clock of bus, should reference the APB
++ clock in the second cell
++- resets phandle to reset controller with the reset number in
++ the second cell
++- interrupts should contain JTAG controller interrupt
++
++Example:
++jtag: jtag@1e6e4000 {
++ compatible = "aspeed,ast2500-jtag";
++ reg = <0x1e6e4000 0x1c>;
++ clocks = <&syscon ASPEED_CLK_APB>;
++ resets = <&syscon ASPEED_RESET_JTAG_MASTER>;
++ interrupts = <43>;
++};
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch
new file mode 100644
index 000000000..1e4142035
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch
@@ -0,0 +1,310 @@
+From d4c55bd4eeb6d9290025fa353d1787f18bca6ade Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Sun, 10 Mar 2019 11:47:40 -0800
+Subject: [PATCH v29 4/6] Documentation: jtag: Add ABI documentation
+
+Added document that describe the ABI for JTAG class driver
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Jiri Pirko <jiri@mellanox.com>
+Cc: Vadim Pasternak <vadimp@mellanox.com>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+v28->v29
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Expand bitbang function to accept multiples bitbang operations within a
+ single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS
+ values and it is expected that driver fills TDO fields with its
+ corresponding output value for every transaction.
+
+v27->v28
+Comments pointed by Steven Filary <steven.a.filary@intel.com>
+- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC
+ end states in SW mode using a lookup table to navigate across states.
+- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER).
+- Support for switching JTAG controller mode between slave and master
+ mode.
+- Setup JTAG controller mode to master only when the driver is opened,
+ letting other HW to own the JTAG bus when it isn't in use.
+- Include JTAG bit bang IOCTL for low level JTAG control usage
+ (JTAG_IOCBITBANG).
+
+v26->v27
+v25->v26
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- fix spell in ABI documentation
+
+v24->v25
+Comments pointed by Greg KH <gregkh@linuxfoundation.org>
+- Fixed documentation according to new open() behavior
+
+v23->v24
+v22->v23
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- fix spell in ABI doccumentation
+
+v21->v22
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- fix spell in ABI doccumentation
+
+v20->v21
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- Fix JTAG dirver help in Kconfig
+
+v19->v20
+Comments pointed by Randy Dunlap <rdunlap@infradead.org>
+- Fix JTAG doccumentation
+
+v18->v19
+Pavel Machek <pavel@ucw.cz>
+- Added JTAG doccumentation to Documentation/jtag
+
+v17->v18
+v16->v17
+v15->v16
+v14->v15
+v13->v14
+v12->v13
+v11->v12 Tobias Klauser <tklauser@distanz.ch>
+Comments pointed by
+- rename /Documentation/ABI/testing/jatg-dev -> jtag-dev
+- Typo: s/interfase/interface
+v10->v11
+v9->v10
+Fixes added by Oleksandr:
+- change jtag-cdev to jtag-dev in documentation
+- update KernelVersion and Date in jtag-dev documentation;
+v8->v9
+v7->v8
+v6->v7
+Comments pointed by Pavel Machek <pavel@ucw.cz>
+- Added jtag-cdev documentation to Documentation/ABI/testing folder
+---
+ Documentation/ABI/testing/jtag-dev | 23 ++++++
+ Documentation/jtag/overview | 27 +++++++
+ Documentation/jtag/transactions | 145 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 195 insertions(+)
+ create mode 100644 Documentation/ABI/testing/jtag-dev
+ create mode 100644 Documentation/jtag/overview
+ create mode 100644 Documentation/jtag/transactions
+
+diff --git a/Documentation/ABI/testing/jtag-dev b/Documentation/ABI/testing/jtag-dev
+new file mode 100644
+index 000000000000..423baab18761
+--- /dev/null
++++ b/Documentation/ABI/testing/jtag-dev
+@@ -0,0 +1,23 @@
++What: /dev/jtag[0-9]+
++Date: July 2018
++KernelVersion: 4.20
++Contact: oleksandrs@mellanox.com
++Description:
++ The misc device files /dev/jtag* are the interface
++ between JTAG master interface and userspace.
++
++ The ioctl(2)-based ABI is defined and documented in
++ [include/uapi]<linux/jtag.h>.
++
++ The following file operations are supported:
++
++ open(2)
++ Opens and allocates file descriptor.
++
++ ioctl(2)
++ Initiate various actions.
++ See the inline documentation in [include/uapi]<linux/jtag.h>
++ for descriptions of all ioctls.
++
++Users:
++ userspace tools which wants to access to JTAG bus
+diff --git a/Documentation/jtag/overview b/Documentation/jtag/overview
+new file mode 100644
+index 000000000000..6a5ec335e313
+--- /dev/null
++++ b/Documentation/jtag/overview
+@@ -0,0 +1,27 @@
++Linux kernel JTAG support
++=========================
++
++JTAG is an industry standard for verifying hardware. JTAG provides access to
++many logic signals of a complex integrated circuit, including the device pins.
++
++A JTAG interface is a special interface added to a chip.
++Depending on the version of JTAG, two, four, or five pins are added.
++
++The connector pins are:
++ TDI (Test Data In)
++ TDO (Test Data Out)
++ TCK (Test Clock)
++ TMS (Test Mode Select)
++ TRST (Test Reset) optional
++
++JTAG interface is designed to have two parts - basic core driver and
++hardware specific driver. The basic driver introduces a general interface
++which is not dependent of specific hardware. It provides communication
++between user space and hardware specific driver.
++Each JTAG device is represented as a char device from (jtag0, jtag1, ...).
++Access to a JTAG device is performed through IOCTL calls.
++
++Call flow example:
++User: open -> /dev/jatgX -> JTAG core driver -> JTAG hardware specific driver
++User: ioctl -> /dev/jtagX -> JTAG core driver -> JTAG hardware specific driver
++User: close -> /dev/jatgX -> JTAG core driver -> JTAG hardware specific driver
+diff --git a/Documentation/jtag/transactions b/Documentation/jtag/transactions
+new file mode 100644
+index 000000000000..f5d4a1ded6cf
+--- /dev/null
++++ b/Documentation/jtag/transactions
+@@ -0,0 +1,145 @@
++The JTAG API
++=============
++
++JTAG master devices can be accessed through a character misc-device.
++Each JTAG master interface can be accessed by using /dev/jtagN.
++
++JTAG system calls set:
++- SIR (Scan Instruction Register, IEEE 1149.1 Instruction Register scan);
++- SDR (Scan Data Register, IEEE 1149.1 Data Register scan);
++- RUNTEST (Forces the IEEE 1149.1 bus to a run state for a specified
++number of clocks.
++
++open(), close()
++-------
++open() opens JTAG device.
++
++Open/Close device:
++- jtag_fd = open("/dev/jtag0", O_RDWR);
++- close(jtag_fd);
++
++ioctl()
++-------
++All access operations to JTAG devices are performed through ioctl interface.
++The IOCTL interface supports these requests:
++ JTAG_SIOCSTATE - Force JTAG state machine to go into a TAPC state
++ JTAG_SIOCFREQ - Set JTAG TCK frequency
++ JTAG_GIOCFREQ - Get JTAG TCK frequency
++ JTAG_IOCXFER - send/receive JTAG data Xfer
++ JTAG_GIOCSTATUS - get current JTAG TAP state
++ JTAG_SIOCMODE - set JTAG mode flags.
++ JTAG_IOCBITBANG - JTAG bitbang low level control.
++
++JTAG_SIOCFREQ, JTAG_GIOCFREQ
++------
++Set/Get JTAG clock speed:
++
++ unsigned int jtag_fd;
++ ioctl(jtag_fd, JTAG_SIOCFREQ, &frq);
++ ioctl(jtag_fd, JTAG_GIOCFREQ, &frq);
++
++JTAG_SIOCSTATE
++------
++Force JTAG state machine to go into a TAPC state
++
++struct jtag_tap_state {
++ __u8 reset;
++ __u8 from;
++ __u8 endstate;
++ __u8 tck;
++};
++
++reset:
++ JTAG_NO_RESET - go through selected endstate from current state
++ JTAG_FORCE_RESET - go through TEST_LOGIC/RESET state before selected endstate
++endstate: completion flag
++tck: clock counter
++
++Example:
++ struct jtag_tap_state tap_state;
++
++ tap_state.from = JTAG_STATE_TLRESET;
++ tap_state.endstate = JTAG_STATE_IDLE;
++ tap_state.reset = 0;
++ tap_state.tck = data_p->tck;
++ usleep(25 * 1000);
++ ioctl(jtag_fd, JTAG_SIOCSTATE, &tap_state);
++
++JTAG_GIOCSTATUS
++------
++Get JTAG TAPC machine state
++
++ unsigned int jtag_fd;
++ jtag_tapstate tapstate;
++ ioctl(jtag_fd, JTAG_GIOCSTATUS, &tapstate);
++
++JTAG_IOCXFER
++------
++Send SDR/SIR transaction
++
++struct jtag_xfer {
++ __u8 type;
++ __u8 direction;
++ __u8 from;
++ __u8 endstate;
++ __u8 padding;
++ __u32 length;
++ __u64 tdio;
++};
++
++type: transfer type - JTAG_SIR_XFER/JTAG_SDR_XFER
++direction: xfer direction - JTAG_READ_XFER/JTAG_WRITE_XFER/JTAG_READ_WRITE_XFER
++length: xfer data length in bits
++tdio : xfer data array
++from: xfer from state can be current JTAG tap state saved by the driver
++ JTAG_STATE_CURRENT or in a multichain environment any state listed in
++ jtag_tapstate struct saved by your multichain controller software.
++endstate: xfer end state after transaction finish
++ can be: any state listed in jtag_tapstate struct
++
++Example:
++ struct jtag_xfer xfer;
++ static char buf[64];
++ static unsigned int buf_len = 0;
++ [...]
++ xfer.type = JTAG_SDR_XFER;
++ xfer.tdio = (__u64)buf;
++ xfer.length = buf_len;
++ xfer.from = JTAG_STATE_TLRESET;
++ xfer.endstate = JTAG_STATE_IDLE;
++
++ if (is_read)
++ xfer.direction = JTAG_READ_XFER;
++ else if (is_write)
++ xfer.direction = JTAG_WRITE_XFER;
++ else
++ xfer.direction = JTAG_READ_WRITE_XFER;
++
++ ioctl(jtag_fd, JTAG_IOCXFER, &xfer);
++
++JTAG_SIOCMODE
++------
++If hardware driver can support different running modes you can change it.
++
++Example:
++ struct jtag_mode mode;
++ mode.feature = JTAG_XFER_MODE;
++ mode.mode = JTAG_XFER_HW_MODE;
++ ioctl(jtag_fd, JTAG_SIOCMODE, &mode);
++
++JTAG_IOCBITBANG
++------
++JTAG Bitbang low level operation.
++
++Example:
++ struct bitbang_packet bitbang;
++ struct tck_bitbang bitbang_data[2];
++ bitbang_data[0].tms = 0;
++ bitbang_data[0].tdi = 1;
++ bitbang_data[1].tms = 0;
++ bitbang_data[1].tdi = 1;
++ bitbang.data = bitbang_data;
++ bitbang.length = 2;
++ ioctl(jtag_fd, JTAG_IOCBITBANG, &bitbang);
++ tdo0 = bitbang_data[0].tdo;
++ tdo1 = bitbang_data[1].tdo;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch
new file mode 100644
index 000000000..99cc318ab
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch
@@ -0,0 +1,57 @@
+From 8618c2cd920d10681859bacf8af56c71f168b5a2 Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Sun, 10 Mar 2019 11:48:18 -0800
+Subject: [PATCH] Documentation jtag: Add JTAG core driver ioctl number
+
+JTAG class driver provide infrastructure to support hardware/software
+JTAG platform drivers. It provide user layer API interface for flashing
+and debugging external devices which equipped with JTAG interface
+using standard transactions.
+
+Driver exposes set of IOCTL to user space for:
+- XFER:
+ SIR (Scan Instruction Register, IEEE 1149.1 Data Register scan);
+ SDR (Scan Data Register, IEEE 1149.1 Instruction Register scan);
+- GIOCSTATUS read the current TAPC state of the JTAG controller
+- SIOCSTATE Forces the JTAG TAPC to go into a particular state.
+- SIOCFREQ/GIOCFREQ for setting and reading JTAG frequency.
+- IOCBITBANG for low level control of JTAG signals.
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Philippe Ombredanne <pombredanne@nexb.com>
+Cc: Jiri Pirko <jiri@mellanox.com>
+Cc: Vadim Pasternak <vadimp@mellanox.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Kishon Vijay Abraham I <kishon@ti.com>
+Cc: Darrick J. Wong <darrick.wong@oracle.com>
+Cc: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+Cc: Eric Sandeen <sandeen@redhat.com>
+Cc: Randy Dunlap <rdunlap@infradead.org>
+Cc: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+ Documentation/ioctl/ioctl-number.rst | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/Documentation/ioctl/ioctl-number.rst b/Documentation/ioctl/ioctl-number.rst
+index de23fc0f0fce..339d198c5adf 100644
+--- a/Documentation/ioctl/ioctl-number.rst
++++ b/Documentation/ioctl/ioctl-number.rst
+@@ -333,6 +333,8 @@ Code Seq# Include File Comments
+ <mailto:vgo@ratio.de>
+ 0xB1 00-1F PPPoX
+ <mailto:mostrows@styx.uwaterloo.ca>
++0xB2 00-0F linux/jtag.h JTAG driver
++ <mailto:oleksandrs@mellanox.com>
+ 0xB3 00 linux/mmc/ioctl.h
+ 0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
+ 0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch
new file mode 100644
index 000000000..9ff92d8ec
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch
@@ -0,0 +1,50 @@
+From fcf8f7fd3cb4e0b08cb1540f9ff9e5988cd285d1 Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Sun, 10 Mar 2019 11:49:37 -0800
+Subject: [PATCH] drivers: jtag: Add JTAG core driver Maintainers
+
+JTAG class driver provide infrastructure to support hardware/software
+JTAG platform drivers. It provide user layer API interface for flashing
+and debugging external devices which equipped with JTAG interface
+using standard transactions.
+
+Signed-off-by: Oleksandr Shamray <oleksandrs@mellanox.com>
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Cc: Jiri Pirko <jiri@mellanox.com>
+Cc: Vadim Pasternak <vadimp@mellanox.com>
+Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
+Cc: Steven A Filary <steven.a.filary@intel.com>
+Cc: Bryan Hunt <bryan.hunt@intel.com>
+---
+ MAINTAINERS | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 3bbdae50eb7e..34ab3522801c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -8819,6 +8819,17 @@ L: linux-serial@vger.kernel.org
+ S: Orphan
+ F: drivers/tty/serial/jsm/
+
++JTAG SUBSYSTEM
++M: Oleksandr Shamray <oleksandrs@mellanox.com>
++M: Vadim Pasternak <vadimp@mellanox.com>
++M Ernesto Corona <ernesto.corona@intel.com>
++S: Maintained
++F: include/linux/jtag.h
++F: include/uapi/linux/jtag.h
++F: drivers/jtag/
++F: Documentation/devicetree/bindings/jtag/
++F: Documentation/ABI/testing/jtag-dev
++
+ K10TEMP HARDWARE MONITORING DRIVER
+ M: Clemens Ladisch <clemens@ladisch.de>
+ L: linux-hwmon@vger.kernel.org
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch
new file mode 100644
index 000000000..fbf422a35
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch
@@ -0,0 +1,1148 @@
+From b8d7d0f3513abdf014345b240a79d23c63409c4c Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 11 Jun 2019 15:07:08 -0700
+Subject: [PATCH] i2c: aspeed: add buffer mode transfer support
+
+Byte mode currently this driver uses makes lots of interrupt call
+which isn't good for performance and it makes the driver very
+timing sensitive. To improve performance of the driver, this commit
+adds buffer mode transfer support which uses I2C SRAM buffer
+instead of using a single byte buffer.
+
+AST2400:
+It has 2 KBytes (256 Bytes x 8 pages) of I2C SRAM buffer pool from
+0x1e78a800 to 0x1e78afff that can be used for all busses with
+buffer pool manipulation. To simplify implementation for supporting
+both AST2400 and AST2500, it assigns each 128 Bytes per bus without
+using buffer pool manipulation so total 1792 Bytes of I2C SRAM
+buffer will be used.
+
+AST2500:
+It has 16 Bytes of individual I2C SRAM buffer per each bus and its
+range is from 0x1e78a200 to 0x1e78a2df, so it doesn't have 'buffer
+page selection' bit field in the Function control register, and
+neither 'base address pointer' bit field in the Pool buffer control
+register it has. To simplify implementation for supporting both
+AST2400 and AST2500, it writes zeros on those register bit fields
+but it's okay because it does nothing in AST2500.
+
+It provides buffer based master and slave data transfer.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../devicetree/bindings/i2c/i2c-aspeed.txt | 40 ++-
+ arch/arm/boot/dts/aspeed-g4.dtsi | 47 +--
+ arch/arm/boot/dts/aspeed-g5.dtsi | 47 +--
+ arch/arm/boot/dts/aspeed-g6.dtsi | 32 +-
+ drivers/i2c/busses/i2c-aspeed.c | 376 +++++++++++++++++++--
+ 5 files changed, 451 insertions(+), 91 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+index 7da7e813b2b0..0ff3539cee95 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+@@ -3,7 +3,10 @@ Device tree configuration for the I2C busses on the AST24XX and AST25XX SoCs.
+ Required Properties:
+ - #address-cells : should be 1
+ - #size-cells : should be 0
+-- reg : address offset and range of bus
++- reg : Address offset and range of bus registers.
++ An additional SRAM buffer address offset and range is
++ optional in case of enabling I2C dedicated SRAM for
++ buffer mode transfer support.
+ - compatible : should be "aspeed,ast2400-i2c-bus"
+ or "aspeed,ast2500-i2c-bus"
+ - clocks : root clock of bus, should reference the APB
+@@ -28,12 +31,21 @@ i2c {
+ #size-cells = <1>;
+ ranges = <0 0x1e78a000 0x1000>;
+
+- i2c_ic: interrupt-controller@0 {
+- #interrupt-cells = <1>;
+- compatible = "aspeed,ast2400-i2c-ic";
++ i2c_gr: i2c-global-regs@0 {
++ compatible = "aspeed,ast2500-i2c-gr", "syscon";
+ reg = <0x0 0x40>;
+- interrupts = <12>;
+- interrupt-controller;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x0 0x40>;
++
++ i2c_ic: interrupt-controller@0 {
++ #interrupt-cells = <1>;
++ compatible = "aspeed,ast2500-i2c-ic";
++ reg = <0x0 0x4>;
++ interrupts = <12>;
++ interrupt-controller;
++ };
+ };
+
+ i2c0: i2c-bus@40 {
+@@ -41,11 +53,25 @@ i2c {
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x40 0x40>;
+- compatible = "aspeed,ast2400-i2c-bus";
++ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+ bus-frequency = <100000>;
+ interrupts = <0>;
+ interrupt-parent = <&i2c_ic>;
+ };
++
++ /* buffer mode transfer enabled */
++ i2c1: i2c-bus@80 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0x80 0x40>, <0x210 0x10>;
++ compatible = "aspeed,ast2500-i2c-bus";
++ clocks = <&syscon ASPEED_CLK_APB>;
++ resets = <&syscon ASPEED_RESET_I2C>;
++ bus-frequency = <100000>;
++ interrupts = <1>;
++ interrupt-parent = <&i2c_ic>;
++ };
+ };
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index fc6f4e009db7..0b30c8546e64 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -518,12 +518,21 @@
+ };
+
+ &i2c {
+- i2c_ic: interrupt-controller@0 {
+- #interrupt-cells = <1>;
+- compatible = "aspeed,ast2400-i2c-ic";
++ i2c_gr: i2c-global-regs@0 {
++ compatible = "aspeed,ast2400-i2c-gr", "syscon";
+ reg = <0x0 0x40>;
+- interrupts = <12>;
+- interrupt-controller;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x0 0x40>;
++
++ i2c_ic: interrupt-controller@0 {
++ #interrupt-cells = <1>;
++ compatible = "aspeed,ast2400-i2c-ic";
++ reg = <0x0 0x4>;
++ interrupts = <12>;
++ interrupt-controller;
++ };
+ };
+
+ i2c0: i2c-bus@40 {
+@@ -531,7 +540,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x40 0x40>;
++ reg = <0x40 0x40>, <0x800 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -547,7 +556,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x80 0x40>;
++ reg = <0x80 0x40>, <0x880 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -563,7 +572,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0xc0 0x40>;
++ reg = <0xc0 0x40>, <0x900 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -580,7 +589,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x100 0x40>;
++ reg = <0x100 0x40>, <0x980 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -597,7 +606,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x140 0x40>;
++ reg = <0x140 0x40>, <0xa00 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -614,7 +623,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x180 0x40>;
++ reg = <0x180 0x40>, <0xa80 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -631,7 +640,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x1c0 0x40>;
++ reg = <0x1c0 0x40>, <0xb00 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -648,7 +657,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x300 0x40>;
++ reg = <0x300 0x40>, <0xb80 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -665,7 +674,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x340 0x40>;
++ reg = <0x340 0x40>, <0xc00 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -682,7 +691,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x380 0x40>;
++ reg = <0x380 0x40>, <0xc80 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -699,7 +708,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x3c0 0x40>;
++ reg = <0x3c0 0x40>, <0xd00 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -716,7 +725,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x400 0x40>;
++ reg = <0x400 0x40>, <0xd80 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -733,7 +742,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x440 0x40>;
++ reg = <0x440 0x40>, <0xe00 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -750,7 +759,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x480 0x40>;
++ reg = <0x480 0x40>, <0xe80 0x80>;
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index eb1f9c9d9cca..51593a0a8a23 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -615,12 +615,21 @@
+ };
+
+ &i2c {
+- i2c_ic: interrupt-controller@0 {
+- #interrupt-cells = <1>;
+- compatible = "aspeed,ast2500-i2c-ic";
++ i2c_gr: i2c-global-regs@0 {
++ compatible = "aspeed,ast2500-i2c-gr", "syscon";
+ reg = <0x0 0x40>;
+- interrupts = <12>;
+- interrupt-controller;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges = <0x0 0x0 0x40>;
++
++ i2c_ic: interrupt-controller@0 {
++ #interrupt-cells = <1>;
++ compatible = "aspeed,ast2500-i2c-ic";
++ reg = <0x0 0x4>;
++ interrupts = <12>;
++ interrupt-controller;
++ };
+ };
+
+ i2c0: i2c-bus@40 {
+@@ -628,7 +637,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x40 0x40>;
++ reg = <0x40 0x40>, <0x200 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -644,7 +653,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x80 0x40>;
++ reg = <0x80 0x40>, <0x210 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -660,7 +669,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0xc0 0x40>;
++ reg = <0xc0 0x40>, <0x220 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -677,7 +686,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x100 0x40>;
++ reg = <0x100 0x40>, <0x230 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -694,7 +703,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x140 0x40>;
++ reg = <0x140 0x40>, <0x240 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -711,7 +720,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x180 0x40>;
++ reg = <0x180 0x40>, <0x250 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -728,7 +737,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x1c0 0x40>;
++ reg = <0x1c0 0x40>, <0x260 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -745,7 +754,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x300 0x40>;
++ reg = <0x300 0x40>, <0x270 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -762,7 +771,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x340 0x40>;
++ reg = <0x340 0x40>, <0x280 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -779,7 +788,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x380 0x40>;
++ reg = <0x380 0x40>, <0x290 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -796,7 +805,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x3c0 0x40>;
++ reg = <0x3c0 0x40>, <0x2a0 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -813,7 +822,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x400 0x40>;
++ reg = <0x400 0x40>, <0x2b0 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -830,7 +839,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x440 0x40>;
++ reg = <0x440 0x40>, <0x2c0 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -847,7 +856,7 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x480 0x40>;
++ reg = <0x480 0x40>, <0x2d0 0x10>;
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index f92a2aa999d1..3ef312543269 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -712,7 +712,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x80 0x80>;
++ reg = <0x80 0x80>, <0xc00 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -727,7 +727,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x100 0x80>;
++ reg = <0x100 0x80>, <0xc20 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -742,7 +742,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x180 0x80>;
++ reg = <0x180 0x80>, <0xc40 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -757,7 +757,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x200 0x80>;
++ reg = <0x200 0x80>, <0xc60 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -772,7 +772,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x280 0x80>;
++ reg = <0x280 0x80>, <0xc80 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -787,7 +787,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x300 0x80>;
++ reg = <0x300 0x80>, <0xca0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -802,7 +802,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x380 0x80>;
++ reg = <0x380 0x80>, <0xcc0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -817,7 +817,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x400 0x80>;
++ reg = <0x400 0x80>, <0xce0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -832,7 +832,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x480 0x80>;
++ reg = <0x480 0x80>, <0xd00 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -847,7 +847,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x500 0x80>;
++ reg = <0x500 0x80>, <0xd20 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -862,7 +862,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x580 0x80>;
++ reg = <0x580 0x80>, <0xd40 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -877,7 +877,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x600 0x80>;
++ reg = <0x600 0x80>, <0xd60 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -892,7 +892,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x680 0x80>;
++ reg = <0x680 0x80>, <0xd80 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -907,7 +907,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x700 0x80>;
++ reg = <0x700 0x80>, <0xda0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -922,7 +922,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x780 0x80>;
++ reg = <0x780 0x80>, <0xdc0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -937,7 +937,7 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+- reg = <0x800 0x80>;
++ reg = <0x800 0x80>, <0xde0 0x20>;
+ compatible = "aspeed,ast2600-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 7becfcd67142..bf72e151d11f 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -7,6 +7,7 @@
+ * Copyright 2017 Google, Inc.
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/completion.h>
+ #include <linux/err.h>
+@@ -19,15 +20,24 @@
+ #include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_platform.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ #include <linux/reset.h>
+ #include <linux/slab.h>
+
+-/* I2C Register */
++/* I2C Global Registers */
++/* 0x00 : I2CG Interrupt Status Register */
++/* 0x08 : I2CG Interrupt Target Assignment */
++/* 0x0c : I2CG Global Control Register (AST2500) */
++#define ASPEED_I2CG_GLOBAL_CTRL_REG 0x0c
++#define ASPEED_I2CG_SRAM_BUFFER_EN BIT(0)
++
++/* I2C Bus Registers */
+ #define ASPEED_I2C_FUN_CTRL_REG 0x00
+ #define ASPEED_I2C_AC_TIMING_REG1 0x04
+ #define ASPEED_I2C_AC_TIMING_REG2 0x08
+@@ -35,14 +45,12 @@
+ #define ASPEED_I2C_INTR_STS_REG 0x10
+ #define ASPEED_I2C_CMD_REG 0x14
+ #define ASPEED_I2C_DEV_ADDR_REG 0x18
++#define ASPEED_I2C_BUF_CTRL_REG 0x1c
+ #define ASPEED_I2C_BYTE_BUF_REG 0x20
+
+-/* Global Register Definition */
+-/* 0x00 : I2C Interrupt Status Register */
+-/* 0x08 : I2C Interrupt Target Assignment */
+-
+ /* Device Register Definition */
+ /* 0x00 : I2CD Function Control Register */
++#define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20)
+ #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15)
+ #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
+ #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
+@@ -102,6 +110,8 @@
+ #define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11)
+
+ /* Command Bit */
++#define ASPEED_I2CD_RX_BUFF_ENABLE BIT(7)
++#define ASPEED_I2CD_TX_BUFF_ENABLE BIT(6)
+ #define ASPEED_I2CD_M_STOP_CMD BIT(5)
+ #define ASPEED_I2CD_M_S_RX_CMD_LAST BIT(4)
+ #define ASPEED_I2CD_M_RX_CMD BIT(3)
+@@ -118,6 +128,13 @@
+ /* 0x18 : I2CD Slave Device Address Register */
+ #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0)
+
++/* 0x1c : I2CD Buffer Control Register */
++/* Use 8-bits or 6-bits wide bit fileds to support both AST2400 and AST2500 */
++#define ASPEED_I2CD_BUF_RX_COUNT_MASK GENMASK(31, 24)
++#define ASPEED_I2CD_BUF_RX_SIZE_MASK GENMASK(23, 16)
++#define ASPEED_I2CD_BUF_TX_COUNT_MASK GENMASK(15, 8)
++#define ASPEED_I2CD_BUF_OFFSET_MASK GENMASK(5, 0)
++
+ enum aspeed_i2c_master_state {
+ ASPEED_I2C_MASTER_INACTIVE,
+ ASPEED_I2C_MASTER_PENDING,
+@@ -163,6 +180,11 @@ struct aspeed_i2c_bus {
+ int master_xfer_result;
+ /* Multi-master */
+ bool multi_master;
++ /* Buffer mode */
++ void __iomem *buf_base;
++ u8 buf_offset;
++ u8 buf_page;
++ size_t buf_size;
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ struct i2c_client *slave;
+ enum aspeed_i2c_slave_state slave_state;
+@@ -255,6 +277,77 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+ }
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
++static inline void
++aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
++ u8 *value)
++{
++ if (bus->buf_base &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
++ *value = readb(bus->buf_base);
++ else
++ *value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++}
++
++static inline void
++aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
++ u8 *value)
++{
++ int i, len;
++
++ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ irq_status & ASPEED_I2CD_INTR_RX_DONE) {
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base +
++ ASPEED_I2C_BUF_CTRL_REG));
++ for (i = 0; i < len; i++) {
++ *value = readb(bus->buf_base + i);
++ i2c_slave_event(bus->slave,
++ I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ }
++ }
++}
++
++static inline void
++aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value)
++{
++ if (bus->buf_base) {
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ bus->buf_size - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(ASPEED_I2CD_RX_BUFF_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ }
++}
++
++static inline void
++aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value)
++{
++ int i, len;
++
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base +
++ ASPEED_I2C_BUF_CTRL_REG));
++ for (i = 1; i < len; i++) {
++ *value = readb(bus->buf_base + i);
++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ bus->buf_size - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(ASPEED_I2CD_RX_BUFF_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ }
++}
++
+ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ {
+ u32 command, irq_handled = 0;
+@@ -281,7 +374,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+
+ /* Slave was sent something. */
+ if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
+- value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value);
+ /* Handle address frame. */
+ if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
+ if (value & 0x1)
+@@ -296,9 +389,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+
+ /* Slave was asked to stop. */
+ if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
++ aspeed_i2c_slave_handle_normal_stop(bus, irq_status, &value);
+ irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;
+ bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+ }
++
+ if (irq_status & ASPEED_I2CD_INTR_TX_NAK &&
+ bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {
+ irq_handled |= ASPEED_I2CD_INTR_TX_NAK;
+@@ -328,9 +423,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ case ASPEED_I2C_SLAVE_WRITE_REQUESTED:
+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
++ aspeed_i2c_slave_handle_write_requested(bus, &value);
+ break;
+ case ASPEED_I2C_SLAVE_WRITE_RECEIVED:
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
++ aspeed_i2c_slave_handle_write_received(bus, &value);
+ break;
+ case ASPEED_I2C_SLAVE_STOP:
+ i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
+@@ -350,12 +447,76 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ }
+ #endif /* CONFIG_I2C_SLAVE */
+
++static inline u32
++aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u32 command = 0;
++ int len;
++
++ if (msg->len > bus->buf_size) {
++ len = bus->buf_size;
++ } else {
++ len = msg->len;
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ if (bus->buf_base) {
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
++
++ return command;
++}
++
++static inline u32
++aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u8 slave_addr = i2c_8bit_addr_from_msg(msg);
++ u32 command = 0;
++ int len;
++
++ if (msg->len + 1 > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len + 1;
++
++ if (bus->buf_base) {
++ u8 wbuf[4];
++ int i;
++
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++
++ /*
++ * Yeah, it looks bad but byte writing on remapped I2C SRAM
++ * causes corruption so use this way to make dword writings.
++ */
++ wbuf[0] = slave_addr;
++ for (i = 1; i < len; i++) {
++ wbuf[i % 4] = msg->buf[i - 1];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf, bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
++ writel(*(u32 *)wbuf, bus->buf_base + i - (i % 4));
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
++
++ bus->buf_index = len - 1;
++
++ return command;
++}
++
+ /* precondition: bus.lock has been acquired. */
+ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ {
+ u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
+ struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
+- u8 slave_addr = i2c_8bit_addr_from_msg(msg);
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /*
+@@ -374,12 +535,21 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+
+ if (msg->flags & I2C_M_RD) {
+ command |= ASPEED_I2CD_M_RX_CMD;
+- /* Need to let the hardware know to NACK after RX. */
+- if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN))
+- command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ if (!(msg->flags & I2C_M_RECV_LEN)) {
++ if (msg->len && bus->buf_base)
++ command |= aspeed_i2c_prepare_rx_buf(bus, msg);
++
++ /* Need to let the hardware know to NACK after RX. */
++ if (msg->len <= 1)
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++ } else if (msg->len && bus->buf_base) {
++ command |= aspeed_i2c_prepare_tx_buf(bus, msg);
+ }
+
+- writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
++ if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE))
++ writel(i2c_8bit_addr_from_msg(msg),
++ bus->base + ASPEED_I2C_BYTE_BUF_REG);
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
+ }
+
+@@ -414,6 +584,104 @@ static int aspeed_i2c_is_irq_error(u32 irq_status)
+ return 0;
+ }
+
++static inline u32
++aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus,
++ struct i2c_msg *msg)
++{
++ u32 command = 0;
++
++ if (bus->buf_base) {
++ u8 wbuf[4];
++ int len;
++ int i;
++
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
++
++
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
++
++ for (i = 0; i < len; i++) {
++ wbuf[i % 4] = msg->buf[bus->buf_index + i];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - (i % 4));
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++
++ bus->buf_index += len;
++ } else {
++ writel(msg->buf[bus->buf_index++],
++ bus->base + ASPEED_I2C_BYTE_BUF_REG);
++ }
++
++ return command;
++}
++
++static inline void
++aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u8 recv_byte;
++ int len;
++
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG));
++ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len);
++ bus->buf_index += len;
++ } else {
++ recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++ msg->buf[bus->buf_index++] = recv_byte;
++ }
++}
++
++static inline u32
++aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
++ struct i2c_msg *msg)
++{
++ u32 command = 0;
++
++ if (bus->buf_base) {
++ int len;
++
++ if (msg->len - bus->buf_index > bus->buf_size) {
++ len = bus->buf_size;
++ } else {
++ len = msg->len - bus->buf_index;
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ } else {
++ if (bus->buf_index + 1 == msg->len)
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ return command;
++}
++
+ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ {
+ u32 irq_handled = 0, command = 0;
+@@ -522,11 +790,10 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ /* fall through */
+ case ASPEED_I2C_MASTER_TX_FIRST:
+ if (bus->buf_index < msg->len) {
++ command = ASPEED_I2CD_M_TX_CMD;
++ command |= aspeed_i2c_master_handle_tx_first(bus, msg);
++ writel(command, bus->base + ASPEED_I2C_CMD_REG);
+ bus->master_state = ASPEED_I2C_MASTER_TX;
+- writel(msg->buf[bus->buf_index++],
+- bus->base + ASPEED_I2C_BYTE_BUF_REG);
+- writel(ASPEED_I2CD_M_TX_CMD,
+- bus->base + ASPEED_I2C_CMD_REG);
+ } else {
+ aspeed_i2c_next_msg_or_stop(bus);
+ }
+@@ -543,26 +810,26 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ }
+ irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
+
+- recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
+- msg->buf[bus->buf_index++] = recv_byte;
+-
+ if (msg->flags & I2C_M_RECV_LEN) {
++ recv_byte = readl(bus->base +
++ ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
+ bus->cmd_err = -EPROTO;
+ aspeed_i2c_do_stop(bus);
+ goto out_no_complete;
+ }
+- msg->len = recv_byte +
+- ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1);
++ msg->len = recv_byte + ((msg->flags & I2C_CLIENT_PEC) ?
++ 2 : 1);
+ msg->flags &= ~I2C_M_RECV_LEN;
++ } else if (msg->len) {
++ aspeed_i2c_master_handle_rx(bus, msg);
+ }
+
+ if (bus->buf_index < msg->len) {
+- bus->master_state = ASPEED_I2C_MASTER_RX;
+ command = ASPEED_I2CD_M_RX_CMD;
+- if (bus->buf_index + 1 == msg->len)
+- command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ command |= aspeed_i2c_master_handle_rx_next(bus, msg);
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
++ bus->master_state = ASPEED_I2C_MASTER_RX;
+ } else {
+ aspeed_i2c_next_msg_or_stop(bus);
+ }
+@@ -924,6 +1191,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+ if (ret < 0)
+ return ret;
+
++ fun_ctrl_reg |= FIELD_PREP(ASPEED_I2CD_BUFFER_PAGE_SEL_MASK,
++ bus->buf_page);
++
+ if (of_property_read_bool(pdev->dev.of_node, "multi-master"))
+ bus->multi_master = true;
+ else
+@@ -964,6 +1234,52 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus)
+ return ret;
+ }
+
++static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus)
++{
++ struct platform_device *pdev = to_platform_device(bus->dev);
++ bool sram_enabled = true;
++ int ret;
++
++ /*
++ * Enable I2C SRAM in case of AST2500.
++ * SRAM is enabled by default in AST2400 and AST2600.
++ */
++ if (of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2500-i2c-bus")) {
++ struct regmap *gr_regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2500-i2c-gr");
++
++ if (IS_ERR(gr_regmap))
++ ret = PTR_ERR(gr_regmap);
++ else
++ ret = regmap_update_bits(gr_regmap,
++ ASPEED_I2CG_GLOBAL_CTRL_REG,
++ ASPEED_I2CG_SRAM_BUFFER_EN,
++ ASPEED_I2CG_SRAM_BUFFER_EN);
++
++ if (ret)
++ sram_enabled = false;
++ }
++
++ if (sram_enabled) {
++ struct resource *res = platform_get_resource(pdev,
++ IORESOURCE_MEM, 1);
++
++ if (res && resource_size(res) >= 2)
++ bus->buf_base = devm_ioremap_resource(&pdev->dev, res);
++
++ if (!IS_ERR_OR_NULL(bus->buf_base)) {
++ bus->buf_size = resource_size(res);
++ if (of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2400-i2c-bus")) {
++ bus->buf_page = ((res->start >> 8) &
++ GENMASK(3, 0)) - 8;
++ bus->buf_offset = (res->start >> 2) &
++ ASPEED_I2CD_BUF_OFFSET_MASK;
++ }
++ }
++ }
++}
++
+ static const struct of_device_id aspeed_i2c_bus_of_table[] = {
+ {
+ .compatible = "aspeed,ast2400-i2c-bus",
+@@ -986,18 +1302,18 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ const struct of_device_id *match;
+ struct aspeed_i2c_bus *bus;
+ struct clk *parent_clk;
+- struct resource *res;
+ int irq, ret;
+
+ bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- bus->base = devm_ioremap_resource(&pdev->dev, res);
++ bus->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bus->base))
+ return PTR_ERR(bus->base);
+
++ bus->dev = &pdev->dev;
++
+ parent_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+@@ -1028,6 +1344,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ bus->get_clk_reg_val = (u32 (*)(struct device *, u32))
+ match->data;
+
++ aspeed_i2c_set_xfer_mode(bus);
++
+ /* Initialize the I2C adapter */
+ spin_lock_init(&bus->lock);
+ init_completion(&bus->cmd_complete);
+@@ -1038,8 +1356,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
+ i2c_set_adapdata(&bus->adap, bus);
+
+- bus->dev = &pdev->dev;
+-
+ /* Clean up any left over interrupt state. */
+ writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
+ writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
+@@ -1063,8 +1379,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, bus);
+
+- dev_info(bus->dev, "i2c bus %d registered, irq %d\n",
+- bus->adap.nr, irq);
++ dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n",
++ bus->adap.nr, bus->buf_base ? "buffer" : "byte", irq);
+
+ return 0;
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch
new file mode 100644
index 000000000..994c20b18
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch
@@ -0,0 +1,491 @@
+From 5bf7a202eb0af455675a85a4f1bdad863fd8805d Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 18 Jun 2019 08:47:50 -0700
+Subject: [PATCH] i2c: aspeed: add DMA mode transfer support
+
+This commit adds DMA mode transfer support.
+
+Only AST2500 supports DMA mode under some limitations:
+I2C is sharing the DMA H/W with UHCI host controller and MCTP
+controller. Since those controllers operate with DMA mode only, I2C
+has to use buffer mode or byte mode instead if one of those
+controllers is enabled. Also make sure that if SD/eMMC or Port80
+snoop uses DMA mode instead of PIO or FIFO respectively, I2C can't
+use DMA mode.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 ++
+ drivers/i2c/busses/i2c-aspeed.c | 253 +++++++++++++++++----
+ 2 files changed, 234 insertions(+), 44 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+index 0ff3539cee95..d3f4a39f7ba6 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+@@ -22,6 +22,16 @@ Optional Properties:
+ - bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not
+ specified.
+ - #retries : Number of retries for master transfer.
++- aspeed,dma-buf-size : size of DMA buffer (from 2 to 4095 in case of AST2500)
++ Only AST2500 supports DMA mode under some limitations:
++ I2C is sharing the DMA H/W with UHCI host controller
++ and MCTP controller. Since those controllers operate
++ with DMA mode only, I2C has to use buffer mode or byte
++ mode instead if one of those controllers is enabled.
++ Also make sure that if SD/eMMC or Port80 snoop uses
++ DMA mode instead of PIO or FIFO respectively, I2C
++ can't use DMA mode. IF both DMA and buffer modes are
++ enabled, DMA mode will be selected.
+
+ Example:
+
+@@ -74,4 +84,19 @@ i2c {
+ interrupts = <1>;
+ interrupt-parent = <&i2c_ic>;
+ };
++
++ /* DMA mode transfer enabled */
++ i2c2: i2c-bus@c0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ #interrupt-cells = <1>;
++ reg = <0xc0 0x40>;
++ aspeed,dma-buf-size = <4095>;
++ compatible = "aspeed,ast2500-i2c-bus";
++ clocks = <&syscon ASPEED_CLK_APB>;
++ resets = <&syscon ASPEED_RESET_I2C>;
++ bus-frequency = <100000>;
++ interrupts = <2>;
++ interrupt-parent = <&i2c_ic>;
++ };
+ };
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index bf72e151d11f..3c9e491cbe4e 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -10,6 +10,8 @@
+ #include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/completion.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
+@@ -47,6 +49,8 @@
+ #define ASPEED_I2C_DEV_ADDR_REG 0x18
+ #define ASPEED_I2C_BUF_CTRL_REG 0x1c
+ #define ASPEED_I2C_BYTE_BUF_REG 0x20
++#define ASPEED_I2C_DMA_ADDR_REG 0x24
++#define ASPEED_I2C_DMA_LEN_REG 0x28
+
+ /* Device Register Definition */
+ /* 0x00 : I2CD Function Control Register */
+@@ -110,6 +114,8 @@
+ #define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11)
+
+ /* Command Bit */
++#define ASPEED_I2CD_RX_DMA_ENABLE BIT(9)
++#define ASPEED_I2CD_TX_DMA_ENABLE BIT(8)
+ #define ASPEED_I2CD_RX_BUFF_ENABLE BIT(7)
+ #define ASPEED_I2CD_TX_BUFF_ENABLE BIT(6)
+ #define ASPEED_I2CD_M_STOP_CMD BIT(5)
+@@ -135,6 +141,14 @@
+ #define ASPEED_I2CD_BUF_TX_COUNT_MASK GENMASK(15, 8)
+ #define ASPEED_I2CD_BUF_OFFSET_MASK GENMASK(5, 0)
+
++/* 0x24 : I2CD DMA Mode Buffer Address Register */
++#define ASPEED_I2CD_DMA_ADDR_MASK GENMASK(31, 2)
++#define ASPEED_I2CD_DMA_ALIGN 4
++
++/* 0x28 : I2CD DMA Transfer Length Register */
++#define ASPEED_I2CD_DMA_LEN_SHIFT 0
++#define ASPEED_I2CD_DMA_LEN_MASK GENMASK(11, 0)
++
+ enum aspeed_i2c_master_state {
+ ASPEED_I2C_MASTER_INACTIVE,
+ ASPEED_I2C_MASTER_PENDING,
+@@ -184,6 +198,12 @@ struct aspeed_i2c_bus {
+ void __iomem *buf_base;
+ u8 buf_offset;
+ u8 buf_page;
++ /* DMA mode */
++ struct dma_pool *dma_pool;
++ dma_addr_t dma_handle;
++ u8 *dma_buf;
++ size_t dma_len;
++ /* Buffer/DMA mode */
+ size_t buf_size;
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ struct i2c_client *slave;
+@@ -281,7 +301,11 @@ static inline void
+ aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
+ u8 *value)
+ {
+- if (bus->buf_base &&
++ if (bus->dma_buf &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
++ *value = bus->dma_buf[0];
++ else if (bus->buf_base &&
+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
+ *value = readb(bus->buf_base);
+@@ -297,7 +321,18 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
+
+ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
+ irq_status & ASPEED_I2CD_INTR_RX_DONE) {
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ len = bus->buf_size -
++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
++ readl(bus->base +
++ ASPEED_I2C_DMA_LEN_REG));
++ for (i = 0; i < len; i++) {
++ *value = bus->dma_buf[i];
++ i2c_slave_event(bus->slave,
++ I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ } else if (bus->buf_base) {
+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
+ readl(bus->base +
+ ASPEED_I2C_BUF_CTRL_REG));
+@@ -314,7 +349,14 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
+ static inline void
+ aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value)
+ {
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ writel(ASPEED_I2CD_RX_DMA_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ } else if (bus->buf_base) {
+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
+ bus->buf_size - 1) |
+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+@@ -330,7 +372,23 @@ aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value)
+ {
+ int i, len;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ len = bus->buf_size -
++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
++ readl(bus->base +
++ ASPEED_I2C_DMA_LEN_REG));
++ for (i = 1; i < len; i++) {
++ *value = bus->dma_buf[i];
++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ writel(ASPEED_I2CD_RX_DMA_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ } else if (bus->buf_base) {
+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
+ readl(bus->base +
+ ASPEED_I2C_BUF_CTRL_REG));
+@@ -460,7 +518,15 @@ aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+ }
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_RX_DMA_ENABLE;
++
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
+ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
+
+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) |
+@@ -483,7 +549,18 @@ aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ else
+ len = msg->len + 1;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_TX_DMA_ENABLE;
++
++ bus->dma_buf[0] = slave_addr;
++ memcpy(bus->dma_buf + 1, msg->buf, len);
++
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
+ u8 wbuf[4];
+ int i;
+
+@@ -536,18 +613,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ if (msg->flags & I2C_M_RD) {
+ command |= ASPEED_I2CD_M_RX_CMD;
+ if (!(msg->flags & I2C_M_RECV_LEN)) {
+- if (msg->len && bus->buf_base)
++ if (msg->len && (bus->dma_buf || bus->buf_base))
+ command |= aspeed_i2c_prepare_rx_buf(bus, msg);
+
+ /* Need to let the hardware know to NACK after RX. */
+ if (msg->len <= 1)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+ }
+- } else if (msg->len && bus->buf_base) {
++ } else if (msg->len && (bus->dma_buf || bus->buf_base)) {
+ command |= aspeed_i2c_prepare_tx_buf(bus, msg);
+ }
+
+- if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE))
++ if (!(command & (ASPEED_I2CD_TX_BUFF_ENABLE |
++ ASPEED_I2CD_TX_DMA_ENABLE)))
+ writel(i2c_8bit_addr_from_msg(msg),
+ bus->base + ASPEED_I2C_BYTE_BUF_REG);
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
+@@ -590,39 +668,52 @@ aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus,
+ {
+ u32 command = 0;
+
+- if (bus->buf_base) {
+- u8 wbuf[4];
++ if (bus->dma_buf || bus->buf_base) {
+ int len;
+- int i;
+
+ if (msg->len - bus->buf_index > bus->buf_size)
+ len = bus->buf_size;
+ else
+ len = msg->len - bus->buf_index;
+
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_TX_DMA_ENABLE;
+
+- command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++ memcpy(bus->dma_buf, msg->buf + bus->buf_index, len);
+
+- if (msg->len - bus->buf_index > bus->buf_size)
+- len = bus->buf_size;
+- else
+- len = msg->len - bus->buf_index;
+
+- for (i = 0; i < len; i++) {
+- wbuf[i % 4] = msg->buf[bus->buf_index + i];
+- if (i % 4 == 3)
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
++ u8 wbuf[4];
++ int i;
++
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
++
++ for (i = 0; i < len; i++) {
++ wbuf[i % 4] = msg->buf[bus->buf_index + i];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
+ writel(*(u32 *)wbuf,
+- bus->buf_base + i - 3);
+- }
+- if (--i % 4 != 3)
+- writel(*(u32 *)wbuf,
+- bus->buf_base + i - (i % 4));
++ bus->buf_base + i - (i % 4));
+
+- writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
+- len - 1) |
+- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+- bus->buf_offset),
+- bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
+
+ bus->buf_index += len;
+ } else {
+@@ -639,7 +730,14 @@ aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ u8 recv_byte;
+ int len;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ len = bus->dma_len -
++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
++ readl(bus->base + ASPEED_I2C_DMA_LEN_REG));
++
++ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len);
++ bus->buf_index += len;
++ } else if (bus->buf_base) {
+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
+ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG));
+ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len);
+@@ -656,7 +754,7 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
+ {
+ u32 command = 0;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf || bus->buf_base) {
+ int len;
+
+ if (msg->len - bus->buf_index > bus->buf_size) {
+@@ -666,14 +764,24 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+ }
+
+- command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_RX_DMA_ENABLE;
+
+- writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
+- len - 1) |
+- FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
+- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+- bus->buf_offset),
+- bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
+ } else {
+ if (bus->buf_index + 1 == msg->len)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+@@ -1260,7 +1368,51 @@ static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus)
+ sram_enabled = false;
+ }
+
+- if (sram_enabled) {
++ /*
++ * Only AST2500 and AST2600 support DMA mode under some limitations:
++ * I2C is sharing the DMA H/W with UHCI host controller and MCTP
++ * controller. Since those controllers operate with DMA mode only, I2C
++ * has to use buffer mode or byte mode instead if one of those
++ * controllers is enabled. Also make sure that if SD/eMMC or Port80
++ * snoop uses DMA mode instead of PIO or FIFO respectively, I2C can't
++ * use DMA mode.
++ */
++ if (sram_enabled && !IS_ENABLED(CONFIG_USB_UHCI_ASPEED) &&
++ !of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2400-i2c-bus")) {
++ u32 dma_len_max = ASPEED_I2CD_DMA_LEN_MASK >>
++ ASPEED_I2CD_DMA_LEN_SHIFT;
++
++ ret = device_property_read_u32(&pdev->dev,
++ "aspeed,dma-buf-size",
++ &bus->buf_size);
++ if (!ret && bus->buf_size > dma_len_max)
++ bus->buf_size = dma_len_max;
++ }
++
++ if (bus->buf_size) {
++ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
++ dev_warn(&pdev->dev, "No suitable DMA available\n");
++ } else {
++ bus->dma_pool = dma_pool_create("i2c-aspeed",
++ &pdev->dev,
++ bus->buf_size,
++ ASPEED_I2CD_DMA_ALIGN,
++ 0);
++ if (bus->dma_pool)
++ bus->dma_buf = dma_pool_alloc(bus->dma_pool,
++ GFP_KERNEL,
++ &bus->dma_handle);
++
++ if (!bus->dma_buf) {
++ dev_warn(&pdev->dev,
++ "Cannot allocate DMA buffer\n");
++ dma_pool_destroy(bus->dma_pool);
++ }
++ }
++ }
++
++ if (!bus->dma_buf && sram_enabled) {
+ struct resource *res = platform_get_resource(pdev,
+ IORESOURCE_MEM, 1);
+
+@@ -1365,24 +1517,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ */
+ ret = aspeed_i2c_init(bus, pdev);
+ if (ret < 0)
+- return ret;
++ goto out_free_dma_buf;
+
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq,
+ 0, dev_name(&pdev->dev), bus);
+ if (ret < 0)
+- return ret;
++ goto out_free_dma_buf;
+
+ ret = i2c_add_adapter(&bus->adap);
+ if (ret < 0)
+- return ret;
++ goto out_free_dma_buf;
+
+ platform_set_drvdata(pdev, bus);
+
+ dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n",
+- bus->adap.nr, bus->buf_base ? "buffer" : "byte", irq);
++ bus->adap.nr, bus->dma_buf ? "dma" :
++ bus->buf_base ? "buffer" : "byte",
++ irq);
+
+ return 0;
++
++out_free_dma_buf:
++ if (bus->dma_buf)
++ dma_pool_free(bus->dma_pool, bus->dma_buf, bus->dma_handle);
++ dma_pool_destroy(bus->dma_pool);
++
++ return ret;
+ }
+
+ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
+@@ -1400,6 +1561,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
+
+ reset_control_assert(bus->rst);
+
++ if (bus->dma_buf)
++ dma_pool_free(bus->dma_pool, bus->dma_buf, bus->dma_handle);
++ dma_pool_destroy(bus->dma_pool);
++
+ i2c_del_adapter(&bus->adap);
+
+ return 0;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch
new file mode 100644
index 000000000..899924f61
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch
@@ -0,0 +1,180 @@
+From d731b53de05b8d69ea739f02275416126cf5fe4e Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 1 May 2019 13:27:34 -0700
+Subject: [PATCH] i2c: aspeed: add general call support
+
+This commit adds general call support into Aspeed I2C driver.
+This is downstream only customization so it should not go into
+upstream.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ .../devicetree/bindings/i2c/i2c-aspeed.txt | 1 +
+ drivers/i2c/busses/i2c-aspeed.c | 39 ++++++++++++++++++++++
+ drivers/i2c/i2c-slave-mqueue.c | 4 ++-
+ include/linux/i2c.h | 1 +
+ 4 files changed, 44 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+index d3f4a39f7ba6..c1ee99398517 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+@@ -19,6 +19,7 @@ Optional Properties:
+ - bus-frequency : frequency of the bus clock in Hz defaults to 100 kHz when not
+ specified
+ - multi-master : states that there is another master active on this bus.
++- general-call : enables general call receiving.
+ - bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not
+ specified.
+ - #retries : Number of retries for master transfer.
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 3c9e491cbe4e..4420899e2c2d 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -59,6 +59,7 @@
+ #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
+ #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
+ #define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6)
++#define ASPEED_I2CD_GCALL_EN BIT(2)
+ #define ASPEED_I2CD_SLAVE_EN BIT(1)
+ #define ASPEED_I2CD_MASTER_EN BIT(0)
+
+@@ -83,6 +84,7 @@
+ */
+ #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
+ #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
++#define ASPEED_I2CD_INTR_GCALL_ADDR BIT(8)
+ #define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7)
+ #define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6)
+ #define ASPEED_I2CD_INTR_ABNORMAL BIT(5)
+@@ -167,6 +169,8 @@ enum aspeed_i2c_slave_state {
+ ASPEED_I2C_SLAVE_READ_PROCESSED,
+ ASPEED_I2C_SLAVE_WRITE_REQUESTED,
+ ASPEED_I2C_SLAVE_WRITE_RECEIVED,
++ ASPEED_I2C_SLAVE_GCALL_START,
++ ASPEED_I2C_SLAVE_GCALL_REQUESTED,
+ ASPEED_I2C_SLAVE_STOP,
+ };
+
+@@ -208,6 +212,8 @@ struct aspeed_i2c_bus {
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ struct i2c_client *slave;
+ enum aspeed_i2c_slave_state slave_state;
++ /* General call */
++ bool general_call;
+ #endif /* CONFIG_I2C_SLAVE */
+ };
+
+@@ -423,6 +429,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ bus->slave_state = ASPEED_I2C_SLAVE_START;
+ }
+
++ /* General call was requested, restart state machine. */
++ if (irq_status & ASPEED_I2CD_INTR_GCALL_ADDR) {
++ irq_handled |= ASPEED_I2CD_INTR_GCALL_ADDR;
++ bus->slave_state = ASPEED_I2C_SLAVE_GCALL_START;
++ }
++
+ /* Slave is not currently active, irq was for someone else. */
+ if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)
+ return irq_handled;
+@@ -441,6 +453,21 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ else
+ bus->slave_state =
+ ASPEED_I2C_SLAVE_WRITE_REQUESTED;
++ } else if (bus->slave_state == ASPEED_I2C_SLAVE_GCALL_START) {
++ /*
++ * I2C spec defines the second byte meaning like below.
++ * 0x06 : Reset and write programmable part of slave
++ * address by hardware.
++ * 0x04 : Write programmable part of slave address by
++ * hardware.
++ * 0x00 : No allowed.
++ *
++ * But in OpenBMC, we are going to use this
++ * 'General call' feature for IPMB message broadcasting
++ * so it delivers all data as is without any specific
++ * handling of the second byte.
++ */
++ bus->slave_state = ASPEED_I2C_SLAVE_GCALL_REQUESTED;
+ }
+ irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
+ }
+@@ -487,11 +514,16 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
+ aspeed_i2c_slave_handle_write_received(bus, &value);
+ break;
++ case ASPEED_I2C_SLAVE_GCALL_REQUESTED:
++ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
++ i2c_slave_event(slave, I2C_SLAVE_GCALL_REQUESTED, &value);
++ break;
+ case ASPEED_I2C_SLAVE_STOP:
+ i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
+ bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
+ break;
+ case ASPEED_I2C_SLAVE_START:
++ case ASPEED_I2C_SLAVE_GCALL_START:
+ /* Slave was just started. Waiting for the next event. */;
+ break;
+ default:
+@@ -1127,6 +1159,8 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
+ /* Turn on slave mode. */
+ func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
+ func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
++ if (bus->general_call)
++ func_ctrl_reg_val |= ASPEED_I2CD_GCALL_EN;
+ writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
+ }
+
+@@ -1165,6 +1199,8 @@ static int aspeed_i2c_unreg_slave(struct i2c_client *client)
+ /* Turn off slave mode. */
+ func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
+ func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN;
++ if (bus->general_call)
++ func_ctrl_reg_val &= ~ASPEED_I2CD_GCALL_EN;
+ writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
+
+ bus->slave = NULL;
+@@ -1312,6 +1348,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+ bus->base + ASPEED_I2C_FUN_CTRL_REG);
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
++ if (of_property_read_bool(pdev->dev.of_node, "general-call"))
++ bus->general_call = true;
++
+ /* If slave has already been registered, re-enable it. */
+ if (bus->slave)
+ __aspeed_i2c_reg_slave(bus, bus->slave->addr);
+diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c
+index 2c7a6038409c..1d4db584b393 100644
+--- a/drivers/i2c/i2c-slave-mqueue.c
++++ b/drivers/i2c/i2c-slave-mqueue.c
+@@ -56,10 +56,12 @@ static int i2c_slave_mqueue_callback(struct i2c_client *client,
+
+ switch (event) {
+ case I2C_SLAVE_WRITE_REQUESTED:
++ case I2C_SLAVE_GCALL_REQUESTED:
+ mq->truncated = 0;
+
+ msg->len = 1;
+- msg->buf[0] = client->addr << 1;
++ msg->buf[0] = event == I2C_SLAVE_GCALL_REQUESTED ?
++ 0 : client->addr << 1;
+ break;
+
+ case I2C_SLAVE_WRITE_RECEIVED:
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index b4055d133338..52369ea150b4 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -365,6 +365,7 @@ enum i2c_slave_event {
+ I2C_SLAVE_WRITE_REQUESTED,
+ I2C_SLAVE_READ_PROCESSED,
+ I2C_SLAVE_WRITE_RECEIVED,
++ I2C_SLAVE_GCALL_REQUESTED,
+ I2C_SLAVE_STOP,
+ };
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch
new file mode 100644
index 000000000..925880eff
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch
@@ -0,0 +1,34 @@
+From 7854a5e094ac49bebf9b2bfdd44db2f8cdd37543 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Fri, 31 May 2019 15:05:13 -0700
+Subject: [PATCH] set idle-disconnect to true in all cases
+
+From sysfs this parameter can't be set. We want the
+muxes to clean themselves up if possible. Set this to
+true.
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ drivers/i2c/muxes/i2c-mux-pca954x.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
+index 923aa3a5a3dc..084c10951890 100644
+--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
++++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
+@@ -474,8 +474,12 @@ static int pca954x_probe(struct i2c_client *client,
+ data->last_chan = 0; /* force the first selection */
+ data->idle_state = MUX_IDLE_AS_IS;
+
++#if 1 /* Forcibly set the self-disconnect flag */
++ idle_disconnect_dt = true;
++#else
+ idle_disconnect_dt = np &&
+ of_property_read_bool(np, "i2c-mux-idle-disconnect");
++#endif
+ if (idle_disconnect_dt)
+ data->idle_state = MUX_IDLE_DISCONNECT;
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
new file mode 100644
index 000000000..0e8a2b101
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
@@ -0,0 +1,191 @@
+From b429cf11ecb2f6009dd9e062ea5e053718802d93 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 11 Jul 2019 13:53:34 -0700
+Subject: [PATCH] i2c: aspeed: add H/W timeout support
+
+This commit adds I2C H/W timeout support.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 82 ++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 76 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 4420899e2c2d..830b3d2cabad 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -55,6 +55,7 @@
+ /* Device Register Definition */
+ /* 0x00 : I2CD Function Control Register */
+ #define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20)
++#define ASPEED_I2CD_BUS_AUTO_RECOVERY_EN BIT(17)
+ #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15)
+ #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
+ #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
+@@ -71,10 +72,14 @@
+ #define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16)
+ #define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12
+ #define ASPEED_I2CD_TIME_SCL_LOW_MASK GENMASK(15, 12)
++#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT 8
++#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK GENMASK(9, 8)
+ #define ASPEED_I2CD_TIME_BASE_DIVISOR_MASK GENMASK(3, 0)
+ #define ASPEED_I2CD_TIME_SCL_REG_MAX GENMASK(3, 0)
++
+ /* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+-#define ASPEED_NO_TIMEOUT_CTRL 0
++#define ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT 0
++#define ASPEED_I2CD_TIMEOUT_CYCLES_MASK GENMASK(4, 0)
+
+ /* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+@@ -82,6 +87,7 @@
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
++#define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15)
+ #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
+ #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
+ #define ASPEED_I2CD_INTR_GCALL_ADDR BIT(8)
+@@ -98,8 +104,11 @@
+ ASPEED_I2CD_INTR_SCL_TIMEOUT | \
+ ASPEED_I2CD_INTR_ABNORMAL | \
+ ASPEED_I2CD_INTR_ARBIT_LOSS)
++#define ASPEED_I2CD_INTR_SLAVE_ERRORS \
++ ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT
+ #define ASPEED_I2CD_INTR_ALL \
+- (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
++ (ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT | \
++ ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
+ ASPEED_I2CD_INTR_BUS_RECOVER_DONE | \
+ ASPEED_I2CD_INTR_SCL_TIMEOUT | \
+ ASPEED_I2CD_INTR_ABNORMAL | \
+@@ -186,6 +195,7 @@ struct aspeed_i2c_bus {
+ u32 divisor);
+ unsigned long parent_clk_frequency;
+ u32 bus_frequency;
++ u32 hw_timeout_ms;
+ /* Transaction state. */
+ enum aspeed_i2c_master_state master_state;
+ struct i2c_msg *msgs;
+@@ -303,6 +313,14 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+ }
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
++static int aspeed_i2c_check_slave_error(u32 irq_status)
++{
++ if (irq_status & ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT)
++ return -EIO;
++
++ return 0;
++}
++
+ static inline void
+ aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
+ u8 *value)
+@@ -421,6 +439,14 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ if (!slave)
+ return 0;
+
++ if (aspeed_i2c_check_slave_error(irq_status)) {
++ dev_dbg(bus->dev, "received slave error interrupt: 0x%08x\n",
++ irq_status);
++ irq_handled |= (irq_status & ASPEED_I2CD_INTR_SLAVE_ERRORS);
++ bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
++ return irq_handled;
++ }
++
+ command = readl(bus->base + ASPEED_I2C_CMD_REG);
+
+ /* Slave was requested, restart state machine. */
+@@ -681,7 +707,7 @@ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
+ }
+ }
+
+-static int aspeed_i2c_is_irq_error(u32 irq_status)
++static int aspeed_i2c_check_master_error(u32 irq_status)
+ {
+ if (irq_status & ASPEED_I2CD_INTR_ARBIT_LOSS)
+ return -EAGAIN;
+@@ -840,9 +866,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ * should clear the command queue effectively taking us back to the
+ * INACTIVE state.
+ */
+- ret = aspeed_i2c_is_irq_error(irq_status);
++ ret = aspeed_i2c_check_master_error(irq_status);
+ if (ret) {
+- dev_dbg(bus->dev, "received error interrupt: 0x%08x\n",
++ dev_dbg(bus->dev, "received master error interrupt: 0x%08x\n",
+ irq_status);
+ irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS);
+ if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
+@@ -1307,6 +1333,7 @@ static u32 aspeed_i2c_25xx_get_clk_reg_val(struct device *dev, u32 divisor)
+ /* precondition: bus.lock has been acquired. */
+ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
+ {
++ u32 timeout_base_divisor, timeout_tick_us, timeout_cycles;
+ u32 divisor, clk_reg_val;
+
+ divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
+@@ -1315,8 +1342,46 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
+ ASPEED_I2CD_TIME_THDSTA_MASK |
+ ASPEED_I2CD_TIME_TACST_MASK);
+ clk_reg_val |= bus->get_clk_reg_val(bus->dev, divisor);
++
++ if (bus->hw_timeout_ms) {
++ u8 div_max = ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK >>
++ ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT;
++ u8 cycles_max = ASPEED_I2CD_TIMEOUT_CYCLES_MASK >>
++ ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT;
++
++ timeout_base_divisor = 0;
++
++ do {
++ timeout_tick_us = 1000 * (16384 <<
++ (timeout_base_divisor << 1)) /
++ (bus->parent_clk_frequency / 1000);
++
++ if (timeout_base_divisor == div_max ||
++ timeout_tick_us * ASPEED_I2CD_TIMEOUT_CYCLES_MASK >=
++ bus->hw_timeout_ms * 1000)
++ break;
++ } while (timeout_base_divisor++ < div_max);
++
++ if (timeout_tick_us) {
++ timeout_cycles = DIV_ROUND_UP(bus->hw_timeout_ms * 1000,
++ timeout_tick_us);
++ if (timeout_cycles == 0)
++ timeout_cycles = 1;
++ else if (timeout_cycles > cycles_max)
++ timeout_cycles = cycles_max;
++ } else {
++ timeout_cycles = 0;
++ }
++ } else {
++ timeout_base_divisor = 0;
++ timeout_cycles = 0;
++ }
++
++ clk_reg_val |= FIELD_PREP(ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK,
++ timeout_base_divisor);
++
+ writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
+- writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
++ writel(timeout_cycles, bus->base + ASPEED_I2C_AC_TIMING_REG2);
+
+ return 0;
+ }
+@@ -1331,6 +1396,11 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+ /* Disable everything. */
+ writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
+
++ device_property_read_u32(&pdev->dev, "aspeed,hw-timeout-ms",
++ &bus->hw_timeout_ms);
++ if (bus->hw_timeout_ms)
++ fun_ctrl_reg |= ASPEED_I2CD_BUS_AUTO_RECOVERY_EN;
++
+ ret = aspeed_i2c_init_clk(bus);
+ if (ret < 0)
+ return ret;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch
new file mode 100644
index 000000000..104279ace
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch
@@ -0,0 +1,50 @@
+From b43bdeb5f3aa297549655e67f0e6a5db5f592e34 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 11 Jul 2019 14:04:39 -0700
+Subject: [PATCH] i2c: aspeed: add SLAVE_ADDR_RECEIVED_PENDING interrupt
+ handling
+
+If a peer master sends messages too quickly before it processes
+previous slave DMA data handling, this indicator will be set. It's
+just a indicator and driver can't recover this case so just ignore
+it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 830b3d2cabad..a308d5896632 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -87,6 +87,7 @@
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
++#define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(30)
+ #define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15)
+ #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
+ #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
+@@ -468,6 +469,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
+ irq_status, command);
+
++ /*
++ * If a peer master sends messages too quickly before it processes
++ * previous slave DMA data handling, this indicator will be set. It's
++ * just a indicator and driver can't recover this case so just ignore
++ * it.
++ */
++ if (unlikely(irq_status &
++ ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING)) {
++ dev_dbg(bus->dev, "A slave addr match interrupt is pending.\n");
++ irq_handled |= ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING;
++ }
++
+ /* Slave was sent something. */
+ if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
+ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch
new file mode 100644
index 000000000..5c3e35016
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch
@@ -0,0 +1,44 @@
+From 0bda96c5fe3064c71f190bc484e2ce59c51d5585 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 19 Jul 2019 12:54:38 -0700
+Subject: [PATCH] gpio: aspeed: temporary fix for gpiochip range setting
+
+Since we are still using fixed indices for gpio line numbers for sysfs
+interface, this commit set the gpiochip range as fixed temporariliy
+til we replace all index based gpio uses with name based uses.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/gpio/gpio-aspeed.c | 2 +-
+ drivers/gpio/sgpio-aspeed.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 39c50c53dae3..05945470bd89 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -1181,7 +1181,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ gpio->chip.set = aspeed_gpio_set;
+ gpio->chip.set_config = aspeed_gpio_set_config;
+ gpio->chip.label = dev_name(&pdev->dev);
+- gpio->chip.base = -1;
++ gpio->chip.base = 0;
+
+ /* Allocate a cache of the output registers */
+ banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
+diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c
+index 5028e9144a75..850539da43f5 100644
+--- a/drivers/gpio/sgpio-aspeed.c
++++ b/drivers/gpio/sgpio-aspeed.c
+@@ -681,7 +681,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
+ gpio->chip.set = aspeed_sgpio_set;
+ gpio->chip.set_config = aspeed_sgpio_set_config;
+ gpio->chip.label = dev_name(&pdev->dev);
+- gpio->chip.base = -1;
++ gpio->chip.base = gpio->config->nr_pgpios;
+
+ rc = aspeed_sgpio_setup_irqs(gpio, pdev);
+ if (rc < 0)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch
new file mode 100644
index 000000000..40a9272e0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch
@@ -0,0 +1,88 @@
+From e360a6c2a3f15bfc8900c7262c56f9bcd5e0f16e Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 8 Aug 2019 10:38:00 -0700
+Subject: [PATCH] pmbus: add 'fault' and 'beep' attributes
+
+This commit adds two more attirbutes to reflect MFR_SPECIFIC bit in
+the STATUS_WORD and 'Unit Off For Insufficient Input Voltage' bit in
+the STATUS_INPUT into 'fault' and 'beep' attributes respectively.
+
+The attributes will be enumerated as 'inX_fault' and 'inX_beep' in
+a 'vin' group.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/hwmon/pmbus/pmbus.h | 1 +
+ drivers/hwmon/pmbus/pmbus_core.c | 30 ++++++++++++++++++++++++++++++
+ 2 files changed, 31 insertions(+)
+
+diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
+index d198af3a92b6..09e6fe01c304 100644
+--- a/drivers/hwmon/pmbus/pmbus.h
++++ b/drivers/hwmon/pmbus/pmbus.h
+@@ -303,6 +303,7 @@ enum pmbus_fan_mode { percent = 0, rpm };
+ #define PB_PIN_OP_WARNING BIT(0)
+ #define PB_IIN_OC_WARNING BIT(1)
+ #define PB_IIN_OC_FAULT BIT(2)
++#define PB_UNIT_OFF_FOR_INSUF_VIN BIT(3)
+
+ /*
+ * STATUS_TEMPERATURE
+diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
+index 898d7378f4f8..85295a45c3ba 100644
+--- a/drivers/hwmon/pmbus/pmbus_core.c
++++ b/drivers/hwmon/pmbus/pmbus_core.c
+@@ -1163,6 +1163,8 @@ struct pmbus_limit_attr {
+ struct pmbus_sensor_attr {
+ u16 reg; /* sensor register */
+ u16 gbit; /* generic status bit */
++ u16 gfbit; /* generic fault status bit */
++ u16 sbbit; /* beep status bit */
+ u8 nlimit; /* # of limit registers */
+ enum pmbus_sensor_classes class;/* sensor class */
+ const char *label; /* sensor label */
+@@ -1264,6 +1266,32 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
+ return ret;
+ }
+ }
++ /*
++ * Add fault attribute if there is a generic fault bit, and if
++ * the generic status register (word or byte, depending on which global
++ * bit is set) for this page is accessible.
++ */
++ if (attr->gfbit) {
++ upper = !!(attr->gfbit & 0xff00); /* need to check STATUS_WORD */
++ if ((!upper || (upper && data->has_status_word)) &&
++ pmbus_check_status_register(client, page)) {
++ ret = pmbus_add_boolean(data, name, "fault", index,
++ NULL, NULL,
++ PB_STATUS_BASE + page,
++ attr->gfbit);
++ if (ret)
++ return ret;
++ }
++ }
++ /* Add beep attribute if there is a beep status bit. */
++ if (attr->sbbit) {
++ ret = pmbus_add_boolean(data, name, "beep", index,
++ NULL, NULL,
++ attr->sbase + page,
++ attr->sbbit);
++ if (ret)
++ return ret;
++ }
+ return 0;
+ }
+
+@@ -1435,6 +1463,8 @@ static const struct pmbus_sensor_attr voltage_attributes[] = {
+ .gbit = PB_STATUS_VIN_UV,
+ .limit = vin_limit_attrs,
+ .nlimit = ARRAY_SIZE(vin_limit_attrs),
++ .gfbit = PB_STATUS_WORD_MFR,
++ .sbbit = PB_UNIT_OFF_FOR_INSUF_VIN,
+ }, {
+ .reg = PMBUS_VIRT_READ_VMON,
+ .class = PSC_VOLTAGE_IN,
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch
new file mode 100644
index 000000000..1056b3beb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch
@@ -0,0 +1,155 @@
+From 5c82e0b33f2a373d5e19569635f108cfa096f53e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Adrian=20Ambro=C5=BCewicz?= <adrian.ambrozewicz@intel.com>
+Date: Mon, 29 Jul 2019 10:19:00 +0200
+Subject: [PATCH] Add IO statistics to USB Mass storage gadget
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Introduces new attribute to Mass Storage Gadget ConfigFS : stats.
+It's read-only attribute which contains statistics of read/write operations
+based on LUN transaction counters (IO number and bytes transferred).
+
+Goal is to provide a way to observe whether simulated device is actually
+used by host. Statistics on hosted file / nbd level are not always viable
+due to page cache having severe impact on actual IO statistics.
+This attribute should provide information about host IO on USB Gadget as
+close to endpoint as possible.
+
+Attribute is tied completely to configFS implementation and it's lifecycle
+is managed by Kernel and user. Driver implements a handler which populates
+output buffer on read.
+
+Tests performed:
+- mounted USB Mass Storage gadget, new attribute showed up in gadget tree
+- attribute was monitored for changes during IO performed on host machine
+- removed device, attribute (along with other device attributes) was gone
+
+Signed-off-by: Adrian Ambrożewicz <adrian.ambrozewicz@intel.com>
+---
+ drivers/usb/gadget/function/f_mass_storage.c | 12 ++++++++++++
+ drivers/usb/gadget/function/storage_common.c | 9 +++++++++
+ drivers/usb/gadget/function/storage_common.h | 29 ++++++++++++++++++++++++++++
+ 3 files changed, 50 insertions(+)
+
+diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
+index 7c96c4665178..ecc3c68a7882 100644
+--- a/drivers/usb/gadget/function/f_mass_storage.c
++++ b/drivers/usb/gadget/function/f_mass_storage.c
+@@ -710,6 +710,8 @@ static int do_read(struct fsg_common *common)
+ amount_left -= nread;
+ common->residue -= nread;
+
++ fsg_stats_rd_attempt(&curlun->stats, nread);
++
+ /*
+ * Except at the end of the transfer, nread will be
+ * equal to the buffer size, which is divisible by the
+@@ -907,6 +909,8 @@ static int do_write(struct fsg_common *common)
+ amount_left_to_write -= nwritten;
+ common->residue -= nwritten;
+
++ fsg_stats_wr_attempt(&curlun->stats, nwritten);
++
+ /* If an error occurred, report it and its position */
+ if (nwritten < amount) {
+ curlun->sense_data = SS_WRITE_ERROR;
+@@ -3122,6 +3126,13 @@ static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item,
+
+ CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string);
+
++static ssize_t fsg_lun_opts_stats_show(struct config_item *item, char *page)
++{
++ return fsg_show_stats(to_fsg_lun_opts(item)->lun, page);
++}
++
++CONFIGFS_ATTR_RO(fsg_lun_opts_, stats);
++
+ static struct configfs_attribute *fsg_lun_attrs[] = {
+ &fsg_lun_opts_attr_file,
+ &fsg_lun_opts_attr_ro,
+@@ -3129,6 +3140,7 @@ static struct configfs_attribute *fsg_lun_attrs[] = {
+ &fsg_lun_opts_attr_cdrom,
+ &fsg_lun_opts_attr_nofua,
+ &fsg_lun_opts_attr_inquiry_string,
++ &fsg_lun_opts_attr_stats,
+ NULL,
+ };
+
+diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c
+index f7e6c42558eb..2325b97961df 100644
+--- a/drivers/usb/gadget/function/storage_common.c
++++ b/drivers/usb/gadget/function/storage_common.c
+@@ -371,6 +371,15 @@ ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf)
+ }
+ EXPORT_SYMBOL_GPL(fsg_show_inquiry_string);
+
++ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf)
++{
++ return sprintf(buf, "read cnt: %u\n" "read sum: %llu\n"
++ "write cnt: %u\n" "write sum: %llu\n",
++ curlun->stats.read.count, curlun->stats.read.bytes,
++ curlun->stats.write.count, curlun->stats.write.bytes);
++}
++EXPORT_SYMBOL_GPL(fsg_show_stats);
++
+ /*
+ * The caller must hold fsg->filesem for reading when calling this function.
+ */
+diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
+index e5e3a2553aaa..447021ba821a 100644
+--- a/drivers/usb/gadget/function/storage_common.h
++++ b/drivers/usb/gadget/function/storage_common.h
+@@ -95,6 +95,32 @@ do { \
+ */
+ #define INQUIRY_STRING_LEN ((size_t) (8 + 16 + 4 + 1))
+
++struct fsg_stats_cnt {
++ u64 bytes;
++ u32 count;
++};
++
++struct fsg_stats {
++ struct fsg_stats_cnt read;
++ struct fsg_stats_cnt write;
++};
++
++static inline void fsg_stats_update(struct fsg_stats_cnt *cnt, u64 diff)
++{
++ cnt->count++;
++ cnt->bytes += diff;
++}
++
++static inline void fsg_stats_wr_attempt(struct fsg_stats *stats, u64 b_written)
++{
++ fsg_stats_update(&stats->write, b_written);
++}
++
++static inline void fsg_stats_rd_attempt(struct fsg_stats *stats, u64 b_read)
++{
++ fsg_stats_update(&stats->read, b_read);
++}
++
+ struct fsg_lun {
+ struct file *filp;
+ loff_t file_length;
+@@ -120,6 +146,8 @@ struct fsg_lun {
+ const char *name; /* "lun.name" */
+ const char **name_pfx; /* "function.name" */
+ char inquiry_string[INQUIRY_STRING_LEN];
++
++ struct fsg_stats stats;
+ };
+
+ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+@@ -213,6 +241,7 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+ ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf);
+ ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf);
+ ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf);
++ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf);
+ ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+ const char *buf, size_t count);
+ ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch
new file mode 100644
index 000000000..52c3617d6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch
@@ -0,0 +1,64 @@
+From 93ba2aeb9ad3899e2b72877daa47376a6bf192b6 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 23 Sep 2019 13:48:49 -0700
+Subject: [PATCH] Refine initialization flow in I2C driver
+
+Since we enabled I2C busses in u-boot, we need to disable the I2C
+bus and clear all garbage interrupts when kernel probes the bus.
+This commit refines the initialization flow by adding a bus reset
+at the beginning of probe function and by moving bus init function
+after interrupt handling setup.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index a308d5896632..b32611088c82 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -1588,6 +1588,11 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+
+ bus->dev = &pdev->dev;
+
++ /* Disable bus and clean up any left over interrupt state. */
++ writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
++ writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
++ writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
++
+ parent_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+@@ -1630,17 +1635,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
+ i2c_set_adapdata(&bus->adap, bus);
+
+- /* Clean up any left over interrupt state. */
+- writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
+- writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
+- /*
+- * bus.lock does not need to be held because the interrupt handler has
+- * not been enabled yet.
+- */
+- ret = aspeed_i2c_init(bus, pdev);
+- if (ret < 0)
+- goto out_free_dma_buf;
+-
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq,
+ 0, dev_name(&pdev->dev), bus);
+@@ -1653,6 +1647,10 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, bus);
+
++ ret = aspeed_i2c_init(bus, pdev);
++ if (ret < 0)
++ goto out_free_dma_buf;
++
+ dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n",
+ bus->adap.nr, bus->dma_buf ? "dma" :
+ bus->buf_base ? "buffer" : "byte",
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch
new file mode 100644
index 000000000..9515a1a89
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch
@@ -0,0 +1,1107 @@
+From a17a084c4889dcc7cb43ef5f93032997cfcee4f0 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@intel.com>
+Date: Fri, 27 Sep 2019 13:09:48 -0700
+Subject: [PATCH] arm: ast2600: add pwm_tacho driver from aspeed
+
+Add the pwm_tacho driver from Aspeed to get pwm working until an
+upstream PWM/Tacho driver is available. This was copied from the v5.02
+BSP from Aspeed.
+
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 10 +
+ drivers/hwmon/Kconfig | 11 +
+ drivers/hwmon/Makefile | 1 +
+ drivers/hwmon/aspeed-g6-pwm-tacho.c | 1025 +++++++++++++++++++++++++++++++++++
+ 4 files changed, 1047 insertions(+)
+ create mode 100644 drivers/hwmon/aspeed-g6-pwm-tacho.c
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index eeace4b7b725..33fcd89db6b8 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -278,6 +278,16 @@
+ #size-cells = <1>;
+ ranges;
+
++ pwm_tacho: pwm-tacho-controller@1e610000 {
++ compatible = "aspeed,ast2600-pwm-tacho";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x1e610000 0x100>;
++ clocks = <&syscon ASPEED_CLK_AHB>;
++ resets = <&syscon ASPEED_RESET_PWM>;
++ status = "disabled";
++ };
++
+ syscon: syscon@1e6e2000 {
+ compatible = "aspeed,ast2600-scu", "syscon", "simple-mfd";
+ reg = <0x1e6e2000 0x1000>;
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index e244a7901392..8312b3798b82 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -371,6 +371,17 @@ config SENSORS_ASPEED
+ This driver can also be built as a module. If so, the module
+ will be called aspeed_pwm_tacho.
+
++config SENSORS_ASPEED_G6
++ tristate "ASPEED AST2600 PWM and Fan tach driver"
++ depends on THERMAL || THERMAL=n
++ select REGMAP
++ help
++ This driver provides support for ASPEED AST2600 PWM
++ and Fan Tacho controllers.
++
++ This driver can also be built as a module. If so, the module
++ will be called aspeed_g6_pwm_tacho.
++
+ config SENSORS_ATXP1
+ tristate "Attansic ATXP1 VID controller"
+ depends on I2C
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 1c7ab361adc7..e74ea925fb56 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -50,6 +50,7 @@ obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
+ obj-$(CONFIG_SENSORS_AS370) += as370-hwmon.o
+ obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
+ obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o
++obj-$(CONFIG_SENSORS_ASPEED_G6) += aspeed-g6-pwm-tacho.o
+ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
+ obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
+ obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
+diff --git a/drivers/hwmon/aspeed-g6-pwm-tacho.c b/drivers/hwmon/aspeed-g6-pwm-tacho.c
+new file mode 100644
+index 000000000000..1894f6ad5edb
+--- /dev/null
++++ b/drivers/hwmon/aspeed-g6-pwm-tacho.c
+@@ -0,0 +1,1025 @@
++/*
++ * Copyright (C) ASPEED Technology Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 or later as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/clk.h>
++#include <linux/errno.h>
++#include <linux/gpio/consumer.h>
++#include <linux/delay.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/sysfs.h>
++#include <linux/reset.h>
++#include <linux/regmap.h>
++#include <linux/thermal.h>
++
++#define ASPEED_PWM_CTRL 0x00 //PWM0 General Register
++#define ASPEED_PWM_CTRL_CH(x) ((x * 0x10) + 0x00)
++#define PWM_LOAD_AS_WDT BIT(19) //load selection as WDT
++#define PWM_DUTY_LOAD_AS_WDT_EN BIT(18) //enable PWM duty load as WDT
++#define PWM_DUTY_SYNC_DIS BIT(17) //disable PWM duty sync
++#define PWM_CLK_ENABLE BIT(16) //enable PWM clock
++#define PWM_LEVEL_OUTPUT BIT(15) //output PWM level
++#define PWM_INVERSE BIT(14) //inverse PWM pin
++#define PWM_OPEN_DRAIN_EN BIT(13) //enable open-drain
++#define PWM_PIN_EN BIT(12) //enable PWM pin
++#define PWM_CLK_DIV_H_MASK (0xf << 8) //PWM clock division H bit [3:0]
++#define PWM_CLK_DIV_L_MASK (0xff) //PWM clock division H bit [3:0]
++
++/*
++\xregmid {11:8 }{RW}{PWM clock division H bit [3:0]}{
++ 0: divide 1 \n
++ 1: divide 2 \n
++ 2: divide 4 \n
++ 3: divide 8 \n
++ ... \n
++ F: divide 32768}
++\xregmid {7 :0 }{RW}{PWM clock division L bit [7:0]}{
++ 00: divide 1 \n
++ 01: divide 2 \n
++ 02: divide 3 \n
++ 03: divide 4 \n
++ ... \n
++ FF: divide 256}
++*/
++
++#define ASPEED_PWM_DUTY_CYCLE 0x04 //PWM0 Duty Cycle Register
++#define ASPEED_PWM_DUTY_CYCLE_CH(x) ((x * 0x10) + 0x04)
++#define PWM_LOOP_BIT_MASK (0xf << 24) //loop bit [7:0]
++#define PWM_PERIOD_BIT (24) //pwm period bit [7:0]
++#define PWM_PERIOD_BIT_MASK (0xff << 24) //pwm period bit [7:0]
++#define PWM_RISING_FALLING_AS_WDT_BIT (16)
++#define PWM_RISING_FALLING_AS_WDT_MASK (0xff << 16) //pwm rising/falling point bit [7:0] as WDT
++#define PWM_RISING_FALLING_MASK (0xffff)
++#define PWM_RISING_FALLING_BIT (8) //pwm falling point bit [7:0]
++#define PWM_RISING_RISING_BIT (0) //pwm rising point bit [7:0]
++
++#define ASPEED_TACHO_CTRL 0x08 //TACH0 General Register
++#define ASPEED_TACHO_CTRL_CH(x) ((x * 0x10) + 0x08)
++#define TACHO_IER BIT(31) //enable tacho interrupt
++#define TACHO_INVERS_LIMIT BIT(30) //inverse tacho limit comparison
++#define TACHO_LOOPBACK BIT(29) //tacho loopback
++#define TACHO_ENABLE BIT(28) //{enable tacho}
++#define TACHO_DEBOUNCE_BIT (26) //{tacho de-bounce}
++#define TACHO_DEBOUNCE_MASK (0x3 << 26) //{tacho de-bounce}
++#define TECHIO_EDGE_MASK (0x3 << 24) //tacho edge}
++#define TECHIO_EDGE_BIT (24) //tacho edge}
++#define TACHO_CLK_DIV_T_MASK (0xf << 20)
++#define TACHO_CLK_DIV_BIT (20)
++#define TACHO_THRESHOLD_MASK (0xfffff) //tacho threshold bit
++/*
++\xregmid {23:20}{RW}{tacho clock division T bit [3:0]}{
++ 0: divide 1 \n
++ 1: divide 4 \n
++ 2: divide 16 \n
++ 3: divide 64 \n
++ ... \n
++ B: divide 4194304 \n
++ others: reserved}
++\xregmidb{19 :0 }{RW}{tacho threshold bit [19:0]}
++*/
++
++#define ASPEED_TACHO_STS 0x0C //TACH0 Status Register
++#define ASPEED_TACHO_STS_CH(x) ((x * 0x10) + 0x0C)
++#define TACHO_ISR BIT(31) //interrupt status and clear
++#define PWM_OUT BIT(25) //{pwm_out}
++#define PWM_OEN BIT(24) //{pwm_oeN}
++#define TACHO_DEB_INPUT BIT(23) //tacho deB input
++#define TACHO_RAW_INPUT BIT(22) //tacho raw input}
++#define TACHO_VALUE_UPDATE BIT(21) //tacho value updated since the last read
++#define TACHO_FULL_MEASUREMENT BIT(20) //{tacho full measurement}
++#define TACHO_VALUE_MASK 0xfffff //tacho value bit [19:0]}
++
++#define MAX_CDEV_NAME_LEN 16
++
++struct aspeed_pwm_channel_params {
++ int load_wdt_rising_falling_pt;
++ int load_wdt_selection; //0: rising , 1: falling
++ int load_wdt_enable;
++ int duty_sync_enable;
++ int invert_pin;
++ u8 divide_h;
++ u8 divide_l;
++ u8 period;
++ u8 rising;
++ u8 falling;
++};
++
++static struct aspeed_pwm_channel_params default_pwm_params[] = {
++ [0] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 1,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [1] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [2] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [3] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [4] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [5] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [6] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [7] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [8] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [9] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [10] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [11] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [12] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [13] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [14] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++ [15] = {
++ .load_wdt_rising_falling_pt = 0x10,
++ .load_wdt_selection = 0,
++ .load_wdt_enable = 0,
++ .duty_sync_enable = 0,
++ .invert_pin = 0,
++ .divide_h = 0x5,
++ .divide_l = 0x6,
++ .period = 0x13, //5% ~~
++ .rising = 0x00,
++ .falling = 0x0a,
++ },
++};
++
++/*
++ * 5:4 fan tach edge mode selection bit:
++ * 00: falling
++ * 01: rising
++ * 10: both
++ * 11: reserved.
++ */
++
++struct aspeed_tacho_channel_params {
++ int limited_inverse;
++ u16 threshold;
++ u8 tacho_edge;
++ u8 tacho_debounce;
++ u8 divide;
++};
++
++
++static struct aspeed_tacho_channel_params default_tacho_params[] = {
++ [0] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [1] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [2] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [3] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [4] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [5] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [6] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [7] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [8] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [9] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [10] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [11] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [12] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [13] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [14] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++ [15] = {
++ .limited_inverse = 0,
++ .threshold = 0,
++ .tacho_edge = 0,
++ .tacho_debounce = 0,
++ .divide = 8,
++ },
++};
++
++struct aspeed_pwm_tachometer_data {
++ struct regmap *regmap;
++ unsigned long clk_freq;
++ struct reset_control *reset;
++ bool pwm_present[16];
++ bool fan_tach_present[16];
++ struct aspeed_pwm_channel_params *pwm_channel;
++ struct aspeed_tacho_channel_params *tacho_channel;
++ struct aspeed_cooling_device *cdev[8];
++ const struct attribute_group *groups[3];
++};
++
++struct aspeed_cooling_device {
++ char name[16];
++ struct aspeed_pwm_tachometer_data *priv;
++ struct thermal_cooling_device *tcdev;
++ int pwm_channel;
++ u8 *cooling_levels;
++ u8 max_state;
++ u8 cur_state;
++};
++
++static int regmap_aspeed_pwm_tachometer_reg_write(void *context, unsigned int reg,
++ unsigned int val)
++{
++ void __iomem *regs = (void __iomem *)context;
++
++ writel(val, regs + reg);
++ return 0;
++}
++
++static int regmap_aspeed_pwm_tachometer_reg_read(void *context, unsigned int reg,
++ unsigned int *val)
++{
++ void __iomem *regs = (void __iomem *)context;
++
++ *val = readl(regs + reg);
++ return 0;
++}
++
++static const struct regmap_config aspeed_pwm_tachometer_regmap_config = {
++ .reg_bits = 32,
++ .val_bits = 32,
++ .reg_stride = 4,
++ .max_register = 0x100,
++ .reg_write = regmap_aspeed_pwm_tachometer_reg_write,
++ .reg_read = regmap_aspeed_pwm_tachometer_reg_read,
++ .fast_io = true,
++};
++
++static void aspeed_set_pwm_channel_enable(struct regmap *regmap, u8 pwm_channel,
++ bool enable)
++{
++ regmap_update_bits(regmap, ASPEED_PWM_CTRL_CH(pwm_channel), (PWM_CLK_ENABLE | PWM_PIN_EN), enable ? (PWM_CLK_ENABLE | PWM_PIN_EN) : 0);
++}
++
++static void aspeed_set_fan_tach_ch_enable(struct aspeed_pwm_tachometer_data *priv, u8 fan_tach_ch,
++ bool enable)
++{
++ u32 i = 0, j;
++ u32 divide_val = 0;
++ u32 reg_value = 0;
++
++ if(enable) {
++ //4 ^ n
++ //check pwm clk and to change tacho devide 25KZ
++ for(i = 0; i < 12; i++) {
++ divide_val = 1;
++ for (j = 1; j <= i; j++)
++ divide_val *= 4;
++// printk("i : %d , priv->clk_freq/divide_val %d ",i, priv->clk_freq/divide_val);
++ if((priv->clk_freq/divide_val) < 250000)
++ break;
++ }
++ i--;
++ divide_val = ((1 << i) * (1 << i));
++// printk("tacho divide_val %d , i %x max tacho clk %d \n", divide_val, i, priv->clk_freq / divide_val);
++ priv->tacho_channel[fan_tach_ch].divide = i;
++
++ reg_value = TACHO_ENABLE |
++ (priv->tacho_channel[fan_tach_ch].tacho_edge << TECHIO_EDGE_BIT) |
++ (priv->tacho_channel[fan_tach_ch].divide << TACHO_CLK_DIV_BIT) |
++ (priv->tacho_channel[fan_tach_ch].tacho_debounce << TACHO_DEBOUNCE_BIT);
++
++ if(priv->tacho_channel[fan_tach_ch].limited_inverse)
++ reg_value |= TACHO_INVERS_LIMIT;
++
++ if(priv->tacho_channel[fan_tach_ch].threshold)
++ reg_value |= (TACHO_IER | priv->tacho_channel[fan_tach_ch].threshold);
++
++ regmap_write(priv->regmap, ASPEED_TACHO_CTRL_CH(fan_tach_ch), reg_value);
++ } else
++ regmap_update_bits(priv->regmap, ASPEED_TACHO_CTRL_CH(fan_tach_ch), TACHO_ENABLE, 0);
++}
++
++static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *priv,
++ u8 index, u8 fan_ctrl)
++{
++ u32 duty_value, ctrl_value;
++
++ if (fan_ctrl == 0) {
++ aspeed_set_pwm_channel_enable(priv->regmap, index, false);
++ } else {
++ duty_value = (priv->pwm_channel[index].period << PWM_PERIOD_BIT) |
++ (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT);
++
++ ctrl_value = (priv->pwm_channel[index].divide_h << 8) | priv->pwm_channel[index].divide_l;
++
++ if (priv->pwm_channel[index].load_wdt_enable) {
++ ctrl_value |= PWM_DUTY_LOAD_AS_WDT_EN;
++ if(priv->pwm_channel[index].load_wdt_selection) {
++ ctrl_value |= PWM_LOAD_AS_WDT;
++ duty_value |= (priv->pwm_channel[index].load_wdt_rising_falling_pt << PWM_RISING_FALLING_AS_WDT_BIT);
++ } else {
++ duty_value |= (priv->pwm_channel[index].load_wdt_rising_falling_pt << PWM_RISING_FALLING_AS_WDT_BIT);
++ }
++ }
++
++ regmap_write(priv->regmap, ASPEED_PWM_DUTY_CYCLE_CH(index), duty_value);
++
++ regmap_write(priv->regmap, ASPEED_PWM_CTRL_CH(index), ctrl_value);
++// printk("pwm clk is %d \n", priv->clk_freq / (priv->pwm_channel[index].period + 1));
++ aspeed_set_pwm_channel_enable(priv->regmap, index, true);
++ }
++}
++
++#define BOTH_EDGES 0x02 /* 10b */
++
++static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv,
++ u8 fan_tach_ch)
++{
++ u32 raw_data, tach_div, clk_source, val;
++ u8 mode, both;
++ int i, retries = 3;
++
++ for(i = 0; i < retries; i++) {
++ regmap_read(priv->regmap, ASPEED_TACHO_STS_CH(fan_tach_ch), &val);
++ if (TACHO_FULL_MEASUREMENT & val)
++ break;
++ }
++
++ raw_data = val & TACHO_VALUE_MASK;
++ if(raw_data == 0xfffff)
++ return 0;
++
++ tach_div = priv->tacho_channel[fan_tach_ch].divide;
++ /*
++ * We need the mode to determine if the raw_data is double (from
++ * counting both edges).
++ */
++ mode = priv->tacho_channel[fan_tach_ch].tacho_edge;
++ both = (mode & BOTH_EDGES) ? 1 : 0;
++// printk("clk %ld, raw_data %x , tach_div %x both %x \n", priv->clk_freq, raw_data, tach_div, both);
++
++ tach_div = (tach_div * 2) * (0x1 << both);
++ clk_source = priv->clk_freq;
++
++ if (raw_data == 0)
++ return 0;
++
++ return (clk_source * 60) / (2 * raw_data * tach_div);
++
++}
++
++static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
++ int index = sensor_attr->index;
++ int ret;
++ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
++ long fan_ctrl;
++
++ ret = kstrtol(buf, 10, &fan_ctrl);
++ if (ret != 0)
++ return ret;
++
++ if (fan_ctrl < 0 || fan_ctrl > priv->pwm_channel[index].period)
++ return -EINVAL;
++
++ if (priv->pwm_channel[index].falling == fan_ctrl)
++ return count;
++
++ priv->pwm_channel[index].falling = fan_ctrl;
++ aspeed_set_pwm_channel_fan_ctrl(priv, index, fan_ctrl);
++
++ return count;
++}
++
++static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
++ int index = sensor_attr->index;
++ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%u\n", priv->pwm_channel[index].falling);
++}
++
++static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
++ int index = sensor_attr->index;
++ int rpm;
++ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
++
++ rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
++ if (rpm < 0)
++ return rpm;
++
++ return sprintf(buf, "%d\n", rpm);
++}
++
++static umode_t pwm_is_visible(struct kobject *kobj,
++ struct attribute *a, int index)
++{
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
++
++ if (!priv->pwm_present[index])
++ return 0;
++ return a->mode;
++}
++
++static umode_t fan_dev_is_visible(struct kobject *kobj,
++ struct attribute *a, int index)
++{
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
++
++ if (!priv->fan_tach_present[index])
++ return 0;
++ return a->mode;
++}
++
++static SENSOR_DEVICE_ATTR(pwm0, 0644,
++ show_pwm, set_pwm, 0);
++static SENSOR_DEVICE_ATTR(pwm1, 0644,
++ show_pwm, set_pwm, 1);
++static SENSOR_DEVICE_ATTR(pwm2, 0644,
++ show_pwm, set_pwm, 2);
++static SENSOR_DEVICE_ATTR(pwm3, 0644,
++ show_pwm, set_pwm, 3);
++static SENSOR_DEVICE_ATTR(pwm4, 0644,
++ show_pwm, set_pwm, 4);
++static SENSOR_DEVICE_ATTR(pwm5, 0644,
++ show_pwm, set_pwm, 5);
++static SENSOR_DEVICE_ATTR(pwm6, 0644,
++ show_pwm, set_pwm, 6);
++static SENSOR_DEVICE_ATTR(pwm7, 0644,
++ show_pwm, set_pwm, 7);
++static SENSOR_DEVICE_ATTR(pwm8, 0644,
++ show_pwm, set_pwm, 8);
++static SENSOR_DEVICE_ATTR(pwm9, 0644,
++ show_pwm, set_pwm, 9);
++static SENSOR_DEVICE_ATTR(pwm10, 0644,
++ show_pwm, set_pwm, 10);
++static SENSOR_DEVICE_ATTR(pwm11, 0644,
++ show_pwm, set_pwm, 11);
++static SENSOR_DEVICE_ATTR(pwm12, 0644,
++ show_pwm, set_pwm, 12);
++static SENSOR_DEVICE_ATTR(pwm13, 0644,
++ show_pwm, set_pwm, 13);
++static SENSOR_DEVICE_ATTR(pwm14, 0644,
++ show_pwm, set_pwm, 14);
++static SENSOR_DEVICE_ATTR(pwm15, 0644,
++ show_pwm, set_pwm, 15);
++static struct attribute *pwm_dev_attrs[] = {
++ &sensor_dev_attr_pwm0.dev_attr.attr,
++ &sensor_dev_attr_pwm1.dev_attr.attr,
++ &sensor_dev_attr_pwm2.dev_attr.attr,
++ &sensor_dev_attr_pwm3.dev_attr.attr,
++ &sensor_dev_attr_pwm4.dev_attr.attr,
++ &sensor_dev_attr_pwm5.dev_attr.attr,
++ &sensor_dev_attr_pwm6.dev_attr.attr,
++ &sensor_dev_attr_pwm7.dev_attr.attr,
++ &sensor_dev_attr_pwm8.dev_attr.attr,
++ &sensor_dev_attr_pwm9.dev_attr.attr,
++ &sensor_dev_attr_pwm10.dev_attr.attr,
++ &sensor_dev_attr_pwm11.dev_attr.attr,
++ &sensor_dev_attr_pwm12.dev_attr.attr,
++ &sensor_dev_attr_pwm13.dev_attr.attr,
++ &sensor_dev_attr_pwm14.dev_attr.attr,
++ &sensor_dev_attr_pwm15.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group pwm_dev_group = {
++ .attrs = pwm_dev_attrs,
++ .is_visible = pwm_is_visible,
++};
++
++static SENSOR_DEVICE_ATTR(fan0_input, 0444,
++ show_rpm, NULL, 0);
++static SENSOR_DEVICE_ATTR(fan1_input, 0444,
++ show_rpm, NULL, 1);
++static SENSOR_DEVICE_ATTR(fan2_input, 0444,
++ show_rpm, NULL, 2);
++static SENSOR_DEVICE_ATTR(fan3_input, 0444,
++ show_rpm, NULL, 3);
++static SENSOR_DEVICE_ATTR(fan4_input, 0444,
++ show_rpm, NULL, 4);
++static SENSOR_DEVICE_ATTR(fan5_input, 0444,
++ show_rpm, NULL, 5);
++static SENSOR_DEVICE_ATTR(fan6_input, 0444,
++ show_rpm, NULL, 6);
++static SENSOR_DEVICE_ATTR(fan7_input, 0444,
++ show_rpm, NULL, 7);
++static SENSOR_DEVICE_ATTR(fan8_input, 0444,
++ show_rpm, NULL, 8);
++static SENSOR_DEVICE_ATTR(fan9_input, 0444,
++ show_rpm, NULL, 9);
++static SENSOR_DEVICE_ATTR(fan10_input, 0444,
++ show_rpm, NULL, 10);
++static SENSOR_DEVICE_ATTR(fan11_input, 0444,
++ show_rpm, NULL, 11);
++static SENSOR_DEVICE_ATTR(fan12_input, 0444,
++ show_rpm, NULL, 12);
++static SENSOR_DEVICE_ATTR(fan13_input, 0444,
++ show_rpm, NULL, 13);
++static SENSOR_DEVICE_ATTR(fan14_input, 0444,
++ show_rpm, NULL, 14);
++static SENSOR_DEVICE_ATTR(fan15_input, 0444,
++ show_rpm, NULL, 15);
++static struct attribute *fan_dev_attrs[] = {
++ &sensor_dev_attr_fan0_input.dev_attr.attr,
++ &sensor_dev_attr_fan1_input.dev_attr.attr,
++ &sensor_dev_attr_fan2_input.dev_attr.attr,
++ &sensor_dev_attr_fan3_input.dev_attr.attr,
++ &sensor_dev_attr_fan4_input.dev_attr.attr,
++ &sensor_dev_attr_fan5_input.dev_attr.attr,
++ &sensor_dev_attr_fan6_input.dev_attr.attr,
++ &sensor_dev_attr_fan7_input.dev_attr.attr,
++ &sensor_dev_attr_fan8_input.dev_attr.attr,
++ &sensor_dev_attr_fan9_input.dev_attr.attr,
++ &sensor_dev_attr_fan10_input.dev_attr.attr,
++ &sensor_dev_attr_fan11_input.dev_attr.attr,
++ &sensor_dev_attr_fan12_input.dev_attr.attr,
++ &sensor_dev_attr_fan13_input.dev_attr.attr,
++ &sensor_dev_attr_fan14_input.dev_attr.attr,
++ &sensor_dev_attr_fan15_input.dev_attr.attr,
++ NULL
++};
++
++static const struct attribute_group fan_dev_group = {
++ .attrs = fan_dev_attrs,
++ .is_visible = fan_dev_is_visible,
++};
++
++static void aspeed_create_pwm_channel(struct aspeed_pwm_tachometer_data *priv,
++ u8 pwm_channel)
++{
++ priv->pwm_present[pwm_channel] = true;
++
++ //use default
++ aspeed_set_pwm_channel_fan_ctrl(priv, pwm_channel, priv->pwm_channel[pwm_channel].falling);
++}
++
++static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tachometer_data *priv,
++ u8 *fan_tach_ch,
++ int count)
++{
++ u8 val, index;
++
++ for (val = 0; val < count; val++) {
++ index = fan_tach_ch[val];
++ priv->fan_tach_present[index] = true;
++ aspeed_set_fan_tach_ch_enable(priv, index, true);
++ }
++}
++
++static int
++aspeed_pwm_cz_get_max_state(struct thermal_cooling_device *tcdev,
++ unsigned long *state)
++{
++ struct aspeed_cooling_device *cdev = tcdev->devdata;
++
++ *state = cdev->max_state;
++
++ return 0;
++}
++
++static int
++aspeed_pwm_cz_get_cur_state(struct thermal_cooling_device *tcdev,
++ unsigned long *state)
++{
++ struct aspeed_cooling_device *cdev = tcdev->devdata;
++
++ *state = cdev->cur_state;
++
++ return 0;
++}
++
++static int
++aspeed_pwm_cz_set_cur_state(struct thermal_cooling_device *tcdev,
++ unsigned long state)
++{
++ struct aspeed_cooling_device *cdev = tcdev->devdata;
++
++ if (state > cdev->max_state)
++ return -EINVAL;
++
++ cdev->cur_state = state;
++ cdev->priv->pwm_channel[cdev->pwm_channel].falling =
++ cdev->cooling_levels[cdev->cur_state];
++ aspeed_set_pwm_channel_fan_ctrl(cdev->priv, cdev->pwm_channel,
++ cdev->cooling_levels[cdev->cur_state]);
++
++ return 0;
++}
++
++static const struct thermal_cooling_device_ops aspeed_pwm_cool_ops = {
++ .get_max_state = aspeed_pwm_cz_get_max_state,
++ .get_cur_state = aspeed_pwm_cz_get_cur_state,
++ .set_cur_state = aspeed_pwm_cz_set_cur_state,
++};
++
++static int aspeed_create_pwm_cooling(struct device *dev,
++ struct device_node *child,
++ struct aspeed_pwm_tachometer_data *priv,
++ u32 pwm_channel, u8 num_levels)
++{
++ int ret;
++ struct aspeed_cooling_device *cdev;
++
++ cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL);
++ if (!cdev)
++ return -ENOMEM;
++
++ cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL);
++ if (!cdev->cooling_levels)
++ return -ENOMEM;
++
++ cdev->max_state = num_levels - 1;
++ ret = of_property_read_u8_array(child, "cooling-levels",
++ cdev->cooling_levels,
++ num_levels);
++ if (ret) {
++ dev_err(dev, "Property 'cooling-levels' cannot be read.\n");
++ return ret;
++ }
++ snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_channel);
++
++ cdev->tcdev = thermal_of_cooling_device_register(child,
++ cdev->name,
++ cdev,
++ &aspeed_pwm_cool_ops);
++ if (IS_ERR(cdev->tcdev))
++ return PTR_ERR(cdev->tcdev);
++
++ cdev->priv = priv;
++ cdev->pwm_channel = pwm_channel;
++
++ priv->cdev[pwm_channel] = cdev;
++
++ return 0;
++}
++
++static int aspeed_pwm_create_fan(struct device *dev,
++ struct device_node *child,
++ struct aspeed_pwm_tachometer_data *priv)
++{
++ u8 *fan_tach_ch;
++ u32 pwm_channel;
++ int ret, count;
++
++ ret = of_property_read_u32(child, "reg", &pwm_channel);
++ if (ret)
++ return ret;
++
++ aspeed_create_pwm_channel(priv, (u8)pwm_channel);
++
++ ret = of_property_count_u8_elems(child, "cooling-levels");
++ if (ret > 0) {
++ ret = aspeed_create_pwm_cooling(dev, child, priv, pwm_channel,
++ ret);
++ if (ret)
++ return ret;
++ }
++
++ count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch");
++ if (count < 1)
++ return -EINVAL;
++
++ fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count,
++ GFP_KERNEL);
++ if (!fan_tach_ch)
++ return -ENOMEM;
++ ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch",
++ fan_tach_ch, count);
++ if (ret)
++ return ret;
++
++ aspeed_create_fan_tach_channel(priv, fan_tach_ch, count);
++
++ return 0;
++}
++
++static int aspeed_pwm_tachometer_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np, *child;
++ struct aspeed_pwm_tachometer_data *priv;
++ void __iomem *regs;
++ struct resource *res;
++ struct device *hwmon;
++ struct clk *clk;
++ int ret;
++
++ np = dev->of_node;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res)
++ return -ENOENT;
++ regs = devm_ioremap_resource(dev, res);
++ if (IS_ERR(regs))
++ return PTR_ERR(regs);
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->pwm_channel = default_pwm_params;
++ priv->tacho_channel = default_tacho_params;
++ priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
++ &aspeed_pwm_tachometer_regmap_config);
++ if (IS_ERR(priv->regmap))
++ return PTR_ERR(priv->regmap);
++
++ clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(clk))
++ return -ENODEV;
++ priv->clk_freq = clk_get_rate(clk);
++
++ priv->reset = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->reset)) {
++ dev_err(&pdev->dev, "can't get aspeed_pwm_tacho reset\n");
++ return PTR_ERR(priv->reset);
++ }
++
++ //scu init
++ reset_control_assert(priv->reset);
++ reset_control_deassert(priv->reset);
++
++ for_each_child_of_node(np, child) {
++ ret = aspeed_pwm_create_fan(dev, child, priv);
++ if (ret) {
++ of_node_put(child);
++ return ret;
++ }
++ }
++
++ priv->groups[0] = &pwm_dev_group;
++ priv->groups[1] = &fan_dev_group;
++ priv->groups[2] = NULL;
++ hwmon = devm_hwmon_device_register_with_groups(dev,
++ "aspeed_g6_pwm_tacho",
++ priv, priv->groups);
++
++ return PTR_ERR_OR_ZERO(hwmon);
++}
++
++static const struct of_device_id of_pwm_tachometer_match_table[] = {
++ { .compatible = "aspeed,ast2600-pwm-tacho", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, of_pwm_tachometer_match_table);
++
++static struct platform_driver aspeed_pwm_tachometer_driver = {
++ .probe = aspeed_pwm_tachometer_probe,
++ .driver = {
++ .name = "aspeed_g6_pwm_tacho",
++ .of_match_table = of_pwm_tachometer_match_table,
++ },
++};
++
++module_platform_driver(aspeed_pwm_tachometer_driver);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_DESCRIPTION("ASPEED PWM and Fan Tachometer device driver");
++MODULE_LICENSE("GPL");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch
new file mode 100644
index 000000000..7ea00a4a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch
@@ -0,0 +1,47 @@
+From f2d62c90f2ea05b1abf9a1887502122eefb5906d Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Wed, 16 Oct 2019 15:11:06 +0800
+Subject: [PATCH] soc: aspeed: Add read-only property support
+
+Add a read-only property, to support export register bits as read-only.
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ drivers/soc/aspeed/aspeed-bmc-misc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/soc/aspeed/aspeed-bmc-misc.c b/drivers/soc/aspeed/aspeed-bmc-misc.c
+index 314007b..bf88376 100644
+--- a/drivers/soc/aspeed/aspeed-bmc-misc.c
++++ b/drivers/soc/aspeed/aspeed-bmc-misc.c
+@@ -15,6 +15,7 @@ struct aspeed_bmc_ctrl {
+ u32 offset;
+ u32 mask;
+ u32 shift;
++ bool read_only;
+ struct regmap *map;
+ struct kobj_attribute attr;
+ };
+@@ -55,6 +56,8 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ if (rc < 0)
+ return rc;
+
++ ctrl->read_only = of_property_read_bool(child, "read-only");
++
+ ctrl->mask <<= ctrl->shift;
+
+ return 0;
+@@ -116,6 +119,10 @@ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj,
+ return rc;
+
+ ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr);
++
++ if (ctrl->read_only)
++ return -EROFS;
++
+ val <<= ctrl->shift;
+ rc = regmap_update_bits(ctrl->map, ctrl->offset, ctrl->mask, val);
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch
new file mode 100644
index 000000000..09a957860
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch
@@ -0,0 +1,70 @@
+From 3eaf814c51f85aaad0d181d27ff686ce35b31d6a Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 29 Oct 2019 11:28:29 +0800
+Subject: [PATCH] Fix NCSI driver issue caused by host shutdown due to
+ overheated.
+
+NCSI device cannot be recovered when host shutdown due to overheated.
+
+Tested:
+Heat host till shutdown due to overheated and then
+run the ipmi command like power status
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ net/ncsi/ncsi-manage.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
+index 70fe02697544..4e16a0015f26 100644
+--- a/net/ncsi/ncsi-manage.c
++++ b/net/ncsi/ncsi-manage.c
+@@ -132,18 +132,15 @@ static void ncsi_channel_monitor(struct timer_list *t)
+ netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n",
+ nc->id);
+ ncsi_report_link(ndp, true);
+- ndp->flags |= NCSI_DEV_RESHUFFLE;
+
+ ncsi_stop_channel_monitor(nc);
+
+- ncm = &nc->modes[NCSI_MODE_LINK];
+ spin_lock_irqsave(&nc->lock, flags);
+- nc->state = NCSI_CHANNEL_INVISIBLE;
+- ncm->data[2] &= ~0x1;
++ nc->state = NCSI_CHANNEL_INACTIVE;
+ spin_unlock_irqrestore(&nc->lock, flags);
+
+ spin_lock_irqsave(&ndp->lock, flags);
+- nc->state = NCSI_CHANNEL_ACTIVE;
++ ndp->flags |= NCSI_DEV_RESHUFFLE | NCSI_DEV_RESET;
+ list_add_tail_rcu(&nc->link, &ndp->channel_queue);
+ spin_unlock_irqrestore(&ndp->lock, flags);
+ ncsi_process_next_channel(ndp);
+@@ -424,6 +421,7 @@ static void ncsi_request_timeout(struct timer_list *t)
+ {
+ struct ncsi_request *nr = from_timer(nr, t, timer);
+ struct ncsi_dev_priv *ndp = nr->ndp;
++ struct ncsi_dev *nd = &ndp->ndev;
+ struct ncsi_cmd_pkt *cmd;
+ struct ncsi_package *np;
+ struct ncsi_channel *nc;
+@@ -438,6 +436,16 @@ static void ncsi_request_timeout(struct timer_list *t)
+ spin_unlock_irqrestore(&ndp->lock, flags);
+ return;
+ }
++ if (nd->state == ncsi_dev_state_suspend ||
++ nd->state == ncsi_dev_state_suspend_select ||
++ nd->state == ncsi_dev_state_suspend_gls ||
++ nd->state == ncsi_dev_state_suspend_dcnt ||
++ nd->state == ncsi_dev_state_suspend_dc ||
++ nd->state == ncsi_dev_state_suspend_deselect ||
++ nd->state == ncsi_dev_state_suspend_done) {
++ ndp->flags |= NCSI_DEV_RESET;
++ nd->state = ncsi_dev_state_suspend_done;
++ }
+ spin_unlock_irqrestore(&ndp->lock, flags);
+
+ if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch
new file mode 100644
index 000000000..89e7b894f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch
@@ -0,0 +1,56 @@
+From a90b8f7dfcfcab2d40d1a575e3948ef3a34f643f Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 8 Nov 2019 15:57:27 -0800
+Subject: [PATCH] i2c: aspeed: filter garbage interrupts out
+
+AST2600 makes a garbage interrupt which is decribed as 'reserved'
+in datasheet so filter them out.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 62b803e15ce2..c24cecdcfe89 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -87,7 +87,11 @@
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
++#if defined(CONFIG_MACH_ASPEED_G6)
++#define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(29)
++#else
+ #define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(30)
++#endif
+ #define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15)
+ #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
+ #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
+@@ -118,6 +122,11 @@
+ ASPEED_I2CD_INTR_RX_DONE | \
+ ASPEED_I2CD_INTR_TX_NAK | \
+ ASPEED_I2CD_INTR_TX_ACK)
++#define ASPEED_I2CD_INTR_STATUS_MASK \
++ (ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING | \
++ ASPEED_I2CD_INTR_GCALL_ADDR | \
++ ASPEED_I2CD_INTR_SLAVE_MATCH | \
++ ASPEED_I2CD_INTR_ALL)
+
+ /* 0x14 : I2CD Command/Status Register */
+ #define ASPEED_I2CD_SCL_LINE_STS BIT(18)
+@@ -1021,6 +1030,11 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
+ /* Ack all interrupts except for Rx done */
+ writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
+ bus->base + ASPEED_I2C_INTR_STS_REG);
++ /*
++ * AST2600 makes a garbage interrupt which is decribed as 'reserved'
++ * in datasheet so filter them out.
++ */
++ irq_received &= ASPEED_I2CD_INTR_STATUS_MASK;
+ irq_remaining = irq_received;
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch
new file mode 100644
index 000000000..f578d0f04
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch
@@ -0,0 +1,35 @@
+From 523bbaaf9f9d064c9cf1f627d64dd7ba169d175d Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 20 Nov 2019 15:01:06 -0800
+Subject: [PATCH] ARM: dts: aspeed-g6: add GFX node
+
+This commit adds GFX node for AST2600 SoC.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index b880e8e8f999..3e2153416e11 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -330,6 +330,15 @@
+ quality = <100>;
+ };
+
++ gfx: display@1e6e6000 {
++ compatible = "aspeed,ast2600-gfx", "syscon";
++ reg = <0x1e6e6000 0x1000>;
++ reg-io-width = <4>;
++ clocks = <&syscon ASPEED_CLK_GATE_D1CLK>;
++ status = "disabled";
++ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
+ adc: adc@1e6e9000 {
+ compatible = "aspeed,ast2500-adc";
+ reg = <0x1e6e9000 0x100>;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch
new file mode 100644
index 000000000..259720e87
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch
@@ -0,0 +1,105 @@
+From 195cd60ff2fe38b18ebdea90245b908548f4e985 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 20 Nov 2019 14:58:24 -0800
+Subject: [PATCH] drm: add AST2600 GFX support
+
+This commit adds support for AST2600 GFX.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/gpu/drm/aspeed/aspeed_gfx.h | 4 ++++
+ drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 6 +++---
+ drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 18 +++++++++++-------
+ 3 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h
+index a10358bb61ec..eebd72eb1220 100644
+--- a/drivers/gpu/drm/aspeed/aspeed_gfx.h
++++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h
+@@ -13,11 +13,15 @@ struct aspeed_gfx {
+ struct drm_simple_display_pipe pipe;
+ struct drm_connector connector;
+ struct drm_fbdev_cma *fbdev;
++ u32 scu_misc_offset;
+ };
+
+ int aspeed_gfx_create_pipe(struct drm_device *drm);
+ int aspeed_gfx_create_output(struct drm_device *drm);
+
++#define SCU_MISC_AST2500 0x2c /* SCU Misc of AST2500 */
++#define SCU_MISC_AST2600 0xc0 /* SCU Misc1 of AST2600 */
++
+ #define CRT_CTRL1 0x60 /* CRT Control I */
+ #define CRT_CTRL2 0x64 /* CRT Control II */
+ #define CRT_STATUS 0x68 /* CRT Status */
+diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
+index 2184b8be6fd4..86359a0fe05f 100644
+--- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
++++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
+@@ -59,8 +59,8 @@ static void aspeed_gfx_enable_controller(struct aspeed_gfx *priv)
+ u32 ctrl1 = readl(priv->base + CRT_CTRL1);
+ u32 ctrl2 = readl(priv->base + CRT_CTRL2);
+
+- /* SCU2C: set DAC source for display output to Graphics CRT (GFX) */
+- regmap_update_bits(priv->scu, 0x2c, BIT(16), BIT(16));
++ /* Set DAC source for display output to Graphics CRT (GFX) */
++ regmap_update_bits(priv->scu, priv->scu_misc_offset, BIT(16), BIT(16));
+
+ writel(ctrl1 | CRT_CTRL_EN, priv->base + CRT_CTRL1);
+ writel(ctrl2 | CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2);
+@@ -74,7 +74,7 @@ static void aspeed_gfx_disable_controller(struct aspeed_gfx *priv)
+ writel(ctrl1 & ~CRT_CTRL_EN, priv->base + CRT_CTRL1);
+ writel(ctrl2 & ~CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2);
+
+- regmap_update_bits(priv->scu, 0x2c, BIT(16), 0);
++ regmap_update_bits(priv->scu, priv->scu_misc_offset, BIT(16), 0);
+ }
+
+ static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv)
+diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
+index ada2f6aca906..92bc9b475e0f 100644
+--- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
++++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
+@@ -112,8 +112,14 @@ static int aspeed_gfx_load(struct drm_device *drm)
+
+ priv->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2500-scu");
+ if (IS_ERR(priv->scu)) {
+- dev_err(&pdev->dev, "failed to find SCU regmap\n");
+- return PTR_ERR(priv->scu);
++ priv->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2600-scu");
++ if (IS_ERR(priv->scu)) {
++ dev_err(&pdev->dev, "failed to find SCU regmap\n");
++ return PTR_ERR(priv->scu);
++ }
++ priv->scu_misc_offset = SCU_MISC_AST2600;
++ } else {
++ priv->scu_misc_offset = SCU_MISC_AST2500;
+ }
+
+ ret = of_reserved_mem_device_init(drm->dev);
+@@ -130,12 +136,9 @@ static int aspeed_gfx_load(struct drm_device *drm)
+ }
+
+ priv->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+- if (IS_ERR(priv->rst)) {
+- dev_err(&pdev->dev,
+- "missing or invalid reset controller device tree entry");
+- return PTR_ERR(priv->rst);
++ if (!IS_ERR_OR_NULL(priv->rst)) {
++ reset_control_deassert(priv->rst);
+ }
+- reset_control_deassert(priv->rst);
+
+ priv->clk = devm_clk_get(drm->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+@@ -211,6 +214,7 @@ static struct drm_driver aspeed_gfx_driver = {
+
+ static const struct of_device_id aspeed_gfx_match[] = {
+ { .compatible = "aspeed,ast2500-gfx" },
++ { .compatible = "aspeed,ast2600-gfx" },
+ { }
+ };
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch
new file mode 100644
index 000000000..4dde9fb06
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch
@@ -0,0 +1,271 @@
+From 278db13a36f128b84f76fc0f0f13860b5bf62588 Mon Sep 17 00:00:00 2001
+From: Chen Yugang <yugang.chen@linux.intel.com>
+Date: Tue, 3 Dec 2019 13:41:37 +0800
+Subject: [PATCH] ADC linux driver for AST2600
+
+Tested:
+it's tested with DC input.
+
+Signed-off-by: Chen Yugang <yugang.chen@linux.intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 14 +++++-
+ drivers/iio/adc/aspeed_adc.c | 99 +++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 99 insertions(+), 14 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 3e2153416e11..5acc1085526d 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -339,12 +339,22 @@
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+- adc: adc@1e6e9000 {
+- compatible = "aspeed,ast2500-adc";
++ adc0: adc@1e6e9000 {
++ compatible = "aspeed,ast2600-adc";
+ reg = <0x1e6e9000 0x100>;
+ clocks = <&syscon ASPEED_CLK_APB2>;
++ resets = <&syscon ASPEED_RESET_ADC>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
++ #io-channel-cells = <1>;
++ status = "disabled";
++ };
++
++ adc1: adc@1e6e9100 {
++ compatible = "aspeed,ast2600-adc";
++ reg = <0x1e6e9100 0x100>;
++ clocks = <&syscon ASPEED_CLK_APB2>;
+ resets = <&syscon ASPEED_RESET_ADC>;
++ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
+index d3fc39df535d..1dd5a97a16bc 100644
+--- a/drivers/iio/adc/aspeed_adc.c
++++ b/drivers/iio/adc/aspeed_adc.c
+@@ -1,8 +1,12 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Aspeed AST2400/2500 ADC
++ * Aspeed AST2400/2500/2600 ADC
+ *
+ * Copyright (C) 2017 Google, Inc.
++ * Copyright (C) ASPEED Technology Inc.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
+ */
+
+ #include <linux/clk.h>
+@@ -30,6 +34,14 @@
+ #define ASPEED_REG_CLOCK_CONTROL 0x0C
+ #define ASPEED_REG_MAX 0xC0
+
++/* ast2600 */
++#define REF_VLOTAGE_2500mV 0
++#define REF_VLOTAGE_1200mV GENMASK(6, 6)
++#define REF_VLOTAGE_1550mV GENMASK(7, 7)
++#define REF_VLOTAGE_900mV GENMASK(7, 6)
++
++#define ASPEED_AUTOPENSATING BIT(5)
++
+ #define ASPEED_OPERATION_MODE_POWER_DOWN (0x0 << 1)
+ #define ASPEED_OPERATION_MODE_STANDBY (0x1 << 1)
+ #define ASPEED_OPERATION_MODE_NORMAL (0x7 << 1)
+@@ -45,8 +57,10 @@ struct aspeed_adc_model_data {
+ const char *model_name;
+ unsigned int min_sampling_rate; // Hz
+ unsigned int max_sampling_rate; // Hz
+- unsigned int vref_voltage; // mV
++ u32 vref_voltage; // mV
+ bool wait_init_sequence;
++ struct iio_chan_spec const *channels;
++ int num_channels;
+ };
+
+ struct aspeed_adc_data {
+@@ -56,6 +70,7 @@ struct aspeed_adc_data {
+ struct clk_hw *clk_prescaler;
+ struct clk_hw *clk_scaler;
+ struct reset_control *rst;
++ int cv;
+ };
+
+ #define ASPEED_CHAN(_idx, _data_reg_addr) { \
+@@ -87,6 +102,17 @@ static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
+ ASPEED_CHAN(15, 0x2E),
+ };
+
++static const struct iio_chan_spec ast2600_adc_iio_channels[] = {
++ ASPEED_CHAN(0, 0x10),
++ ASPEED_CHAN(1, 0x12),
++ ASPEED_CHAN(2, 0x14),
++ ASPEED_CHAN(3, 0x16),
++ ASPEED_CHAN(4, 0x18),
++ ASPEED_CHAN(5, 0x1A),
++ ASPEED_CHAN(6, 0x1C),
++ ASPEED_CHAN(7, 0x1E),
++};
++
+ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+@@ -175,7 +201,10 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ const struct aspeed_adc_model_data *model_data;
+ struct resource *res;
+ const char *clk_parent_name;
++ char prescaler_clk_name[32];
++ char scaler_clk_name[32];
+ int ret;
++ u32 eng_ctrl = 0;
+ u32 adc_engine_control_reg_val;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
+@@ -194,19 +223,21 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ spin_lock_init(&data->clk_lock);
+ clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
+
++ snprintf(prescaler_clk_name, sizeof(prescaler_clk_name), "prescaler-%s", pdev->name);
+ data->clk_prescaler = clk_hw_register_divider(
+- &pdev->dev, "prescaler", clk_parent_name, 0,
++ &pdev->dev, prescaler_clk_name, clk_parent_name, 0,
+ data->base + ASPEED_REG_CLOCK_CONTROL,
+ 17, 15, 0, &data->clk_lock);
+ if (IS_ERR(data->clk_prescaler))
+ return PTR_ERR(data->clk_prescaler);
+
++ snprintf(scaler_clk_name, sizeof(scaler_clk_name), "scaler-%s", pdev->name);
+ /*
+ * Register ADC clock scaler downstream from the prescaler. Allow rate
+ * setting to adjust the prescaler as well.
+ */
+ data->clk_scaler = clk_hw_register_divider(
+- &pdev->dev, "scaler", "prescaler",
++ &pdev->dev, scaler_clk_name, prescaler_clk_name,
+ CLK_SET_RATE_PARENT,
+ data->base + ASPEED_REG_CLOCK_CONTROL,
+ 0, 10, 0, &data->clk_lock);
+@@ -215,7 +246,7 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ goto scaler_error;
+ }
+
+- data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
++ data->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
+ if (IS_ERR(data->rst)) {
+ dev_err(&pdev->dev,
+ "invalid or missing reset controller device tree entry");
+@@ -225,11 +256,26 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ reset_control_deassert(data->rst);
+
+ model_data = of_device_get_match_data(&pdev->dev);
++ if (!of_property_read_u32(pdev->dev.of_node, "ref_voltage", (u32 *)&model_data->vref_voltage)) {
++ if (model_data->vref_voltage == 2500)
++ eng_ctrl = REF_VLOTAGE_2500mV;
++ else if (model_data->vref_voltage == 1200)
++ eng_ctrl = REF_VLOTAGE_1200mV;
++ else if ((model_data->vref_voltage >= 1550) && (model_data->vref_voltage <= 2700))
++ eng_ctrl = REF_VLOTAGE_1550mV;
++ else if ((model_data->vref_voltage >= 900) && (model_data->vref_voltage <= 1650))
++ eng_ctrl = REF_VLOTAGE_900mV;
++ else {
++ printk("error ref voltage %d \n", model_data->vref_voltage);
++ eng_ctrl = 0;
++ }
++ } else
++ eng_ctrl = 0;
+
+ if (model_data->wait_init_sequence) {
+ /* Enable engine in normal mode. */
+- writel(ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE,
+- data->base + ASPEED_REG_ENGINE_CONTROL);
++ eng_ctrl |= ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
++ writel(eng_ctrl, data->base + ASPEED_REG_ENGINE_CONTROL);
+
+ /* Wait for initial sequence complete. */
+ ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL,
+@@ -242,12 +288,26 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ goto poll_timeout_error;
+ }
+
++ /* do compensating calculation use ch 0 */
++ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL |
++ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL);
++
++ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL | BIT(16) |
++ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL);
++ mdelay(1);
++
++ data->cv = 0x200 - (readl(data->base + 0x10) & GENMASK(9, 0));
++
++ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL |
++ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL);
++ printk(KERN_INFO "aspeed_adc: cv %d \n", data->cv);
++
+ /* Start all channels in normal mode. */
+ ret = clk_prepare_enable(data->clk_scaler->clk);
+ if (ret)
+ goto clk_enable_error;
+
+- adc_engine_control_reg_val = GENMASK(31, 16) |
++ adc_engine_control_reg_val = eng_ctrl | GENMASK(31, 16) |
+ ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
+ writel(adc_engine_control_reg_val,
+ data->base + ASPEED_REG_ENGINE_CONTROL);
+@@ -257,8 +317,8 @@ static int aspeed_adc_probe(struct platform_device *pdev)
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->info = &aspeed_adc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+- indio_dev->channels = aspeed_adc_iio_channels;
+- indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
++ indio_dev->channels = model_data->channels;
++ indio_dev->num_channels = model_data->num_channels;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+@@ -301,6 +361,8 @@ static const struct aspeed_adc_model_data ast2400_model_data = {
+ .vref_voltage = 2500, // mV
+ .min_sampling_rate = 10000,
+ .max_sampling_rate = 500000,
++ .channels = aspeed_adc_iio_channels,
++ .num_channels = 16,
+ };
+
+ static const struct aspeed_adc_model_data ast2500_model_data = {
+@@ -309,11 +371,24 @@ static const struct aspeed_adc_model_data ast2500_model_data = {
+ .min_sampling_rate = 1,
+ .max_sampling_rate = 1000000,
+ .wait_init_sequence = true,
++ .channels = aspeed_adc_iio_channels,
++ .num_channels = 16,
++};
++
++static const struct aspeed_adc_model_data ast2600_model_data = {
++ .model_name = "ast2500-adc",
++ .vref_voltage = 1800, /* mV --> can be 1.2v or 2.5 or ext 1.55~2.7v, 0.9v ~1.65v */
++ .min_sampling_rate = 1,
++ .max_sampling_rate = 1000000,
++ .wait_init_sequence = true,
++ .channels = ast2600_adc_iio_channels,
++ .num_channels = 8,
+ };
+
+ static const struct of_device_id aspeed_adc_matches[] = {
+ { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
+ { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
++ { .compatible = "aspeed,ast2600-adc", .data = &ast2600_model_data },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
+@@ -330,5 +405,5 @@ static struct platform_driver aspeed_adc_driver = {
+ module_platform_driver(aspeed_adc_driver);
+
+ MODULE_AUTHOR("Rick Altherr <raltherr@google.com>");
+-MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
++MODULE_DESCRIPTION("Aspeed AST2400/2500/2600 ADC Driver");
+ MODULE_LICENSE("GPL");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch
new file mode 100644
index 000000000..221800720
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch
@@ -0,0 +1,36 @@
+From 90c72bbe5f1ac2c8d62736c44492bd8bbc4fcab0 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 26 Nov 2019 16:37:36 -0800
+Subject: [PATCH] ARM: dts: aspeed-g6: add video node
+
+This commit adds video node.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 5acc1085526d..b0283e03e9ff 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -359,6 +359,16 @@
+ status = "disabled";
+ };
+
++ video: video@1e700000 {
++ compatible = "aspeed,ast2600-video-engine";
++ reg = <0x1e700000 0x1000>;
++ clocks = <&syscon ASPEED_CLK_GATE_VCLK>,
++ <&syscon ASPEED_CLK_GATE_ECLK>;
++ clock-names = "vclk", "eclk";
++ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
++ status = "disabled";
++ };
++
+ gpio0: gpio@1e780000 {
+ #gpio-cells = <2>;
+ gpio-controller;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch
new file mode 100644
index 000000000..1d8b722de
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch
@@ -0,0 +1,63 @@
+From 1765cb18bacff9d1f48b833f44da198a09f7d5cb Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 26 Nov 2019 16:39:16 -0800
+Subject: [PATCH] media: aspeed: add aspeed,ast2600-video-engine compatible
+ string
+
+This commit adds "aspeed,ast2600-video-engine" compatible string
+to support AST2600 video engine H/W. Also. it adds G6 specific
+register handling flow.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/media/platform/aspeed-video.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
+index db45502774b1..fe70ad408375 100644
+--- a/drivers/media/platform/aspeed-video.c
++++ b/drivers/media/platform/aspeed-video.c
+@@ -72,8 +72,8 @@
+ #define VE_SEQ_CTRL_CAP_BUSY BIT(16)
+ #define VE_SEQ_CTRL_COMP_BUSY BIT(18)
+
+-#ifdef CONFIG_MACH_ASPEED_G5
+-#define VE_SEQ_CTRL_JPEG_MODE BIT(13) /* AST2500 */
++#if defined(CONFIG_MACH_ASPEED_G5) || defined(CONFIG_MACH_ASPEED_G6)
++#define VE_SEQ_CTRL_JPEG_MODE BIT(13) /* AST2500/2600 */
+ #else
+ #define VE_SEQ_CTRL_JPEG_MODE BIT(8) /* AST2400 */
+ #endif /* CONFIG_MACH_ASPEED_G5 */
+@@ -135,6 +135,12 @@
+
+ #define VE_OFFSET_COMP_STREAM 0x078
+
++#ifdef CONFIG_MACH_ASPEED_G6
++#define VE_JPEG_COMP_SIZE_READ_BACK 0x084 /* AST2600 */
++#else
++#define VE_JPEG_COMP_SIZE_READ_BACK VE_OFFSET_COMP_STREAM
++#endif
++
+ #define VE_SRC_LR_EDGE_DET 0x090
+ #define VE_SRC_LR_EDGE_DET_LEFT GENMASK(11, 0)
+ #define VE_SRC_LR_EDGE_DET_NO_V BIT(12)
+@@ -572,7 +578,7 @@ static irqreturn_t aspeed_video_irq(int irq, void *arg)
+ if (sts & VE_INTERRUPT_COMP_COMPLETE) {
+ struct aspeed_video_buffer *buf;
+ u32 frame_size = aspeed_video_read(video,
+- VE_OFFSET_COMP_STREAM);
++ VE_JPEG_COMP_SIZE_READ_BACK);
+
+ spin_lock(&video->lock);
+ clear_bit(VIDEO_FRAME_INPRG, &video->flags);
+@@ -1718,6 +1724,7 @@ static int aspeed_video_remove(struct platform_device *pdev)
+ static const struct of_device_id aspeed_video_of_match[] = {
+ { .compatible = "aspeed,ast2400-video-engine" },
+ { .compatible = "aspeed,ast2500-video-engine" },
++ { .compatible = "aspeed,ast2600-video-engine" },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, aspeed_video_of_match);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch
new file mode 100644
index 000000000..34df0882b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch
@@ -0,0 +1,30 @@
+From 37efef00064a228c3e723b0eece22d72f2632705 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 6 Dec 2019 13:51:37 -0800
+Subject: [PATCH] clk: ast2600: enable ESPICLK always
+
+To support continous eSPI H/W handshaking, this patch enables
+ESPICLK always so that there discontinuity of eSPI handshaking while
+boot BMC.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/clk/clk-ast2600.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
+index 8201d65..21967bc 100644
+--- a/drivers/clk/clk-ast2600.c
++++ b/drivers/clk/clk-ast2600.c
+@@ -87,7 +87,7 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = {
+ [ASPEED_CLK_GATE_EMMCCLK] = { 27, 16, "emmcclk-gate", NULL, 0 }, /* For card clk */
+ /* Reserved 28/29/30 */
+ [ASPEED_CLK_GATE_LCLK] = { 32, 32, "lclk-gate", NULL, 0 }, /* LPC */
+- [ASPEED_CLK_GATE_ESPICLK] = { 33, -1, "espiclk-gate", NULL, 0 }, /* eSPI */
++ [ASPEED_CLK_GATE_ESPICLK] = { 33, -1, "espiclk-gate", NULL, CLK_IS_CRITICAL }, /* eSPI */
+ [ASPEED_CLK_GATE_REF1CLK] = { 34, -1, "ref1clk-gate", "clkin", CLK_IS_CRITICAL },
+ /* Reserved 35 */
+ [ASPEED_CLK_GATE_SDCLK] = { 36, 56, "sdclk-gate", NULL, 0 }, /* SDIO/SD */
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch
new file mode 100644
index 000000000..962d42e6f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch
@@ -0,0 +1,97 @@
+From 054391014d04e5b97ae62e1bf5e6aed005f3c67a Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 13 Dec 2019 16:15:16 +0800
+Subject: [PATCH] ast2600: enable high speed uart in kernel.
+
+Tested:
+1. Config baud rate to 921600 in BIOS setup page
+2. BMC could change env variable "hostserialcfg" to 1.
+3. BMC is force to reboot and SPA baud rate is changed to 921600 successfully.
+4. It is same for back to 115200.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ drivers/clk/clk-ast2600.c | 26 +++++++++++++++++++-------
+ include/dt-bindings/clock/ast2600-clock.h | 2 ++
+ 2 files changed, 21 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
+index c7236e39ef85..af908b2dbeb6 100644
+--- a/drivers/clk/clk-ast2600.c
++++ b/drivers/clk/clk-ast2600.c
+@@ -15,7 +15,7 @@
+
+ #include "clk-aspeed.h"
+
+-#define ASPEED_G6_NUM_CLKS 71
++#define ASPEED_G6_NUM_CLKS ASPEED_CLK_MAX
+
+ #define ASPEED_G6_SILICON_REV 0x004
+
+@@ -43,6 +43,9 @@
+ #define ASPEED_MAC12_CLK_DLY 0x340
+ #define ASPEED_MAC34_CLK_DLY 0x350
+
++#define ASPEED_G6_GEN_UART_REF 0x338
++#define UART_192MHZ_R_N_VALUE 0x3c38e
++
+ /* Globally visible clocks */
+ static DEFINE_SPINLOCK(aspeed_g6_clk_lock);
+
+@@ -76,7 +79,7 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = {
+ /* Reserved 11/12 */
+ [ASPEED_CLK_GATE_YCLK] = { 13, 4, "yclk-gate", NULL, 0 }, /* HAC */
+ [ASPEED_CLK_GATE_USBPORT1CLK] = { 14, 14, "usb-port1-gate", NULL, 0 }, /* USB2 hub/USB2 host port 1/USB1.1 dev */
+- [ASPEED_CLK_GATE_UART5CLK] = { 15, -1, "uart5clk-gate", "uart", 0 }, /* UART5 */
++ [ASPEED_CLK_GATE_UART5CLK] = { 15, -1, "uart5clk-gate", "uart5", 0 }, /* UART5 */
+ /* Reserved 16/19 */
+ [ASPEED_CLK_GATE_MAC1CLK] = { 20, 11, "mac1clk-gate", "mac12", 0 }, /* MAC1 */
+ [ASPEED_CLK_GATE_MAC2CLK] = { 21, 12, "mac2clk-gate", "mac12", 0 }, /* MAC2 */
+@@ -437,17 +440,26 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- /* UART clock div13 setting */
+- regmap_read(map, ASPEED_G6_MISC_CTRL, &val);
+- if (val & UART_DIV13_EN)
+- rate = 24000000 / 13;
++ /* UART clock setting */
++ regmap_read(map, ASPEED_G6_GEN_UART_REF, &val);
++ if (val == UART_192MHZ_R_N_VALUE){
++ rate = 192000000 / 13;
++ dev_err(dev, "192Mhz baud rate 921600\n");
++ }
+ else
+- rate = 24000000;
++ rate = 24000000 / 13;
+ hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+ aspeed_g6_clk_data->hws[ASPEED_CLK_UART] = hw;
+
++ /* UART5 clock setting */
++ rate = 24000000 / 13;
++ hw = clk_hw_register_fixed_rate(dev, "uart5", NULL, 0, rate);
++ if (IS_ERR(hw))
++ return PTR_ERR(hw);
++ aspeed_g6_clk_data->hws[ASPEED_CLK_UART5] = hw;
++
+ /* UART6~13 clock div13 setting */
+ regmap_read(map, 0x80, &val);
+ if (val & BIT(31))
+diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
+index 3d90582a813f..4952f7683be7 100644
+--- a/include/dt-bindings/clock/ast2600-clock.h
++++ b/include/dt-bindings/clock/ast2600-clock.h
+@@ -87,6 +87,8 @@
+ #define ASPEED_CLK_MAC2RCLK 68
+ #define ASPEED_CLK_MAC3RCLK 69
+ #define ASPEED_CLK_MAC4RCLK 70
++#define ASPEED_CLK_UART5 71
++#define ASPEED_CLK_MAX 72
+
+ /* Only list resets here that are not part of a gate */
+ #define ASPEED_RESET_ADC 55
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch
new file mode 100644
index 000000000..475e9611f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch
@@ -0,0 +1,405 @@
+From e40f7d10d5306c075e2fc7e538ce1efc70eeb448 Mon Sep 17 00:00:00 2001
+From: ZhikuiRen <zhikui.ren@intel.com>
+Date: Thu, 9 Jan 2020 10:48:00 -0800
+Subject: [PATCH] Add peci-cpupower driver
+
+peci-cpupower reads CPU energy counter through peci
+and computes average power in mW since last read.
+
+Signed-off-by: ZhikuiRen <zhikui.ren@intel.com>
+---
+ Documentation/hwmon/index.rst | 1 +
+ Documentation/hwmon/peci-cpupower.rst | 52 ++++++++
+ arch/arm/configs/aspeed_g5_defconfig | 1 +
+ drivers/hwmon/Kconfig | 14 +++
+ drivers/hwmon/Makefile | 1 +
+ drivers/hwmon/peci-cpupower.c | 231 ++++++++++++++++++++++++++++++++++
+ drivers/mfd/intel-peci-client.c | 1 +
+ include/uapi/linux/peci-ioctl.h | 1 +
+ 8 files changed, 302 insertions(+)
+ create mode 100644 Documentation/hwmon/peci-cpupower.rst
+ create mode 100644 drivers/hwmon/peci-cpupower.c
+
+diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
+index 7d894c9..0bde0ef 100644
+--- a/Documentation/hwmon/index.rst
++++ b/Documentation/hwmon/index.rst
+@@ -130,6 +130,7 @@ Hardware Monitoring Kernel Drivers
+ pcf8591
+ peci-cputemp
+ peci-dimmtemp
++ peci-cpupower
+ pmbus
+ powr1220
+ pxe1610
+diff --git a/Documentation/hwmon/peci-cpupower.rst b/Documentation/hwmon/peci-cpupower.rst
+new file mode 100644
+index 0000000..4d7bd61
+--- /dev/null
++++ b/Documentation/hwmon/peci-cpupower.rst
+@@ -0,0 +1,52 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++Kernel driver peci-cpupower
++==========================
++
++:Copyright: |copy| 2018-2020 Intel Corporation
++
++Supported chips:
++ One of Intel server CPUs listed below which is connected to a PECI bus.
++ * Intel Xeon E5/E7 v3 server processors
++ Intel Xeon E5-14xx v3 family
++ Intel Xeon E5-24xx v3 family
++ Intel Xeon E5-16xx v3 family
++ Intel Xeon E5-26xx v3 family
++ Intel Xeon E5-46xx v3 family
++ Intel Xeon E7-48xx v3 family
++ Intel Xeon E7-88xx v3 family
++ * Intel Xeon E5/E7 v4 server processors
++ Intel Xeon E5-16xx v4 family
++ Intel Xeon E5-26xx v4 family
++ Intel Xeon E5-46xx v4 family
++ Intel Xeon E7-48xx v4 family
++ Intel Xeon E7-88xx v4 family
++ * Intel Xeon Scalable server processors
++ Intel Xeon D family
++ Intel Xeon Bronze family
++ Intel Xeon Silver family
++ Intel Xeon Gold family
++ Intel Xeon Platinum family
++
++ Addresses scanned: PECI client address 0x30 - 0x37
++ Datasheet: Available from http://www.intel.com/design/literature.htm
++
++Author:
++ Zhikui Ren <zhikui.ren@.intel.com>
++
++Description
++-----------
++
++This driver implements a generic PECI hwmon feature which provides
++average power consumption readings of the CPU package based on energy counter
++accessible using the PECI Client Command Suite via the processor PECI client.
++
++Power values are average power since last measure given in milli Watt and
++will be measurable only when the target CPU is powered on.
++
++``sysfs`` interface
++-------------------
++======================= =======================================================
++power1_average Provides average power since last read in milli Watt.
++power1_label Provides string "Average Power".
++======================= =======================================================
+diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
+index 1e589a0..0e50040 100644
+--- a/arch/arm/configs/aspeed_g5_defconfig
++++ b/arch/arm/configs/aspeed_g5_defconfig
+@@ -177,6 +177,7 @@ CONFIG_SENSORS_OCC_P8_I2C=y
+ CONFIG_SENSORS_OCC_P9_SBE=y
+ CONFIG_SENSORS_PECI_CPUTEMP=y
+ CONFIG_SENSORS_PECI_DIMMTEMP=y
++CONFIG_SENSORS_PECI_CPUPOWER=y
+ CONFIG_PMBUS=y
+ CONFIG_SENSORS_ADM1275=y
+ CONFIG_SENSORS_IBM_CFFPS=y
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 8312b37..07d8826 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -1361,6 +1361,20 @@ config SENSORS_PECI_DIMMTEMP
+ This driver can also be built as a module. If so, the module
+ will be called peci-dimmtemp.
+
++config SENSORS_PECI_CPUPOWER
++ tristate "PECI CPU power monitoring support"
++ depends on PECI
++ select MFD_INTEL_PECI_CLIENT
++ help
++ If you say yes here you get support for the generic Intel PECI
++ cputemp driver which provides average engergy
++ readings of the CPU package using
++ the PECI Client Command Suite via the processor PECI client.
++ Check Documentation/hwmon/peci-cpupower for details.
++
++ This driver can also be built as a module. If so, the module
++ will be called peci-cpupower.
++
+ source "drivers/hwmon/pmbus/Kconfig"
+
+ config SENSORS_PWM_FAN
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index e74ea92..fab43fd 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -144,6 +144,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
+ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+ obj-$(CONFIG_SENSORS_PECI_CPUTEMP) += peci-cputemp.o
+ obj-$(CONFIG_SENSORS_PECI_DIMMTEMP) += peci-dimmtemp.o
++obj-$(CONFIG_SENSORS_PECI_CPUPOWER) += peci-cpupower.o
+ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
+ obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+ obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
+diff --git a/drivers/hwmon/peci-cpupower.c b/drivers/hwmon/peci-cpupower.c
+new file mode 100644
+index 0000000..6907696
+--- /dev/null
++++ b/drivers/hwmon/peci-cpupower.c
+@@ -0,0 +1,231 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020 Intel Corporation
++
++#include <linux/hwmon.h>
++#include <linux/jiffies.h>
++#include <linux/mfd/intel-peci-client.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include "peci-hwmon.h"
++
++#define POWER_DEFAULT_CHANNEL_NUMS 1
++
++struct peci_cpupower {
++ struct peci_client_manager *mgr;
++ struct device *dev;
++ char name[PECI_NAME_SIZE];
++ const struct cpu_gen_info *gen_info;
++ struct peci_sensor_data energy;
++ long avg_power_val;
++ u64 core_mask;
++ u32 power_config[POWER_DEFAULT_CHANNEL_NUMS + 1];
++ uint config_idx;
++ struct hwmon_channel_info power_info;
++ const struct hwmon_channel_info *info[2];
++ struct hwmon_chip_info chip;
++};
++
++enum cpupower_channels {
++ average_power,
++};
++
++static const u32 config_table[POWER_DEFAULT_CHANNEL_NUMS] = {
++ /* average power */
++ HWMON_P_LABEL | HWMON_P_AVERAGE,
++};
++
++static const char *cpupower_label[POWER_DEFAULT_CHANNEL_NUMS] = {
++ "Average Power",
++};
++
++static int get_average_power(struct peci_cpupower *priv)
++{
++ u8 pkg_cfg[4];
++ int ret;
++
++ if (!peci_sensor_need_update(&priv->energy))
++ return 0;
++
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_TDP_UNITS,
++ PECI_PKG_ID_PKG_ENERGY_STATUS,
++ pkg_cfg);
++
++ u32 power_unit = ((le32_to_cpup((__le32 *)pkg_cfg)) & 0x1f00) >> 8;
++
++ dev_dbg(priv->dev, "cpupower units %d (1J/pow(2, unit))\n",
++ power_unit);
++
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_ENERGY_COUNTER,
++ PECI_PKG_ID_PKG_ENERGY_STATUS,
++ pkg_cfg);
++ if (!ret) {
++ u32 energy_cnt = le32_to_cpup((__le32 *)pkg_cfg);
++ ulong jif = jiffies;
++ ulong elapsed = (jif - priv->energy.last_updated);
++ long power_val = 0;
++ /*
++ * Don't calculate average power for first counter read or
++ * counter wrapped around or last counter read was more than
++ * 60 minutes ago (jiffies did not wrap and power calculation
++ * does not overflow or underflow
++ */
++ if (priv->energy.last_updated > 0 &&
++ energy_cnt > priv->energy.value &&
++ (elapsed < (HZ * 3600))) {
++ power_val = (long)(energy_cnt - priv->energy.value)
++ / elapsed * HZ;
++ dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, raw powerValue %d scale to %d mW\n",
++ (long)(energy_cnt - priv->energy.value),
++ elapsed, power_val,
++ power_val >> (power_unit - 10));
++ } else {
++ dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, skipping calculate power, try agin\n",
++ (long)(energy_cnt - priv->energy.value),
++ elapsed);
++ ret = -EAGAIN;
++ }
++
++ priv->energy.value = energy_cnt;
++ priv->avg_power_val = power_val >> ((power_unit - 10));
++ peci_sensor_mark_updated(&priv->energy);
++
++ dev_dbg(priv->dev, "energy counter 0x%8x, average power %dmW, jif %u, HZ is %d jiffies\n",
++ priv->energy.value, priv->avg_power_val,
++ jif, HZ);
++ }
++ return ret;
++}
++
++static int cpupower_read_string(struct device *dev,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel, const char **str)
++{
++ if (attr != hwmon_power_label)
++ return -EOPNOTSUPP;
++ if (channel >= POWER_DEFAULT_CHANNEL_NUMS)
++ return -EOPNOTSUPP;
++ *str = cpupower_label[channel];
++
++ return 0;
++}
++
++static int cpupower_read(struct device *dev,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel, long *val)
++{
++ struct peci_cpupower *priv = dev_get_drvdata(dev);
++ int ret;
++
++ if (channel >= POWER_DEFAULT_CHANNEL_NUMS ||
++ !(priv->power_config[channel] & BIT(attr)))
++ return -EOPNOTSUPP;
++
++ switch (attr) {
++ case hwmon_power_average:
++ switch (channel) {
++ case average_power:
++ ret = get_average_power(priv);
++ if (ret)
++ break;
++
++ *val = priv->avg_power_val;
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++ }
++
++ return ret;
++}
++
++static umode_t cpupower_is_visible(const void *data,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel)
++{
++ const struct peci_cpupower *priv = data;
++
++ if (channel < POWER_DEFAULT_CHANNEL_NUMS ||
++ (priv->power_config[channel] & BIT(attr)))
++ return 0444;
++
++ return 0;
++}
++
++static const struct hwmon_ops cpupower_ops = {
++ .is_visible = cpupower_is_visible,
++ .read_string = cpupower_read_string,
++ .read = cpupower_read,
++};
++
++static int peci_cpupower_probe(struct platform_device *pdev)
++{
++ struct peci_client_manager *mgr = dev_get_drvdata(pdev->dev.parent);
++ struct device *dev = &pdev->dev;
++ struct peci_cpupower *priv;
++ struct device *hwmon_dev;
++
++ if ((mgr->client->adapter->cmd_mask &
++ (BIT(PECI_CMD_RD_PKG_CFG))) !=
++ (BIT(PECI_CMD_RD_PKG_CFG))) {
++ return -ENODEV;
++ }
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ dev_set_drvdata(dev, priv);
++ priv->mgr = mgr;
++ priv->dev = dev;
++ priv->gen_info = mgr->gen_info;
++
++ snprintf(priv->name, PECI_NAME_SIZE, "peci_cpupower.cpu%d",
++ mgr->client->addr - PECI_BASE_ADDR);
++
++ priv->power_config[priv->config_idx++] = config_table[average_power];
++
++ priv->chip.ops = &cpupower_ops;
++ priv->chip.info = priv->info;
++
++ priv->info[0] = &priv->power_info;
++
++ priv->power_info.type = hwmon_power;
++ priv->power_info.config = priv->power_config;
++
++ hwmon_dev = devm_hwmon_device_register_with_info(priv->dev,
++ priv->name,
++ priv,
++ &priv->chip,
++ NULL);
++
++ if (IS_ERR(hwmon_dev))
++ return PTR_ERR(hwmon_dev);
++
++ dev_dbg(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), priv->name);
++
++ return 0;
++}
++
++static const struct platform_device_id peci_cpupower_ids[] = {
++ { .name = "peci-cpupower", .driver_data = 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(platform, peci_cpupower_ids);
++
++static struct platform_driver peci_cpupower_driver = {
++ .probe = peci_cpupower_probe,
++ .id_table = peci_cpupower_ids,
++ .driver = { .name = KBUILD_MODNAME, },
++};
++module_platform_driver(peci_cpupower_driver);
++
++MODULE_AUTHOR("Zhikui Ren <zhikui.ren@intel.com>");
++MODULE_DESCRIPTION("PECI cpupower driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c
+index 9751b04..0c62ad6 100644
+--- a/drivers/mfd/intel-peci-client.c
++++ b/drivers/mfd/intel-peci-client.c
+@@ -21,6 +21,7 @@
+ static struct mfd_cell peci_functions[] = {
+ { .name = "peci-cputemp", },
+ { .name = "peci-dimmtemp", },
++ { .name = "peci-cpupower", },
+ };
+
+ static const struct cpu_gen_info cpu_gen_info_table[] = {
+diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
+index 843930f..d16f7c9 100644
+--- a/include/uapi/linux/peci-ioctl.h
++++ b/include/uapi/linux/peci-ioctl.h
+@@ -231,6 +231,7 @@ struct peci_rd_pkg_cfg_msg {
+ #define PECI_PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */
+ #define PECI_PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */
+ #define PECI_PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */
++#define PECI_PKG_ID_PKG_ENERGY_STATUS 0x00ff /* Average Energy */
+
+ __u8 rx_len;
+ __u8 cc;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch
new file mode 100644
index 000000000..f8a05fd7c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch
@@ -0,0 +1,136 @@
+From f231c8d6babe5ac1b74ab4eb09901b864020a83f Mon Sep 17 00:00:00 2001
+From: arun-pm <arun.p.m@linux.intel.com>
+Date: Tue, 3 Dec 2019 17:22:28 +0530
+Subject: [PATCH] SPI Quad IO driver support AST2600
+
+This commit adds spi driver quad io support for AST2600
+
+Note:- Removed n25q00 Quad I/O support for the time being due to clock issue
+ with chip 'Micron 8UA15 - rw182 (128MB)' while enabling Quad I/O mode.
+
+Signed-off-by: arun-pm <arun.p.m@linux.intel.com>
+---
+ drivers/mtd/spi-nor/aspeed-smc.c | 49 ++++++++++++++++++++++++++++++++++------
+ drivers/mtd/spi-nor/spi-nor.c | 7 +++++-
+ 2 files changed, 48 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
+index 0805dcab8cb1..6e2f3802d162 100644
+--- a/drivers/mtd/spi-nor/aspeed-smc.c
++++ b/drivers/mtd/spi-nor/aspeed-smc.c
+@@ -21,6 +21,11 @@
+ #include <linux/sysfs.h>
+
+ #define DEVICE_NAME "aspeed-smc"
++#define AST2600A0 0x05000303
++#define AST2600A0_MAX_FREQ 50000000
++#define AST2600A0_SAFE_FREQ 40000000
++#define AST_MAX_FREQ 100000000
++#define AST2600_REVISION_ID_SCU 0x1e6e2004
+
+ /*
+ * The driver only support SPI flash
+@@ -542,6 +547,10 @@ static int aspeed_smc_get_io_mode(struct aspeed_smc_chip *chip)
+ return CONTROL_IO_DUAL_DATA;
+ case SNOR_PROTO_1_2_2:
+ return CONTROL_IO_DUAL_ADDR_DATA;
++ case SNOR_PROTO_1_1_4:
++ return CONTROL_IO_QUAD_DATA;
++ case SNOR_PROTO_1_4_4:
++ return CONTROL_IO_QUAD_ADDR_DATA;
+ default:
+ dev_err(chip->nor.dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+@@ -573,7 +582,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from,
+ aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy));
+
+ /* Set IO mode only for data */
+- if (io_mode == CONTROL_IO_DUAL_DATA)
++ if (io_mode == CONTROL_IO_DUAL_DATA || io_mode == CONTROL_IO_QUAD_DATA)
+ aspeed_smc_set_io_mode(chip, io_mode);
+
+ aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len);
+@@ -1222,20 +1231,35 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
+ return 0;
+ }
+
++static void aspeed_allowed_max_freq(struct aspeed_smc_chip *chip)
++{
++ void __iomem *scu_ast_revision_id = ioremap(AST2600_REVISION_ID_SCU, 4);
++ u32 rev_id = readl(scu_ast_revision_id);
++
++ /*Limit max spi frequency less than 50MHz on AST2600-A0 due
++ * to FWSPICLK signal quality issue.
++ */
++ if(rev_id == AST2600A0 && chip->clk_rate > AST2600A0_MAX_FREQ)
++ chip->clk_rate = AST2600A0_MAX_FREQ;
++}
++
++static u32 get_hwcaps(unsigned int tx_width){
++ if(tx_width == 4)
++ return SNOR_HWCAPS_READ_1_1_4;
++ else
++ return SNOR_HWCAPS_READ_1_1_2;
++}
++
+ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
+ struct device_node *np, struct resource *r)
+ {
+- const struct spi_nor_hwcaps hwcaps = {
+- .mask = SNOR_HWCAPS_READ |
+- SNOR_HWCAPS_READ_FAST |
+- SNOR_HWCAPS_READ_1_1_2 |
+- SNOR_HWCAPS_PP,
+- };
++ struct spi_nor_hwcaps hwcaps;
+ const struct aspeed_smc_info *info = controller->info;
+ struct device *dev = controller->dev;
+ struct device_node *child;
+ unsigned int cs;
+ int ret = -ENODEV;
++ unsigned int spi_tx_width;
+
+ for_each_available_child_of_node(np, child) {
+ struct aspeed_smc_chip *chip;
+@@ -1276,9 +1300,20 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
+ &chip->clk_rate)) {
+ chip->clk_rate = ASPEED_SPI_DEFAULT_FREQ;
+ }
++ aspeed_allowed_max_freq(chip);
+ dev_info(dev, "Using %d MHz SPI frequency\n",
+ chip->clk_rate / 1000000);
+
++ if (of_property_read_u32(child, "spi-tx-bus-width",
++ &spi_tx_width)) {
++ spi_tx_width = 2;
++ }
++ dev_info(dev, "tx width: %ld\n", spi_tx_width);
++
++ hwcaps.mask = SNOR_HWCAPS_READ |
++ SNOR_HWCAPS_READ_FAST |
++ get_hwcaps(spi_tx_width) |
++ SNOR_HWCAPS_PP;
+ chip->controller = controller;
+ chip->ctl = controller->regs + info->ctl0 + cs * 4;
+ chip->cs = cs;
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index 3668a862d37d..50904876cb09 100644
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -2315,7 +2315,12 @@ static const struct flash_info spi_nor_ids[] = {
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K |
+ SPI_NOR_QUAD_READ) },
+- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
++ /* Removed n25q00 Quad I/O support for the time being due to clock issue with chip 'Micron 8UA15 - rw182 (128MB)'
++ * while enabling Quad I/O mode. As this chip is default shipped in platforms, marking it
++ * as Not supported for the time being. Once all chips are replaced with the new model, this can be enabled
++ * back(Note:- Certain other chips having same name(n25q00) but different part number has no issues).
++ */
++ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | NO_CHIP_ERASE) },
+ { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch
new file mode 100644
index 000000000..4b3b6b838
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch
@@ -0,0 +1,37 @@
+From 8be7c34e78bd09fa95ce9972332c8c2bb950ec03 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 28 Jan 2020 16:14:07 -0800
+Subject: [PATCH] ipmi: ipmb_dev_int: add quick fix for raw I2C type
+ registration
+
+This commit adds quick fix for cases of run time registration
+through sysfs. It should be fixed later by adding parsing code for
+ipmb_id instead.
+
+This is a temporary fix. Do not upstream it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/char/ipmi/ipmb_dev_int.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c
+index 382e4a1df510..c5db37266724 100644
+--- a/drivers/char/ipmi/ipmb_dev_int.c
++++ b/drivers/char/ipmi/ipmb_dev_int.c
+@@ -328,8 +328,12 @@ static int ipmb_probe(struct i2c_client *client,
+ if (ret)
+ return ret;
+
++#if 1 /* FIXME: Quick fix. Need to add parsing code for ipmb_id instead */
++ ipmb_dev->is_i2c_protocol = true;
++#else
+ ipmb_dev->is_i2c_protocol
+ = device_property_read_bool(&client->dev, "i2c-protocol");
++#endif
+
+ ipmb_dev->client = client;
+ i2c_set_clientdata(client, ipmb_dev);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch
new file mode 100644
index 000000000..3e426edcd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch
@@ -0,0 +1,57 @@
+From f280c15c79e7d13e4a59d413a3091eb21b56dd92 Mon Sep 17 00:00:00 2001
+From: Johnathan Mantey <johnathanx.mantey@intel.com>
+Date: Mon, 27 Jan 2020 09:03:56 -0800
+Subject: [PATCH] Return link speed and duplex settings for the NCSI channel
+
+The ftgmac100_open function initializes state for the NCSI
+channel. The get link settings function does not return this
+data. This caused the link speed, and the duplex value to be returned
+incorrectly by the PHY driver (0 Mbps, and duplex off).
+
+Update the driver to return either the PHY settings when not using
+NCSI, or the NCSI values that were assigned when the driver is opened.
+
+Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
+---
+ drivers/net/ethernet/faraday/ftgmac100.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
+index 8ed85037f021..a53878eecfc8 100644
+--- a/drivers/net/ethernet/faraday/ftgmac100.c
++++ b/drivers/net/ethernet/faraday/ftgmac100.c
+@@ -1218,10 +1218,30 @@ static int ftgmac100_set_pauseparam(struct net_device *netdev,
+ return 0;
+ }
+
++int ftgmac100_ethtool_get_link_ksettings(struct net_device *netdev,
++ struct ethtool_link_ksettings *cmd)
++{
++ struct phy_device *phydev = netdev->phydev;
++ struct ftgmac100 *priv = netdev_priv(netdev);
++ int retval = 0;
++
++ if (phydev) {
++ phy_ethtool_ksettings_get(phydev, cmd);
++ } else if (priv->use_ncsi) {
++ cmd->base.speed = priv->cur_speed;
++ cmd->base.duplex = priv->cur_duplex;
++ cmd->base.autoneg = 0;
++ } else {
++ retval = -ENODEV;
++ }
++
++ return retval;
++}
++
+ static const struct ethtool_ops ftgmac100_ethtool_ops = {
+ .get_drvinfo = ftgmac100_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+- .get_link_ksettings = phy_ethtool_get_link_ksettings,
++ .get_link_ksettings = ftgmac100_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .nway_reset = phy_ethtool_nway_reset,
+ .get_ringparam = ftgmac100_get_ringparam,
+--
+2.24.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch
new file mode 100644
index 000000000..377ec2b36
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch
@@ -0,0 +1,783 @@
+From 0301f9b2bc948069aaad2899e15e6c94a07ca818 Mon Sep 17 00:00:00 2001
+From: Ayushi Smriti <smriti.ayushi@intel.com>
+Date: Mon, 2 Mar 2020 22:51:46 +0530
+Subject: [PATCH] pwm and tach driver changes for ast2600
+
+This commit includes additions/changes in driver code
+to support 9 PWM outputs and 9 fan tachometer inputs for
+ast2600
+
+Signed-off-by: Ayushi Smriti <smriti.ayushi@intel.com>
+---
+ drivers/hwmon/aspeed-g6-pwm-tacho.c | 328 +++++++++++++++-------------
+ 1 file changed, 171 insertions(+), 157 deletions(-)
+
+diff --git a/drivers/hwmon/aspeed-g6-pwm-tacho.c b/drivers/hwmon/aspeed-g6-pwm-tacho.c
+index 1894f6ad5edb..1ff788bf1133 100644
+--- a/drivers/hwmon/aspeed-g6-pwm-tacho.c
++++ b/drivers/hwmon/aspeed-g6-pwm-tacho.c
+@@ -64,6 +64,8 @@
+ #define PWM_RISING_FALLING_BIT (8) //pwm falling point bit [7:0]
+ #define PWM_RISING_RISING_BIT (0) //pwm rising point bit [7:0]
+
++#define DEF_PWM_PERIOD 0xff
++
+ #define ASPEED_TACHO_CTRL 0x08 //TACH0 General Register
+ #define ASPEED_TACHO_CTRL_CH(x) ((x * 0x10) + 0x08)
+ #define TACHO_IER BIT(31) //enable tacho interrupt
+@@ -72,8 +74,7 @@
+ #define TACHO_ENABLE BIT(28) //{enable tacho}
+ #define TACHO_DEBOUNCE_BIT (26) //{tacho de-bounce}
+ #define TACHO_DEBOUNCE_MASK (0x3 << 26) //{tacho de-bounce}
+-#define TECHIO_EDGE_MASK (0x3 << 24) //tacho edge}
+-#define TECHIO_EDGE_BIT (24) //tacho edge}
++#define TACHIO_EDGE_BIT (24) /*tacho edge}*/
+ #define TACHO_CLK_DIV_T_MASK (0xf << 20)
+ #define TACHO_CLK_DIV_BIT (20)
+ #define TACHO_THRESHOLD_MASK (0xfffff) //tacho threshold bit
+@@ -102,211 +103,183 @@
+
+ #define MAX_CDEV_NAME_LEN 16
+
++#define DEFAULT_TARGET_PWM_FREQ 25000
++#define DEFAULT_MIN_RPM 2900
++
++#define PWM_FALLING_VALUE 0xff
++
+ struct aspeed_pwm_channel_params {
++ int target_freq;
++ int pwm_freq;
+ int load_wdt_rising_falling_pt;
+ int load_wdt_selection; //0: rising , 1: falling
+ int load_wdt_enable;
+ int duty_sync_enable;
+ int invert_pin;
+- u8 divide_h;
+- u8 divide_l;
+- u8 period;
+ u8 rising;
+ u8 falling;
+ };
+
+ static struct aspeed_pwm_channel_params default_pwm_params[] = {
+ [0] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 1,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [1] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [2] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [3] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [4] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [5] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [6] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [7] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [8] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [9] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [10] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [11] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [12] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [13] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [14] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ [15] = {
++ .target_freq = 25000,
+ .load_wdt_rising_falling_pt = 0x10,
+ .load_wdt_selection = 0,
+ .load_wdt_enable = 0,
+ .duty_sync_enable = 0,
+ .invert_pin = 0,
+- .divide_h = 0x5,
+- .divide_l = 0x6,
+- .period = 0x13, //5% ~~
+ .rising = 0x00,
+- .falling = 0x0a,
++ .falling = PWM_FALLING_VALUE,
+ },
+ };
+
+@@ -318,125 +291,146 @@ static struct aspeed_pwm_channel_params default_pwm_params[] = {
+ * 11: reserved.
+ */
+
++#define F2F_EDGES 0x00
++#define R2R_EDGES 0x01
++#define BOTH_EDGES 0x02
++
+ struct aspeed_tacho_channel_params {
++ u32 min_rpm;
+ int limited_inverse;
+ u16 threshold;
+ u8 tacho_edge;
+ u8 tacho_debounce;
+- u8 divide;
++ u32 divide;
+ };
+
+
+ static struct aspeed_tacho_channel_params default_tacho_params[] = {
+ [0] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [1] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [2] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [3] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [4] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [5] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [6] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [7] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [8] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [9] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [10] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [11] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [12] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [13] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [14] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+ [15] = {
++ .min_rpm = 2900,
+ .limited_inverse = 0,
+ .threshold = 0,
+- .tacho_edge = 0,
++ .tacho_edge = F2F_EDGES,
+ .tacho_debounce = 0,
+ .divide = 8,
+ },
+@@ -501,29 +495,28 @@ static void aspeed_set_pwm_channel_enable(struct regmap *regmap, u8 pwm_channel,
+ static void aspeed_set_fan_tach_ch_enable(struct aspeed_pwm_tachometer_data *priv, u8 fan_tach_ch,
+ bool enable)
+ {
+- u32 i = 0, j;
++ u32 i;
+ u32 divide_val = 0;
++ u32 target_div;
+ u32 reg_value = 0;
+
+ if(enable) {
+- //4 ^ n
+- //check pwm clk and to change tacho devide 25KZ
+- for(i = 0; i < 12; i++) {
++ /*RPM calculation as per ast2600 datasheet*/
++ target_div = (priv->clk_freq * 60 / priv->tacho_channel[fan_tach_ch].min_rpm * 2) / (0xfffff + 1);
++ if (target_div) {
++ for (i = 0; i < 12; i++) {
++ divide_val = BIT(i) * BIT(i);
++ if (divide_val > target_div)
++ break;
++ }
++ } else {
+ divide_val = 1;
+- for (j = 1; j <= i; j++)
+- divide_val *= 4;
+-// printk("i : %d , priv->clk_freq/divide_val %d ",i, priv->clk_freq/divide_val);
+- if((priv->clk_freq/divide_val) < 250000)
+- break;
+ }
+- i--;
+- divide_val = ((1 << i) * (1 << i));
+-// printk("tacho divide_val %d , i %x max tacho clk %d \n", divide_val, i, priv->clk_freq / divide_val);
+- priv->tacho_channel[fan_tach_ch].divide = i;
++ priv->tacho_channel[fan_tach_ch].divide = divide_val;
+
+ reg_value = TACHO_ENABLE |
+- (priv->tacho_channel[fan_tach_ch].tacho_edge << TECHIO_EDGE_BIT) |
+- (priv->tacho_channel[fan_tach_ch].divide << TACHO_CLK_DIV_BIT) |
++ (priv->tacho_channel[fan_tach_ch].tacho_edge << TACHIO_EDGE_BIT) |
++ (i << TACHO_CLK_DIV_BIT) |
+ (priv->tacho_channel[fan_tach_ch].tacho_debounce << TACHO_DEBOUNCE_BIT);
+
+ if(priv->tacho_channel[fan_tach_ch].limited_inverse)
+@@ -541,14 +534,28 @@ static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *p
+ u8 index, u8 fan_ctrl)
+ {
+ u32 duty_value, ctrl_value;
++ u32 div_h, div_l, cal_freq;
+
+ if (fan_ctrl == 0) {
+ aspeed_set_pwm_channel_enable(priv->regmap, index, false);
+ } else {
+- duty_value = (priv->pwm_channel[index].period << PWM_PERIOD_BIT) |
+- (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT);
++ cal_freq = priv->clk_freq / (DEF_PWM_PERIOD + 1);
++ /*calculate for target frequence*/
++ for (div_l = 0; div_l < 0x100; div_l++) {
++ for (div_h = 0; div_h < 0x10; div_h++) {
++ if ((cal_freq / (BIT(div_h) * (div_l + 1))) < priv->pwm_channel[index].target_freq)
++ break;
++ }
++ if ((cal_freq / (BIT(div_h) * (div_l + 1))) < priv->pwm_channel[index].target_freq)
++ break;
++ }
++
++ priv->pwm_channel[index].pwm_freq = cal_freq / (BIT(div_h) * (div_l + 1));
+
+- ctrl_value = (priv->pwm_channel[index].divide_h << 8) | priv->pwm_channel[index].divide_l;
++ ctrl_value = (div_h << 8) | div_l;
++
++ duty_value = (DEF_PWM_PERIOD << PWM_PERIOD_BIT) |
++ (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT);
+
+ if (priv->pwm_channel[index].load_wdt_enable) {
+ ctrl_value |= PWM_DUTY_LOAD_AS_WDT_EN;
+@@ -568,13 +575,11 @@ static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *p
+ }
+ }
+
+-#define BOTH_EDGES 0x02 /* 10b */
+-
+ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv,
+ u8 fan_tach_ch)
+ {
+ u32 raw_data, tach_div, clk_source, val;
+- u8 mode, both;
++ u8 multiplier = 2;
+ int i, retries = 3;
+
+ for(i = 0; i < retries; i++) {
+@@ -587,22 +592,15 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv,
+ if(raw_data == 0xfffff)
+ return 0;
+
+- tach_div = priv->tacho_channel[fan_tach_ch].divide;
+- /*
+- * We need the mode to determine if the raw_data is double (from
+- * counting both edges).
+- */
+- mode = priv->tacho_channel[fan_tach_ch].tacho_edge;
+- both = (mode & BOTH_EDGES) ? 1 : 0;
+-// printk("clk %ld, raw_data %x , tach_div %x both %x \n", priv->clk_freq, raw_data, tach_div, both);
++ raw_data += 1;
++ tach_div = raw_data * (priv->tacho_channel[fan_tach_ch].divide) * (multiplier);
+
+- tach_div = (tach_div * 2) * (0x1 << both);
+ clk_source = priv->clk_freq;
+
+ if (raw_data == 0)
+ return 0;
+
+- return (clk_source * 60) / (2 * raw_data * tach_div);
++ return (clk_source / tach_div * 60);
+
+ }
+
+@@ -614,19 +612,27 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ int ret;
+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev);
+ long fan_ctrl;
++ u8 org_falling = priv->pwm_channel[index].falling;
+
+ ret = kstrtol(buf, 10, &fan_ctrl);
+ if (ret != 0)
+ return ret;
+
+- if (fan_ctrl < 0 || fan_ctrl > priv->pwm_channel[index].period)
++ if (fan_ctrl < 0 || fan_ctrl > DEF_PWM_PERIOD)
+ return -EINVAL;
+
+ if (priv->pwm_channel[index].falling == fan_ctrl)
+ return count;
+
+ priv->pwm_channel[index].falling = fan_ctrl;
+- aspeed_set_pwm_channel_fan_ctrl(priv, index, fan_ctrl);
++
++ if (fan_ctrl == 0)
++ aspeed_set_pwm_channel_enable(priv->regmap, index, false);
++ else
++ regmap_update_bits(priv->regmap, ASPEED_PWM_DUTY_CYCLE_CH(index), GENMASK(15, 8), (fan_ctrl << PWM_RISING_FALLING_BIT));
++
++ if (org_falling == 0)
++ aspeed_set_pwm_channel_enable(priv->regmap, index, true);
+
+ return count;
+ }
+@@ -678,40 +684,39 @@ static umode_t fan_dev_is_visible(struct kobject *kobj,
+ return a->mode;
+ }
+
+-static SENSOR_DEVICE_ATTR(pwm0, 0644,
+- show_pwm, set_pwm, 0);
+ static SENSOR_DEVICE_ATTR(pwm1, 0644,
+- show_pwm, set_pwm, 1);
++ show_pwm, set_pwm, 0);
+ static SENSOR_DEVICE_ATTR(pwm2, 0644,
+- show_pwm, set_pwm, 2);
++ show_pwm, set_pwm, 1);
+ static SENSOR_DEVICE_ATTR(pwm3, 0644,
+- show_pwm, set_pwm, 3);
++ show_pwm, set_pwm, 2);
+ static SENSOR_DEVICE_ATTR(pwm4, 0644,
+- show_pwm, set_pwm, 4);
++ show_pwm, set_pwm, 3);
+ static SENSOR_DEVICE_ATTR(pwm5, 0644,
+- show_pwm, set_pwm, 5);
++ show_pwm, set_pwm, 4);
+ static SENSOR_DEVICE_ATTR(pwm6, 0644,
+- show_pwm, set_pwm, 6);
++ show_pwm, set_pwm, 5);
+ static SENSOR_DEVICE_ATTR(pwm7, 0644,
+- show_pwm, set_pwm, 7);
++ show_pwm, set_pwm, 6);
+ static SENSOR_DEVICE_ATTR(pwm8, 0644,
+- show_pwm, set_pwm, 8);
++ show_pwm, set_pwm, 7);
+ static SENSOR_DEVICE_ATTR(pwm9, 0644,
+- show_pwm, set_pwm, 9);
++ show_pwm, set_pwm, 8);
+ static SENSOR_DEVICE_ATTR(pwm10, 0644,
+- show_pwm, set_pwm, 10);
++ show_pwm, set_pwm, 9);
+ static SENSOR_DEVICE_ATTR(pwm11, 0644,
+- show_pwm, set_pwm, 11);
++ show_pwm, set_pwm, 10);
+ static SENSOR_DEVICE_ATTR(pwm12, 0644,
+- show_pwm, set_pwm, 12);
++ show_pwm, set_pwm, 11);
+ static SENSOR_DEVICE_ATTR(pwm13, 0644,
+- show_pwm, set_pwm, 13);
++ show_pwm, set_pwm, 12);
+ static SENSOR_DEVICE_ATTR(pwm14, 0644,
+- show_pwm, set_pwm, 14);
++ show_pwm, set_pwm, 13);
+ static SENSOR_DEVICE_ATTR(pwm15, 0644,
++ show_pwm, set_pwm, 14);
++static SENSOR_DEVICE_ATTR(pwm16, 0644,
+ show_pwm, set_pwm, 15);
+ static struct attribute *pwm_dev_attrs[] = {
+- &sensor_dev_attr_pwm0.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+@@ -727,6 +732,7 @@ static struct attribute *pwm_dev_attrs[] = {
+ &sensor_dev_attr_pwm13.dev_attr.attr,
+ &sensor_dev_attr_pwm14.dev_attr.attr,
+ &sensor_dev_attr_pwm15.dev_attr.attr,
++ &sensor_dev_attr_pwm16.dev_attr.attr,
+ NULL,
+ };
+
+@@ -735,40 +741,39 @@ static const struct attribute_group pwm_dev_group = {
+ .is_visible = pwm_is_visible,
+ };
+
+-static SENSOR_DEVICE_ATTR(fan0_input, 0444,
+- show_rpm, NULL, 0);
+ static SENSOR_DEVICE_ATTR(fan1_input, 0444,
+- show_rpm, NULL, 1);
++ show_rpm, NULL, 0);
+ static SENSOR_DEVICE_ATTR(fan2_input, 0444,
+- show_rpm, NULL, 2);
++ show_rpm, NULL, 1);
+ static SENSOR_DEVICE_ATTR(fan3_input, 0444,
+- show_rpm, NULL, 3);
++ show_rpm, NULL, 2);
+ static SENSOR_DEVICE_ATTR(fan4_input, 0444,
+- show_rpm, NULL, 4);
++ show_rpm, NULL, 3);
+ static SENSOR_DEVICE_ATTR(fan5_input, 0444,
+- show_rpm, NULL, 5);
++ show_rpm, NULL, 4);
+ static SENSOR_DEVICE_ATTR(fan6_input, 0444,
+- show_rpm, NULL, 6);
++ show_rpm, NULL, 5);
+ static SENSOR_DEVICE_ATTR(fan7_input, 0444,
+- show_rpm, NULL, 7);
++ show_rpm, NULL, 6);
+ static SENSOR_DEVICE_ATTR(fan8_input, 0444,
+- show_rpm, NULL, 8);
++ show_rpm, NULL, 7);
+ static SENSOR_DEVICE_ATTR(fan9_input, 0444,
+- show_rpm, NULL, 9);
++ show_rpm, NULL, 8);
+ static SENSOR_DEVICE_ATTR(fan10_input, 0444,
+- show_rpm, NULL, 10);
++ show_rpm, NULL, 9);
+ static SENSOR_DEVICE_ATTR(fan11_input, 0444,
+- show_rpm, NULL, 11);
++ show_rpm, NULL, 10);
+ static SENSOR_DEVICE_ATTR(fan12_input, 0444,
+- show_rpm, NULL, 12);
++ show_rpm, NULL, 11);
+ static SENSOR_DEVICE_ATTR(fan13_input, 0444,
+- show_rpm, NULL, 13);
++ show_rpm, NULL, 12);
+ static SENSOR_DEVICE_ATTR(fan14_input, 0444,
+- show_rpm, NULL, 14);
++ show_rpm, NULL, 13);
+ static SENSOR_DEVICE_ATTR(fan15_input, 0444,
++ show_rpm, NULL, 14);
++static SENSOR_DEVICE_ATTR(fan16_input, 0444,
+ show_rpm, NULL, 15);
+ static struct attribute *fan_dev_attrs[] = {
+- &sensor_dev_attr_fan0_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+@@ -784,6 +789,7 @@ static struct attribute *fan_dev_attrs[] = {
+ &sensor_dev_attr_fan13_input.dev_attr.attr,
+ &sensor_dev_attr_fan14_input.dev_attr.attr,
+ &sensor_dev_attr_fan15_input.dev_attr.attr,
++ &sensor_dev_attr_fan16_input.dev_attr.attr,
+ NULL
+ };
+
+@@ -802,14 +808,14 @@ static void aspeed_create_pwm_channel(struct aspeed_pwm_tachometer_data *priv,
+ }
+
+ static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tachometer_data *priv,
+- u8 *fan_tach_ch,
+- int count)
++ u8 *fan_tach_ch, int count, u32 min_rpm)
+ {
+ u8 val, index;
+
+ for (val = 0; val < count; val++) {
+ index = fan_tach_ch[val];
+ priv->fan_tach_present[index] = true;
++ priv->tacho_channel[index].min_rpm = min_rpm;
+ aspeed_set_fan_tach_ch_enable(priv, index, true);
+ }
+ }
+@@ -906,13 +912,19 @@ static int aspeed_pwm_create_fan(struct device *dev,
+ struct aspeed_pwm_tachometer_data *priv)
+ {
+ u8 *fan_tach_ch;
++ u32 fan_min_rpm;
+ u32 pwm_channel;
++ u32 target_pwm_freq;
+ int ret, count;
+
+ ret = of_property_read_u32(child, "reg", &pwm_channel);
+ if (ret)
+ return ret;
+
++ ret = of_property_read_u32(child, "aspeed,target_pwm", &target_pwm_freq);
++ if (ret)
++ target_pwm_freq = DEFAULT_TARGET_PWM_FREQ;
++
+ aspeed_create_pwm_channel(priv, (u8)pwm_channel);
+
+ ret = of_property_count_u8_elems(child, "cooling-levels");
+@@ -935,9 +947,11 @@ static int aspeed_pwm_create_fan(struct device *dev,
+ fan_tach_ch, count);
+ if (ret)
+ return ret;
++ ret = of_property_read_u32(child, "aspeed,min_rpm", &fan_min_rpm);
++ if (ret)
++ fan_min_rpm = DEFAULT_MIN_RPM;
+
+- aspeed_create_fan_tach_channel(priv, fan_tach_ch, count);
+-
++ aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, fan_min_rpm);
+ return 0;
+ }
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch
new file mode 100644
index 000000000..e2196c629
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch
@@ -0,0 +1,40 @@
+From 7555448ab0676ea974ef67ef0c8ebe5d68b73d25 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Tue, 18 Feb 2020 14:17:22 -0800
+Subject: [PATCH] Fix truncated WrEndPointConfig MMIO command
+
+When address type is 6, the driver is reducing the msg buffer to
+the base size and truncating the additional command data.
+
+This removes the line that sets the msg buffer size to the base
+size. The correct buffer size is already set.
+
+Tested:
+Ran this command:
+peci_cmds WrEndpointConfigMMIO 6 0 0 0x7e 0x1a 0x0 0x224e0 0x5f5a56
+
+and got the full buffer in the driver log:
+[ 795.207278] peci_aspeed 1e78b000.peci-bus: HEAD : 0x00011730
+[ 795.212980] TX : c5 00 05 00 00 00 06 00 d0 7e e0 24 02 00 00 00 .........~.$....
+[ 795.220556] TX : 00 00 56 5a 5f 00 a8 ..VZ_..
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ drivers/peci/peci-core.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
+index 9aedb74..efb73b0 100644
+--- a/drivers/peci/peci-core.c
++++ b/drivers/peci/peci-core.c
+@@ -1040,7 +1040,6 @@ static int peci_cmd_wr_end_pt_cfg(struct peci_adapter *adapter, void *vmsg)
+ >> 24); /* MSB - DWORD Register Offset */
+ if (umsg->params.mmio.addr_type ==
+ PECI_ENDPTCFG_ADDR_TYPE_MMIO_Q) {
+- msg->tx_len = PECI_WRENDPTCFG_MMIO_Q_WRITE_LEN_BASE;
+ msg->tx_buf[14] = (u8)(umsg->params.mmio.offset
+ >> 32); /* Register Offset */
+ msg->tx_buf[15] = (u8)(umsg->params.mmio.offset
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch
new file mode 100644
index 000000000..cb06f9def
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch
@@ -0,0 +1,237 @@
+From d5bc758cee51d92c48f2835ca2b4ebb146f0f0b4 Mon Sep 17 00:00:00 2001
+From: "Arun P. Mohanan" <arun.p.m@linux.intel.com>
+Date: Wed, 11 Mar 2020 17:23:49 +0530
+Subject: [PATCH] [Mailbox] Enabling interrupt based mailbox
+
+Modifying the mailbox driver to use FIFO queue while using interrupt.
+
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+---
+ drivers/soc/aspeed/aspeed-lpc-mbox.c | 102 ++++++++++++++++++---------
+ 1 file changed, 69 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c
+index 795107206022..1ca68bb3534c 100644
+--- a/drivers/soc/aspeed/aspeed-lpc-mbox.c
++++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c
+@@ -12,10 +12,11 @@
+ #include <linux/poll.h>
+ #include <linux/regmap.h>
+ #include <linux/slab.h>
++#include <linux/kfifo.h>
+
+ #define DEVICE_NAME "aspeed-mbox"
+
+-#define MBX_USE_INTERRUPT 0
++#define MBX_USE_INTERRUPT 1
+
+ #define ASPEED_MBOX_NUM_REGS 16
+
+@@ -29,6 +30,7 @@
+ #define ASPEED_MBOX_HOST_CTRL 0x4c
+ #define ASPEED_MBOX_INTERRUPT_0 0x50
+ #define ASPEED_MBOX_INTERRUPT_1 0x54
++#define MBOX_FIFO_SIZE 64
+
+ struct aspeed_mbox {
+ struct miscdevice miscdev;
+@@ -38,6 +40,8 @@ struct aspeed_mbox {
+ int irq;
+ wait_queue_head_t queue;
+ struct mutex mutex;
++ struct kfifo fifo;
++ spinlock_t lock;
+ };
+
+ static atomic_t aspeed_mbox_open_count = ATOMIC_INIT(0);
+@@ -74,20 +78,37 @@ static struct aspeed_mbox *file_mbox(struct file *file)
+ return container_of(file->private_data, struct aspeed_mbox, miscdev);
+ }
+
++/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */
++static void put_fifo_with_discard(struct aspeed_mbox *mbox, u8 val)
++{
++ if (!kfifo_initialized(&mbox->fifo))
++ return;
++ if (kfifo_is_full(&mbox->fifo))
++ kfifo_skip(&mbox->fifo);
++ kfifo_put(&mbox->fifo, val);
++}
++
+ static int aspeed_mbox_open(struct inode *inode, struct file *file)
+ {
+ #if MBX_USE_INTERRUPT
+ struct aspeed_mbox *mbox = file_mbox(file);
++ int i;
+ #endif
+
+ if (atomic_inc_return(&aspeed_mbox_open_count) == 1) {
+ #if MBX_USE_INTERRUPT
+ /*
+- * Clear the interrupt status bit if it was left on and unmask
+- * interrupts.
+- * ASPEED_MBOX_CTRL_RECV bit is W1C, this also unmasks in 1 step
++ * Reset the FIFO while opening to clear the old cached data
++ * and load the FIFO with latest mailbox register values.
+ */
+- aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
++ kfifo_reset(&mbox->fifo);
++ spin_lock_irq(&mbox->lock);
++ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) {
++ put_fifo_with_discard(mbox,
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)));
++ }
++ spin_unlock_irq(&mbox->lock);
++
+ #endif
+ return 0;
+ }
+@@ -102,6 +123,8 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ struct aspeed_mbox *mbox = file_mbox(file);
+ char __user *p = buf;
+ ssize_t ret;
++ unsigned int copied;
++ unsigned long flags;
+ int i;
+
+ if (!access_ok(buf, count))
+@@ -111,17 +134,32 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ return -EINVAL;
+
+ #if MBX_USE_INTERRUPT
+- if (file->f_flags & O_NONBLOCK) {
+- if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) &
+- ASPEED_MBOX_CTRL_RECV))
++ /*
++ * Restrict count as per the number of mailbox registers
++ * to use kfifo.
++ */
++ if (count != ASPEED_MBOX_NUM_REGS)
++ goto reg_read;
++
++ if (kfifo_is_empty(&mbox->fifo)) {
++ if (file->f_flags & O_NONBLOCK){
+ return -EAGAIN;
+- } else if (wait_event_interruptible(mbox->queue,
+- aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) &
+- ASPEED_MBOX_CTRL_RECV)) {
+- return -ERESTARTSYS;
++ }
++ ret = wait_event_interruptible(mbox->queue,
++ !kfifo_is_empty(&mbox->fifo));
++ if (ret == -ERESTARTSYS){
++ return -EINTR;
++ }
+ }
++
++ spin_lock_irqsave(&mbox->lock, flags);
++ ret = kfifo_to_user(&mbox->fifo, buf, count, &copied);
++ spin_unlock_irqrestore(&mbox->lock, flags);
++ return ret ? ret : copied;
++
+ #endif
+
++reg_read:
+ mutex_lock(&mbox->mutex);
+
+ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) {
+@@ -134,11 +172,6 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ p++;
+ count--;
+ }
+-
+-#if MBX_USE_INTERRUPT
+- /* ASPEED_MBOX_CTRL_RECV bit is write to clear, this also unmasks in 1 step */
+- aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL);
+-#endif
+ ret = p - buf;
+
+ out_unlock:
+@@ -186,16 +219,9 @@ static ssize_t aspeed_mbox_write(struct file *file, const char __user *buf,
+ static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait)
+ {
+ struct aspeed_mbox *mbox = file_mbox(file);
+- unsigned int mask = 0;
+
+ poll_wait(file, &mbox->queue, wait);
+-
+-#if MBX_USE_INTERRUPT
+- if (aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV)
+-#endif
+- mask |= POLLIN;
+-
+- return mask;
++ return !kfifo_is_empty(&mbox->fifo) ? POLLIN : 0;
+ }
+
+ static int aspeed_mbox_release(struct inode *inode, struct file *file)
+@@ -220,19 +246,23 @@ static irqreturn_t aspeed_mbox_irq(int irq, void *arg)
+ #if MBX_USE_INTERRUPT
+ int i;
+
+-// if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV))
+-// return IRQ_NONE;
+-
+- printk(KERN_ERR "BMC_CTRL: 0x%02x\n",
++ dev_dbg(mbox->miscdev.parent, "BMC_CTRL11: 0x%02x\n",
+ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL));
+- printk(KERN_ERR "STATUS_0: 0x%02x\n",
++ dev_dbg(mbox->miscdev.parent, "STATUS_0: 0x%02x\n",
+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_0));
+- printk(KERN_ERR "STATUS_1: 0x%02x\n",
++ dev_dbg(mbox->miscdev.parent, "STATUS_1: 0x%02x\n",
+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_1));
+ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) {
+- printk(KERN_ERR "DATA_%d: 0x%02x\n", i,
++ dev_dbg(mbox->miscdev.parent, "DATA_%d: 0x%02x\n", i,
+ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)));
+ }
++
++ spin_lock(&mbox->lock);
++ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) {
++ put_fifo_with_discard(mbox,
++ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)));
++ }
++ spin_unlock(&mbox->lock);
+ #endif
+
+ /* Clear interrupt status */
+@@ -249,7 +279,6 @@ static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox,
+ {
+ struct device *dev = &pdev->dev;
+ int rc;
+-
+ mbox->irq = platform_get_irq(pdev, 0);
+ if (!mbox->irq)
+ return -ENODEV;
+@@ -300,6 +329,7 @@ static int aspeed_mbox_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
++ spin_lock_init(&mbox->lock);
+ mutex_init(&mbox->mutex);
+ init_waitqueue_head(&mbox->queue);
+
+@@ -316,6 +346,11 @@ static int aspeed_mbox_probe(struct platform_device *pdev)
+ return rc;
+ }
+
++ /* Create FIFO data structure */
++ rc = kfifo_alloc(&mbox->fifo, MBOX_FIFO_SIZE, GFP_KERNEL);
++ if (rc)
++ return rc;
++
+ mbox->miscdev.minor = MISC_DYNAMIC_MINOR;
+ mbox->miscdev.name = DEVICE_NAME;
+ mbox->miscdev.fops = &aspeed_mbox_fops;
+@@ -349,6 +384,7 @@ static int aspeed_mbox_remove(struct platform_device *pdev)
+
+ misc_deregister(&mbox->miscdev);
+ clk_disable_unprepare(mbox->clk);
++ kfifo_free(&mbox->fifo);
+
+ return 0;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch
new file mode 100644
index 000000000..b4118e169
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch
@@ -0,0 +1,151 @@
+From 9479d8f12efc845faca4bb1aef9b6e63799a7e5c Mon Sep 17 00:00:00 2001
+From: "Arun P. Mohanan" <arun.p.m@linux.intel.com>
+Date: Wed, 18 Mar 2020 08:34:43 +0530
+Subject: [PATCH] Add poll fops in eSPI driver
+
+Modify eSPI driver to support poll fops.
+
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+---
+ drivers/misc/aspeed-espi-slave.c | 85 +++++++++++++++++++++++---------
+ 1 file changed, 61 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c
+index 87bc81948694..cb8ed585c69f 100644
+--- a/drivers/misc/aspeed-espi-slave.c
++++ b/drivers/misc/aspeed-espi-slave.c
+@@ -9,6 +9,7 @@
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
++#include <linux/poll.h>
+ #include <linux/regmap.h>
+ #include <linux/reset.h>
+ #include <linux/sched/signal.h>
+@@ -95,6 +96,7 @@ struct aspeed_espi {
+ spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */
+ wait_queue_head_t pltrstn_waitq;
+ char pltrstn;
++ bool pltrstn_in_avail;
+ };
+
+ static void aspeed_espi_sys_event(struct aspeed_espi *priv)
+@@ -127,7 +129,10 @@ static void aspeed_espi_sys_event(struct aspeed_espi *priv)
+ dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n");
+ }
+ if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') {
++ spin_lock(&priv->pltrstn_lock);
+ priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0';
++ priv->pltrstn_in_avail = true;
++ spin_unlock(&priv->pltrstn_lock);
+ wake_up_interruptible(&priv->pltrstn_waitq);
+ dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn);
+ }
+@@ -269,6 +274,8 @@ static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp)
+ {
+ if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
+ return -EACCES;
++ struct aspeed_espi *priv = to_aspeed_espi(filp);
++ priv->pltrstn_in_avail = true ; /*Setting true returns first data after file open*/
+
+ return 0;
+ }
+@@ -284,41 +291,71 @@ static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf,
+
+ spin_lock_irqsave(&priv->pltrstn_lock, flags);
+
+- add_wait_queue(&priv->pltrstn_waitq, &wait);
+- set_current_state(TASK_INTERRUPTIBLE);
+-
+- old_sample = priv->pltrstn;
+-
+- do {
+- char new_sample = priv->pltrstn;
+-
+- if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) {
+- ret = put_user(new_sample, (unsigned long __user *)buf);
+- if (!ret)
+- ret = sizeof(new_sample);
+- } else if (signal_pending(current)) {
+- ret = -ERESTARTSYS;
++ if (filp->f_flags & O_NONBLOCK) {
++ if (!priv->pltrstn_in_avail) {
++ ret = -EAGAIN;
++ goto out_unlock;
+ }
+-
+- if (!ret) {
+- spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
+- schedule();
+- spin_lock_irqsave(&priv->pltrstn_lock, flags);
++ char data = priv->pltrstn;
++ ret = put_user(data, (unsigned long __user *)buf);
++ if (!ret){
++ ret = sizeof(data);
++ } else{
++ ret = -EAGAIN;
+ }
+- } while (!ret);
+-
+- remove_wait_queue(&priv->pltrstn_waitq, &wait);
+- set_current_state(TASK_RUNNING);
+-
++ priv->pltrstn_in_avail = false;
++ } else {
++ add_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ old_sample = priv->pltrstn;
++
++ do {
++ char new_sample = priv->pltrstn;
++
++ if (old_sample != new_sample) {
++ ret = put_user(new_sample,
++ (unsigned long __user *)buf);
++ if (!ret)
++ ret = sizeof(new_sample);
++ } else if (signal_pending(current)) {
++ ret = -ERESTARTSYS;
++ }
++
++ if (!ret) {
++ spin_unlock_irqrestore(&priv->pltrstn_lock,
++ flags);
++ schedule();
++ spin_lock_irqsave(&priv->pltrstn_lock, flags);
++ }
++ } while (!ret);
++
++ remove_wait_queue(&priv->pltrstn_waitq, &wait);
++ set_current_state(TASK_RUNNING);
++ }
++out_unlock:
+ spin_unlock_irqrestore(&priv->pltrstn_lock, flags);
+
+ return ret;
+ }
+
++static unsigned int aspeed_espi_pltrstn_poll(struct file *file,
++ poll_table *wait)
++{
++ struct aspeed_espi *priv = to_aspeed_espi(file);
++ unsigned int mask = 0;
++ poll_wait(file, &priv->pltrstn_waitq, wait);
++
++ if (priv->pltrstn_in_avail)
++ mask |= POLLIN;
++ return mask;
++}
++
+ static const struct file_operations aspeed_espi_pltrstn_fops = {
+ .owner = THIS_MODULE,
+ .open = aspeed_espi_pltrstn_open,
+ .read = aspeed_espi_pltrstn_read,
++ .poll = aspeed_espi_pltrstn_poll,
+ };
+
+ static const struct regmap_config aspeed_espi_regmap_cfg = {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch
new file mode 100644
index 000000000..f3bb26a8a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch
@@ -0,0 +1,94 @@
+From 9d4191d2702ad5a368ca79eb253de26ce94b91c7 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 30 Mar 2020 11:00:16 +0530
+Subject: [PATCH] From: Thomas Betker <thomas.betker@rohde-schwarz.com>
+
+jffs2_flash_direct_writev() always invokes jffs2_sum_add_kvec(), even
+if mtd_writev() fails. Usually, this results in an extra summary entry
+pointing to dirty node space, which should be ignored -- it is a bit of
+a waste, but harmless.
+
+When mtd_writev() returns *retlen == 0, though, the node space is not
+reserved as dirty, but re-used; the extra summary entry then points
+into the space of the next node. After the erase block has been closed,
+we get the following messages on remount:
+
+ jffs2: error: (79) jffs2_link_node_ref:
+ Adding new ref c3048d18 at (0x00ec5b88-0x00ec6bcc)
+ not immediately after previous (0x00ec5b88-0x00ec5b88)
+ ...
+ jffs2: Checked all inodes but still 0x2088 bytes of unchecked space?
+ jffs2: No space for garbage collection. Aborting GC thread
+
+The extra summary entries amount to "unchecked space", so that
+jffs2_garbage_collect_pass() returns -ENOSPC. And without garbage
+collection, the filesystem becomes unuseable over time as the erase
+blocks fill up.
+
+Fix this by skipping jffs2_sum_add_kvec() when the MTD write fails. We
+don't need the summary entry anyway, and the behaviour matches that of
+jffs2_flash_writev() in wbuf.c (with write buffering enabled).
+
+Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
+---
+ fs/jffs2/writev.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
+index a1bda9d..eec4197 100644
+--- a/fs/jffs2/writev.c
++++ b/fs/jffs2/writev.c
+@@ -16,9 +16,18 @@
+ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
+ {
++ int ret;
++
++ ret = mtd_writev(c->mtd, vecs, count, to, retlen);
++
+ if (!jffs2_is_writebuffered(c)) {
+ if (jffs2_sum_active()) {
+ int res;
++
++ if (ret ||
++ *retlen != iov_length((struct iovec *) vecs, count))
++ return ret;
++
+ res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to);
+ if (res) {
+ return res;
+@@ -26,19 +35,23 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
+ }
+ }
+
+- return mtd_writev(c->mtd, vecs, count, to, retlen);
++ return ret;
+ }
+
+ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf)
+ {
+ int ret;
++
+ ret = mtd_write(c->mtd, ofs, len, retlen, buf);
+
+ if (jffs2_sum_active()) {
+ struct kvec vecs[1];
+ int res;
+
++ if (ret || *retlen != len)
++ return ret;
++
+ vecs[0].iov_base = (unsigned char *) buf;
+ vecs[0].iov_len = len;
+
+@@ -47,5 +60,6 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
+ return res;
+ }
+ }
++
+ return ret;
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch
new file mode 100644
index 000000000..ef234fffe
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch
@@ -0,0 +1,129 @@
+From 9fc2343bac42db2432f96db1bbfc6979822a7154 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 26 Mar 2020 14:20:19 -0700
+Subject: [PATCH] Refine clock settings
+
+This commit refines clock settings with cherry picking the latest
+code from Aspeed SDK v00.05.05
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/clk/clk-ast2600.c | 60 +++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 53 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
+index fb6b11440b97..e07326544fdc 100644
+--- a/drivers/clk/clk-ast2600.c
++++ b/drivers/clk/clk-ast2600.c
+@@ -31,6 +31,24 @@
+ #define ASPEED_G6_CLK_SELECTION1 0x300
+ #define ASPEED_G6_CLK_SELECTION2 0x304
+ #define ASPEED_G6_CLK_SELECTION4 0x310
++#define ASPEED_G6_CLK_SELECTION5 0x314
++
++#define ASPEED_G6_MAC12_CLK_CTRL0 0x340
++#define ASPEED_G6_MAC12_CLK_CTRL1 0x348
++#define ASPEED_G6_MAC12_CLK_CTRL2 0x34C
++
++#define ASPEED_G6_MAC34_CLK_CTRL0 0x350
++#define ASPEED_G6_MAC34_CLK_CTRL1 0x358
++#define ASPEED_G6_MAC34_CLK_CTRL2 0x35C
++
++#define ASPEED_G6_MAC34_DRIVING_CTRL 0x458
++
++#define ASPEED_G6_DEF_MAC12_DELAY_1G 0x0041b410
++#define ASPEED_G6_DEF_MAC12_DELAY_100M 0x00417410
++#define ASPEED_G6_DEF_MAC12_DELAY_10M 0x00417410
++#define ASPEED_G6_DEF_MAC34_DELAY_1G 0x00104208
++#define ASPEED_G6_DEF_MAC34_DELAY_100M 0x00104208
++#define ASPEED_G6_DEF_MAC34_DELAY_10M 0x00104208
+
+ #define ASPEED_HPLL_PARAM 0x200
+ #define ASPEED_APLL_PARAM 0x210
+@@ -40,9 +58,6 @@
+
+ #define ASPEED_G6_STRAP1 0x500
+
+-#define ASPEED_MAC12_CLK_DLY 0x340
+-#define ASPEED_MAC34_CLK_DLY 0x350
+-
+ #define ASPEED_G6_GEN_UART_REF 0x338
+ #define UART_192MHZ_R_N_VALUE 0x3c38e
+
+@@ -515,7 +530,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
+
+ /* RMII1 50MHz (RCLK) output enable */
+ hw = clk_hw_register_gate(dev, "mac1rclk", "mac12rclk", 0,
+- scu_g6_base + ASPEED_MAC12_CLK_DLY, 29, 0,
++ scu_g6_base + ASPEED_G6_MAC12_CLK_CTRL0, 29, 0,
+ &aspeed_g6_clk_lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+@@ -523,7 +538,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
+
+ /* RMII2 50MHz (RCLK) output enable */
+ hw = clk_hw_register_gate(dev, "mac2rclk", "mac12rclk", 0,
+- scu_g6_base + ASPEED_MAC12_CLK_DLY, 30, 0,
++ scu_g6_base + ASPEED_G6_MAC12_CLK_CTRL0, 30, 0,
+ &aspeed_g6_clk_lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+@@ -545,7 +560,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
+
+ /* RMII3 50MHz (RCLK) output enable */
+ hw = clk_hw_register_gate(dev, "mac3rclk", "mac34rclk", 0,
+- scu_g6_base + ASPEED_MAC34_CLK_DLY, 29, 0,
++ scu_g6_base + ASPEED_G6_MAC34_CLK_CTRL0, 29, 0,
+ &aspeed_g6_clk_lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+@@ -553,7 +568,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev)
+
+ /* RMII4 50MHz (RCLK) output enable */
+ hw = clk_hw_register_gate(dev, "mac4rclk", "mac34rclk", 0,
+- scu_g6_base + ASPEED_MAC34_CLK_DLY, 30, 0,
++ scu_g6_base + ASPEED_G6_MAC34_CLK_CTRL0, 30, 0,
+ &aspeed_g6_clk_lock);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+@@ -770,6 +785,37 @@ static void __init aspeed_g6_cc_init(struct device_node *np)
+ return;
+ }
+
++ /* fixed settings for RGMII/RMII clock generator */
++ /* MAC1/2 RGMII 125MHz = EPLL / 8 */
++ regmap_update_bits(map, ASPEED_G6_CLK_SELECTION2, GENMASK(23, 20),
++ (0x7 << 20));
++
++ /* MAC3/4 RMII 50MHz = HCLK / 4 */
++ regmap_update_bits(map, ASPEED_G6_CLK_SELECTION4, GENMASK(18, 16),
++ (0x3 << 16));
++
++ /*
++ * BIT[31]: MAC1/2 RGMII 125M source = internal PLL
++ * BIT[28]: RGMIICK pad direction = output
++ */
++ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL0,
++ BIT(31) | BIT(28) | ASPEED_G6_DEF_MAC12_DELAY_1G);
++ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL1,
++ ASPEED_G6_DEF_MAC12_DELAY_100M);
++ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL2,
++ ASPEED_G6_DEF_MAC12_DELAY_10M);
++
++ /* MAC3/4 RGMII 125M source = RGMIICK pad */
++ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL0,
++ ASPEED_G6_DEF_MAC34_DELAY_1G);
++ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL1,
++ ASPEED_G6_DEF_MAC34_DELAY_100M);
++ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL2,
++ ASPEED_G6_DEF_MAC34_DELAY_10M);
++
++ /* MAC3/4 default pad driving strength */
++ regmap_write(map, ASPEED_G6_MAC34_DRIVING_CTRL, 0x0000000a);
++
+ aspeed_g6_cc(map);
+ aspeed_g6_clk_data->num = ASPEED_G6_NUM_CLKS;
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_g6_clk_data);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch
new file mode 100644
index 000000000..ec215d07a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch
@@ -0,0 +1,215 @@
+From 766f7e504cc2a0508c887c7625332c88f93c5729 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 27 Mar 2020 14:42:05 -0700
+Subject: [PATCH] Add chip unique id reading interface
+
+This commit adds an interface for reading chip unique id value.
+Optionally, the id can be encrypted using a dts-supplied hash data.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+Signed-off-by: Arun P. Mohanan <arun.p.m@linux.intel.com>
+---
+ drivers/soc/aspeed/aspeed-bmc-misc.c | 118 ++++++++++++++++++++++++---
+ 1 file changed, 105 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/soc/aspeed/aspeed-bmc-misc.c b/drivers/soc/aspeed/aspeed-bmc-misc.c
+index 04d97ab17274..4aad3129f793 100644
+--- a/drivers/soc/aspeed/aspeed-bmc-misc.c
++++ b/drivers/soc/aspeed/aspeed-bmc-misc.c
+@@ -7,15 +7,18 @@
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
++#include <crypto/hash.h>
+
+ #define DEVICE_NAME "aspeed-bmc-misc"
+
+ struct aspeed_bmc_ctrl {
+ const char *name;
+ u32 offset;
+- u32 mask;
++ u64 mask;
+ u32 shift;
+ bool read_only;
++ u32 reg_width;
++ const char *hash_data;
+ struct regmap *map;
+ struct kobj_attribute attr;
+ };
+@@ -31,6 +34,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ struct aspeed_bmc_ctrl *ctrl)
+ {
+ int rc;
++ u32 mask;
+
+ /* Example child:
+ *
+@@ -38,6 +42,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ * offset = <0x80>;
+ * bit-mask = <0x1>;
+ * bit-shift = <6>;
++ * reg-width = <64>;
+ * label = "foo";
+ * }
+ */
+@@ -48,9 +53,21 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ if (rc < 0)
+ return rc;
+
+- rc = of_property_read_u32(child, "bit-mask", &ctrl->mask);
+- if (rc < 0)
+- return rc;
++ /* optional reg-width, default to 32 */
++ rc = of_property_read_u32(child, "reg-width", &ctrl->reg_width);
++ if (rc < 0 || ctrl->reg_width != 64)
++ ctrl->reg_width = 32;
++
++ if (ctrl->reg_width == 32) {
++ rc = of_property_read_u32(child, "bit-mask", &mask);
++ if (rc < 0)
++ return rc;
++ ctrl->mask = mask;
++ } else {
++ rc = of_property_read_u64(child, "bit-mask", &ctrl->mask);
++ if (rc < 0)
++ return rc;
++ }
+
+ rc = of_property_read_u32(child, "bit-shift", &ctrl->shift);
+ if (rc < 0)
+@@ -59,6 +76,9 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ ctrl->read_only = of_property_read_bool(child, "read-only");
+
+ ctrl->mask <<= ctrl->shift;
++ /* optional hash_data for obfuscating reads */
++ if (of_property_read_string(child, "hash-data", &ctrl->hash_data))
++ ctrl->hash_data = NULL;
+
+ return 0;
+ }
+@@ -88,22 +108,94 @@ static int aspeed_bmc_misc_parse_dt(struct aspeed_bmc_misc *bmc,
+ return 0;
+ }
+
++#define SHA256_DIGEST_LEN 32
++static int hmac_sha256(u8 *key, u8 ksize, const char *plaintext, u8 psize,
++ u8 *output)
++{
++ struct crypto_shash *tfm;
++ struct shash_desc *shash;
++ int ret;
++
++ if (!ksize)
++ return -EINVAL;
++
++ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
++ if (IS_ERR(tfm)) {
++ return -ENOMEM;
++ }
++
++ ret = crypto_shash_setkey(tfm, key, ksize);
++ if (ret)
++ goto failed;
++
++ shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), GFP_KERNEL);
++ if (!shash) {
++ ret = -ENOMEM;
++ goto failed;
++ }
++
++ shash->tfm = tfm;
++ ret = crypto_shash_digest(shash, plaintext, psize, output);
++
++ kfree(shash);
++
++failed:
++ crypto_free_shash(tfm);
++ return ret;
++}
++
+ static ssize_t aspeed_bmc_misc_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+ {
+ struct aspeed_bmc_ctrl *ctrl;
+- unsigned int val;
++ u32 val;
++ u64 val64;
+ int rc;
++ u8 *binbuf;
++ size_t buf_len;
++ u8 hashbuf[SHA256_DIGEST_LEN];
+
+ ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr);
++
++ if (ctrl->reg_width == 32) {
++ rc = regmap_read(ctrl->map, ctrl->offset, &val);
++ if (rc)
++ return rc;
++ val &= (u32)ctrl->mask;
++ val >>= ctrl->shift;
++
++ return sprintf(buf, "%u\n", val);
++ }
+ rc = regmap_read(ctrl->map, ctrl->offset, &val);
+ if (rc)
+ return rc;
++ val64 = val;
++ rc = regmap_read(ctrl->map, ctrl->offset + sizeof(u32), &val);
++ if (rc)
++ return rc;
++ /* aspeed puts 64-bit regs as L, H in address space */
++ val64 |= (u64)val << 32;
++ val64 &= ctrl->mask;
++ val64 >>= ctrl->shift;
++ buf_len = sizeof(val64);
++
++ if (ctrl->hash_data) {
++ rc = hmac_sha256((u8*)&val64, buf_len, ctrl->hash_data,
++ strlen(ctrl->hash_data), hashbuf);
++ if (rc)
++ return rc;
++ buf_len = SHA256_DIGEST_LEN;
++ binbuf = hashbuf;
++ } else {
++ binbuf = (u8*)&val64;
++ buf_len = sizeof(val64);
++ }
++ bin2hex(buf, binbuf, buf_len);
++ buf[buf_len * 2] = '\n';
++ rc = buf_len * 2 + 1;
+
+- val &= ctrl->mask;
+- val >>= ctrl->shift;
++ return rc;
+
+- return sprintf(buf, "%u\n", val);
+ }
+
+ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj,
+@@ -114,17 +206,17 @@ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj,
+ long val;
+ int rc;
+
+- rc = kstrtol(buf, 0, &val);
+- if (rc)
+- return rc;
+-
+ ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr);
+
+ if (ctrl->read_only)
+ return -EROFS;
+
++ rc = kstrtol(buf, 0, &val);
++ if (rc)
++ return rc;
++
+ val <<= ctrl->shift;
+- rc = regmap_update_bits(ctrl->map, ctrl->offset, ctrl->mask, val);
++ rc = regmap_write_bits(ctrl->map, ctrl->offset, ctrl->mask, val);
+
+ return rc < 0 ? rc : count;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch
new file mode 100644
index 000000000..f5c0a6ec8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch
@@ -0,0 +1,38 @@
+From 2cf0bee18a390a90cd1e5736ba79909a8feef94e Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 28 Apr 2020 12:08:14 -0700
+Subject: [PATCH] i2c: aspeed: fix arbitration loss handling logic
+
+When an arbitration loss happens in a multi-master bus, driver
+drops the packet induce I2C subsystem to retry the transaction
+by returning -EAGAIN. During this handling, tx_ack comes along
+sometimes and it causes this this garbage printing
+out:
+
+aspeed-i2c-bus 1e78a400.i2c-bus: irq handled != irq. expected 0x00000009, but was 0x00000008
+
+To fix this issue, this commit adds the tx_ack flag clearing into
+the arbitration loss handling logic.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index b56e60508914..8625c0da440b 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -896,6 +896,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
+ bus->cmd_err = ret;
+ bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
++ if (ret == -EAGAIN)
++ irq_handled |= (irq_status &
++ ASPEED_I2CD_INTR_TX_ACK);
+ goto out_complete;
+ }
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch
new file mode 100644
index 000000000..7eac39e5b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch
@@ -0,0 +1,922 @@
+From ec463c332c3b954a5a0ef4ceb253701b8190bbb9 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 6 May 2020 18:11:29 -0700
+Subject: [PATCH] enable AST2600 I3C
+
+This commit ports I3C related changes from Aspeed SDK v00.05.05.
+It also includes Vitor's I3C cdev implementation which isn't
+upstreamed yet so it should be refined later.
+
+Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
+Signed-off-by: Vitor Soares <soares@synopsys.com>
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g6.dtsi | 19 +-
+ drivers/clk/clk-ast2600.c | 30 ++-
+ drivers/i3c/Kconfig | 15 ++
+ drivers/i3c/Makefile | 1 +
+ drivers/i3c/i3cdev.c | 428 ++++++++++++++++++++++++++++++
+ drivers/i3c/internals.h | 2 +
+ drivers/i3c/master.c | 39 ++-
+ drivers/i3c/master/Kconfig | 5 +
+ drivers/i3c/master/Makefile | 1 +
+ drivers/i3c/master/aspeed-i3c-global.c | 89 +++++++
+ include/dt-bindings/clock/ast2600-clock.h | 3 +-
+ include/uapi/linux/i3c/i3cdev.h | 38 +++
+ 12 files changed, 646 insertions(+), 24 deletions(-)
+ create mode 100644 drivers/i3c/i3cdev.c
+ create mode 100644 drivers/i3c/master/aspeed-i3c-global.c
+ create mode 100644 include/uapi/linux/i3c/i3cdev.h
+
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 91f431e419d9..33e1b0ef24f0 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -1091,13 +1091,20 @@
+ };
+
+ &i3c {
++ i3cglobal: i3cg@0 {
++ reg = <0x0 0x1000>;
++ compatible = "aspeed,ast2600-i3c-global";
++ resets = <&syscon ASPEED_RESET_I3C_DMA>;
++ status = "disabled";
++ };
++
+ i3c0: i3c0@2000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x2000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C0CLK>;
+ resets = <&syscon ASPEED_RESET_I3C0>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+@@ -1110,7 +1117,7 @@
+ #interrupt-cells = <1>;
+ reg = <0x3000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C1CLK>;
+ resets = <&syscon ASPEED_RESET_I3C1>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+@@ -1123,7 +1130,7 @@
+ #interrupt-cells = <1>;
+ reg = <0x4000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C2CLK>;
+ resets = <&syscon ASPEED_RESET_I3C2>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+@@ -1138,7 +1145,7 @@
+ #interrupt-cells = <1>;
+ reg = <0x5000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C3CLK>;
+ resets = <&syscon ASPEED_RESET_I3C3>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+@@ -1153,7 +1160,7 @@
+ #interrupt-cells = <1>;
+ reg = <0x6000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C4CLK>;
+ resets = <&syscon ASPEED_RESET_I3C4>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+@@ -1168,7 +1175,7 @@
+ #interrupt-cells = <1>;
+ reg = <0x7000 0x1000>;
+ compatible = "snps,dw-i3c-master-1.00a";
+- clocks = <&syscon ASPEED_CLK_APB2>;
++ clocks = <&syscon ASPEED_CLK_GATE_I3C5CLK>;
+ resets = <&syscon ASPEED_RESET_I3C5>;
+ bus-frequency = <100000>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
+index e07326544fdc..a30dcbb1a3fd 100644
+--- a/drivers/clk/clk-ast2600.c
++++ b/drivers/clk/clk-ast2600.c
+@@ -112,14 +112,14 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = {
+ [ASPEED_CLK_GATE_LHCCLK] = { 37, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */
+ /* Reserved 38 RSA: no longer used */
+ /* Reserved 39 */
+- [ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", NULL, 0 }, /* I3C0 */
+- [ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", NULL, 0 }, /* I3C1 */
+- [ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", NULL, 0 }, /* I3C2 */
+- [ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", NULL, 0 }, /* I3C3 */
+- [ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", NULL, 0 }, /* I3C4 */
+- [ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", NULL, 0 }, /* I3C5 */
+- [ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", NULL, 0 }, /* I3C6 */
+- [ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", NULL, 0 }, /* I3C7 */
++ [ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", "i3cclk", 0 }, /* I3C0 */
++ [ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", "i3cclk", 0 }, /* I3C1 */
++ [ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", "i3cclk", 0 }, /* I3C2 */
++ [ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", "i3cclk", 0 }, /* I3C3 */
++ [ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", "i3cclk", 0 }, /* I3C4 */
++ [ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", "i3cclk", 0 }, /* I3C5 */
++ [ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", "i3cclk", 0 }, /* I3C6 */
++ [ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", "i3cclk", 0 }, /* I3C7 */
+ [ASPEED_CLK_GATE_UART1CLK] = { 48, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */
+ [ASPEED_CLK_GATE_UART2CLK] = { 49, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */
+ [ASPEED_CLK_GATE_UART3CLK] = { 50, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */
+@@ -749,6 +749,20 @@ static void __init aspeed_g6_cc(struct regmap *map)
+ /* USB 2.0 port1 phy 40MHz clock */
+ hw = clk_hw_register_fixed_rate(NULL, "usb-phy-40m", NULL, 0, 40000000);
+ aspeed_g6_clk_data->hws[ASPEED_CLK_USBPHY_40M] = hw;
++
++ /* i3c clock source */
++ regmap_read(map, ASPEED_G6_CLK_SELECTION5, &val);
++ if(val & BIT(31)) {
++ val = (val >> 28) & 0x7;
++ if(val)
++ div = val + 1;
++ else
++ div = val + 2;
++ hw = clk_hw_register_fixed_factor(NULL, "i3cclk", "apll", 0, 1, div);
++ } else {
++ hw = clk_hw_register_fixed_factor(NULL, "i3cclk", "ahb", 0, 1, 1);
++ }
++ aspeed_g6_clk_data->hws[ASPEED_CLK_I3C] = hw;
+ };
+
+ static void __init aspeed_g6_cc_init(struct device_node *np)
+diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
+index 30a441506f61..01642768ab5f 100644
+--- a/drivers/i3c/Kconfig
++++ b/drivers/i3c/Kconfig
+@@ -20,5 +20,20 @@ menuconfig I3C
+ will be called i3c.
+
+ if I3C
++
++config I3CDEV
++ tristate "I3C device interface"
++ depends on I3C
++ help
++ Say Y here to use i3c-* device files, usually found in the /dev
++ directory on your system. They make it possible to have user-space
++ programs use the I3C devices.
++
++ This support is also available as a module. If so, the module
++ will be called i3cdev.
++
++ Note that this application programming interface is EXPERIMENTAL
++ and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
++
+ source "drivers/i3c/master/Kconfig"
+ endif # I3C
+diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile
+index 11982efbc6d9..606d422841b2 100644
+--- a/drivers/i3c/Makefile
++++ b/drivers/i3c/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+ i3c-y := device.o master.o
+ obj-$(CONFIG_I3C) += i3c.o
++obj-$(CONFIG_I3CDEV) += i3cdev.o
+ obj-$(CONFIG_I3C) += master/
+diff --git a/drivers/i3c/i3cdev.c b/drivers/i3c/i3cdev.c
+new file mode 100644
+index 000000000000..07f5641a902d
+--- /dev/null
++++ b/drivers/i3c/i3cdev.c
+@@ -0,0 +1,428 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
++ *
++ * Author: Vitor Soares <soares@synopsys.com>
++ */
++
++#include <linux/cdev.h>
++#include <linux/compat.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/jiffies.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/notifier.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++
++#include <linux/i3c/i3cdev.h>
++
++#include "internals.h"
++
++struct i3cdev_data {
++ struct list_head list;
++ struct i3c_device *i3c;
++ struct cdev cdev;
++ struct device *dev;
++ int id;
++};
++
++static DEFINE_IDA(i3cdev_ida);
++static dev_t i3cdev_number;
++#define I3C_MINORS 16 /* 16 I3C devices supported for now */
++
++static LIST_HEAD(i3cdev_list);
++static DEFINE_SPINLOCK(i3cdev_list_lock);
++
++static struct i3cdev_data *i3cdev_get_by_i3c(struct i3c_device *i3c)
++{
++ struct i3cdev_data *i3cdev;
++
++ spin_lock(&i3cdev_list_lock);
++ list_for_each_entry(i3cdev, &i3cdev_list, list) {
++ if (i3cdev->i3c == i3c)
++ goto found;
++ }
++
++ i3cdev = NULL;
++
++found:
++ spin_unlock(&i3cdev_list_lock);
++ return i3cdev;
++}
++
++static struct i3cdev_data *get_free_i3cdev(struct i3c_device *i3c)
++{
++ struct i3cdev_data *i3cdev;
++ int id;
++
++ id = ida_simple_get(&i3cdev_ida, 0, I3C_MINORS, GFP_KERNEL);
++ if (id < 0) {
++ pr_err("i3cdev: no minor number available!\n");
++ return ERR_PTR(id);
++ }
++
++ i3cdev = kzalloc(sizeof(*i3cdev), GFP_KERNEL);
++ if (!i3cdev) {
++ ida_simple_remove(&i3cdev_ida, id);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ i3cdev->i3c = i3c;
++ i3cdev->id = id;
++
++ spin_lock(&i3cdev_list_lock);
++ list_add_tail(&i3cdev->list, &i3cdev_list);
++ spin_unlock(&i3cdev_list_lock);
++
++ return i3cdev;
++}
++
++static void put_i3cdev(struct i3cdev_data *i3cdev)
++{
++ spin_lock(&i3cdev_list_lock);
++ list_del(&i3cdev->list);
++ spin_unlock(&i3cdev_list_lock);
++ kfree(i3cdev);
++}
++
++static ssize_t
++i3cdev_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
++{
++ struct i3c_device *i3c = file->private_data;
++ struct i3c_priv_xfer xfers = {
++ .rnw = true,
++ .len = count,
++ };
++ char *tmp;
++ int ret;
++
++ tmp = kzalloc(count, GFP_KERNEL);
++ if (!tmp)
++ return -ENOMEM;
++
++ xfers.data.in = tmp;
++
++ dev_dbg(&i3c->dev, "Reading %zu bytes.\n", count);
++
++ ret = i3c_device_do_priv_xfers(i3c, &xfers, 1);
++ if (!ret)
++ ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
++
++ kfree(tmp);
++ return ret;
++}
++
++static ssize_t
++i3cdev_write(struct file *file, const char __user *buf, size_t count,
++ loff_t *f_pos)
++{
++ struct i3c_device *i3c = file->private_data;
++ struct i3c_priv_xfer xfers = {
++ .rnw = false,
++ .len = count,
++ };
++ char *tmp;
++ int ret;
++
++ tmp = memdup_user(buf, count);
++ if (IS_ERR(tmp))
++ return PTR_ERR(tmp);
++
++ xfers.data.out = tmp;
++
++ dev_dbg(&i3c->dev, "Writing %zu bytes.\n", count);
++
++ ret = i3c_device_do_priv_xfers(i3c, &xfers, 1);
++ kfree(tmp);
++ return (!ret) ? count : ret;
++}
++
++static int
++i3cdev_do_priv_xfer(struct i3c_device *dev, struct i3c_ioc_priv_xfer *xfers,
++ unsigned int nxfers)
++{
++ struct i3c_priv_xfer *k_xfers;
++ u8 **data_ptrs;
++ int i, ret = 0;
++
++ k_xfers = kcalloc(nxfers, sizeof(*k_xfers), GFP_KERNEL);
++ if (!k_xfers)
++ return -ENOMEM;
++
++ data_ptrs = kcalloc(nxfers, sizeof(*data_ptrs), GFP_KERNEL);
++ if (!data_ptrs) {
++ ret = -ENOMEM;
++ goto err_free_k_xfer;
++ }
++
++ for (i = 0; i < nxfers; i++) {
++ data_ptrs[i] = memdup_user((const u8 __user *)
++ (uintptr_t)xfers[i].data,
++ xfers[i].len);
++ if (IS_ERR(data_ptrs[i])) {
++ ret = PTR_ERR(data_ptrs[i]);
++ break;
++ }
++
++ k_xfers[i].len = xfers[i].len;
++ if (xfers[i].rnw) {
++ k_xfers[i].rnw = true;
++ k_xfers[i].data.in = data_ptrs[i];
++ } else {
++ k_xfers[i].rnw = false;
++ k_xfers[i].data.out = data_ptrs[i];
++ }
++ }
++
++ if (ret < 0) {
++ i--;
++ goto err_free_mem;
++ }
++
++ ret = i3c_device_do_priv_xfers(dev, k_xfers, nxfers);
++ if (ret)
++ goto err_free_mem;
++
++ for (i = 0; i < nxfers; i++) {
++ if (xfers[i].rnw) {
++ if (copy_to_user((void __user *)(uintptr_t)xfers[i].data,
++ data_ptrs[i], xfers[i].len))
++ ret = -EFAULT;
++ }
++ }
++
++err_free_mem:
++ for (; i >= 0; i--)
++ kfree(data_ptrs[i]);
++ kfree(data_ptrs);
++err_free_k_xfer:
++ kfree(k_xfers);
++ return ret;
++}
++
++static struct i3c_ioc_priv_xfer *
++i3cdev_get_ioc_priv_xfer(unsigned int cmd, struct i3c_ioc_priv_xfer *u_xfers,
++ unsigned int *nxfers)
++{
++ u32 tmp = _IOC_SIZE(cmd);
++
++ if ((tmp % sizeof(struct i3c_ioc_priv_xfer)) != 0)
++ return ERR_PTR(-EINVAL);
++
++ *nxfers = tmp / sizeof(struct i3c_ioc_priv_xfer);
++ if (*nxfers == 0)
++ return NULL;
++
++ return memdup_user(u_xfers, tmp);
++}
++
++static int
++i3cdev_ioc_priv_xfer(struct i3c_device *i3c, unsigned int cmd,
++ struct i3c_ioc_priv_xfer *u_xfers)
++{
++ struct i3c_ioc_priv_xfer *k_xfers;
++ unsigned int nxfers;
++ int ret;
++
++ k_xfers = i3cdev_get_ioc_priv_xfer(cmd, u_xfers, &nxfers);
++ if (IS_ERR_OR_NULL(k_xfers))
++ return PTR_ERR(k_xfers);
++
++ ret = i3cdev_do_priv_xfer(i3c, k_xfers, nxfers);
++
++ kfree(k_xfers);
++
++ return ret;
++}
++
++static long
++i3cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct i3c_device *i3c = file->private_data;
++
++ dev_dbg(&i3c->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", cmd, arg);
++
++ if (_IOC_TYPE(cmd) != I3C_DEV_IOC_MAGIC)
++ return -ENOTTY;
++
++ /* Check command number and direction */
++ if (_IOC_NR(cmd) == _IOC_NR(I3C_IOC_PRIV_XFER(0)) &&
++ _IOC_DIR(cmd) == (_IOC_READ | _IOC_WRITE))
++ return i3cdev_ioc_priv_xfer(i3c, cmd,
++ (struct i3c_ioc_priv_xfer __user *)arg);
++
++ return 0;
++}
++
++static int i3cdev_open(struct inode *inode, struct file *file)
++{
++ struct i3cdev_data *i3cdev = container_of(inode->i_cdev,
++ struct i3cdev_data,
++ cdev);
++
++ file->private_data = i3cdev->i3c;
++
++ return 0;
++}
++
++static int i3cdev_release(struct inode *inode, struct file *file)
++{
++ file->private_data = NULL;
++
++ return 0;
++}
++
++static const struct file_operations i3cdev_fops = {
++ .owner = THIS_MODULE,
++ .read = i3cdev_read,
++ .write = i3cdev_write,
++ .unlocked_ioctl = i3cdev_ioctl,
++ .open = i3cdev_open,
++ .release = i3cdev_release,
++};
++
++/* ------------------------------------------------------------------------- */
++
++static struct class *i3cdev_class;
++
++static int i3cdev_attach(struct device *dev, void *dummy)
++{
++ struct i3cdev_data *i3cdev;
++ struct i3c_device *i3c;
++ int res;
++
++ if (dev->type == &i3c_masterdev_type || dev->driver)
++ return 0;
++
++ i3c = dev_to_i3cdev(dev);
++
++ /* Get a device */
++ i3cdev = get_free_i3cdev(i3c);
++ if (IS_ERR(i3cdev))
++ return PTR_ERR(i3cdev);
++
++ cdev_init(&i3cdev->cdev, &i3cdev_fops);
++ i3cdev->cdev.owner = THIS_MODULE;
++ res = cdev_add(&i3cdev->cdev,
++ MKDEV(MAJOR(i3cdev_number), i3cdev->id), 1);
++ if (res)
++ goto error_cdev;
++
++ /* register this i3c device with the driver core */
++ i3cdev->dev = device_create(i3cdev_class, &i3c->dev,
++ MKDEV(MAJOR(i3cdev_number), i3cdev->id),
++ NULL, "i3c-%s", dev_name(&i3c->dev));
++ if (IS_ERR(i3cdev->dev)) {
++ res = PTR_ERR(i3cdev->dev);
++ goto error;
++ }
++ pr_debug("i3cdev: I3C device [%s] registered as minor %d\n",
++ dev_name(&i3c->dev), i3cdev->id);
++ return 0;
++
++error:
++ cdev_del(&i3cdev->cdev);
++error_cdev:
++ put_i3cdev(i3cdev);
++ return res;
++}
++
++static int i3cdev_detach(struct device *dev, void *dummy)
++{
++ struct i3cdev_data *i3cdev;
++ struct i3c_device *i3c;
++
++ if (dev->type == &i3c_masterdev_type)
++ return 0;
++
++ i3c = dev_to_i3cdev(dev);
++
++ i3cdev = i3cdev_get_by_i3c(i3c);
++ if (!i3cdev)
++ return 0;
++
++ cdev_del(&i3cdev->cdev);
++ device_destroy(i3cdev_class, MKDEV(MAJOR(i3cdev_number), i3cdev->id));
++ ida_simple_remove(&i3cdev_ida, i3cdev->id);
++ put_i3cdev(i3cdev);
++
++ pr_debug("i3cdev: device [%s] unregistered\n", dev_name(&i3c->dev));
++
++ return 0;
++}
++
++static int i3cdev_notifier_call(struct notifier_block *nb,
++ unsigned long action,
++ void *data)
++{
++ struct device *dev = data;
++
++ switch (action) {
++ case BUS_NOTIFY_ADD_DEVICE:
++ case BUS_NOTIFY_UNBOUND_DRIVER:
++ return i3cdev_attach(dev, NULL);
++ case BUS_NOTIFY_DEL_DEVICE:
++ case BUS_NOTIFY_BOUND_DRIVER:
++ return i3cdev_detach(dev, NULL);
++ }
++
++ return 0;
++}
++
++static struct notifier_block i3c_notifier = {
++ .notifier_call = i3cdev_notifier_call,
++};
++
++static int __init i3cdev_init(void)
++{
++ int res;
++
++ /* Dynamically request unused major number */
++ res = alloc_chrdev_region(&i3cdev_number, 0, I3C_MINORS, "i3c");
++ if (res)
++ goto out;
++
++ /* Create a classe to populate sysfs entries*/
++ i3cdev_class = class_create(THIS_MODULE, "i3cdev");
++ if (IS_ERR(i3cdev_class)) {
++ res = PTR_ERR(i3cdev_class);
++ goto out_unreg_chrdev;
++ }
++
++ /* Keep track of busses which have devices to add or remove later */
++ res = bus_register_notifier(&i3c_bus_type, &i3c_notifier);
++ if (res)
++ goto out_unreg_class;
++
++ /* Bind to already existing device without driver right away */
++ i3c_for_each_dev(NULL, i3cdev_attach);
++
++ return 0;
++
++out_unreg_class:
++ class_destroy(i3cdev_class);
++out_unreg_chrdev:
++ unregister_chrdev_region(i3cdev_number, I3C_MINORS);
++out:
++ pr_err("%s: Driver Initialisation failed\n", __FILE__);
++ return res;
++}
++
++static void __exit i3cdev_exit(void)
++{
++ bus_unregister_notifier(&i3c_bus_type, &i3c_notifier);
++ i3c_for_each_dev(NULL, i3cdev_detach);
++ class_destroy(i3cdev_class);
++ unregister_chrdev_region(i3cdev_number, I3C_MINORS);
++}
++
++MODULE_AUTHOR("Vitor Soares <soares@synopsys.com>");
++MODULE_DESCRIPTION("I3C /dev entries driver");
++MODULE_LICENSE("GPL");
++
++module_init(i3cdev_init);
++module_exit(i3cdev_exit);
+diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
+index 86b7b44cfca2..a6deedf5ce06 100644
+--- a/drivers/i3c/internals.h
++++ b/drivers/i3c/internals.h
+@@ -11,6 +11,7 @@
+ #include <linux/i3c/master.h>
+
+ extern struct bus_type i3c_bus_type;
++extern const struct device_type i3c_masterdev_type;
+
+ void i3c_bus_normaluse_lock(struct i3c_bus *bus);
+ void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
+@@ -23,4 +24,5 @@ int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev);
+ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
+ const struct i3c_ibi_setup *req);
+ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev);
++int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *));
+ #endif /* I3C_INTERNAL_H */
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index 5c051dba32a5..53910fb6702e 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -321,6 +321,7 @@ struct bus_type i3c_bus_type = {
+ .probe = i3c_device_probe,
+ .remove = i3c_device_remove,
+ };
++EXPORT_SYMBOL_GPL(i3c_bus_type);
+
+ static enum i3c_addr_slot_status
+ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+@@ -523,11 +524,12 @@ static void i3c_masterdev_release(struct device *dev)
+ of_node_put(dev->of_node);
+ }
+
+-static const struct device_type i3c_masterdev_type = {
++const struct device_type i3c_masterdev_type = {
+ .groups = i3c_masterdev_groups,
+ };
++EXPORT_SYMBOL_GPL(i3c_masterdev_type);
+
+-int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
++static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
+ unsigned long max_i2c_scl_rate)
+ {
+ struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
+@@ -1410,19 +1412,19 @@ static void i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
+ master->ops->detach_i2c_dev(dev);
+ }
+
+-static void i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev)
++static int i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev)
+ {
+ struct i3c_master_controller *master = i3c_dev_get_master(dev);
+ int ret;
+
+ if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr ||
+ !dev->boardinfo->static_addr)
+- return;
++ return -1;
+
+ ret = i3c_master_setdasa_locked(master, dev->info.static_addr,
+ dev->boardinfo->init_dyn_addr);
+ if (ret)
+- return;
++ return ret;
+
+ dev->info.dyn_addr = dev->boardinfo->init_dyn_addr;
+ ret = i3c_master_reattach_i3c_dev(dev, 0);
+@@ -1433,10 +1435,11 @@ static void i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev)
+ if (ret)
+ goto err_rstdaa;
+
+- return;
++ return 0;
+
+ err_rstdaa:
+ i3c_master_rstdaa_locked(master, dev->boardinfo->init_dyn_addr);
++ return ret;
+ }
+
+ static void
+@@ -1631,7 +1634,7 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ enum i3c_addr_slot_status status;
+ struct i2c_dev_boardinfo *i2cboardinfo;
+ struct i3c_dev_boardinfo *i3cboardinfo;
+- struct i3c_dev_desc *i3cdev;
++ struct i3c_dev_desc *i3cdev, *i3ctmp;
+ struct i2c_dev_desc *i2cdev;
+ int ret;
+
+@@ -1730,8 +1733,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ * Pre-assign dynamic address and retrieve device information if
+ * needed.
+ */
+- i3c_bus_for_each_i3cdev(&master->bus, i3cdev)
+- i3c_master_pre_assign_dyn_addr(i3cdev);
++ list_for_each_entry_safe(i3cdev, i3ctmp, &master->bus.devs.i3c,
++ common.node) {
++ ret = i3c_master_pre_assign_dyn_addr(i3cdev);
++ if (ret) {
++ i3c_master_detach_i3c_dev(i3cdev);
++ i3c_master_free_i3c_dev(i3cdev);
++ }
++ }
+
+ ret = i3c_master_do_daa(master);
+ if (ret)
+@@ -2638,6 +2647,18 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
+ dev->ibi = NULL;
+ }
+
++int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *))
++{
++ int res;
++
++ mutex_lock(&i3c_core_lock);
++ res = bus_for_each_dev(&i3c_bus_type, NULL, data, fn);
++ mutex_unlock(&i3c_core_lock);
++
++ return res;
++}
++EXPORT_SYMBOL_GPL(i3c_for_each_dev);
++
+ static int __init i3c_init(void)
+ {
+ return bus_register(&i3c_bus_type);
+diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
+index 4e80a1fcbf91..693f9aba2b17 100644
+--- a/drivers/i3c/master/Kconfig
++++ b/drivers/i3c/master/Kconfig
+@@ -21,3 +21,8 @@ config DW_I3C_MASTER
+
+ This driver can also be built as a module. If so, the module
+ will be called dw-i3c-master.
++
++config ASPEED_I3C_GLOBAL
++ tristate "ASPEED I3C global driver"
++ depends on I3C
++ depends on MACH_ASPEED_G6
+diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
+index 7eea9e086144..09057d1432cc 100644
+--- a/drivers/i3c/master/Makefile
++++ b/drivers/i3c/master/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_CDNS_I3C_MASTER) += i3c-master-cdns.o
+ obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o
++obj-$(CONFIG_ASPEED_I3C_GLOBAL) += aspeed-i3c-global.o
+diff --git a/drivers/i3c/master/aspeed-i3c-global.c b/drivers/i3c/master/aspeed-i3c-global.c
+new file mode 100644
+index 000000000000..9c3e58794a3e
+--- /dev/null
++++ b/drivers/i3c/master/aspeed-i3c-global.c
+@@ -0,0 +1,89 @@
++/*
++ * Aspeed I2C Interrupt Controller.
++ *
++ * Copyright (C) 2012-2017 ASPEED Technology Inc.
++ * Copyright 2017 IBM Corporation
++ * Copyright 2017 Google, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/irqchip.h>
++#include <linux/irqchip/chained_irq.h>
++#include <linux/irqdomain.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/io.h>
++#include <linux/reset.h>
++#include <linux/delay.h>
++
++#define ASPEED_I3CG_CTRL(x) (0x10 + (x*0x10))
++#define ASPEED_I3CG_SET(x) (0x14 + (x*0x10))
++
++struct aspeed_i3c_global {
++ void __iomem *base;
++ struct reset_control *rst;
++};
++
++static const struct of_device_id aspeed_i3c_of_match[] = {
++ { .compatible = "aspeed,ast2600-i3c-global", },
++ {},
++};
++
++static int aspeed_i3c_global_probe(struct platform_device *pdev)
++{
++ struct aspeed_i3c_global *i3c_global;
++ struct device_node *node = pdev->dev.of_node;
++ int i = 0;
++
++ i3c_global = kzalloc(sizeof(*i3c_global), GFP_KERNEL);
++ if (!i3c_global)
++ return -ENOMEM;
++
++ i3c_global->base = of_iomap(node, 0);
++ if (!i3c_global->base) {
++ return -ENOMEM;
++ }
++
++ i3c_global->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
++
++ if (IS_ERR(i3c_global->rst)) {
++ dev_err(&pdev->dev,
++ "missing or invalid reset controller device tree entry");
++ return PTR_ERR(i3c_global->rst);
++ }
++
++ reset_control_assert(i3c_global->rst);
++ udelay(3);
++ reset_control_deassert(i3c_global->rst);
++
++ /* init */
++ for(i = 0; i < 5; i++)
++ writel(0x000474c4, i3c_global->base + ASPEED_I3CG_SET(i));
++
++ return 0;
++}
++
++static struct platform_driver aspeed_i3c_driver = {
++ .probe = aspeed_i3c_global_probe,
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = aspeed_i3c_of_match,
++ },
++};
++
++static int __init aspeed_i3c_global_init(void)
++{
++ return platform_driver_register(&aspeed_i3c_driver);
++}
++postcore_initcall(aspeed_i3c_global_init);
++
++MODULE_AUTHOR("Ryan Chen");
++MODULE_DESCRIPTION("ASPEED I3C Global Driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
+index 26f84584a821..6cc47373cc97 100644
+--- a/include/dt-bindings/clock/ast2600-clock.h
++++ b/include/dt-bindings/clock/ast2600-clock.h
+@@ -88,7 +88,8 @@
+ #define ASPEED_CLK_MAC3RCLK 69
+ #define ASPEED_CLK_MAC4RCLK 70
+ #define ASPEED_CLK_UART5 71
+-#define ASPEED_CLK_MAX 72
++#define ASPEED_CLK_I3C 72
++#define ASPEED_CLK_MAX 73
+
+ /* Only list resets here that are not part of a gate */
+ #define ASPEED_RESET_ADC 55
+diff --git a/include/uapi/linux/i3c/i3cdev.h b/include/uapi/linux/i3c/i3cdev.h
+new file mode 100644
+index 000000000000..0897313f5516
+--- /dev/null
++++ b/include/uapi/linux/i3c/i3cdev.h
+@@ -0,0 +1,38 @@
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++/*
++ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
++ *
++ * Author: Vitor Soares <vitor.soares@synopsys.com>
++ */
++
++#ifndef _UAPI_I3C_DEV_H_
++#define _UAPI_I3C_DEV_H_
++
++#include <linux/types.h>
++#include <linux/ioctl.h>
++
++/* IOCTL commands */
++#define I3C_DEV_IOC_MAGIC 0x07
++
++/**
++ * struct i3c_ioc_priv_xfer - I3C SDR ioctl private transfer
++ * @data: Holds pointer to userspace buffer with transmit data.
++ * @len: Length of data buffer buffers, in bytes.
++ * @rnw: encodes the transfer direction. true for a read, false for a write
++ */
++struct i3c_ioc_priv_xfer {
++ __u64 data;
++ __u16 len;
++ __u8 rnw;
++ __u8 pad[5];
++};
++
++
++#define I3C_PRIV_XFER_SIZE(N) \
++ ((((sizeof(struct i3c_ioc_priv_xfer)) * (N)) < (1 << _IOC_SIZEBITS)) \
++ ? ((sizeof(struct i3c_ioc_priv_xfer)) * (N)) : 0)
++
++#define I3C_IOC_PRIV_XFER(N) \
++ _IOC(_IOC_READ|_IOC_WRITE, I3C_DEV_IOC_MAGIC, 30, I3C_PRIV_XFER_SIZE(N))
++
++#endif
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch
new file mode 100644
index 000000000..fc72c7537
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch
@@ -0,0 +1,79 @@
+From 7f4dc6aee65d9badf841099806ae6b85a86320ce Mon Sep 17 00:00:00 2001
+From: Iwona Winiarska <iwona.winiarska@intel.com>
+Date: Thu, 27 Feb 2020 00:53:38 +0100
+Subject: [PATCH 107/108] arm: dts: aspeed-g6: Add ast2600-mctp node
+
+AST2600 provides MCTP over PCIe controller allowing BMC to communicate
+with devices on host PCIe bus.
+
+We are also adding syscon node describing PCIe Host controller device
+which can be used to gather information on PCIe enumeration (and
+assigned address).
+
+Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
+---
+ .../bindings/soc/aspeed/aspeed-mctp.txt | 25 +++++++++++++++++++
+ arch/arm/boot/dts/aspeed-g6.dtsi | 15 +++++++++++
+ 2 files changed, 40 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt
+
+diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt
+new file mode 100644
+index 000000000000..5dc30fdfc53a
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt
+@@ -0,0 +1,25 @@
++* Aspeed AST2600 MCTP PCIe VDM Controller
++
++Required properties:
++- compatible : must be "aspeed,ast2600-mctp"
++- reg : contains the address and size of the memory region
++ associated with the MCTP controller
++- resets : reset specifier for the syscon reset associated with
++ the MCTP controller
++- interrupts-extended : two interrupt cells; the first specifies the global
++ interrupt for MCTP controller and the second
++ specifies the PCIe reset or PERST interrupt
++- aspeed,pcieh : a phandle to the PCIe Host Controller node to be
++ used in conjunction with the PCIe reset or PERST
++ interrupt
++Example:
++
++mctp: mctp@1e6e8000 {
++ compatible = "aspeed,ast2600-mctp";
++ reg = <0x1e6e8000 0x1000>;
++ interrupts-extended = <&gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
++ <&scu_ic0 ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>;
++ resets = <&syscon ASPEED_RESET_DEV_MCTP>;
++ aspeed,pcieh = <&pcieh>;
++ status = "disabled";
++};
+diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
+index 33e1b0ef24f0..90a060db20c7 100644
+--- a/arch/arm/boot/dts/aspeed-g6.dtsi
++++ b/arch/arm/boot/dts/aspeed-g6.dtsi
+@@ -407,6 +407,21 @@
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
++ pcieh: pcieh@1e6ed000 {
++ compatible = "aspeed,ast2600-pcieh", "syscon";
++ reg = <0x1e6ed000 0x100>;
++ };
++
++ mctp: mctp@1e6e8000 {
++ compatible = "aspeed,ast2600-mctp";
++ reg = <0x1e6e8000 0x1000>;
++ interrupts-extended = <&gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
++ <&scu_ic0 ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>;
++ resets = <&syscon ASPEED_RESET_DEV_MCTP>;
++ aspeed,pcieh = <&pcieh>;
++ status = "disabled";
++ };
++
+ adc0: adc@1e6e9000 {
+ compatible = "aspeed,ast2600-adc";
+ reg = <0x1e6e9000 0x100>;
+--
+2.21.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch
new file mode 100644
index 000000000..bff271bfe
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch
@@ -0,0 +1,1265 @@
+From cafc578414a664ecde96598838a3907a5d915416 Mon Sep 17 00:00:00 2001
+From: Iwona Winiarska <iwona.winiarska@intel.com>
+Date: Mon, 6 Apr 2020 22:00:46 +0200
+Subject: [PATCH 108/108] soc: aspeed: mctp: Add initial driver for
+ ast2600-mctp
+
+Currently, there is no proper MCTP networking subsystem in Linux.
+Until we are able to work out the details of that, we are going to
+expose HW to userspace using raw read/write interface.
+Because of that, this driver is not intended to be submitted upstream.
+
+Here we are providing a simple device driver for AST2600 MCTP
+controller.
+
+Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
+---
+ drivers/soc/aspeed/Kconfig | 8 +
+ drivers/soc/aspeed/Makefile | 1 +
+ drivers/soc/aspeed/aspeed-mctp.c | 1126 ++++++++++++++++++++++++++++++
+ include/uapi/linux/aspeed-mctp.h | 72 ++
+ 4 files changed, 1207 insertions(+)
+ create mode 100644 drivers/soc/aspeed/aspeed-mctp.c
+ create mode 100644 include/uapi/linux/aspeed-mctp.h
+
+diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
+index 13cd9fbabbf1..78d9140d822b 100644
+--- a/drivers/soc/aspeed/Kconfig
++++ b/drivers/soc/aspeed/Kconfig
+@@ -43,6 +43,14 @@ config ASPEED_LPC_SNOOP
+ allows the BMC to listen on and save the data written by
+ the host to an arbitrary LPC I/O port.
+
++config ASPEED_MCTP
++ tristate "Aspeed ast2600 MCTP Controller support"
++ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
++ help
++ Enable support for ast2600 MCTP Controller.
++ The MCTP controller allows the BMC to communicate with devices on
++ the host PCIe network.
++
+ config ASPEED_P2A_CTRL
+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+ tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control"
+diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
+index 875f0d9e7866..b3c143f9e24c 100644
+--- a/drivers/soc/aspeed/Makefile
++++ b/drivers/soc/aspeed/Makefile
+@@ -7,3 +7,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
+ obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o
+ obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o
++obj-$(CONFIG_ASPEED_MCTP) += aspeed-mctp.o
+diff --git a/drivers/soc/aspeed/aspeed-mctp.c b/drivers/soc/aspeed/aspeed-mctp.c
+new file mode 100644
+index 000000000000..addf96133abf
+--- /dev/null
++++ b/drivers/soc/aspeed/aspeed-mctp.c
+@@ -0,0 +1,1126 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2020, Intel Corporation.
++
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/mfd/syscon.h>
++#include <linux/miscdevice.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/pci.h>
++#include <linux/poll.h>
++#include <linux/ptr_ring.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++#include <linux/workqueue.h>
++#include <uapi/linux/aspeed-mctp.h>
++
++/* AST2600 MCTP Controller registers */
++#define ASPEED_MCTP_CTRL 0x000
++#define TX_CMD_TRIGGER BIT(0)
++#define RX_CMD_READY BIT(4)
++#define MATCHING_EID BIT(9)
++
++#define ASPEED_MCTP_TX_CMD 0x004
++#define ASPEED_MCTP_RX_CMD 0x008
++
++#define ASPEED_MCTP_INT_STS 0x00c
++#define ASPEED_MCTP_INT_EN 0x010
++#define TX_CMD_SENT_INT BIT(0)
++#define TX_CMD_LAST_INT BIT(1)
++#define TX_CMD_WRONG_INT BIT(2)
++#define RX_CMD_RECEIVE_INT BIT(8)
++#define RX_CMD_NO_MORE_INT BIT(9)
++
++#define ASPEED_MCTP_EID 0x014
++#define ASPEED_MCTP_OBFF_CTRL 0x018
++
++#define ASPEED_MCTP_ENGINE_CTRL 0x01c
++#define TX_MAX_PAYLOAD_SIZE_SHIFT 0
++#define TX_MAX_PAYLOAD_SIZE_MASK GENMASK(1, TX_MAX_PAYLOAD_SIZE_SHIFT)
++#define TX_MAX_PAYLOAD_SIZE(x) \
++ (((x) << TX_MAX_PAYLOAD_SIZE_SHIFT) & TX_MAX_PAYLOAD_SIZE_MASK)
++#define RX_MAX_PAYLOAD_SIZE_SHIFT 4
++#define RX_MAX_PAYLOAD_SIZE_MASK GENMASK(5, RX_MAX_PAYLOAD_SIZE_SHIFT)
++#define RX_MAX_PAYLOAD_SIZE(x) \
++ (((x) << RX_MAX_PAYLOAD_SIZE_SHIFT) & RX_MAX_PAYLOAD_SIZE_MASK)
++#define FIFO_LAYOUT_SHIFT 8
++#define FIFO_LAYOUT_MASK GENMASK(9, FIFO_LAYOUT_SHIFT)
++#define FIFO_LAYOUT(x) \
++ (((x) << FIFO_LAYOUT_SHIFT) & FIFO_LAYOUT_MASK)
++
++#define ASPEED_MCTP_RX_BUF_ADDR 0x020
++#define ASPEED_MCTP_RX_BUF_SIZE 0x024
++#define ASPEED_MCTP_RX_BUF_RD_PTR 0x028
++#define UPDATE_RX_RD_PTR BIT(31)
++#define RX_BUFFER_RD_PTR GENMASK(11, 0)
++#define ASPEED_MCTP_RX_BUF_WR_PTR 0x02c
++#define RX_BUFFER_WR_PTR GENMASK(11, 0)
++
++#define ASPEED_MCTP_TX_BUF_ADDR 0x004
++#define ASPEED_MCTP_TX_BUF_SIZE 0x034
++#define ASPEED_MCTP_TX_BUF_RD_PTR 0x038
++#define UPDATE_TX_RD_PTR BIT(31)
++#define TX_BUFFER_RD_PTR GENMASK(11, 0)
++#define ASPEED_MCTP_TX_BUF_WR_PTR 0x03c
++#define TX_BUFFER_WR_PTR GENMASK(11, 0)
++
++#define ADDR_LEN (BIT(26) - 1)
++#define DATA_ADDR(x) (((x) >> 4) & ADDR_LEN)
++
++/* TX command */
++#define TX_LAST_CMD BIT(31)
++#define TX_DATA_ADDR_SHIFT 4
++#define TX_DATA_ADDR_MASK GENMASK(30, TX_DATA_ADDR_SHIFT)
++#define TX_DATA_ADDR(x) \
++ ((DATA_ADDR(x) << TX_DATA_ADDR_SHIFT) & TX_DATA_ADDR_MASK)
++#define TX_RESERVED_1_MASK GENMASK(1, 0) /* must be 1 */
++#define TX_RESERVED_1 1
++#define TX_STOP_AFTER_CMD BIT(16)
++#define TX_INTERRUPT_AFTER_CMD BIT(15)
++#define TX_PACKET_SIZE_SHIFT 2
++#define TX_PACKET_SIZE_MASK GENMASK(12, TX_PACKET_SIZE_SHIFT)
++#define TX_PACKET_SIZE(x) \
++ (((x) << TX_PACKET_SIZE_SHIFT) & TX_PACKET_SIZE_MASK)
++#define TX_RESERVED_0_MASK GENMASK(1, 0) /* MBZ */
++#define TX_RESERVED_0 0
++
++/* RX command */
++#define RX_INTERRUPT_AFTER_CMD BIT(2)
++#define RX_DATA_ADDR_SHIFT 4
++#define RX_DATA_ADDR_MASK GENMASK(30, RX_DATA_ADDR_SHIFT)
++#define RX_DATA_ADDR(x) \
++ ((DATA_ADDR(x) << RX_DATA_ADDR_SHIFT) & RX_DATA_ADDR_MASK)
++
++/* Buffer sizes */
++#define TX_CMD_COUNT 4
++#define RX_CMD_COUNT 4
++#define TX_MAX_CMD_COUNT SZ_4K
++#define RX_MAX_CMD_COUNT SZ_4K
++
++/* PCIe Host Controller registers */
++#define ASPEED_PCIE_MISC_STS_1 0x0c4
++
++/* PCI address definitions */
++#define PCI_DEV_NUM_MASK GENMASK(4, 0)
++#define PCI_BUS_NUM_SHIFT 5
++#define PCI_BUS_NUM_MASK GENMASK(12, PCI_BUS_NUM_SHIFT)
++#define GET_PCI_DEV_NUM(x) ((x) & PCI_DEV_NUM_MASK)
++#define GET_PCI_BUS_NUM(x) (((x) & PCI_BUS_NUM_MASK) >> PCI_BUS_NUM_SHIFT)
++
++/* FIXME: ast2600 supports variable max transmission unit */
++#define ASPEED_MCTP_MTU 64
++
++struct mctp_pcie_packet {
++ struct {
++ u32 hdr[4];
++ u32 payload[16];
++ } data;
++ u32 size;
++};
++
++struct aspeed_mctp_tx_cmd {
++ u32 tx_lo;
++ u32 tx_hi;
++};
++
++struct mctp_buffer {
++ void *vaddr;
++ dma_addr_t dma_handle;
++};
++
++struct mctp_channel {
++ struct mctp_buffer data;
++ struct mctp_buffer cmd;
++ struct tasklet_struct tasklet;
++ u32 rd_ptr;
++ u32 wr_ptr;
++};
++
++struct aspeed_mctp {
++ struct device *dev;
++ struct regmap *map;
++ struct reset_control *reset;
++ struct mctp_channel tx;
++ struct mctp_channel rx;
++ struct list_head clients;
++ spinlock_t clients_lock; /* to protect clients list operations */
++ wait_queue_head_t wait_queue;
++ struct {
++ struct regmap *map;
++ struct delayed_work rst_dwork;
++ bool need_uevent;
++ u16 bdf;
++ } pcie;
++};
++
++struct mctp_client {
++ struct kref ref;
++ struct aspeed_mctp *priv;
++ struct ptr_ring tx_queue;
++ struct ptr_ring rx_queue;
++ struct list_head link;
++ bool disconnected;
++};
++
++#define TX_CMD_BUF_SIZE \
++ PAGE_ALIGN(TX_CMD_COUNT * sizeof(struct aspeed_mctp_tx_cmd))
++#define TX_DATA_BUF_SIZE \
++ PAGE_ALIGN(TX_CMD_COUNT * sizeof(struct mctp_pcie_packet))
++#define RX_CMD_BUF_SIZE PAGE_ALIGN(RX_CMD_COUNT * sizeof(u32))
++#define RX_DATA_BUF_SIZE \
++ PAGE_ALIGN(RX_CMD_COUNT * sizeof(struct mctp_pcie_packet))
++
++struct kmem_cache *packet_cache;
++
++static void *packet_alloc(gfp_t flags)
++{
++ return kmem_cache_alloc(packet_cache, flags);
++}
++
++static void packet_free(void *packet)
++{
++ kmem_cache_free(packet_cache, packet);
++}
++
++static void aspeed_mctp_rx_trigger(struct mctp_channel *rx)
++{
++ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx);
++
++ /*
++ * Even though rx_buf_addr doesn't change, if we don't do the write
++ * here, the HW doesn't trigger RX.
++ * Also, note that we're writing 0 as wr_ptr. If we're writing other
++ * value, the HW behaves in a bizzare way that's hard to explain...
++ */
++ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_ADDR, rx->cmd.dma_handle);
++ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_WR_PTR, 0);
++ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, RX_CMD_READY,
++ RX_CMD_READY);
++}
++
++static void aspeed_mctp_tx_trigger(struct mctp_channel *tx)
++{
++ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx);
++
++ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_ADDR,
++ tx->cmd.dma_handle);
++ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_WR_PTR, tx->wr_ptr);
++ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, TX_CMD_TRIGGER,
++ TX_CMD_TRIGGER);
++}
++
++static void aspeed_mctp_emit_tx_cmd(struct mctp_channel *tx,
++ struct mctp_pcie_packet *packet, bool last)
++{
++ struct aspeed_mctp_tx_cmd *tx_cmd =
++ (struct aspeed_mctp_tx_cmd *)tx->cmd.vaddr + tx->wr_ptr;
++ u32 packet_sz_dw = packet->size / sizeof(u32) -
++ sizeof(packet->data.hdr) / sizeof(u32);
++ u32 offset = tx->wr_ptr * sizeof(packet->data);
++
++ memcpy(tx->data.vaddr + offset, &packet->data,
++ sizeof(packet->data));
++
++ tx_cmd->tx_lo |= TX_PACKET_SIZE(packet_sz_dw);
++ tx_cmd->tx_lo |= TX_STOP_AFTER_CMD;
++ tx_cmd->tx_lo |= TX_INTERRUPT_AFTER_CMD;
++ tx_cmd->tx_hi |= TX_RESERVED_1;
++ tx_cmd->tx_hi |= TX_DATA_ADDR(tx->data.dma_handle + offset);
++ if (last)
++ tx_cmd->tx_hi |= TX_LAST_CMD;
++
++ tx->wr_ptr++;
++}
++
++static struct mctp_client *aspeed_mctp_client_alloc(struct aspeed_mctp *priv)
++{
++ struct mctp_client *client;
++
++ client = kzalloc(sizeof(*client), GFP_KERNEL);
++ if (!client)
++ goto out;
++
++ kref_init(&client->ref);
++ client->priv = priv;
++ ptr_ring_init(&client->tx_queue, TX_CMD_COUNT, GFP_KERNEL);
++ ptr_ring_init(&client->rx_queue, RX_CMD_COUNT, GFP_ATOMIC);
++
++out:
++ return client;
++}
++
++static void aspeed_mctp_client_free(struct kref *ref)
++{
++ struct mctp_client *client = container_of(ref, typeof(*client), ref);
++
++ ptr_ring_cleanup(&client->rx_queue, &packet_free);
++ ptr_ring_cleanup(&client->tx_queue, &packet_free);
++
++ kfree(client);
++}
++
++static void aspeed_mctp_client_get(struct mctp_client *client)
++{
++ lockdep_assert_held(&client->priv->clients_lock);
++
++ kref_get(&client->ref);
++}
++
++static void aspeed_mctp_client_put(struct mctp_client *client)
++{
++ kref_put(&client->ref, &aspeed_mctp_client_free);
++}
++
++static void aspeed_mctp_tx_tasklet(unsigned long data)
++{
++ struct mctp_channel *tx = (struct mctp_channel *)data;
++ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx);
++ u32 rd_ptr = READ_ONCE(tx->rd_ptr);
++ struct mctp_pcie_packet *packet;
++ struct mctp_client *client;
++ bool last, trigger = false;
++
++ /* we're called while there's still TX in progress */
++ if (rd_ptr == 0 && tx->wr_ptr != 0)
++ return;
++
++ spin_lock(&priv->clients_lock);
++ client = list_first_entry_or_null(&priv->clients, typeof(*client),
++ link);
++ if (!client) {
++ spin_unlock(&priv->clients_lock);
++ return;
++ }
++ aspeed_mctp_client_get(client);
++ spin_unlock(&priv->clients_lock);
++
++ /* last tx ended up with buffer size, meaning we now restart from 0 */
++ if (rd_ptr == TX_CMD_COUNT) {
++ WRITE_ONCE(tx->rd_ptr, 0);
++ tx->wr_ptr = 0;
++ }
++
++ while (tx->wr_ptr < TX_CMD_COUNT) {
++ packet = ptr_ring_consume(&client->tx_queue);
++ if (!packet)
++ break;
++
++ last = !__ptr_ring_peek(&client->tx_queue);
++
++ aspeed_mctp_emit_tx_cmd(tx, packet, last);
++ packet_free(packet);
++
++ trigger = true;
++
++ if (last)
++ break;
++ }
++
++ aspeed_mctp_client_put(client);
++
++ if (trigger)
++ aspeed_mctp_tx_trigger(tx);
++}
++
++static void aspeed_mctp_rx_tasklet(unsigned long data)
++{
++ struct mctp_channel *rx = (struct mctp_channel *)data;
++ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx);
++ u32 rd_ptr = READ_ONCE(priv->rx.rd_ptr);
++ struct mctp_pcie_packet *rx_packet;
++ struct mctp_client *client;
++ int ret;
++
++ spin_lock(&priv->clients_lock);
++ client = list_first_entry_or_null(&priv->clients, typeof(*client),
++ link);
++ if (!client) {
++ rx->wr_ptr = rd_ptr;
++ spin_unlock(&priv->clients_lock);
++ goto out_skip;
++ }
++ aspeed_mctp_client_get(client);
++ spin_unlock(&priv->clients_lock);
++
++ while (rx->wr_ptr < rd_ptr) {
++ rx_packet = packet_alloc(GFP_ATOMIC);
++ if (!rx_packet) {
++ dev_err(priv->dev, "Failed to allocate RX packet\n");
++ goto out_put;
++ }
++
++ memcpy(&rx_packet->data,
++ rx->data.vaddr + rx->wr_ptr * sizeof(rx_packet->data),
++ sizeof(rx_packet->data));
++ rx->wr_ptr++;
++
++ ret = ptr_ring_produce(&client->rx_queue, rx_packet);
++ if (ret) {
++ dev_warn(priv->dev, "Failed to produce RX packet: %d\n",
++ ret);
++ packet_free(rx_packet);
++ continue;
++ }
++ }
++out_skip:
++ if (rx->wr_ptr == RX_CMD_COUNT || (rx->wr_ptr == 0 && rd_ptr == 0)) {
++ rx->wr_ptr = 0;
++ if (client)
++ aspeed_mctp_rx_trigger(rx);
++ else
++ WRITE_ONCE(rx->rd_ptr, 0);
++ }
++ wake_up_all(&priv->wait_queue);
++
++out_put:
++ if (client)
++ aspeed_mctp_client_put(client);
++}
++
++static void aspeed_mctp_rx_chan_init(struct mctp_channel *rx)
++{
++ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx);
++ u32 *rx_cmd = (u32 *)rx->cmd.vaddr;
++ u32 rx_data_addr = rx->data.dma_handle;
++ struct mctp_pcie_packet packet;
++ u32 data_size = sizeof(packet.data);
++ u32 i;
++
++ for (i = 0; i < RX_CMD_COUNT; i++) {
++ *rx_cmd |= RX_DATA_ADDR(rx_data_addr);
++ *rx_cmd |= RX_INTERRUPT_AFTER_CMD;
++ rx_data_addr += data_size;
++ rx_cmd++;
++ }
++ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_SIZE, RX_CMD_COUNT);
++}
++
++static void aspeed_mctp_tx_chan_init(struct mctp_channel *tx)
++{
++ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx);
++
++ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_SIZE, TX_CMD_COUNT);
++ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_WR_PTR, 0);
++}
++
++static int aspeed_mctp_open(struct inode *inode, struct file *file)
++{
++ struct miscdevice *misc = file->private_data;
++ struct platform_device *pdev = to_platform_device(misc->parent);
++ struct aspeed_mctp *priv = platform_get_drvdata(pdev);
++ struct mctp_client *client;
++ int ret;
++
++ if (priv->pcie.bdf == 0) {
++ ret = -ENODEV;
++ goto out;
++ }
++
++ client = aspeed_mctp_client_alloc(priv);
++ if (!client) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ spin_lock_bh(&priv->clients_lock);
++ /* TODO: Add support for multiple clients */
++ if (!list_empty(&priv->clients)) {
++ ret = -EBUSY;
++ goto out_unlock;
++ }
++ list_add_tail(&client->link, &priv->clients);
++ spin_unlock_bh(&priv->clients_lock);
++
++ /*
++ * kick the tasklet to trigger rx
++ * bh_disable/enable is just to make sure that the tasklet gets
++ * scheduled immediately in process context without any unnecessary
++ * delay
++ */
++ local_bh_disable();
++ tasklet_hi_schedule(&priv->rx.tasklet);
++ local_bh_enable();
++
++ file->private_data = client;
++
++ return 0;
++out_unlock:
++ spin_unlock_bh(&priv->clients_lock);
++ aspeed_mctp_client_put(client);
++out:
++ return ret;
++}
++
++static int aspeed_mctp_release(struct inode *inode, struct file *file)
++{
++ struct mctp_client *client = file->private_data;
++ struct aspeed_mctp *priv = client->priv;
++
++ spin_lock_bh(&priv->clients_lock);
++ list_del(&client->link);
++ spin_unlock_bh(&priv->clients_lock);
++
++ /* Disable the tasklet to appease lockdep */
++ local_bh_disable();
++ aspeed_mctp_client_put(client);
++ local_bh_enable();
++
++ return 0;
++}
++
++static ssize_t aspeed_mctp_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct mctp_client *client = file->private_data;
++ struct aspeed_mctp *priv = client->priv;
++ struct mctp_pcie_packet *rx_packet;
++ size_t packet_sz = sizeof(rx_packet->data);
++
++ if (READ_ONCE(client->disconnected))
++ return -EIO;
++
++ if (buf && count > 0) {
++ if (count > packet_sz)
++ count = packet_sz;
++
++ rx_packet = ptr_ring_consume_bh(&client->rx_queue);
++ if (!rx_packet)
++ return -EAGAIN;
++
++ if (copy_to_user(buf, &rx_packet->data, count)) {
++ dev_err(priv->dev, "copy to user failed\n");
++ packet_free(rx_packet);
++ return -EFAULT;
++ }
++
++ packet_free(rx_packet);
++ }
++
++ return count;
++}
++
++static ssize_t aspeed_mctp_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ struct mctp_client *client = file->private_data;
++ struct aspeed_mctp *priv = client->priv;
++ struct mctp_pcie_packet *tx_packet;
++ int ret;
++
++ if (READ_ONCE(client->disconnected))
++ return -EIO;
++
++ tx_packet = packet_alloc(GFP_KERNEL);
++ if (!tx_packet) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ if (buf && count > 0) {
++ if (count > sizeof(tx_packet->data)) {
++ ret = -ENOSPC;
++ goto out_packet;
++ }
++
++ if (copy_from_user(&tx_packet->data, buf, count)) {
++ dev_err(priv->dev, "copy from user failed\n");
++ ret = -EFAULT;
++ goto out_packet;
++ }
++ tx_packet->size = count;
++
++ ret = ptr_ring_produce_bh(&client->tx_queue, tx_packet);
++ if (ret)
++ goto out_packet;
++
++ tasklet_hi_schedule(&priv->tx.tasklet);
++ }
++
++ return count;
++
++out_packet:
++ packet_free(tx_packet);
++out:
++ return ret;
++}
++
++static int
++aspeed_mctp_filter_eid(struct aspeed_mctp *priv, void __user *userbuf)
++{
++ struct aspeed_mctp_filter_eid eid;
++
++ if (copy_from_user(&eid, userbuf, sizeof(eid))) {
++ dev_err(priv->dev, "copy from user failed\n");
++ return -EFAULT;
++ }
++
++ if (eid.enable) {
++ regmap_write(priv->map, ASPEED_MCTP_EID, eid.eid);
++ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL,
++ MATCHING_EID, MATCHING_EID);
++ } else {
++ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL,
++ MATCHING_EID, 0);
++ }
++ return 0;
++}
++
++static int aspeed_mctp_get_bdf(struct aspeed_mctp *priv, void __user *userbuf)
++{
++ struct aspeed_mctp_get_bdf bdf = { priv->pcie.bdf };
++
++ if (copy_to_user(userbuf, &bdf, sizeof(bdf))) {
++ dev_err(priv->dev, "copy to user failed\n");
++ return -EFAULT;
++ }
++ return 0;
++}
++
++static int
++aspeed_mctp_get_medium_id(struct aspeed_mctp *priv, void __user *userbuf)
++{
++ struct aspeed_mctp_get_medium_id id = { 0x09 }; /* PCIe revision 2.0 */
++
++ if (copy_to_user(userbuf, &id, sizeof(id))) {
++ dev_err(priv->dev, "copy to user failed\n");
++ return -EFAULT;
++ }
++ return 0;
++}
++
++static int
++aspeed_mctp_get_mtu(struct aspeed_mctp *priv, void __user *userbuf)
++{
++ struct aspeed_mctp_get_mtu id = { ASPEED_MCTP_MTU };
++
++ if (copy_to_user(userbuf, &id, sizeof(id))) {
++ dev_err(priv->dev, "copy to user failed\n");
++ return -EFAULT;
++ }
++ return 0;
++}
++
++static long
++aspeed_mctp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct mctp_client *client = file->private_data;
++ struct aspeed_mctp *priv = client->priv;
++ void __user *userbuf = (void __user *)arg;
++ int ret;
++
++ switch (cmd) {
++ case ASPEED_MCTP_IOCTL_FILTER_EID:
++ ret = aspeed_mctp_filter_eid(priv, userbuf);
++ break;
++
++ case ASPEED_MCTP_IOCTL_GET_BDF:
++ ret = aspeed_mctp_get_bdf(priv, userbuf);
++ break;
++
++ case ASPEED_MCTP_IOCTL_GET_MEDIUM_ID:
++ ret = aspeed_mctp_get_medium_id(priv, userbuf);
++ break;
++
++ case ASPEED_MCTP_IOCTL_GET_MTU:
++ ret = aspeed_mctp_get_mtu(priv, userbuf);
++ break;
++
++ default:
++ dev_err(priv->dev, "Command not found\n");
++ ret = -EINVAL;
++ }
++
++ return ret;
++}
++
++static __poll_t aspeed_mctp_poll(struct file *file,
++ struct poll_table_struct *pt)
++{
++ struct mctp_client *client = file->private_data;
++ struct aspeed_mctp *priv = client->priv;
++ __poll_t ret = 0;
++
++ poll_wait(file, &priv->wait_queue, pt);
++
++ if (!ptr_ring_full_bh(&client->tx_queue))
++ ret |= EPOLLOUT;
++
++ if (__ptr_ring_peek(&client->rx_queue))
++ ret |= EPOLLIN;
++
++ return ret;
++}
++
++static const struct file_operations aspeed_mctp_fops = {
++ .owner = THIS_MODULE,
++ .open = aspeed_mctp_open,
++ .release = aspeed_mctp_release,
++ .read = aspeed_mctp_read,
++ .write = aspeed_mctp_write,
++ .unlocked_ioctl = aspeed_mctp_ioctl,
++ .poll = aspeed_mctp_poll,
++};
++
++static const struct regmap_config aspeed_mctp_regmap_cfg = {
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .max_register = ASPEED_MCTP_TX_BUF_WR_PTR,
++};
++
++struct device_type aspeed_mctp_type = {
++ .name = "aspeed-mctp",
++};
++
++static struct miscdevice aspeed_mctp_miscdev = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = "aspeed-mctp",
++ .fops = &aspeed_mctp_fops,
++};
++
++static void aspeed_mctp_send_pcie_uevent(struct kobject *kobj, bool ready)
++{
++ char *pcie_not_ready_event[] = { ASPEED_MCTP_READY "=0", NULL };
++ char *pcie_ready_event[] = { ASPEED_MCTP_READY "=1", NULL };
++
++ kobject_uevent_env(kobj, KOBJ_CHANGE,
++ ready ? pcie_ready_event : pcie_not_ready_event);
++}
++
++static void aspeed_mctp_pcie_setup(struct aspeed_mctp *priv)
++{
++ u32 reg;
++
++ regmap_read(priv->pcie.map, ASPEED_PCIE_MISC_STS_1, &reg);
++
++ priv->pcie.bdf = PCI_DEVID(GET_PCI_BUS_NUM(reg), GET_PCI_DEV_NUM(reg));
++ if (priv->pcie.bdf != 0)
++ cancel_delayed_work(&priv->pcie.rst_dwork);
++ else
++ schedule_delayed_work(&priv->pcie.rst_dwork,
++ msecs_to_jiffies(1000));
++}
++
++static void aspeed_mctp_irq_enable(struct aspeed_mctp *priv)
++{
++ u32 enable = TX_CMD_LAST_INT | TX_CMD_WRONG_INT |
++ RX_CMD_RECEIVE_INT;
++
++ regmap_write(priv->map, ASPEED_MCTP_INT_EN, enable);
++}
++
++static void aspeed_mctp_irq_disable(struct aspeed_mctp *priv)
++{
++ regmap_write(priv->map, ASPEED_MCTP_INT_EN, 0);
++}
++
++static void aspeed_mctp_reset_work(struct work_struct *work)
++{
++ struct aspeed_mctp *priv = container_of(work, typeof(*priv),
++ pcie.rst_dwork.work);
++
++ /*
++ * Client "disconnection" is permanent to avoid forcing the user to use
++ * uevents in order to monitor for reset. Even if no reads/writes are
++ * issued during pci reset, userspace will still get -EIO afterwards,
++ * forcing it to reopen and check the BDF (which may have potentially
++ * changed after reset). Uevents can be used to avoid looping in open()
++ */
++ if (priv->pcie.need_uevent) {
++ struct kobject *kobj = &aspeed_mctp_miscdev.this_device->kobj;
++ struct mctp_client *client;
++
++ spin_lock_bh(&priv->clients_lock);
++ client = list_first_entry_or_null(&priv->clients,
++ typeof(*client), link);
++ /*
++ * Here, we're only updating the "disconnected" flag under
++ * spinlock, meaning that we can skip taking the refcount
++ */
++ if (client)
++ WRITE_ONCE(client->disconnected, true);
++ spin_unlock_bh(&priv->clients_lock);
++
++ aspeed_mctp_send_pcie_uevent(kobj, false);
++ priv->pcie.need_uevent = false;
++ }
++
++ aspeed_mctp_pcie_setup(priv);
++
++ if (priv->pcie.bdf) {
++ aspeed_mctp_send_pcie_uevent(&priv->dev->kobj, true);
++ aspeed_mctp_irq_enable(priv);
++ }
++}
++
++static void aspeed_mctp_channels_init(struct aspeed_mctp *priv)
++{
++ aspeed_mctp_rx_chan_init(&priv->rx);
++ aspeed_mctp_tx_chan_init(&priv->tx);
++}
++
++static irqreturn_t aspeed_mctp_irq_handler(int irq, void *arg)
++{
++ struct aspeed_mctp *priv = arg;
++ u32 handled = 0;
++ u32 status;
++
++ regmap_read(priv->map, ASPEED_MCTP_INT_STS, &status);
++ regmap_write(priv->map, ASPEED_MCTP_INT_STS, status);
++
++ if (status & TX_CMD_LAST_INT) {
++ u32 rd_ptr;
++
++ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_RD_PTR,
++ UPDATE_RX_RD_PTR);
++ regmap_read(priv->map, ASPEED_MCTP_TX_BUF_RD_PTR, &rd_ptr);
++ rd_ptr &= TX_BUFFER_RD_PTR;
++
++ /*
++ * rd_ptr on TX side seems to be busted...
++ * Since we're always reading zeroes, let's trust that when
++ * we're getting LAST_CMD irq, everything we previously
++ * submitted was transmitted and start from 0
++ */
++ WRITE_ONCE(priv->tx.rd_ptr, TX_CMD_COUNT);
++
++ tasklet_hi_schedule(&priv->tx.tasklet);
++
++ wake_up_all(&priv->wait_queue);
++
++ handled |= TX_CMD_LAST_INT;
++ }
++
++ if (status & TX_CMD_WRONG_INT) {
++ /* TODO: print the actual command */
++ dev_warn(priv->dev, "TX wrong");
++
++ handled |= TX_CMD_WRONG_INT;
++ }
++
++ if (status & RX_CMD_RECEIVE_INT) {
++ u32 rd_ptr;
++
++ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_RD_PTR,
++ UPDATE_RX_RD_PTR);
++ regmap_read(priv->map, ASPEED_MCTP_RX_BUF_RD_PTR, &rd_ptr);
++ rd_ptr &= RX_BUFFER_RD_PTR;
++
++ WRITE_ONCE(priv->rx.rd_ptr, rd_ptr > 0 ? rd_ptr : RX_CMD_COUNT);
++
++ tasklet_hi_schedule(&priv->rx.tasklet);
++
++ handled |= RX_CMD_RECEIVE_INT;
++ }
++
++ if (!handled)
++ return IRQ_NONE;
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t aspeed_mctp_pcie_rst_irq_handler(int irq, void *arg)
++{
++ struct aspeed_mctp *priv = arg;
++
++ aspeed_mctp_channels_init(priv);
++
++ priv->pcie.need_uevent = true;
++ priv->pcie.bdf = 0;
++
++ schedule_delayed_work(&priv->pcie.rst_dwork, 0);
++
++ return IRQ_HANDLED;
++}
++
++static void aspeed_mctp_drv_init(struct aspeed_mctp *priv)
++{
++ init_waitqueue_head(&priv->wait_queue);
++ INIT_LIST_HEAD(&priv->clients);
++
++ spin_lock_init(&priv->clients_lock);
++
++ INIT_DELAYED_WORK(&priv->pcie.rst_dwork, aspeed_mctp_reset_work);
++
++ tasklet_init(&priv->tx.tasklet, aspeed_mctp_tx_tasklet,
++ (unsigned long)&priv->tx);
++ tasklet_init(&priv->rx.tasklet, aspeed_mctp_rx_tasklet,
++ (unsigned long)&priv->rx);
++}
++
++static void aspeed_mctp_drv_fini(struct aspeed_mctp *priv)
++{
++ tasklet_disable(&priv->tx.tasklet);
++ tasklet_kill(&priv->tx.tasklet);
++ tasklet_disable(&priv->rx.tasklet);
++ tasklet_kill(&priv->rx.tasklet);
++
++ cancel_delayed_work_sync(&priv->pcie.rst_dwork);
++}
++
++static int aspeed_mctp_resources_init(struct aspeed_mctp *priv)
++{
++ struct platform_device *pdev = to_platform_device(priv->dev);
++ void __iomem *regs;
++
++ regs = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(regs)) {
++ dev_err(priv->dev, "Failed to get regmap!\n");
++ return PTR_ERR(regs);
++ }
++
++ priv->map = devm_regmap_init_mmio(priv->dev, regs,
++ &aspeed_mctp_regmap_cfg);
++ if (IS_ERR(priv->map))
++ return PTR_ERR(priv->map);
++
++ priv->reset = devm_reset_control_get(priv->dev, 0);
++ if (IS_ERR(priv->reset)) {
++ dev_err(priv->dev, "Failed to get reset!\n");
++ return PTR_ERR(priv->reset);
++ }
++
++ priv->pcie.map =
++ syscon_regmap_lookup_by_phandle(priv->dev->of_node,
++ "aspeed,pcieh");
++ if (IS_ERR(priv->pcie.map)) {
++ dev_err(priv->dev, "Failed to find PCIe Host regmap!\n");
++ return PTR_ERR(priv->pcie.map);
++ }
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++}
++
++static int aspeed_mctp_dma_init(struct aspeed_mctp *priv)
++{
++ struct mctp_channel *tx = &priv->tx;
++ struct mctp_channel *rx = &priv->rx;
++ int ret = -ENOMEM;
++
++ BUILD_BUG_ON(TX_CMD_COUNT >= TX_MAX_CMD_COUNT);
++ BUILD_BUG_ON(RX_CMD_COUNT >= RX_MAX_CMD_COUNT);
++
++ tx->cmd.vaddr = dma_alloc_coherent(priv->dev, TX_CMD_BUF_SIZE,
++ &tx->cmd.dma_handle, GFP_KERNEL);
++
++ if (!tx->cmd.vaddr)
++ return ret;
++
++ tx->data.vaddr = dma_alloc_coherent(priv->dev, TX_DATA_BUF_SIZE,
++ &tx->data.dma_handle, GFP_KERNEL);
++
++ if (!tx->data.vaddr)
++ goto out_tx_data;
++
++ rx->cmd.vaddr = dma_alloc_coherent(priv->dev, RX_CMD_BUF_SIZE,
++ &rx->cmd.dma_handle, GFP_KERNEL);
++
++ if (!rx->cmd.vaddr)
++ goto out_tx_cmd;
++
++ rx->data.vaddr = dma_alloc_coherent(priv->dev, RX_DATA_BUF_SIZE,
++ &rx->data.dma_handle, GFP_KERNEL);
++
++ if (!rx->data.vaddr)
++ goto out_rx_data;
++
++ return 0;
++out_rx_data:
++ dma_free_coherent(priv->dev, RX_CMD_BUF_SIZE, rx->cmd.vaddr,
++ rx->cmd.dma_handle);
++
++out_tx_cmd:
++ dma_free_coherent(priv->dev, TX_DATA_BUF_SIZE, tx->data.vaddr,
++ tx->data.dma_handle);
++
++out_tx_data:
++ dma_free_coherent(priv->dev, TX_CMD_BUF_SIZE, tx->cmd.vaddr,
++ tx->cmd.dma_handle);
++ return ret;
++}
++
++static void aspeed_mctp_dma_fini(struct aspeed_mctp *priv)
++{
++ struct mctp_channel *tx = &priv->tx;
++ struct mctp_channel *rx = &priv->rx;
++
++ dma_free_coherent(priv->dev, TX_CMD_BUF_SIZE, tx->cmd.vaddr,
++ tx->cmd.dma_handle);
++
++ dma_free_coherent(priv->dev, RX_CMD_BUF_SIZE, rx->cmd.vaddr,
++ rx->cmd.dma_handle);
++
++ dma_free_coherent(priv->dev, TX_DATA_BUF_SIZE, tx->data.vaddr,
++ tx->data.dma_handle);
++
++ dma_free_coherent(priv->dev, RX_DATA_BUF_SIZE, rx->data.vaddr,
++ rx->data.dma_handle);
++}
++
++static int aspeed_mctp_irq_init(struct aspeed_mctp *priv)
++{
++ struct platform_device *pdev = to_platform_device(priv->dev);
++ int irq, ret;
++
++ irq = platform_get_irq(pdev, 0);
++ if (!irq)
++ return -ENODEV;
++
++ ret = devm_request_irq(priv->dev, irq, aspeed_mctp_irq_handler,
++ IRQF_SHARED, "aspeed-mctp", priv);
++ if (ret)
++ return ret;
++
++ irq = platform_get_irq(pdev, 1);
++ if (!irq)
++ return -ENODEV;
++
++ ret = devm_request_irq(priv->dev, irq,
++ aspeed_mctp_pcie_rst_irq_handler,
++ IRQF_SHARED, "aspeed-mctp", priv);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static void aspeed_mctp_hw_reset(struct aspeed_mctp *priv)
++{
++ if (reset_control_assert(priv->reset) != 0)
++ dev_warn(priv->dev, "Failed to assert reset\n");
++
++ if (reset_control_deassert(priv->reset) != 0)
++ dev_warn(priv->dev, "Failed to deassert reset\n");
++}
++
++static int aspeed_mctp_probe(struct platform_device *pdev)
++{
++ struct aspeed_mctp *priv;
++ int ret;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ priv->dev = &pdev->dev;
++
++ aspeed_mctp_drv_init(priv);
++
++ ret = aspeed_mctp_resources_init(priv);
++ if (ret) {
++ dev_err(priv->dev, "Failed to init resources\n");
++ goto out_drv;
++ }
++
++ ret = aspeed_mctp_dma_init(priv);
++ if (ret) {
++ dev_err(priv->dev, "Failed to init DMA\n");
++ goto out_drv;
++ }
++
++ /*
++ * FIXME: We need to verify how to make the reset work when we probe
++ * multiple times. Currently calling reset more than once seems to make
++ * the HW upset, however, we do need to reset after boot before we're
++ * able to use the HW.
++ */
++ aspeed_mctp_hw_reset(priv);
++
++ aspeed_mctp_channels_init(priv);
++
++ aspeed_mctp_miscdev.parent = priv->dev;
++ ret = misc_register(&aspeed_mctp_miscdev);
++ if (ret) {
++ dev_err(priv->dev, "Failed to register miscdev\n");
++ goto out_dma;
++ }
++ aspeed_mctp_miscdev.this_device->type = &aspeed_mctp_type;
++
++ ret = aspeed_mctp_irq_init(priv);
++ if (ret) {
++ dev_err(priv->dev, "Failed to init IRQ!\n");
++ goto out_dma;
++ }
++
++ aspeed_mctp_irq_enable(priv);
++
++ aspeed_mctp_pcie_setup(priv);
++
++ return 0;
++
++out_dma:
++ aspeed_mctp_dma_fini(priv);
++out_drv:
++ aspeed_mctp_drv_fini(priv);
++out:
++ dev_err(priv->dev, "Failed to probe Aspeed MCTP: %d\n", ret);
++ return ret;
++}
++
++static int aspeed_mctp_remove(struct platform_device *pdev)
++{
++ struct aspeed_mctp *priv = platform_get_drvdata(pdev);
++
++ misc_deregister(&aspeed_mctp_miscdev);
++
++ aspeed_mctp_irq_disable(priv);
++
++ aspeed_mctp_dma_fini(priv);
++
++ aspeed_mctp_drv_fini(priv);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_mctp_match_table[] = {
++ { .compatible = "aspeed,ast2600-mctp" },
++ { }
++};
++
++static struct platform_driver aspeed_mctp_driver = {
++ .driver = {
++ .name = "aspeed-mctp",
++ .of_match_table = of_match_ptr(aspeed_mctp_match_table),
++ },
++ .probe = aspeed_mctp_probe,
++ .remove = aspeed_mctp_remove,
++};
++
++static int __init aspeed_mctp_init(void)
++{
++ packet_cache =
++ kmem_cache_create_usercopy("mctp-packet",
++ sizeof(struct mctp_pcie_packet),
++ 0, 0, 0,
++ sizeof(struct mctp_pcie_packet),
++ NULL);
++ if (!packet_cache)
++ return -ENOMEM;
++
++ return platform_driver_register(&aspeed_mctp_driver);
++}
++
++static void __exit aspeed_mctp_exit(void)
++{
++ platform_driver_unregister(&aspeed_mctp_driver);
++ kmem_cache_destroy(packet_cache);
++}
++
++module_init(aspeed_mctp_init)
++module_exit(aspeed_mctp_exit)
++
++MODULE_DEVICE_TABLE(of, aspeed_mctp_match_table);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
++MODULE_DESCRIPTION("Aspeed AST2600 MCTP driver");
+diff --git a/include/uapi/linux/aspeed-mctp.h b/include/uapi/linux/aspeed-mctp.h
+new file mode 100644
+index 000000000000..e37fa3afde9d
+--- /dev/null
++++ b/include/uapi/linux/aspeed-mctp.h
+@@ -0,0 +1,72 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2020 Intel Corporation */
++
++#ifndef _UAPI_LINUX_ASPEED_MCTP_H
++#define _UAPI_LINUX_ASPEED_MCTP_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++/*
++ * aspeed-mctp is a simple device driver exposing a read/write interface:
++ * +----------------------+
++ * | PCIe VDM Header | 16 bytes (Big Endian)
++ * +----------------------+
++ * | MCTP Message Payload | 64/128/256/512 bytes (Little Endian)
++ * +----------------------+
++ *
++ * MCTP packet description can be found in DMTF DSP0238,
++ * MCTP PCIe VDM Transport Specification.
++ *
++ * Note: AST2600 hardware follows MCTP Message Payload rules from earlier
++ * hardware and we've decided to copy the packets directly, without swapping.
++ * This means that it's userspace responsibility to provide the data in
++ * a format that the hardware expects.
++ */
++
++#define ASPEED_MCTP_PCIE_VDM_HDR_SIZE 16
++
++/*
++ * uevents generated by aspeed-mctp driver
++ */
++#define ASPEED_MCTP_READY "PCIE_READY"
++
++/*
++ * MCTP operations
++ * @ASPEED_MCTP_IOCTL_FILTER_EID: enable/disable filter incoming packets based
++ * on Endpoint ID (BROKEN)
++ * @ASPEED_MCTP_IOCTL_GET_BDF: read PCI bus/device/function of MCTP Controller
++ * @ASPEED_MCTP_IOCTL_GET_MEDIUM_ID: read MCTP physical medium identifier
++ * related to PCIe revision
++ * @ASPEED_MCTP_IOCTL_GET_MTU: read max transmission unit (in bytes)
++ */
++
++struct aspeed_mctp_filter_eid {
++ __u8 eid;
++ bool enable;
++};
++
++struct aspeed_mctp_get_bdf {
++ __u16 bdf;
++};
++
++struct aspeed_mctp_get_medium_id {
++ __u8 medium_id;
++};
++
++struct aspeed_mctp_get_mtu {
++ __u8 mtu;
++};
++
++#define ASPEED_MCTP_IOCTL_BASE 0x4d
++
++#define ASPEED_MCTP_IOCTL_FILTER_EID \
++ _IOW(ASPEED_MCTP_IOCTL_BASE, 0, struct aspeed_mctp_filter_eid)
++#define ASPEED_MCTP_IOCTL_GET_BDF \
++ _IOR(ASPEED_MCTP_IOCTL_BASE, 1, struct aspeed_mctp_get_bdf)
++#define ASPEED_MCTP_IOCTL_GET_MEDIUM_ID \
++ _IOR(ASPEED_MCTP_IOCTL_BASE, 2, struct aspeed_mctp_get_medium_id)
++#define ASPEED_MCTP_IOCTL_GET_MTU \
++ _IOR(ASPEED_MCTP_IOCTL_BASE, 3, struct aspeed_mctp_get_mtu)
++
++#endif /* _UAPI_LINUX_ASPEED_MCTP_H */
+--
+2.21.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0109-signal-Extend-exec_id-to-64bits.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0109-signal-Extend-exec_id-to-64bits.patch
new file mode 100644
index 000000000..7d879ab82
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0109-signal-Extend-exec_id-to-64bits.patch
@@ -0,0 +1,88 @@
+From 5f2d04139aa5ed04eab54b84e8a25bab87a2449c Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Mon, 30 Mar 2020 19:01:04 -0500
+Subject: [PATCH] signal: Extend exec_id to 64bits
+
+commit d1e7fd6462ca9fc76650fbe6ca800e35b24267da upstream.
+
+Replace the 32bit exec_id with a 64bit exec_id to make it impossible
+to wrap the exec_id counter. With care an attacker can cause exec_id
+wrap and send arbitrary signals to a newly exec'd parent. This
+bypasses the signal sending checks if the parent changes their
+credentials during exec.
+
+The severity of this problem can been seen that in my limited testing
+of a 32bit exec_id it can take as little as 19s to exec 65536 times.
+Which means that it can take as little as 14 days to wrap a 32bit
+exec_id. Adam Zabrocki has succeeded wrapping the self_exe_id in 7
+days. Even my slower timing is in the uptime of a typical server.
+Which means self_exec_id is simply a speed bump today, and if exec
+gets noticably faster self_exec_id won't even be a speed bump.
+
+Extending self_exec_id to 64bits introduces a problem on 32bit
+architectures where reading self_exec_id is no longer atomic and can
+take two read instructions. Which means that is is possible to hit
+a window where the read value of exec_id does not match the written
+value. So with very lucky timing after this change this still
+remains expoiltable.
+
+I have updated the update of exec_id on exec to use WRITE_ONCE
+and the read of exec_id in do_notify_parent to use READ_ONCE
+to make it clear that there is no locking between these two
+locations.
+
+Link: https://lore.kernel.org/kernel-hardening/20200324215049.GA3710@pi3.com.pl
+Fixes: 2.3.23pre2
+Cc: stable@vger.kernel.org
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exec.c | 2 +-
+ include/linux/sched.h | 4 ++--
+ kernel/signal.c | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/fs/exec.c b/fs/exec.c
+index c27231234764..fc2870f2aca9 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1383,7 +1383,7 @@ void setup_new_exec(struct linux_binprm * bprm)
+
+ /* An exec changes our domain. We are no longer part of the thread
+ group */
+- current->self_exec_id++;
++ WRITE_ONCE(current->self_exec_id, current->self_exec_id + 1);
+ flush_signal_handlers(current, 0);
+ }
+ EXPORT_SYMBOL(setup_new_exec);
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index b968d736833b..5710b80f8050 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -934,8 +934,8 @@ struct task_struct {
+ struct seccomp seccomp;
+
+ /* Thread group tracking: */
+- u32 parent_exec_id;
+- u32 self_exec_id;
++ u64 parent_exec_id;
++ u64 self_exec_id;
+
+ /* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
+ spinlock_t alloc_lock;
+diff --git a/kernel/signal.c b/kernel/signal.c
+index eea748174ade..7d3d35eb7a0b 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1931,7 +1931,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
+ * This is only possible if parent == real_parent.
+ * Check if it has changed security domain.
+ */
+- if (tsk->parent_exec_id != tsk->parent->self_exec_id)
++ if (tsk->parent_exec_id != READ_ONCE(tsk->parent->self_exec_id))
+ sig = SIGCHLD;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch
new file mode 100644
index 000000000..542d80e16
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch
@@ -0,0 +1,75 @@
+From 15753588bcd4bbffae1cca33c8ced5722477fe1f Mon Sep 17 00:00:00 2001
+From: Kyungtae Kim <kt0755@gmail.com>
+Date: Sun, 10 May 2020 05:43:34 +0000
+Subject: [PATCH] USB: gadget: fix illegal array access in binding with UDC
+
+FuzzUSB (a variant of syzkaller) found an illegal array access
+using an incorrect index while binding a gadget with UDC.
+
+Reference: https://www.spinics.net/lists/linux-usb/msg194331.html
+
+This bug occurs when a size variable used for a buffer
+is misused to access its strcpy-ed buffer.
+Given a buffer along with its size variable (taken from user input),
+from which, a new buffer is created using kstrdup().
+Due to the original buffer containing 0 value in the middle,
+the size of the kstrdup-ed buffer becomes smaller than that of the original.
+So accessing the kstrdup-ed buffer with the same size variable
+triggers memory access violation.
+
+The fix makes sure no zero value in the buffer,
+by comparing the strlen() of the orignal buffer with the size variable,
+so that the access to the kstrdup-ed buffer is safe.
+
+BUG: KASAN: slab-out-of-bounds in gadget_dev_desc_UDC_store+0x1ba/0x200
+drivers/usb/gadget/configfs.c:266
+Read of size 1 at addr ffff88806a55dd7e by task syz-executor.0/17208
+
+CPU: 2 PID: 17208 Comm: syz-executor.0 Not tainted 5.6.8 #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0xce/0x128 lib/dump_stack.c:118
+ print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374
+ __kasan_report+0x131/0x1b0 mm/kasan/report.c:506
+ kasan_report+0x12/0x20 mm/kasan/common.c:641
+ __asan_report_load1_noabort+0x14/0x20 mm/kasan/generic_report.c:132
+ gadget_dev_desc_UDC_store+0x1ba/0x200 drivers/usb/gadget/configfs.c:266
+ flush_write_buffer fs/configfs/file.c:251 [inline]
+ configfs_write_file+0x2f1/0x4c0 fs/configfs/file.c:283
+ __vfs_write+0x85/0x110 fs/read_write.c:494
+ vfs_write+0x1cd/0x510 fs/read_write.c:558
+ ksys_write+0x18a/0x220 fs/read_write.c:611
+ __do_sys_write fs/read_write.c:623 [inline]
+ __se_sys_write fs/read_write.c:620 [inline]
+ __x64_sys_write+0x73/0xb0 fs/read_write.c:620
+ do_syscall_64+0x9e/0x510 arch/x86/entry/common.c:294
+ entry_SYSCALL_64_after_hwframe+0x49/0xbe
+
+Signed-off-by: Kyungtae Kim <kt0755@gmail.com>
+Reported-and-tested-by: Kyungtae Kim <kt0755@gmail.com>
+Cc: Felipe Balbi <balbi@kernel.org>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200510054326.GA19198@pizza01
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/configfs.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
+index 32b637e3e1fa..6a9aa4413d64 100644
+--- a/drivers/usb/gadget/configfs.c
++++ b/drivers/usb/gadget/configfs.c
+@@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
+ char *name;
+ int ret;
+
++ if (strlen(page) < len)
++ return -EOVERFLOW;
++
+ name = kstrdup(page, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg
new file mode 100644
index 000000000..bbc7fa5b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg
@@ -0,0 +1,2 @@
+CONFIG_DEVMEM = y
+CONFIG_DEVMEM_BOOTPARAM = n
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
new file mode 100644
index 000000000..5f453510a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
@@ -0,0 +1,89 @@
+CONFIG_BLK_DEV_RAM=y
+CONFIG_HWMON=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_IIO=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_ASPEED_ADC=y
+CONFIG_SGPIO_ASPEED=y
+CONFIG_CRC8=y
+CONFIG_PECI=y
+CONFIG_PECI_CHARDEV=y
+CONFIG_PECI_ASPEED=y
+CONFIG_SENSORS_PECI_CPUTEMP=y
+CONFIG_SENSORS_PECI_DIMMTEMP=y
+CONFIG_SENSORS_PECI_CPUPOWER=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_BLK_DEV_RAM_SIZE=49152
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x01
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_ASPEED_ESPI_SLAVE=y
+CONFIG_ASPEED_KCS_IPMI_BMC=y
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_MQUEUE=y
+CONFIG_I2C_SLAVE_MQUEUE_MESSAGE_SIZE=256
+CONFIG_I2C_SLAVE_MQUEUE_QUEUE_SIZE=32
+CONFIG_ASPEED_BT_IPMI_BMC=n
+CONFIG_ASPEED_LPC_CTRL=n
+CONFIG_ASPEED_LPC_MBOX=y
+CONFIG_ASPEED_LPC_SIO=y
+CONFIG_JTAG=y
+CONFIG_JTAG_ASPEED=y
+CONFIG_FRAME_VECTOR=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_ASPEED=y
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_V4L2=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_DMA_CONTIG=y
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+CONFIG_USB_LIBCOMPOSITE=y
+CONFIG_USB_F_HID=y
+CONFIG_USB_GADGET=y
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_ASPEED_VHUB=y
+CONFIG_USB_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_ASPEED_UART_ROUTING=y
+CONFIG_ASPEED_VGA_SHAREDMEM=y
+CONFIG_PWM=y
+CONFIG_PWM_FTTMR010=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PWM_BEEPER=y
+CONFIG_VFAT_FS=y
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_CIFS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_ZLIB_COMPRESS=y
+CONFIG_PSTORE_RAM=y
+CONFIG_FSI=n
+CONFIG_FSI_MASTER_HUB=n
+CONFIG_FSI_MASTER_ASPEED=n
+CONFIG_FSI_SCOM=n
+CONFIG_FSI_SBEFIFO=n
+CONFIG_FSI_OCC=n
+CONFIG_ASPEED_P2A_CTRL=n
+CONFIG_USB=n
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=n
+CONFIG_USB_DYNAMIC_MINORS=n
+CONFIG_USB_EHCI_HCD=n
+CONFIG_USB_EHCI_ROOT_HUB_TT=n
+CONFIG_USB_EHCI_HCD_PLATFORM=n
+CONFIG_IPMB_DEVICE_INTERFACE=y
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
new file mode 100644
index 000000000..f1d781f6f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -0,0 +1,87 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+do_compile_prepend(){
+ # device tree compiler flags
+ export DTC_FLAGS=-@
+}
+
+SRC_URI += " \
+ file://intel.cfg \
+ file://0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch \
+ file://0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch \
+ file://0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch \
+ file://0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch \
+ file://0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch \
+ file://0006-Allow-monitoring-of-power-control-input-GPIOs.patch \
+ file://0007-aspeed-pwm-tacho-change-default-fan-speed.patch \
+ file://0014-arm-dts-aspeed-g5-add-espi.patch \
+ file://0015-New-flash-map-for-intel.patch \
+ file://0016-Add-ASPEED-SGPIO-driver.patch \
+ file://0017-SGPIO-DT-and-pinctrl-fixup.patch \
+ file://0019-Add-I2C-IPMB-support.patch \
+ file://0020-misc-aspeed-add-lpc-mbox-driver.patch \
+ file://0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch \
+ file://0022-Add-AST2500-eSPI-driver.patch \
+ file://0028-Add-AST2500-JTAG-driver.patch \
+ file://0030-Add-dump-debug-code-into-I2C-drivers.patch \
+ file://0031-Add-high-speed-baud-rate-support-for-UART.patch \
+ file://0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch \
+ file://0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch \
+ file://0035-Implement-a-memory-driver-share-memory.patch \
+ file://0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch \
+ file://0040-i2c-Add-mux-hold-unhold-msg-types.patch \
+ file://0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch \
+ file://0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch \
+ file://0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch \
+ file://0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch \
+ file://0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch \
+ file://0049-Suppress-excessive-HID-gadget-error-logs.patch \
+ file://0051-Add-AST2500-JTAG-device.patch \
+ file://0052-drivers-jtag-Add-JTAG-core-driver.patch \
+ file://0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch \
+ file://0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch \
+ file://0055-Documentation-jtag-Add-ABI-documentation.patch \
+ file://0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch \
+ file://0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch \
+ file://0061-i2c-aspeed-add-buffer-mode-transfer-support.patch \
+ file://0062-i2c-aspeed-add-DMA-mode-transfer-support.patch \
+ file://0063-i2c-aspeed-add-general-call-support.patch \
+ file://0064-set-idle-disconnect-to-true-in-all-cases.patch \
+ file://0068-i2c-aspeed-add-H-W-timeout-support.patch \
+ file://0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch \
+ file://0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch \
+ file://0072-pmbus-add-fault-and-beep-attributes.patch \
+ file://0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch \
+ file://0075-Refine-initialization-flow-in-I2C-driver.patch \
+ file://0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch \
+ file://0077-soc-aspeed-Add-read-only-property-support.patch \
+ file://0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch \
+ file://0080-i2c-aspeed-filter-garbage-interrupts-out.patch \
+ file://0084-ARM-dts-aspeed-g6-add-GFX-node.patch \
+ file://0085-drm-add-AST2600-GFX-support.patch \
+ file://0086-ADC-linux-driver-for-AST2600.patch \
+ file://0086-ARM-dts-aspeed-g6-add-video-node.patch \
+ file://0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch \
+ file://0088-clk-ast2600-enable-ESPICLK-always.patch \
+ file://0089-ast2600-enable-high-speed-uart-in-kernel.patch \
+ file://0090-peci-cpupower-driver-1.patch \
+ file://0092-SPI-Quad-IO-driver-support-AST2600.patch \
+ file://0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch \
+ file://0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch \
+ file://0095-pwm-and-tach-driver-changes-for-ast2600.patch \
+ file://0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch \
+ file://0100-Mailbox-Enabling-interrupt-based-mailbox.patch \
+ file://0101-Add-poll-fops-in-eSPI-driver.patch \
+ file://0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch \
+ file://0103-Refine-clock-settings.patch \
+ file://0104-Add-chip-unique-id-reading-interface.patch \
+ file://0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch \
+ file://0106-enable-AST2600-I3C.patch \
+ file://0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch \
+ file://0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch \
+ file://0109-signal-Extend-exec_id-to-64bits.patch \
+ file://0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch \
+ "
+
+SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}"
+SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', 'file://debug.cfg', '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch
new file mode 100644
index 000000000..05e26bedb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch
@@ -0,0 +1,412 @@
+From 5dfcd6c81a9f26c6c9c867a7a49f5259c3512be2 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Thu, 2 Apr 2020 17:06:07 +0530
+Subject: [PATCH 1/2] Adding channel specific privilege to network
+
+ - Adding the channel access information to the network
+ interface object. This privilege will be used in
+ channel specific authorization.
+ - Get supported priv from user manager service dynamically.
+ - Signal handling for capturing the supported priv list
+ changes from user managerment.
+
+Tested-by:
+Verified channel access through ipmitool get/set channel
+access command
+
+Change-Id: I3b592a19363eef684e31d5f7c34dad8f2f9211df
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ ethernet_interface.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++++
+ ethernet_interface.hpp | 39 +++++++++++++++-
+ network_manager.cpp | 104 +++++++++++++++++++++++++++++++++++++++++
+ network_manager.hpp | 9 ++++
+ 4 files changed, 274 insertions(+), 1 deletion(-)
+
+diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
+index ed1e1ba..fca86bd 100644
+--- a/ethernet_interface.cpp
++++ b/ethernet_interface.cpp
+@@ -37,6 +37,10 @@ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+ using Argument = xyz::openbmc_project::Common::InvalidArgument;
+
++static constexpr const char* networkChannelCfgFile =
++ "/var/channel_intf_data.json";
++static constexpr const char* defaultChannelPriv = "priv-admin";
++
+ struct EthernetIntfSocket
+ {
+ EthernetIntfSocket(int domain, int type, int protocol)
+@@ -86,6 +90,7 @@ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
+ EthernetInterfaceIntf::linkUp(std::get<3>(ifInfo));
+ #endif
++ getChannelPrivilege(intfName);
+
+ // Emit deferred signal.
+ if (emitSignal)
+@@ -869,5 +874,123 @@ void EthernetInterface::deleteAll()
+ manager.writeToConfigurationFile();
+ }
+
++nlohmann::json EthernetInterface::readJsonFile(const std::string& configFile)
++{
++ std::ifstream jsonFile(configFile);
++ if (!jsonFile.good())
++ {
++ log<level::ERR>("JSON file not found");
++ return nullptr;
++ }
++
++ nlohmann::json data = nullptr;
++ try
++ {
++ data = nlohmann::json::parse(jsonFile, nullptr, false);
++ }
++ catch (nlohmann::json::parse_error& e)
++ {
++ log<level::DEBUG>("Corrupted channel config.",
++ entry("MSG: %s", e.what()));
++ throw std::runtime_error("Corrupted channel config file");
++ }
++
++ return data;
++}
++
++int EthernetInterface::writeJsonFile(const std::string& configFile,
++ const nlohmann::json& jsonData)
++{
++ std::ofstream jsonFile(configFile);
++ if (!jsonFile.good())
++ {
++ log<level::ERR>("JSON file open failed",
++ entry("FILE=%s", networkChannelCfgFile));
++ return -1;
++ }
++
++ // Write JSON to file
++ jsonFile << jsonData;
++
++ jsonFile.flush();
++ return 0;
++}
++
++std::string
++ EthernetInterface::getChannelPrivilege(const std::string& interfaceName)
++{
++ std::string priv(defaultChannelPriv);
++ std::string retPriv;
++
++ nlohmann::json jsonData = readJsonFile(networkChannelCfgFile);
++ if (jsonData != nullptr)
++ {
++ try
++ {
++ priv = jsonData[interfaceName].get<std::string>();
++ retPriv = ChannelAccessIntf::maxPrivilege(std::move(priv));
++ return retPriv;
++ }
++ catch (const nlohmann::json::exception& e)
++ {
++ jsonData[interfaceName] = priv;
++ }
++ }
++ else
++ {
++ jsonData[interfaceName] = priv;
++ }
++
++ if (writeJsonFile(networkChannelCfgFile, jsonData) != 0)
++ {
++ log<level::DEBUG>("Error in write JSON data to file",
++ entry("FILE=%s", networkChannelCfgFile));
++ elog<InternalFailure>();
++ }
++
++ retPriv = ChannelAccessIntf::maxPrivilege(std::move(priv));
++
++ return retPriv;
++}
++
++std::string EthernetInterface::maxPrivilege(std::string priv)
++{
++ std::string intfName = interfaceName();
++
++ if (manager.supportedPrivList.empty())
++ {
++ // Populate the supported privilege list
++ manager.initSupportedPrivilges();
++ }
++
++ if (!priv.empty() && (std::find(manager.supportedPrivList.begin(),
++ manager.supportedPrivList.end(),
++ priv) == manager.supportedPrivList.end()))
++ {
++ log<level::ERR>("Invalid privilege");
++ elog<InvalidArgument>(Argument::ARGUMENT_NAME("Privilege"),
++ Argument::ARGUMENT_VALUE(priv.c_str()));
++ }
++
++ if (ChannelAccessIntf::maxPrivilege() == priv)
++ {
++ // No change in privilege so just return.
++ return priv;
++ }
++
++ nlohmann::json jsonData = readJsonFile(networkChannelCfgFile);
++ jsonData[intfName] = priv;
++
++ if (writeJsonFile(networkChannelCfgFile, jsonData) != 0)
++ {
++ log<level::DEBUG>("Error in write JSON data to file",
++ entry("FILE=%s", networkChannelCfgFile));
++ elog<InternalFailure>();
++ }
++
++ // Property change signal will be sent
++ return ChannelAccessIntf::maxPrivilege(std::move(priv));
++}
++
+ } // namespace network
+ } // namespace phosphor
+diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
+index 68668d6..058d328 100644
+--- a/ethernet_interface.hpp
++++ b/ethernet_interface.hpp
+@@ -2,11 +2,14 @@
+
+ #include "types.hpp"
+ #include "util.hpp"
++#include "xyz/openbmc_project/Channel/ChannelAccess/server.hpp"
+ #include "xyz/openbmc_project/Network/IP/Create/server.hpp"
+ #include "xyz/openbmc_project/Network/Neighbor/CreateStatic/server.hpp"
+
+ #include <experimental/filesystem>
++#include <nlohmann/json.hpp>
+ #include <sdbusplus/bus.hpp>
++#include <sdbusplus/bus/match.hpp>
+ #include <sdbusplus/server/object.hpp>
+ #include <string>
+ #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
+@@ -23,7 +26,8 @@ using Ifaces = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Network::server::MACAddress,
+ sdbusplus::xyz::openbmc_project::Network::IP::server::Create,
+ sdbusplus::xyz::openbmc_project::Network::Neighbor::server::CreateStatic,
+- sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll>;
++ sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll,
++ sdbusplus::xyz::openbmc_project::Channel::server::ChannelAccess>;
+
+ using IP = sdbusplus::xyz::openbmc_project::Network::server::IP;
+
+@@ -31,10 +35,15 @@ using EthernetInterfaceIntf =
+ sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
+ using MacAddressIntf =
+ sdbusplus::xyz::openbmc_project::Network::server::MACAddress;
++using ChannelAccessIntf =
++ sdbusplus::xyz::openbmc_project::Channel::server::ChannelAccess;
+
+ using ServerList = std::vector<std::string>;
+ using ObjectPath = sdbusplus::message::object_path;
+
++using DbusVariant =
++ sdbusplus::message::variant<std::string, std::vector<std::string>>;
++
+ namespace fs = std::experimental::filesystem;
+
+ class Manager; // forward declaration of network manager.
+@@ -199,6 +208,14 @@ class EthernetInterface : public Ifaces
+ */
+ void deleteAll();
+
++ /** @brief sets the channel maxium privilege.
++ * @param[in] value - Channel privilege which needs to be set on the
++ * system.
++ * @returns privilege of the interface or throws an error.
++ */
++ std::string maxPrivilege(std::string value) override;
++
++ using ChannelAccessIntf::maxPrivilege;
+ using EthernetInterfaceIntf::dHCPEnabled;
+ using EthernetInterfaceIntf::interfaceName;
+ using EthernetInterfaceIntf::linkUp;
+@@ -296,6 +313,26 @@ class EthernetInterface : public Ifaces
+ std::string objPath;
+
+ friend class TestEthernetInterface;
++
++ /** @brief gets the channel privilege.
++ * @param[in] interfaceName - Network interface name.
++ * @returns privilege of the interface
++ */
++ std::string getChannelPrivilege(const std::string& interfaceName);
++
++ /** @brief reads the channel access info from file.
++ * @param[in] configFile - channel access filename
++ * @returns json file data
++ */
++ nlohmann::json readJsonFile(const std::string& configFile);
++
++ /** @brief writes the channel access info to file.
++ * @param[in] configFile - channel access filename
++ * @param[in] jsonData - json data to write
++ * @returns success or failure
++ */
++ int writeJsonFile(const std::string& configFile,
++ const nlohmann::json& jsonData);
+ };
+
+ } // namespace network
+diff --git a/network_manager.cpp b/network_manager.cpp
+index 043d7a2..75f4e5f 100644
+--- a/network_manager.cpp
++++ b/network_manager.cpp
+@@ -34,6 +34,13 @@ extern std::unique_ptr<Timer> restartTimer;
+ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
++static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
++static constexpr const char* userMgrInterface =
++ "xyz.openbmc_project.User.Manager";
++static constexpr const char* propNameAllPrivileges = "AllPrivileges";
++
++std::unique_ptr<sdbusplus::bus::match_t> usrMgmtSignal(nullptr);
++
+ Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath,
+ const std::string& path) :
+ details::VLANCreateIface(bus, objPath, true),
+@@ -41,6 +48,103 @@ Manager::Manager(sdbusplus::bus::bus& bus, const char* objPath,
+ {
+ fs::path confDir(path);
+ setConfDir(confDir);
++ initSupportedPrivilges();
++}
++
++std::string getUserService(sdbusplus::bus::bus& bus, const std::string& intf,
++ const std::string& path)
++{
++ auto mapperCall =
++ bus.new_method_call("xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject");
++
++ mapperCall.append(path);
++ mapperCall.append(std::vector<std::string>({intf}));
++
++ auto mapperResponseMsg = bus.call(mapperCall);
++
++ std::map<std::string, std::vector<std::string>> mapperResponse;
++ mapperResponseMsg.read(mapperResponse);
++
++ if (mapperResponse.begin() == mapperResponse.end())
++ {
++ throw std::runtime_error("ERROR in reading the mapper response");
++ }
++
++ return mapperResponse.begin()->first;
++}
++
++std::string Manager::getUserServiceName()
++{
++ static std::string userMgmtService;
++ if (userMgmtService.empty())
++ {
++ try
++ {
++ userMgmtService =
++ getUserService(bus, userMgrInterface, userMgrObjBasePath);
++ }
++ catch (const std::exception& e)
++ {
++ log<level::ERR>("Exception caught in getUserServiceName.");
++ userMgmtService.clear();
++ }
++ }
++ return userMgmtService;
++}
++
++void Manager::initSupportedPrivilges()
++{
++ std::string userServiceName = getUserServiceName();
++ if (!userServiceName.empty())
++ {
++ auto method = bus.new_method_call(
++ getUserServiceName().c_str(), userMgrObjBasePath,
++ "org.freedesktop.DBus.Properties", "Get");
++ method.append(userMgrInterface, propNameAllPrivileges);
++
++ auto reply = bus.call(method);
++ if (reply.is_method_error())
++ {
++ log<level::DEBUG>("get-property AllPrivileges failed",
++ entry("OBJPATH:%s", userMgrObjBasePath),
++ entry("INTERFACE:%s", userMgrInterface));
++ return;
++ }
++
++ sdbusplus::message::variant<std::vector<std::string>> result;
++ reply.read(result);
++
++ supportedPrivList =
++ sdbusplus::message::variant_ns::get<std::vector<std::string>>(
++ result);
++ }
++
++ // Resgister the signal
++ if (usrMgmtSignal == nullptr)
++ {
++ log<level::DEBUG>("Registering User.Manager propertychange signal.");
++ usrMgmtSignal = std::make_unique<sdbusplus::bus::match_t>(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(userMgrObjBasePath,
++ userMgrInterface),
++ [&](sdbusplus::message::message& msg) {
++ log<level::DEBUG>("UserMgr properties changed signal");
++ std::map<std::string, DbusVariant> props;
++ std::string iface;
++ msg.read(iface, props);
++ for (const auto& t : props)
++ {
++ if (t.first == propNameAllPrivileges)
++ {
++ supportedPrivList = sdbusplus::message::variant_ns::get<
++ std::vector<std::string>>(t.second);
++ }
++ }
++ });
++ }
++ return;
+ }
+
+ bool Manager::createDefaultNetworkFiles(bool force)
+diff --git a/network_manager.hpp b/network_manager.hpp
+index edb341f..5fb9fe8 100644
+--- a/network_manager.hpp
++++ b/network_manager.hpp
+@@ -137,6 +137,12 @@ class Manager : public details::VLANCreateIface
+ return (interfaces.find(intf) != interfaces.end());
+ }
+
++ /** supported privilege list **/
++ std::vector<std::string> supportedPrivList;
++
++ /** @brief initializes the supportedPrivilege List */
++ void initSupportedPrivilges();
++
+ protected:
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+@@ -159,6 +165,9 @@ class Manager : public details::VLANCreateIface
+
+ /** @brief Network Configuration directory. */
+ fs::path confDir;
++
++ /** Get the user management service name dynamically **/
++ std::string getUserServiceName();
+ };
+
+ } // namespace network
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch
new file mode 100644
index 000000000..1b36e9d77
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch
@@ -0,0 +1,506 @@
+From 8aee963295f7da07ae67aa09c4eba3fbd2a6ff19 Mon Sep 17 00:00:00 2001
+From: Johnathan Mantey <johnathanx.mantey@intel.com>
+Date: Thu, 30 Jan 2020 15:07:39 -0800
+Subject: [PATCH] Enhance DHCP beyond just OFF and IPv4/IPv6 enabled.
+
+DHCP is not a binary option. The network interface can have DHCP
+disabled, IPv4 only, IPv6 only, and IPv4/IPv6.
+
+Tested:
+Using dbus-send or busctl:
+Disabled DHCP, and confirmed only link local addresses were present.
+
+Assigned only static addresses. Both with/and without the gateway set
+to 0.0.0.0
+
+Deleted static IPv4 addresses.
+Reassigned static addresses.
+
+Enabled DHCP for ipv4 only, and witnessed a DHCP server assign a valid
+address.
+
+Assigned static IPv4 address.
+Assigned static IPv6 address.
+Confirmed both IPv4 and IPv6 static addresses are active.
+
+Enabled DHCP for ipv6 only, and confirmed the static v4 address
+remains. The ipv6 address is removed, waiting for a DHCP6 server.
+
+Enabled DHCP for both ipv4 and ipv6. IPv4 address was assigned. IPv6
+address is assumed to succeed, as systemd config file enables IPv6
+DHCP.
+
+Change-Id: I2e0ff80ac3a5e88bcff28adac419bf21e37be162
+Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
+
+%% original patch: 0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch
+---
+ Makefile.am | 1 +
+ configure.ac | 1 +
+ ethernet_interface.cpp | 146 ++++++++++++++++++++++---------
+ ethernet_interface.hpp | 31 ++++++-
+ test/test_ethernet_interface.cpp | 3 +-
+ test/test_vlan_interface.cpp | 3 +-
+ types.hpp | 3 +
+ util.cpp | 16 +++-
+ util.hpp | 7 +-
+ vlan_interface.cpp | 2 +-
+ vlan_interface.hpp | 4 +-
+ 11 files changed, 164 insertions(+), 53 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 3bb5e7b..0bbbc8f 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -97,6 +97,7 @@ phosphor_network_manager_CXXFLAGS = \
+ $(SDEVENTPLUS_CFLAGS) \
+ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+ $(PHOSPHOR_LOGGING_CFLAGS) \
++ -DBOOST_ASIO_DISABLE_THREADS \
+ -flto
+
+ if FEATURE_NIC_ETHTOOL
+diff --git a/configure.ac b/configure.ac
+index 12d6caa..fed3e09 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -36,6 +36,7 @@ AC_PATH_PROG([SDBUSPLUSPLUS], [sdbus++])
+ PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging])
+ PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces])
+ PKG_CHECK_MODULES([LIBNL], [libnl-3.0 libnl-genl-3.0])
++AC_CHECK_HEADER(boost/algorithm/string/split.hpp, [], [AC_MSG_ERROR([Could not find boost/algorithm/string/split.hpp])])
+
+ # Checks for header files.
+ AC_CHECK_HEADER(systemd/sd-bus.h, ,\
+diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
+index d6c7bdd..82716f9 100644
+--- a/ethernet_interface.cpp
++++ b/ethernet_interface.cpp
+@@ -3,7 +3,6 @@
+ #include "ethernet_interface.hpp"
+
+ #include "config_parser.hpp"
+-#include "ipaddress.hpp"
+ #include "neighbor.hpp"
+ #include "network_manager.hpp"
+ #include "vlan_interface.hpp"
+@@ -69,10 +68,12 @@ struct EthernetIntfSocket
+
+ int sock{-1};
+ };
++std::map<std::string, std::string> mapDHCPToSystemd = {
++ {"both", "true"}, {"v4", "ipv4"}, {"v6", "ipv6"}, {"none", "false"}};
+
+ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ const std::string& objPath,
+- bool dhcpEnabled, Manager& parent,
++ DHCPConf dhcpEnabled, Manager& parent,
+ bool emitSignal) :
+ Ifaces(bus, objPath.c_str(), true),
+ bus(bus), manager(parent), objPath(objPath)
+@@ -119,6 +120,65 @@ static IP::Protocol convertFamily(int family)
+ throw std::invalid_argument("Bad address family");
+ }
+
++void EthernetInterface::disableDHCP(IP::Protocol protocol)
++{
++ DHCPConf dhcpState = EthernetInterfaceIntf::dHCPEnabled();
++ if (dhcpState == EthernetInterface::DHCPConf::both)
++ {
++ if (protocol == IP::Protocol::IPv4)
++ {
++ dHCPEnabled(EthernetInterface::DHCPConf::v6);
++ }
++ else if (protocol == IP::Protocol::IPv6)
++ {
++ dHCPEnabled(EthernetInterface::DHCPConf::v4);
++ }
++ }
++ else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
++ (protocol == IP::Protocol::IPv4))
++ {
++ dHCPEnabled(EthernetInterface::DHCPConf::none);
++ }
++ else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
++ (protocol == IP::Protocol::IPv6))
++ {
++ dHCPEnabled(EthernetInterface::DHCPConf::none);
++ }
++}
++
++bool EthernetInterface::dhcpIsEnabled(IP::Protocol family, bool ignoreProtocol)
++{
++ return ((EthernetInterfaceIntf::dHCPEnabled() ==
++ EthernetInterface::DHCPConf::both) ||
++ ((EthernetInterfaceIntf::dHCPEnabled() ==
++ EthernetInterface::DHCPConf::v6) &&
++ ((family == IP::Protocol::IPv6) || ignoreProtocol)) ||
++ ((EthernetInterfaceIntf::dHCPEnabled() ==
++ EthernetInterface::DHCPConf::v4) &&
++ ((family == IP::Protocol::IPv4) || ignoreProtocol)));
++}
++
++bool EthernetInterface::dhcpToBeEnabled(IP::Protocol family,
++ std::string& nextDHCPState)
++{
++ return ((nextDHCPState == "true") ||
++ ((nextDHCPState == "ipv6") && (family == IP::Protocol::IPv6)) ||
++ ((nextDHCPState == "ipv4") && (family == IP::Protocol::IPv4)));
++}
++
++bool EthernetInterface::addressIsStatic(IP::AddressOrigin origin)
++{
++ return (
++#ifdef LINK_LOCAL_AUTOCONFIGURATION
++ (origin == IP::AddressOrigin::Static)
++#else
++ (origin == IP::AddressOrigin::Static ||
++ origin == IP::AddressOrigin::LinkLocal)
++#endif
++
++ );
++}
++
+ void EthernetInterface::createIPAddressObjects()
+ {
+ addrs.clear();
+@@ -129,7 +189,7 @@ void EthernetInterface::createIPAddressObjects()
+ {
+ IP::Protocol addressType = convertFamily(addr.addrType);
+ IP::AddressOrigin origin = IP::AddressOrigin::Static;
+- if (dHCPEnabled())
++ if (dhcpIsEnabled(addressType))
+ {
+ origin = IP::AddressOrigin::DHCP;
+ }
+@@ -190,11 +250,11 @@ ObjectPath EthernetInterface::iP(IP::Protocol protType, std::string ipaddress,
+ uint8_t prefixLength, std::string gateway)
+ {
+
+- if (dHCPEnabled())
++ if (dhcpIsEnabled(protType))
+ {
+ log<level::INFO>("DHCP enabled on the interface"),
+ entry("INTERFACE=%s", interfaceName().c_str());
+- dHCPEnabled(false);
++ disableDHCP(protType);
+ }
+
+ IP::AddressOrigin origin = IP::AddressOrigin::Static;
+@@ -469,7 +529,7 @@ bool EthernetInterface::iPv6AcceptRA(bool value)
+ return value;
+ }
+
+-bool EthernetInterface::dHCPEnabled(bool value)
++EthernetInterface::DHCPConf EthernetInterface::dHCPEnabled(DHCPConf value)
+ {
+ if (value == EthernetInterfaceIntf::dHCPEnabled())
+ {
+@@ -685,7 +745,7 @@ void EthernetInterface::loadVLAN(VlanId id)
+ std::string path = objPath;
+ path += "_" + std::to_string(id);
+
+- auto dhcpEnabled =
++ DHCPConf dhcpEnabled =
+ getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
+
+ auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
+@@ -707,7 +767,8 @@ ObjectPath EthernetInterface::createVLAN(VlanId id)
+ path += "_" + std::to_string(id);
+
+ auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
+- bus, path.c_str(), false, id, *this, manager);
++ bus, path.c_str(), EthernetInterface::DHCPConf::none, id, *this,
++ manager);
+
+ // write the device file for the vlan interface.
+ vlanIntf->writeDeviceFile();
+@@ -780,8 +841,6 @@ void EthernetInterface::writeConfigurationFile()
+ // write all the static ip address in the systemd-network conf file
+
+ using namespace std::string_literals;
+- using AddressOrigin =
+- sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
+ namespace fs = std::experimental::filesystem;
+
+ // if there is vlan interafce then write the configuration file
+@@ -855,42 +914,45 @@ void EthernetInterface::writeConfigurationFile()
+ }
+
+ // Add the DHCP entry
+- auto value = dHCPEnabled() ? "true"s : "false"s;
+- stream << "DHCP="s + value + "\n";
++ std::string value = convertForMessage(EthernetInterfaceIntf::dHCPEnabled());
++ std::string::size_type loc = value.rfind(".");
++ std::string requestedDHCPState = value.substr(loc + 1);
++ std::string mappedDHCPState = mapDHCPToSystemd[requestedDHCPState];
++ stream << "DHCP="s + mappedDHCPState + "\n";
++
++ bool dhcpv6Requested = dhcpToBeEnabled(IP::Protocol::IPv6, mappedDHCPState);
++ bool dhcpv4Requested = dhcpToBeEnabled(IP::Protocol::IPv4, mappedDHCPState);
++ // Static IP addresses
++ for (const auto& addr : addrs)
++ {
++ bool isValidIPv4 = isValidIP(AF_INET, addr.second->address());
++ bool isValidIPv6 = isValidIP(AF_INET6, addr.second->address());
++ if (((!dhcpv4Requested && isValidIPv4) ||
++ (!dhcpv6Requested && isValidIPv6)) &&
++ addressIsStatic(addr.second->origin()))
++ {
++ // Process all static addresses
++ std::string address = addr.second->address() + "/" +
++ std::to_string(addr.second->prefixLength());
++
++ // build the address entries. Do not use [Network] shortcuts to
++ // insert address entries.
++ stream << "[Address]\n";
++ stream << "Address=" << address << "\n";
++ }
++ }
+
+- // When the interface configured as dhcp, we don't need below given entries
+- // in config file.
+- if (dHCPEnabled() == false)
++ if (manager.getSystemConf())
+ {
+- // Static
+- for (const auto& addr : addrs)
++ const auto& gateway = manager.getSystemConf()->defaultGateway();
++ if (!gateway.empty())
+ {
+- if (addr.second->origin() == AddressOrigin::Static
+-#ifndef LINK_LOCAL_AUTOCONFIGURATION
+- || addr.second->origin() == AddressOrigin::LinkLocal
+-#endif
+- )
+- {
+- std::string address =
+- addr.second->address() + "/" +
+- std::to_string(addr.second->prefixLength());
+-
+- stream << "Address=" << address << "\n";
+- }
++ stream << "Gateway=" << gateway << "\n";
+ }
+-
+- if (manager.getSystemConf())
++ const auto& gateway6 = manager.getSystemConf()->defaultGateway6();
++ if (!gateway6.empty())
+ {
+- const auto& gateway = manager.getSystemConf()->defaultGateway();
+- if (!gateway.empty())
+- {
+- stream << "Gateway=" << gateway << "\n";
+- }
+- const auto& gateway6 = manager.getSystemConf()->defaultGateway6();
+- if (!gateway6.empty())
+- {
+- stream << "Gateway=" << gateway6 << "\n";
+- }
++ stream << "Gateway=" << gateway6 << "\n";
+ }
+ }
+
+@@ -1001,7 +1063,7 @@ std::string EthernetInterface::mACAddress(std::string value)
+
+ void EthernetInterface::deleteAll()
+ {
+- if (EthernetInterfaceIntf::dHCPEnabled())
++ if (dhcpIsEnabled(IP::Protocol::IPv4, true))
+ {
+ log<level::INFO>("DHCP enabled on the interface"),
+ entry("INTERFACE=%s", interfaceName().c_str());
+diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
+index 6344533..3f7fd31 100644
+--- a/ethernet_interface.hpp
++++ b/ethernet_interface.hpp
+@@ -94,7 +94,7 @@ class EthernetInterface : public Ifaces
+ * send.
+ */
+ EthernetInterface(sdbusplus::bus::bus& bus, const std::string& objPath,
+- bool dhcpEnabled, Manager& parent,
++ DHCPConf dhcpEnabled, Manager& parent,
+ bool emitSignal = true);
+
+ /** @brief Function used to load the nameservers.
+@@ -164,7 +164,34 @@ class EthernetInterface : public Ifaces
+ }
+
+ /** Set value of DHCPEnabled */
+- bool dHCPEnabled(bool value) override;
++ DHCPConf dHCPEnabled(DHCPConf value) override;
++
++ /** @brief Determines if DHCP is active for the IP::Protocol supplied.
++ * @param[in] protocol - Either IPv4 or IPv6
++ * @param[in] ignoreProtocol - Allows IPv4 and IPv6 to be checked using a
++ * single call.
++ * @returns true/false value if DHCP is active for the input protocol
++ */
++ bool dhcpIsEnabled(IP::Protocol protocol, bool ignoreProtocol = false);
++
++ /** @brief Determines if DHCP will be active following next reconfig
++ * @param[in] protocol - Either IPv4 or IPv6
++ * @param[in] nextDHCPState - The new DHCP mode to take affect
++ * @returns true/false value if DHCP is active for the input protocol
++ */
++ bool dhcpToBeEnabled(IP::Protocol family, std::string& nextDHCPState);
++
++ /** @brief Determines if the address is manually assigned
++ * @param[in] origin - The origin entry of the IP::Address
++ * @returns true/false value if the address is static
++ */
++ bool addressIsStatic(IP::AddressOrigin origin);
++
++ /** @brief Selectively disables DHCP
++ * @param[in] protocol - The IPv4 or IPv6 protocol to return to static
++ * addressing mode
++ */
++ void disableDHCP(IP::Protocol protocol);
+
+ /** Retrieve Link State */
+ bool linkUp() const override;
+diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
+index d0beef7..3e2f9ff 100644
+--- a/test/test_ethernet_interface.cpp
++++ b/test/test_ethernet_interface.cpp
+@@ -59,7 +59,8 @@ class TestEthernetInterface : public testing::Test
+ {
+ mock_clear();
+ mock_addIF("test0", 1, mac);
+- return {bus, "/xyz/openbmc_test/network/test0", false, manager, true};
++ return {bus, "/xyz/openbmc_test/network/test0",
++ EthernetInterface::DHCPConf::none, manager};
+ }
+
+ int countIPObjects()
+diff --git a/test/test_vlan_interface.cpp b/test/test_vlan_interface.cpp
+index 1dffc7e..e49b43f 100644
+--- a/test/test_vlan_interface.cpp
++++ b/test/test_vlan_interface.cpp
+@@ -50,7 +50,8 @@ class TestVlanInterface : public testing::Test
+ {
+ mock_clear();
+ mock_addIF("test0", 1);
+- return {bus, "/xyz/openbmc_test/network/test0", false, manager};
++ return {bus, "/xyz/openbmc_test/network/test0",
++ EthernetInterface::DHCPConf::none, manager};
+ }
+
+ void setConfDir()
+diff --git a/types.hpp b/types.hpp
+index 123067a..c4409fe 100644
+--- a/types.hpp
++++ b/types.hpp
+@@ -1,5 +1,7 @@
+ #pragma once
+
++#include "ipaddress.hpp"
++
+ #include <ifaddrs.h>
+ #include <netinet/in.h>
+ #include <systemd/sd-event.h>
+@@ -50,6 +52,7 @@ struct AddrInfo
+ {
+ uint8_t addrType;
+ std::string ipaddress;
++ IP::AddressOrigin origin;
+ uint16_t prefix;
+ };
+
+diff --git a/util.cpp b/util.cpp
+index 13a607f..554d7f6 100644
+--- a/util.cpp
++++ b/util.cpp
+@@ -410,9 +410,11 @@ std::optional<std::string> interfaceToUbootEthAddr(const char* intf)
+ return "eth" + std::to_string(idx) + "addr";
+ }
+
+-bool getDHCPValue(const std::string& confDir, const std::string& intf)
++EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
++ const std::string& intf)
+ {
+- bool dhcp = false;
++ EthernetInterfaceIntf::DHCPConf dhcp =
++ EthernetInterfaceIntf::DHCPConf::none;
+ // Get the interface mode value from systemd conf
+ // using namespace std::string_literals;
+ fs::path confPath = confDir;
+@@ -434,7 +436,15 @@ bool getDHCPValue(const std::string& confDir, const std::string& intf)
+ // There will be only single value for DHCP key.
+ if (values[0] == "true")
+ {
+- dhcp = true;
++ dhcp = EthernetInterfaceIntf::DHCPConf::both;
++ }
++ else if (values[0] == "ipv4")
++ {
++ dhcp = EthernetInterfaceIntf::DHCPConf::v4;
++ }
++ else if (values[0] == "ipv6")
++ {
++ dhcp = EthernetInterfaceIntf::DHCPConf::v6;
+ }
+ return dhcp;
+ }
+diff --git a/util.hpp b/util.hpp
+index 251aa0d..ee11f4e 100644
+--- a/util.hpp
++++ b/util.hpp
+@@ -13,12 +13,16 @@
+ #include <sdbusplus/bus.hpp>
+ #include <string>
+ #include <string_view>
++#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
+
+ namespace phosphor
+ {
+ namespace network
+ {
+
++using EthernetInterfaceIntf =
++ sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
++
+ constexpr auto IPV4_MIN_PREFIX_LENGTH = 1;
+ constexpr auto IPV4_MAX_PREFIX_LENGTH = 32;
+ constexpr auto IPV6_MAX_PREFIX_LENGTH = 64;
+@@ -156,7 +160,8 @@ std::optional<std::string> interfaceToUbootEthAddr(const char* intf);
+ * @param[in] confDir - Network configuration directory.
+ * @param[in] intf - Interface name.
+ */
+-bool getDHCPValue(const std::string& confDir, const std::string& intf);
++EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
++ const std::string& intf);
+
+ namespace internal
+ {
+diff --git a/vlan_interface.cpp b/vlan_interface.cpp
+index 73de4e8..26282cb 100644
+--- a/vlan_interface.cpp
++++ b/vlan_interface.cpp
+@@ -22,7 +22,7 @@ using namespace phosphor::logging;
+ using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
+ VlanInterface::VlanInterface(sdbusplus::bus::bus& bus,
+- const std::string& objPath, bool dhcpEnabled,
++ const std::string& objPath, DHCPConf dhcpEnabled,
+ uint32_t vlanID, EthernetInterface& intf,
+ Manager& parent) :
+ VlanIface(bus, objPath.c_str()),
+diff --git a/vlan_interface.hpp b/vlan_interface.hpp
+index a994d05..37ae7ee 100644
+--- a/vlan_interface.hpp
++++ b/vlan_interface.hpp
+@@ -45,8 +45,8 @@ class VlanInterface : public VlanIface,
+ * @param[in] manager - network manager object.
+ */
+ VlanInterface(sdbusplus::bus::bus& bus, const std::string& objPath,
+- bool dhcpEnabled, uint32_t vlanID, EthernetInterface& intf,
+- Manager& manager);
++ DHCPConf dhcpEnabled, uint32_t vlanID,
++ EthernetInterface& intf, Manager& manager);
+
+ /** @brief Delete this d-bus object.
+ */
+--
+2.25.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend
new file mode 100644
index 000000000..5774d5318
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend
@@ -0,0 +1,12 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += "nlohmann-json boost"
+
+#todo: Appu, fix nobranch
+SRC_URI = "git://github.com/openbmc/phosphor-networkd;nobranch=1"
+SRC_URI += "file://0003-Adding-channel-specific-privilege-to-network.patch \
+ file://0009-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-enabled.patch \
+ "
+SRCREV = "d0679f9bb46670c593061c4aaebec2a577cdd5c3"
+
+EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb
new file mode 100644
index 000000000..0dab0fc1a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr.bb
@@ -0,0 +1,24 @@
+SUMMARY = "Enforce static MAC addresses"
+DESCRIPTION = "Set a priority on MAC addresses to run with: \
+ factory-specified > u-boot-specified > random"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+PV = "1.0"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI = "\
+ file://mac-check \
+ file://${PN}.service \
+ "
+
+inherit obmc-phosphor-systemd
+
+SYSTEMD_SERVICE_${PN} += "${PN}.service"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/mac-check ${D}${bindir}
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
new file mode 100644
index 000000000..7e81ad63a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
@@ -0,0 +1,109 @@
+#!/bin/sh
+# Copyright 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SOFS_MNT=/var/sofs
+SOFS_MACDIR=${SOFS_MNT}/factory-settings/network/mac
+
+read_hw_mac() {
+ local iface="$1"
+ cat /sys/class/net/"$iface"/address 2>/dev/null
+}
+
+set_hw_mac() {
+ local iface="$1"
+ local mac="$2"
+ ip link show dev "$iface" | grep -q "${iface}:.*\<UP\>" 2>/dev/null
+ local up=$?
+ [[ $up -eq 0 ]] && ip link set dev "$iface" down
+ ip link set dev "$iface" address "$mac"
+ [[ $up -eq 0 ]] && ip link set dev "$iface" up
+}
+
+read_sofs_mac() {
+ local iface="$1"
+ cat "${SOFS_MACDIR}/${iface}" 2>/dev/null
+}
+
+read_fw_env_mac() {
+ local envname="$1"
+ fw_printenv "$envname" 2>/dev/null | sed "s/^$envname=//"
+}
+
+set_fw_env_mac() {
+ local envname="$1"
+ local mac="$2"
+ fw_setenv "$envname" "$mac"
+}
+
+create_macdir() {
+if [ -a ${SOFS_MACDIR} ]; then
+ if [ ! -d ${SOFS_MACDIR} ]; then
+ rm -rf ${SOFS_MACDIR}
+ mkdir -p ${SOFS_MACDIR}
+ fi
+else
+ mkdir -p ${SOFS_MACDIR}
+fi
+return 0
+}
+
+mac_check() {
+ local iface="$1"
+ local envname="$2"
+
+ # Read the MAC address in use by the NIC
+ local hw_mac=$(read_hw_mac "$iface")
+
+ # Read the MAC address stored in the non-volatile file provisioned in
+ # manufacturing.
+ local sofs_mac=$(read_sofs_mac "$iface")
+
+ if [ -n "$sofs_mac" ] && [ "$hw_mac" != "$sofs_mac" ]; then
+ # A factory assigned address was found, and it is newly assigned.
+ # Update the active interface and save the new value to the u-boot
+ # environment.
+ set_hw_mac "$iface" "$sofs_mac"
+ set_fw_env_mac "$envname" "$sofs_mac"
+ return $?
+ elif [ -n "$hw_mac" ]; then
+ # Read the MAC address stored by U-Boot
+ local fw_env_mac=$(read_fw_env_mac "$envname")
+ if [ -z "$fw_env_mac" ] || [ "$fw_env_mac" != "$hw_mac" ]; then
+ set_fw_env_mac "$envname" "$hw_mac"
+ return $?
+ fi
+ else
+ # Could not identify a MAC address
+ return 255
+ fi
+ return 0
+}
+
+create_macdir
+
+error=0
+first_error_seen=0
+
+while read IFACE UBDEV; do
+ mac_check "$IFACE" "$UBDEV"
+ error=$?
+ if [ $error -ne 0 ] && [ $first_error_seen -eq 0 ]; then
+ first_error_seen=$error
+ fi
+done <<-END_CONF
+ eth0 eth1addr
+ eth1 ethaddr
+END_CONF
+exit $first_error_seen
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service
new file mode 100644
index 000000000..86371db11
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/static-mac-addr.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Enforce Static MAC addr mapping
+
+[Service]
+Type=oneshot
+Restart=no
+ExecStart=/usr/bin/mac-check
+
+[Install]
+WantedBy=network.target
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/beepcode-mgr.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/beepcode-mgr.bb
new file mode 100644
index 000000000..1bf81d953
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/beepcode-mgr.bb
@@ -0,0 +1,25 @@
+
+SUMMARY = "Beep code manager service"
+DESCRIPTION = "The beep code manager service will provide a method for beep code"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://beepcode_mgr.cpp \
+ "
+PV = "0.1"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+S = "${WORKDIR}"
+
+SYSTEMD_SERVICE_${PN} = "beepcode-mgr.service"
+
+inherit cmake
+inherit obmc-phosphor-systemd
+
+DEPENDS += " \
+ sdbusplus \
+ phosphor-logging \
+ boost \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/.clang-format
new file mode 100644
index 000000000..dd2770837
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/.clang-format
@@ -0,0 +1,98 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/CMakeLists.txt
new file mode 100644
index 000000000..472257279
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
+project (beepcode-mgr CXX)
+set (CMAKE_CXX_STANDARD 17)
+set (CMAKE_CXX_STANDARD_REQUIRED ON)
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+# boost support
+find_package (Boost REQUIRED)
+# pkg_check_modules(Boost boost REQUIRED)
+include_directories (${Boost_INCLUDE_DIRS})
+add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY)
+add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED)
+add_definitions (-DBOOST_ALL_NO_LIB)
+add_definitions (-DBOOST_NO_RTTI)
+add_definitions (-DBOOST_NO_TYPEID)
+add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
+
+# import sdbusplus
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED)
+include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS})
+link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS})
+
+# import phosphor-logging
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (LOGGING phosphor-logging REQUIRED)
+include_directories (${LOGGING_INCLUDE_DIRS})
+link_directories (${LOGGING_LIBRARY_DIRS})
+
+add_executable (beepcode-mgr beepcode_mgr.cpp)
+
+target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${SDBUSPLUSPLUS_LIBRARIES}
+ phosphor_logging)
+
+install (TARGETS beepcode-mgr DESTINATION bin)
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode-mgr.service b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode-mgr.service
new file mode 100644
index 000000000..8099e2541
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode-mgr.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Beep code manager
+
+[Service]
+Restart=always
+RestartSec=2
+ExecStart=/usr/bin/beepcode-mgr
+StartLimitInterval=0
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp
new file mode 100644
index 000000000..2940610da
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/beepcode_mgr.cpp
@@ -0,0 +1,325 @@
+/* Copyright 2019 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <linux/input.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <chrono>
+#include <iostream>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+static constexpr uint32_t defaultBeepFrequence = 2000;
+static constexpr uint32_t defaultBeepDurationMs = 300;
+// Duration between two beeps
+static constexpr uint32_t defaultInterBeepDurationMs = 300;
+// Duration between two 4-bit digitals
+static constexpr uint32_t defaultInterDigitBeepDurationMs = 800;
+// Duration between two patterns
+static constexpr uint32_t defaultPostBeepDurationMs = 1000;
+
+static constexpr uint8_t offBeepState = 0;
+static constexpr uint8_t onBeepState = 1;
+// finish 1 bit beep
+static constexpr uint8_t interBeepState = 2;
+// finish 4 bits beep
+static constexpr uint8_t interDigitBeepState = 3;
+// finish all bits beep
+static constexpr uint8_t postBeepState = 4;
+
+static const std::vector<uint32_t> beepDelayTable = {
+ 0, defaultBeepDurationMs, defaultInterBeepDurationMs,
+ defaultInterDigitBeepDurationMs, defaultPostBeepDurationMs};
+
+static constexpr uint32_t bpBitCount = 4;
+static constexpr uint32_t bpShiftCount = 32;
+static constexpr uint32_t bpMask = 0xf0000000;
+
+// beep code priority
+static constexpr uint8_t beepOff = 0;
+static constexpr uint8_t beepVRWatchdogTimeout = 1;
+static constexpr uint8_t beepPSUFailure = 2;
+static constexpr uint8_t beepCPUMIssing = 3;
+static constexpr uint8_t beepCPUCatError = 4;
+static constexpr uint8_t beepCPUErr2 = 5;
+static constexpr uint8_t beepVoltageMismatch = 6;
+static constexpr uint8_t beepCPUConfigError = 7;
+static constexpr uint8_t beepPowerFail = 8;
+static constexpr uint8_t beepPowerGoodTimeOut = 9;
+static constexpr uint8_t beepMax = 10;
+
+// priority, abbrev name map
+static const std::map<uint8_t, std::string> beepCodeNameList = {
+ {beepVRWatchdogTimeout, "VRWatchdogTimeout"},
+ {beepPSUFailure, "PSUFailure"},
+ {beepCPUMIssing, "CPUMissing"},
+ {beepCPUCatError, "CPUCatError"},
+ {beepCPUErr2, "CPUErr2"},
+ {beepVoltageMismatch, "VoltageMismatch"},
+ {beepCPUConfigError, "CPUConfigError"},
+ {beepPowerFail, "PowerFail"},
+ {beepPowerGoodTimeOut, "PowerGoodTimeOut"},
+};
+
+// priority, code pattern map
+static const std::map<uint8_t, std::string> beepCodePatternList = {
+ {beepVRWatchdogTimeout, "1-5-1-2"}, {beepPSUFailure, "1-5-1-4"},
+ {beepCPUMIssing, "1-5-2-1"}, {beepCPUCatError, "1-5-2-2"},
+ {beepCPUErr2, "1-5-2-3"}, {beepVoltageMismatch, "1-5-2-4"},
+ {beepCPUConfigError, "1-5-2-5"}, {beepPowerFail, "1-5-4-2"},
+ {beepPowerGoodTimeOut, "1-5-4-4"},
+};
+
+static const std::vector<uint32_t> beepCodeTable = {
+ 0, 0x1512, 0x1514, 0x1521, 0x1522, 0x1523, 0x1524, 0x1525, 0x1542, 0x1544};
+
+static constexpr char bpDevName[] = "/dev/input/event0";
+static constexpr char bpBusName[] = "xyz.openbmc_project.BeepCode";
+static constexpr char bpObjName[] = "/xyz/openbmc_project/BeepCode";
+static constexpr char bpIntfName[] = "xyz.openbmc_project.BeepCode";
+static constexpr char bpMethodName[] = "Beep";
+
+static std::shared_ptr<sdbusplus::asio::dbus_interface> bpIface;
+static boost::asio::io_service io;
+static auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+
+class Beeper
+{
+ public:
+ Beeper(boost::asio::io_service& io)
+ {
+ timer = std::make_unique<boost::asio::steady_timer>(io);
+ fdBeepDev = -1;
+ currentCount = 0;
+ currentBeepCode = 0;
+ currentMask = bpMask;
+ currentShift = bpShiftCount;
+ currentState = offBeepState;
+ timerRunning = false;
+ }
+
+ ~Beeper()
+ {
+ }
+
+ void beep(const uint8_t& beepPriority)
+ {
+ if (timerRunning)
+ {
+ pendingList.push_back(beepPriority);
+ pendingList.sort(std::greater<uint8_t>());
+ return;
+ }
+
+ performBeep(beepPriority);
+ }
+
+ private:
+ void performBeep(const uint8_t& beepPriority)
+ {
+ currentBeepCode = beepCodeTable[beepPriority];
+ currentCount = 0;
+ currentMask = bpMask;
+ currentShift = bpShiftCount;
+ getCurrentCount();
+ startBeep(defaultBeepFrequence);
+ currentState = onBeepState;
+ currentCount--;
+ timerRunning = true;
+ startBeepTimer();
+ }
+
+ void startBeepTimer()
+ {
+ timer->expires_after(
+ std::chrono::milliseconds(beepDelayTable[currentState]));
+ timer->async_wait([this](const boost::system::error_code& ec) {
+ // timer timeout
+ switch (currentState)
+ {
+ case onBeepState:
+ stopBeep();
+ if (currentCount == 0)
+ {
+ // finished the current 4-bit
+ if (currentBeepCode == 0)
+ {
+ // finished all bits
+ currentState = postBeepState;
+ }
+ else
+ {
+ // start next 4-bit
+ currentState = interDigitBeepState;
+ getCurrentCount();
+ currentCount--;
+ }
+ }
+ else
+ {
+ // still in 4-bit processing
+ currentCount--;
+ currentState = interBeepState;
+ }
+ startBeepTimer();
+ break;
+
+ case interBeepState:
+ case interDigitBeepState:
+ startBeep(defaultBeepFrequence);
+ currentState = onBeepState;
+ startBeepTimer();
+ break;
+ case postBeepState:
+ if (pendingList.size() != 0)
+ {
+ // continue the next new beepcode
+ uint8_t beepPriority = pendingList.front();
+ pendingList.pop_front();
+ performBeep(beepPriority);
+ }
+ else
+ {
+ timerRunning = false;
+ }
+ break;
+
+ default:
+ std::cerr << "Incorrect beepState: "
+ << static_cast<unsigned int>(currentState)
+ << std::endl;
+ break;
+ }
+ });
+ }
+
+ void startBeep(uint32_t freq)
+ {
+ if (fdBeepDev != -1)
+ {
+ std::cerr << "beep device is opening already!" << std::endl;
+ ::close(fdBeepDev);
+ fdBeepDev = -1;
+ }
+
+ if ((fdBeepDev = ::open(bpDevName, O_RDWR | O_CLOEXEC)) < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to open input device");
+ return;
+ }
+
+ struct input_event event;
+ event.type = EV_SND;
+ event.code = SND_TONE;
+ event.value = freq;
+
+ if (::write(fdBeepDev, &event, sizeof(struct input_event)) !=
+ sizeof(struct input_event))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to write a tone sound event");
+ ::close(fdBeepDev);
+ fdBeepDev = -1;
+ return;
+ }
+ return;
+ }
+
+ void stopBeep()
+ {
+ if (fdBeepDev == -1)
+ {
+ std::cerr << "beep device is closed!" << std::endl;
+ return;
+ }
+
+ ::close(fdBeepDev);
+ fdBeepDev = -1;
+ }
+
+ // Split the beep code based on bpBitCount, for example 0x1544,
+ // currentCount=1, 5, 4, 4
+ void getCurrentCount()
+ {
+ while (currentCount == 0)
+ {
+ currentCount = currentMask & currentBeepCode;
+ currentShift -= bpBitCount;
+ currentCount >>= currentShift;
+ currentBeepCode = currentBeepCode & ~currentMask;
+ currentMask >>= bpBitCount;
+ if (currentMask == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ int fdBeepDev;
+ bool timerRunning;
+ uint32_t currentCount;
+ uint32_t currentBeepCode;
+ uint32_t currentMask;
+ uint32_t currentShift;
+ uint8_t currentState;
+ std::unique_ptr<boost::asio::steady_timer> timer;
+ std::list<uint8_t> pendingList;
+};
+
+static Beeper beeper(io);
+
+// dbus method
+static void beep(const uint8_t& beepPriority)
+{
+ if ((beepPriority >= beepMax) || (beepPriority == beepOff))
+ {
+ std::cerr << "Incorrect input: "
+ << static_cast<unsigned int>(beepPriority) << std::endl;
+ return;
+ }
+
+ // Log into redfish event log
+ sd_journal_send("MESSAGE=BeepCode: Priority=%d", beepPriority,
+ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
+ "OpenBMC.0.1.BeepCode", "REDFISH_MESSAGE_ARGS=%d",
+ beepPriority, NULL);
+
+ beeper.beep(beepPriority);
+
+ return;
+}
+
+int main(int argc, char** argv)
+{
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "Starting BeepCode service");
+
+ conn->request_name(bpBusName);
+ sdbusplus::asio::object_server server =
+ sdbusplus::asio::object_server(conn);
+ bpIface = server.add_interface(bpObjName, bpIntfName);
+
+ bpIface->register_property("BeepCodeNameList", beepCodeNameList,
+ sdbusplus::asio::PropertyPermission::readOnly);
+ bpIface->register_property("BeepCodePatternList", beepCodePatternList,
+ sdbusplus::asio::PropertyPermission::readOnly);
+ bpIface->register_method(bpMethodName, beep);
+ bpIface->initialize();
+
+ io.run();
+ return 0;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/cmake-format.json b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/cmake-format.json
new file mode 100644
index 000000000..583c255a3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/beepcode-mgr/files/cmake-format.json
@@ -0,0 +1,12 @@
+{
+ "enum_char": ".",
+ "line_ending": "unix",
+ "bullet_char": "*",
+ "max_subargs_per_line": 99,
+ "command_case": "lower",
+ "tab_size": 4,
+ "line_width": 80,
+ "separate_fn_name_with_space": true,
+ "dangle_parens": true,
+ "separate_ctrl_name_with_space": true
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
new file mode 100644
index 000000000..577e5aaaa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,6 @@
+# this is here just to bump faster than upstream
+SRC_URI = "git://github.com/openbmc/entity-manager.git"
+SRCREV = "fa8d322d08743b3ca0e6f575011814058e18f011"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb
new file mode 100644
index 000000000..089aaf59f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb
@@ -0,0 +1,26 @@
+
+SUMMARY = "PCH BMC time service"
+DESCRIPTION = "This service will read date/time from PCH device periodically, and set the BMC system time accordingly"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://pch-time-sync.cpp \
+ "
+PV = "0.1"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+S = "${WORKDIR}"
+
+SYSTEMD_SERVICE_${PN} = "pch-time-sync.service"
+
+inherit cmake
+inherit obmc-phosphor-systemd
+
+DEPENDS += " \
+ sdbusplus \
+ phosphor-logging \
+ boost \
+ i2c-tools \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format
new file mode 100644
index 000000000..dd2770837
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format
@@ -0,0 +1,98 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt
new file mode 100644
index 000000000..a4cf8155f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
+project (pch-time-sync CXX)
+set (CMAKE_CXX_STANDARD 17)
+set (CMAKE_CXX_STANDARD_REQUIRED ON)
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+# boost support
+find_package (Boost REQUIRED)
+# pkg_check_modules(Boost boost REQUIRED)
+include_directories (${Boost_INCLUDE_DIRS})
+add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY)
+add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED)
+add_definitions (-DBOOST_ALL_NO_LIB)
+add_definitions (-DBOOST_NO_RTTI)
+add_definitions (-DBOOST_NO_TYPEID)
+add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
+
+# import sdbusplus
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED)
+include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS})
+link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS})
+
+# import phosphor-logging
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (LOGGING phosphor-logging REQUIRED)
+include_directories (${LOGGING_INCLUDE_DIRS})
+link_directories (${LOGGING_LIBRARY_DIRS})
+
+add_executable (pch-time-sync pch-time-sync.cpp)
+
+target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${SDBUSPLUSPLUS_LIBRARIES}
+ phosphor_logging)
+target_link_libraries (${PROJECT_NAME} i2c)
+
+install (TARGETS pch-time-sync DESTINATION bin)
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json
new file mode 100644
index 000000000..583c255a3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json
@@ -0,0 +1,12 @@
+{
+ "enum_char": ".",
+ "line_ending": "unix",
+ "bullet_char": "*",
+ "max_subargs_per_line": 99,
+ "command_case": "lower",
+ "tab_size": 4,
+ "line_width": 80,
+ "separate_fn_name_with_space": true,
+ "dangle_parens": true,
+ "separate_ctrl_name_with_space": true
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp
new file mode 100644
index 000000000..0c1014589
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp
@@ -0,0 +1,265 @@
+/* Copyright 2019 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <time.h>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <chrono>
+#include <iostream>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+extern "C" {
+#include <i2c/smbus.h>
+#include <linux/i2c-dev.h>
+}
+
+static constexpr uint32_t syncIntervalNormalMS = 60000;
+static constexpr uint32_t syncIntervalFastMS = (syncIntervalNormalMS / 2);
+
+static uint32_t syncIntervalMS = syncIntervalNormalMS;
+
+// will update bmc time if the time difference beyond this value
+static constexpr uint8_t timeDiffAllowedSecond = 1;
+
+static inline uint8_t bcd2Decimal(uint8_t hex)
+{
+ uint8_t dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
+ return dec;
+}
+
+class I2CFile
+{
+ private:
+ int fd = -1;
+
+ public:
+ I2CFile(const int& i2cBus, const int& slaveAddr, const int& flags)
+ {
+ std::string i2cDev = "/dev/i2c-" + std::to_string(i2cBus);
+
+ fd = open(i2cDev.c_str(), flags);
+ if (fd < 0)
+ {
+ throw std::runtime_error("Unable to open i2c device.");
+ }
+
+ if (ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
+ {
+ close(fd);
+ fd = -1;
+ throw std::runtime_error("Unable to set i2c slave address.");
+ }
+ }
+
+ uint8_t i2cReadByteData(const uint8_t& offset)
+ {
+ int ret = i2c_smbus_read_byte_data(fd, offset);
+
+ if (ret < 0)
+ {
+ throw std::runtime_error("i2c read failed");
+ }
+ return static_cast<uint8_t>(ret);
+ }
+
+ ~I2CFile()
+ {
+ if (!(fd < 0))
+ {
+ close(fd);
+ }
+ }
+};
+
+class PCHSync
+{
+ private:
+ bool getPCHDate(uint8_t& year, uint8_t& month, uint8_t& day, uint8_t& hour,
+ uint8_t& minute, uint8_t& second)
+ {
+ try
+ {
+ constexpr uint8_t pchDevI2CBusNumber = 0x03;
+ constexpr uint8_t pchDevI2CSlaveAddress = 0x44;
+ constexpr uint8_t pchDevRegRTCYear = 0x0f;
+ constexpr uint8_t pchDevRegRTCMonth = 0x0e;
+ constexpr uint8_t pchDevRegRTCDay = 0x0d;
+ constexpr uint8_t pchDevRegRTCHour = 0x0b;
+ constexpr uint8_t pchDevRegRTCMinute = 0x0a;
+ constexpr uint8_t pchDevRegRTCSecond = 0x09;
+ I2CFile pchDev(pchDevI2CBusNumber, pchDevI2CSlaveAddress,
+ O_RDWR | O_CLOEXEC);
+ year = pchDev.i2cReadByteData(pchDevRegRTCYear);
+ year = bcd2Decimal(year);
+ if (year > 99)
+ {
+ return false;
+ }
+
+ month = pchDev.i2cReadByteData(pchDevRegRTCMonth);
+ month = bcd2Decimal(month);
+ if ((month < 1) || (month > 12))
+ {
+ return false;
+ }
+
+ day = pchDev.i2cReadByteData(pchDevRegRTCDay);
+ day = bcd2Decimal(day);
+ if ((day < 1) || (day > 31))
+ {
+ return false;
+ }
+
+ hour = pchDev.i2cReadByteData(pchDevRegRTCHour);
+ hour = bcd2Decimal(hour);
+ if (hour >= 24)
+ {
+ return false;
+ }
+
+ minute = pchDev.i2cReadByteData(pchDevRegRTCMinute);
+ minute = bcd2Decimal(minute);
+ if (minute >= 60)
+ {
+ return false;
+ }
+
+ second = pchDev.i2cReadByteData(pchDevRegRTCSecond);
+ second = bcd2Decimal(second);
+ if (second >= 60)
+ {
+ return false;
+ }
+ }
+ catch (const std::exception& e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool getSystemTime(time_t& timeSeconds)
+ {
+ struct timespec sTime = {0};
+ int ret = 0;
+
+ ret = clock_gettime(CLOCK_REALTIME, &sTime);
+
+ if (ret != 0)
+ {
+ return false;
+ }
+ timeSeconds = sTime.tv_sec;
+ return true;
+ }
+
+ bool setSystemTime(uint32_t timeSeconds)
+ {
+ struct timespec sTime = {0};
+ int ret = 0;
+
+ sTime.tv_sec = timeSeconds;
+ sTime.tv_nsec = 0;
+
+ ret = clock_settime(CLOCK_REALTIME, &sTime);
+
+ return (ret == 0);
+ }
+
+ bool updateBMCTime()
+ {
+ int ret = 0;
+ time_t BMCTimeSeconds = 0;
+ time_t PCHTimeSeconds = 0;
+ struct tm tm = {0};
+
+ // get PCH and system time
+ if (!getPCHDate(year, month, day, hour, minute, second))
+ {
+ return false;
+ };
+
+ if (!getSystemTime(BMCTimeSeconds))
+ {
+ return false;
+ }
+
+ std::string dateString =
+ "20" + std::to_string(year) + "-" + std::to_string(month) + "-" +
+ std::to_string(day) + " " + std::to_string(hour) + ":" +
+ std::to_string(minute) + ":" + std::to_string(second);
+
+ strptime(dateString.c_str(), "%Y-%m-%d %H:%M:%S", &tm);
+
+ PCHTimeSeconds = mktime(&tm);
+ if (PCHTimeSeconds == -1)
+ {
+ return false;
+ }
+
+ if (std::abs(PCHTimeSeconds - BMCTimeSeconds) > timeDiffAllowedSecond)
+ {
+ if (!setSystemTime(PCHTimeSeconds))
+ {
+ return false;
+ }
+ std::cout << "Update BMC time to " << dateString << std::endl;
+ }
+
+ return true;
+ }
+
+ void startSyncTimer()
+ {
+ if (updateBMCTime())
+ {
+ syncIntervalMS = syncIntervalNormalMS;
+ }
+ else
+ {
+ std::cout << "Update BMC time Fail" << std::endl;
+ syncIntervalMS = syncIntervalFastMS;
+ }
+
+ syncTimer->expires_after(std::chrono::milliseconds(syncIntervalMS));
+ syncTimer->async_wait(
+ [this](const boost::system::error_code& ec) { startSyncTimer(); });
+ }
+
+ std::unique_ptr<boost::asio::steady_timer> syncTimer;
+ uint8_t year, month, day, hour, minute, second;
+
+ public:
+ PCHSync(boost::asio::io_service& io)
+ {
+ syncTimer = std::make_unique<boost::asio::steady_timer>(io);
+ startSyncTimer();
+ }
+
+ ~PCHSync() = default;
+};
+
+int main(int argc, char** argv)
+{
+ boost::asio::io_service io;
+ PCHSync pchSyncer(io);
+
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "Starting PCH time sync service");
+
+ io.run();
+ return 0;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service
new file mode 100644
index 000000000..cf9c3053f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=PCH BMC time sync service
+Conflicts=systemd-timesyncd.service
+
+[Service]
+Restart=always
+RestartSec=10
+ExecStart=/usr/bin/pch-time-sync
+StartLimitInterval=0
+Type=simple
+
+[Install]
+WantedBy=sysinit.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/phosphor-time-manager_git.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/phosphor-time-manager_git.bbappend
new file mode 100644
index 000000000..18780dfdd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/phosphor-time-manager_git.bbappend
@@ -0,0 +1,2 @@
+RDEPENDS_${PN}_remove = "phosphor-settings-manager"
+RDEPENDS_${PN} += " settings"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0001-Reapply-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-e.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0001-Reapply-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-e.patch
new file mode 100644
index 000000000..3344c27dd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0001-Reapply-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-e.patch
@@ -0,0 +1,47 @@
+From 3789a98fda6e3cafd377b0f4fa1c0c40bb94297e Mon Sep 17 00:00:00 2001
+From: Johnathan Mantey <jonathanx.mantey@intel.com>
+Date: Wed, 20 Nov 2019 10:56:44 -0500
+Subject: [PATCH] Reapply: "Enhance DHCP beyond just OFF and IPv4/IPv6
+ enabled."
+
+DHCP is not a binary option. The network interface can have DHCP
+disabled, IPv4 only, IPv6 only, and IPv4/IPv6.
+
+Signed-off-by: Johnathan Mantey <jonathanx.mantey@intel.com>
+
+Reapplied ->
+Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
+Change-Id: I7654116aa3962de253225271190ce4a2fe229ce9
+---
+ .../Network/EthernetInterface.interface.yaml | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+index ee54145..56285ee 100644
+--- a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
++++ b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+@@ -23,7 +23,7 @@ properties:
+ description: >
+ Domain names of the ethernet interface.
+ - name: DHCPEnabled
+- type: boolean
++ type: enum[self.DHCPConf]
+ description: >
+ Address mode of the ethernet interface.
+ - name: Nameservers
+@@ -69,4 +69,11 @@ enumerations:
+ - name: v4
+ - name: v6
+ - name: none
+-
++ - name: DHCPConf
++ description: >
++ A list of the permitted DHCP settings used by systemd.
++ values:
++ - name: both
++ - name: v4
++ - name: v6
++ - name: none
+--
+2.21.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch
new file mode 100644
index 000000000..4cfc4acc8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch
@@ -0,0 +1,65 @@
+From a30a09f58b9ebfb267c0b9cce9ae25994ea025ca Mon Sep 17 00:00:00 2001
+From: cyang29 <cheng.c.yang@intel.com>
+Date: Tue, 17 Jul 2018 16:04:58 +0800
+Subject: [PATCH] Add DBUS interface of CPU properties Feature
+ Support: SMBIOS service interface. CPU information redfish
+ interface. Base on smbios spec DSP0134_3.0.0
+
+Signed-off-by: cyang29 <cheng.c.yang@intel.com>
+---
+ .../Inventory/Item/Cpu.interface.yaml | 41 +++++++++++++++++++
+ 1 files changed, 41 insertions(+)
+
+diff --git a/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml b/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
+index ab29cf3..313eada 100644
+--- a/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
++++ b/xyz/openbmc_project/Inventory/Item/Cpu.interface.yaml
+@@ -1,4 +1,45 @@
+ description: >
+ Implement to provide CPU attributes.
++properties:
++ - name: ProcessorSocket
++ type: string
++ description: >
++ Processor Socket on MotherBoard
++ - name: ProcessorType
++ type: string
++ description: >
++ Processor Type of CPU
++ - name: ProcessorFamily
++ type: string
++ description: >
++ Processor Family of CPU
++ - name: ProcessorManufacturer
++ type: string
++ description: >
++ Processor Manufacturer of CPU
++ - name: ProcessorId
++ type: uint32
++ description: >
++ Processor ID of CPU
++ - name: ProcessorVersion
++ type: string
++ description: >
++ Processor Version of CPU
++ - name: ProcessorMaxSpeed
++ type: uint16
++ description: >
++ Max Speed CPU Can Support
++ - name: ProcessorCharacteristics
++ type: string
++ description: >
++ The Characteristics CPU Has
++ - name: ProcessorCoreCount
++ type: uint16
++ description: >
++ The Count of Core in CPU
++ - name: ProcessorThreadCount
++ type: uint16
++ description: >
++ The Count of Thread CPU Can Support
+
+ # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch
new file mode 100644
index 000000000..c87b2d89d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0007-ipmi-set-BIOS-id.patch
@@ -0,0 +1,32 @@
+From 49debd0955b672d591f35e74119b288bd6df2992 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 24 Jul 2018 11:40:49 +0800
+Subject: [PATCH] [ipmi] set BIOS id
+
+change#2
+add new dbus interface for BIOS attributes
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ xyz/openbmc_project/Inventory/Item/Bios.interface.yaml | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+ create mode 100644 xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+
+diff --git a/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml b/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+new file mode 100644
+index 0000000..d7a6b95
+--- /dev/null
++++ b/xyz/openbmc_project/Inventory/Item/Bios.interface.yaml
+@@ -0,0 +1,9 @@
++description: >
++ Implement to provide BIOS attributes.
++properties:
++ - name: BiosId
++ type: string
++ description: >
++ BIOS ID (version) string
++
++# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch
new file mode 100644
index 000000000..2c9344306
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0010-Increase-the-default-watchdog-timeout-value.patch
@@ -0,0 +1,34 @@
+From 631deef0ca88a77283741edeae8078d2185f414c Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 10 Aug 2018 16:23:13 +0800
+Subject: [PATCH] Increase the default watchdog timeout value
+
+The default timeout for poweron is 30 seconds,
+but currently the host power on needs 120+ seconds
+due to unimplemented ipmi commands for BIOS.
+
+Increase the value as a workaround,
+to avoid the watchdog timeout during power on.
+Will adjust this value in the future
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ xyz/openbmc_project/State/Watchdog.interface.yaml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/State/Watchdog.interface.yaml b/xyz/openbmc_project/State/Watchdog.interface.yaml
+index f76dbf2..402e1a8 100644
+--- a/xyz/openbmc_project/State/Watchdog.interface.yaml
++++ b/xyz/openbmc_project/State/Watchdog.interface.yaml
+@@ -37,7 +37,7 @@ properties:
+ type: uint64
+ description: >
+ Time interval to arm the watchdog, in milli-second.
+- default: 30000
++ default: 600000
+ - name: TimeRemaining
+ type: uint64
+ description: >
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch
new file mode 100644
index 000000000..9052435ca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0012-Add-RestoreDelay-interface-for-power-restore-delay.patch
@@ -0,0 +1,34 @@
+From eeac4cf4528994aeb213d549daf4c033ac9d3bbc Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 24 Aug 2018 17:55:35 +0800
+Subject: [PATCH] Add RestoreDelay interface for power restore delay
+
+Which provide one property "PowerRestoreDelay"
+
+Change-Id: I4e6d3e45948b1e288301b4aa52cc08cace4f1bc2
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../Control/Power/RestoreDelay.interface.yaml | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+
+diff --git a/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml b/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+new file mode 100644
+index 0000000..55ee80a
+--- /dev/null
++++ b/xyz/openbmc_project/Control/Power/RestoreDelay.interface.yaml
+@@ -0,0 +1,11 @@
++description: >
++ Implement to specify power transition behavior on a BMC reset.
++ The implementation based on restore policy and set a delay time
++ for power restore.
++
++properties:
++ - name: PowerRestoreDelay
++ type: uint16
++ description: >
++ The delay time for power restore.
++ Power Restore Delay is NOT applied on power policy is "Always Off"
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch
new file mode 100644
index 000000000..9471c7ab2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch
@@ -0,0 +1,86 @@
+From 7260c24b201759f3a5168eebfee215072c13e641 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Thu, 30 Aug 2018 16:22:43 +0800
+Subject: [PATCH] Add ErrConfig.yaml interface for processor error
+ configuration.
+
+Which provide 3 properties:
+ ResetCfg
+ type: byte
+ description: >
+ Reset Configuration
+ [0]: CATERR Reset Enabled
+ 0b: Disabled
+ 1b: Enabled
+ [1]: ERR2 Reset Enabled
+ 0b: Disabled
+ 1b: Enabled
+ [7:2]: Reserved
+ ResetErrorOccurrenceCounts
+ type: byte
+ description: >
+ Reset Error Occurrence Counts
+ [0]: Reset CPU Error Counts
+ 0b: Keep CPU Error Counts
+ 1b: Reset all CPU Error Counts to zero
+ [7:1]: Reserved
+ CATERRStatus
+ type: array[byte]
+ description: >
+ For all CPUs including the non-legacy socket CPU
+ CPU CATERR (Core Error) occurrence
+ [5:0]: Error Occurrence Count
+ [7:6]: CPU Status
+ 00b: Disabled
+ 01b: Enabled
+ 11b: Not Present
+
+Change-Id: Ibc5a7a5e15c998e56c04e23b1043d99243a91171
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../Processor/ErrConfig.interface.yaml | 33 +++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+ create mode 100644 xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+
+diff --git a/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml b/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+new file mode 100644
+index 0000000..2304263
+--- /dev/null
++++ b/xyz/openbmc_project/Control/Processor/ErrConfig.interface.yaml
+@@ -0,0 +1,33 @@
++description: >
++ This defines processor error configuration.
++properties:
++ - name: ResetCfg
++ type: byte
++ description: >
++ Reset Configuration
++ [0]: CATERR Reset Enabled
++ 0b: Disabled
++ 1b: Enabled
++ [1]: ERR2 Reset Enabled
++ 0b: Disabled
++ 1b: Enabled
++ [7:2]: Reserved
++
++ - name: ResetErrorOccurrenceCounts
++ type: byte
++ description: >
++ Reset Error Occurrence Counts
++ [0]: Reset CPU Error Counts
++ 0b: Keep CPU Error Counts
++ 1b: Reset all CPU Error Counts to zero
++ [7:1]: Reserved
++ - name: CATERRStatus
++ type: array[byte]
++ description: >
++ For all CPUs including the non-legacy socket CPU
++ CPU CATERR (Core Error) occurrence
++ [5:0]: Error Occurrence Count
++ [7:6]: CPU Status
++ 00b: Disabled
++ 01b: Enabled
++ 11b: Not Present
+--
+2.17.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.patch
new file mode 100644
index 000000000..67fa59090
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.patch
@@ -0,0 +1,57 @@
+From 6e9a19c43acac7d4254910906329d98d7b59085a Mon Sep 17 00:00:00 2001
+From: Ren Yu <yux.ren@intel.com>
+Date: Fri, 24 May 2019 14:55:10 +0800
+Subject: [PATCH] Add the pre-timeout interrupt defined in IPMI spec
+
+The IPMI watchdog pre-timeout interrupt is used to set the different
+pre-timeout interrupt source. Add them as a dbus property,
+IPMI set/get watchdog commands will use it.
+
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+---
+ xyz/openbmc_project/State/Watchdog.interface.yaml | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/xyz/openbmc_project/State/Watchdog.interface.yaml b/xyz/openbmc_project/State/Watchdog.interface.yaml
+index 2fc47d8..6dfa9b9 100644
+--- a/xyz/openbmc_project/State/Watchdog.interface.yaml
++++ b/xyz/openbmc_project/State/Watchdog.interface.yaml
+@@ -33,6 +33,11 @@ properties:
+ description: >
+ The action the watchdog should perform when it expires.
+ default: 'HardReset'
++ - name: PreTimeoutInterrupt
++ type: enum[self.PreTimeoutInterruptAction]
++ description: >
++ The BMC generates the selected interrupt before the timer expires.
++ default: 'None'
+ - name: Interval
+ type: uint64
+ description: >
+@@ -73,6 +78,23 @@ enumerations:
+ description: >
+ Perform a power cycle of the system.
+
++ - name: PreTimeoutInterruptAction
++ description: >
++ The type of PreTimeout Interrupt.
++ values:
++ - name: 'None'
++ description: >
++ Do nothing.
++ - name: 'SMI'
++ description: >
++ SMI.
++ - name: 'NMI'
++ description: >
++ NMI / Diagnostic Interrupt.
++ - name: 'MI'
++ description: >
++ Messaging Interrupt.
++
+ - name: TimerUse
+ description: >
+ The type of timer use.
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0025-Add-PreInterruptFlag-properity-in-DBUS.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0025-Add-PreInterruptFlag-properity-in-DBUS.patch
new file mode 100644
index 000000000..d7e66abd2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0025-Add-PreInterruptFlag-properity-in-DBUS.patch
@@ -0,0 +1,39 @@
+From b7c487750c05dcc081219ccdd4ef539beef6aa30 Mon Sep 17 00:00:00 2001
+From: Ren Yu <yux.ren@intel.com>
+Date: Mon, 29 Jul 2019 10:51:12 +0800
+Subject: [PATCH] Add PreInterruptFlag properity in DBUS.
+
+PreTimeoutInterruptOccurFlag in DBUS would be set 'true'
+when watchdog pre-timeout interrupt occurred.
+
+Tested:
+Enable command(raw 0x06 0x31) that get message flag
+can set right bit about watchdog,
+need record PreTimeoutInterruptOccurFlag
+at xyz.openbmmc_project.State.Watchdog when watchdog
+pre-timeout interrupt occurred.
+
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+---
+ xyz/openbmc_project/State/Watchdog.interface.yaml | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/xyz/openbmc_project/State/Watchdog.interface.yaml b/xyz/openbmc_project/State/Watchdog.interface.yaml
+index bf4cca0..6579368 100644
+--- a/xyz/openbmc_project/State/Watchdog.interface.yaml
++++ b/xyz/openbmc_project/State/Watchdog.interface.yaml
+@@ -59,6 +59,11 @@ properties:
+ description: >
+ The timer user at the time of expiration.
+ default: 'Reserved'
++ - name: PreTimeoutInterruptOccurFlag
++ type: boolean
++ description: >
++ PreTimeoutInterruptOccurFlag that preTimeoutInterrupt action occurred.
++ default: false
+
+ enumerations:
+ - name: Action
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0026-Add-StandbySpare-support-for-software-inventory.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0026-Add-StandbySpare-support-for-software-inventory.patch
new file mode 100644
index 000000000..36c63ec58
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0026-Add-StandbySpare-support-for-software-inventory.patch
@@ -0,0 +1,55 @@
+From 0d6556539be9bda478a3cabb6127eace5764fa11 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Wed, 15 Jan 2020 10:01:04 +0800
+Subject: [PATCH] Add StandbySpare support for software inventory
+
+Add support to allow update for active / recovery
+regions of specified firmware. This update enables
+the backend modules to advertise whether the
+software object is active or recovery (StandbySpare)
+image.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ xyz/openbmc_project/Software/Activation.interface.yaml | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/xyz/openbmc_project/Software/Activation.interface.yaml b/xyz/openbmc_project/Software/Activation.interface.yaml
+index efeeeb6..6c9ce75 100644
+--- a/xyz/openbmc_project/Software/Activation.interface.yaml
++++ b/xyz/openbmc_project/Software/Activation.interface.yaml
+@@ -28,12 +28,20 @@ enumerations:
+ - name: Activating
+ description: >
+ The Software.Version is in the process of being Activated.
++ - name: ActivatingAsStandbySpare
++ description: >
++ The Software.Version is in the process of being processed
++ as StandbySpare.
+ - name: Active
+ description: >
+ The Software.Version is currently Active.
+ - name: Failed
+ description: >
+ The Software.Version failed during or after Activation.
++ - name: StandbySpare
++ description: >
++ The Software.Version is part of a redundancy set and awaits
++ a failover or external action to activate.
+ - name: Staged
+ description: >
+ The Software.Version is currently in staged flash area.
+@@ -48,6 +56,10 @@ enumerations:
+ - name: Active
+ description: >
+ The Software.Version has been requested for Activation.
++ - name: StandbySpare
++ description: >
++ The Software.Version has been requested to be enabled as
++ StandbySpare.
+ # TODO: Specify "EAGAIN" type error when requested is unable to be acted on
+ # due to current system state. Currently, sdbusplus does not support
+ # errors on properties.
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch
new file mode 100644
index 000000000..fba025207
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0028-MCTP-Daemon-D-Bus-interface-definition.patch
@@ -0,0 +1,459 @@
+From 7a3fc3a969d2a187be20a972a5a7209944731bea Mon Sep 17 00:00:00 2001
+From: "Kowalski, Mariusz" <mariusz.kowalski@intel.com>
+Date: Thu, 27 Feb 2020 15:48:56 +0100
+Subject: [PATCH] MCTP Daemon D-Bus interface definition.
+
+This interface definition was created on base of the MCTP design
+proposed in this document:
+https://gerrit.openbmc-project.xyz/c/openbmc/docs/+/28424/9/designs/mctp.md
+
+Signed-off-by: Mariusz Kowalski <mariusz.kowalski@intel.com>
+Signed-off-by: Karol Wachowski <karol.wachowski@intel.com>
+Change-Id: Ida66f8ffcf00003655edcb0fb0112202797b8e1a
+---
+ xyz/openbmc_project/MCTP/Base.interface.yaml | 231 ++++++++++++++++++
+ .../MCTP/Binding/PCIe.interface.yaml | 29 +++
+ .../MCTP/Binding/SMBus.interface.yaml | 17 ++
+ .../MCTP/BusOwner.interface.yaml | 15 ++
+ .../MCTP/Endpoint.interface.yaml | 19 ++
+ xyz/openbmc_project/MCTP/README.md | 38 +++
+ .../MCTP/SupportedMessageTypes.interface.yaml | 36 +++
+ 7 files changed, 385 insertions(+)
+ create mode 100644 xyz/openbmc_project/MCTP/Base.interface.yaml
+ create mode 100644 xyz/openbmc_project/MCTP/Binding/PCIe.interface.yaml
+ create mode 100644 xyz/openbmc_project/MCTP/Binding/SMBus.interface.yaml
+ create mode 100644 xyz/openbmc_project/MCTP/BusOwner.interface.yaml
+ create mode 100644 xyz/openbmc_project/MCTP/Endpoint.interface.yaml
+ create mode 100644 xyz/openbmc_project/MCTP/README.md
+ create mode 100644 xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml
+
+diff --git a/xyz/openbmc_project/MCTP/Base.interface.yaml b/xyz/openbmc_project/MCTP/Base.interface.yaml
+new file mode 100644
+index 0000000..9a649a5
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/Base.interface.yaml
+@@ -0,0 +1,231 @@
++description: >
++ Mandatory interface for each instance of the MCTP Daemon to expose
++ the base MCTP daemon and medium type interfaces.
++
++methods:
++ - name: SendMctpMessagePayload
++ description: >
++ Sends message over MCTP interface
++ parameters:
++ - name: DestinationEID
++ type: byte
++ description: >
++ Destination Endpoint ID. The logical address used to route MCTP
++ messages to a specific MCTP endpoint.
++ - name: MsgTag
++ type: byte
++ description: >
++ Message tag. Field that, along with the Source Endpoint IDs and the
++ Tag Owner (TO) field, identifies a unique message at the MCTP
++ transport level.
++ - name: TagOwner
++ type: boolean
++ description: >
++ Tag Owner bit identifies whether the message tag was originated by
++ the endpoint that is the source of the message or by the endpoint
++ that is the destination of the message.
++ - name: Payload
++ type: array[byte]
++ description: Payload of message.
++ returns:
++ - name: Status
++ type: byte
++ description: 0 - if success
++ errors:
++ - xyz.openbmc_project.Common.Error.Timeout
++ - xyz.openbmc_project.Common.Error.InvalidArgument
++ - xyz.openbmc_project.Common.Error.InternalFailure
++
++ - name: SendMctpMessageFileDescriptor
++ description: >
++ Sends message over MCTP interface
++ parameters:
++ - name: DestinationEID
++ type: byte
++ description: >
++ Destination Endpoint ID. The logical address used to route MCTP
++ messages to a specific MCTP endpoint.
++ - name: MsgTag
++ type: byte
++ description: >
++ Message tag. Field that, along with the Source Endpoint IDs and the
++ Tag Owner (TO) field, identifies a unique message at the MCTP
++ transport level.
++ - name: TagOwner
++ type: boolean
++ description: >
++ Tag Owner bit identifies whether the message tag was originated by
++ the endpoint that is the source of the message or by the endpoint
++ that is the destination of the message.
++ - name: FileDescriptor
++ type: unixfd
++ description: File descriptor of message.
++ returns:
++ - name: Status
++ type: byte
++ description: 0 - if success
++ errors:
++ - xyz.openbmc_project.Common.Error.Timeout
++ - xyz.openbmc_project.Common.Error.InvalidArgument
++ - xyz.openbmc_project.Common.Error.InternalFailure
++
++signals:
++ - name: MessageReceivedSignal
++ description: >
++ Signal indicating upper layers about arrival of a MCTP message.
++ properties:
++ - name: MessageType
++ type: enum[self.MessageTypes]
++ description: >
++ Defines the values for the Message Type field for different message
++ types transported through MCTP.
++ - name: SrcEid
++ type: byte
++ description: >
++ Source Endpoint ID. The logical address used to route MCTP messages
++ to a specific MCTP endpoint.
++ - name: MsgTag
++ type: byte
++ description: >
++ Message tag. Field that, along with the Source Endpoint IDs and the
++ Tag Owner (TO) field, identifies a unique message at the MCTP
++ transport level.
++ - name: TagOwner
++ type: boolean
++ description: >
++ Tag Owner bit identifies whether the message tag was originated by
++ the endpoint that is the source of the message or by the endpoint
++ that is the destination of the message.
++ - name: Payload
++ type: array[byte]
++ description: Payload of message.
++
++properties:
++ - name: Eid
++ type: byte
++ description: >
++ Endpoint ID. The logical address used to route MCTP messages to a
++ specific MCTP endpoint.
++
++ - name: BindingID
++ type: enum[self.BindingTypes]
++
++ - name: BindingMediumID
++ type: enum[self.MctpPhysicalMediumIdentifiers]
++
++ - name: StaticEid
++ type: boolean
++ description: Support for statically/dynamicly allocated IDs
++
++ - name: Uuid
++ type: array[byte]
++ description: Guid - 16bytes
++
++ - name: BindingMode
++ type: enum[self.BindingModeTypes]
++ description: Bus Owner / Endpoint / Bridge
++
++enumerations:
++ - name: BindingTypes
++ description: >
++ All other values than described are reserved.
++ values:
++ - name: MctpOverSmbus
++ - name: MctpOverPcieVdm
++ - name: MctpOverUsb
++ description: Reserved for MCTP over USB
++ - name: MctpOverKcs
++ - name: MctpOverSerial
++ - name: VendorDefined
++
++ - name: MctpPhysicalMediumIdentifiers
++ description: >
++ Identifies MCTP physical medium identifiers. see DSP0239.
++ values:
++ - name: Smbus
++ descritpion: SMBus 2.0 100 kHz compatible
++ - name: SmbusI2c
++ descritpion: SMBus 2.0 + I2C 100 kHz compatible
++ - name: I2cCompatible
++ description: I2C 100 kHz compatible (Standard-mode)
++ - name: Smbus3OrI2c400khzCompatible
++ description: SMBus 3.0 or I2C 400 kHz compatible (Fast-mode)
++ - name: Smbus3OrI2c1MhzCompatible
++ description: SMBus 3.0 or I2C 1 MHz compatible (Fast-mode Plus)
++ - name: I2c3Mhz4Compatible
++ description: I2C 3.4 MHz compatible (High-speed mode)
++ - name: Pcie11
++ description: PCIe revision 1.1 compatible
++ - name: Pcie2
++ description: PCIe revision 2.0 compatible
++ - name: Pcie21
++ description: PCIe revision 2.1 compatible
++ - name: Pcie3
++ description: PCIe revision 3.0 compatible
++ - name: Pcie4
++ description: PCIe revision 4.0 compatible
++ - name: Pcie5
++ description: PCIe revision 4.0 compatible
++ - name: PciCompatible
++ description: >
++ PCI compatible (PCI 1.0,2.0,2.1,2.2,2.3,3.0,PCI-X 1.0, PCI-X 2.0)
++ - name: Usb11Compatible
++ description: USB 1.1 compatible
++ - name: Usb20Compatible
++ description: USB 2.0 compatible
++ - name: Usb30Compatible
++ description: USB 3.0 compatible
++ - name: NcSiOverRbt
++ description: >
++ NC-SI over RBT (A physical interface based on RMII as defined in
++ DSP0222)
++ - name: KcsLegacy
++ description: KCS1 / Legacy (Fixed Address Decoding)
++ - name: KcsPci
++ description: KCS1 / PCI (Base Class 0xC0 Subclass 0x01)
++ - name: SerialHostLegacy
++ description: Serial Host2 / Legacy (Fixed Address Decoding)
++ - name: SerialHostPci
++ description: Serial Host2 / PCI (Base Class 0x07 Subclass 0x00)
++ - name: AsynchronousSerial
++ description: Asynchronous Serial (Between MCs and IMDs)
++ - name: I3cSDR
++ description: I3C 12.5 MHz compatible (SDR)
++ - name: I3cHDRDDR
++ description: I3C 25 MHz compatible (HDR-DDR)
++
++ - name: BindingModeTypes
++ values:
++ - name: Endpoint
++ description: >
++ An MCTP communication terminus. An MCTP endpoint is a terminus or
++ origin of MCTP packets or messages. That is, the combined
++ functionality within a physical device that communicates using the
++ MCTP transport protocol and handles MCTP control commands. This
++ includes MCTP-capable management controllers and managed devices.
++ Also referred to in this document as "endpoint".
++ - name: BusOwner
++ description: >
++ The party responsible for managing address assignments (can be
++ logical or physical addresses) on a bus (for example, in MCTP, the
++ bus owner is the party responsible for managing EID assignments for
++ a given bus). A bus owner may also have additional media-specific
++ responsibilities, such as assignment of physical addresses.
++ - name: Bridge
++ description: >
++ An MCTP endpoint that can route MCTP messages not destined for
++ itself that it receives on one interconnect onto another without
++ interpreting them. The ingress and egress media at the bridge may
++ be either homogeneous or heterogeneous. Also referred to in this
++ document as a "bridge".
++
++ - name: MessageTypes
++ values:
++ - name: MctpControl
++ - name: PLDM
++ - name: NCSI
++ - name: Ethernet
++ - name: NVMeMgmtMsg
++ - name: SPDM
++ - name: VDPCI
++ - name: VDIANA
+diff --git a/xyz/openbmc_project/MCTP/Binding/PCIe.interface.yaml b/xyz/openbmc_project/MCTP/Binding/PCIe.interface.yaml
+new file mode 100644
+index 0000000..1bd2881
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/Binding/PCIe.interface.yaml
+@@ -0,0 +1,29 @@
++description: >
++ Interface exposed by MCTP daemon for PCIe binding
++
++properties:
++ - name: DiscoveredFlag
++ type: enum[self.DiscoveryFlags]
++ description: >
++ Each endpoint (except the bus owner) on the PCIe bus maintains an
++ internal flag called the Discovered flag. The flag is set to the
++ discovered state when the Set Endpoint ID command is received.
++
++ - name: BDF
++ type: uint16
++ description: >
++ Byte 1 [7:0] Bus number
++ Byte 2 [7:3] Device number [2:0] Function Number
++
++enumerations:
++ - name: DiscoveryFlags
++ description: >
++ The Prepare for Endpoint Discovery message causes each recipient
++ endpoint on the PCIe bus to set their respective Discovered flag to
++ the undiscovered state. For the Prepare for Endpoint Discovery request
++ message, the routing in the physical transport header should be set to
++ 011b (Broadcast from Root Complex).
++ values:
++ - name: Discovered
++ - name: Undiscovered
++ - name: NotApplicable
+diff --git a/xyz/openbmc_project/MCTP/Binding/SMBus.interface.yaml b/xyz/openbmc_project/MCTP/Binding/SMBus.interface.yaml
+new file mode 100644
+index 0000000..9219ad0
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/Binding/SMBus.interface.yaml
+@@ -0,0 +1,17 @@
++description: >
++ Interface exposed by MCTP daemon for SMBus binding
++
++properties:
++ - name: ArpMasterSupport
++ type: boolean
++ description: >
++ The SMBus binding can also run ARP Master protocol and
++ assign SMBus addresses to the devices on the bus.
++
++ - name: BusNumber
++ type: byte
++ description: I2C bus number of the medium used
++
++ - name: SlaveAddress
++ type: byte
++ description: Slave address to be used for this medium
+diff --git a/xyz/openbmc_project/MCTP/BusOwner.interface.yaml b/xyz/openbmc_project/MCTP/BusOwner.interface.yaml
+new file mode 100644
+index 0000000..0853381
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/BusOwner.interface.yaml
+@@ -0,0 +1,15 @@
++description: >
++ Interface exposed by MCTP root object, when executing in Bus Owner mode.
++
++properties:
++ - name: EidPool
++ type: array[struct[byte, byte]]
++ description: Pool of allowed EIDs to be used
++
++ - name: TopMostBusOwner
++ type: boolean
++ description: To indicate whether BMC is topmost Bus Owner
++
++ - name: OwnEidPool
++ type: boolean
++ description: Indicates Eid pool is managed by self
+diff --git a/xyz/openbmc_project/MCTP/Endpoint.interface.yaml b/xyz/openbmc_project/MCTP/Endpoint.interface.yaml
+new file mode 100644
+index 0000000..b7f9a67
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/Endpoint.interface.yaml
+@@ -0,0 +1,19 @@
++description:
++ Interface exposed by discovered MCTP endpoints.
++
++properties:
++ - name: Uuid
++ type: array[byte]
++ description: >
++ Universally unique identifier (UUID), also referred to as a globally
++ unique ID (GUID), for the management controller or management device.
++
++ - name: Mode
++ type: enum[xyz.openbmc_project.MCTP.Base.BindingModeTypes]
++ description: Endpoint / BusOwner / Bridge
++
++ - name: NetworkId
++ type: uint16
++ description: >
++ MCTP network ID a unique identifier to distinguish each independent
++ MCTP network within a platform.
+diff --git a/xyz/openbmc_project/MCTP/README.md b/xyz/openbmc_project/MCTP/README.md
+new file mode 100644
+index 0000000..1c3b4aa
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/README.md
+@@ -0,0 +1,38 @@
++# MCTP Daemon
++
++## Overview
++MCTP service exposes D-Bus methods / properties / signals for managing
++MCTP devices or work as MCTP Endpoint. MCTP daemon will either
++work in Bus Owner or Endpoint mode for the specified physical medium.
++
++### MCTP service
++MCTP service can be started either in Bus Owner mode or Endpoint mode.
++It will expose following objects.
++1. Base object
++2. MCTP Endpoints (discovered in case of Bus Owner mode, queried using
++routing table in case of Endpoint mode)
++Please refer individual yaml file for details about the
++methods / signals / properties exposed in the interfaces.
++
++#### Base object
++Exposed under the path `/xyz/openbmc_project/mctp` with the following
++interfaces.
++1. `xyz.openbmc_project.MCTP.Base` which exposes all the common properties
++needed for MCTP Daemon.
++2. `xyz.openbmc_project.MCTP.BusOwner` available only in Bus Owner mode
++which exposes the properties needed by Bus Owner MCTP Daemon.
++3. `xyz.openbmc_project.MCTP.SupportedMessageTypes` which exposes the message
++types supported.
++4. Binding interface `xyz.openbmc_project.MCTP.Binding.PCIe` or
++`xyz.openbmc_project.MCTP.Binding.SMBus` as per the physical medium in which
++this MCTP Daemon is instantiated.
++
++#### Endpoint object
++Exposed under the path `/xyz/openbmc_project/mctp/device/<eid>` with the
++following interfaces.
++1. `xyz.openbmc_project.MCTP.SupportedMessageTypes` which exposes supported MCTP
++message types for the discovered MCTP Endpoint.
++2. `xyz.openbmc_project.MCTP.Enpoint` which exposes properties like UUID and endpoint
++mode (to identify Bus Owner or Bridge or Endpoint) for the discovered MCTP Endpoint.
++3. `xyz.openbmc_project.MCTP.Bridge` available only for discovered MCTP Bridges to
++expose properties like EID pool. (TBD)
+diff --git a/xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml b/xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml
+new file mode 100644
+index 0000000..fa447ee
+--- /dev/null
++++ b/xyz/openbmc_project/MCTP/SupportedMessageTypes.interface.yaml
+@@ -0,0 +1,36 @@
++description:
++ Interface used to represent the supported MCTP message types.
++ This will be exposed by all MCTP endpoints.
++
++properties:
++ - name: MctpControl
++ type: boolean
++ description: Indicates support availability
++
++ - name: PLDM
++ type: boolean
++ description: Indicates support availability
++
++ - name: NCSI
++ type: boolean
++ description: Indicates support availability
++
++ - name: Ethernet
++ type: boolean
++ description: Indicates support availability
++
++ - name: NVMeMgmtMsg
++ type: boolean
++ description: Indicates support availability
++
++ - name: SPDM
++ type: boolean
++ description: Indicates support availability
++
++ - name: VDPCI
++ type: boolean
++ description: Indicates support availability
++
++ - name: VDIANA
++ type: boolean
++ description: Indicates support availability
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
new file mode 100644
index 000000000..762efe2b4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
@@ -0,0 +1,16 @@
+SRC_URI = "git://github.com/openbmc/phosphor-dbus-interfaces.git"
+SRCREV = "fdd88281dd243b3b9e6140b3f7b59aaaa188f37e"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch \
+ file://0007-ipmi-set-BIOS-id.patch \
+ file://0010-Increase-the-default-watchdog-timeout-value.patch \
+ file://0012-Add-RestoreDelay-interface-for-power-restore-delay.patch \
+ file://0013-Add-ErrConfig.yaml-interface-for-processor-error-config.patch \
+ file://0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.patch \
+ file://0025-Add-PreInterruptFlag-properity-in-DBUS.patch \
+ file://0001-Reapply-Enhance-DHCP-beyond-just-OFF-and-IPv4-IPv6-e.patch \
+ file://0026-Add-StandbySpare-support-for-software-inventory.patch \
+ file://0028-MCTP-Daemon-D-Bus-interface-definition.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service
new file mode 100644
index 000000000..9af9af254
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/xyz.openbmc_project.ObjectMapper.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=Phosphor DBus Service Discovery Manager
+Before=obmc-mapper.target
+After=dbus.socket
+
+[Service]
+Restart=always
+Type=dbus
+ExecStart=/usr/bin/env mapperx \
+ --service-namespaces="xyz. com. org." \
+ --interface-namespaces="org. com. xyz." \
+ --service-blacklists="org.freedesktop.systemd1"
+SyslogIdentifier=phosphor-mapper
+BusName={BUSNAME}
+TimeoutStartSec=300
+RestartSec=5
+EnvironmentFile={envfiledir}/obmc/mapper
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend
new file mode 100644
index 000000000..72d991c7e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control/phosphor-pid-control.service
new file mode 100644
index 000000000..0e80b554a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/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
+RestartSec=5
+StartLimitInterval=0
+Type=simple
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
new file mode 100644
index 000000000..2026a13b0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
@@ -0,0 +1,10 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+inherit obmc-phosphor-systemd
+SYSTEMD_SERVICE_${PN} = "phosphor-pid-control.service"
+EXTRA_OECONF = "--enable-configure-dbus=yes"
+
+SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git"
+SRCREV = "298a95cbb192ecc678b1a496acc954a3b2adf450"
+
+FILES_${PN} = "${bindir}/swampd ${bindir}/setsensor"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch
new file mode 100644
index 000000000..2a4c7e9b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0002-Redfish-firmware-activation.patch
@@ -0,0 +1,44 @@
+From b6b3051c8078267153712ed8cf514373924fd07a Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Mon, 16 Jul 2018 19:15:04 -0700
+Subject: [PATCH 2/6] Redfish firmware activation -- Modified flash.cpp to
+ call to customized flash service
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I81c3185e9c4c2ee907feeb53620faa22723c04d4
+---
+ ubi/flash.cpp | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/ubi/flash.cpp b/ubi/flash.cpp
+index ffa9348..5af2a17 100644
+--- a/ubi/flash.cpp
++++ b/ubi/flash.cpp
+@@ -15,10 +15,13 @@ void Activation::flashWrite()
+ {
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+- method.append("obmc-flash-bmc-ubirw.service", "replace");
++ std::string rwServiceFile =
++ "obmc-flash-bmc-ubirw@" + versionId + ".service";
++ method.append(rwServiceFile, "replace");
+ bus.call_noreply(method);
+
+- auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
++ std::string roServiceFile =
++ "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(roServiceFile, "replace");
+@@ -37,7 +40,7 @@ void Activation::onStateChanges(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- auto rwServiceFile = "obmc-flash-bmc-ubirw.service";
++ auto rwServiceFile = "obmc-flash-bmc-ubirw@" + versionId + ".service";
+ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ auto ubootVarsServiceFile =
+ "obmc-flash-bmc-updateubootvars@" + versionId + ".service";
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch
new file mode 100644
index 000000000..3fc3907ba
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0004-Changed-the-condition-of-software-version-service-wa.patch
@@ -0,0 +1,41 @@
+From 1b00440d0c8fabfa2e3eda984a21c0f004ca2150 Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Fri, 26 Oct 2018 11:54:05 -0700
+Subject: [PATCH 4/6] Changed the condition of software version service
+ watching deamon
+
+ Originally it watches only files that are "written" into /tmp/images directory.
+This change modified the condition to also watch files that are "moved" into this directory.
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I3e9cf1ffc3f5350d4649d32d3d3837991322a65b
+---
+ watch.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/watch.cpp b/watch.cpp
+index e46b8aa..eee1bc3 100644
+--- a/watch.cpp
++++ b/watch.cpp
+@@ -45,7 +45,7 @@ Watch::Watch(sd_event* loop, std::function<int(std::string&)> imageCallback) :
+ std::strerror(error));
+ }
+
+- wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE);
++ wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE | IN_MOVED_TO);
+ if (-1 == wd)
+ {
+ auto error = errno;
+@@ -96,7 +96,8 @@ int Watch::callback(sd_event_source* s, int fd, uint32_t revents,
+ while (offset < bytes)
+ {
+ auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
+- if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
++ if ((event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) &&
++ !(event->mask & IN_ISDIR))
+ {
+ auto tarballPath = std::string{IMG_UPLOAD_DIR} + '/' + event->name;
+ auto rc = static_cast<Watch*>(userdata)->imageCallback(tarballPath);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch
new file mode 100644
index 000000000..355261e8f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch
@@ -0,0 +1,188 @@
+From 32d90301c494c1b43f8e1d74ac9e7c1dc2fe486a Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Mon, 10 Dec 2018 10:36:44 -0800
+Subject: [PATCH 1/1] Modified firmware activation to launch fwupd.sh through
+
+ non-ubi fs code path to match more closely to the upstream design -
+ Added option FWUPD_SCRIPT to saperate intel customized code - Adopted
+ ActivationProgress from ubi fs activation code mainly for progress indicator
+ for ipmi update
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ activation.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 7 +++++++
+ static/flash.cpp | 41 +++++++++++++++++++++++++++++++++++++++--
+ ubi/flash.cpp | 9 +++------
+ 4 files changed, 92 insertions(+), 8 deletions(-)
+
+diff --git a/activation.cpp b/activation.cpp
+index ab76420..91e3a10 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -200,6 +200,49 @@ auto Activation::activation(Activations value) -> Activations
+ softwareServer::Activation::Activations::Active);
+ }
+ }
++#elif defined(FWUPD_SCRIPT)
++ if (!activationProgress)
++ {
++ // Enable systemd signals
++ Activation::subscribeToSystemdSignals();
++ parent.freeSpace(*this);
++
++ activationProgress =
++ std::make_unique<ActivationProgress>(bus, path);
++
++#ifdef WANT_SIGNATURE_VERIFY
++ fs::path uploadDir(IMG_UPLOAD_DIR);
++ if (!verifySignature(uploadDir / versionId, SIGNED_IMAGE_CONF_PATH))
++ {
++ onVerifyFailed();
++ // Stop the activation process, if fieldMode is enabled.
++ if (parent.control::FieldMode::fieldModeEnabled())
++ {
++ return softwareServer::Activation::activation(
++ softwareServer::Activation::Activations::Failed);
++ }
++ }
++#endif
++ flashWrite();
++ }
++ else if (activationProgress->progress() == 100)
++ {
++ log<level::ERR>("[Jennifer] progress == 100...");
++ if (!redundancyPriority)
++ {
++ redundancyPriority =
++ std::make_unique<RedundancyPriority>(bus, path, *this, 0);
++ }
++
++ // Remove version object from image manager
++ Activation::deleteImageManagerObject();
++
++ // Create active association
++ parent.createActiveAssociation(path);
++
++ return softwareServer::Activation::activation(
++ softwareServer::Activation::Activations::Active);
++ }
+ #else // !UBIFS_LAYOUT
+
+ #ifdef WANT_SIGNATURE_VERIFY
+diff --git a/configure.ac b/configure.ac
+index 5fba420..3b5fdab 100755
+--- a/configure.ac
++++ b/configure.ac
+@@ -194,6 +194,13 @@ AS_IF([test "x$enable_host_bios_upgrade" == "xyes"], \
+ [AC_DEFINE([HOST_BIOS_UPGRADE],[],[Enable host bios upgrade support.])])
+ AM_CONDITIONAL([HOST_BIOS_UPGRADE], [test "x$enable_host_bios_upgrade" == "xyes"])
+
++# setup fwupd script support
++AC_ARG_ENABLE([fwupd_script],
++ AS_HELP_STRING([--enable-fwupd_script], [Enable fwupd script support.]))
++AS_IF([test "x$enable_fwupd_script" == "xyes"], \
++ [AC_DEFINE([FWUPD_SCRIPT],[],[Enable fwupd script support.])])
++AM_CONDITIONAL([FWUPD_SCRIPT], [test "x$enable_fwupd_script" == "xyes"])
++
+ # Check for header files.
+ AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd development package required])])
+ AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])])
+diff --git a/static/flash.cpp b/static/flash.cpp
+index 82c2393..1bf29d5 100644
+--- a/static/flash.cpp
++++ b/static/flash.cpp
+@@ -20,9 +20,11 @@ namespace updater
+ {
+
+ namespace fs = std::experimental::filesystem;
++namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
+
+ void Activation::flashWrite()
+ {
++#ifndef FWUPD_SCRIPT
+ // For static layout code update, just put images in /run/initramfs.
+ // It expects user to trigger a reboot and an updater script will program
+ // the image to flash during reboot.
+@@ -33,11 +35,46 @@ void Activation::flashWrite()
+ fs::copy_file(uploadDir / versionId / bmcImage, toPath / bmcImage,
+ fs::copy_options::overwrite_existing);
+ }
++
++#else
++ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
++ SYSTEMD_INTERFACE, "StartUnit");
++ method.append("fwupd@" + versionId + ".service", "replace");
++ bus.call_noreply(method);
++#endif
+ }
+
+-void Activation::onStateChanges(sdbusplus::message::message& /*msg*/)
++void Activation::onStateChanges(sdbusplus::message::message& msg)
+ {
+- // Empty
++#ifndef FWUPD_SCRIPT
++ uint32_t newStateID{};
++ sdbusplus::message::object_path newStateObjPath;
++ std::string newStateUnit{};
++ std::string newStateResult{};
++
++ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
++
++ auto rwServiceFile = "fwupdw@" + versionId + ".service";
++
++ if (newStateUnit == rwServiceFile && newStateResult == "done")
++ {
++ activationProgress->progress(100);
++ }
++
++ if (newStateUnit == rwServiceFile)
++ {
++ if (newStateResult == "failed" || newStateResult == "dependency")
++ {
++ Activation::activation(
++ softwareServer::Activation::Activations::Failed);
++ }
++ else
++ {
++ Activation::activation(
++ softwareServer::Activation::Activations::Activating);
++ }
++ }
++#endif
+ }
+
+ } // namespace updater
+diff --git a/ubi/flash.cpp b/ubi/flash.cpp
+index 5af2a17..ffa9348 100644
+--- a/ubi/flash.cpp
++++ b/ubi/flash.cpp
+@@ -15,13 +15,10 @@ void Activation::flashWrite()
+ {
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+- std::string rwServiceFile =
+- "obmc-flash-bmc-ubirw@" + versionId + ".service";
+- method.append(rwServiceFile, "replace");
++ method.append("obmc-flash-bmc-ubirw.service", "replace");
+ bus.call_noreply(method);
+
+- std::string roServiceFile =
+- "obmc-flash-bmc-ubiro@" + versionId + ".service";
++ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ method.append(roServiceFile, "replace");
+@@ -40,7 +37,7 @@ void Activation::onStateChanges(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- auto rwServiceFile = "obmc-flash-bmc-ubirw@" + versionId + ".service";
++ auto rwServiceFile = "obmc-flash-bmc-ubirw.service";
+ auto roServiceFile = "obmc-flash-bmc-ubiro@" + versionId + ".service";
+ auto ubootVarsServiceFile =
+ "obmc-flash-bmc-updateubootvars@" + versionId + ".service";
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch
new file mode 100644
index 000000000..2d2ac2673
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch
@@ -0,0 +1,44 @@
+From 9b3c44e9fb3d907c0152f14b967e23ab964c0e0b Mon Sep 17 00:00:00 2001
+From: Jennifer Lee <jennifer1.lee@intel.com>
+Date: Thu, 14 Feb 2019 14:54:45 -0800
+Subject: [PATCH 6/6] Modify the ID of software image updater object on DBus to
+ allow force update onto same version image
+
+In the original design of image update, it does not allow the same version of image to be flashed onto itself.
+But this blocks validation tests and in most of the cases we don't prevent user from doing such update.
+
+This patch appends a random number after the version ID hash string to unblock such limitation.
+
+Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
+Change-Id: I16aba4804ae1bc2e8784320f91c0419fb8b23c35
+---
+ image_manager.cpp | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/image_manager.cpp b/image_manager.cpp
+index 5b2ff49..e3d26e3 100644
+--- a/image_manager.cpp
++++ b/image_manager.cpp
+@@ -9,6 +9,7 @@
+ #include <stdlib.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
++#include <time.h>
+ #include <unistd.h>
+
+ #include <algorithm>
+@@ -129,6 +130,11 @@ int Manager::processImage(const std::string& tarFilePath)
+ // Compute id
+ auto id = Version::getId(version);
+
++ // Append a random number after the original version hash
++ // This will allow forcing image update onto the same version
++ srand(time(NULL));
++ id = id + "_" + std::to_string(rand());
++
+ fs::path imageDirPath = std::string{IMG_UPLOAD_DIR};
+ imageDirPath /= id;
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch
new file mode 100644
index 000000000..b63226cce
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-Adding-StandBySpare-for-firmware-activation.patch
@@ -0,0 +1,76 @@
+From c2ae3ac444f7a5e9674a82f47086874f947bcec6 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+Date: Thu, 5 Dec 2019 12:38:21 +0530
+Subject: [PATCH] Adding StandBySpare for firmware activation
+
+Added new states 'StandBySpare', 'ActivatingAsStandbySpare' for
+firmware activation. If the uploaded firmware image is for
+backup/recovery, then it sets the "StandBySpare" value for
+Activations. When backup/recovery image is in activating state,
+then activations will be set to "ActivatingAsStandbySpare".
+
+Tested:
+Tested using redfish interface.
+Did the GET on "/redfish/v1/UpdateService/FirmwareInventory/<backup image>"
+Response:
+ ....
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "StandbySpare"
+ }
+.......
+
+Change-Id: I7f1608fac3196774a6d593b6128d58da3f5c88fc
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+---
+ activation.cpp | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/activation.cpp b/activation.cpp
+index 2966b2f..a098784 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -80,12 +80,16 @@ auto Activation::activation(Activations value) -> Activations
+ {
+
+ if ((value != softwareServer::Activation::Activations::Active) &&
+- (value != softwareServer::Activation::Activations::Activating))
++ (value != softwareServer::Activation::Activations::Activating) &&
++ (value !=
++ softwareServer::Activation::Activations::ActivatingAsStandbySpare))
+ {
+ redundancyPriority.reset(nullptr);
+ }
+
+- if (value == softwareServer::Activation::Activations::Activating)
++ if (value == softwareServer::Activation::Activations::Activating ||
++ value ==
++ softwareServer::Activation::Activations::ActivatingAsStandbySpare)
+ {
+ #ifdef UBIFS_LAYOUT
+ if (rwVolumeCreated == false && roVolumeCreated == false)
+@@ -256,6 +260,20 @@ auto Activation::requestedActivation(RequestedActivations value)
+ softwareServer::Activation::Activations::Activating);
+ }
+ }
++ else if ((value ==
++ softwareServer::Activation::RequestedActivations::StandbySpare) &&
++ (softwareServer::Activation::requestedActivation() !=
++ softwareServer::Activation::RequestedActivations::StandbySpare))
++ {
++ if ((softwareServer::Activation::activation() ==
++ softwareServer::Activation::Activations::Ready) ||
++ (softwareServer::Activation::activation() ==
++ softwareServer::Activation::Activations::Failed))
++ {
++ Activation::activation(softwareServer::Activation::Activations::
++ ActivatingAsStandbySpare);
++ }
++ }
+ return softwareServer::Activation::requestedActivation(value);
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch
new file mode 100644
index 000000000..92b3ced38
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0007-PFR-images-support.patch
@@ -0,0 +1,438 @@
+From 030f918b90ea45104bccf68082c2d634c6694238 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Tue, 13 Aug 2019 22:43:12 +0530
+Subject: [PATCH] PFR images support in phosphor-software-manager
+
+This commit adds support for handling the PFR images
+upload and processing.
+
+Testing:
+tested PFR image uploads and updates
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ Makefile.am | 18 +++-
+ activation.cpp | 2 +-
+ configure.ac | 7 ++
+ item_updater.cpp | 6 +-
+ pfr_image_manager.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++
+ pfr_image_manager.hpp | 75 +++++++++++++++
+ 6 files changed, 320 insertions(+), 5 deletions(-)
+ create mode 100644 pfr_image_manager.cpp
+ create mode 100644 pfr_image_manager.hpp
+
+diff --git a/Makefile.am b/Makefile.am
+index 6c3ec16..59ebecc 100755
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -6,13 +6,20 @@ noinst_HEADERS = \
+ watch.hpp \
+ version.hpp \
+ images.hpp \
+- image_manager.hpp \
+ item_updater.hpp \
+ activation.hpp \
+ flash.hpp \
+ item_updater_helper.hpp \
+ utils.hpp
+
++if PFR_UPDATE
++noinst_HEADERS += \
++ pfr_image_manager.hpp
++else
++noinst_HEADERS += \
++ image_manager.hpp
++endif
++
+ bin_PROGRAMS = \
+ phosphor-version-software-manager \
+ phosphor-download-manager \
+@@ -24,8 +31,15 @@ dist_bin_SCRIPTS = \
+ phosphor_version_software_manager_SOURCES = \
+ image_manager_main.cpp \
+ watch.cpp \
+- version.cpp \
++ version.cpp
++
++if PFR_UPDATE
++phosphor_version_software_manager_SOURCES += \
++ pfr_image_manager.cpp
++else
++phosphor_version_software_manager_SOURCES += \
+ image_manager.cpp
++endif
+
+ BUILT_SOURCES = \
+ xyz/openbmc_project/Software/Image/error.cpp \
+diff --git a/activation.cpp b/activation.cpp
+index cea1e50..7ff4196 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -197,7 +197,7 @@ auto Activation::activation(Activations value) -> Activations
+ }
+ else if (activationProgress->progress() == 100)
+ {
+- log<level::ERR>("[Jennifer] progress == 100...");
++ log<level::INFO>("progress == 100...");
+ if (!redundancyPriority)
+ {
+ redundancyPriority =
+diff --git a/configure.ac b/configure.ac
+index 720e704..e527682 100755
+--- a/configure.ac
++++ b/configure.ac
+@@ -191,6 +191,13 @@ AS_IF([test "x$enable_fwupd_script" == "xyes"], \
+ [AC_DEFINE([FWUPD_SCRIPT],[],[Enable fwupd script support.])])
+ AM_CONDITIONAL([FWUPD_SCRIPT], [test "x$enable_fwupd_script" == "xyes"])
+
++# setup pfr image update support
++AC_ARG_ENABLE([pfr_update],
++ AS_HELP_STRING([--enable-pfr_update], [Enable pfr image update support.]))
++AS_IF([test "x$enable_pfr_update" == "xyes"], \
++ [AC_DEFINE([PFR_UPDATE],[],[Enable pfr image update support.])])
++AM_CONDITIONAL([PFR_UPDATE], [test "x$enable_pfr_update" == "xyes"])
++
+ # Check for header files.
+ AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd development package required])])
+ AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])])
+diff --git a/item_updater.cpp b/item_updater.cpp
+index 21fb6e0..fd76a7f 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -64,10 +64,10 @@ void ItemUpdater::createActivation(sdbusplus::message::message& msg)
+ auto value = SVersion::convertVersionPurposeFromString(
+ variant_ns::get<std::string>(property.second));
+ if (value == VersionPurpose::BMC ||
+-#ifdef HOST_BIOS_UPGRADE
++#if defined(HOST_BIOS_UPGRADE) || defined(PFR_UPDATE)
+ value == VersionPurpose::Host ||
+ #endif
+- value == VersionPurpose::System)
++ value == VersionPurpose::Other)
+ {
+ purpose = value;
+ }
+@@ -356,6 +357,7 @@ void ItemUpdater::deleteAll()
+ ItemUpdater::ActivationStatus
+ ItemUpdater::validateSquashFSImage(const std::string& filePath)
+ {
++#ifndef PFR_UPDATE
+ bool invalid = false;
+
+ for (auto& bmcImage : bmcImages)
+@@ -375,7 +377,7 @@ ItemUpdater::ActivationStatus
+ {
+ return ItemUpdater::ActivationStatus::invalid;
+ }
+-
++#endif
+ return ItemUpdater::ActivationStatus::ready;
+ }
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+new file mode 100644
+index 0000000..242a6ca
+--- /dev/null
++++ b/pfr_image_manager.cpp
+@@ -0,0 +1,217 @@
++#include "config.h"
++
++#include "pfr_image_manager.hpp"
++
++#include "version.hpp"
++#include "watch.hpp"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/stat.h>
++#include <sys/wait.h>
++#include <time.h>
++#include <unistd.h>
++
++#include <algorithm>
++#include <cstring>
++#include <elog-errors.hpp>
++#include <filesystem>
++#include <fstream>
++#include <iomanip>
++#include <sstream>
++#include <string>
++#include <xyz/openbmc_project/Software/Image/error.hpp>
++
++namespace phosphor
++{
++namespace software
++{
++namespace manager
++{
++
++using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error;
++namespace Software = phosphor::logging::xyz::openbmc_project::Software;
++
++static constexpr const uint32_t pfmPos = 2054;
++
++static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
++ std::string& version)
++{
++ struct pfrImgBlock0 block0Data;
++ uint8_t verData[2];
++
++ if (std::filesystem::exists(imgPath))
++ {
++ try
++ {
++ std::ifstream imgFile(imgPath, std::ios::binary | std::ios::in);
++
++ if (!imgFile.good())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image file read failed");
++ return -1;
++ }
++
++ imgFile.read(reinterpret_cast<char*>(&block0Data),
++ sizeof(block0Data));
++ imgType = block0Data.pcType[0];
++ imgFile.seekg(pfmPos,
++ std::ios::beg); // Version is at 0x806 in the PFM
++ imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
++ imgFile.close();
++ version =
++ std::to_string(verData[0]) + "." + std::to_string(verData[1]);
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "PFR image",
++ phosphor::logging::entry("PCType=%d", block0Data.pcType[0]),
++ phosphor::logging::entry("VERSION=%s", version.c_str()));
++ }
++ catch (std::exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return -1;
++ }
++ }
++
++ return 0;
++}
++
++int Manager::processImage(const std::string& imgFilePath)
++{
++ std::filesystem::path imgPath(imgFilePath);
++
++ if (!std::filesystem::exists(imgPath))
++ return -1;
++
++ uint8_t imgType;
++ int retry = 3;
++ std::string ver;
++ std::string purposeString;
++
++ if (0 != getPFRImgInfo(imgFilePath, imgType, ver))
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error reading uploaded image type and version");
++ return -1;
++ }
++
++ if (ver.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Empty version from image file");
++ return -1;
++ }
++
++ if (imgType == pfrBMCUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
++ }
++ else if (imgType == pfrPCHUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
++ }
++ else if (imgType == pfrCPLDUpdateCap)
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
++ }
++ else
++ {
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Unknown";
++
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unknown image type");
++ return -1;
++ }
++
++ sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
++ purpose = Version::VersionPurpose::Unknown;
++ try
++ {
++ purpose = Version::convertVersionPurposeFromString(purposeString);
++ }
++ catch (const sdbusplus::exception::InvalidEnumString& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: Failed to convert purpose to enum."
++ " Setting to Unknown.");
++ }
++
++ // Compute id
++ std::string id = Version::getId(ver);
++
++ // Append a random number after the original version hash
++ // This will allow forcing image update onto the same version
++ // with 3 retries on random number generation.
++ do
++ {
++ srand(time(NULL));
++ id = id + "_" + std::to_string(rand());
++ } while ((versions.find(id) != versions.end()) && retry--);
++
++ if (versions.find(id) != versions.end())
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Software Object with the same version already exists, exiting "
++ "the update",
++ phosphor::logging::entry("VERSION_ID=%s", id.c_str()));
++
++ return -1;
++ }
++
++ std::filesystem::path imageDirPath(IMG_UPLOAD_DIR);
++ imageDirPath /= id;
++
++ std::filesystem::create_directory(imageDirPath);
++
++ std::filesystem::path newFileName = imageDirPath / "image-runtime";
++ std::filesystem::rename(imgFilePath, newFileName);
++
++ // Create Version object
++ std::string objPath = std::string{SOFTWARE_OBJPATH} + '/' + id;
++
++ auto versionPtr = std::make_unique<Version>(
++ bus, objPath, ver, purpose, imageDirPath.string(),
++ std::bind(&Manager::erase, this, std::placeholders::_1));
++ versionPtr->deleteObject =
++ std::make_unique<phosphor::software::manager::Delete>(bus, objPath,
++ *versionPtr);
++ versions.insert(std::make_pair(id, std::move(versionPtr)));
++
++ return 0;
++}
++
++void Manager::erase(std::string entryId)
++{
++ auto it = versions.find(entryId);
++ if (it == versions.end())
++ {
++ return;
++ }
++
++ if (it->second->isFunctional())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ ("Error: Version " + entryId +
++ " is currently running on the BMC."
++ " Unable to remove.")
++ .c_str());
++ return;
++ }
++
++ // Delete image dir
++ std::filesystem::path imageDirPath = (*(it->second)).path();
++ if (std::filesystem::exists(imageDirPath))
++ {
++ std::filesystem::remove_all(imageDirPath);
++ }
++ this->versions.erase(entryId);
++}
++
++} // namespace manager
++} // namespace software
++} // namespace phosphor
+diff --git a/pfr_image_manager.hpp b/pfr_image_manager.hpp
+new file mode 100644
+index 0000000..c6ee6a4
+--- /dev/null
++++ b/pfr_image_manager.hpp
+@@ -0,0 +1,75 @@
++#pragma once
++#include "version.hpp"
++
++#include <sdbusplus/server.hpp>
++
++namespace phosphor
++{
++namespace software
++{
++namespace manager
++{
++
++enum pfrImgPCType {
++ pfrCPLDUpdateCap = 0x00,
++ pfrPCHPFM = 0x01,
++ pfrPCHUpdateCap = 0x02,
++ pfrBMCPFM = 0x03,
++ pfrBMCUpdateCap = 0x04
++};
++
++/* PFR image block 0 - As defined in HAS */
++struct pfrImgBlock0 {
++ uint8_t tag[4];
++ uint8_t pcLength[4];
++ uint8_t pcType[4];
++ uint8_t reserved1[4];
++ uint8_t hash256[32];
++ uint8_t hash384[48];
++ uint8_t reserved2[32];
++}__attribute__((packed));
++
++/** @class Manager
++ * @brief Contains a map of Version dbus objects.
++ * @details The software image manager class that contains the Version dbus
++ * objects and their version ids.
++ */
++class Manager
++{
++ public:
++ /** @brief Constructs Manager Class
++ *
++ * @param[in] bus - The Dbus bus object
++ */
++ Manager(sdbusplus::bus::bus& bus) : bus(bus){};
++
++ /**
++ * @brief Verify the image and provide the image to updater.
++ * Create and populate the version and file path interfaces.
++ *
++ * @param[in] uploaded image.
++ * @param[out] result - 0 if successful.
++ */
++ int processImage(const std::string& imageFilePath);
++
++ /**
++ * @brief Erase specified entry d-bus object
++ * and deletes the image file.
++ *
++ * @param[in] entryId - unique identifier of the entry
++ */
++ void erase(std::string entryId);
++
++ private:
++ /** @brief Persistent map of Version dbus objects and their
++ * version id */
++ std::map<std::string, std::unique_ptr<Version>> versions;
++
++ /** @brief Persistent sdbusplus DBus bus connection. */
++ sdbusplus::bus::bus& bus;
++
++};
++
++} // namespace manager
++} // namespace software
++} // namespace phosphor
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch
new file mode 100644
index 000000000..31373104f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-PFR-image-HASH-verification.patch
@@ -0,0 +1,408 @@
+From ac6e0c217a1b136d82f93b691aff1acb40009f26 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+Date: Thu, 5 Dec 2019 11:55:36 +0530
+Subject: [PATCH] PFR image HASH verification
+
+This adds HASH verification on PFR images uploaded for
+firmware updates
+
+Tested: tested firmware update with good and bad HASH images.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@linux.intel.com>
+---
+ pfr_image_manager.cpp | 149 ++++++++++++++++++++++++++++++++----------
+ pfr_image_manager.hpp | 112 +++++++++++++++++++++++++++++--
+ 2 files changed, 221 insertions(+), 40 deletions(-)
+
+diff --git a/pfr_image_manager.cpp b/pfr_image_manager.cpp
+index 242a6ca..1a41cbe 100644
+--- a/pfr_image_manager.cpp
++++ b/pfr_image_manager.cpp
+@@ -5,6 +5,8 @@
+ #include "version.hpp"
+ #include "watch.hpp"
+
++#include <fcntl.h>
++#include <openssl/err.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/stat.h>
+@@ -15,9 +17,9 @@
+ #include <algorithm>
+ #include <cstring>
+ #include <elog-errors.hpp>
+-#include <filesystem>
+ #include <fstream>
+ #include <iomanip>
++#include <set>
+ #include <sstream>
+ #include <string>
+ #include <xyz/openbmc_project/Software/Image/error.hpp>
+@@ -33,12 +35,21 @@ using namespace sdbusplus::xyz::openbmc_project::Software::Image::Error;
+ namespace Software = phosphor::logging::xyz::openbmc_project::Software;
+
+ static constexpr const uint32_t pfmPos = 2054;
++static constexpr const uint32_t block0Magic = 0xB6EAFD19;
++static constexpr const uint32_t lengthBlk0Blk1 = 1024;
+
+-static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+- std::string& version)
++int Manager::verifyPFRImage(const std::filesystem::path imgPath,
++ std::string& version, std::string& purposeString)
+ {
+- struct pfrImgBlock0 block0Data;
+- uint8_t verData[2];
++ uint8_t imgType = 0;
++ uint32_t imgMagic = 0;
++ uint8_t verData[2] = {0};
++ uint32_t hashLen = 0;
++ struct pfrImgBlock0 block0Data = {};
++
++ std::string imageName;
++
++ EVP_MD_CTX* ctx;
+
+ if (std::filesystem::exists(imgPath))
+ {
+@@ -55,17 +66,101 @@ static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+
+ imgFile.read(reinterpret_cast<char*>(&block0Data),
+ sizeof(block0Data));
++
++ imgMagic = block0Data.tag;
++
++ if (imgMagic != block0Magic)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Image magic number match failed",
++ phosphor::logging::entry("IMAGEMAGIC=0x%x", imgMagic));
++ return -1;
++ }
++
+ imgType = block0Data.pcType[0];
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Image Type", phosphor::logging::entry(
++ "IMAGETYPE=0x%x", static_cast<int>(imgType)));
++
++ if (imgType == pfrBMCUpdateCap || imgType == pfrBMCPFM)
++ {
++ imageName = "BMC";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
++ }
++ else if (imgType == pfrPCHUpdateCap || imgType == pfrPCHPFM)
++ {
++ imageName = "BIOS";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
++ }
++ else if (imgType == pfrCPLDUpdateCap)
++ {
++ imageName = "CPLD";
++ purposeString =
++ "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
++ }
++ else
++ {
++ purposeString = "xyz.openbmc_project.Software.Version."
++ "VersionPurpose.Unknown";
++
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unknown image type");
++ return -1;
++ }
++
+ imgFile.seekg(pfmPos,
+ std::ios::beg); // Version is at 0x806 in the PFM
+ imgFile.read(reinterpret_cast<char*>(&verData), sizeof(verData));
+ imgFile.close();
+- version =
+- std::to_string(verData[0]) + "." + std::to_string(verData[1]);
++
++ auto size = std::filesystem::file_size(imgPath);
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Image Size", phosphor::logging::entry("IMAGESIZE=0x%x",
++ static_cast<int>(size)));
++
++ // Adds all digest algorithms to the internal table
++ OpenSSL_add_all_digests();
++
++ ctx = EVP_MD_CTX_create();
++ EVP_DigestInit(ctx, EVP_sha256());
++
++ // Hash the image file and update the digest
++ auto dataPtr = mapFile(imgPath, size);
++
++ EVP_DigestUpdate(ctx, ((uint8_t*)dataPtr() + lengthBlk0Blk1),
++ (size - lengthBlk0Blk1));
++
++ std::vector<uint8_t> digest(EVP_MD_size(EVP_sha256()));
++ std::vector<uint8_t> expectedDigest(block0Data.hash256,
++ &block0Data.hash256[0] + 32);
++
++ EVP_DigestFinal(ctx, digest.data(), &hashLen);
++ EVP_MD_CTX_destroy(ctx);
++
++ std::string redfishMsgID = "OpenBMC.0.1";
++
++ if (expectedDigest != digest)
++ {
++ redfishMsgID += ".GeneralFirmwareSecurityViolation";
++ sd_journal_send("MESSAGE=%s",
++ "Firmware image HASH verification failed",
++ "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s",
++ redfishMsgID.c_str(), "REDFISH_MESSAGE_ARGS=%s",
++ "Image HASH check fail", NULL);
++ return -1;
++ }
++
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "PFR image",
+ phosphor::logging::entry("PCType=%d", block0Data.pcType[0]),
+ phosphor::logging::entry("VERSION=%s", version.c_str()));
++
++ version =
++ std::to_string(verData[0]) + "." + std::to_string(verData[1]);
+ }
+ catch (std::exception& e)
+ {
+@@ -79,20 +174,20 @@ static int getPFRImgInfo(const std::filesystem::path imgPath, uint8_t& imgType,
+
+ int Manager::processImage(const std::string& imgFilePath)
+ {
++
+ std::filesystem::path imgPath(imgFilePath);
+
+ if (!std::filesystem::exists(imgPath))
+ return -1;
+
+- uint8_t imgType;
+ int retry = 3;
+ std::string ver;
+ std::string purposeString;
+
+- if (0 != getPFRImgInfo(imgFilePath, imgType, ver))
++ if (0 != verifyPFRImage(imgFilePath, ver, purposeString))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+- "Error reading uploaded image type and version");
++ "Error verifying uploaded image");
+ return -1;
+ }
+
+@@ -103,31 +198,6 @@ int Manager::processImage(const std::string& imgFilePath)
+ return -1;
+ }
+
+- if (imgType == pfrBMCUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.BMC";
+- }
+- else if (imgType == pfrPCHUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Host";
+- }
+- else if (imgType == pfrCPLDUpdateCap)
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Other";
+- }
+- else
+- {
+- purposeString =
+- "xyz.openbmc_project.Software.Version.VersionPurpose.Unknown";
+-
+- phosphor::logging::log<phosphor::logging::level::ERR>(
+- "Unknown image type");
+- return -1;
+- }
+-
+ sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
+ purpose = Version::VersionPurpose::Unknown;
+ try
+@@ -169,6 +239,7 @@ int Manager::processImage(const std::string& imgFilePath)
+ std::filesystem::create_directory(imageDirPath);
+
+ std::filesystem::path newFileName = imageDirPath / "image-runtime";
++
+ std::filesystem::rename(imgFilePath, newFileName);
+
+ // Create Version object
+@@ -212,6 +283,14 @@ void Manager::erase(std::string entryId)
+ this->versions.erase(entryId);
+ }
+
++CustomMap Manager::mapFile(const std::filesystem::path& path, size_t size)
++{
++
++ CustomFd fd(open(path.c_str(), O_RDONLY));
++
++ return CustomMap(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd(), 0),
++ size);
++}
+ } // namespace manager
+ } // namespace software
+ } // namespace phosphor
+diff --git a/pfr_image_manager.hpp b/pfr_image_manager.hpp
+index c6ee6a4..5b7b2c3 100644
+--- a/pfr_image_manager.hpp
++++ b/pfr_image_manager.hpp
+@@ -1,6 +1,13 @@
+ #pragma once
+ #include "version.hpp"
+
++#include <openssl/evp.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++#include <filesystem>
+ #include <sdbusplus/server.hpp>
+
+ namespace phosphor
+@@ -10,7 +17,8 @@ namespace software
+ namespace manager
+ {
+
+-enum pfrImgPCType {
++enum pfrImgPCType
++{
+ pfrCPLDUpdateCap = 0x00,
+ pfrPCHPFM = 0x01,
+ pfrPCHUpdateCap = 0x02,
+@@ -19,15 +27,94 @@ enum pfrImgPCType {
+ };
+
+ /* PFR image block 0 - As defined in HAS */
+-struct pfrImgBlock0 {
+- uint8_t tag[4];
++struct pfrImgBlock0
++{
++ uint32_t tag;
+ uint8_t pcLength[4];
+ uint8_t pcType[4];
+ uint8_t reserved1[4];
+ uint8_t hash256[32];
+ uint8_t hash384[48];
+ uint8_t reserved2[32];
+-}__attribute__((packed));
++} __attribute__((packed));
++
++/** @struct CustomFd
++ *
++ * RAII wrapper for file descriptor.
++ */
++struct CustomFd
++{
++ public:
++ CustomFd() = delete;
++ CustomFd(const CustomFd&) = delete;
++ CustomFd& operator=(const CustomFd&) = delete;
++ CustomFd(CustomFd&&) = default;
++ CustomFd& operator=(CustomFd&&) = default;
++ /** @brief Saves File descriptor and uses it to do file operation
++ *
++ * @param[in] fd - File descriptor
++ */
++ CustomFd(int fd) : fd(fd)
++ {
++ }
++
++ ~CustomFd()
++ {
++ if (fd >= 0)
++ {
++ close(fd);
++ }
++ }
++
++ int operator()() const
++ {
++ return fd;
++ }
++
++ private:
++ /** @brief File descriptor */
++ int fd = -1;
++};
++
++/** @struct CustomMap
++ *
++ * RAII wrapper for mmap.
++ */
++struct CustomMap
++{
++ private:
++ /** @brief starting address of the map */
++ void* addr;
++
++ /** @brief length of the mapping */
++ size_t length;
++
++ public:
++ CustomMap() = delete;
++ CustomMap(const CustomMap&) = delete;
++ CustomMap& operator=(const CustomMap&) = delete;
++ CustomMap(CustomMap&&) = default;
++ CustomMap& operator=(CustomMap&&) = default;
++
++ /** @brief Saves starting address of the map and
++ * and length of the file.
++ * @param[in] addr - Starting address of the map
++ * @param[in] length - length of the map
++ */
++ CustomMap(void* addr, size_t length) : addr(addr), length(length)
++ {
++ }
++
++ ~CustomMap()
++ {
++ munmap(addr, length);
++ }
++
++ void* operator()() const
++ {
++ return addr;
++ }
++};
+
+ /** @class Manager
+ * @brief Contains a map of Version dbus objects.
+@@ -61,13 +148,28 @@ class Manager
+ void erase(std::string entryId);
+
+ private:
++ /**
++ * @brief Memory map the file
++ * @param[in] - file path
++ * @param[in] - file size
++ * @param[out] - Custom Mmap address
++ */
++ CustomMap mapFile(const std::filesystem::path& path, size_t size);
++
++ /**
++ * @brief Verify the PFR image and return version and purpose
++ * @param[in] - file path
++ * @param[out] - version
++ * @param[out] - purpose
++ */
++ int verifyPFRImage(const std::filesystem::path imgPath,
++ std::string& version, std::string& purposeString);
+ /** @brief Persistent map of Version dbus objects and their
+ * version id */
+ std::map<std::string, std::unique_ptr<Version>> versions;
+
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+-
+ };
+
+ } // namespace manager
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch
new file mode 100644
index 000000000..bac756a18
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0008-item_updater-update-the-bmc_active-objectPath.patch
@@ -0,0 +1,30 @@
+From d9e50ecf8bd8bc764838e7244084184644a3f0fc Mon Sep 17 00:00:00 2001
+From: Chalapathi <chalapathix.venkataramashetty@intel.com>
+Date: Thu, 23 Apr 2020 19:06:19 +0000
+Subject: [PATCH] item_updater: update the bmc_active objectPath
+
+Update the Software object path to bmc_active instead of random Id.
+
+Signed-off-by: Chalapathi <chalapathix.venkataramashetty@intel.com>
+---
+ item_updater.cpp | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/item_updater.cpp b/item_updater.cpp
+index 7fe69e4..3ce1dbf 100644
+--- a/item_updater.cpp
++++ b/item_updater.cpp
+@@ -175,9 +175,7 @@ void ItemUpdater::processBMCImage()
+ if (0 ==
+ iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX))
+ {
+- // The versionId is extracted from the path
+- // for example /media/ro-2a1022fe.
+- auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
++ std::string id = "bmc_active";
+ auto osRelease = iter.path() / OS_RELEASE_FILE;
+ if (!fs::is_regular_file(osRelease))
+ {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
new file mode 100644
index 000000000..64d9a47a6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Flash BMC with fwupd script : %I
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/fwupd.sh %i
+SyslogIdentifier=fwupd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
new file mode 100644
index 000000000..edd4254ce
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
@@ -0,0 +1,20 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+EXTRA_OECONF += "--enable-fwupd_script"
+
+SYSTEMD_SERVICE_${PN}-updater += "fwupd@.service"
+
+EXTRA_OECONF += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '--enable-pfr_update', '', d)}"
+
+SRC_URI += "file://0002-Redfish-firmware-activation.patch \
+ file://0004-Changed-the-condition-of-software-version-service-wa.patch \
+ file://0005-Modified-firmware-activation-to-launch-fwupd.sh-thro.patch \
+ file://0006-Modify-the-ID-of-software-image-updater-object-on-DB.patch \
+ file://0007-Adding-StandBySpare-for-firmware-activation.patch \
+ file://0008-item_updater-update-the-bmc_active-objectPath.patch \
+ "
+
+SRC_URI_PFR = "file://0007-PFR-images-support.patch \
+ file://0008-PFR-image-HASH-verification.patch \
+ "
+
+SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', SRC_URI_PFR, '', d)}"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru.bb
new file mode 100644
index 000000000..53cec437d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru.bb
@@ -0,0 +1,30 @@
+SUMMARY = "Default Fru"
+DESCRIPTION = "Builds a default FRU file at runtime based on board ID"
+
+inherit systemd
+inherit cmake
+
+SYSTEMD_SERVICE_${PN} = "SetBaseboardFru.service"
+
+S = "${WORKDIR}"
+SRC_URI = "file://checkFru.sh \
+ file://SetBaseboardFru.service \
+ file://mkfru.cpp \
+ file://CMakeLists.txt \
+ "
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "\
+ file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658 \
+ file://mkfru.cpp;beginline=2;endline=14;md5=c451359f18a13ee69602afce1588c01a \
+ "
+
+RDEPENDS_${PN} = "bash"
+
+do_install_append() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/checkFru.sh ${D}/${bindir}/checkFru.sh
+
+ install -d ${D}${base_libdir}/systemd/system
+ install -m 0644 ${S}/SetBaseboardFru.service ${D}${base_libdir}/systemd/system
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/CMakeLists.txt
new file mode 100644
index 000000000..a8e633644
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
+project(mkfru CXX)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+add_executable(mkfru mkfru.cpp)
+install(TARGETS mkfru DESTINATION bin)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/SetBaseboardFru.service b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/SetBaseboardFru.service
new file mode 100644
index 000000000..d8c2a75ac
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/SetBaseboardFru.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Check for FRU presence
+
+[Service]
+ExecStart=/usr/bin/checkFru.sh
+Type=oneshot
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/checkFru.sh b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/checkFru.sh
new file mode 100755
index 000000000..9227beb20
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/checkFru.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# this script checks the gpio id and loads the correct baseboard fru
+FRUPATH="/etc/fru"
+PRODIDPATH="/var/cache/private"
+fruFile="$FRUPATH/baseboard.fru.bin"
+prodIDFile="$PRODIDPATH/prodID"
+
+if [ -f $fruFile -a -f $prodIDFile ]; then
+ exit 0
+fi
+
+read_id() {
+ local idx=0
+ local result=0
+ local value=0
+ for ((idx=0; idx<6; idx++))
+ do
+ typeset -i value=$(gpioget $(gpiofind "FM_BMC_BOARD_SKU_ID${idx}_N"))
+ value=$((value << idx))
+ result=$((result | value))
+ done
+ echo $result
+}
+
+BOARD_ID=$(read_id)
+if grep -q 'CPU part\s*: 0xb76' /proc/cpuinfo; then
+ # AST2500
+ case $BOARD_ID in
+ 12) NAME="D50TNP1SB"
+ PRODID="0x99";;
+ 40) NAME="CooperCity"
+ PRODID="0x9d";;
+ 42) NAME="WilsonCity"
+ PRODID="0x91";;
+ 44) NAME="WilsonCityM"
+ PRODID="0x91";;
+ 45) NAME="WilsonCity"
+ PRODID="0x91";;
+ 60) NAME="M50CYP2SB2U"
+ PRODID="0x98";;
+ 62) NAME="WilsonPoint"
+ PRODID="0x9a";;
+ *) NAME="S2600WFT"
+ PRODID="0x7b";;
+ esac
+
+elif grep -q 'CPU part\s*: 0xc07' /proc/cpuinfo; then
+ # AST2600
+ case $BOARD_ID in
+ 62) NAME="ArcherCity"
+ PRODID="0x9c";;
+ *) NAME="AST2600EVB"
+ PRODID="0x00";;
+ esac
+
+fi
+
+if [ -z "$NAME" ]; then
+ NAME="Unknown"
+fi
+
+if [ ! -e $prodIDFile ]
+then
+ echo $PRODID >$prodIDFile
+fi
+
+if [ ! -f $fruFile ]
+then
+ cd /tmp
+ mkdir -p $FRUPATH
+ mkfru $NAME
+ mv $NAME.fru.bin $fruFile
+fi
+
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/mkfru.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/mkfru.cpp
new file mode 100644
index 000000000..afadbd324
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fru/default-fru/mkfru.cpp
@@ -0,0 +1,219 @@
+/*
+// Copyright (c) 2019 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Abstract: default FRU generation
+//
+*/
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <numeric>
+#include <string>
+#include <vector>
+
+constexpr uint8_t fillChar = '.';
+constexpr uint8_t eof = 0xc1;
+const std::string intel = "Intel Corporation";
+
+// round up to nearest block size (power of 2)
+constexpr size_t blockRound(size_t len, size_t blk)
+{
+ return ((len) + (((blk) - ((len) & ((blk)-1))) & ((blk)-1)));
+}
+
+uint8_t mklen(uint8_t len)
+{
+ return static_cast<uint8_t>((0x3 << 6) | len);
+}
+
+struct FruEntry
+{
+ static constexpr size_t fruBlockSize = 8; // type, length, checksum
+ static constexpr size_t fixedBytes = 3; // type, length, checksum
+ FruEntry() = delete;
+ FruEntry(const std::vector<uint8_t>& contents)
+ {
+ constexpr size_t verOffset = 0;
+ constexpr size_t lenOffset = 1;
+ value.resize(blockRound(fixedBytes + contents.size(), fruBlockSize));
+ value[verOffset] = 1;
+ value[lenOffset] = blocks();
+ std::copy(contents.begin(), contents.end(), value.begin() + 2);
+ addChecksum();
+ }
+
+ void addChecksum()
+ {
+ int sum = std::accumulate(value.begin(), value.end(), 0);
+ value.back() = static_cast<uint8_t>(256 - sum & 0xff);
+ }
+
+ uint8_t blocks() const
+ {
+ return static_cast<uint8_t>(value.size() / 8);
+ }
+
+ std::vector<uint8_t> value;
+};
+
+size_t fillDots(std::vector<uint8_t>::iterator start, size_t count)
+{
+ *start++ = mklen(count); // prefix with (0xc0 | count)
+ auto end = start + count++;
+ std::fill(start, end, '.');
+ return count;
+}
+
+size_t fillStr(std::vector<uint8_t>::iterator start, const std::string& str)
+{
+ size_t count = str.size();
+ *start++ = mklen(count++); // prefix with (0xc0 | count)
+ std::copy(str.begin(), str.end(), start);
+ return count;
+}
+
+std::vector<uint8_t> genChassisContents()
+{
+ constexpr size_t pnSize = 18;
+ constexpr size_t snSize = 18;
+ constexpr size_t amSize = 31;
+ constexpr size_t headerSize = 1;
+ constexpr size_t contentSize = headerSize + 1 + pnSize + 1 + snSize + 1 +
+ amSize + 1 + amSize + sizeof(eof);
+ std::vector<uint8_t> data(contentSize);
+ size_t offset = 0;
+ // chassis type (main server chassis)
+ data[offset++] = 0x17;
+ // chassis part number
+ offset += fillDots(data.begin() + offset, pnSize);
+ // chassis serial number
+ offset += fillDots(data.begin() + offset, snSize);
+ // info am1
+ offset += fillDots(data.begin() + offset, amSize);
+ // info am2
+ offset += fillDots(data.begin() + offset, amSize);
+ data[offset] = eof;
+
+ return data;
+}
+
+std::vector<uint8_t> genBoardContents(const std::string& name)
+{
+ constexpr size_t headerSize = 4;
+ constexpr size_t snSize = 12;
+ constexpr size_t pnSize = 10;
+ const std::string version = "FRU Ver 0.01";
+ size_t contentSize = headerSize + 1 + name.size() + 1 + intel.size() + 1 +
+ snSize + 1 + pnSize + 1 + version.size() + sizeof(eof);
+ std::vector<uint8_t> data(contentSize);
+ size_t offset = 0;
+ // chassis type (main server chassis)
+ data[offset++] = 0; // language code
+ data[offset++] = 0; // mfg date/time
+ data[offset++] = 0; // mfg date/time
+ data[offset++] = 0; // mfg date/time
+ // manufacturer name
+ offset += fillStr(data.begin() + offset, intel);
+ // product name
+ offset += fillStr(data.begin() + offset, name);
+ // board sn
+ offset += fillDots(data.begin() + offset, snSize);
+ // board pn
+ offset += fillDots(data.begin() + offset, pnSize);
+ // fru version string
+ offset += fillStr(data.begin() + offset, version);
+ data[offset] = eof;
+
+ return data;
+}
+
+std::vector<uint8_t> genProductContents(const std::string& name)
+{
+ constexpr size_t headerSize = 1;
+ constexpr size_t pnSize = 10;
+ constexpr size_t pvSize = 20;
+ constexpr size_t snSize = 12;
+ constexpr size_t atSize = 20;
+ constexpr size_t idSize = 0;
+ const std::string version = "FRU Ver 0.01";
+ size_t contentSize = headerSize + 1 + intel.size() + 1 + name.size() + 1 +
+ pnSize + 1 + pvSize + 1 + snSize + 1 + atSize + 1 +
+ idSize + sizeof(eof);
+ std::vector<uint8_t> data(contentSize);
+ size_t offset = 0;
+ // chassis type (main server chassis)
+ data[offset++] = 0; // language code
+ // manufacturer name
+ offset += fillStr(data.begin() + offset, intel);
+ // product name
+ offset += fillStr(data.begin() + offset, name);
+ // product part number
+ offset += fillDots(data.begin() + offset, pnSize);
+ // product version
+ offset += fillDots(data.begin() + offset, pvSize);
+ // product serial number
+ offset += fillDots(data.begin() + offset, snSize);
+ // product asset tag
+ offset += fillDots(data.begin() + offset, atSize);
+ // empty fru file id
+ offset += fillDots(data.begin() + offset, idSize);
+ data[offset] = eof;
+
+ return data;
+}
+
+int createFru(const std::string& name)
+{
+ std::vector<uint8_t> internal{1, 0, 0, 0, 0, 0, 0, 1}; // fixed data
+ FruEntry chassis(genChassisContents());
+ FruEntry board(genBoardContents(name));
+ FruEntry product(genProductContents(name));
+ uint8_t offset = 1; // room for header's offset
+ FruEntry header({
+ offset += 1, // internal size
+ offset += chassis.blocks(),
+ offset += board.blocks(),
+ });
+ std::string filename = name + ".fru.bin";
+ std::ofstream output(filename);
+ std::ostream_iterator<uint8_t> outputIter(output);
+ std::copy(header.value.begin(), header.value.end(), outputIter);
+ std::copy(internal.begin(), internal.end(), outputIter);
+ std::copy(chassis.value.begin(), chassis.value.end(), outputIter);
+ std::copy(board.value.begin(), board.value.end(), outputIter);
+ std::copy(product.value.begin(), product.value.end(), outputIter);
+ constexpr size_t minFruSize = 0x1ff;
+ size_t fruSize = header.value.size() + internal.size() +
+ chassis.value.size() + board.value.size() +
+ product.value.size();
+ if (fruSize < minFruSize)
+ {
+ std::vector<uint8_t> padding(minFruSize - fruSize);
+ std::copy(padding.begin(), padding.end(), outputIter);
+ }
+ output.close();
+ return 0;
+}
+
+int main(int argc, const char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " <'Product Name'>\n";
+ return 1;
+ }
+ return createFru(argv[1]);
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend
new file mode 100644
index 000000000..5326680f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/host/obmc-op-control-host%.bbappend
@@ -0,0 +1,6 @@
+SYSTEMD_LINK_${PN}_remove += "../op-start-host@.service:obmc-host-startmin@0.target.requires/op-start-host@0.service"
+SYSTEMD_LINK_${PN}_remove += "../op-init-pnor@.service:obmc-host-startmin@0.target.requires/op-init-pnor@0.service"
+
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires"
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires/op-start-host@0.service"
+FILES_${PN}_remove = "${systemd_unitdir}/system/obmc-host-startmin@0.target.requires/op-init-pnor@0.service" \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-support-for-StandBySpare.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-support-for-StandBySpare.patch
new file mode 100644
index 000000000..46e94e339
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0001-Firmware-update-support-for-StandBySpare.patch
@@ -0,0 +1,462 @@
+From 461da7ec950704a1f5bcc7f6527ed8ca119cfaf9 Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Tue, 24 Mar 2020 16:05:32 +0530
+Subject: [PATCH] Firmware update support for StandBySpare
+
+Firmware update support for StandBySpare. This will
+have support for adding 'HttpPushUriTargets' and
+'HttpPushUriTargetsBusy' attributes. These attributes enables
+'HttpPushUri' to distinguish between the firmware update targets.
+
+Tested:
+ - GET on "/redfish/v1/UpdateService", got below response
+.........
+ "HttpPushUriTargets": [],
+ "HttpPushUriTargetsBusy": false
+........
+
+ - PATCH on "/redfish/v1/UpdateService" and works fine.
+{
+ "HttpPushUriTargets": ["bmc_recovery"],
+ "HttpPushUriTargetsBusy": true
+}
+
+ - Did Firmware update and verified end to end functionality
+ for both bmc active and backup images.
+
+ - Successfully ran redfish validater with no new errors.
+
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
+---
+ redfish-core/lib/update_service.hpp | 274 +++++++++++++++++++++++++++++++-----
+ 1 file changed, 241 insertions(+), 33 deletions(-)
+
+diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
+index e9793eb..a913bac 100644
+--- a/redfish-core/lib/update_service.hpp
++++ b/redfish-core/lib/update_service.hpp
+@@ -30,6 +30,17 @@ static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
+ static bool fwUpdateInProgress = false;
+ // Timer for software available
+ static std::unique_ptr<boost::asio::steady_timer> fwAvailableTimer;
++static constexpr const char *versionIntf =
++ "xyz.openbmc_project.Software.Version";
++static constexpr const char *activationIntf =
++ "xyz.openbmc_project.Software.Activation";
++static constexpr const char *reqActivationPropName = "RequestedActivation";
++static constexpr const char *reqActivationsActive =
++ "xyz.openbmc_project.Software.Activation.RequestedActivations.Active";
++static constexpr const char *reqActivationsStandBySpare =
++ "xyz.openbmc_project.Software.Activation.RequestedActivations.StandbySpare";
++static constexpr const char *activationsStandBySpare =
++ "xyz.openbmc_project.Software.Activation.Activations.StandbySpare";
+
+ static void cleanUp()
+ {
+@@ -37,27 +48,119 @@ static void cleanUp()
+ fwUpdateMatcher = nullptr;
+ }
+ static void activateImage(const std::string &objPath,
+- const std::string &service)
++ const std::string &service,
++ const std::vector<std::string> &imgUriTargets)
+ {
+ BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service;
++ // If targets is empty, it will apply to the active.
++ if (imgUriTargets.size() == 0)
++ {
++ crow::connections::systemBus->async_method_call(
++ [](const boost::system::error_code error_code) {
++ if (error_code)
++ {
++ BMCWEB_LOG_DEBUG
++ << "RequestedActivation failed: error_code = "
++ << error_code;
++ BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
++ }
++ },
++ service, objPath, "org.freedesktop.DBus.Properties", "Set",
++ activationIntf, reqActivationPropName,
++ std::variant<std::string>(reqActivationsActive));
++ return;
++ }
++
++ // TODO: Now we support only one target becuase software-manager
++ // code support one activation per object. It will be enhanced
++ // to multiple targets for single image in future. For now,
++ // consider first target alone.
+ crow::connections::systemBus->async_method_call(
+- [](const boost::system::error_code error_code) {
+- if (error_code)
++ [objPath, service, imgTarget{imgUriTargets[0]}](
++ const boost::system::error_code ec,
++ const crow::openbmc_mapper::GetSubTreeType &subtree) {
++ if (ec || !subtree.size())
+ {
+- BMCWEB_LOG_DEBUG << "error_code = " << error_code;
+- BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
++ return;
++ }
++
++ for (const auto &[invObjPath, invDict] : subtree)
++ {
++ std::size_t idPos = invObjPath.rfind("/");
++ if ((idPos == std::string::npos) ||
++ ((idPos + 1) >= invObjPath.size()))
++ {
++ BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!";
++ return;
++ }
++ std::string swId = invObjPath.substr(idPos + 1);
++
++ if (swId != imgTarget)
++ {
++ continue;
++ }
++
++ if (invDict.size() < 1)
++ {
++ continue;
++ }
++ BMCWEB_LOG_DEBUG << "Image target matched with object "
++ << invObjPath;
++ crow::connections::systemBus->async_method_call(
++ [objPath,
++ service](const boost::system::error_code error_code,
++ const std::variant<std::string> value) {
++ if (error_code)
++ {
++ BMCWEB_LOG_DEBUG
++ << "Error in querying activation value";
++ // not all fwtypes are updateable,
++ // this is ok
++ return;
++ }
++ std::string activationValue =
++ std::get<std::string>(value);
++ BMCWEB_LOG_DEBUG << "Activation Value: "
++ << activationValue;
++ std::string reqActivation = reqActivationsActive;
++ if (activationValue == activationsStandBySpare)
++ {
++ reqActivation = reqActivationsStandBySpare;
++ }
++ BMCWEB_LOG_DEBUG
++ << "Setting RequestedActivation value as "
++ << reqActivation << " for " << service << " "
++ << objPath;
++ crow::connections::systemBus->async_method_call(
++ [](const boost::system::error_code error_code) {
++ if (error_code)
++ {
++ BMCWEB_LOG_DEBUG
++ << "RequestedActivation failed: ec = "
++ << error_code;
++ }
++ return;
++ },
++ service, objPath, "org.freedesktop.DBus.Properties",
++ "Set", activationIntf, reqActivationPropName,
++ std::variant<std::string>(reqActivation));
++ },
++ invDict[0].first,
++ "/xyz/openbmc_project/software/" + imgTarget,
++ "org.freedesktop.DBus.Properties", "Get", activationIntf,
++ "Activation");
+ }
+ },
+- service, objPath, "org.freedesktop.DBus.Properties", "Set",
+- "xyz.openbmc_project.Software.Activation", "RequestedActivation",
+- std::variant<std::string>(
+- "xyz.openbmc_project.Software.Activation.RequestedActivations."
+- "Active"));
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/",
++ static_cast<int32_t>(0), std::array<const char *, 1>{versionIntf});
+ }
+
+ // Note that asyncResp can be either a valid pointer or nullptr. If nullptr
+ // then no asyncResp updates will occur
+ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
++ const std::vector<std::string> imgUriTargets,
+ sdbusplus::message::message &m,
+ const crow::Request &req)
+ {
+@@ -70,25 +173,27 @@ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+
+ m.read(objPath, interfacesProperties);
+
+- BMCWEB_LOG_DEBUG << "obj path = " << objPath.str;
++ BMCWEB_LOG_DEBUG << "Software Interface Added. obj path = " << objPath.str;
+ for (auto &interface : interfacesProperties)
+ {
+ BMCWEB_LOG_DEBUG << "interface = " << interface.first;
+
+- if (interface.first == "xyz.openbmc_project.Software.Activation")
++ if (interface.first == activationIntf)
+ {
+ // Found our interface, disable callbacks
+ fwUpdateMatcher = nullptr;
+
+ // Retrieve service and activate
+ crow::connections::systemBus->async_method_call(
+- [objPath, asyncResp,
++ [objPath, asyncResp, imgTargets{imgUriTargets},
+ req](const boost::system::error_code error_code,
+ const std::vector<std::pair<
+ std::string, std::vector<std::string>>> &objInfo) {
+ if (error_code)
+ {
+- BMCWEB_LOG_DEBUG << "error_code = " << error_code;
++ BMCWEB_LOG_DEBUG
++ << "GetSoftwareObject path failed: error_code = "
++ << error_code;
+ BMCWEB_LOG_DEBUG << "error msg = "
+ << error_code.message();
+ if (asyncResp)
+@@ -115,7 +220,7 @@ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ // is added
+ fwAvailableTimer = nullptr;
+
+- activateImage(objPath.str, objInfo[0].first);
++ activateImage(objPath.str, objInfo[0].first, imgTargets);
+ if (asyncResp)
+ {
+ std::shared_ptr<task::TaskData> task =
+@@ -196,17 +301,16 @@ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetObject", objPath.str,
+- std::array<const char *, 1>{
+- "xyz.openbmc_project.Software.Activation"});
++ std::array<const char *, 1>{activationIntf});
+ }
+ }
+ }
+
+ // Note that asyncResp can be either a valid pointer or nullptr. If nullptr
+ // then no asyncResp updates will occur
+-static void monitorForSoftwareAvailable(std::shared_ptr<AsyncResp> asyncResp,
+- const crow::Request &req,
+- int timeoutTimeSeconds = 5)
++static void monitorForSoftwareAvailable(
++ std::shared_ptr<AsyncResp> asyncResp, const crow::Request &req,
++ const std::vector<std::string> &imgUriTargets, int timeoutTimeSeconds = 5)
+ {
+ // Only allow one FW update at a time
+ if (fwUpdateInProgress != false)
+@@ -246,9 +350,10 @@ static void monitorForSoftwareAvailable(std::shared_ptr<AsyncResp> asyncResp,
+ }
+ });
+
+- auto callback = [asyncResp, req](sdbusplus::message::message &m) {
++ auto callback = [asyncResp, imgTargets{imgUriTargets},
++ req](sdbusplus::message::message &m) {
+ BMCWEB_LOG_DEBUG << "Match fired";
+- softwareInterfaceAdded(asyncResp, m, req);
++ softwareInterfaceAdded(asyncResp, imgTargets, m, req);
+ };
+
+ fwUpdateInProgress = true;
+@@ -358,9 +463,12 @@ class UpdateServiceActionsSimpleUpdate : public Node
+ std::string fwFile = imageURI.substr(separator + 1);
+ BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile;
+
++ // We will pass empty targets and its handled in activation.
++ std::vector<std::string> httpUriTargets;
++
+ // Setup callback for when new software detected
+ // Give TFTP 2 minutes to complete
+- monitorForSoftwareAvailable(nullptr, req, 120);
++ monitorForSoftwareAvailable(nullptr, req, httpUriTargets, 120);
+
+ // TFTP can take up to 2 minutes depending on image size and
+ // connection speed. Return to caller as soon as the TFTP operation
+@@ -394,7 +502,8 @@ class UpdateServiceActionsSimpleUpdate : public Node
+ class UpdateService : public Node
+ {
+ public:
+- UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
++ UpdateService(CrowApp &app) :
++ Node(app, "/redfish/v1/UpdateService/"), httpPushUriTargetBusy(false)
+ {
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+@@ -406,6 +515,9 @@ class UpdateService : public Node
+ }
+
+ private:
++ std::vector<std::string> httpPushUriTargets;
++ bool httpPushUriTargetBusy;
++
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) override
+ {
+@@ -416,6 +528,8 @@ class UpdateService : public Node
+ res.jsonValue["Description"] = "Service for Software Update";
+ res.jsonValue["Name"] = "Update Service";
+ res.jsonValue["HttpPushUri"] = "/redfish/v1/UpdateService";
++ res.jsonValue["HttpPushUriTargets"] = httpPushUriTargets;
++ res.jsonValue["HttpPushUriTargetsBusy"] = httpPushUriTargetBusy;
+ // UpdateService cannot be disabled
+ res.jsonValue["ServiceEnabled"] = true;
+ res.jsonValue["FirmwareInventory"] = {
+@@ -475,9 +589,14 @@ class UpdateService : public Node
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ std::optional<nlohmann::json> pushUriOptions;
+- if (!json_util::readJson(req, res, "HttpPushUriOptions",
+- pushUriOptions))
++ std::optional<std::vector<std::string>> imgTargets;
++ std::optional<bool> imgTargetBusy;
++
++ if (!json_util::readJson(req, res, "HttpPushUriOptions", pushUriOptions,
++ "HttpPushUriTargets", imgTargets,
++ "HttpPushUriTargetsBusy", imgTargetBusy))
+ {
++ BMCWEB_LOG_DEBUG << "UpdateService doPatch: Invalid request body";
+ return;
+ }
+
+@@ -545,6 +664,98 @@ class UpdateService : public Node
+ }
+ }
+ }
++
++ if (imgTargetBusy)
++ {
++ if ((httpPushUriTargetBusy) && (*imgTargetBusy))
++ {
++ BMCWEB_LOG_DEBUG
++ << "Other client has reserved the HttpPushUriTargets "
++ "property for firmware updates.";
++ messages::resourceInUse(asyncResp->res);
++ return;
++ }
++
++ if (imgTargets)
++ {
++ if (!(*imgTargetBusy))
++ {
++ BMCWEB_LOG_DEBUG
++ << "UpdateService doPatch: httpPushUriTargetBusy "
++ "should be "
++ "true before setting httpPushUriTargets";
++ messages::invalidObject(asyncResp->res,
++ "HttpPushUriTargetsBusy");
++ return;
++ }
++ if ((*imgTargets).size() != 0)
++ {
++ // TODO: Now we support max one target becuase
++ // software-manager code support one activation per object.
++ // It will be enhanced to multiple targets for single image
++ // in future. For now, consider first target alone.
++ if ((*imgTargets).size() != 1)
++ {
++ messages::invalidObject(asyncResp->res,
++ "HttpPushUriTargets");
++ return;
++ }
++ crow::connections::systemBus->async_method_call(
++ [this, asyncResp, uriTargets{*imgTargets},
++ targetBusy{*imgTargetBusy}](
++ const boost::system::error_code ec,
++ const std::vector<std::string> swInvPaths) {
++ if (ec)
++ {
++ return;
++ }
++
++ bool swInvObjFound = false;
++ for (const std::string &path : swInvPaths)
++ {
++ std::size_t idPos = path.rfind("/");
++ if ((idPos == std::string::npos) ||
++ ((idPos + 1) >= path.size()))
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_DEBUG
++ << "Can't parse firmware ID!!";
++ return;
++ }
++ std::string swId = path.substr(idPos + 1);
++
++ if (swId == uriTargets[0])
++ {
++ swInvObjFound = true;
++ break;
++ }
++ }
++ if (!swInvObjFound)
++ {
++ messages::invalidObject(asyncResp->res,
++ "HttpPushUriTargets");
++ return;
++ }
++ this->httpPushUriTargetBusy = targetBusy;
++ this->httpPushUriTargets = uriTargets;
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
++ "/", static_cast<int32_t>(0),
++ std::array<const char *, 1>{versionIntf});
++ }
++ else
++ {
++ httpPushUriTargetBusy = *imgTargetBusy;
++ httpPushUriTargets = *imgTargets;
++ }
++ }
++ else
++ {
++ httpPushUriTargetBusy = *imgTargetBusy;
++ }
++ }
+ }
+
+ void doPost(crow::Response &res, const crow::Request &req,
+@@ -555,7 +766,7 @@ class UpdateService : public Node
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+
+ // Setup callback for when new software detected
+- monitorForSoftwareAvailable(asyncResp, req);
++ monitorForSoftwareAvailable(asyncResp, req, httpPushUriTargets);
+
+ std::string filepath(
+ "/tmp/images/" +
+@@ -641,8 +852,7 @@ class SoftwareInventoryCollection : public Node
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/software", static_cast<int32_t>(0),
+- std::array<const char *, 1>{
+- "xyz.openbmc_project.Software.Version"});
++ std::array<const char *, 1>{versionIntf});
+ }
+ };
+
+@@ -825,7 +1035,7 @@ class SoftwareInventory : public Node
+ },
+ obj.second[0].first, obj.first,
+ "org.freedesktop.DBus.Properties", "GetAll",
+- "xyz.openbmc_project.Software.Version");
++ versionIntf);
+ }
+ if (!found)
+ {
+@@ -846,9 +1056,7 @@ class SoftwareInventory : public Node
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/",
+- static_cast<int32_t>(0),
+- std::array<const char *, 1>{
+- "xyz.openbmc_project.Software.Version"});
++ static_cast<int32_t>(0), std::array<const char *, 1>{versionIntf});
+ }
+ };
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Use-chip-id-based-UUID-for-Service-Root.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Use-chip-id-based-UUID-for-Service-Root.patch
new file mode 100644
index 000000000..03c27fb43
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0002-Use-chip-id-based-UUID-for-Service-Root.patch
@@ -0,0 +1,71 @@
+From d629bf86a9ac970d8c0505c0aa2488373c9df102 Mon Sep 17 00:00:00 2001
+From: Wiktor Golgowski <wiktor.golgowski@linux.intel.com>
+Date: Thu, 30 Apr 2020 11:09:35 +0200
+Subject: [PATCH] Use chip id-based UUID for Service Root.
+
+If the sysfs-provided chip id is available, it will be used as
+payload to generate Service Root UUID from hardcoded namespace.
+
+Tested:
+Generated UUID is consistent between BMC image reflashes.
+If the sysfs node is not available, code falls back to randomly
+generated UUID.
+
+Signed-off-by: Wiktor Gołgowski <wiktor.golgowski@linux.intel.com>
+---
+ include/persistent_data_middleware.hpp | 32 +++++++++++++++++++++++---
+ 1 file changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/include/persistent_data_middleware.hpp b/include/persistent_data_middleware.hpp
+index 348079b..925e7b6 100644
+--- a/include/persistent_data_middleware.hpp
++++ b/include/persistent_data_middleware.hpp
+@@ -30,6 +30,10 @@ class Middleware
+ public:
+ // todo(ed) should read this from a fixed location somewhere, not CWD
+ static constexpr const char* filename = "bmcweb_persistent_data.json";
++ static constexpr const char* chipIdSysfsNode = "/sys/devices/platform"
++ "/ahb/ahb:apb/1e6e2000.syscon/1e6e2000.syscon:misc_control/chip_id";
++ static constexpr const char* UuidNs = "{b7b0553a-54cc-4162-982d-"
++ "944847ed76f5}";
+
+ struct Context
+ {
+@@ -143,9 +147,31 @@ class Middleware
+
+ if (systemUuid.empty())
+ {
+- systemUuid =
+- boost::uuids::to_string(boost::uuids::random_generator()());
+- needWrite = true;
++ // Try to retrieve chip id-based uuid.
++ std::ifstream chipIdFile(chipIdSysfsNode);
++ if (chipIdFile.is_open())
++ {
++ std::string chipId;
++ std::getline(chipIdFile, chipId);
++ if (!chipId.empty())
++ {
++ boost::uuids::name_generator_sha1 gen(
++ boost::uuids::string_generator()(UuidNs));
++ systemUuid = boost::uuids::to_string(gen(chipId.c_str()));
++ needWrite = true;
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "Cannot get chip id-based System UUID.";
++ }
++ }
++ // If the above fails, generate random uuid.
++ if (systemUuid.empty())
++ {
++ systemUuid =
++ boost::uuids::to_string(boost::uuids::random_generator()());
++ needWrite = true;
++ }
+ }
+ if (fileRevision < jsonRevision)
+ {
+--
+2.20.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket
new file mode 100644
index 000000000..8782e4dd3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/bmcweb.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=BMC Webserver socket
+
+[Socket]
+ListenStream=443
+ReusePort=true
+
+[Install]
+WantedBy=sockets.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
new file mode 100644
index 000000000..9824210cd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -0,0 +1,25 @@
+# todo(james) remove nobranch
+SRC_URI = "git://github.com/openbmc/bmcweb.git"
+SRCREV = "7d1cc387d312e2a8e4844f9d69ab39b042acd5ce"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+# add a user called bmcweb for the server to assume
+# bmcweb is part of group shadow for non-root pam authentication
+USERADD_PARAM_${PN} = "-r -s /usr/sbin/nologin -d /home/bmcweb -m -G shadow bmcweb"
+
+GROUPADD_PARAM_${PN} = "web; redfish "
+
+SRC_URI += "file://0001-Firmware-update-support-for-StandBySpare.patch \
+ file://0002-Use-chip-id-based-UUID-for-Service-Root.patch \
+"
+
+# Enable PFR support
+EXTRA_OECMAKE += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', '-DBMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE=ON', '', d)}"
+
+# Enable NBD_PROXY
+EXTRA_OECMAKE += " -DBMCWEB_ENABLE_VM_NBDPROXY=ON"
+
+# Enable Validation unsecure based on IMAGE_FEATURES
+EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend
new file mode 100644
index 000000000..616fb9a75
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config.bbappend
@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += " file://dev_id.json \
+ file://channel_access.json \
+ file://channel_config.json \
+ file://master_write_read_white_list.json \
+ "
+
+FILES_${PN} += " \
+ ${datadir}/ipmi-providers/channel_access.json \
+ ${datadir}/ipmi-providers/channel_config.json \
+ ${datadir}/ipmi-providers/master_write_read_white_list.json \
+ "
+
+do_install_append() {
+ install -m 0644 -D ${WORKDIR}/channel_access.json \
+ ${D}${datadir}/ipmi-providers/channel_access.json
+ install -m 0644 -D ${WORKDIR}/channel_config.json \
+ ${D}${datadir}/ipmi-providers/channel_config.json
+ install -m 0644 -D ${WORKDIR}/master_write_read_white_list.json \
+ ${D}${datadir}/ipmi-providers/master_write_read_white_list.json
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json
new file mode 100644
index 000000000..299483121
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_access.json
@@ -0,0 +1,23 @@
+{
+ "1" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ },
+ "2" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ },
+ "3" : {
+ "access_mode" : "always_available",
+ "user_auth_disabled" : false,
+ "per_msg_auth_disabled" : false,
+ "alerting_disabled" : false,
+ "priv_limit" : "priv-admin"
+ }
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json
new file mode 100644
index 000000000..b02595e81
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/channel_config.json
@@ -0,0 +1,178 @@
+{
+ "0" : {
+ "name" : "Ipmb",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "1" : {
+ "name" : "eth1",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "lan-802.3",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "multi-session",
+ "is_ipmi" : true
+ }
+ },
+ "2" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "3" : {
+ "name" : "eth0",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "lan-802.3",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "multi-session",
+ "is_ipmi" : true
+ }
+ },
+ "4" : {
+ "name" : "RESERVED",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "5" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "6" : {
+ "name" : "SMLINK",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "7" : {
+ "name" : "ipmi_kcs4",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "system-interface",
+ "protocol_type" : "kcs",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "8" : {
+ "name" : "INTRABMC",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "oem",
+ "protocol_type" : "oem",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "9" : {
+ "name" : "SIPMB",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "10" : {
+ "name" : "PCIE",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "11" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "12" : {
+ "name" : "INTERNAL",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "13" : {
+ "name" : "RESERVED",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "reserved",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "14" : {
+ "name" : "SELF",
+ "is_valid" : false,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "unknown",
+ "protocol_type" : "na",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ },
+ "15" : {
+ "name" : "ipmi_kcs3",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "system-interface",
+ "protocol_type" : "kcs",
+ "session_supported" : "session-less",
+ "is_ipmi" : true
+ }
+ }
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json
new file mode 100644
index 000000000..e561569d9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/dev_id.json
@@ -0,0 +1,2 @@
+{"id": 35, "revision": 0, "addn_dev_support": 191,
+ "manuf_id": 343, "prod_id": 123, "aux": 0}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json
new file mode 100644
index 000000000..6fc46f452
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-config/master_write_read_white_list.json
@@ -0,0 +1,76 @@
+{
+ "filters": [
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x01",
+ "slaveAddr": "0x4d",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x01",
+ "slaveAddr": "0x57",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x40",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x49",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x02",
+ "slaveAddr": "0x51",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x03",
+ "slaveAddr": "0x44",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x03",
+ "slaveAddr": "0x68",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x06",
+ "slaveAddr": "0x40",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ },
+ {
+ "Description": "Allow full read - ignore first byte write value",
+ "busId": "0x07",
+ "slaveAddr": "0x51",
+ "slaveAddrMask": "0x00",
+ "command": "0x00",
+ "commandMask": "0xFF"
+ }
+ ]
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend
new file mode 100644
index 000000000..2d892ad1a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += " file://config.yaml"
+
+#override source file before it is used for final FRU file (merged from multiple sources)
+do_install() {
+ cp ${WORKDIR}/config.yaml ${config_datadir}/
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml
new file mode 100644
index 000000000..e9b7a621e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-fru-merge-config-native/config.yaml
@@ -0,0 +1,31 @@
+# A YAML similar to this example would have to be generated, for eg with MRW
+# inputs and system configuration, to depict IPMI Fru information.
+#
+# This file maps IPMI properties to phosphor dbus inventory properties
+#
+# This YAML could help generate C++ code.
+# Format of the YAML:
+# Fruid:
+# Associated Fru paths
+# d-bus Interfaces
+# d-bus Properties
+# IPMI Fru mapping
+0:
+ /system/board/WFP_Baseboard:
+ entityID: 23
+ entityInstance: 1
+ interfaces:
+ xyz.openbmc_project.Inventory.Item:
+ name:
+ IPMIFruProperty: Product Name
+ IPMIFruSection: Product
+ xyz.openbmc_project.Inventory.Decorator.Asset:
+ Manufacturer:
+ IPMIFruProperty: Manufacturer
+ IPMIFruSection: Product
+ PartNumber:
+ IPMIFruProperty: Part Number
+ IPMIFruSection: Product
+ SerialNumber:
+ IPMIFruProperty: Serial Number
+ IPMIFruSection: Product
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/.clang-format
new file mode 100644
index 000000000..ea71ad6e1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/.clang-format
@@ -0,0 +1,99 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch
new file mode 100644
index 000000000..7e3f92dbc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch
@@ -0,0 +1,231 @@
+From 8e9fba263179ccc87be7212c7dbd87cd7a37ac30 Mon Sep 17 00:00:00 2001
+From: Johnathan Mantey <johnathanx.mantey@intel.com>
+Date: Thu, 14 Nov 2019 11:24:19 -0800
+Subject: [PATCH] Modify Get Lan Configuration IP Address Source to use correct
+ DBus DHCPEnabled type
+
+The Get/Set Lan Configuration "IP Address Source" subcommand got
+broken by phosphor-dbus-interfaces commit 12162be
+
+12162be changed the DBus DHCPEnabled type from boolean to enum
+type. The Get LAN Configuration IP address Source IPMI command did not
+get changed to an enum type prior to 12162be being merged. This commit
+retroactively updates the boolean type to enum type.
+
+Tested:
+
+ipmitool raw 0xc 2 3 4 0 0 # returns correct state
+ipmitool raw 0xc 1 3 4 1 # changes DCHP to Static
+ipmitool raw 0xc 1 3 4 2 # returns Static to DHCP
+
+Assigned a static address via Redfish and tested using:
+ipmitool raw 0xc 2 3 4 0 0 # returns correct state
+
+Returned the NIC to use DHCP via Redfish and tested using:
+ipmitool raw 0xc 2 3 4 0 0 # returns correct state
+
+Change-Id: Ia66f7fcf3d5ad0a383b06658b18e8ce2b282e052
+Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
+---
+ transporthandler.cpp | 97 ++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 79 insertions(+), 18 deletions(-)
+
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 16ce2b2..ccc2a97 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -109,6 +109,18 @@ constexpr auto INTF_NEIGHBOR_CREATE_STATIC =
+ constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
+ constexpr auto INTF_VLAN_CREATE = "xyz.openbmc_project.Network.VLAN.Create";
+
++static constexpr auto dhcpv4v6 =
++ "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
++static constexpr auto dhcpv6 =
++ "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
++static constexpr auto dhcpv4 =
++ "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
++static constexpr auto dhcpoff =
++ "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
++
++static std::array<const char*, 4> dhcpEnumerations = {dhcpv4v6, dhcpv4, dhcpv6,
++ dhcpoff};
++
+ /** @brief Generic paramters for different address families */
+ template <int family>
+ struct AddrFamily
+@@ -456,25 +468,63 @@ auto channelCall(uint8_t channel, Args&&... args)
+ *
+ * @param[in] bus - The bus object used for lookups
+ * @param[in] params - The parameters for the channel
+- * @return True if DHCP is enabled, false otherwise
++ * @return string containing an enumerated value
++ * constexpr's dhcpv4v6, dhcpv4, dhcpv6, and dhcpoff
+ */
+-bool getDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params)
++std::string getDHCPProperty(sdbusplus::bus::bus& bus,
++ const ChannelParams& params)
+ {
+- return std::get<bool>(getDbusProperty(
++ return std::get<std::string>(getDbusProperty(
+ bus, params.service, params.logicalPath, INTF_ETHERNET, "DHCPEnabled"));
+ }
+
+ /** @brief Sets the system value for DHCP on the given interface
+ *
+- * @param[in] bus - The bus object used for lookups
+- * @param[in] params - The parameters for the channel
+- * @param[in] on - Whether or not to enable DHCP
++ * @param[in] bus - The bus object used for lookups
++ * @param[in] params - The parameters for the channel
++ * @param[in] setting - DHCP state to assign (none, v4, v6, both)
+ */
+ void setDHCPProperty(sdbusplus::bus::bus& bus, const ChannelParams& params,
+- bool on)
++ const std::string& setting)
+ {
++ auto it = dhcpEnumerations.begin();
++ while (it != dhcpEnumerations.end())
++ {
++ if (*it == setting)
++ {
++ break;
++ }
++ it++;
++ }
++ if (it == dhcpEnumerations.end())
++ {
++ log<level::ERR>("Invalid DHCP setting.",
++ entry("Requested DHCP mode=%s", setting.c_str()));
++ elog<InternalFailure>();
++ }
++
++ std::string dhcp = getDHCPProperty(bus, params);
++ std::string nextDhcp{};
++
++ if (((dhcp == dhcpv4) && (setting == dhcpv6)) ||
++ ((dhcp == dhcpv6) && (setting == dhcpv4)))
++ {
++ // DHCP is enabled independently for IPv4 and IPv6. If IPv4
++ // DHCP is enabled, and a request to add IPv6 is received,
++ // change the DHCPEnabled enum to "both" active. The same
++ // logic is applied if IPV6 is already enabled, and an IPv4
++ // enable request is made.
++ nextDhcp = dhcpv4v6;
++ }
++ else
++ {
++ // "both" enabled -> ipv4 only
++ // "both" enabled -> ipv6 only
++ // "ip4v", "ipv6", or "both" enabled -> no DHCP
++ nextDhcp = setting;
++ }
+ setDbusProperty(bus, params.service, params.logicalPath, INTF_ETHERNET,
+- "DHCPEnabled", on);
++ "DHCPEnabled", nextDhcp);
+ }
+
+ /** @brief Converts a human readable MAC string into MAC bytes
+@@ -1113,7 +1163,7 @@ void deconfigureChannel(sdbusplus::bus::bus& bus, ChannelParams& params)
+ }
+
+ // Clear out any settings on the lower physical interface
+- setDHCPProperty(bus, params, false);
++ setDHCPProperty(bus, params, dhcpoff);
+ }
+
+ /** @brief Creates a new VLAN on the specified interface
+@@ -1401,7 +1451,8 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ }
+ case LanParam::IP:
+ {
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcpSetting = channelCall<getDHCPProperty>(channel);
++ if ((dhcpSetting == dhcpv4) || (dhcpSetting == dhcpv4v6))
+ {
+ return responseCommandNotAvailable();
+ }
+@@ -1431,7 +1482,11 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ {
+ case IPSrc::DHCP:
+ {
+- channelCall<setDHCPProperty>(channel, true);
++ // The IPSrc IPMI command is only for IPv4
++ // management. Modifying IPv6 state is done using
++ // a completely different Set LAN Configuration
++ // subcommand.
++ channelCall<setDHCPProperty>(channel, dhcpv4);
+ return responseSuccess();
+ }
+ case IPSrc::Unspecified:
+@@ -1439,7 +1494,7 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ case IPSrc::BIOS:
+ case IPSrc::BMC:
+ {
+- channelCall<setDHCPProperty>(channel, false);
++ channelCall<setDHCPProperty>(channel, dhcpoff);
+ return responseSuccess();
+ }
+ }
+@@ -1464,7 +1519,8 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ }
+ case LanParam::SubnetMask:
+ {
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcpSetting = channelCall<getDHCPProperty>(channel);
++ if ((dhcpSetting == dhcpv4) || (dhcpSetting == dhcpv4v6))
+ {
+ return responseCommandNotAvailable();
+ }
+@@ -1481,7 +1537,8 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ }
+ case LanParam::Gateway1:
+ {
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcpSetting = channelCall<getDHCPProperty>(channel);
++ if ((dhcpSetting == dhcpv4) || (dhcpSetting == dhcpv4v6))
+ {
+ return responseCommandNotAvailable();
+ }
+@@ -1606,7 +1663,8 @@ RspType<> setLan(uint4_t channelBits, uint4_t, uint8_t parameter,
+ return responseReqDataLenInvalid();
+ }
+ std::bitset<8> expected;
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcp = channelCall<getDHCPProperty>(channel);
++ if ((dhcp == dhcpv4v6) || (dhcp == dhcpv6))
+ {
+ expected[IPv6RouterControlFlag::Dynamic] = 1;
+ }
+@@ -1756,7 +1814,8 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
+ case LanParam::IPSrc:
+ {
+ auto src = IPSrc::Static;
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcp = channelCall<getDHCPProperty>(channel);
++ if ((dhcp == dhcpv4) || (dhcp == dhcpv4v6))
+ {
+ src = IPSrc::DHCP;
+ }
+@@ -1877,7 +1936,8 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
+ case LanParam::IPv6RouterControl:
+ {
+ std::bitset<8> control;
+- if (channelCall<getDHCPProperty>(channel))
++ std::string dhcp = channelCall<getDHCPProperty>(channel);
++ if ((dhcp == dhcpv4v6) || (dhcp == dhcpv6))
+ {
+ control[IPv6RouterControlFlag::Dynamic] = 1;
+ }
+@@ -1891,7 +1951,8 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
+ case LanParam::IPv6StaticRouter1IP:
+ {
+ in6_addr gateway{};
+- if (!channelCall<getDHCPProperty>(channel))
++ std::string dhcp = channelCall<getDHCPProperty>(channel);
++ if ((dhcp == dhcpv4) || (dhcp == dhcpoff))
+ {
+ gateway =
+ channelCall<getGatewayProperty<AF_INET6>>(channel).value_or(
+--
+2.24.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch
new file mode 100644
index 000000000..ccf326a91
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch
@@ -0,0 +1,41 @@
+From c1925ab965271875d4e9333be85cdfe8e1516948 Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Fri, 14 Feb 2020 13:13:06 -0800
+Subject: [PATCH] Fix 'Get System GUID' to use settings UUID
+
+The upstream Get System GUID command looks first for a BMC interface
+and then assumes that the UUID interface is next to that. But that is
+not the case on Intel systems where the system GUID is found in the
+settings daemon.
+
+Change-Id: I924bd05e0a546f2b30288c1faf72157296ab6579
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ apphandler.cpp | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index dcfda11..780afbc 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -784,8 +784,6 @@ auto ipmiAppGetBtCapabilities()
+
+ auto ipmiAppGetSystemGuid() -> ipmi::RspType<std::array<uint8_t, 16>>
+ {
+- static constexpr auto bmcInterface =
+- "xyz.openbmc_project.Inventory.Item.Bmc";
+ static constexpr auto uuidInterface = "xyz.openbmc_project.Common.UUID";
+ static constexpr auto uuidProperty = "UUID";
+
+@@ -794,7 +792,7 @@ auto ipmiAppGetSystemGuid() -> ipmi::RspType<std::array<uint8_t, 16>>
+ {
+ // Get the Inventory object implementing BMC interface
+ auto busPtr = getSdBus();
+- auto objectInfo = ipmi::getDbusObject(*busPtr, bmcInterface);
++ auto objectInfo = ipmi::getDbusObject(*busPtr, uuidInterface);
+
+ // Read UUID property value from bmcObject
+ // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch
new file mode 100644
index 000000000..903ae96a7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0053-Fix-keep-looping-issue-when-entering-OS.patch
@@ -0,0 +1,80 @@
+From ad93a6e17310d92ef07b8d367b23c93793562d0f Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@linux.intel.com>
+Date: Wed, 23 Jan 2019 17:02:40 +0800
+Subject: [PATCH] Fix keep looping issue when entering OS
+
+Sometimes when entering OS, OS will keep continuously sending ipmi command
+"READ EVENT MESSAGE BUFFER" to BMC. This issue is caused by incorrect KCS
+status. If restart the host immediately while OS is still running, SMS_ATN
+will be set, after that KCS come into an incorrect status, and then KCS
+communction between BMC and OS crash. To make KCS go back to correct status
+and fix the issue, clear SMS_ATN after every time power cycle happen.
+
+Unit Test:
+ After entered OS, force reset system, after enter OS again, OS can start
+normally without keep sending READ EVENT MESSAGE BUFFER command.
+ After power on system, enter EFI SHELL, check cmdtool.efi can work
+correctly through KCS channel.
+---
+ host-cmd-manager.cpp | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/host-cmd-manager.cpp b/host-cmd-manager.cpp
+index f3aba7f..465eb81 100644
+--- a/host-cmd-manager.cpp
++++ b/host-cmd-manager.cpp
+@@ -26,6 +26,8 @@ constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
+ constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
+ constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host";
+ constexpr auto HOST_TRANS_PROP = "RequestedHostTransition";
++constexpr const char* IPMI_PATH = "/xyz/openbmc_project/Ipmi/Channel/ipmi_kcs3";
++constexpr const char* IPMI_INTERFACE = "xyz.openbmc_project.Ipmi.Channel.SMS";
+
+ // For throwing exceptions
+ using namespace phosphor::logging;
+@@ -106,6 +108,20 @@ void Manager::clearQueue()
+ // `false` indicating Failure
+ std::get<CallBack>(command)(ipmiCmdData, false);
+ }
++
++ auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH);
++ auto method = this->bus.new_method_call(host.c_str(), IPMI_PATH,
++ IPMI_INTERFACE, "clearAttention");
++
++ try
++ {
++ auto reply = this->bus.call(method);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ log<level::ERR>("Error in clearing SMS attention");
++ elog<InternalFailure>();
++ }
+ }
+
+ // Called for alerting the host
+@@ -115,9 +131,6 @@ void Manager::checkQueueAndAlertHost()
+ {
+ log<level::DEBUG>("Asserting SMS Attention");
+
+- std::string IPMI_PATH("/org/openbmc/HostIpmi/1");
+- std::string IPMI_INTERFACE("org.openbmc.HostIpmi");
+-
+ auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH);
+
+ // Start the timer for this transaction
+@@ -131,9 +144,8 @@ void Manager::checkQueueAndAlertHost()
+ return;
+ }
+
+- auto method =
+- this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(),
+- IPMI_INTERFACE.c_str(), "setAttention");
++ auto method = this->bus.new_method_call(host.c_str(), IPMI_PATH,
++ IPMI_INTERFACE, "setAttention");
+ auto reply = this->bus.call(method);
+
+ if (reply.is_method_error())
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch
new file mode 100644
index 000000000..987e61448
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch
@@ -0,0 +1,105 @@
+From f9f260391f099b4e67999f9d4ca05cbf9b422baf Mon Sep 17 00:00:00 2001
+From: "Jia, chunhui" <chunhui.jia@linux.intel.com>
+Date: Tue, 19 Mar 2019 16:09:06 +0800
+Subject: [PATCH] add SetInProgress to get/set boot option cmd
+
+It is required by BIOS. BIOS will check setinprogress first.
+If this flag is not supported, BIOS will bypass all boot
+option flow.
+
+Change-Id: Ibb0501ea5bc36c4f1f72339efef03724dd4e613f
+Signed-off-by: Jia, chunhui <chunhui.jia@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 28 +++++++++++++++++++++++++++-
+ chassishandler.hpp | 3 +++
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 305897b..ee23845 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -1399,6 +1399,10 @@ static ipmi_ret_t setBootMode(const Mode::Modes& mode)
+ return IPMI_CC_OK;
+ }
+
++static constexpr uint8_t setComplete = 0x0;
++static constexpr uint8_t setInProgress = 0x1;
++static uint8_t transferStatus = setComplete;
++
+ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+@@ -1413,11 +1417,21 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
+ IpmiValue bootOption = ipmiDefault;
+
++ if (reqptr->parameter ==
++ static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ {
++ *data_len =
++ static_cast<uint8_t>(BootOptionResponseSize::SET_IN_PROGRESS);
++ resp->version = SET_PARM_VERSION;
++ resp->parm = static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS);
++ resp->data[0] = transferStatus;
++ return IPMI_CC_OK;
++ }
++
+ std::memset(resp, 0, sizeof(*resp));
+ resp->version = SET_PARM_VERSION;
+ resp->parm = 5;
+ resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
+-
+ /*
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+@@ -1553,6 +1567,18 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ // This IPMI command does not have any resposne data
+ *data_len = 0;
+
++ if (reqptr->parameter ==
++ static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS))
++ {
++ if ((transferStatus == setInProgress) &&
++ (reqptr->data[0] != setComplete))
++ {
++ return IPMI_CC_FAIL_SET_IN_PROGRESS;
++ }
++ transferStatus = reqptr->data[0];
++ return IPMI_CC_OK;
++ }
++
+ /* 000101
+ * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
+ * This is the only parameter used by petitboot.
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index dcaf06c..353a929 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -25,6 +25,7 @@ enum ipmi_chassis_return_codes
+ {
+ IPMI_OK = 0x0,
+ IPMI_CC_PARM_NOT_SUPPORTED = 0x80,
++ IPMI_CC_FAIL_SET_IN_PROGRESS = 0x81,
+ };
+
+ // Generic completion codes,
+@@ -46,6 +47,7 @@ enum ipmi_chassis_control_cmds : uint8_t
+ };
+ enum class BootOptionParameter : size_t
+ {
++ SET_IN_PROGRESS = 0x0,
+ BOOT_INFO = 0x4,
+ BOOT_FLAGS = 0x5,
+ OPAL_NETWORK_SETTINGS = 0x61
+@@ -53,6 +55,7 @@ enum class BootOptionParameter : size_t
+
+ enum class BootOptionResponseSize : size_t
+ {
++ SET_IN_PROGRESS = 3,
+ BOOT_FLAGS = 5,
+ OPAL_NETWORK_SETTINGS = 50
+ };
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch
new file mode 100644
index 000000000..bc8c72f13
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch
@@ -0,0 +1,356 @@
+From 1c8cb6b7c99ad85f470aa87095fcfb4de822ddb1 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Wed, 16 Oct 2019 14:24:20 +0800
+Subject: [PATCH 1/1] Move Set SOL config parameter to host-ipmid
+
+Move Set SOL config parameter command from net-ipmid to host-ipmid,
+so that BIOS in Intel platform can enable or disable SOL through KCS.
+Get SOL config parameter command will be moved later.
+
+Tested by:
+With the related change in phospher-ipmi-net and phospher-dbus-interface,
+Run commands:
+ipmitool raw 0x0c 0x21 0x0e 0x00 0x01
+ipmitool raw 0x0c 0x21 0x0e 0x01 0x00
+ipmitool raw 0x0c 0x21 0x0e 0x02 0x03
+ipmitool raw 0x0c 0x21 0x0e 0x03 0x5 0x03
+ipmitool raw 0x0c 0x21 0x0e 0x04 0x5 0x03
+All these commands have correct response and all dbus interface for
+sol command change to same value in above commands.
+After reboot BMC, "Progress" property in dbus interface change back
+to 0 and other properties will not reset to default value.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ transporthandler.cpp | 294 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 295 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 5397115..c93f3b1 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -41,6 +41,7 @@
+ 0x0A:0x48 //<Storage>:<Get SEL Time>
+ 0x0A:0x49 //<Storage>:<Set SEL Time>
+ 0x0C:0x02 //<Transport>:<Get LAN Configuration Parameters>
++0x0C:0x21 //<Transport>:<Set SOL Configuration Parameters>
+ 0x2C:0x00 //<Group Extension>:<Group Extension Command>
+ 0x2C:0x01 //<Group Extension>:<Get DCMI Capabilities>
+ 0x2C:0x02 //<Group Extension>:<Get Power Reading>
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 61065ad..59e38ea 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -1469,8 +1469,298 @@ RspType<message::Payload> getLan(uint4_t channelBits, uint3_t, bool revOnly,
+ } // namespace transport
+ } // namespace ipmi
+
++constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
++constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
++
+ void register_netfn_transport_functions() __attribute__((constructor));
+
++static std::string
++ getSOLService(std::shared_ptr<sdbusplus::asio::connection> dbus,
++ const std::string& solPathWitheEthName)
++{
++ static std::string solService{};
++ if (solService.empty())
++ {
++ try
++ {
++ solService =
++ ipmi::getService(*dbus, solInterface, solPathWitheEthName);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return solService;
++ }
++ }
++ return solService;
++}
++
++static int setSOLParameter(const std::string& property,
++ const ipmi::Value& value, const uint8_t& channelNum)
++{
++ auto dbus = getSdBus();
++
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++
++ std::string solPathWitheEthName = std::string(solPath) + ethdevice;
++
++ std::string service = getSOLService(dbus, solPathWitheEthName);
++ if (service.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get SOL service failed");
++ return -1;
++ }
++ try
++ {
++ ipmi::setDbusProperty(*dbus, service, solPathWitheEthName, solInterface,
++ property, value);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error setting sol parameter");
++ return -1;
++ }
++
++ return 0;
++}
++
++static int getSOLParameter(const std::string& property, ipmi::Value& value,
++ const uint8_t& channelNum)
++{
++ auto dbus = getSdBus();
++
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++
++ std::string solPathWitheEthName = std::string(solPath) + ethdevice;
++
++ std::string service = getSOLService(dbus, solPathWitheEthName);
++ if (service.empty())
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get SOL service failed");
++ return -1;
++ }
++ try
++ {
++ value = ipmi::getDbusProperty(*dbus, service, solPathWitheEthName,
++ solInterface, property);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error getting sol parameter");
++ return -1;
++ }
++
++ return 0;
++}
++
++static const constexpr uint8_t encryptMask = 0x80;
++static const constexpr uint8_t encryptShift = 7;
++static const constexpr uint8_t authMask = 0x40;
++static const constexpr uint8_t authShift = 6;
++static const constexpr uint8_t privilegeMask = 0xf;
++
++namespace ipmi
++{
++constexpr Cc ccParmNotSupported = 0x80;
++constexpr Cc ccSetInProgressActive = 0x81;
++constexpr Cc ccSystemInfoParameterSetReadOnly = 0x82;
++
++static inline auto responseParmNotSupported()
++{
++ return response(ccParmNotSupported);
++}
++static inline auto responseSetInProgressActive()
++{
++ return response(ccSetInProgressActive);
++}
++static inline auto responseSystemInfoParameterSetReadOnly()
++{
++ return response(ccSystemInfoParameterSetReadOnly);
++}
++
++} // namespace ipmi
++
++namespace sol
++{
++enum class Parameter
++{
++ progress, //!< Set In Progress.
++ enable, //!< SOL Enable.
++ authentication, //!< SOL Authentication.
++ accumulate, //!< Character Accumulate Interval & Send Threshold.
++ retry, //!< SOL Retry.
++ nvbitrate, //!< SOL non-volatile bit rate.
++ vbitrate, //!< SOL volatile bit rate.
++ channel, //!< SOL payload channel.
++ port, //!< SOL payload port.
++};
++
++enum class Privilege : uint8_t
++{
++ highestPriv,
++ callbackPriv,
++ userPriv,
++ operatorPriv,
++ adminPriv,
++ oemPriv,
++};
++
++} // namespace sol
++
++constexpr uint8_t progressMask = 0x03;
++constexpr uint8_t enableMask = 0x01;
++constexpr uint8_t retryMask = 0x07;
++
++ipmi::RspType<> setSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum,
++ uint4_t reserved, uint8_t paramSelector,
++ uint8_t configParamData1,
++ std::optional<uint8_t> configParamData2)
++{
++ ipmi::ChannelInfo chInfo;
++ uint8_t channelNum = ipmi::convertCurrentChannelNum(
++ static_cast<uint8_t>(chNum), ctx->channel);
++ if (reserved != 0 ||
++ (!ipmi::isValidChannel(static_cast<uint8_t>(channelNum))))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ ipmi_ret_t compCode =
++ ipmi::getChannelInfo(static_cast<uint8_t>(channelNum), chInfo);
++ if (compCode != IPMI_CC_OK ||
++ chInfo.mediumType !=
++ static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ switch (static_cast<sol::Parameter>(paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ uint8_t progress = configParamData1 & progressMask;
++ ipmi::Value currentProgress = 0;
++ if (getSOLParameter("Progress", currentProgress, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ if ((std::get<uint8_t>(currentProgress) == 1) && (progress == 1))
++ {
++ return ipmi::responseSetInProgressActive();
++ }
++
++ if (setSOLParameter("Progress", progress, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::enable:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ bool enable = configParamData1 & enableMask;
++ if (setSOLParameter("Enable", enable, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::authentication:
++ {
++ if (configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ uint8_t encrypt = (configParamData1 & encryptMask) >> encryptShift;
++ uint8_t auth = (configParamData1 & authMask) >> authShift;
++ uint8_t privilege = configParamData1 & privilegeMask;
++ // For security considering encryption and authentication must be
++ // true.
++ if (!encrypt || !auth)
++ {
++ return ipmi::responseSystemInfoParameterSetReadOnly();
++ }
++ else if (privilege <
++ static_cast<uint8_t>(sol::Privilege::userPriv) ||
++ privilege > static_cast<uint8_t>(sol::Privilege::oemPriv))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ if (setSOLParameter("Privilege", privilege, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ break;
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (!configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if (*configParamData2 == 0)
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ if (setSOLParameter("AccumulateIntervalMS", configParamData1,
++ channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ if (setSOLParameter("Threshold", *configParamData2, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ break;
++ }
++ case sol::Parameter::retry:
++ {
++ if (!configParamData2)
++ {
++ return ipmi::responseReqDataLenInvalid();
++ }
++ if ((setSOLParameter(
++ "RetryCount",
++ static_cast<uint8_t>(configParamData1 & retryMask),
++ channelNum) < 0) ||
++ (setSOLParameter("RetryIntervalMS", *configParamData2,
++ channelNum) < 0))
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ break;
++ }
++ case sol::Parameter::port:
++ {
++ return ipmi::responseSystemInfoParameterSetReadOnly();
++ }
++ case sol::Parameter::nvbitrate:
++ case sol::Parameter::vbitrate:
++ case sol::Parameter::channel:
++ default:
++ return ipmi::responseParmNotSupported();
++ }
++
++ return ipmi::responseSuccess();
++}
++
+ void register_netfn_transport_functions()
+ {
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+@@ -1479,4 +1769,8 @@ void register_netfn_transport_functions()
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+ ipmi::transport::cmdGetLanConfigParameters,
+ ipmi::Privilege::Operator, ipmi::transport::getLan);
++
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
++ ipmi::transport::cmdSetSolConfigParameters,
++ ipmi::Privilege::Admin, setSOLConfParams);
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch
new file mode 100644
index 000000000..61ac5fede
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch
@@ -0,0 +1,259 @@
+From b5400c4bc756a800fbeb4cc53117956fb59dc57d Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Thu, 11 Jul 2019 00:32:58 +0800
+Subject: [PATCH 1/1] Move Get SOL config parameter to host-ipmid
+
+Move Get SOL config parameter command from net-ipmid to host-ipmid.
+
+Tested:
+Run command ipmitool sol info 1
+Set in progress : set-complete
+Enabled : true
+Force Encryption : false
+Force Authentication : false
+Privilege Level : ADMINISTRATOR
+Character Accumulate Level (ms) : 60
+Character Send Threshold : 96
+Retry Count : 6
+Retry Interval (ms) : 200
+Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Non-Volatile Bit Rate (kbps) : 115.2
+Payload Channel : 1 (0x01)
+Payload Port : 623
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ transporthandler.cpp | 191 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 192 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index c93f3b1..730437d 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -42,6 +42,7 @@
+ 0x0A:0x49 //<Storage>:<Set SEL Time>
+ 0x0C:0x02 //<Transport>:<Get LAN Configuration Parameters>
+ 0x0C:0x21 //<Transport>:<Set SOL Configuration Parameters>
++0x0C:0x22 //<Transport>:<Get SOL Configuration Parameters>
+ 0x2C:0x00 //<Group Extension>:<Group Extension Command>
+ 0x2C:0x01 //<Group Extension>:<Get DCMI Capabilities>
+ 0x2C:0x02 //<Group Extension>:<Get Power Reading>
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 59e38ea..b64953f 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -1559,6 +1559,28 @@ static int getSOLParameter(const std::string& property, ipmi::Value& value,
+ return 0;
+ }
+
++constexpr const char* consoleInterface = "xyz.openbmc_project.console";
++constexpr const char* consolePath = "/xyz/openbmc_project/console";
++static int getSOLBaudRate(ipmi::Value& value)
++{
++ auto dbus = getSdBus();
++
++ try
++ {
++ value =
++ ipmi::getDbusProperty(*dbus, "xyz.openbmc_project.console",
++ consolePath, consoleInterface, "baudrate");
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error getting sol baud rate");
++ return -1;
++ }
++
++ return 0;
++}
++
+ static const constexpr uint8_t encryptMask = 0x80;
+ static const constexpr uint8_t encryptShift = 7;
+ static const constexpr uint8_t authMask = 0x40;
+@@ -1761,6 +1783,171 @@ ipmi::RspType<> setSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum,
+ return ipmi::responseSuccess();
+ }
+
++static const constexpr uint8_t retryCountMask = 0x07;
++static constexpr uint16_t ipmiStdPort = 623;
++static constexpr uint8_t solParameterRevision = 0x11;
++ipmi::RspType<uint8_t, std::optional<uint8_t>, std::optional<uint8_t>>
++ getSOLConfParams(ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved,
++ bool getParamRev, uint8_t paramSelector,
++ uint8_t setSelector, uint8_t blockSelector)
++{
++ ipmi::ChannelInfo chInfo;
++ uint8_t channelNum = ipmi::convertCurrentChannelNum(
++ static_cast<uint8_t>(chNum), ctx->channel);
++ if (reserved != 0 ||
++ (!ipmi::isValidChannel(static_cast<uint8_t>(channelNum))) ||
++ (ipmi::EChannelSessSupported::none ==
++ ipmi::getChannelSessionSupport(static_cast<uint8_t>(channelNum))))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++ ipmi_ret_t compCode =
++ ipmi::getChannelInfo(static_cast<uint8_t>(channelNum), chInfo);
++ if (compCode != IPMI_CC_OK ||
++ chInfo.mediumType !=
++ static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
++ {
++ return ipmi::responseInvalidFieldRequest();
++ }
++
++ if (getParamRev)
++ {
++ return ipmi::responseSuccess(solParameterRevision, std::nullopt,
++ std::nullopt);
++ }
++
++ ipmi::Value value;
++ switch (static_cast<sol::Parameter>(paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ if (getSOLParameter("Progress", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision, std::get<uint8_t>(value), std::nullopt);
++ }
++ case sol::Parameter::enable:
++ {
++ if (getSOLParameter("Enable", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision,
++ static_cast<uint8_t>(std::get<bool>(value)), std::nullopt);
++ }
++ case sol::Parameter::authentication:
++ {
++ uint8_t authentication = 0;
++ if (getSOLParameter("Privilege", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication = (std::get<uint8_t>(value) & 0x0f);
++
++ if (getSOLParameter("ForceAuthentication", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 6);
++
++ if (getSOLParameter("ForceEncryption", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 7);
++ return ipmi::responseSuccess(solParameterRevision, authentication,
++ std::nullopt);
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (getSOLParameter("AccumulateIntervalMS", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ ipmi::Value value1;
++ if (getSOLParameter("Threshold", value1, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(solParameterRevision,
++ std::get<uint8_t>(value),
++ std::get<uint8_t>(value1));
++ }
++ case sol::Parameter::retry:
++ {
++ if (getSOLParameter("RetryCount", value, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++
++ ipmi::Value value1;
++ if (getSOLParameter("RetryIntervalMS", value1, channelNum) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ return ipmi::responseSuccess(
++ solParameterRevision, std::get<uint8_t>(value) & retryCountMask,
++ std::get<uint8_t>(value1));
++ }
++ case sol::Parameter::channel:
++ {
++ return ipmi::responseSuccess(solParameterRevision, channelNum,
++ std::nullopt);
++ }
++ case sol::Parameter::port:
++ {
++ uint16_t port = htole16(ipmiStdPort);
++ auto buffer = reinterpret_cast<const uint8_t*>(&port);
++ return ipmi::responseSuccess(solParameterRevision, buffer[0],
++ buffer[1]);
++ }
++ case sol::Parameter::nvbitrate:
++ {
++ if (getSOLBaudRate(value) < 0)
++ {
++ return ipmi::responseUnspecifiedError();
++ }
++ uint8_t bitRate = 0;
++ uint32_t* pBaudRate = std::get_if<uint32_t>(&value);
++ if (!pBaudRate)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get valid baud rate from D-Bus interface");
++ }
++ switch (*pBaudRate)
++ {
++ case 9600:
++ bitRate = 0x06;
++ break;
++ case 19200:
++ bitRate = 0x07;
++ break;
++ case 38400:
++ bitRate = 0x08;
++ break;
++ case 57600:
++ bitRate = 0x09;
++ break;
++ case 115200:
++ bitRate = 0x0a;
++ break;
++ default:
++ break;
++ }
++ return ipmi::responseSuccess(solParameterRevision, bitRate,
++ std::nullopt);
++ }
++ default:
++ return ipmi::responseParmNotSupported();
++ }
++}
++
+ void register_netfn_transport_functions()
+ {
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+@@ -1773,4 +1960,8 @@ void register_netfn_transport_functions()
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
+ ipmi::transport::cmdSetSolConfigParameters,
+ ipmi::Privilege::Admin, setSOLConfParams);
++
++ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnTransport,
++ ipmi::transport::cmdGetSolConfigParameters,
++ ipmi::Privilege::User, getSOLConfParams);
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch
new file mode 100644
index 000000000..96e45cad3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch
@@ -0,0 +1,291 @@
+From 92bdbcd90a445e49ba2f8e483d44ec41152d32b4 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 3 Jun 2019 17:01:47 -0700
+Subject: [PATCH] Update IPMI Chassis Control command
+
+This change updates the IPMI Chassis Control command to use the new
+host state transitions. This allows each chassis control action
+to more closely follow the behavior defined in the IPMI spec.
+
+ref: https://gerrit.openbmc-project.xyz/c/openbmc/docs/+/22358
+
+Tested:
+Ran each IPMI chassis control command to confirm the expected
+behavior:
+ipmitool power on: system is powered-on
+ipmitool power off: system is forced off
+ipmitool power cycle: system is forced off then powered-on
+ipmitool power reset: system is hard reset
+ipmitool power soft: soft power-off requested from system software
+
+Change-Id: Ic9fba3ca4abd9a758eb88f1e6ee09f7ca64ff80a
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ chassishandler.cpp | 206 +++++++++++++----------------------------------------
+ 1 file changed, 50 insertions(+), 156 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 0326806..8bfab88 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -31,6 +31,7 @@
+ #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
+ #include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
+ #include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
++#include <xyz/openbmc_project/State/Chassis/server.hpp>
+ #include <xyz/openbmc_project/State/Host/server.hpp>
+ #include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
+
+@@ -717,59 +718,63 @@ ipmi::RspType<> ipmiSetChassisCap(bool intrusion, bool fpLockout,
+ //------------------------------------------
+ // Calls into Host State Manager Dbus object
+ //------------------------------------------
+-int initiate_state_transition(State::Host::Transition transition)
++int initiateHostStateTransition(State::Host::Transition transition)
+ {
+ // OpenBMC Host State Manager dbus framework
+- constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
+- constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
+- constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+- constexpr auto PROPERTY = "RequestedHostTransition";
++ constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0";
++ constexpr auto hostStateIntf = "xyz.openbmc_project.State.Host";
+
+- // sd_bus error
+- int rc = 0;
+- char* busname = NULL;
++ auto service = ipmi::getService(*getSdBus(), hostStateIntf, hostStatePath);
+
+- // SD Bus error report mechanism.
+- sd_bus_error bus_error = SD_BUS_ERROR_NULL;
++ // Convert to string equivalent of the passed in transition enum.
++ auto request = State::convertForMessage(transition);
+
+- // Gets a hook onto either a SYSTEM or SESSION bus
+- sd_bus* bus_type = ipmid_get_sd_bus_connection();
+- rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
+- if (rc < 0)
++ try
++ {
++ ipmi::setDbusProperty(*getSdBus(), service, hostStatePath,
++ hostStateIntf, "RequestedHostTransition",
++ request);
++ }
++ catch (std::exception& e)
+ {
+ log<level::ERR>(
+- "Failed to get bus name",
+- entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
+- return rc;
++ "Failed to initiate transition",
++ entry("EXCEPTION=%s, REQUEST=%s", e.what(), request.c_str()));
++ return -1;
+ }
++ return 0;
++}
++
++//------------------------------------------
++// Calls into Chassis State Manager Dbus object
++//------------------------------------------
++int initiateChassisStateTransition(State::Chassis::Transition transition)
++{
++ // OpenBMC Chassis State Manager dbus framework
++ constexpr auto chassisStatePath = "/xyz/openbmc_project/state/chassis0";
++ constexpr auto chassisStateIntf = "xyz.openbmc_project.State.Chassis";
++
++ auto service =
++ ipmi::getService(*getSdBus(), chassisStateIntf, chassisStatePath);
+
+ // Convert to string equivalent of the passed in transition enum.
+ auto request = State::convertForMessage(transition);
+
+- rc = sd_bus_call_method(bus_type, // On the system bus
+- busname, // Service to contact
+- HOST_STATE_MANAGER_ROOT, // Object path
+- DBUS_PROPERTY_IFACE, // Interface name
+- "Set", // Method to be called
+- &bus_error, // object to return error
+- nullptr, // Response buffer if any
+- "ssv", // Takes 3 arguments
+- HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
+- request.c_str());
+- if (rc < 0)
+- {
+- log<level::ERR>("Failed to initiate transition",
+- entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
++ try
++ {
++ ipmi::setDbusProperty(*getSdBus(), service, chassisStatePath,
++ chassisStateIntf, "RequestedPowerTransition",
++ request);
+ }
+- else
++ catch (std::exception& e)
+ {
+- log<level::INFO>("Transition request initiated successfully");
++ log<level::ERR>(
++ "Failed to initiate transition",
++ entry("EXCEPTION=%s, REQUEST=%s", e.what(), request.c_str()));
++ return -1;
+ }
+
+- sd_bus_error_free(&bus_error);
+- free(busname);
+-
+- return rc;
++ return 0;
+ }
+
+ //------------------------------------------
+@@ -1071,76 +1076,6 @@ ipmi::RspType<bool, // Power is on
+ diagButtonDisableAllow, sleepButtonDisableAllow);
+ }
+
+-//-------------------------------------------------------------
+-// Send a command to SoftPowerOff application to stop any timer
+-//-------------------------------------------------------------
+-int stop_soft_off_timer()
+-{
+- constexpr auto iface = "org.freedesktop.DBus.Properties";
+- constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
+- "SoftPowerOff";
+-
+- constexpr auto property = "ResponseReceived";
+- constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
+- "SoftPowerOff.HostResponse.HostShutdown";
+-
+- // Get the system bus where most system services are provided.
+- auto bus = ipmid_get_sd_bus_connection();
+-
+- // Get the service name
+- // TODO openbmc/openbmc#1661 - Mapper refactor
+- //
+- // See openbmc/openbmc#1743 for some details but high level summary is that
+- // for now the code will directly call the soft off interface due to a
+- // race condition with mapper usage
+- //
+- // char *busname = nullptr;
+- // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
+- // if (r < 0)
+- //{
+- // fprintf(stderr, "Failed to get %s bus name: %s\n",
+- // SOFTOFF_OBJPATH, -r);
+- // return r;
+- //}
+-
+- // No error object or reply expected.
+- int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
+- "Set", nullptr, nullptr, "ssv", soft_off_iface,
+- property, "s", value);
+- if (rc < 0)
+- {
+- log<level::ERR>("Failed to set property in SoftPowerOff object",
+- entry("ERRNO=0x%X", -rc));
+- }
+-
+- // TODO openbmc/openbmc#1661 - Mapper refactor
+- // free(busname);
+- return rc;
+-}
+-
+-//----------------------------------------------------------------------
+-// Create file to indicate there is no need for softoff notification to host
+-//----------------------------------------------------------------------
+-void indicate_no_softoff_needed()
+-{
+- fs::path path{HOST_INBAND_REQUEST_DIR};
+- if (!fs::is_directory(path))
+- {
+- fs::create_directory(path);
+- }
+-
+- // Add the host instance (default 0 for now) to the file name
+- std::string file{HOST_INBAND_REQUEST_FILE};
+- auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
+- size++; // null
+- std::unique_ptr<char[]> buf(new char[size]);
+- std::snprintf(buf.get(), size, file.c_str(), 0);
+-
+- // Append file name to directory and create it
+- path /= buf.get();
+- std::ofstream(path.c_str());
+-}
+-
+ /** @brief Implementation of chassis control command
+ *
+ * @param - chassisControl command byte
+@@ -1153,63 +1088,22 @@ ipmi::RspType<> ipmiChassisControl(uint8_t chassisControl)
+ switch (chassisControl)
+ {
+ case CMD_POWER_ON:
+- rc = initiate_state_transition(State::Host::Transition::On);
++ rc = initiateHostStateTransition(State::Host::Transition::On);
+ break;
+ case CMD_POWER_OFF:
+- // This path would be hit in 2 conditions.
+- // 1: When user asks for power off using ipmi chassis command 0x04
+- // 2: Host asking for power off post shutting down.
+-
+- // If it's a host requested power off, then need to nudge Softoff
+- // application that it needs to stop the watchdog timer if running.
+- // If it is a user requested power off, then this is not really
+- // needed. But then we need to differentiate between user and host
+- // calling this same command
+-
+- // For now, we are going ahead with trying to nudge the soft off and
+- // interpret the failure to do so as a non softoff case
+- rc = stop_soft_off_timer();
+-
+- // Only request the Off transition if the soft power off
+- // application is not running
+- if (rc < 0)
+- {
+- // First create a file to indicate to the soft off application
+- // that it should not run. Not doing this will result in State
+- // manager doing a default soft power off when asked for power
+- // off.
+- indicate_no_softoff_needed();
+-
+- // Now request the shutdown
+- rc = initiate_state_transition(State::Host::Transition::Off);
+- }
+- else
+- {
+- log<level::INFO>("Soft off is running, so let shutdown target "
+- "stop the host");
+- }
++ rc =
++ initiateChassisStateTransition(State::Chassis::Transition::Off);
+ break;
+-
+ case CMD_HARD_RESET:
++ rc = initiateHostStateTransition(
++ State::Host::Transition::ForceWarmReboot);
++ break;
+ case CMD_POWER_CYCLE:
+- // SPEC has a section that says certain implementations can trigger
+- // PowerOn if power is Off when a command to power cycle is
+- // requested
+-
+- // First create a file to indicate to the soft off application
+- // that it should not run since this is a direct user initiated
+- // power reboot request (i.e. a reboot request that is not
+- // originating via a soft power off SMS request)
+- indicate_no_softoff_needed();
+-
+- rc = initiate_state_transition(State::Host::Transition::Reboot);
++ rc = initiateHostStateTransition(State::Host::Transition::Reboot);
+ break;
+-
+ case CMD_SOFT_OFF_VIA_OVER_TEMP:
+- // Request Host State Manager to do a soft power off
+- rc = initiate_state_transition(State::Host::Transition::Off);
++ rc = initiateHostStateTransition(State::Host::Transition::Off);
+ break;
+-
+ case CMD_PULSE_DIAGNOSTIC_INTR:
+ rc = setNmiProperty(true);
+ break;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch
new file mode 100644
index 000000000..aac0850ea
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch
@@ -0,0 +1,140 @@
+From d9c89943d7b0aa00ee99b7c11278ac272a47a790 Mon Sep 17 00:00:00 2001
+From: Ren Yu <yux.ren@intel.com>
+Date: Tue, 28 May 2019 17:11:17 +0800
+Subject: [PATCH] Save the pre-timeout interrupt in dbus property
+
+Get the watchdog pre-timeout interrupt value from ipmi watchdog set command,
+and store it into dbus property.
+
+Tested:
+Config IPMI watchdog: BIOS FRB2 Power Cycle after 1 seconds:
+ipmitool raw 0x06 0x24 0x01 0x13 0x0 0x2 0xa 0x00
+Start watchdog:
+Ipmitool mc watchdog reset
+Check the watchdog pre-timeout interrupt in below:
+https://BMCIP/redfish/v1/Systems/system/LogServices/EventLog/Entries
+
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+---
+ app/watchdog.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ app/watchdog_service.cpp | 6 ++++++
+ app/watchdog_service.hpp | 9 +++++++++
+ 3 files changed, 62 insertions(+)
+
+diff --git a/app/watchdog.cpp b/app/watchdog.cpp
+index 2ffaae3..e9b7a9c 100644
+--- a/app/watchdog.cpp
++++ b/app/watchdog.cpp
+@@ -81,6 +81,7 @@ ipmi::RspType<> ipmiAppResetWatchdogTimer()
+
+ static constexpr uint8_t wd_dont_stop = 0x1 << 6;
+ static constexpr uint8_t wd_timeout_action_mask = 0x3;
++static constexpr uint8_t wdPreTimeoutInterruptMask = 0x3;
+
+ static constexpr uint8_t wdTimerUseMask = 0x7;
+ static constexpr uint8_t wdTimerUseResTimer1 = 0x0;
+@@ -130,6 +131,45 @@ WatchdogService::Action ipmiActionToWdAction(IpmiAction ipmi_action)
+ }
+ }
+
++enum class IpmiPreTimeoutInterrupt : uint8_t
++{
++ None = 0x0,
++ SMI = 0x1,
++ NMI = 0x2,
++ MI = 0x3,
++};
++/** @brief Converts an IPMI Watchdog PreTimeoutInterrupt to DBUS defined action
++ * @param[in] ipmi_action The IPMI Watchdog PreTimeoutInterrupt
++ * @return The Watchdog PreTimeoutInterrupt that the ipmi_action maps to
++ */
++WatchdogService::PreTimeoutInterruptAction ipmiPreTimeoutInterruptToWdAction(
++ IpmiPreTimeoutInterrupt ipmiPreTimeOutInterrupt)
++{
++ switch (ipmiPreTimeOutInterrupt)
++ {
++ case IpmiPreTimeoutInterrupt::None:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::None;
++ }
++ case IpmiPreTimeoutInterrupt::SMI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::SMI;
++ }
++ case IpmiPreTimeoutInterrupt::NMI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::NMI;
++ }
++ case IpmiPreTimeoutInterrupt::MI:
++ {
++ return WatchdogService::PreTimeoutInterruptAction::MI;
++ }
++ default:
++ {
++ throw std::domain_error("IPMI PreTimeoutInterrupt is invalid");
++ }
++ }
++}
++
+ enum class IpmiTimerUse : uint8_t
+ {
+ Reserved = 0x0,
+@@ -257,6 +297,13 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ // Mark as initialized so that future resets behave correctly
+ wd_service.setInitialized(true);
+
++ // pretimeOutAction
++ const auto ipmiPreTimeoutInterrupt =
++ static_cast<IpmiPreTimeoutInterrupt>(wdPreTimeoutInterruptMask &
++ (static_cast<uint8_t>(preTimeoutInterrupt)));
++ wd_service.setPreTimeoutInterrupt(
++ ipmiPreTimeoutInterruptToWdAction(ipmiPreTimeoutInterrupt));
++
+ lastCallSuccessful = true;
+ return IPMI_CC_OK;
+ }
+diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp
+index 77663b4..0c4ea28 100644
+--- a/app/watchdog_service.cpp
++++ b/app/watchdog_service.cpp
+@@ -203,3 +203,9 @@ void WatchdogService::setTimeRemaining(uint64_t timeRemaining)
+ {
+ setProperty("TimeRemaining", timeRemaining);
+ }
++
++void WatchdogService::setPreTimeoutInterrupt(
++ PreTimeoutInterruptAction preTimeoutInterrupt)
++{
++ setProperty("PreTimeoutInterrupt", convertForMessage(preTimeoutInterrupt));
++}
+\ No newline at end of file
+diff --git a/app/watchdog_service.hpp b/app/watchdog_service.hpp
+index ed64a3c..b550f37 100644
+--- a/app/watchdog_service.hpp
++++ b/app/watchdog_service.hpp
+@@ -15,6 +15,8 @@ class WatchdogService
+
+ using Action =
+ sdbusplus::xyz::openbmc_project::State::server::Watchdog::Action;
++ using PreTimeoutInterruptAction = sdbusplus::xyz::openbmc_project::State::
++ server::Watchdog::PreTimeoutInterruptAction;
+ using TimerUse =
+ sdbusplus::xyz::openbmc_project::State::server::Watchdog::TimerUse;
+
+@@ -99,6 +101,13 @@ class WatchdogService
+ */
+ void setTimeRemaining(uint64_t timeRemaining);
+
++ /** @brief Sets the value of the PreTimeoutInterrupt property on the host
++ * watchdog
++ *
++ * @param[in] PreTimeoutInterrupt - The new PreTimeoutInterrupt value
++ */
++ void setPreTimeoutInterrupt(PreTimeoutInterruptAction preTimeoutInterrupt);
++
+ private:
+ /** @brief sdbusplus handle */
+ sdbusplus::bus::bus bus;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
new file mode 100644
index 000000000..1e45ee6c9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Phosphor Inband IPMI
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+ExecStart=/usr/bin/env ipmid
+SyslogIdentifier=ipmid
+RuntimeDirectory = ipmi
+RuntimeDirectoryPreserve = yes
+StateDirectory = ipmi
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/transporthandler_oem.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/transporthandler_oem.cpp
new file mode 100644
index 000000000..856a80fbc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/transporthandler_oem.cpp
@@ -0,0 +1,147 @@
+/* Copyright 2019 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dcmihandler.hpp"
+
+#include <cstdint>
+#include <ipmid/api-types.hpp>
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+#include <ipmid/message/types.hpp>
+#include <ipmid/utils.hpp>
+#include <vector>
+
+enum class oemLanParam : uint8_t
+{
+ intelHostnameConfig = 0xc7,
+};
+
+constexpr size_t IpmiHostnameLen = 16;
+constexpr uint8_t CurrentRevision = 0x11; // Current rev per IPMI Spec 2.0
+
+constexpr ipmi::Cc ccParamNotSupported = 0x80;
+constexpr ipmi::Cc ccUnprintable = 0x90;
+
+namespace ipmi::transport
+{
+
+constexpr auto validHostnameChars =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX"
+ "YZ0123456789-";
+constexpr int lanOemHostnameLength = 64;
+
+RspType<> setLanOem(uint8_t channel, uint8_t parameter, message::Payload& req)
+{
+ std::vector<uint8_t> dataBytes;
+ switch (static_cast<oemLanParam>(parameter))
+ {
+ case oemLanParam::intelHostnameConfig:
+ {
+ static std::array<uint8_t, lanOemHostnameLength> blockData;
+ uint8_t block = 0;
+ uint8_t complete = 0;
+ if ((req.unpack(block, complete, dataBytes) != 0) ||
+ (!req.fullyUnpacked()))
+ {
+ return responseReqDataLenInvalid();
+ }
+
+ size_t numDataBytes = req.size() - 4;
+ if ((numDataBytes > IpmiHostnameLen) ||
+ (!complete && (numDataBytes < IpmiHostnameLen)))
+ {
+ return responseReqDataLenInvalid();
+ }
+
+ if (!((block > 0) && (block < 5)) ||
+ ((complete != 0) && (complete != 1)))
+ {
+ return responseInvalidFieldRequest();
+ }
+
+ if (block == 1)
+ {
+ blockData.fill(0);
+ }
+
+ std::copy(dataBytes.begin(), dataBytes.end(),
+ blockData.data() + ((block - 1) * IpmiHostnameLen));
+ if (complete)
+ {
+ blockData[lanOemHostnameLength - 1] = 0;
+ // check hostname, and write it
+ std::string newHostname(
+ reinterpret_cast<char*>(blockData.data()),
+ lanOemHostnameLength);
+ size_t firstNull = newHostname.find_first_of('\0');
+ if (newHostname.find_first_not_of(validHostnameChars) !=
+ firstNull)
+ {
+ return response(ccUnprintable);
+ }
+ std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
+ ipmi::setDbusProperty(*busp, ::dcmi::networkServiceName,
+ ::dcmi::networkConfigObj,
+ ::dcmi::networkConfigIntf,
+ ::dcmi::hostNameProp, newHostname);
+ }
+ return responseSuccess();
+ }
+ default:
+ return response(ccParamNotSupported);
+ }
+ return response(ccParamNotSupported);
+}
+
+RspType<message::Payload> getLanOem(uint8_t channel, uint8_t parameter,
+ uint8_t set, uint8_t block)
+{
+ message::Payload message;
+ message.pack(CurrentRevision);
+ oemLanParam param = static_cast<oemLanParam>(parameter);
+ switch (param)
+ {
+ case oemLanParam::intelHostnameConfig:
+ {
+ if (set != 0)
+ {
+ return responseInvalidFieldRequest();
+ }
+ if ((block < 1) || (block > 4))
+ {
+ return responseInvalidFieldRequest();
+ }
+ std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
+ auto service = ipmi::getService(*busp, ::dcmi::networkConfigIntf,
+ ::dcmi::networkConfigObj);
+ auto value = ipmi::getDbusProperty(
+ *busp, service, ::dcmi::networkConfigObj,
+ ::dcmi::networkConfigIntf, ::dcmi::hostNameProp);
+ std::string hostname = std::get<std::string>(value);
+ std::array<char, IpmiHostnameLen> buf = {0};
+ size_t head = (block - 1) * IpmiHostnameLen;
+ if (head < hostname.size())
+ {
+ size_t numToCopy = hostname.size() - head;
+ numToCopy = std::min(IpmiHostnameLen, numToCopy);
+ hostname.copy(buf.data(), numToCopy, head);
+ }
+ message.pack(buf);
+ return responseSuccess(std::move(message));
+ }
+ }
+ return response(ccParamNotSupported);
+}
+} // namespace ipmi::transport
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
new file mode 100644
index 000000000..6f27959a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -0,0 +1,44 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+PROJECT_SRC_DIR := "${THISDIR}/${PN}"
+
+# latest upstream HEAD until meta-phosphor autobumps
+SRCREV = "6ba8d31525130dbb5ef5b60336993ef7b50a8f51"
+
+SRC_URI += "file://phosphor-ipmi-host.service \
+ file://0010-fix-get-system-GUID-ipmi-command.patch \
+ file://0053-Fix-keep-looping-issue-when-entering-OS.patch \
+ file://0056-add-SetInProgress-to-get-set-boot-option-cmd.patch \
+ file://0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch \
+ file://0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch \
+ file://0062-Update-IPMI-Chassis-Control-command.patch \
+ file://0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch \
+ file://0001-Modify-Get-Lan-Configuration-IP-Address-Source-to-us.patch \
+ "
+
+EXTRA_OECONF_append = " --disable-i2c-whitelist-check"
+EXTRA_OECONF_append = " --enable-transport-oem=yes"
+EXTRA_OECONF_append = " --disable-boot-flag-safe-mode-support"
+EXTRA_OECONF_append = " --disable-ipmi-whitelist"
+
+RDEPENDS_${PN}_remove = "clear-once"
+
+# remove the softpoweroff service since we do not need it
+SYSTEMD_SERVICE_${PN}_remove += " \
+ xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service"
+
+SYSTEMD_LINK_${PN}_remove += " \
+ ../xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service:obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \
+ "
+FILES_${PN}_remove = " \
+ ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/ \
+ ${systemd_unitdir}/system/obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \
+ "
+
+do_compile_prepend(){
+ cp -f ${PROJECT_SRC_DIR}/transporthandler_oem.cpp ${S}
+}
+
+do_install_append(){
+ rm -f ${D}/${bindir}/phosphor-softpoweroff
+ rm -f ${S}/transporthandler_oem.cpp
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb/0001-Add-dbus-method-SlotIpmbRequest.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb/0001-Add-dbus-method-SlotIpmbRequest.patch
new file mode 100644
index 000000000..3f01cd2c8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb/0001-Add-dbus-method-SlotIpmbRequest.patch
@@ -0,0 +1,536 @@
+From 644165bf32fd6e757c261881987d127a865cbf2b Mon Sep 17 00:00:00 2001
+From: Rajashekar Gade Reddy <raja.sekhar.reddy.gade@linux.intel.com>
+Date: Mon, 23 Mar 2020 22:19:07 +0530
+Subject: [PATCH] Add dbus method SlotIpmbRequest
+
+Added dbus method SlotIpmbRequest which enables the applications to
+communicate with add-in cards.
+
+This is submitted in down stream because SlotIpmbRequest uses hold and
+unhold mux kernel patches which are downstream only patches.
+
+Tested:
+
+busctl call xyz.openbmc_project.Ipmi.Channel.Ipmb
+/xyz/openbmc_project/Ipmi/Channel/Ipmb org.openbmc.Ipmb SlotIpmbRequest
+"yyyyyay" <valid_addressType> <valid_slot> <valid_slaveAddr> <valid_netFun> <valid_cmd> <data> // method call
+(iyyyyay) 0 7 0 1 0 15 0 0 0 0 2 12 87 1 0 0 0 0 0 0 0 // success
+
+busctl call xyz.openbmc_project.Ipmi.Channel.Ipmb
+/xyz/openbmc_project/Ipmi/Channel/Ipmb org.openbmc.Ipmb SlotIpmbRequest
+"yyyyyay" <valid_addressType> <invalid_slot> <valid_slaveAddr> <valid_netFun> <valid_cmd> <data> // method call
+(iyyyyay) 4 0 0 0 0 0 // failure
+
+busctl call xyz.openbmc_project.Ipmi.Channel.Ipmb
+/xyz/openbmc_project/Ipmi/Channel/Ipmb org.openbmc.Ipmb SlotIpmbRequest
+"yyyyyay" <valid_addressType> <valid_slot> <invalid_slaveAddr> <valid_netFun> <valid_cmd> <data> // method call
+(iyyyyay) 4 0 0 0 0 0 // failure
+
+//This ipmi command internally calls the dbus method SlotIpmbRequest.
+ipmitool raw 0x3e 0x51 0 0x01 0xb0 0x6 1
+00 00 00 00 00 02 0c 57 01 00 00 00 00 00 00 00 //success
+
+Note: Tested for all possible negative test cases and it works fine.
+
+Signed-off-by: Rajashekar Gade Reddy <raja.sekhar.reddy.gade@intel.com>
+
+%% original patch: 0001-Add-dbus-method-SlotIpmbRequest.patch
+---
+ CMakeLists.txt | 2 +-
+ include/linux/i2c.h | 159 ++++++++++++++++++++++++++++++++
+ ipmb-channels.json | 6 ++
+ ipmbbridged.cpp | 220 +++++++++++++++++++++++++++++++++++++++++++-
+ ipmbbridged.hpp | 8 +-
+ 5 files changed, 391 insertions(+), 4 deletions(-)
+ create mode 100644 include/linux/i2c.h
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 80377f5..1436d5e 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -5,7 +5,7 @@ set (CMAKE_CXX_STANDARD_REQUIRED ON)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
+-include_directories (${CMAKE_CURRENT_SOURCE_DIR})
++include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
+ find_package (Boost REQUIRED)
+ include_directories (${Boost_INCLUDE_DIRS})
+ add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY)
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+new file mode 100644
+index 0000000..a1db9b1
+--- /dev/null
++++ b/include/linux/i2c.h
+@@ -0,0 +1,159 @@
++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
++/* ------------------------------------------------------------------------- */
++/* */
++/* i2c.h - definitions for the i2c-bus interface */
++/* */
++/* ------------------------------------------------------------------------- */
++/* Copyright (C) 1995-2000 Simon G. Vogl
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ MA 02110-1301 USA. */
++/* ------------------------------------------------------------------------- */
++
++/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
++ Frodo Looijaard <frodol@dds.nl> */
++
++#ifndef _UAPI_LINUX_I2C_H
++#define _UAPI_LINUX_I2C_H
++
++#include <linux/types.h>
++
++/**
++ * struct i2c_msg - an I2C transaction segment beginning with START
++ * @addr: Slave address, either seven or ten bits. When this is a ten
++ * bit address, I2C_M_TEN must be set in @flags and the adapter
++ * must support I2C_FUNC_10BIT_ADDR.
++ * @flags: I2C_M_RD is handled by all adapters. No other flags may be
++ * provided unless the adapter exported the relevant I2C_FUNC_*
++ * flags through i2c_check_functionality().
++ * @len: Number of data bytes in @buf being read from or written to the
++ * I2C slave address. For read transactions where I2C_M_RECV_LEN
++ * is set, the caller guarantees that this buffer can hold up to
++ * 32 bytes in addition to the initial length byte sent by the
++ * slave (plus, if used, the SMBus PEC); and this value will be
++ * incremented by the number of block data bytes received.
++ * @buf: The buffer into which data is read, or from which it's written.
++ *
++ * An i2c_msg is the low level representation of one segment of an I2C
++ * transaction. It is visible to drivers in the @i2c_transfer() procedure,
++ * to userspace from i2c-dev, and to I2C adapter drivers through the
++ * @i2c_adapter.@master_xfer() method.
++ *
++ * Except when I2C "protocol mangling" is used, all I2C adapters implement
++ * the standard rules for I2C transactions. Each transaction begins with a
++ * START. That is followed by the slave address, and a bit encoding read
++ * versus write. Then follow all the data bytes, possibly including a byte
++ * with SMBus PEC. The transfer terminates with a NAK, or when all those
++ * bytes have been transferred and ACKed. If this is the last message in a
++ * group, it is followed by a STOP. Otherwise it is followed by the next
++ * @i2c_msg transaction segment, beginning with a (repeated) START.
++ *
++ * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then
++ * passing certain @flags may have changed those standard protocol behaviors.
++ * Those flags are only for use with broken/nonconforming slaves, and with
++ * adapters which are known to support the specific mangling options they
++ * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).
++ */
++struct i2c_msg {
++ __u16 addr; /* slave address */
++ __u16 flags;
++#define I2C_M_RD 0x0001 /* read data, from slave to master */
++ /* I2C_M_RD is guaranteed to be 0x0001! */
++#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
++#define I2C_M_HOLD 0x0100 /* for holding a mux path */
++#define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */
++ /* makes only sense in kernelspace */
++ /* userspace buffers are copied anyway */
++#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
++#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
++#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++ __u16 len; /* msg length */
++ __u8 *buf; /* pointer to msg data */
++};
++
++/* To determine what functionality is present */
++
++#define I2C_FUNC_I2C 0x00000001
++#define I2C_FUNC_10BIT_ADDR 0x00000002
++#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_IGNORE_NAK etc. */
++#define I2C_FUNC_SMBUS_PEC 0x00000008
++#define I2C_FUNC_NOSTART 0x00000010 /* I2C_M_NOSTART */
++#define I2C_FUNC_SLAVE 0x00000020
++#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
++#define I2C_FUNC_SMBUS_QUICK 0x00010000
++#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
++#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
++#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
++#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
++#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
++#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
++#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
++#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
++#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
++#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
++#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
++#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000
++
++#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
++ I2C_FUNC_SMBUS_WRITE_BYTE)
++#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
++#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
++ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
++#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
++ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
++#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
++
++#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
++ I2C_FUNC_SMBUS_BYTE | \
++ I2C_FUNC_SMBUS_BYTE_DATA | \
++ I2C_FUNC_SMBUS_WORD_DATA | \
++ I2C_FUNC_SMBUS_PROC_CALL | \
++ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
++ I2C_FUNC_SMBUS_I2C_BLOCK | \
++ I2C_FUNC_SMBUS_PEC)
++
++/*
++ * Data for SMBus Messages
++ */
++#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
++union i2c_smbus_data {
++ __u8 byte;
++ __u16 word;
++ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
++ /* and one more for user-space compatibility */
++};
++
++/* i2c_smbus_xfer read or write markers */
++#define I2C_SMBUS_READ 1
++#define I2C_SMBUS_WRITE 0
++
++/* SMBus transaction types (size parameter in the above functions)
++ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
++#define I2C_SMBUS_QUICK 0
++#define I2C_SMBUS_BYTE 1
++#define I2C_SMBUS_BYTE_DATA 2
++#define I2C_SMBUS_WORD_DATA 3
++#define I2C_SMBUS_PROC_CALL 4
++#define I2C_SMBUS_BLOCK_DATA 5
++#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
++#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
++#define I2C_SMBUS_I2C_BLOCK_DATA 8
++
++#endif /* _UAPI_LINUX_I2C_H */
+diff --git a/ipmb-channels.json b/ipmb-channels.json
+index 0876db7..ff570c6 100644
+--- a/ipmb-channels.json
++++ b/ipmb-channels.json
+@@ -11,6 +11,12 @@
+ "slave-path": "/dev/ipmb-0",
+ "bmc-addr": 32,
+ "remote-addr": 88
++ },
++ {
++ "type": "slot-ipmb",
++ "slave-path": "/dev/ipmb-6",
++ "bmc-addr": 18,
++ "remote-addr": 176
+ }
+ ]
+ }
+diff --git a/ipmbbridged.cpp b/ipmbbridged.cpp
+index e0eadfc..72ede8c 100644
+--- a/ipmbbridged.cpp
++++ b/ipmbbridged.cpp
+@@ -18,6 +18,11 @@
+ #include "ipmbdefines.hpp"
+ #include "ipmbutils.hpp"
+
++#include <i2c/smbus.h>
++#include <linux/i2c-dev.h>
++#include <linux/i2c.h>
++#include <sys/ioctl.h>
++
+ #include <boost/algorithm/string/replace.hpp>
+ #include <filesystem>
+ #include <fstream>
+@@ -39,7 +44,8 @@ auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+ static std::list<IpmbChannel> ipmbChannels;
+ static const std::unordered_map<std::string, ipmbChannelType>
+ ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
+- {"ipmb", ipmbChannelType::ipmb}};
++ {"ipmb", ipmbChannelType::ipmb},
++ {"slot-ipmb", ipmbChannelType::slot_ipmb}};
+
+ /**
+ * @brief Ipmb request class methods
+@@ -551,7 +557,10 @@ int IpmbChannel::ipmbChannelInit(const char *ipmbI2cSlave)
+ {
+ std::string deviceFileName =
+ "/sys/bus/i2c/devices/i2c-" + busStr + "/new_device";
+- std::string para = "ipmb-dev 0x1010"; // init with BMC addr 0x20
++ std::ostringstream param;
++ param << "ipmb-dev 0x" << std::hex
++ << static_cast<uint16_t>(0x1000 | (ipmbBmcSlaveAddress >> 1));
++ std::string para(param.str());
+ std::fstream deviceFile;
+ deviceFile.open(deviceFileName, std::ios::out);
+ if (!deviceFile.good())
+@@ -697,6 +706,171 @@ void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
+ }
+ }
+
++class Mux
++{
++ public:
++ Mux(const std::string &path) : heldMux(false)
++ {
++ fd = open(path.c_str(), O_RDWR | O_NONBLOCK);
++ }
++ ~Mux()
++ {
++ if (heldMux)
++ {
++ if (unholdMux() < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error while unholding the bus");
++ }
++ }
++ if (!(fd < 0))
++ {
++ close(fd);
++ }
++ }
++
++ int transferAndHoldMux(const uint8_t slaveAddr, uint8_t *buffer,
++ const uint8_t len, uint16_t timeout)
++ {
++ if (!isMuxFdOpen())
++ {
++ return -1;
++ }
++ struct i2c_msg holdmsg[2] = {
++ {slaveAddr, 0, len, buffer},
++ {0, I2C_M_HOLD, sizeof(timeout), (uint8_t *)&timeout}};
++
++ struct i2c_rdwr_ioctl_data msgrdwr = {&holdmsg[0], 2};
++
++ int retVal = ioctl(fd, I2C_RDWR, &msgrdwr);
++ if (retVal >= 0)
++ {
++ heldMux = true;
++ }
++ return retVal;
++ }
++
++ bool isMuxFdOpen()
++ {
++ if (fd < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error while opening the mux device file");
++ return false;
++ }
++ return true;
++ }
++
++ private:
++ int unholdMux()
++ {
++ if (!isMuxFdOpen())
++ {
++ return -1;
++ }
++ uint16_t holdtimeout = 0; // unhold the bus
++
++ struct i2c_msg holdmsg = {0, I2C_M_HOLD, sizeof(holdtimeout),
++ (uint8_t *)&holdtimeout};
++
++ struct i2c_rdwr_ioctl_data msgrdwr = {&holdmsg, 1};
++
++ return ioctl(fd, I2C_RDWR, &msgrdwr);
++ }
++
++ int fd;
++ bool heldMux;
++};
++
++std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
++ IpmbChannel::slotRequestAdd(boost::asio::yield_context &yield,
++ std::shared_ptr<IpmbRequest> request,
++ const uint8_t pcieSlot)
++{
++ makeRequestValid(request);
++ std::filesystem::path p =
++ "/dev/i2c-mux/PCIE_Mux/Pcie_Slot_" + std::to_string(pcieSlot);
++
++ if (!std::filesystem::exists(p) || !std::filesystem::is_symlink(p))
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "does not exist or not a symlink ",
++ phosphor::logging::entry("File:%s", p.c_str()));
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ Mux mux(p);
++ if (!mux.isMuxFdOpen())
++ {
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ std::vector<uint8_t> buffer(0);
++ if (request->ipmbToi2cConstruct(buffer) != 0)
++ {
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ uint8_t size = buffer.size();
++
++ const uint8_t slaveAddrIndex = 1;
++ const uint8_t slotIpmbHeader = 2;
++
++ for (int i = 0; i < ipmbNumberOfTries; i++)
++ {
++ boost::system::error_code ec;
++ int i2cRetryCnt = 0;
++ do
++ {
++ if (mux.transferAndHoldMux(
++ buffer[slaveAddrIndex] >> 1, buffer.data() + slotIpmbHeader,
++ size - slotIpmbHeader, ipmbRequestRetryTimeout) >= 0)
++ {
++ break;
++ }
++
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error sending slot IPMB command");
++ i2cRetryCnt++;
++ } while (i2cRetryCnt < ipmbI2cNumberOfRetries);
++
++ if (i2cRetryCnt == ipmbI2cNumberOfRetries)
++ {
++ std::string msgToLog =
++ "slotRequestAdd: Sent to I2C failed after retries."
++ " busId=" +
++ std::to_string(ipmbBusId) + ", error=" + ec.message();
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ msgToLog.c_str());
++ makeRequestInvalid(*request);
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ request->timer->expires_after(
++ std::chrono::milliseconds(ipmbRequestRetryTimeout));
++ request->timer->async_wait(yield[ec]);
++
++ if (ec && ec != boost::asio::error::operation_aborted)
++ {
++ // unexpected error - invalidate request and return generic error
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "requestAdd: async_wait error");
++ makeRequestInvalid(*request);
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ if (request->state == ipmbRequestState::matched)
++ {
++ // matched response, send it to client application
++ makeRequestInvalid(*request);
++ return request->returnMatchedResponse();
++ }
++ }
++
++ makeRequestInvalid(*request);
++ return returnStatus(ipmbResponseStatus::timeout);
++}
++
+ std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+ IpmbChannel::requestAdd(boost::asio::yield_context &yield,
+ std::shared_ptr<IpmbRequest> request)
+@@ -826,6 +1000,46 @@ static int initializeChannels()
+ return 0;
+ }
+
++auto slotIpmbHandleRequest =
++ [](boost::asio::yield_context yield, uint8_t addressType,
++ uint8_t slotNumber, uint8_t targetSlaveAddr, uint8_t netfn, uint8_t cmd,
++ std::vector<uint8_t> dataReceived) {
++ uint8_t lun = 0; // No support for lun in slot IPMB
++ IpmbChannel *channel = getChannel(ipmbChannelType::slot_ipmb);
++ if (channel == nullptr)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "slotIpmbHandleRequest: Slot IPMB channel does not exist");
++ return returnStatus(ipmbResponseStatus::error);
++ }
++
++ // check outstanding request list for valid sequence number
++ uint8_t seqNum = 0;
++ bool seqValid = channel->seqNumGet(seqNum);
++ if (!seqValid)
++ {
++ phosphor::logging::log<phosphor::logging::level::WARNING>(
++ "slotIpmbHandleRequest: cannot add more requests to the list");
++ return returnStatus(ipmbResponseStatus::busy);
++ }
++
++ uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
++ uint8_t rqSlaveAddress = targetSlaveAddr;
++
++ // construct the request to add it to outstanding request list
++ std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
++ rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
++ dataReceived);
++
++ if (!request->timer)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "slotIpmbHandleRequest: timer object does not exist");
++ return returnStatus(ipmbResponseStatus::error);
++ }
++ return channel->slotRequestAdd(yield, request, slotNumber);
++ };
++
+ auto ipmbHandleRequest = [](boost::asio::yield_context yield,
+ uint8_t reqChannel, uint8_t netfn, uint8_t lun,
+ uint8_t cmd, std::vector<uint8_t> dataReceived) {
+@@ -971,6 +1185,8 @@ int main(int argc, char *argv[])
+ server.add_interface(ipmbObj, ipmbDbusIntf);
+
+ ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
++ ipmbIface->register_method("SlotIpmbRequest",
++ std::move(slotIpmbHandleRequest));
+ ipmbIface->initialize();
+
+ if (initializeChannels() < 0)
+diff --git a/ipmbbridged.hpp b/ipmbbridged.hpp
+index e264195..167f613 100644
+--- a/ipmbbridged.hpp
++++ b/ipmbbridged.hpp
+@@ -153,7 +153,8 @@ enum class ipmbRequestState
+ enum class ipmbChannelType
+ {
+ ipmb = 0,
+- me = 1
++ me = 1,
++ slot_ipmb = 2
+ };
+
+ /**
+@@ -287,6 +288,11 @@ class IpmbChannel
+ void ipmbSendI2cFrame(std::shared_ptr<std::vector<uint8_t>> buffer,
+ size_t retriesAttempted);
+
++ std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
++ slotRequestAdd(boost::asio::yield_context &yield,
++ std::shared_ptr<IpmbRequest> requestToSend,
++ const uint8_t pcieSlot);
++
+ std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
+ requestAdd(boost::asio::yield_context &yield,
+ std::shared_ptr<IpmbRequest> requestToSend);
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend
new file mode 100644
index 000000000..dcbba98e7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend
@@ -0,0 +1,4 @@
+SRC_URI = "git://github.com/openbmc/ipmbbridge.git"
+SRCREV = "a86059348fe133725f4616f3e46ff0d555db4039"
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += "file://0001-Add-dbus-method-SlotIpmbRequest.patch"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules
new file mode 100644
index 000000000..0a64b58db
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs/99-ipmi-kcs.rules
@@ -0,0 +1,2 @@
+KERNEL=="ipmi-kcs3", SYMLINK+="ipmi_kcs3"
+KERNEL=="ipmi-kcs4", SYMLINK+="ipmi_kcs4"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend
new file mode 100644
index 000000000..97d329498
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-kcs_%.bbappend
@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+#SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}"
+
+# Default kcs device is ipmi-kcs3; this is SMS.
+# Add SMM kcs device instance
+
+# Replace the '-' to '_', since Dbus object/interface names do not allow '-'.
+KCS_DEVICE = "ipmi_kcs3"
+SMM_DEVICE = "ipmi_kcs4"
+SYSTEMD_SERVICE_${PN}_append = " ${PN}@${SMM_DEVICE}.service "
+
+SRC_URI = "git://github.com/openbmc/kcsbridge.git"
+SRCREV = "58d596ad9625790b5e06804360aa161579364425"
+
+SRC_URI += "file://99-ipmi-kcs.rules"
+
+do_install_append() {
+ install -d ${D}${base_libdir}/udev/rules.d
+ install -m 0644 ${WORKDIR}/99-ipmi-kcs.rules ${D}${base_libdir}/udev/rules.d/
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch
new file mode 100644
index 000000000..867b3aba6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/00010-Change-Authentication-Parameter.patch
@@ -0,0 +1,40 @@
+From 0fd38eb0a155cb11ff5a5452087f68c46d12111b Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Thu, 28 Mar 2019 18:10:40 +0800
+Subject: [PATCH] Change Authentication Parameter
+
+Seprate D-bus interface Authentication to forceAuthentication,
+forceEncryption, Privilege according to the related change in
+sol-dbus-interface.
+
+Tested By:
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0x03
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0xc2
+The parameters has been changed to the request data in above command.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ sol/sol_manager.cpp | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
+index de36723..0bd837e 100644
+--- a/sol/sol_manager.cpp
++++ b/sol/sol_manager.cpp
+@@ -195,8 +195,12 @@ void Manager::updateSOLParameter()
+
+ enable = std::get<bool>(properties["Enable"]);
+
++ forceEncrypt = std::get<bool>(properties["ForceEncryption"]);
++
++ forceAuth = std::get<bool>(properties["ForceAuthentication"]);
++
+ solMinPrivilege = static_cast<session::Privilege>(
+- std::get<uint8_t>(properties["Authentication"]));
++ std::get<uint8_t>(properties["Privilege"]));
+
+ accumulateInterval =
+ std::get<uint8_t>((properties["AccumulateIntervalMS"])) *
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch
new file mode 100644
index 000000000..0ad625a1f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch
@@ -0,0 +1,39 @@
+From 6fc55bb689272d34ff6616cdd4b24367ea39c749 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Mon, 2 Jul 2018 15:51:52 +0800
+Subject: [PATCH] Modify dbus namespace of chassis control for guid.cpp
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch chassis control service namespace for guid.cpp from “org” to “xyz”,
+to compatible with new intel-chassis services
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ command/guid.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+Index: phosphor-net-ipmid.clean/command/guid.cpp
+===================================================================
+--- phosphor-net-ipmid.clean.orig/command/guid.cpp
++++ phosphor-net-ipmid.clean/command/guid.cpp
+@@ -21,7 +21,8 @@ namespace command
+
+ std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);
+
+-static constexpr auto guidObjPath = "/org/openbmc/control/chassis0";
++static constexpr auto guidObjPath =
++ "/xyz/openbmc_project/Chassis/Control/Chassis0";
+ static constexpr auto propInterface = "org.freedesktop.DBus.Properties";
+
+ Guid getSystemGUID()
+@@ -31,7 +32,7 @@ Guid getSystemGUID()
+ Guid guid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
+
+- constexpr auto chassisIntf = "org.openbmc.control.Chassis";
++ constexpr auto chassisIntf = "xyz.openbmc_project.Chassis.Control.Chassis";
+
+ sd_bus_message* reply = nullptr;
+ sd_bus_error error = SD_BUS_ERROR_NULL;
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
new file mode 100644
index 000000000..dc7f7357c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch
@@ -0,0 +1,319 @@
+From 97c21a556702a0d65096b30c07ef23f15cb6a7d9 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Wed, 3 Jul 2019 07:39:47 +0800
+Subject: [PATCH] Add dbus interface for sol commands
+
+Add dbus interface for sol config parameters so that after move set/get
+sol config parameter command from net-ipmid to host-ipmid, the command
+can send config parameters to net-ipmid sol service through the dbus
+interface.
+
+Tested by:
+busctl introspect xyz.openbmc_project.Settings /xyz/openbmc_project
+/network/host0/sol can show correct dbus properties of sol parameters.
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x00 0x01
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x01 0x00
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x02 0x83
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x03 0x5 0x03
+ipmitool -I lanplus -H x -U x -P x raw 0x0c 0x21 0x0e 0x04 0x5 0x03
+all these commands can change the dbus properties as the value in
+above commands.
+Before and after run these commands, ipmitool -I lanplus -H x -U x
+-P x sol activate can start sol session correctly.
+After reboot BMC, "Progress" property in dbus interface change back
+to 0 and other properties will not reset to default value.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ command/payload_cmds.cpp | 3 ++
+ command/sol_cmds.cpp | 84 -------------------------------
+ sol/sol_manager.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++
+ sol/sol_manager.hpp | 1 +
+ sol_module.cpp | 6 ---
+ 5 files changed, 129 insertions(+), 90 deletions(-)
+
+diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
+index c32a510..17167a7 100644
+--- a/command/payload_cmds.cpp
++++ b/command/payload_cmds.cpp
+@@ -34,6 +34,9 @@ std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
+ return outPayload;
+ }
+
++ std::get<sol::Manager&>(singletonPool)
++ .updateSOLParameter(ipmi::convertCurrentChannelNum(
++ ipmi::currentChNum, getInterfaceIndex()));
+ if (!std::get<sol::Manager&>(singletonPool).enable)
+ {
+ response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
+diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
+index a8fa410..804b5ea 100644
+--- a/command/sol_cmds.cpp
++++ b/command/sol_cmds.cpp
+@@ -65,90 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
+ outPayload);
+ }
+
+-std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler)
+-{
+- std::vector<uint8_t> outPayload(sizeof(SetConfParamsResponse));
+- auto request =
+- reinterpret_cast<const SetConfParamsRequest*>(inPayload.data());
+- auto response = reinterpret_cast<SetConfParamsResponse*>(outPayload.data());
+- response->completionCode = IPMI_CC_OK;
+-
+- switch (static_cast<Parameter>(request->paramSelector))
+- {
+- case Parameter::PROGRESS:
+- {
+- uint8_t progress = request->value & progressMask;
+- std::get<sol::Manager&>(singletonPool).progress = progress;
+- break;
+- }
+- case Parameter::ENABLE:
+- {
+- bool enable = request->value & enableMask;
+- std::get<sol::Manager&>(singletonPool).enable = enable;
+- break;
+- }
+- case Parameter::AUTHENTICATION:
+- {
+- if (!request->auth.auth || !request->auth.encrypt)
+- {
+- response->completionCode = ipmiCCWriteReadParameter;
+- }
+- else if (request->auth.privilege <
+- static_cast<uint8_t>(session::Privilege::USER) ||
+- request->auth.privilege >
+- static_cast<uint8_t>(session::Privilege::OEM))
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- }
+- else
+- {
+- std::get<sol::Manager&>(singletonPool).solMinPrivilege =
+- static_cast<session::Privilege>(request->auth.privilege);
+- }
+- break;
+- }
+- case Parameter::ACCUMULATE:
+- {
+- using namespace std::chrono_literals;
+-
+- if (request->acc.threshold == 0)
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- break;
+- }
+-
+- std::get<sol::Manager&>(singletonPool).accumulateInterval =
+- request->acc.interval * sol::accIntervalFactor * 1ms;
+- std::get<sol::Manager&>(singletonPool).sendThreshold =
+- request->acc.threshold;
+- break;
+- }
+- case Parameter::RETRY:
+- {
+- using namespace std::chrono_literals;
+-
+- std::get<sol::Manager&>(singletonPool).retryCount =
+- request->retry.count;
+- std::get<sol::Manager&>(singletonPool).retryInterval =
+- request->retry.interval * sol::retryIntervalFactor * 1ms;
+- break;
+- }
+- case Parameter::PORT:
+- {
+- response->completionCode = ipmiCCWriteReadParameter;
+- break;
+- }
+- case Parameter::NVBITRATE:
+- case Parameter::VBITRATE:
+- case Parameter::CHANNEL:
+- default:
+- response->completionCode = ipmiCCParamNotSupported;
+- }
+-
+- return outPayload;
+-}
+-
+ std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+ {
+diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
+index 2046fe4..eedd28a 100644
+--- a/sol/sol_manager.cpp
++++ b/sol/sol_manager.cpp
+@@ -12,7 +12,13 @@
+ #include <boost/asio/write.hpp>
+ #include <chrono>
+ #include <cmath>
++#include <ipmid/utils.hpp>
+ #include <phosphor-logging/log.hpp>
++#include <sdbusplus/message/types.hpp>
++
++constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
++constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol/";
++constexpr const char* PROP_INTF = "org.freedesktop.DBus.Properties";
+
+ namespace sol
+ {
+@@ -93,6 +99,125 @@ void Manager::stopHostConsole()
+ }
+ }
+
++std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
++ const std::string& path)
++{
++ auto mapperCall =
++ bus.new_method_call("xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetObject");
++
++ mapperCall.append(path);
++ mapperCall.append(std::vector<std::string>({intf}));
++
++ std::map<std::string, std::vector<std::string>> mapperResponse;
++
++ try
++ {
++ auto mapperResponseMsg = bus.call(mapperCall);
++ mapperResponseMsg.read(mapperResponse);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ throw std::runtime_error("ERROR in mapper call");
++ }
++
++ if (mapperResponse.begin() == mapperResponse.end())
++ {
++ throw std::runtime_error("ERROR in reading the mapper response");
++ }
++
++ return mapperResponse.begin()->first;
++}
++
++ipmi::PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
++ const std::string& service,
++ const std::string& objPath,
++ const std::string& interface)
++{
++ ipmi::PropertyMap properties;
++
++ sdbusplus::message::message method = bus.new_method_call(
++ service.c_str(), objPath.c_str(), PROP_INTF, "GetAll");
++
++ method.append(interface);
++
++ try
++ {
++ sdbusplus::message::message reply = bus.call(method);
++ reply.read(properties);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get all properties",
++ phosphor::logging::entry("PATH=%s", objPath.c_str()),
++ phosphor::logging::entry("INTERFACE=%s", interface.c_str()));
++ throw std::runtime_error("ERROR in reading proerties");
++ }
++
++ return properties;
++}
++
++void Manager::updateSOLParameter(uint8_t channelNum)
++{
++ std::variant<uint8_t, bool> value;
++ sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
++ static std::string solService{};
++ ipmi::PropertyMap properties;
++ std::string ethdevice = ipmi::getChannelName(channelNum);
++ std::string solPathWitheEthName = solPath + ethdevice;
++ if (solService.empty())
++ {
++ try
++ {
++ solService = getService(dbus, solInterface, solPathWitheEthName);
++ }
++ catch (const std::runtime_error& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return;
++ }
++ }
++ try
++ {
++ properties = getAllDbusProperties(dbus, solService, solPathWitheEthName,
++ solInterface);
++ }
++ catch (const std::runtime_error&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error setting sol parameter");
++ return;
++ }
++
++ progress = std::get<uint8_t>(properties["Progress"]);
++
++ enable = std::get<bool>(properties["Enable"]);
++
++ forceEncrypt = std::get<bool>(properties["ForceEncryption"]);
++
++ forceAuth = std::get<bool>(properties["ForceAuthentication"]);
++
++ solMinPrivilege = static_cast<session::Privilege>(
++ std::get<uint8_t>(properties["Privilege"]));
++
++ accumulateInterval =
++ std::get<uint8_t>((properties["AccumulateIntervalMS"])) *
++ sol::accIntervalFactor * 1ms;
++
++ sendThreshold = std::get<uint8_t>(properties["Threshold"]);
++
++ retryCount = std::get<uint8_t>(properties["RetryCount"]);
++
++ retryInterval = std::get<uint8_t>(properties["RetryIntervalMS"]) *
++ sol::retryIntervalFactor * 1ms;
++
++ return;
++}
++
+ void Manager::startPayloadInstance(uint8_t payloadInstance,
+ session::SessionID sessionID)
+ {
+diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
+index 5d96890..00da9fb 100644
+--- a/sol/sol_manager.hpp
++++ b/sol/sol_manager.hpp
+@@ -248,6 +248,7 @@ class Manager
+ * @return 0 on success and errno on failure.
+ */
+ int writeConsoleSocket(const std::vector<uint8_t>& input) const;
++ void updateSOLParameter(uint8_t channelNum);
+
+ private:
+ SOLPayloadMap payloadMap;
+diff --git a/sol_module.cpp b/sol_module.cpp
+index 8200e74..2b1fb46 100644
+--- a/sol_module.cpp
++++ b/sol_module.cpp
+@@ -42,12 +42,6 @@ void registerCommands()
+ &getPayloadInfo,
+ session::Privilege::USER,
+ false},
+- // Set SOL Configuration Parameters
+- {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x21},
+- &setConfParams,
+- session::Privilege::ADMIN,
+- false},
+ // Get SOL Configuration Parameters
+ {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+ static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x22},
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch
new file mode 100644
index 000000000..da173704b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch
@@ -0,0 +1,336 @@
+From a36f181163974b2da0a954fc97a89fb2cdbd7287 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Tue, 30 Apr 2019 05:35:31 +0800
+Subject: [PATCH] Remove Get SOL Config Command from Netipmid
+
+Since Get SOL Config Parameter command already exists in host-ipmid, and
+can be shared to net channel, remove this command from net-ipmid.
+
+Tested:
+Run ipmitool -I lanplus -H xxx -U root -P 0penBmc sol info, the command
+returns the same result as ipmitool sol info as below.
+Info: SOL parameter 'Nonvolatile Bitrate (5)' not supported
+Info: SOL parameter 'Volatile Bitrate (6)' not supported
+Info: SOL parameter 'Payload Channel (7)' not supported - defaulting to 0x0e
+Set in progress : set-complete
+Enabled : true
+Force Encryption : true
+Force Authentication : true
+Privilege Level : USER
+Character Accumulate Level (ms) : 100
+Character Send Threshold : 1
+Retry Count : 3
+Retry Interval (ms) : 100
+Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Non-Volatile Bit Rate (kbps) : IPMI-Over-Serial-Setting
+Payload Channel : 14 (0x0e)
+Payload Port : 623
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ command/sol_cmds.cpp | 91 ----------------------------
+ command/sol_cmds.hpp | 168 ---------------------------------------------------
+ sol_module.cpp | 6 --
+ 3 files changed, 265 deletions(-)
+
+diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
+index 804b5ea..8b2d041 100644
+--- a/command/sol_cmds.cpp
++++ b/command/sol_cmds.cpp
+@@ -65,97 +65,6 @@ void activating(uint8_t payloadInstance, uint32_t sessionID)
+ outPayload);
+ }
+
+-std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler)
+-{
+- std::vector<uint8_t> outPayload(sizeof(GetConfParamsResponse));
+- auto request =
+- reinterpret_cast<const GetConfParamsRequest*>(inPayload.data());
+- auto response = reinterpret_cast<GetConfParamsResponse*>(outPayload.data());
+- response->completionCode = IPMI_CC_OK;
+- response->paramRev = parameterRevision;
+-
+- if (request->getParamRev)
+- {
+- return outPayload;
+- }
+-
+- switch (static_cast<Parameter>(request->paramSelector))
+- {
+- case Parameter::PROGRESS:
+- {
+- outPayload.push_back(
+- std::get<sol::Manager&>(singletonPool).progress);
+- break;
+- }
+- case Parameter::ENABLE:
+- {
+- outPayload.push_back(std::get<sol::Manager&>(singletonPool).enable);
+- break;
+- }
+- case Parameter::AUTHENTICATION:
+- {
+- Auth value{0};
+-
+- value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
+- value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
+- value.privilege = static_cast<uint8_t>(
+- std::get<sol::Manager&>(singletonPool).solMinPrivilege);
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::ACCUMULATE:
+- {
+- Accumulate value{0};
+-
+- value.interval = std::get<sol::Manager&>(singletonPool)
+- .accumulateInterval.count() /
+- sol::accIntervalFactor;
+- value.threshold =
+- std::get<sol::Manager&>(singletonPool).sendThreshold;
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::RETRY:
+- {
+- Retry value{0};
+-
+- value.count = std::get<sol::Manager&>(singletonPool).retryCount;
+- value.interval =
+- std::get<sol::Manager&>(singletonPool).retryInterval.count() /
+- sol::retryIntervalFactor;
+- auto buffer = reinterpret_cast<const uint8_t*>(&value);
+-
+- std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::PORT:
+- {
+- auto port = endian::to_ipmi<uint16_t>(IPMI_STD_PORT);
+- auto buffer = reinterpret_cast<const uint8_t*>(&port);
+-
+- std::copy_n(buffer, sizeof(port), std::back_inserter(outPayload));
+- break;
+- }
+- case Parameter::CHANNEL:
+- {
+- outPayload.push_back(
+- std::get<sol::Manager&>(singletonPool).channel);
+- break;
+- }
+- case Parameter::NVBITRATE:
+- case Parameter::VBITRATE:
+- default:
+- response->completionCode = ipmiCCParamNotSupported;
+- }
+-
+- return outPayload;
+-}
+-
+ } // namespace command
+
+ } // namespace sol
+diff --git a/command/sol_cmds.hpp b/command/sol_cmds.hpp
+index 182b73e..10cbf25 100644
+--- a/command/sol_cmds.hpp
++++ b/command/sol_cmds.hpp
+@@ -62,174 +62,6 @@ struct ActivatingRequest
+ */
+ void activating(uint8_t payloadInstance, uint32_t sessionID);
+
+-/** @enum Parameter
+- *
+- * SOL parameters are volatile, they are initialized by the SOL manager.
+- * They can be read using Get SOL configuration parameters command and updated
+- * using Set SOL configuration parameters command.
+- */
+-enum class Parameter
+-{
+- PROGRESS, //!< Set In Progress.
+- ENABLE, //!< SOL Enable.
+- AUTHENTICATION, //!< SOL Authentication.
+- ACCUMULATE, //!< Character Accumulate Interval & Send Threshold.
+- RETRY, //!< SOL Retry.
+- NVBITRATE, //!< SOL non-volatile bit rate.
+- VBITRATE, //!< SOL volatile bit rate.
+- CHANNEL, //!< SOL payload channel.
+- PORT, //!< SOL payload port.
+-};
+-
+-constexpr uint8_t progressMask = 0x03;
+-constexpr uint8_t enableMask = 0x01;
+-
+-/** @struct Auth
+- *
+- * SOL authentication parameter.
+- */
+-struct Auth
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t privilege : 4; //!< SOL privilege level.
+- uint8_t reserved : 2; //!< Reserved.
+- uint8_t auth : 1; //!< Force SOL payload Authentication.
+- uint8_t encrypt : 1; //!< Force SOL payload encryption.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t encrypt : 1; //!< Force SOL payload encryption.
+- uint8_t auth : 1; //!< Force SOL payload Authentication.
+- uint8_t reserved : 2; //!< Reserved.
+- uint8_t privilege : 4; //!< SOL privilege level.
+-#endif
+-} __attribute__((packed));
+-
+-/** @struct Accumulate
+- *
+- * Character accumulate interval & Character send threshold.
+- */
+-struct Accumulate
+-{
+- uint8_t interval; //!< Character accumulate interval.
+- uint8_t threshold; //!< Character send threshold.
+-} __attribute__((packed));
+-
+-constexpr uint8_t retryCountMask = 0x07;
+-
+-/** @struct Retry
+- *
+- * SOL retry count and interval.
+- */
+-struct Retry
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t count : 3; //!< SOL retry count.
+- uint8_t reserved : 5; //!< Reserved.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t reserved : 5; //!< Reserved.
+- uint8_t count : 3; //!< SOL retry count.
+-#endif
+-
+- uint8_t interval; //!< SOL retry interval.
+-} __attribute__((packed));
+-
+-constexpr uint8_t ipmiCCParamNotSupported = 0x80;
+-constexpr uint8_t ipmiCCInvalidSetInProgress = 0x81;
+-constexpr uint8_t ipmiCCWriteReadParameter = 0x82;
+-constexpr uint8_t ipmiCCReadWriteParameter = 0x83;
+-constexpr uint8_t parameterRevision = 0x11;
+-
+-/** @struct SetConfParamsRequest
+- *
+- * IPMI payload for Set SOL configuration parameters command request.
+- */
+-struct SetConfParamsRequest
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t channelNumber : 4; //!< Channel number.
+- uint8_t reserved : 4; //!< Reserved.
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t reserved : 4; //!< Reserved.
+- uint8_t channelNumber : 4; //!< Channel number.
+-#endif
+-
+- uint8_t paramSelector; //!< Parameter selector.
+- union
+- {
+- uint8_t value; //!< Represents one byte SOL parameters.
+- struct Accumulate acc; //!< Character accumulate values.
+- struct Retry retry; //!< Retry values.
+- struct Auth auth; //!< Authentication parameters.
+- };
+-} __attribute__((packed));
+-
+-/** @struct SetConfParamsResponse
+- *
+- * IPMI payload for Set SOL configuration parameters command response.
+- */
+-struct SetConfParamsResponse
+-{
+- uint8_t completionCode; //!< Completion code.
+-} __attribute__((packed));
+-
+-/** @brief Set SOL configuration parameters command.
+- *
+- * @param[in] inPayload - Request data for the command.
+- * @param[in] handler - Reference to the message handler.
+- *
+- * @return Response data for the command.
+- */
+-std::vector<uint8_t> setConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler);
+-
+-/** @struct GetConfParamsRequest
+- *
+- * IPMI payload for Get SOL configuration parameters command request.
+- */
+-struct GetConfParamsRequest
+-{
+-#if BYTE_ORDER == LITTLE_ENDIAN
+- uint8_t channelNum : 4; //!< Channel number.
+- uint8_t reserved : 3; //!< Reserved.
+- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision
+-#endif
+-
+-#if BYTE_ORDER == BIG_ENDIAN
+- uint8_t getParamRev : 1; //!< Get parameter or Get parameter revision
+- uint8_t reserved : 3; //!< Reserved.
+- uint8_t channelNum : 4; //!< Channel number.
+-#endif
+-
+- uint8_t paramSelector; //!< Parameter selector.
+- uint8_t setSelector; //!< Set selector.
+- uint8_t blockSelector; //!< Block selector.
+-} __attribute__((packed));
+-
+-/** @struct GetConfParamsResponse
+- *
+- * IPMI payload for Get SOL configuration parameters command response.
+- */
+-struct GetConfParamsResponse
+-{
+- uint8_t completionCode; //!< Completion code.
+- uint8_t paramRev; //!< Parameter revision.
+-} __attribute__((packed));
+-
+-/** @brief Get SOL configuration parameters command.
+- *
+- * @param[in] inPayload - Request data for the command.
+- * @param[in] handler - Reference to the message handler.
+- *
+- * @return Response data for the command.
+- */
+-std::vector<uint8_t> getConfParams(const std::vector<uint8_t>& inPayload,
+- const message::Handler& handler);
+-
+ } // namespace command
+
+ } // namespace sol
+diff --git a/sol_module.cpp b/sol_module.cpp
+index 2b1fb46..6da82c0 100644
+--- a/sol_module.cpp
++++ b/sol_module.cpp
+@@ -42,12 +42,6 @@ void registerCommands()
+ &getPayloadInfo,
+ session::Privilege::USER,
+ false},
+- // Get SOL Configuration Parameters
+- {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(::command::NetFns::TRANSPORT) | 0x22},
+- &getConfParams,
+- session::Privilege::USER,
+- false},
+ };
+
+ for (const auto& iter : commands)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/10-nice-rules.conf b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/10-nice-rules.conf
new file mode 100644
index 000000000..d2fb5ba04
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/10-nice-rules.conf
@@ -0,0 +1,2 @@
+[Service]
+Nice=-18
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
new file mode 100644
index 000000000..0a9a6ba57
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
@@ -0,0 +1,31 @@
+inherit useradd
+
+# TODO: This should be removed, once up-stream bump up
+# issue is resolved
+SRC_URI += "git://github.com/openbmc/phosphor-net-ipmid"
+SRCREV = "9d9b7638cb1e95989329680730ec272da786615f"
+
+USERADD_PACKAGES = "${PN}"
+# add a group called ipmi
+GROUPADD_PARAM_${PN} = "ipmi "
+
+# Default rmcpp iface is eth0; channel 1
+# Add channel 2 instance (eth1)
+RMCPP_EXTRA = "eth1"
+SYSTEMD_SERVICE_${PN} += " \
+ ${PN}@${RMCPP_EXTRA}.service \
+ ${PN}@${RMCPP_EXTRA}.socket \
+ "
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " file://10-nice-rules.conf \
+ file://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch \
+ file://0009-Add-dbus-interface-for-sol-commands.patch \
+ file://0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch \
+ "
+
+do_install_append() {
+ mkdir -p ${D}${sysconfdir}/systemd/system/phosphor-ipmi-net@.service.d/
+ install -m 0644 ${WORKDIR}/10-nice-rules.conf ${D}${sysconfdir}/systemd/system/phosphor-ipmi-net@.service.d/
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend
new file mode 100644
index 000000000..72d991c7e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-sensor-inventory%/config.yaml
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb
new file mode 100644
index 000000000..36d65fd72
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Node Manager Proxy"
+DESCRIPTION = "The Node Manager Proxy provides a simple interface for communicating \
+with Management Engine via IPMB"
+
+SRC_URI = "git://github.com/Intel-BMC/node-manager;protocol=ssh"
+SRCREV = "de212d839bb515939bd089c66072e4fcf33b8653"
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SYSTEMD_SERVICE_${PN} = "node-manager-proxy.service"
+
+DEPENDS = "sdbusplus \
+ phosphor-logging \
+ boost"
+
+S = "${WORKDIR}/git/"
+inherit cmake systemd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.service b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.service
new file mode 100644
index 000000000..51e59c614
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=turn off the ID LED when BMC is ready
+Wants=multi-user.target
+After=multi-user.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/id-led-off.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.sh b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.sh
new file mode 100755
index 000000000..b609fc0ea
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off/id-led-off.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+busctl set-property "xyz.openbmc_project.LED.GroupManager" \
+"/xyz/openbmc_project/led/groups/enclosure_identify" \
+"xyz.openbmc_project.Led.Group" "Asserted" b false
+
+busctl set-property "xyz.openbmc_project.LED.GroupManager" \
+"/xyz/openbmc_project/led/groups/enclosure_identify_blink" \
+"xyz.openbmc_project.Led.Group" "Asserted" b false
+
+busctl set-property "xyz.openbmc_project.LED.Controller.identify" \
+"/xyz/openbmc_project/led/physical/identify" \
+"xyz.openbmc_project.Led.Physical" "State" s "xyz.openbmc_project.Led.Physical.Action.Off"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off_git.bb
new file mode 100644
index 000000000..a1d20c2bc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/id-led-off_git.bb
@@ -0,0 +1,24 @@
+SUMMARY = "Turn off the ID LED"
+DESCRIPTION = "Script to turn off the ID LED after BMC is ready"
+
+S = "${WORKDIR}"
+SRC_URI = "file://id-led-off.sh \
+ file://id-led-off.service \
+ "
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+RDEPENDS_${PN} += "bash"
+
+inherit systemd
+
+FILES_${PN} += "${systemd_system_unitdir}/id-led-off.service"
+
+do_install() {
+ install -d ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/id-led-off.service ${D}${systemd_system_unitdir}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/id-led-off.sh ${D}/${bindir}/id-led-off.sh
+}
+
+SYSTEMD_SERVICE_${PN} += " id-led-off.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb
new file mode 100644
index 000000000..dd48df0c6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config-native.bb
@@ -0,0 +1,21 @@
+SUMMARY = "Phosphor LED Group Management for Intel"
+PR = "r1"
+
+inherit native
+inherit obmc-phosphor-utils
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+PROVIDES += "virtual/phosphor-led-manager-config-native"
+
+SRC_URI += "file://led.yaml"
+S = "${WORKDIR}"
+
+# Overwrite the example led layout yaml file prior
+# to building the phosphor-led-manager package
+do_install() {
+ SRC=${S}
+ DEST=${D}${datadir}/phosphor-led-manager
+ install -D ${SRC}/led.yaml ${DEST}/led.yaml
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml
new file mode 100644
index 000000000..533df68a4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml
@@ -0,0 +1,48 @@
+bmc_booted:
+
+power_on:
+
+status_ok:
+ status_green:
+ Action: 'On'
+ status_amber:
+ Action: 'Off'
+
+status_degraded:
+ status_green:
+ Action: 'Blink'
+ DutyOn: 50
+ Period: 1000
+ status_amber:
+ Action: 'Off'
+
+status_non_critical:
+ status_green:
+ Action: 'Off'
+ status_amber:
+ Action: 'Blink'
+ DutyOn: 50
+ Period: 1000
+
+status_critical:
+ status_green:
+ Action: 'Off'
+ status_amber:
+ Action: 'On'
+
+enclosure_identify:
+ identify:
+ Action: 'On'
+
+enclosure_identify_blink:
+ identify:
+ Action: 'Blink'
+
+cpu0_fault:
+ cpu0fault:
+ Action: 'On'
+
+cpu1_fault:
+ cpu1fault:
+ Action: 'On'
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb
new file mode 100644
index 000000000..f6a6b1f1b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb
@@ -0,0 +1,17 @@
+SUMMARY = "Multi node manager"
+DESCRIPTION = "Daemon to handle chassis level shared resources on multi-node platform"
+
+SRC_URI = "git://github.com/Intel-BMC/multi-node-manager.git;protocol=ssh"
+SRCREV = "34d959285a3ca12c4bfefa4040d82d571c78843b"
+
+S = "${WORKDIR}/git/"
+
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SYSTEMD_SERVICE_${PN} = "multi-node-manager.service"
+
+DEPENDS = "boost sdbusplus phosphor-logging i2c-tools"
+inherit cmake systemd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl.bb
new file mode 100644
index 000000000..c47a581f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl.bb
@@ -0,0 +1,27 @@
+SUMMARY = "Multi-node Non-legacy"
+DESCRIPTION = "New systemd target for non-legacy nodes on multi-node platform"
+
+inherit systemd
+
+SYSTEMD_SERVICE_${PN} = "multi-node-nl.target"
+SYSTEMD_SERVICE_${PN} += "nonLegacyNode.service"
+
+S = "${WORKDIR}"
+SRC_URI = "file://multi-node-nl.target \
+ file://nonLegacyNode.service \
+ file://nonLegacyNode.sh \
+ "
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+RDEPENDS_${PN} = "bash"
+
+do_install_append() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/nonLegacyNode.sh ${D}/${bindir}/nonLegacyNode.sh
+
+ install -d ${D}${base_libdir}/systemd/system
+ install -m 0644 ${S}/multi-node-nl.target ${D}${base_libdir}/systemd/system
+ install -m 0644 ${S}/nonLegacyNode.service ${D}${base_libdir}/systemd/system
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/multi-node-nl.target b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/multi-node-nl.target
new file mode 100644
index 000000000..32b50532f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/multi-node-nl.target
@@ -0,0 +1,4 @@
+[Unit]
+Description=Target for non-legacy node in multi-node system
+Documentation=man:systemd.special(7)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.service b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.service
new file mode 100644
index 000000000..8e3d07ba4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Non Legacy node
+
+[Service]
+ExecStart=/usr/bin/nonLegacyNode.sh
+Type=exec
+
+[Install]
+WantedBy=multi-node-nl.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.sh b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.sh
new file mode 100755
index 000000000..28a6bbe2a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-nl/multi-node-nl/nonLegacyNode.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+PWM_FILE="/sys/class/hwmon/hwmon0/pwm"
+FAN_SPEED=$((255 * 80 / 100))
+
+set_fan_speed() {
+ local idx=0
+ for ((idx=1; idx<=8; idx++))
+ do
+ if [ -f $PWM_FILE$idx ]; then
+ echo $FAN_SPEED > $PWM_FILE$idx
+ fi
+ done
+}
+
+$(set_fan_speed)
+
+#Stop power control service in NL mode
+systemctl stop xyz.openbmc_project.Chassis.Control.Power.service
+
+export TERM=xterm
+# Autologin root user to serial console (ttyS4) on boot
+exec /sbin/agetty -a root -J -8 -L ttyS4 115200 $TERM
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/phosphor-u-boot-mgr/phosphor-u-boot-mgr_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/phosphor-u-boot-mgr/phosphor-u-boot-mgr_git.bb
new file mode 100644
index 000000000..48f740637
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/phosphor-u-boot-mgr/phosphor-u-boot-mgr_git.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Phosphor U-Boot environment manager"
+DESCRIPTION = "Daemon to read or write U-Boot environment variables"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+SRC_URI = "git://github.com/openbmc/phosphor-u-boot-env-mgr.git;protocol=ssh"
+
+SRCREV = "7a36277b6fdf33a554a4f9e2258e39d1696b00c2"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.U_Boot.Environment.Manager.service"
+
+DEPENDS = "boost sdbusplus phosphor-logging"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
new file mode 100644
index 000000000..2ffa151f4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
@@ -0,0 +1,16 @@
+SUMMARY = "libmctp_intel"
+DESCRIPTION = "Implementation of MCTP(DMTF DSP0236)"
+
+SRC_URI = "git://github.com/Intel-BMC/libmctp.git;protocol=ssh"
+SRCREV = "1f22461796e1f95a9b0d32f95cb8e871aab820c7"
+
+S = "${WORKDIR}/git/"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0 | GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=0d30807bb7a4f16d36e96b78f9ed8fae"
+
+inherit cmake
+
+DEPENDS += "i2c-tools"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
new file mode 100644
index 000000000..3b048b4fd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
@@ -0,0 +1,30 @@
+SUMMARY = "MCTP Daemon"
+DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=bcd9ada3a943f58551867d72893cc9ab"
+
+SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
+SRCREV = "5cecf9c8b1ab2ff819221f002b67010a6260c9a3"
+
+S = "${WORKDIR}/git/mctp_emulator/"
+
+PV = "1.0+git${SRCPV}"
+
+inherit cmake systemd
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += " \
+ libmctp-intel \
+ systemd \
+ sdbusplus \
+ phosphor-logging \
+ boost \
+ i2c-tools \
+ cli11 \
+ nlohmann-json \
+ gtest \
+ "
+
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.mctp-emulator.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
new file mode 100644
index 000000000..6335440a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
@@ -0,0 +1,34 @@
+SUMMARY = "MCTP Daemon"
+DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
+SRCREV = "5cecf9c8b1ab2ff819221f002b67010a6260c9a3"
+
+S = "${WORKDIR}/git/mctpd/"
+
+PV = "1.0+git${SRCPV}"
+
+inherit cmake systemd
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += " \
+ libmctp-intel \
+ systemd \
+ sdbusplus \
+ phosphor-logging \
+ boost \
+ i2c-tools \
+ cli11 \
+ nlohmann-json \
+ gtest \
+ phosphor-dbus-interfaces \
+ "
+SMBUS_BINDING = "smbus"
+
+FILES_${PN} += "${systemd_system_unitdir}/xyz.openbmc_project.mctpd@.service"
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.mctpd@${SMBUS_BINDING}.service"
+FILES_${PN} += "/usr/share/mctp/mctp_config.json"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts.bbappend
new file mode 100644
index 000000000..dc22b3c95
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI = "file://init" \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts/init b/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts/init
new file mode 100755
index 000000000..e954d7757
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts/init
@@ -0,0 +1,258 @@
+#!/bin/sh
+
+# Copyright 2017-2019 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+# provide a couple of places in the RO root filesystem
+# that can be made RW with an overlayfs
+
+log() {
+ [ -c /dev/kmsg ] && echo "init: $@" > /dev/kmsg
+ echo "init: $@"
+}
+
+# start with /proc and /tmp mounted
+[ -e /proc/mounts ] || mount -t proc proc /proc
+# FIXME: add size limits to /tmp
+grep -q /tmp /proc/mounts || mount -t tmpfs -o rw,nosuid,nodev tmp /tmp
+grep -q /sys /proc/mounts || mount -t sysfs -o rw,nosuid,nodev,noexec sys /sys
+
+# fix up /srv to be RW
+mkdir -p /tmp/srv
+mount --bind /tmp/srv /srv
+
+if grep -q debug-init /proc/cmdline; then
+ exec > /tmp/init.log 2>&1
+ set -x
+ env
+else
+ # silent bob
+ exec >/dev/null 2>&1
+fi
+
+# list of things that need to be rw at boot
+NV_OVERLAYS="/etc /var /home"
+
+# place to mount the overlay backing store
+OVERLAY_MNT=/tmp/.overlay
+OVERLAY_SIZE=16384
+# place to mount NV
+RWFS_MNT=/tmp/.rwfs
+# NV overlay storage
+OVERLAY_SYNC=${RWFS_MNT}/.overlay
+
+if grep -q "$RWFS_MNT" /proc/mounts; then
+ # quit - we have already run
+ exit 0
+fi
+mkdir -p "$OVERLAY_MNT"
+# TODO: remount the overlay with a size limit?
+# mount -t tmpfs -o rw,size=${OVERLAY_SIZE} oltmp ${OVERLAY_MNT}
+
+mtd_by_name() {
+ local name="$1"
+ local mtd="/dev/$(grep "$name" /proc/mtd | cut -d : -f 1)"
+ echo "$mtd"
+}
+
+mtdnum_by_name() {
+ local name="$1"
+ local mtdnum="$(grep "$name" /proc/mtd | cut -c 4)"
+ echo "$mtdnum"
+}
+
+NV_MTD=rwfs
+NV_MTD_DEV="$(mtd_by_name ${NV_MTD})"
+NV_MTD_NUM="$(mtdnum_by_name ${NV_MTD})"
+
+nvrw() {
+ local p="$1"
+ # Clear the work dir doing overlay mount
+ rm -rf "${OVERLAY_MNT}${p}.work"
+ mkdir -p "${OVERLAY_MNT}${p}" "${OVERLAY_MNT}${p}.work"
+ local mname=$(echo "ol${p}" | sed 's,/,,g')
+ local opts="lowerdir=${p},upperdir=${OVERLAY_MNT}${p},workdir=${OVERLAY_MNT}${p}.work,sync"
+ mount -t overlay -o "$opts" "$mname" "$p"
+}
+
+targeted_clean() {
+ log "restore-defaults: targeted_clean"
+ # Do not delete FRU info, ssh/ssl certs, or machine-id
+ (
+ cd "${OVERLAY_SYNC}/etc"
+ find . ! -regex '.*\(/ssl\|/dropbear\|/machine-id\(_bkup\)\?\|/fru\).*' -exec rm -rf {} +
+ )
+ # nothing should be in the workdir, but clear it just in case
+ rm -rf "${OVERLAY_SYNC}/etc.work"
+
+ # clean everything out of /home
+ rm -rf "${OVERLAY_SYNC}/home" "${OVERLAY_SYNC}/home.work"
+
+ # clean everything out of /var
+ rm -rf "${OVERLAY_SYNC}/var" "${OVERLAY_SYNC}/var.work"
+
+ echo "Files remaining: $(find $OVERLAY_SYNC/)"
+ sync
+}
+
+full_clean() {
+ log "restore-defaults: full_clean"
+ local OVL=''
+ for OVL in $NV_OVERLAYS; do
+ rm -rf "${OVERLAY_SYNC}${OVL}" "${OVERLAY_SYNC}${OVL}.work"
+ done
+ sync
+}
+
+reformat_jffs2_partition() {
+ local mtd_name="$1"
+ local mnt="$2"
+ # unmount the partition to reformat it
+ umount -f "$mnt"
+ flash_eraseall "$(mtd_by_name ${mtd_name})"
+ # remount the JFFS2
+ mount -t jffs2 -o sync mtd:"$mtd_name" "$mnt"
+ if [ $? -ne 0 ]; then
+ log "Failed to mount reformatted NV volume; system unstable"
+ fi
+}
+
+clear_ubenv() {
+ log "Clearing U-Boot environment"
+ flash_erase /dev/mtd/u-boot-env 0 0
+}
+
+# mount NV filesystem
+mkdir -p "$RWFS_MNT"
+mount -t jffs2 -o sync mtd:"$NV_MTD" "$RWFS_MNT"
+if [ $? -ne 0 ]; then
+ log "Failed to mount NV volume; attempting recovery"
+ reformat_jffs2_partition $NV_MTD $RWFS_MNT
+fi
+
+# check for full factory reset: if so, format $NV_MTD_DEV
+RESTORE_FLAG=$RWFS_MNT/.restore_op
+restore_op=$(cat $RESTORE_FLAG) # read from NV
+restore_op=${restore_op:-0} # set default value 0
+restore_op=$((restore_op & 3)) # mask off 2 bits
+if [ $restore_op -eq 1 ]; then
+ targeted_clean
+elif [ $restore_op -eq 2 ]; then
+ full_clean
+ clear_ubenv
+elif [ $restore_op -eq 3 ]; then
+ log "restore-defaults: reformat"
+ reformat_jffs2_partition $NV_MTD $RWFS_MNT
+ clear_ubenv
+fi
+rm -f $RESTORE_FLAG
+
+# Restore the overlay saved in the sync
+rsync -a --delete "${OVERLAY_SYNC}/" "${OVERLAY_MNT}"
+log "Restored overlay from sync location"
+
+for FS in $NV_OVERLAYS; do
+ nvrw "$FS"
+done
+
+# work around bug where /etc/machine-id will be mounted with a temporary file
+# if rootfs is read-only and the file is empty
+MACHINE_ID=/etc/machine-id
+generate_machine_id() {
+ systemd-machine-id-setup
+ cp -pf "$MACHINE_ID" "${MACHINE_ID}_bkup"
+}
+
+if [ ! -s "$MACHINE_ID" ]; then
+ # work around - Bug: Overlay fs fails for machine-id due to
+ # origin mismatch. Clean it up, from overlay fs before re-creating
+ # the same.
+ if [ -e "$OVERLAY_MNT$MACHINE_ID" ]; then
+ umount "/etc"
+ rm -f "$OVERLAY_MNT$MACHINE_ID"
+ nvrw "/etc"
+ # Restore the machine-id from backup, else generate it.
+ if [ -s "${MACHINE_ID}_bkup" ]; then
+ cp -pf "${MACHINE_ID}_bkup" "${MACHINE_ID}"
+ else
+ generate_machine_id
+ fi
+ log "Remounted /etc for machine-id origin mismatch"
+ else
+ generate_machine_id
+ fi
+fi
+
+# mount persistent NV filesystem, where immortal settings live
+SOFS_MNT=/var/sofs
+if ! grep -q sofs /proc/mounts; then
+ mkdir -p $SOFS_MNT
+ SOFS_MTD=sofs
+ SOFS_MTD_NUM="$(mtdnum_by_name ${SOFS_MTD})"
+
+ # mount a JFFS2 on the partition
+ mount -t jffs2 -o sync mtd:"$SOFS_MTD" "$SOFS_MNT"
+ if [ $? -ne 0 ]; then
+ log "Failed to mount SOFS volume; attempting recovery"
+ reformat_jffs2_partition $SOFS_MTD $SOFS_MNT
+ fi
+fi
+
+log "Finished mounting nv and overlays"
+
+
+# Detect the non-legacy node in cooper city and boot in to special mode.
+
+readonly COOPER_CITY=40 # Board id of cooper city
+
+is_nl_node() {
+ typeset -i nid1=$(gpioget $(gpiofind "FM_NODE_ID_1"))
+ typeset -i nid2=$(gpioget $(gpiofind "FM_NODE_ID_2"))
+ echo $((nid1|nid2))
+}
+
+read_board_id() {
+ local idx=0
+ local result=0
+ local value=0
+ for ((idx=0; idx<6; idx++))
+ do
+ typeset -i value=$(gpioget $(gpiofind "FM_BMC_BOARD_SKU_ID${idx}_N"))
+ value=$((value << idx))
+ result=$((result | value))
+ done
+ echo $result
+}
+
+pfr_write() {
+ [ $# -ne 2 ] && return 1
+ local PFR_BUS=4
+ local PFR_ADDR=0x38
+ local reg=$1
+ local val=$2
+ i2cset -y $PFR_BUS $PFR_ADDR $reg $val >&/dev/null
+}
+
+board_id=$(read_board_id)
+if [ $board_id -eq $COOPER_CITY ]; then
+ if [ $(is_nl_node) -ne 0 ]; then
+ systemctl set-default multi-node-nl.target
+ PFR_BMC_CHECKPOINT_REG=0xf
+ PFR_BMC_CHECKPOINT_COMPLETE=0x9
+ pfr_write $PFR_BMC_CHECKPOINT_REG $PFR_BMC_CHECKPOINT_COMPLETE
+ fi
+fi
+
+exec /lib/systemd/systemd
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/prov-mode-mgr/prov-mode-mgr_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/prov-mode-mgr/prov-mode-mgr_git.bb
new file mode 100644
index 000000000..ce6cf5998
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/prov-mode-mgr/prov-mode-mgr_git.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Provision mode daemon - RestrictionMode"
+DESCRIPTION = "Daemon allows to configure RestrictionMode property"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/provisioning-mode-manager.git;protocol=ssh"
+
+SRCREV = "8994b09bfe2eae4e3d18f3a4633e965bd945547f"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.RestrictionMode.Manager.service"
+
+DEPENDS = "boost sdbusplus phosphor-logging"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/security-manager/security-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/security-manager/security-manager_git.bb
new file mode 100644
index 000000000..64201acc1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/security-manager/security-manager_git.bb
@@ -0,0 +1,24 @@
+SUMMARY = "Security Manager daemon to detect the security violation- ASD/ user management"
+DESCRIPTION = "Daemon check for Remote debug enable and user account violation"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/security-manager"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+inherit cmake systemd
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.SecurityManager.service"
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ libgpiod \
+ sdbusplus-native \
+ phosphor-logging \
+ boost \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
new file mode 100644
index 000000000..67d8854d2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
@@ -0,0 +1,4 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/phosphor-sel-logger.git"
+SRCREV = "761bf202ba9db9fe644f8f400a5e768abe1a70cf"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service
new file mode 100644
index 000000000..b8c3554ae
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test/xyz.openbmc_project.selftest.service
@@ -0,0 +1,10 @@
+[Unit]
+Description= BMC Self-Test
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/env selftest
+SyslogIdentifier=selftest
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb
new file mode 100644
index 000000000..f655d22e4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/selftest/intel-self-test_git.bb
@@ -0,0 +1,38 @@
+SUMMARY = "BMC Self Test service"
+DESCRIPTION = "BMC Self Test service for subsystem diagnosis failure info"
+
+SRC_URI = "git://github.com/Intel-BMC/intel-self-test;protocol=ssh"
+
+PV = "1.0+git${SRCPV}"
+SRCREV = "d039998ad2c55aeae4191af30e15bbd3032508c1"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=fa818a259cbed7ce8bc2a22d35a464fc"
+
+inherit cmake
+inherit obmc-phosphor-dbus-service
+inherit obmc-phosphor-systemd
+inherit pkgconfig pythonnative
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.selftest.service"
+
+DEPENDS += " \
+ autoconf-archive-native \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ "
+
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ "
+
+EXTRA_OECMAKE = " -DENABLE_GTEST=OFF -DCMAKE_SKIP_RPATH=ON"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
new file mode 100644
index 000000000..c78b00bc1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -0,0 +1,9 @@
+SRCREV = "3840d0ad45134597455f6d70fe1ae76f3cac0e7d"
+#SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
+
+DEPENDS_append = " libgpiod libmctp"
+
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+EXTRA_OECMAKE += "-DDISABLE_NVME=OFF"
+SYSTEMD_SERVICE_${PN} += " xyz.openbmc_project.nvmesensor.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
new file mode 100644
index 000000000..e49a410cb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Settings"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SYSTEMD_SERVICE_${PN} = "xyz.openbmc_project.Settings.service"
+
+DEPENDS = "boost \
+ nlohmann-json \
+ sdbusplus"
+
+S = "${WORKDIR}/git/settings"
+inherit cmake systemd
+
+EXTRA_OECMAKE = "-DYOCTO=1"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
new file mode 100644
index 000000000..6f6bb860d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
@@ -0,0 +1,31 @@
+SUMMARY = "Special mode manager daemon to handle manufacturing modes"
+DESCRIPTION = "Daemon exposes the manufacturing mode property"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/special-mode-manager.git;protocol=ssh"
+SRCREV = "cf2ba04cf68d76047211f66d9bb4ae1be1907323"
+
+EXTRA_OECMAKE += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'validation-unsecure', '-DBMC_VALIDATION_UNSECURE_FEATURE=ON', '', d)}"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "specialmodemgr.service"
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ boost \
+ libpam \
+ "
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb
new file mode 100644
index 000000000..b1ac1fbc1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb
@@ -0,0 +1,28 @@
+SUMMARY = "Service configuration manager daemon to control service properties"
+DESCRIPTION = "Daemon controls service properies like port, channels, state etc.."
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/srvcfg-manager"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "srvcfg-manager.service"
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ boost \
+ "
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
new file mode 100644
index 000000000..d23480a05
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += "gtest"
+
+SYSTEMD_SERVICE_${PN}-bmc += "obmc-mapper.target"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb
new file mode 100644
index 000000000..cc84015f4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb
@@ -0,0 +1,19 @@
+SUMMARY = "Callback Manager"
+DESCRIPTION = "D-Bus daemon that registers matches that trigger method calls"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground;protocol=ssh"
+
+inherit cmake systemd
+DEPENDS = "boost sdbusplus"
+
+PV = "0.1+git${SRCPV}"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+S = "${WORKDIR}/git/callback-manager"
+
+SYSTEMD_SERVICE_${PN} += "callback-manager.service"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENCE;md5=7becf906c8f8d03c237bad13bc3dac53"
+
+EXTRA_OECMAKE = "-DYOCTO=1"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch
new file mode 100644
index 000000000..2182201cf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch
@@ -0,0 +1,1658 @@
+From ab2ff3d715b00a13b0a670fb010793dc626352e0 Mon Sep 17 00:00:00 2001
+From: Radivoje Jovanovic <radivoje.jovanovic@intel.com>
+Date: Mon, 2 Jul 2018 19:23:25 -0700
+Subject: [PATCH] Added suport for multiple user manager services
+
+Support added for SSSD service implementation
+
+Signed-off-by: Alberto Salazar Perez <alberto.salazar.perez@intel.com>
+Signed-off-by: Radivoje Jovanovic <radivoje.jovanovic@intel.com>
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ Makefile.am | 5 +-
+ mainapp.cpp | 89 ++++++-
+ user_mgr.cpp | 297 ++-------------------
+ user_mgr.hpp | 9 +-
+ user_service.cpp | 786 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ user_service.hpp | 233 +++++++++++++++++
+ 6 files changed, 1145 insertions(+), 274 deletions(-)
+ create mode 100644 user_service.cpp
+ create mode 100644 user_service.hpp
+
+diff --git a/Makefile.am b/Makefile.am
+index 7c7271e..58916b0 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,11 +1,12 @@
+ bin_PROGRAMS = phosphor-user-manager
+
+-noinst_HEADERS = user_mgr.hpp users.hpp
++noinst_HEADERS = user_mgr.hpp users.hpp user_service.hpp
+
+ phosphor_user_manager_SOURCES = \
+ mainapp.cpp \
+ user_mgr.cpp \
+- users.cpp
++ users.cpp \
++ user_service.cpp
+
+ phosphor_user_manager_LDFLAGS = $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+diff --git a/mainapp.cpp b/mainapp.cpp
+index c9da030..03c406a 100644
+--- a/mainapp.cpp
++++ b/mainapp.cpp
+@@ -14,18 +14,105 @@
+ * limitations under the License.
+ */
+ #include <string>
++#include <iostream>
++#include <getopt.h>
+ #include "user_mgr.hpp"
++#include "user_service.hpp"
+ #include "config.h"
+
+ // D-Bus root for user manager
+ constexpr auto USER_MANAGER_ROOT = "/xyz/openbmc_project/user";
+
++void printUsage()
++{
++ std::string usage =
++ R"(Usage:
++ phosphor-user-manager [OPTIONS]
++
++Backend DBUS service for OpenBMC User Management.
++If no OPTIONS are specified, shadow file will be used.
++
++Options:
++ -s, --service={shadow|sssd}
++ Specify the authentication service to use:
++ 'shadow' will use the /etc/shadow file.
++ 'sssd' will use the sssd service domains.
++ -h, --help Displays this help message.
++)";
++ std::cerr << usage;
++}
++
++void parseArgs(int argc, char** argv,
++ phosphor::user::UserService::ServiceType& srvc)
++{
++ const std::string shortOpts{"s:h"};
++ const struct option longOpts[] = {{"service", 1, nullptr, 's'},
++ {"help", 0, nullptr, 'h'},
++ {nullptr, 0, nullptr, 0}};
++
++ while (true)
++ {
++ const auto opt =
++ getopt_long(argc, argv, shortOpts.c_str(), longOpts, nullptr);
++
++ if (opt == -1)
++ {
++ if (srvc == phosphor::user::UserService::ServiceType::none)
++ {
++ srvc = phosphor::user::UserService::ServiceType::shadow;
++ }
++ break;
++ }
++
++ switch (opt)
++ {
++ case 's':
++ {
++ std::string srvcStr{optarg};
++ if (!srvcStr.compare("shadow"))
++ {
++ srvc = phosphor::user::UserService::ServiceType::shadow;
++ }
++ else if (!srvcStr.compare("sssd"))
++ {
++ srvc = phosphor::user::UserService::ServiceType::sssd;
++ }
++ else
++ {
++ std::cerr << "Error. '" << srvcStr << "' is not a valid"
++ << " authentication service." << std::endl;
++ printUsage();
++ exit(1);
++ }
++ }
++ break;
++
++ case 'h':
++ {
++ printUsage();
++ exit(0);
++ }
++
++ default:
++ {
++ printUsage();
++ exit(1);
++ }
++ }
++ }
++}
++
+ int main(int argc, char** argv)
+ {
++ // Check command line options. Exit if error.
++ phosphor::user::UserService::ServiceType srvc =
++ phosphor::user::UserService::ServiceType::none;
++ parseArgs(argc, argv, srvc);
++
+ auto bus = sdbusplus::bus::new_default();
+ sdbusplus::server::manager::manager objManager(bus, USER_MANAGER_ROOT);
+
+- phosphor::user::UserMgr userMgr(bus, USER_MANAGER_ROOT);
++ phosphor::user::UserMgr userMgr(bus, USER_MANAGER_ROOT, srvc);
+
+ // Claim the bus now
+ bus.request_name(USER_MANAGER_BUSNAME);
+diff --git a/user_mgr.cpp b/user_mgr.cpp
+index 9694fd1..c48196a 100644
+--- a/user_mgr.cpp
++++ b/user_mgr.cpp
+@@ -14,27 +14,20 @@
+ // limitations under the License.
+ */
+
+-#include <shadow.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <sys/wait.h>
+ #include <time.h>
++#include <cstdio>
+ #include <fstream>
+ #include <grp.h>
+ #include <pwd.h>
+ #include <regex>
+-#include <algorithm>
+-#include <numeric>
+-#include <boost/process/child.hpp>
+-#include <boost/process/io.hpp>
+ #include <boost/algorithm/string/split.hpp>
+ #include <xyz/openbmc_project/Common/error.hpp>
+ #include <xyz/openbmc_project/User/Common/error.hpp>
+ #include <phosphor-logging/log.hpp>
+ #include <phosphor-logging/elog.hpp>
+ #include <phosphor-logging/elog-errors.hpp>
++#include <stdexcept>
+ #include "shadowlock.hpp"
+-#include "file.hpp"
+ #include "user_mgr.hpp"
+ #include "users.hpp"
+ #include "config.h"
+@@ -44,12 +37,10 @@ namespace phosphor
+ namespace user
+ {
+
+-static constexpr const char *passwdFileName = "/etc/passwd";
+ static constexpr size_t ipmiMaxUsers = 15;
+ static constexpr size_t ipmiMaxUserNameLen = 16;
+ static constexpr size_t systemMaxUserNameLen = 30;
+ static constexpr size_t maxSystemUsers = 30;
+-static constexpr const char *grpSsh = "ssh";
+ static constexpr uint8_t minPasswdLength = 8;
+ static constexpr int success = 0;
+ static constexpr int failure = -1;
+@@ -95,79 +86,6 @@ using NoResource =
+
+ using Argument = xyz::openbmc_project::Common::InvalidArgument;
+
+-template <typename... ArgTypes>
+-static std::vector<std::string> executeCmd(const char *path,
+- ArgTypes &&... tArgs)
+-{
+- std::vector<std::string> stdOutput;
+- boost::process::ipstream stdOutStream;
+- boost::process::child execProg(path, const_cast<char *>(tArgs)...,
+- boost::process::std_out > stdOutStream);
+- std::string stdOutLine;
+-
+- while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
+- !stdOutLine.empty())
+- {
+- stdOutput.emplace_back(stdOutLine);
+- }
+-
+- execProg.wait();
+-
+- int retCode = execProg.exit_code();
+- if (retCode)
+- {
+- log<level::ERR>("Command execution failed", entry("PATH=%d", path),
+- entry("RETURN_CODE:%d", retCode));
+- elog<InternalFailure>();
+- }
+-
+- return stdOutput;
+-}
+-
+-static std::string getCSVFromVector(std::vector<std::string> vec)
+-{
+- switch (vec.size())
+- {
+- case 0:
+- {
+- return "";
+- }
+- break;
+-
+- case 1:
+- {
+- return std::string{vec[0]};
+- }
+- break;
+-
+- default:
+- {
+- return std::accumulate(
+- std::next(vec.begin()), vec.end(), vec[0],
+- [](std::string a, std::string b) { return a + ',' + b; });
+- }
+- }
+-}
+-
+-static bool removeStringFromCSV(std::string &csvStr, const std::string &delStr)
+-{
+- std::string::size_type delStrPos = csvStr.find(delStr);
+- if (delStrPos != std::string::npos)
+- {
+- // need to also delete the comma char
+- if (delStrPos == 0)
+- {
+- csvStr.erase(delStrPos, delStr.size() + 1);
+- }
+- else
+- {
+- csvStr.erase(delStrPos - 1, delStr.size() + 1);
+- }
+- return true;
+- }
+- return false;
+-}
+-
+ bool UserMgr::isUserExist(const std::string &userName)
+ {
+ if (userName.empty())
+@@ -294,39 +212,14 @@ void UserMgr::createUser(std::string userName,
+ {
+ throwForInvalidPrivilege(priv);
+ throwForInvalidGroups(groupNames);
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserExists(userName);
+ throwForUserNameConstraints(userName, groupNames);
+ throwForMaxGrpUserCount(groupNames);
+
+- std::string groups = getCSVFromVector(groupNames);
+- bool sshRequested = removeStringFromCSV(groups, grpSsh);
+-
+- // treat privilege as a group - This is to avoid using different file to
+- // store the same.
+- if (!priv.empty())
+- {
+- if (groups.size() != 0)
+- {
+- groups += ",";
+- }
+- groups += priv;
+- }
+- try
+- {
+- executeCmd("/usr/sbin/useradd", userName.c_str(), "-G", groups.c_str(),
+- "-m", "-N", "-s",
+- (sshRequested ? "/bin/sh" : "/bin/nologin"), "-e",
+- (enabled ? "" : "1970-01-02"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to create new user");
+- elog<InternalFailure>();
+- }
++ // Tell the User Service to create a new user with the info provided.
++ userSrvc->createUser(userName, groupNames, priv, enabled);
+
+- // Add the users object before sending out the signal
++ // Add the users to the local list before sending out the signal
+ std::string userObj = std::string(usersObjPath) + "/" + userName;
+ std::sort(groupNames.begin(), groupNames.end());
+ usersList.emplace(
+@@ -340,19 +233,11 @@ void UserMgr::createUser(std::string userName,
+
+ void UserMgr::deleteUser(std::string userName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+- try
+- {
+- executeCmd("/usr/sbin/userdel", userName.c_str(), "-r");
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("User delete failed",
+- entry("USER_NAME=%s", userName.c_str()));
+- elog<InternalFailure>();
+- }
++
++ // Tell the User Service to delete user
++ userSrvc->deleteUser(userName);
++ // Then delete user from local list
+
+ usersList.erase(userName);
+
+@@ -363,24 +248,13 @@ void UserMgr::deleteUser(std::string userName)
+
+ void UserMgr::renameUser(std::string userName, std::string newUserName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+ throwForUserExists(newUserName);
+ throwForUserNameConstraints(newUserName,
+ usersList[userName].get()->userGroups());
+- try
+- {
+- std::string newHomeDir = "/home/" + newUserName;
+- executeCmd("/usr/sbin/usermod", "-l", newUserName.c_str(),
+- userName.c_str(), "-d", newHomeDir.c_str(), "-m");
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("User rename failed",
+- entry("USER_NAME=%s", userName.c_str()));
+- elog<InternalFailure>();
+- }
++ // Call The User Service to rename user on the system
++ userSrvc->renameUser(userName, newUserName);
++ // Update local list to reflect the name change
+ const auto &user = usersList[userName];
+ std::string priv = user.get()->userPrivilege();
+ std::vector<std::string> groupNames = user.get()->userGroups();
+@@ -404,8 +278,6 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName,
+ {
+ throwForInvalidPrivilege(priv);
+ throwForInvalidGroups(groupNames);
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+ const std::vector<std::string> &oldGroupNames =
+ usersList[userName].get()->userGroups();
+@@ -421,29 +293,8 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName,
+ throwForMaxGrpUserCount(groupNames);
+ }
+
+- std::string groups = getCSVFromVector(groupNames);
+- bool sshRequested = removeStringFromCSV(groups, grpSsh);
+-
+- // treat privilege as a group - This is to avoid using different file to
+- // store the same.
+- if (!priv.empty())
+- {
+- if (groups.size() != 0)
+- {
+- groups += ",";
+- }
+- groups += priv;
+- }
+- try
+- {
+- executeCmd("/usr/sbin/usermod", userName.c_str(), "-G", groups.c_str(),
+- "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to modify user privilege / groups");
+- elog<InternalFailure>();
+- }
++ // Call The User Service to update user groups and priv on the system
++ userSrvc->updateGroupsAndPriv(userName, groupNames, priv);
+
+ log<level::INFO>("User groups / privilege updated successfully",
+ entry("USER_NAME=%s", userName.c_str()));
+@@ -639,19 +490,9 @@ int UserMgr::setPamModuleArgValue(const std::string &moduleName,
+
+ void UserMgr::userEnable(const std::string &userName, bool enabled)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+ throwForUserDoesNotExist(userName);
+- try
+- {
+- executeCmd("/usr/sbin/usermod", userName.c_str(), "-e",
+- (enabled ? "" : "1970-01-02"));
+- }
+- catch (const InternalFailure &e)
+- {
+- log<level::ERR>("Unable to modify user enabled state");
+- elog<InternalFailure>();
+- }
++ // Call The User Service to update user groups and priv on the system
++ userSrvc->updateUserStatus(userName, enabled);
+
+ log<level::INFO>("User enabled/disabled state updated successfully",
+ entry("USER_NAME=%s", userName.c_str()),
+@@ -773,54 +614,8 @@ bool UserMgr::userPasswordExpired(const std::string &userName)
+
+ UserSSHLists UserMgr::getUserAndSshGrpList()
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+-
+- std::vector<std::string> userList;
+- std::vector<std::string> sshUsersList;
+- struct passwd pw, *pwp = nullptr;
+- std::array<char, 1024> buffer{};
+-
+- phosphor::user::File passwd(passwdFileName, "r");
+- if ((passwd)() == NULL)
+- {
+- log<level::ERR>("Error opening the passwd file");
+- elog<InternalFailure>();
+- }
+-
+- while (true)
+- {
+- auto r = fgetpwent_r((passwd)(), &pw, buffer.data(), buffer.max_size(),
+- &pwp);
+- if ((r != 0) || (pwp == NULL))
+- {
+- // Any error, break the loop.
+- break;
+- }
+-#ifdef ENABLE_ROOT_USER_MGMT
+- // Add all users whose UID >= 1000 and < 65534
+- // and special UID 0.
+- if ((pwp->pw_uid == 0) ||
+- ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534)))
+-#else
+- // Add all users whose UID >=1000 and < 65534
+- if ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534))
+-#endif
+- {
+- std::string userName(pwp->pw_name);
+- userList.emplace_back(userName);
+-
+- // ssh doesn't have separate group. Check login shell entry to
+- // get all users list which are member of ssh group.
+- std::string loginShell(pwp->pw_shell);
+- if (loginShell == "/bin/sh")
+- {
+- sshUsersList.emplace_back(userName);
+- }
+- }
+- }
+- endpwent();
+- return std::make_pair(std::move(userList), std::move(sshUsersList));
++ // Call The User Service to get the User and SSUsers lists
++ return std::move(userSrvc->getUserAndSshGrpList());
+ }
+
+ size_t UserMgr::getIpmiUsersCount()
+@@ -831,49 +626,14 @@ size_t UserMgr::getIpmiUsersCount()
+
+ bool UserMgr::isUserEnabled(const std::string &userName)
+ {
+- // All user management lock has to be based on /etc/shadow
+- phosphor::user::shadow::Lock lock();
+- std::array<char, 4096> buffer{};
+- struct spwd spwd;
+- struct spwd *resultPtr = nullptr;
+- int status = getspnam_r(userName.c_str(), &spwd, buffer.data(),
+- buffer.max_size(), &resultPtr);
+- if (!status && (&spwd == resultPtr))
+- {
+- if (resultPtr->sp_expire >= 0)
+- {
+- return false; // user locked out
+- }
+- return true;
+- }
+- return false; // assume user is disabled for any error.
++ // Call The User Service to verify if user is enabled
++ return userSrvc->isUserEnabled(userName);
+ }
+
+ std::vector<std::string> UserMgr::getUsersInGroup(const std::string &groupName)
+ {
+- std::vector<std::string> usersInGroup;
+- // Should be more than enough to get the pwd structure.
+- std::array<char, 4096> buffer{};
+- struct group grp;
+- struct group *resultPtr = nullptr;
+-
+- int status = getgrnam_r(groupName.c_str(), &grp, buffer.data(),
+- buffer.max_size(), &resultPtr);
+-
+- if (!status && (&grp == resultPtr))
+- {
+- for (; *(grp.gr_mem) != NULL; ++(grp.gr_mem))
+- {
+- usersInGroup.emplace_back(*(grp.gr_mem));
+- }
+- }
+- else
+- {
+- log<level::ERR>("Group not found",
+- entry("GROUP=%s", groupName.c_str()));
+- // Don't throw error, just return empty userList - fallback
+- }
+- return usersInGroup;
++ // Call The User Service to get the users that belong to a group
++ return std::move(userSrvc->getUsersInGroup(groupName));
+ }
+
+ DbusUserObj UserMgr::getPrivilegeMapperObject(void)
+@@ -1104,11 +864,9 @@ void UserMgr::initUserObjects(void)
+ {
+ // All user management lock has to be based on /etc/shadow
+ phosphor::user::shadow::Lock lock();
+- std::vector<std::string> userNameList;
+- std::vector<std::string> sshGrpUsersList;
+ UserSSHLists userSSHLists = getUserAndSshGrpList();
+- userNameList = std::move(userSSHLists.first);
+- sshGrpUsersList = std::move(userSSHLists.second);
++ std::vector<std::string> userNameList = std::move(userSSHLists.first);
++ std::vector<std::string> sshGrpUsersList = std::move(userSSHLists.second);
+
+ if (!userNameList.empty())
+ {
+@@ -1163,8 +921,10 @@ void UserMgr::initUserObjects(void)
+ }
+ }
+
+-UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+- Ifaces(bus, path, true), bus(bus), path(path)
++UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path,
++ UserService::ServiceType srvc) :
++ Ifaces(bus, path, true),
++ bus(bus), path(path)
+ {
+ UserMgrIface::allPrivileges(privMgr);
+ std::sort(groupsMgr.begin(), groupsMgr.end());
+@@ -1272,6 +1032,7 @@ UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+ }
+ AccountPolicyIface::accountUnlockTimeout(value32);
+ }
++ userSrvc = std::make_unique<UserService>(srvc, groupsMgr, privMgr);
+ initUserObjects();
+
+ // emit the signal
+diff --git a/user_mgr.hpp b/user_mgr.hpp
+index e25ca87..262aaf9 100644
+--- a/user_mgr.hpp
++++ b/user_mgr.hpp
+@@ -21,6 +21,7 @@
+ #include <unordered_map>
+ #include <variant>
+ #include "users.hpp"
++#include "user_service.hpp"
+
+ namespace phosphor
+ {
+@@ -28,8 +29,6 @@ namespace user
+ {
+
+ using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager;
+-using UserSSHLists =
+- std::pair<std::vector<std::string>, std::vector<std::string>>;
+ using AccountPolicyIface =
+ sdbusplus::xyz::openbmc_project::User::server::AccountPolicy;
+
+@@ -76,8 +75,10 @@ class UserMgr : public Ifaces
+ *
+ * @param[in] bus - sdbusplus handler
+ * @param[in] path - D-Bus path
++ * @param[in] srvc - User service to be used
+ */
+- UserMgr(sdbusplus::bus::bus &bus, const char *path);
++ UserMgr(sdbusplus::bus::bus &bus, const char *path,
++ UserService::ServiceType srvc);
+
+ /** @brief create user method.
+ * This method creates a new user as requested
+@@ -193,6 +194,8 @@ class UserMgr : public Ifaces
+ /** @brief object path */
+ const std::string path;
+
++ /** @brief user service to be used */
++ std::unique_ptr<UserService> userSrvc;
+ /** @brief privilege manager container */
+ std::vector<std::string> privMgr = {"priv-admin", "priv-operator",
+ "priv-user", "priv-noaccess"};
+diff --git a/user_service.cpp b/user_service.cpp
+new file mode 100644
+index 0000000..c3c45bd
+--- /dev/null
++++ b/user_service.cpp
+@@ -0,0 +1,786 @@
++/*
++// Copyright (c) 2018 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#include <grp.h>
++#include <pwd.h>
++#include <numeric>
++#include <boost/process/child.hpp>
++#include <boost/process/io.hpp>
++#include <boost/algorithm/string/split.hpp>
++#include "shadowlock.hpp"
++#include "file.hpp"
++#include "user_service.hpp"
++
++/* anonymous namespace for User Service interface implementations.
++// Each class inside this namespace implements a special service
++// to be used for the User Manager class. This can be extended to use
++// other user management services and it should be as simple as
++// adding a new class which inherits from phosphor::user::UserServiceInterface
++*/
++
++namespace
++{
++
++std::string getCSVFromVector(std::vector<std::string> vec)
++{
++ switch (vec.size())
++ {
++ case 0:
++ {
++ return "";
++ }
++ break;
++
++ case 1:
++ {
++ return std::string{vec[0]};
++ }
++ break;
++
++ default:
++ {
++ return std::accumulate(
++ std::next(vec.begin()), vec.end(), vec[0],
++ [](std::string a, std::string b) { return a + ',' + b; });
++ }
++ }
++}
++
++bool removeStringFromCSV(std::string &csvStr, const std::string &delStr)
++{
++ std::string::size_type delStrPos = csvStr.find(delStr);
++ if (delStrPos != std::string::npos)
++ {
++ // need to also delete the comma char
++ if (delStrPos == 0)
++ {
++ csvStr.erase(delStrPos, delStr.size() + 1);
++ }
++ else
++ {
++ csvStr.erase(delStrPos - 1, delStr.size() + 1);
++ }
++ return true;
++ }
++ return false;
++}
++
++class ShadowService : public phosphor::user::UserServiceInterface
++{
++ public:
++ ShadowService() = default;
++
++ ~ShadowService() = default;
++
++ phosphor::user::UserSSHLists getUserAndSshGrpList() const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::vector<std::string> userList;
++ std::vector<std::string> sshUsersList;
++
++ struct passwd pw, *pwp = nullptr;
++ std::array<char, 1024> buffer{};
++
++ phosphor::user::File passwd(passwdFileName, "r");
++ if ((passwd)() == NULL)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error opening the passwd file");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ while (true)
++ {
++ auto r = fgetpwent_r((passwd)(), &pw, buffer.data(),
++ buffer.max_size(), &pwp);
++ if ((r != 0) || (pwp == NULL))
++ {
++ // Any error, break the loop.
++ break;
++ }
++#ifdef ENABLE_ROOT_USER_MGMT
++ // Add all users whose UID >= 1000 and < 65534
++ // and special UID 0.
++ if ((pwp->pw_uid == 0) ||
++ ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534)))
++#else
++ // Add all users whose UID >=1000 and < 65534
++ if ((pwp->pw_uid >= 1000) && (pwp->pw_uid < 65534))
++#endif
++ {
++ std::string userName(pwp->pw_name);
++ userList.emplace_back(userName);
++
++ // ssh doesn't have separate group. Check login shell entry to
++ // get all users list which are member of ssh group.
++ std::string loginShell(pwp->pw_shell);
++ if (loginShell == "/bin/sh")
++ {
++ sshUsersList.emplace_back(userName);
++ }
++ }
++ }
++ endpwent();
++ return std::make_pair(std::move(userList), std::move(sshUsersList));
++ }
++
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const override
++ {
++ std::vector<std::string> usersInGroup;
++ // Should be more than enough to get the pwd structure.
++ std::array<char, 4096> buffer{};
++ struct group grp;
++ struct group *grpPtr = &grp;
++ struct group *resultPtr;
++
++ int status = getgrnam_r(groupName.c_str(), grpPtr, buffer.data(),
++ buffer.max_size(), &resultPtr);
++
++ if (!status && (grpPtr == resultPtr))
++ {
++ for (; *(grp.gr_mem) != NULL; ++(grp.gr_mem))
++ {
++ usersInGroup.emplace_back(*(grp.gr_mem));
++ }
++ }
++ else
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Group not found",
++ phosphor::logging::entry("GROUP=%s", groupName.c_str()));
++ // Don't throw error, just return empty usersInGroup - fallback
++ }
++ return usersInGroup;
++ }
++
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups.append(",");
++ }
++ groups.append(priv);
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/useradd", userName.c_str(), "-G", groups.c_str(),
++ "-m", "-N", "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"),
++ "-e", (enabled ? "" : "1970-01-02"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create new user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ try
++ {
++ std::string newHomeDir = "/home/" + newUserName;
++ phosphor::user::executeCmd("/usr/sbin/usermod", "-l",
++ newUserName.c_str(), userName.c_str(),
++ "-d", newHomeDir.c_str(), "-m");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "User rename failed",
++ phosphor::logging::entry("USER_NAME=%s", userName.c_str()));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void deleteUser(const std::string &userName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/userdel", userName.c_str(),
++ "-r");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "User delete failed",
++ phosphor::logging::entry("USER_NAME=%s", userName.c_str()));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same.
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/usermod", userName.c_str(), "-G", groups.c_str(),
++ "-s", (sshRequested ? "/bin/sh" : "/bin/nologin"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to modify user privilege / groups");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/usermod", userName.c_str(),
++ "-e", (enabled ? "" : "1970-01-02"));
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to modify user enabled state");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ bool isUserEnabled(const std::string &userName) const override
++ {
++ // All user management lock has to be based on /etc/shadow
++ phosphor::user::shadow::Lock lock();
++ std::array<char, 4096> buffer{};
++ struct spwd spwd;
++ struct spwd *resultPtr = nullptr;
++ int status = getspnam_r(userName.c_str(), &spwd, buffer.data(),
++ buffer.max_size(), &resultPtr);
++ if (!status && (&spwd == resultPtr))
++ {
++ if (resultPtr->sp_expire >= 0)
++ {
++ return false; // user locked out
++ }
++ return true;
++ }
++ return false; // assume user is disabled for any error.
++ }
++
++ std::vector<std::string>
++ getUserGroups(const std::string &userName) const override
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "ShadowService::getUserGroups not implemented!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ return std::vector<std::string>();
++ }
++
++ void createGroup(const std::string &groupName) const override
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "ShadowService::createGroup not implemented!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ private:
++ static constexpr const char *passwdFileName = "/etc/passwd";
++};
++
++class SSSDService : public phosphor::user::UserServiceInterface
++{
++ public:
++ SSSDService(const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++ {
++
++ createGroup(lockedGrp);
++ for (const auto &g : groups)
++ {
++ createGroup(g);
++ }
++ for (const auto &p : privs)
++ {
++ createGroup(p);
++ }
++ }
++
++ ~SSSDService() = default;
++
++ phosphor::user::UserSSHLists getUserAndSshGrpList() const override
++ {
++ std::vector<std::string> users;
++ std::vector<std::string> sshGroup;
++ std::vector<std::string> exeOutput;
++
++ try
++ {
++ exeOutput = phosphor::user::executeCmd("/usr/bin/getent", "-s",
++ "sss", "passwd");
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get users information "
++ "from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ for (const auto &userLine : exeOutput)
++ {
++ std::vector<std::string> userInfo;
++ boost::algorithm::split(userInfo, userLine,
++ boost::algorithm::is_any_of(":"));
++ // At this point userInfo is a vector containing the passwd
++ // info for the user, so we know the correct positions:
++ // 0: User name.
++ // 1: Encrypted password.
++ // 2: User ID number (UID)
++ // 3: User's group ID number (GID)
++ // 4: Full name of the user (GECOS)
++ // 5: User home directory.
++ // 6: Login shell.
++ users.emplace_back(userInfo[0]);
++
++ // ssh doesn't have separate group. Check login shell entry to
++ // get all users list which are member of ssh group.
++ if (userInfo[6] == "/bin/sh")
++ {
++ sshGroup.emplace_back(userInfo[0]);
++ }
++ }
++
++ return std::make_pair(std::move(users), std::move(sshGroup));
++ }
++
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const override
++ {
++ std::vector<std::string> userList;
++ std::vector<std::string> exeOutput;
++
++ try
++ {
++ exeOutput = phosphor::user::executeCmd("/usr/sbin/sss_groupshow",
++ groupName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get group users from sssd service");
++ // Don't throw error, just return empty usersInGroup - return
++ return userList;
++ }
++ // exeOutput should have 5 entries
++ // 0: Group
++ // 1: GID number
++ // 2: Member users
++ // 3: Is a member of
++ // 4: Member groups
++ exeOutput[2].erase(
++ exeOutput[2].begin(),
++ std::find(exeOutput[2].begin(), exeOutput[2].end(), ':'));
++ boost::algorithm::trim_left(exeOutput[2]);
++ boost::algorithm::split(userList, exeOutput[2],
++ boost::algorithm::is_any_of(","));
++ return userList;
++ }
++
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const override
++ {
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/sss_useradd", "-m", "-G", groups.c_str(), "-s",
++ (sshRequested ? "/bin/sh" : "/bin/nologin"), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create new user in sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ // Sometimes the SSSD service needs some time to actually
++ // reflect the changes to the local DB to the NSS service,
++ // that is why we have this sleep here ...
++ std::this_thread::sleep_for(std::chrono::seconds(1));
++ // update user status (locked/unlocked)
++ updateUserStatus(userName, enabled);
++ }
++
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const override
++ {
++ std::vector<std::string> exeOutput;
++ // Local Domain for sssd doesn't have a rename feature
++ // so we need to first create a new user and then delete
++ // the old one.
++ // The only issue with this is that the password for the
++ // user will have to be reseted since it is a new user being created.
++
++ // Get original user groups
++ std::vector<std::string> groups = getUserGroups(userName);
++ // Check if it has a "ssh" group by looking for the shell login
++ try
++ {
++ exeOutput = phosphor::user::executeCmd(
++ "/usr/bin/getent", "-s", "sss", "passwd", userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get information for user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ if (exeOutput[0].find("/bin/sh"))
++ {
++ groups.emplace_back(phosphor::user::grpSsh);
++ }
++ // Call create user with the new user names and previous groups
++ // Priv is already part of the groups so that can be empty.
++ createUser(newUserName, groups, "", isUserEnabled(userName));
++
++ // Now delete original user
++ deleteUser(userName);
++ }
++
++ void deleteUser(const std::string &userName) const override
++ {
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_userdel", "-r",
++ userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to delete user from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const override
++ {
++ // local domain sssd do not allow to update all list of groups,
++ // so we will remove all groups first (except for the user one)
++ // and then all all the ones that were passed
++ std::string oldGroups = getCSVFromVector(getUserGroups(userName));
++ std::string groups = getCSVFromVector(groupNames);
++ bool sshRequested = removeStringFromCSV(groups, phosphor::user::grpSsh);
++ // treat privilege as a group - This is to avoid using different file to
++ // store the same
++ if (!priv.empty())
++ {
++ if (groups.size() != 0)
++ {
++ groups += ",";
++ }
++ groups += priv;
++ }
++ try
++ {
++ phosphor::user::executeCmd(
++ "/usr/sbin/sss_usermod", "-r", oldGroups.c_str(), "-a",
++ groups.c_str(), "-s",
++ (sshRequested ? "/bin/sh" : "/bin/nologin"), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to update user groups and "
++ "priv from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const override
++ {
++ std::string enabledStr;
++ std::string lockedStr;
++ if (isUserEnabled(userName) == enabled)
++ {
++ return;
++ }
++ if (enabled)
++ {
++ enabledStr = "-r";
++ lockedStr = "-U";
++ }
++ else
++ {
++ enabledStr = "-a";
++ lockedStr = "-L";
++ }
++ try
++ {
++ // We will add a special locked group to identify the users
++ // that have been locked out of the system.
++ // TODO: sss_usermod is not locking user accounts for the
++ // LOCAL domain, need to find the correct PAM configuration
++ // to actually lockout users for SSSD.
++ // As a workaround we are using the pam module pam_listfile.so
++ // to lockout all users that belong to the locked group.
++ phosphor::user::executeCmd("/usr/sbin/sss_usermod",
++ enabledStr.c_str(), lockedGrp.c_str(),
++ lockedStr.c_str(), userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to update user status from sssd service");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ bool isUserEnabled(const std::string &userName) const override
++ {
++ std::vector<std::string> userGrps = getUserGroups(userName);
++ return std::find(userGrps.begin(), userGrps.end(), lockedGrp) ==
++ userGrps.end();
++ }
++
++ std::vector<std::string>
++ getUserGroups(const std::string &userName) const override
++ {
++ std::vector<std::string> exeOutput;
++ try
++ {
++ exeOutput =
++ phosphor::user::executeCmd("/usr/bin/groups", userName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to get groups for user");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ std::vector<std::string> groups;
++ boost::algorithm::split(groups, exeOutput[0],
++ boost::algorithm::is_any_of(" "));
++ // Delete group that equals user name if it exists
++ auto userNameGroup = std::find(groups.begin(), groups.end(), userName);
++ if (userNameGroup != groups.end())
++ {
++ groups.erase(userNameGroup);
++ }
++ return groups;
++ }
++
++ void createGroup(const std::string &groupName) const override
++ {
++ try
++ {
++ if (!groupExists(groupName))
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_groupadd",
++ groupName.c_str());
++ }
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Unable to create group");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ }
++
++ private:
++ static const std::string lockedGrp;
++
++ bool groupExists(const std::string &groupName) const
++ {
++ try
++ {
++ phosphor::user::executeCmd("/usr/sbin/sss_groupshow",
++ groupName.c_str());
++ }
++ catch (const phosphor::user::InternalFailure &e)
++ {
++ return false;
++ }
++ return true;
++ }
++};
++
++const std::string SSSDService::lockedGrp = "sssd_locked";
++} // anonymous namespace
++
++namespace phosphor
++{
++namespace user
++{
++
++UserService::UserService(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ setServiceImpl(srvcType, groups, privs);
++}
++
++void UserService::updateServiceType(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ usrSrvcImpl.reset();
++ setServiceImpl(srvcType, groups, privs);
++}
++
++void UserService::setServiceImpl(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs)
++{
++ switch (srvcType)
++ {
++ case ServiceType::shadow:
++ {
++ usrSrvcImpl = std::make_unique<ShadowService>();
++ }
++ break;
++
++ case ServiceType::sssd:
++ {
++ usrSrvcImpl = std::make_unique<SSSDService>(groups, privs);
++ }
++ break;
++
++ case ServiceType::none:
++ default:
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Invalid service type initialization!");
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++ break;
++ }
++}
++
++UserService::~UserService()
++{
++}
++
++phosphor::user::UserSSHLists UserService::getUserAndSshGrpList() const
++{
++ return usrSrvcImpl->getUserAndSshGrpList();
++}
++
++std::vector<std::string>
++ UserService::getUsersInGroup(const std::string &groupName) const
++{
++ return usrSrvcImpl->getUsersInGroup(groupName);
++}
++
++void UserService::createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const
++{
++ usrSrvcImpl->createUser(userName, groupNames, priv, enabled);
++}
++
++void UserService::renameUser(const std::string &userName,
++ const std::string &newUserName) const
++{
++ usrSrvcImpl->renameUser(userName, newUserName);
++}
++
++void UserService::deleteUser(const std::string &userName) const
++{
++ usrSrvcImpl->deleteUser(userName);
++}
++
++void UserService::updateGroupsAndPriv(
++ const std::string &userName, const std::vector<std::string> &groupNames,
++ const std::string &priv) const
++{
++ usrSrvcImpl->updateGroupsAndPriv(userName, groupNames, priv);
++}
++
++void UserService::updateUserStatus(const std::string &userName,
++ const bool &enabled) const
++{
++ usrSrvcImpl->updateUserStatus(userName, enabled);
++}
++
++bool UserService::isUserEnabled(const std::string &userName) const
++{
++ return usrSrvcImpl->isUserEnabled(userName);
++}
++
++std::vector<std::string>
++ UserService::getUserGroups(const std::string &userName) const
++{
++ return usrSrvcImpl->getUserGroups(userName);
++}
++
++} // namespace user
++} // namespace phosphor
+diff --git a/user_service.hpp b/user_service.hpp
+new file mode 100644
+index 0000000..97a049b
+--- /dev/null
++++ b/user_service.hpp
+@@ -0,0 +1,233 @@
++/*
++// Copyright (c) 2018 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++
++#pragma once
++#include <xyz/openbmc_project/Common/error.hpp>
++#include <xyz/openbmc_project/User/Common/error.hpp>
++#include <phosphor-logging/log.hpp>
++#include <phosphor-logging/elog.hpp>
++#include <boost/process/child.hpp>
++#include <boost/process/io.hpp>
++
++namespace phosphor
++{
++namespace user
++{
++
++using UserSSHLists =
++ std::pair<std::vector<std::string>, std::vector<std::string>>;
++using InternalFailure =
++ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
++using InsufficientPermission =
++ sdbusplus::xyz::openbmc_project::Common::Error::InsufficientPermission;
++
++const std::string grpSsh = "ssh";
++
++template <typename... ArgTypes>
++std::vector<std::string> executeCmd(const char *path, ArgTypes &&... tArgs)
++{
++ std::vector<std::string> stdOutput;
++ boost::process::ipstream stdOutStream;
++ boost::process::child execProg(path, const_cast<char *>(tArgs)...,
++ boost::process::std_out > stdOutStream);
++ std::string stdOutLine;
++
++ while (stdOutStream && std::getline(stdOutStream, stdOutLine) &&
++ !stdOutLine.empty())
++ {
++ stdOutput.emplace_back(stdOutLine);
++ }
++
++ execProg.wait();
++
++ int retCode = execProg.exit_code();
++ if (retCode)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Command execution failed",
++ phosphor::logging::entry("PATH=%d", path),
++ phosphor::logging::entry("RETURN_CODE:%d", retCode));
++ phosphor::logging::elog<phosphor::user::InternalFailure>();
++ }
++
++ return stdOutput;
++}
++
++/** @class UserServiceInterface
++ * @brief Interface class for methods provided by the implemmentations
++ * of the user service. Provides the same methods as the UserService
++ * class.
++ */
++class UserServiceInterface
++{
++ public:
++ UserServiceInterface() = default;
++ virtual ~UserServiceInterface() = default;
++ virtual UserSSHLists getUserAndSshGrpList() const = 0;
++ virtual std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const = 0;
++ virtual void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv,
++ const bool &enabled) const = 0;
++ virtual void renameUser(const std::string &userName,
++ const std::string &newUserName) const = 0;
++ virtual void deleteUser(const std::string &userName) const = 0;
++ virtual void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const = 0;
++ virtual void updateUserStatus(const std::string &userName,
++ const bool &enabled) const = 0;
++ virtual bool isUserEnabled(const std::string &userName) const = 0;
++ virtual std::vector<std::string>
++ getUserGroups(const std::string &userName) const = 0;
++ virtual void createGroup(const std::string &groupName) const = 0;
++};
++
++/** @class UserService
++ * @brief Responsible for managing the user service for the user manager.
++ * This service is the one responsible to actually change the user information
++ * of the application. It can support sevaral services, currently the ones
++ * supported are:
++ *
++ * 1) Shadow: Which uses the /etc/shadow file for updating the users
++ * 2) SSSD: Which uses the sssd service for a LOCAL domain only right now.
++ */
++class UserService
++{
++ public:
++ UserService() = delete;
++ UserService(const UserService &) = delete;
++ UserService &operator=(const UserService &) = delete;
++ UserService(UserService &&) = delete;
++ UserService &operator=(UserService &&) = delete;
++
++ // Service Types implemented. None is used to validate.
++ enum class ServiceType
++ {
++ none,
++ shadow,
++ sssd
++ };
++
++ UserService(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++ ~UserService();
++
++ /** @brief update the current Service type of the instance.
++ * This function is used to update in real time the service
++ * being used for the user management without restarting the
++ * whole service.
++ *
++ * @param[in] srvcType
++ * @param[in] groups
++ * @param[in] privs
++ */
++ void updateServiceType(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++
++ /** @brief get user list and SSH group members list
++ * This method gets the list of users from the service.
++ * If the userlist reference is empty, all the users will be added
++ * and DBus notified about them. If the list is not empty, the function
++ * will only update list adding the missing ones to it. It will not remove
++ * any extra users on the list that are not part of the service!
++ *
++ */
++ UserSSHLists getUserAndSshGrpList() const;
++
++ /** @brief Get users in group.
++ * This method creates a new user as requested
++ *
++ * @param[in] groupName - Name of the group which has to be queried
++ */
++ std::vector<std::string>
++ getUsersInGroup(const std::string &groupName) const;
++
++ /** @brief create user method.
++ * This method creates a new user as requested
++ *
++ * @param[in] userName - Name of the user which has to be created
++ * @param[in] groupNames - Group names list, to which user has to be added.
++ * @param[in] priv - Privilege of the user.
++ * @param[in] enabled - State of the user enabled / disabled.
++ */
++ void createUser(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv, const bool &enabled) const;
++
++ /** @brief rename user method.
++ * This method renames the user as requested
++ *
++ * @param[in] userName - current name of the user
++ * @param[in] userName - user name to which it has to be renamed.
++ */
++ void renameUser(const std::string &userName,
++ const std::string &newUserName) const;
++
++ /** @brief delete user method.
++ * This method deletes the user as requested
++ *
++ * @param[in] userName - Name of the user which has to be deleted
++ */
++ void deleteUser(const std::string &userName) const;
++
++ /** @brief Updates user Groups and Privilege.
++ *
++ * @param[in] userName - Name of the user which has to be modified
++ * @param[in] groupNames - Group names list for user.
++ * @param[in] priv - Privilege of the user.
++ */
++ void updateGroupsAndPriv(const std::string &userName,
++ const std::vector<std::string> &groupNames,
++ const std::string &priv) const;
++
++ /** @brief Updates user status
++ * If enabled = false: User will be disabled
++ * If enabled = true : User will be enabled
++ *
++ * @param[in] userName - Name of the user
++ * @param[in] enabled - Status of the user: enabled / disabled?
++ */
++ void updateUserStatus(const std::string &userName,
++ const bool &enabled) const;
++
++ /** @brief Verify if user is enabled or not
++ * If enabled returns true
++ * If not enabled returns false
++ *
++ * @param[in] userName - Name of the user
++ */
++ bool isUserEnabled(const std::string &userName) const;
++
++ /** @brief Get the list of groups a user belongs to
++ *
++ * @param[in] userName - Name of the user
++ */
++ std::vector<std::string> getUserGroups(const std::string &userName) const;
++
++ private:
++ // User service implementation.
++ void setServiceImpl(const ServiceType &srvcType,
++ const std::vector<std::string> &groups,
++ const std::vector<std::string> &privs);
++ std::unique_ptr<UserServiceInterface> usrSrvcImpl;
++};
++
++} // namespace user
++} // namespace phosphor
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch
new file mode 100644
index 000000000..2abfeb78c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch
@@ -0,0 +1,76 @@
+From a78bad158bca59dadb93c9c52d6daefa1c52b9cf Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Mon, 24 Feb 2020 13:37:12 +0530
+Subject: [PATCH] Use groupmems instead of getgrnam_r due to overlay
+
+With JFFS2 overlay, getgrnam_r during initial time returns the
+old group details as per the lower dir, instead of the overlay one
+but at the same time groupmems where returning proper values, which
+reads the file everytime. Hence replacing getgrnam_r with groupmems
+
+Tested:
+1. Verified that when added multiple user and then doing
+BMC reset using ipmitool raw 6 2 doesn't reproduce the issue of
+user with only ssh group. (on 38 version source + this fix)
+2. Updated using redfish to version 39 + this fix, and made sure
+issue doesn't happen.
+
+Note: For testing purpose added debug statements to dump ouput of
+both getgrnam_r & groupmems and able to see proper list only
+in groupmems when the issue is reproduced
+
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+---
+ user_service.cpp | 28 +++++++++++++---------------
+ 1 file changed, 13 insertions(+), 15 deletions(-)
+
+diff --git a/user_service.cpp b/user_service.cpp
+index c3c45bd..0a6b171 100644
+--- a/user_service.cpp
++++ b/user_service.cpp
+@@ -143,28 +143,26 @@ class ShadowService : public phosphor::user::UserServiceInterface
+ getUsersInGroup(const std::string &groupName) const override
+ {
+ std::vector<std::string> usersInGroup;
+- // Should be more than enough to get the pwd structure.
+- std::array<char, 4096> buffer{};
+- struct group grp;
+- struct group *grpPtr = &grp;
+- struct group *resultPtr;
+-
+- int status = getgrnam_r(groupName.c_str(), grpPtr, buffer.data(),
+- buffer.max_size(), &resultPtr);
+-
+- if (!status && (grpPtr == resultPtr))
++ std::vector<std::string> output;
++ try
+ {
+- for (; *(grp.gr_mem) != NULL; ++(grp.gr_mem))
+- {
+- usersInGroup.emplace_back(*(grp.gr_mem));
+- }
++ output = phosphor::user::executeCmd("/usr/sbin/groupmems", "-l",
++ "-g", groupName.c_str());
+ }
+- else
++ catch (const phosphor::user::InternalFailure &e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Group not found",
+ phosphor::logging::entry("GROUP=%s", groupName.c_str()));
+ // Don't throw error, just return empty usersInGroup - fallback
++ return usersInGroup;
++ }
++ if (!output.empty())
++ {
++ boost::algorithm::trim_right(output[0]);
++ boost::algorithm::split(usersInGroup, output[0],
++ boost::algorithm::is_any_of("\t "),
++ boost::token_compress_on);
+ }
+ return usersInGroup;
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
new file mode 100644
index 000000000..162f5210c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
@@ -0,0 +1,10 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRCREV = "3ab6cc280e71c1fffe53a4f3f14ea683f0e2e87e"
+
+EXTRA_OECONF += "${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'allow-root-login' ], '', '--disable-root_user_mgmt', d)}"
+
+SRC_URI += " \
+ file://0005-Added-suport-for-multiple-user-manager-services.patch \
+ file://0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb
new file mode 100644
index 000000000..333611dbb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/virtual-media/virtual-media.bb
@@ -0,0 +1,25 @@
+SUMMARY = "Virtual Media Service"
+DESCRIPTION = "Virtual Media Service"
+
+SRC_URI = "git://github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "bee56d62b209088454d166d1efae4825a2b175df"
+
+S = "${WORKDIR}/git/virtual-media/"
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.VirtualMedia.service"
+
+DEPENDS = "udev boost nlohmann-json systemd sdbusplus"
+
+# Needed for legacy mode
+RDEPENDS_${PN} = "nbdkit"
+
+inherit cmake systemd
+
+EXTRA_OECMAKE += "-DYOCTO_DEPENDENCIES=ON"
+EXTRA_OECMAKE += "-DLEGACY_MODE_ENABLED=ON"
+
+FULL_OPTIMIZATION = "-Os -pipe -flto -fno-rtti"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb
new file mode 100644
index 000000000..ebd795e83
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog.bb
@@ -0,0 +1,35 @@
+
+SUMMARY = "FRB2 timer service"
+DESCRIPTION = "The FRB2 timer service will monitor the mailbox register 0\
+and start a watchdog for FRB2 if the data is 1(BIOS will write this value)"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://frb2-watchdog.cpp \
+ "
+PV = "0.1"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+S = "${WORKDIR}"
+
+inherit cmake
+inherit pkgconfig pythonnative
+
+DEPENDS += " \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ boost \
+ "
+
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-logging \
+ phosphor-dbus-interfaces \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format
new file mode 100644
index 000000000..dd2770837
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/.clang-format
@@ -0,0 +1,98 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt
new file mode 100644
index 000000000..bd5567d31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
+project (frb2-watchdog CXX)
+set (CMAKE_CXX_STANDARD 17)
+set (CMAKE_CXX_STANDARD_REQUIRED ON)
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti")
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+# boost support
+find_package (Boost REQUIRED)
+# pkg_check_modules(Boost boost REQUIRED)
+include_directories (${Boost_INCLUDE_DIRS})
+add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY)
+add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED)
+add_definitions (-DBOOST_ALL_NO_LIB)
+add_definitions (-DBOOST_NO_RTTI)
+add_definitions (-DBOOST_NO_TYPEID)
+add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
+
+# import libsystemd
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SYSTEMD libsystemd REQUIRED)
+include_directories (${SYSTEMD_INCLUDE_DIRS})
+link_directories (${SYSTEMD_LIBRARY_DIRS})
+
+# import sdbusplus
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED)
+include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS})
+link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS})
+
+# import phosphor-logging
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (LOGGING phosphor-logging REQUIRED)
+include_directories (${LOGGING_INCLUDE_DIRS})
+link_directories (${LOGGING_LIBRARY_DIRS})
+
+# import phosphor-dbus-interfaces
+find_package (PkgConfig REQUIRED)
+pkg_check_modules (DBUSINTERFACE phosphor-dbus-interfaces REQUIRED)
+include_directories (${DBUSINTERFACE_INCLUDE_DIRS})
+link_directories (${DBUSINTERFACE_LIBRARY_DIRS})
+
+add_executable (frb2-watchdog frb2-watchdog.cpp)
+
+target_link_libraries (${PROJECT_NAME} systemd)
+target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${SDBUSPLUSPLUS_LIBRARIES})
+target_link_libraries (${PROJECT_NAME} ${DBUSINTERFACE_LIBRARIES}
+ phosphor_logging)
+install (TARGETS frb2-watchdog DESTINATION bin)
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json
new file mode 100644
index 000000000..583c255a3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/cmake-format.json
@@ -0,0 +1,12 @@
+{
+ "enum_char": ".",
+ "line_ending": "unix",
+ "bullet_char": "*",
+ "max_subargs_per_line": 99,
+ "command_case": "lower",
+ "tab_size": 4,
+ "line_width": 80,
+ "separate_fn_name_with_space": true,
+ "dangle_parens": true,
+ "separate_ctrl_name_with_space": true
+} \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp
new file mode 100644
index 000000000..5356e95db
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/frb2-watchdog/frb2-watchdog.cpp
@@ -0,0 +1,258 @@
+/* Copyright 2018 Intel
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <boost/container/flat_set.hpp>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <optional>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/timer.hpp>
+#include <vector>
+#include <xyz/openbmc_project/State/Watchdog/server.hpp>
+
+void handleResponse(const boost::system::error_code &err,
+ std::size_t bytes_transferred);
+
+static int mailboxDevFd = -1;
+
+static boost::asio::io_service io;
+static auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+boost::asio::ip::tcp::socket mailBoxDevSocket(io);
+boost::asio::deadline_timer pollTimer(io);
+boost::asio::posix::stream_descriptor inputDevice(io);
+
+// mailbox registre data[0:0] for FRB2 enable bit
+boost::asio::streambuf readBuf(1);
+std::string dataRead;
+
+// FRB2 watchdog timeout is 6 minutes
+static constexpr unsigned int frb2TimerIntervalMs = 360 * 1000;
+
+// mailbox device polling time interval is 2 seconds
+static constexpr unsigned int pollMs = 2000;
+
+static constexpr unsigned int frb2Started = 1;
+static constexpr unsigned int frb2Stopped = 0;
+
+// FRB2 status
+static uint8_t frb2Status = frb2Stopped;
+
+static constexpr const char *mailboxDevName = "/dev/aspeed-mbox";
+
+static constexpr const char frb2Bus[] = "xyz.openbmc_project.FRB2";
+static constexpr const char frb2Obj[] = "/xyz/openbmc_project/FRB2";
+static constexpr const char frb2Intf[] = "xyz.openbmc_project.FRB2";
+
+static constexpr char powerBus[] = "xyz.openbmc_project.Chassis.Control.Power";
+static constexpr char powerPath[] =
+ "/xyz/openbmc_project/Chassis/Control/Power0";
+static constexpr char powerIntf[] = "xyz.openbmc_project.Chassis.Control.Power";
+
+static constexpr char wdBus[] = "xyz.openbmc_project.Watchdog";
+static constexpr char wdPath[] = "/xyz/openbmc_project/watchdog/host0";
+static constexpr char wdIntf[] = "xyz.openbmc_project.State.Watchdog";
+static constexpr char propIntf[] = "org.freedesktop.DBus.Properties";
+
+typedef boost::asio::buffers_iterator<boost::asio::const_buffers_1> iterator;
+
+// check if FRB2 bit is 0x1
+std::pair<iterator, bool> matchFRB2(iterator begin, iterator end)
+{
+ unsigned char ch = 0;
+ iterator i = begin;
+
+ while (i != end)
+ {
+ ch = static_cast<unsigned char>(*i);
+ if (ch & 0x1)
+ {
+ return std::make_pair(i, true);
+ }
+ i++;
+ }
+
+ return std::make_pair(i, false);
+}
+
+static void startRead()
+{
+ boost::asio::async_read_until(inputDevice, readBuf, matchFRB2,
+ [&](const boost::system::error_code &ec,
+ std::size_t bytes_transferred) {
+ handleResponse(ec, bytes_transferred);
+ });
+}
+
+template <typename T> void setProperty(const std::string &key, const T &val)
+{
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "setProperty", phosphor::logging::entry("KEY=%s", key.c_str()));
+
+ try
+ {
+ conn->async_method_call(
+ [](const boost::system::error_code &err) {
+ if (err)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "async_method_call error!",
+ phosphor::logging::entry(
+ "ERROR=%s",
+ boost::system::system_error(err).what()));
+ }
+ },
+ wdBus, wdPath, propIntf, "Set", wdIntf, key,
+ sdbusplus::message::variant_ns::variant<T>(val));
+ }
+ catch (sdbusplus::exception::SdBusError &e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Dbus error!", phosphor::logging::entry("ERROR=%s", e.what()));
+ }
+}
+void handleResponse(const boost::system::error_code &err,
+ std::size_t bytes_transferred)
+{
+ std::istream responseStream(&readBuf);
+ std::string response;
+ int n = 0;
+ uint64_t interval = frb2TimerIntervalMs;
+
+ std::getline(responseStream, response);
+ responseStream.clear();
+
+ if (err == boost::system::errc::bad_file_descriptor)
+ {
+
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "bad file descriptor");
+ return; // we're being destroyed
+ }
+
+ if (!err)
+ {
+ // FRB2 is set by BIOS
+ if (frb2Stopped == frb2Status)
+ {
+ // start FRB2 watchdog
+ frb2Status = frb2Started;
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "FRB2 enable, start FRB2 watchdog");
+ setProperty(
+ "ExpireAction",
+ std::string(
+ "xyz.openbmc_project.State.Watchdog.Action.HardReset"));
+ setProperty("Interval", interval);
+ setProperty("TimeRemaining", interval);
+ setProperty("Initialized", true);
+ setProperty("Enabled", true);
+ }
+ }
+ else if (err == boost::asio::error::misc_errors::not_found)
+ {
+ // FRB2 is clear, stop FRB2 watchdog if it is started
+ if (frb2Started == frb2Status)
+ {
+ frb2Status = frb2Stopped;
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "FRB2 is unset, stop FRB2 watchdog");
+ setProperty("Enabled", false);
+ }
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "handleResponse error!",
+ phosphor::logging::entry("ERROR=%s",
+ boost::system::system_error(err).what()));
+ }
+
+ pollTimer.expires_from_now(boost::posix_time::milliseconds(pollMs));
+ pollTimer.async_wait(
+ [](const boost::system::error_code &ec) { startRead(); });
+}
+
+int main(int argc, char **argv)
+{
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "Monitor FRB2 signal");
+
+ sdbusplus::bus::match_t biosPostSignal(
+ static_cast<sdbusplus::bus::bus &>(*conn),
+ sdbusplus::bus::match::rules::type::signal() +
+ sdbusplus::bus::match::rules::member("PostCompleted") +
+ sdbusplus::bus::match::rules::path(powerPath) +
+ sdbusplus::bus::match::rules::interface(powerIntf),
+ [](sdbusplus::message::message &msg) {
+ uint8_t value = 0;
+ ssize_t rc = 0;
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "BIOS post completed signal");
+ // stop FRB2 and clean mailbox
+ value = 0;
+ rc = ::pwrite(mailboxDevFd, &value, 1, 0);
+ if (rc != 1)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "mailbox write error!");
+ }
+ setProperty("Enabled", false);
+ frb2Status = frb2Stopped;
+ return;
+ });
+
+ conn->request_name(frb2Bus);
+
+ auto server = sdbusplus::asio::object_server(conn);
+
+ std::shared_ptr<sdbusplus::asio::dbus_interface> frb2Iface =
+ server.add_interface(frb2Obj, frb2Intf);
+
+ frb2Iface->register_property("frb2Status", frb2Status);
+
+ frb2Iface->initialize();
+
+ mailboxDevFd = ::open(mailboxDevName, O_RDWR | O_CLOEXEC);
+ if (mailboxDevFd < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "mailbox device open fail!");
+ return -1;
+ }
+
+ inputDevice.assign(mailboxDevFd);
+
+ startRead();
+
+ io.run();
+
+ ::close(mailboxDevFd);
+
+ return 0;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
new file mode 100644
index 000000000..360ba35f0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
@@ -0,0 +1,336 @@
+From 82f31d1e6096acd4f223f0b0fe0d814c27450022 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Mon, 17 Jun 2019 12:00:58 -0700
+Subject: [PATCH] Customize phosphor-watchdog for Intel platforms
+
+This patch adds various changes to phosphor-watchdog that are
+required for compatibility with Intel platforms.
+
+ 1. Add Redfish messages for watchdog timeout and pre-interrupt
+ 2. Use dbus properties for power control insted of service files
+ 3. Use host status to enable/disable watchdog
+ 4. Set preTimeoutInterruptOccurFlag
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ watchdog.cpp | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ watchdog.hpp | 23 ++++++-
+ 2 files changed, 226 insertions(+), 10 deletions(-)
+
+diff --git a/watchdog.cpp b/watchdog.cpp
+index 9090760..079d88e 100644
+--- a/watchdog.cpp
++++ b/watchdog.cpp
+@@ -1,11 +1,14 @@
+ #include "watchdog.hpp"
+
++#include <systemd/sd-journal.h>
++
+ #include <algorithm>
+ #include <chrono>
+ #include <phosphor-logging/elog.hpp>
+ #include <phosphor-logging/log.hpp>
+ #include <sdbusplus/exception.hpp>
+ #include <xyz/openbmc_project/Common/error.hpp>
++#include <xyz/openbmc_project/State/Host/server.hpp>
+
+ namespace phosphor
+ {
+@@ -18,10 +21,77 @@ using namespace phosphor::logging;
+ using sdbusplus::exception::SdBusError;
+ using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+-// systemd service to kick start a target.
+-constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
+-constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
+-constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
++const static constexpr char* currentHostState = "CurrentHostState";
++const static constexpr char* hostStatusOff =
++ "xyz.openbmc_project.State.Host.HostState.Off";
++
++const static constexpr char* actionDescription = " due to Watchdog timeout";
++const static constexpr char* hardResetDescription = "Hard Reset - System reset";
++const static constexpr char* powerOffDescription =
++ "Power Down - System power down";
++const static constexpr char* powerCycleDescription =
++ "Power Cycle - System power cycle";
++const static constexpr char* timerExpiredDescription = "Timer expired";
++
++const static constexpr char* preInterruptActionNone =
++ "xyz.openbmc_project.State.Watchdog.PreTimeoutInterruptAction.None";
++
++const static constexpr char* preInterruptDescriptionSMI = "SMI";
++const static constexpr char* preInterruptDescriptionNMI = "NMI";
++const static constexpr char* preInterruptDescriptionMI = "Messaging Interrupt";
++
++const static constexpr char* reservedDescription = "Reserved";
++
++const static constexpr char* timerUseDescriptionBIOSFRB2 = "BIOS FRB2";
++const static constexpr char* timerUseDescriptionBIOSPOST = "BIOS/POST";
++const static constexpr char* timerUseDescriptionOSLoad = "OSLoad";
++const static constexpr char* timerUseDescriptionSMSOS = "SMS/OS";
++const static constexpr char* timerUseDescriptionOEM = "OEM";
++
++namespace restart
++{
++static constexpr const char* busName =
++ "xyz.openbmc_project.Control.Host.RestartCause";
++static constexpr const char* path =
++ "/xyz/openbmc_project/control/host0/restart_cause";
++static constexpr const char* interface =
++ "xyz.openbmc_project.Control.Host.RestartCause";
++static constexpr const char* property = "RequestedRestartCause";
++} // namespace restart
++
++// chassis state manager service
++namespace chassis
++{
++static constexpr const char* busName = "xyz.openbmc_project.State.Chassis";
++static constexpr const char* path = "/xyz/openbmc_project/state/chassis0";
++static constexpr const char* interface = "xyz.openbmc_project.State.Chassis";
++static constexpr const char* request = "RequestedPowerTransition";
++} // namespace chassis
++
++namespace host
++{
++static constexpr const char* busName = "xyz.openbmc_project.State.Host";
++static constexpr const char* path = "/xyz/openbmc_project/state/host0";
++static constexpr const char* interface = "xyz.openbmc_project.State.Host";
++static constexpr const char* request = "RequestedHostTransition";
++} // namespace host
++
++void Watchdog::powerStateChangedHandler(
++ const std::map<std::string, std::variant<std::string>>& props)
++{
++ const auto iter = props.find(currentHostState);
++ if (iter != props.end())
++ {
++ const std::string* powerState = std::get_if<std::string>(&iter->second);
++ if (powerState && (*powerState == hostStatusOff))
++ {
++ if (timerEnabled())
++ {
++ enabled(false);
++ }
++ }
++ }
++}
+
+ void Watchdog::resetTimeRemaining(bool enableWatchdog)
+ {
+@@ -102,13 +172,102 @@ uint64_t Watchdog::interval(uint64_t value)
+ // Optional callback function on timer expiration
+ void Watchdog::timeOutHandler()
+ {
++ PreTimeoutInterruptAction preTimeoutInterruptAction = preTimeoutInterrupt();
++ std::string preInterruptActionMessageArgs{};
++
+ Action action = expireAction();
++ std::string actionMessageArgs{};
++
++ expiredTimerUse(currentTimerUse());
++
++ TimerUse timeUser = expiredTimerUse();
++ std::string timeUserMessage{};
++
+ if (!this->enabled())
+ {
+ action = fallback->action;
+ }
+
+- expiredTimerUse(currentTimerUse());
++ switch (timeUser)
++ {
++ case Watchdog::TimerUse::BIOSFRB2:
++ timeUserMessage = timerUseDescriptionBIOSFRB2;
++ break;
++ case Watchdog::TimerUse::BIOSPOST:
++ timeUserMessage = timerUseDescriptionBIOSPOST;
++ break;
++ case Watchdog::TimerUse::OSLoad:
++ timeUserMessage = timerUseDescriptionOSLoad;
++ break;
++ case Watchdog::TimerUse::SMSOS:
++ timeUserMessage = timerUseDescriptionSMSOS;
++ break;
++ case Watchdog::TimerUse::OEM:
++ timeUserMessage = timerUseDescriptionOEM;
++ break;
++ default:
++ timeUserMessage = reservedDescription;
++ break;
++ }
++
++ switch (action)
++ {
++ case Watchdog::Action::HardReset:
++ actionMessageArgs = std::string(hardResetDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::PowerOff:
++ actionMessageArgs = std::string(powerOffDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::PowerCycle:
++ actionMessageArgs = std::string(powerCycleDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::None:
++ actionMessageArgs = timerExpiredDescription;
++ break;
++ default:
++ actionMessageArgs = reservedDescription;
++ break;
++ }
++
++ // Log into redfish event log
++ sd_journal_send("MESSAGE=IPMIWatchdog: Timed out ACTION=%s",
++ convertForMessage(action).c_str(), "PRIORITY=%i", LOG_INFO,
++ "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.IPMIWatchdog",
++ "REDFISH_MESSAGE_ARGS=%s. timer use: %s",
++ actionMessageArgs.c_str(), timeUserMessage.c_str(), NULL);
++
++ switch (preTimeoutInterruptAction)
++ {
++ case Watchdog::PreTimeoutInterruptAction::SMI:
++ preInterruptActionMessageArgs = preInterruptDescriptionSMI;
++ break;
++ case Watchdog::PreTimeoutInterruptAction::NMI:
++ preInterruptActionMessageArgs = preInterruptDescriptionNMI;
++ break;
++ case Watchdog::PreTimeoutInterruptAction::MI:
++ preInterruptActionMessageArgs = preInterruptDescriptionMI;
++ break;
++ default:
++ preInterruptActionMessageArgs = reservedDescription;
++ break;
++ }
++
++ if (preInterruptActionNone != convertForMessage(preTimeoutInterruptAction))
++ {
++ preTimeoutInterruptOccurFlag(true);
++
++ sd_journal_send("MESSAGE=IPMIWatchdog: Pre Timed out Interrupt=%s",
++ convertForMessage(preTimeoutInterruptAction).c_str(),
++ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
++ "OpenBMC.0.1.IPMIWatchdog",
++ "REDFISH_MESSAGE_ARGS=Timer interrupt - %s due to "
++ "Watchdog timeout. timer use: %s",
++ preInterruptActionMessageArgs.c_str(),
++ timeUserMessage.c_str(), NULL);
++ }
+
+ auto target = actionTargetMap.find(action);
+ if (target == actionTargetMap.end())
+@@ -128,10 +287,23 @@ void Watchdog::timeOutHandler()
+
+ try
+ {
+- auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
+- SYSTEMD_INTERFACE, "StartUnit");
+- method.append(target->second);
+- method.append("replace");
++ sdbusplus::message::message method;
++ if (action == Watchdog::Action::HardReset)
++ {
++ method = bus.new_method_call(host::busName, host::path,
++ "org.freedesktop.DBus.Properties",
++ "Set");
++ method.append(host::interface, host::request,
++ std::variant<std::string>(target->second));
++ }
++ else
++ {
++ method = bus.new_method_call(chassis::busName, chassis::path,
++ "org.freedesktop.DBus.Properties",
++ "Set");
++ method.append(chassis::interface, chassis::request,
++ std::variant<std::string>(target->second));
++ }
+
+ bus.call_noreply(method);
+ }
+@@ -142,6 +314,29 @@ void Watchdog::timeOutHandler()
+ entry("ERROR=%s", e.what()));
+ commit<InternalFailure>();
+ }
++
++ // set restart cause for watchdog HardReset & PowerCycle actions
++ if ((action == Watchdog::Action::HardReset) ||
++ (action == Watchdog::Action::PowerCycle))
++ {
++ try
++ {
++ auto method = bus.new_method_call(
++ restart::busName, restart::path,
++ "org.freedesktop.DBus.Properties", "Set");
++ method.append(
++ restart::interface, restart::property,
++ std::variant<std::string>("xyz.openbmc_project.State.Host."
++ "RestartCause.WatchdogTimer"));
++ bus.call(method);
++ }
++ catch (sdbusplus::exception_t& e)
++ {
++ log<level::ERR>("Failed to set HostRestartCause property",
++ entry("ERROR=%s", e.what()));
++ commit<InternalFailure>();
++ }
++ }
+ }
+
+ tryFallbackOrDisable();
+diff --git a/watchdog.hpp b/watchdog.hpp
+index 7de9bb3..b004b7a 100644
+--- a/watchdog.hpp
++++ b/watchdog.hpp
+@@ -68,7 +68,18 @@ class Watchdog : public WatchdogInherits
+ WatchdogInherits(bus, objPath),
+ bus(bus), actionTargetMap(std::move(actionTargetMap)),
+ fallback(std::move(fallback)), minInterval(minInterval),
+- timer(event, std::bind(&Watchdog::timeOutHandler, this))
++ timer(event, std::bind(&Watchdog::timeOutHandler, this)),
++ powerStateChangedSignal(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(
++ "/xyz/openbmc_project/state/host0",
++ "xyz.openbmc_project.State.Host"),
++ [this](sdbusplus::message::message& msg) {
++ std::string objectName;
++ std::map<std::string, std::variant<std::string>> props;
++ msg.read(objectName, props);
++ powerStateChangedHandler(props);
++ })
+ {
+ // We set the watchdog interval with the default value.
+ interval(interval());
+@@ -77,6 +88,12 @@ class Watchdog : public WatchdogInherits
+ tryFallbackOrDisable();
+ }
+
++ /** @brief Disable watchdog when power status change meet
++ * the specific requirement
++ */
++ void powerStateChangedHandler(
++ const std::map<std::string, std::variant<std::string>>& props);
++
+ /** @brief Resets the TimeRemaining to the configured Interval
+ * Optionally enables the watchdog.
+ *
+@@ -165,6 +182,10 @@ class Watchdog : public WatchdogInherits
+ /** @brief Contained timer object */
+ sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
+
++ /** @brief Optional Callback handler when power status change meet
++ * the specific requirement */
++ sdbusplus::bus::match_t powerStateChangedSignal;
++
+ /** @brief Optional Callback handler on timer expirartion */
+ void timeOutHandler();
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog.service
new file mode 100644
index 000000000..007e39d8a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Phosphor Watchdog
+
+[Service]
+ExecStart=/usr/bin/env phosphor-watchdog --continue --service=xyz.openbmc_project.Watchdog \
+ --path=/xyz/openbmc_project/watchdog/host0 \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.HardReset=xyz.openbmc_project.State.Host.Transition.ForceWarmReboot \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.PowerOff=xyz.openbmc_project.State.Chassis.Transition.Off \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.PowerCycle=xyz.openbmc_project.State.Chassis.Transition.PowerCycle
+
+SyslogIdentifier=phosphor-watchdog
+BusName =xyz.openbmc_project.Watchdog
+Type=dbus
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend
new file mode 100644
index 000000000..f0b8e8f23
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRCREV = "c35135d32f9cb84b62de7b72eee3a2e87b4b3d4d"
+SRC_URI += "file://0001-Customize-phosphor-watchdog-for-Intel-platforms.patch \
+ "
+
+# Remove the override to keep service running after DC cycle
+SYSTEMD_OVERRIDE_${PN}_remove = "poweron.conf:phosphor-watchdog@poweron.service.d/poweron.conf"
+SYSTEMD_SERVICE_${PN} = "phosphor-watchdog.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb
new file mode 100644
index 000000000..fc6e1034a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb
@@ -0,0 +1,24 @@
+SUMMARY = "System watchdog"
+DESCRIPTION = "BMC hardware watchdog service that is used to reset BMC \
+ when unrecoverable events occurs"
+
+inherit allarch
+inherit obmc-phosphor-systemd
+
+RDEPENDS_${PN} = "bash"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SYSTEMD_SERVICE_${PN} += "system-watchdog.service"
+SYSTEMD_ENVIRONMENT_FILE_${PN} += "obmc/system-watchdog/system-watchdog.conf"
+
+SYSTEMD_SERVICE_${PN} += "watchdog-reset@.service"
+SYSTEMD_SERVICE_${PN} += "watchdog-clear-failures.service"
+SYSTEMD_SERVICE_${PN} += "watchdog-clear-failures.timer"
+SRC_URI += "file://watchdog-reset.sh"
+
+do_install_append(){
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/watchdog-reset.sh ${D}${bindir}
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf
new file mode 100644
index 000000000..defe830a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/obmc/system-watchdog/system-watchdog.conf
@@ -0,0 +1,3 @@
+TIMEOUT=60
+INTERVAL=10
+DEVICE=/dev/watchdog1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service
new file mode 100644
index 000000000..1564fda20
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/system-watchdog.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=BMC Hardware Watchdog Daemon
+
+[Service]
+EnvironmentFile=/etc/default/obmc/system-watchdog/system-watchdog.conf
+ExecStart=/sbin/watchdog -T ${{TIMEOUT}} -t ${{INTERVAL}} -F ${{DEVICE}}
+KillSignal=SIGKILL
+
+[Install]
+WantedBy=basic.target
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.service
new file mode 100644
index 000000000..801f4ed27
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Reset BMC Hardware Watchdog Failure Count
+
+[Service]
+ExecStart=busctl call xyz.openbmc_project.U_Boot.Environment.Manager \
+ /xyz/openbmc_project/u_boot/environment/mgr \
+ xyz.openbmc_project.U_Boot.Environment.Manager \
+ Write ss bootfailures 0
+Type=oneshot
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.timer b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.timer
new file mode 100644
index 000000000..1abac4326
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-clear-failures.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=Starts the clear watchdog serivce after 30 minutes
+
+[Timer]
+OnBootSec=30min
+
+[Install]
+WantedBy=timers.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset.sh b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset.sh
new file mode 100644
index 000000000..3413fdb9f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+echo "Watchdog being started by $1" > /dev/kmsg
+
+if /sbin/fw_printenv bootfailures -n | grep -q 3; then
+ exit 0 # passed boot limit, user started again on purpose
+fi
+
+if test -f "/tmp/nowatchdog"; then
+ echo "Not resetting due to nowatchdog file" > /dev/kmsg
+ exit 0
+fi
+
+echo "Log as follows:" > /dev/kmsg
+journalctl -r -n 100 | while read line; do echo $line > /dev/kmsg; done
+
+systemctl stop system-watchdog.service
+/sbin/watchdog -T 0 -F /dev/watchdog1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset@.service
new file mode 100644
index 000000000..6b1ebc544
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog/watchdog-reset@.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Reset BMC Using Hardware Watchdog
+
+[Service]
+ExecStart=/usr/bin/watchdog-reset.sh %i
+Type=oneshot
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json
new file mode 100644
index 000000000..348a7792d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json
@@ -0,0 +1,9 @@
+{
+ "customKeyEnable": true,
+ "keyType" : "VT100+",
+ "customConsoleDisplaySize": {
+ "width": 100,
+ "height": 32
+ },
+ "VirtualMediaEnabled" : true
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
new file mode 100644
index 000000000..be02d5fd9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
@@ -0,0 +1,4 @@
+SRC_URI = "git://github.com/Intel-BMC/phosphor-webui;protocol=ssh;branch=intel2"
+FILESEXTRAPATHS_prepend_intel := "${THISDIR}/${PN}:"
+
+SRCREV = "34a4a702870e33a5612d2c4a84385eae2edbf477"
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/files/ldb.sh b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/ldb.sh
new file mode 100644
index 000000000..176bfd7ca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/ldb.sh
@@ -0,0 +1 @@
+export LDB_MODULES_PATH=/usr/lib/ldb
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/files/locked_groups b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/locked_groups
new file mode 100644
index 000000000..7c189e231
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/locked_groups
@@ -0,0 +1 @@
+sssd_locked
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/files/nscd.conf b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/nscd.conf
new file mode 100644
index 000000000..d2ffe5ddc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/nscd.conf
@@ -0,0 +1,2 @@
+enable-cache passwd no
+enable-cache group no \ No newline at end of file
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.conf b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.conf
new file mode 100644
index 000000000..7a2786bee
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.conf
@@ -0,0 +1,16 @@
+[sssd]
+domains = LOCAL
+services = nss, pam
+config_file_version = 2
+
+[nss]
+enum_cache_timeout = 1
+filter_groups = root
+filter_users = root
+
+[pam]
+
+[domain/LOCAL]
+enumerate = true
+id_provider = local
+auth_provider = local
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.service b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.service
new file mode 100644
index 000000000..fe2bcf8b4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/files/sssd.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=System Security Services Daemon
+# SSSD must be running before we permit user sessions
+Before=systemd-user-sessions.service nss-user-lookup.target
+Wants=nss-user-lookup.target
+
+[Service]
+Environment=LDB_MODULES_PATH=/usr/lib/ldb DEBUG_LOGGER=-f
+ExecStart=/usr/sbin/sssd $DEBUG_LOGGER
+Type=simple
+Restart=always
+PIDFile=/var/run/sssd.pid
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-security/sssd/sssd_%.bbappend b/meta-openbmc-mods/meta-common/recipes-security/sssd/sssd_%.bbappend
new file mode 100644
index 000000000..03965ce72
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-security/sssd/sssd_%.bbappend
@@ -0,0 +1,26 @@
+inherit obmc-phosphor-systemd
+
+FILESEXTRAPATHS_append := "${THISDIR}/files:"
+SRC_URI += "file://sssd.conf \
+ file://nscd.conf \
+ file://locked_groups \
+ file://ldb.sh \
+ "
+
+PACKAGECONFIG += " systemd "
+SYSTEMD_AUTO_ENABLE = "enable"
+
+EXTRA_OECONF += " --enable-pammoddir=${base_libdir}/security"
+
+do_install_append() {
+ # sssd creates also the /var/run link. Need to remove it to avoid conflicts
+ # with the one created by base-files recipe.
+ rm -rf ${D}/var/run
+ install -m 600 ${WORKDIR}/locked_groups ${D}/${sysconfdir}/${BPN}
+ install -m 600 ${WORKDIR}/nscd.conf ${D}/${sysconfdir}
+ install -d ${D}${sysconfdir}/profile.d
+ install -m 0644 ${WORKDIR}/ldb.sh ${D}${sysconfdir}/profile.d
+}
+
+FILES_${PN} += " /lib/security/pam_sss.so "
+
diff --git a/meta-openbmc-mods/meta-common/recipes-support/boost/boost/0001-Fix-Issue-62.patch b/meta-openbmc-mods/meta-common/recipes-support/boost/boost/0001-Fix-Issue-62.patch
new file mode 100644
index 000000000..80dfc2725
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/boost/boost/0001-Fix-Issue-62.patch
@@ -0,0 +1,28 @@
+From 318439af2e77731ae2c3df5e198c1d3e8392d556 Mon Sep 17 00:00:00 2001
+From: Simon Ebner <Simon.Ebner@advertima.com>
+Date: Fri, 22 Mar 2019 15:27:35 +0100
+Subject: [PATCH 1/2] Fix Issue 62
+
+Fixes a leaking pipe. See https://github.com/boostorg/process/issues/62
+---
+ boost/process/detail/posix/executor.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/boost/process/detail/posix/executor.hpp b/boost/process/detail/posix/executor.hpp
+index 1390a58..8b86ed1 100644
+--- a/boost/process/detail/posix/executor.hpp
++++ b/boost/process/detail/posix/executor.hpp
+@@ -282,7 +282,10 @@ class executor
+ set_error(std::error_code(err, std::system_category()), "Error read pipe");
+ }
+ if (count == 0)
++ {
++ ::close(source);
+ return ;
++ }
+
+ std::error_code ec(data[0], std::system_category());
+ std::string msg(data[1], ' ');
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-support/boost/boost_%.bbappend b/meta-openbmc-mods/meta-common/recipes-support/boost/boost_%.bbappend
new file mode 100644
index 000000000..f85e30b1f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/boost/boost_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Fix-Issue-62.patch"
diff --git a/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/default b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/default
new file mode 100644
index 000000000..b9f8e0363
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/default
@@ -0,0 +1 @@
+EXTRA_ARGS="-r /dev/hwrng"
diff --git a/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/init b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/init
new file mode 100644
index 000000000..13f0ecd37
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/init
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# This is an init script for openembedded
+# Copy it to @SYSCONFDIR@/init.d/rng-tools and type
+# > update-rc.d rng-tools defaults 60
+#
+
+rngd=@SBINDIR@/rngd
+test -x "$rngd" || exit 1
+
+[ -r @SYSCONFDIR@/default/rng-tools ] && . "@SYSCONFDIR@/default/rng-tools"
+
+case "$1" in
+ start)
+ echo -n "Starting random number generator daemon"
+ start-stop-daemon -S -q -x $rngd -- $EXTRA_ARGS
+ echo "."
+ ;;
+ stop)
+ echo -n "Stopping random number generator daemon"
+ start-stop-daemon -K -q -n rngd
+ echo "."
+ ;;
+ reload|force-reload)
+ echo -n "Signalling rng daemon restart"
+ start-stop-daemon -K -q -s 1 -x $rngd
+ start-stop-daemon -K -q -s 1 -x $rngd
+ ;;
+ restart)
+ echo -n "Stopping random number generator daemon"
+ start-stop-daemon -K -q -n rngd
+ echo "."
+ echo -n "Starting random number generator daemon"
+ start-stop-daemon -S -q -x $rngd -- $EXTRA_ARGS
+ echo "."
+ ;;
+ *)
+ echo "Usage: @SYSCONFDIR@/init.d/rng-tools {start|stop|reload|restart|force-reload}"
+ exit 1
+esac
+
+exit 0
diff --git a/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/rngd.service b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/rngd.service
new file mode 100644
index 000000000..d76e9a0c4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools/rngd.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Hardware RNG Entropy Gatherer Daemon
+
+[Service]
+EnvironmentFile=-@SYSCONFDIR@/default/rng-tools
+ExecStart=@SBINDIR@/rngd -f $EXTRA_ARGS
+Nice=15
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools_6.7.bb b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools_6.7.bb
new file mode 100644
index 000000000..b4e453f67
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/rng-tools/rng-tools_6.7.bb
@@ -0,0 +1,52 @@
+SUMMARY = "Random number generator daemon"
+DESCRIPTION = "Check and feed random data from hardware device to kernel"
+AUTHOR = "Philipp Rumpf, Jeff Garzik <jgarzik@pobox.com>, \
+ Henrique de Moraes Holschuh <hmh@debian.org>"
+HOMEPAGE = "https://github.com/nhorman/rng-tools"
+BUGTRACKER = "https://github.com/nhorman/rng-tools/issues"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+DEPENDS = "sysfsutils"
+
+SRC_URI = "\
+ git://github.com/nhorman/rng-tools.git \
+ file://init \
+ file://default \
+ file://rngd.service \
+"
+SRCREV = "9fc873c5af0e392632e6b736938b811f7ca97251"
+
+S = "${WORKDIR}/git"
+
+inherit autotools update-rc.d systemd pkgconfig
+
+PACKAGECONFIG ??= "libgcrypt libjitterentropy"
+PACKAGECONFIG_libc-musl = "libargp libjitterentropy"
+
+PACKAGECONFIG[libargp] = "--with-libargp,--without-libargp,argp-standalone,"
+PACKAGECONFIG[libgcrypt] = "--with-libgcrypt,--without-libgcrypt,libgcrypt,"
+PACKAGECONFIG[libjitterentropy] = "--enable-jitterentropy,--disable-jitterentropy,libjitterentropy"
+PACKAGECONFIG[libp11] = "--with-pkcs11,--without-pkcs11,libp11 openssl"
+PACKAGECONFIG[nistbeacon] = "--with-nistbeacon,--without-nistbeacon,curl libxml2 openssl"
+
+INITSCRIPT_NAME = "rng-tools"
+INITSCRIPT_PARAMS = "start 03 2 3 4 5 . stop 30 0 6 1 ."
+
+SYSTEMD_SERVICE_${PN} = "rngd.service"
+
+# Refer autogen.sh in rng-tools
+do_configure_prepend() {
+ cp ${S}/README.md ${S}/README
+}
+
+do_install_append() {
+ install -Dm 0644 ${WORKDIR}/default ${D}${sysconfdir}/default/rng-tools
+ install -Dm 0755 ${WORKDIR}/init ${D}${sysconfdir}/init.d/rng-tools
+ install -Dm 0644 ${WORKDIR}/rngd.service \
+ ${D}${systemd_system_unitdir}/rngd.service
+ sed -i \
+ -e 's,@SYSCONFDIR@,${sysconfdir},g' \
+ -e 's,@SBINDIR@,${sbindir},g' \
+ ${D}${sysconfdir}/init.d/rng-tools \
+ ${D}${systemd_system_unitdir}/rngd.service
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/beeper-test.bb b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/beeper-test.bb
new file mode 100644
index 000000000..51cda82e9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/beeper-test.bb
@@ -0,0 +1,17 @@
+SUMMARY = "Beeper Test App"
+DESCRIPTION = "Beeper Test Application for pwm-beeper"
+
+inherit cmake
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM += "\
+ file://beeper-test.cpp;beginline=2;endline=14;md5=c451359f18a13ee69602afce1588c01a \
+ "
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://beeper-test.cpp \
+ "
+
+S = "${WORKDIR}"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/.clang-format b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/.clang-format
new file mode 100644
index 000000000..ea71ad6e1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/.clang-format
@@ -0,0 +1,99 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: false
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: true
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: AfterColon
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+PointerAlignment: Left
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^[<"](gtest|gmock)'
+ Priority: 5
+ - Regex: '^"config.h"'
+ Priority: -1
+ - Regex: '^".*\.hpp"'
+ Priority: 1
+ - Regex: '^<.*\.h>'
+ Priority: 2
+ - Regex: '^<.*'
+ Priority: 3
+ - Regex: '.*'
+ Priority: 4
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/CMakeLists.txt
new file mode 100644
index 000000000..81a0c7e81
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
+project(beeper-test CXX)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+add_executable(beeper-test beeper-test.cpp)
+install(TARGETS beeper-test DESTINATION bin)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/beeper-test.cpp b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/beeper-test.cpp
new file mode 100644
index 000000000..31dafdd88
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/beeper-test/files/beeper-test.cpp
@@ -0,0 +1,81 @@
+/*
+// Copyright (c) 2019 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Abstract: pwm-beeper test application
+//
+*/
+
+#include <fcntl.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <iostream>
+
+int main(int argc, char** argv)
+{
+ if (argc < 3)
+ {
+ std::cout << "usage: <input device> <sequence of 'tone in "
+ "Hz','duration in ms' pair>\n";
+ std::cout << "example: beeper-test /dev/input/event0 "
+ "2100,100,0,150,2500,50,0,50,2200,100\n";
+ return 1;
+ }
+
+ int fd;
+ if ((fd = open(argv[1], O_RDWR | O_CLOEXEC)) < 0)
+ {
+ perror("Failed to open input device");
+ return -1;
+ }
+
+ struct input_event event;
+ event.type = EV_SND;
+ event.code = SND_TONE;
+
+ char* pch = strtok(argv[2], ",");
+ while (pch != NULL)
+ {
+ event.value = atoi(pch);
+
+ pch = strtok(NULL, ",");
+ if (!pch)
+ {
+ std::cerr << "Invalid tone,duration pair\n";
+ close(fd);
+ return -1;
+ }
+
+ int durationMs = atoi(pch);
+
+ if (write(fd, &event, sizeof(struct input_event)) !=
+ sizeof(struct input_event))
+ {
+ perror("Failed to write a tone sound event");
+ close(fd);
+ return -1;
+ }
+
+ usleep(durationMs * 1000);
+
+ pch = strtok(NULL, ",");
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/dimmsensor.bb b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/dimmsensor.bb
new file mode 100644
index 000000000..78240c0f4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/dimmsensor.bb
@@ -0,0 +1,17 @@
+SUMMARY = "Dimm Sensor"
+DESCRIPTION = "Dimm Sensor Executable"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://DimmSensor.cpp \
+ "
+
+LICENSE = "CLOSED"
+
+S = "${WORKDIR}"
+
+inherit cmake
+
+# linux-libc-headers guides this way to include custom uapi headers
+CXXFLAGS_append = " -I ${STAGING_KERNEL_DIR}/include/uapi"
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/CMakeLists.txt
new file mode 100644
index 000000000..6262f8dee
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
+project(dimmsensor CXX)
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+add_executable(dimmsensor DimmSensor.cpp)
+install (TARGETS dimmsensor DESTINATION bin)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/DimmSensor.cpp b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/DimmSensor.cpp
new file mode 100644
index 000000000..9cc13c2a5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/dimmsensor/files/DimmSensor.cpp
@@ -0,0 +1,143 @@
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <vector>
+#include <linux/aspeed_peci_ioctl.h>
+
+#define PECI_DIMM_TEMP_REG 0x150
+#define DIMM_DEFAULT_VALUE 0x55
+
+class DimmConfig {
+ public:
+ uint8_t chanId, bus, device, function, dimmnum;
+};
+
+#define MAX_BUFFER_SIZE 32
+
+// TODO get this from config
+auto GetDimmConfig(uint8_t dimm) {
+ uint8_t chan = dimm / 2;
+ assert(chan < 6);
+
+ auto ret = std::make_unique<DimmConfig>();
+
+ ret->chanId = chan;
+ ret->dimmnum = 2;
+ ret->bus = 2;
+ switch (chan) {
+ case 0:
+ ret->device = 10;
+ ret->function = 2;
+ break;
+ case 1:
+ ret->device = 10;
+ ret->function = 6;
+ break;
+ case 2:
+ ret->device = 11;
+ ret->function = 2;
+ break;
+ case 3:
+ ret->device = 12;
+ ret->function = 2;
+ break;
+ case 4:
+ ret->device = 12;
+ ret->function = 6;
+ break;
+ case 5:
+ ret->device = 13;
+ ret->function = 2;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return ret;
+}
+
+// returns read vector on success, empty vector on failure
+auto peci_config_local(uint8_t u8target, uint8_t u8bus, uint8_t u8device,
+ uint8_t u8fcn, uint16_t u16reg, uint8_t u8readlen) {
+ auto msg = std::make_unique<peci_xfer_msg>();
+ uint32_t u32Address;
+ int fd;
+ std::vector<uint8_t> ret;
+
+ u32Address = u16reg;
+ u32Address |= u8fcn << 12;
+ u32Address |= u8device << 15;
+ u32Address |= u8bus << 20;
+
+ msg->client_addr = u8target;
+ msg->tx_len = RDPCICFGLOCAL_WRITE_LEN;
+ msg->rx_len = RDPCICFGLOCAL_READ_LEN_BASE + u8readlen;
+
+ msg->tx_buf[0] = RDPCICFGLOCAL_PECI_CMD;
+ msg->tx_buf[2] = u32Address & 0xFF;
+ msg->tx_buf[3] = (u32Address >> 8) & 0xFF;
+ msg->tx_buf[4] = (u32Address >> 16) & 0xFF;
+
+ fd = open("/dev/peci", O_RDWR | O_CLOEXEC);
+ if (fd >= 0) {
+ int success = ioctl(fd, PECI_IOC_XFER, msg.get());
+ if (success == 0) {
+ if (DEV_PECI_CC_SUCCESS == msg->rx_buf[0]) {
+ ret.resize(RDPCICFGLOCAL_READ_LEN_BASE + u8readlen - 1);
+ memcpy(ret.data(), &(msg->rx_buf[1]), ret.size());
+ }
+ }
+ close(fd);
+ }
+ return ret;
+}
+
+int main(int argc, char** argv) {
+ if (argc != 3) {
+ std::cout << argv[0] << " requires 2 arguments: CPUNum, DimmNum.\n";
+ return -1;
+ }
+ uint8_t cpunum = atoi(argv[1]);
+ if (cpunum > 3) {
+ std::cout << cpunum << " greater than cpu max of 3.\n";
+ return -1;
+ }
+ uint8_t dimmnum = atoi(argv[2]);
+ if (dimmnum > 11) {
+ std::cout << dimmnum << " greater than dimm max of 11.\n";
+ return -1;
+ }
+
+ auto dimm_config = GetDimmConfig(dimmnum);
+
+ uint8_t dimmSelect = dimmnum % 2; // dimm 0 or 1 for each config
+
+ auto val = peci_config_local(PECI_BASE_ADDR + cpunum, dimm_config->bus,
+ dimm_config->device, dimm_config->function,
+ PECI_DIMM_TEMP_REG + dimmSelect * 4, 4);
+
+ if (!val.size()) {
+ std::cout << "Peci Error\n";
+ return -1;
+ }
+
+ // TODO dimm offsets needed?
+
+ if (val[0] == 0)
+ std::cout << "Dimm " << unsigned(dimmnum) << " CPU " << unsigned(cpunum)
+ << " not populated.\n";
+ else if(val[0] == DIMM_DEFAULT_VALUE)
+ std::cout << "Dimm " << unsigned(dimmnum) << " CPU " << unsigned(cpunum)
+ << " in illegal state.\n";
+ else
+ std::cout << unsigned(val[0]) << " degrees C.\n";
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/intel-signed-image/files/genimage-si.ini b/meta-openbmc-mods/meta-common/recipes-utilities/intel-signed-image/files/genimage-si.ini
new file mode 100644
index 000000000..38609ad5d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/intel-signed-image/files/genimage-si.ini
@@ -0,0 +1,277 @@
+;
+; Copyright 2015 Intel Corporation.
+;
+; The source code, information and material ("Material") contained herein is
+; owned by Intel Corporation or its suppliers or licensors, and title to such
+; Material remains with Intel Corporation or its suppliers or licensors. The
+; Material contains proprietary information of Intel or its suppliers and
+; licensors. The Material is protected by worldwide copyright laws and treaty
+; provisions. No part of the Material may be used, copied, reproduced,
+; modified, published, uploaded, posted, transmitted, distributed or disclosed
+; in any way without Intel's prior express written permission. No license under
+; any patent, copyright or other intellectual property rights in the Material
+; is granted to or conferred upon you, either expressly, by implication,
+; inducement, estoppel or otherwise. Any license under such intellectual
+; property rights must be express and approved by Intel in writing.
+
+;
+; This file is similar to the config.genimage2 file of previous BMC
+; generations but it is not generated. It contains all of the information
+; to generate the signed-image variant of the signtool config file.
+;
+
+[GLOBAL]
+Major = 0
+Minor = 72
+Output = update.bin
+Alloc = 33792K ; 0x2100000
+BlockSize = 64K
+Type = 0xffffffff ; generate top level composite image
+Locate = 0
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Factory ROM file generation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+RomOutput = rom-a-only.ima
+RomAlloc = 33M
+KeyRegion = Certificate
+NewKeyRegion = ReplacementCertificate
+SecVersion = 0
+
+
+
+; RecoveryOnly items should be place first in the image
+
+[FRISBEE_ROM]
+Major = 1
+Minor = 5
+Type = ROBL
+File = frisbee.bin
+Locate = 0x00000000
+Alloc = 240K
+Compress = 0
+SecVersion = 1
+Unsigned = 1
+
+[Certificate]
+Locate = 0x3c000
+Type = CERT
+Alloc = 8K
+Fill = 0xff
+Unsigned = 1
+ROMOnly = 1
+SecVersion = 0
+
+;[FWPRODUCTID]
+;Major = 1
+;Minor = 0
+;Type = FWID
+;File = fwproductid.bin
+;Locate = 0x0003f000
+;ROMOnly = 1
+;SecVersion = 0
+
+[FRISBEE_UPD]
+Major = 1
+Minor = 5
+Type = RWBL
+File = frisbee.bin
+Locate = 0x040000
+Alloc = 256K
+Compress = 0
+SecVersion = 1
+IndivSign = 1
+SigOffset = 0x03e000
+
+[U-Boot]
+Major = 1
+Minor = 5
+Type = UBT\x00
+File = u-boot.bin
+Alloc = 256K
+Compress = 0
+SecVersion = 1
+IndivSign = 1
+SigOffset = 0x03e000
+
+; Linux OS Image
+[OSIMAGE]
+Major = 1
+Minor = 1
+Type = LKNL
+File = uImage
+SecVersion = 1
+
+[DTB]
+Major = 1
+Minor = 1
+Type = DTB\x00
+File = uImage-aspeed-bmc-intel-ast2500.dtb
+SecVersion = 0
+
+; Root File System
+[ROOT]
+Major = 1
+Minor = 1
+Type = RtFS
+File = image-rofs.squashfs-xz.u-boot
+Load = 0x83000000
+SecVersion = 1
+;
+; WWW File System in CRAMFS.
+;[WWW]
+;Major = 1
+;Minor = 1
+;Type = WWW\x00
+;File = webfs.bin
+;BlockDev = 1
+;SecVersion = 1
+
+; Replacement certificate for re-keying the BMC
+; Will only be added to image if -rk is specified
+[ReplacementCertificate]
+Major = 1
+Minor = 1
+Type = CRT0
+Alloc = 4K
+SecVersion = 0
+Compress = 0
+IndivSign = 1
+Unbound = 1
+Fill = 0xff
+SigOffset = 0x800
+
+; Manifest goes here
+; This gets some special treatment (this needs to match the location
+; that Frisbee thinks the manifest is at or it won't boot)
+[Manifest]
+Major = 0
+Minor = 0
+Type = MFST
+Alloc = 4K
+Locate = 0x1bff000
+Fill = 0xff
+SecVersion = 0
+
+;
+; NV File System in JFFS2, but it is blank in the ROM version
+; and filled in with defaults from the rootfs
+[PARAMS]
+Major = 1
+Minor = 1
+Type = CONF
+Alloc = 4096K
+Locate = 0x1c00000
+ROMOnly = 1
+BlockDev = 1
+SecVersion = 1
+Unsigned = 1
+
+; notice that these sections have no file
+; and are marked as ROMOnly. This forces them
+; into the allocation so we don't get overlapping
+; sections, but does not actually put anything into
+; the rom at build time.
+
+[UBootEnv]
+Major = 1
+Minor = 0
+Type = UENV
+; File = ; no file makes this a placeholder
+Locate = 0x2000000
+Alloc = 64K
+BlockDev = 1
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+[FRUData]
+Major = 1
+Minor = 0
+Type = FRU\x00
+Alloc = 64K
+Locate = 0x2010000
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+[SEL]
+Major = 1
+Minor = 0
+Type = SEL\x00
+Alloc = 512K
+Locate = 0x2020000
+BlockDev = 1
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+; NV filesystem that survives reset mfg defaults.
+; OEM Web customization goes here.
+[PersistentNV]
+Major = 1
+Minor = 0
+Type = PNV\x00
+Alloc = 2048K
+Locate = 0x20a0000
+BlockDev = 1
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+[RubixLog]
+Major = 1
+Minor = 0
+Type = BTLG
+Alloc = 4K
+Locate = 0x23fe000
+BlockDev = 0
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+[BootPointer]
+Major = 1
+Minor = 0
+Type = BPTR
+Alloc = 4K
+Locate = 0x23ff000
+BlockDev = 0
+ROMOnly = 1
+Unsigned = 1
+SecVersion = 0
+
+;
+; Example Section with all possible fields with their default
+; values, unless the field is specified mandatory
+;
+;[EXAMPLE]
+;Major = 0 ; Major number of module
+;Minor = 0 ; Minor number of module
+;Type = TYPE ; four bytes hopefully human readable,
+; ; use c-style escapes if non-ascii, \x23\x10\x00\xf3
+; ; or use a number 0xf3001023
+;Alloc = X ; Maximum memory allocated; X = roundup
+;File = name ; File containing the module
+; ; If Alloc is specified, but no File, a blank
+; ; header will be created (only useful for ROMOnly)
+;Locate = addr ; Location in Flash; MANDATORY
+;ROMOnly = 1 ; if ROMOnly is set and non-zero, this section
+; ; will only be present in the ROM image, not the updater image
+;RecoveryOnly = 1 ; if RecoveryOnly is set and non-zero, this section
+; ; will only be present in the recovery image, not the active image
+;BlockDev = 1 ; this will make the signed image code export this
+; ; image as a mtd block device at runtime
+;Unsigned = 1 ; Do not include this section in signatures (NV data)
+;Compress = 1 ; compress image contents (useful for non-compressed items)
+;SecVersion = X ; a 16-bit security revision to enforce no downgrades
+;IndivSign = 1 ; section is individually signed; do not include in full signature
+;Unbound = 1 ; by default, individually signed sections are part of the
+; ; full signature too. This makes them independent
+;SigOffset = X ; offset within individually-signed section to place signature
+;Fill = xx ; fill with pattern xx instead of a file's contents
+;
+; Note: Numeric values can be represented either by decimal or a
+; hexadecimal (Prefixed by 0x)
+; Numeric values can either end with K or M to specify in
+; KiloBytes or MegaBytes
+;
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/CMakeLists.txt
new file mode 100644
index 000000000..0c98160b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
+project(io-app C)
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+add_executable(io io-app.c)
+install (TARGETS io DESTINATION bin)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/io-app.c b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/io-app.c
new file mode 100644
index 000000000..955674fa6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/io-app.c
@@ -0,0 +1,696 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Abstract: map io region to read or write to HW registers
+//
+*/
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+static int quiet = 0;
+
+static int dump(unsigned long phys, void *addr, size_t len)
+{
+ const uint32_t *ubuf = addr;
+ unsigned int wd = 0, l, iv;
+ unsigned char *h, *a;
+ char line[256];
+ static const char itoh[] = "0123456789abcdef";
+
+ /* 0 1 2 3 4 5 6
+ * 0123456789012345678901234567890123456789012345678901234567890123456789
+ * 00000000: 00000000 00000000 00000000 00000000 ................
+ */
+ while (wd < len)
+ {
+ memset(line, ' ', sizeof(line));
+ sprintf(line, "%08lx: ", phys + (wd*sizeof(uint32_t)));
+ a = (unsigned char*)&line[47];
+ h = (unsigned char*)&line[10];
+ for (l=0; l<4 && (l+wd)<len; l++)
+ {
+ uint32_t v = *ubuf++;
+ for (iv=0; iv<sizeof(v); iv++)
+ {
+ uint8_t b = v >> (8*((sizeof(v)-1)-iv));
+ *h++ = itoh[b>>4];
+ *h++ = itoh[b&0xf];
+ if (isprint(b))
+ *a++ = (char)b;
+ else
+ *a++ = '.';
+ }
+ *h++ = ' ';
+ }
+ *a++ = '\n';
+ *a = 0;
+ wd += l;
+ fputs(line, stdout);
+ }
+ return wd;
+}
+
+
+struct mapping
+{
+ unsigned long phys;
+ void *virt;
+ size_t len;
+};
+
+static struct mapping *maps = NULL;
+static int nr_maps = 0;
+
+static void unmap_all(void)
+{
+ int i;
+ for (i=0; i<nr_maps; i++)
+ {
+ if (maps[i].virt)
+ munmap(maps[i].virt, maps[i].len);
+ maps[i].virt = NULL;
+ }
+}
+
+int add_a_map(unsigned long phys, void *virt, size_t len)
+{
+ void *new_maps;
+ new_maps = realloc(maps, (nr_maps + 1) * sizeof(struct mapping));
+ if (!new_maps)
+ {
+ unmap_all();
+ munmap(virt, len);
+ }
+ else
+ {
+ maps = new_maps;
+ maps[nr_maps].phys = phys;
+ maps[nr_maps].virt = virt;
+ maps[nr_maps].len = len;
+ nr_maps++;
+ return 0;
+ }
+ return -1;
+}
+
+static void *map_fd(int fd, off_t offset, size_t len, int mode, int flags)
+{
+ void *mapped_at;
+ unsigned long phys = -1;
+
+ if (offset != -1)
+ phys = offset;
+ else
+ offset = 0;
+
+ mapped_at = mmap(NULL, len, mode, flags, fd, offset);
+ if (mapped_at != MAP_FAILED)
+ {
+ if (add_a_map(phys, mapped_at, len) != 0)
+ {
+ mapped_at = MAP_FAILED;
+ }
+ }
+
+ return mapped_at;
+}
+
+static void *map_file(const char *fname, size_t *len, int mode, int flags)
+{
+ int fd;
+ struct stat sb;
+ void *ptr;
+ int fmode;
+
+ if (mode & PROT_WRITE)
+ fmode = O_RDWR;
+ else
+ fmode = O_RDONLY;
+
+ fd = open(fname, fmode);
+ if (fd < 0)
+ return MAP_FAILED;
+
+ if (*len == 0)
+ {
+ fstat(fd, &sb);
+ *len = sb.st_size;
+ }
+ ptr = map_fd(fd, -1, *len, mode, flags);
+ close(fd);
+ return ptr;
+}
+
+static int load_maps(const char *cmap_str, size_t mlen)
+{
+ char *tmp_sa = NULL, *tmp_sl = NULL, *endptr = NULL;
+ const void *mapped = NULL;
+ int ret = 0;
+ const char *delim = "\r\n\t ,";
+ unsigned long addr;
+ size_t len;
+ char *map_str = NULL, *paddr = NULL, *plen = NULL;
+ int fd;
+
+ fd = open("/dev/mem", O_RDWR);
+ if (fd < 0)
+ {
+ return -1;
+ }
+
+ len = strlen(cmap_str);
+ map_str = (char *)malloc(len + 1);
+ if (!map_str)
+ {
+ close(fd);
+ return -1;
+ }
+ strncpy(map_str, cmap_str, len);
+ map_str[len] = '\0';
+ paddr = strtok_r(map_str, delim, &tmp_sa);
+ while (paddr)
+ {
+ /* find the next comma or newline */
+ if (!strtok_r(paddr, ":", &tmp_sl))
+ {
+ fprintf(stderr, "malformed map string '%s'\n", paddr);
+ goto _loop;
+ }
+ plen = strtok_r(NULL, ":", &tmp_sl);
+ if (!plen)
+ {
+ goto _loop;
+ }
+ addr = strtoul(paddr, &endptr, 16);
+ if (*endptr)
+ {
+ fprintf(stderr, "Failed to parse address from '%s'\n", paddr);
+ ret = -1;
+ break;
+ }
+ len = strtoul(plen, &endptr, 16);
+ if (*endptr)
+ {
+ fprintf(stderr, "Failed to parse len from '%s'\n", plen);
+ ret = -1;
+ break;
+ }
+ if (MAP_FAILED == (mapped = map_fd(fd, addr, len, PROT_READ|PROT_WRITE, MAP_SHARED)))
+ {
+ fprintf(stderr, "Failed to map %lx +%x\n", addr, len);
+ ret = -1;
+ break;
+ }
+ if (!quiet)
+ printf("added map: %p (%lx..%lx)\n", mapped, addr, addr+len);
+_loop:
+ paddr = strtok_r(NULL, delim, &tmp_sa);
+ }
+ free(map_str);
+ close(fd);
+ return ret;
+}
+
+int md(unsigned long addr, uint32_t unused, size_t len)
+{
+ int i, j;
+
+ (void)unused;
+ for (i=0; i<nr_maps; i++)
+ {
+ if (-1 == maps[i].phys)
+ continue;
+ if (maps[i].phys <= addr &&
+ (addr + len * sizeof(uint32_t)) < (maps[i].phys + maps[i].len))
+ {
+ uint32_t *buf, *pv;
+
+ buf = (uint32_t *)malloc(len*sizeof(uint32_t));
+ if (!buf)
+ return 1;
+ pv = (uint32_t *)(maps[i].virt + (addr - maps[i].phys));
+ for (j=0; j<len; j++)
+ buf[j] = *pv++;
+
+ dump(addr, buf, len);
+ free(buf);
+ return 0;
+ }
+ }
+ fprintf(stderr, "%lx +%x not in mapped memory\n", addr, len);
+ return 1;
+}
+
+int mw(unsigned long addr, uint32_t val, size_t len)
+{
+ int i, j;
+
+ for (i=0; i<nr_maps; i++)
+ {
+ if (-1 == maps[i].phys)
+ continue;
+ if (maps[i].phys <= addr &&
+ (addr + len * sizeof(uint32_t)) < (maps[i].phys + maps[i].len))
+ {
+ for (j=0; j<len; j++)
+ {
+ *((uint32_t*)(maps[i].virt + (addr - maps[i].phys))) = val;
+ }
+ return 0;
+ }
+ }
+ fprintf(stderr, "%lx +%x not in mapped memory\n", addr, len);
+ return 1;
+}
+
+char *readline(char *buf, size_t len, FILE *f)
+{
+ int raw = 0;
+ size_t br = 0;
+ struct termios tios, orig_tios;
+
+ if (!quiet)
+ {
+ /* put terminal in raw mode to get unbuffered io */
+ if (tcgetattr(fileno(f), &orig_tios) == 0)
+ {
+ tios = orig_tios;
+ tios.c_iflag |= IGNPAR;
+ tios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
+ tios.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN);
+ tios.c_oflag &= ~OPOST;
+ tios.c_cc[VMIN] = 1;
+ tios.c_cc[VTIME] = 0;
+ tcsetattr(fileno(f), TCSADRAIN, &tios);
+ raw = 1;
+ }
+ }
+ if (!raw)
+ {
+ return fgets(buf, len, f);
+ }
+ /* read in bytes one at a time and echo them */
+ while (br < (len-1))
+ {
+ int c = fgetc(f);
+ switch (c)
+ {
+ case 3: /* ^C */
+ br = 0;
+ c = '\n';
+ break;
+ case 4:
+ br = 0;
+ c = -1;
+ break;
+ case '\b':
+ if (br > 0)
+ {
+ fputs("\b \b", stdout);
+ br--;
+ }
+ break;
+ case '\r':
+ case '\n':
+ fputs("\r\n", stdout);
+ buf[br++] = '\n';
+ break;
+ case ' '...'~':
+ fputc(c, stdout);
+ buf[br++] = c;
+ break;
+ break;
+ default:
+ break;
+ }
+ if (c == -1)
+ {
+ if (br == 0)
+ buf = NULL;
+ break;
+ }
+ if (c == '\r' || c == '\n')
+ break;
+ }
+ if (buf)
+ buf[br] = 0;
+
+ tcsetattr(fileno(f), TCSADRAIN, &orig_tios);
+ return buf;
+}
+
+#define MAX_LINE_LEN 4096
+int io(void)
+{
+ const char delim1[] = "\r\n;";
+ const char delim2[] = "\t ";
+ char line[MAX_LINE_LEN];
+ char *command, *cmd, *paddr, *pval, *plen, *endptr;
+ char *tmp_s1, *tmp_s2;
+ unsigned long addr;
+ uint32_t val;
+ size_t len;
+ int (*fn)(unsigned long, uint32_t, size_t);
+
+ if (!quiet)
+ fputs("> ", stdout);
+ while (readline(line, MAX_LINE_LEN, stdin) != NULL && *line)
+ {
+ /* read next line or next command (up to newline or ';') */
+ command = strtok_r(line, delim1, &tmp_s1);
+ if (!command || strlen(command) == 0)
+ goto _command_loop;
+ while (NULL != command && strlen(command) > 0)
+ {
+ cmd = strtok_r(command, delim2, &tmp_s2);
+ if (!cmd)
+ goto _cmd_err;
+ if (cmd[0] == 'q' || cmd[0] == 'Q')
+ return 0;
+ paddr = strtok_r(NULL, delim2, &tmp_s2);
+ if (!paddr)
+ goto _cmd_err;
+ addr = strtoul(paddr, &endptr, 16);
+ if (*endptr)
+ goto _cmd_err;
+ fn = NULL;
+ if (strncmp(cmd, "mw", 3) == 0)
+ {
+ fn = mw;
+ pval = strtok_r(NULL, delim2, &tmp_s2);
+ if (!pval)
+ goto _cmd_err;
+ val = strtoul(pval, &endptr, 16);
+ if (*endptr)
+ goto _cmd_err;
+ len = 1;
+ }
+ else if (strncmp(cmd, "md", 3) == 0)
+ {
+ fn = md;
+ len = 0x40;
+ val = 0;
+ }
+ else
+ {
+ goto _cmd_err;
+ }
+ plen = strtok_r(NULL, delim2, &tmp_s2);
+ if (plen)
+ {
+ len = strtoul(plen, &endptr, 16);
+ if (*endptr)
+ goto _cmd_err;
+ }
+
+ if (fn)
+ fn(addr, val, len);
+
+ command = strtok_r(NULL, delim1, &tmp_s1);
+ }
+_command_loop:
+ if (!quiet)
+ fputs("> ", stderr);
+ continue;
+_cmd_err:
+ fprintf(stderr, "md addr [len]\nmw addr val [len]\n"
+ "q[uit] | ctrl-d | ctrl-c to exit\n");
+ if (!quiet)
+ fputs("> ", stderr);
+ }
+ return 0;
+}
+
+typedef enum
+{
+ CPU_NONE = 0,
+ CPU_PILOT3,
+ CPU_PILOT4,
+ CPU_AST2500,
+ CPU_AST2600,
+ CPU_MAX,
+} CPU_TYPE;
+
+static CPU_TYPE probe_cpu(void)
+{
+ FILE *f;
+ char cpuinfo[128];
+ static CPU_TYPE this_cpu = CPU_NONE;
+
+ if (CPU_NONE == this_cpu)
+ {
+ f = fopen("/sys/firmware/devicetree/base/compatible", "r");
+ if (f) {
+ int br = fread(cpuinfo, 1, sizeof(cpuinfo)-1, f);
+ if (br > 0) {
+ cpuinfo[br] = 0;
+ char *v = cpuinfo;
+ while (v < (cpuinfo + sizeof(cpuinfo)) && *v) {
+ if (strncmp("aspeed,ast2500", v, 15) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "AST2500\n");
+ this_cpu = CPU_AST2500;
+ }
+ v += 1 + strnlen(v, sizeof(cpuinfo) - (v - cpuinfo));
+ }
+ }
+ fclose(f);
+ }
+ }
+ if (CPU_NONE == this_cpu)
+ {
+ const char delim[] = "\r\n\t :";
+ char *tmp_s;
+ f = fopen("/proc/cpuinfo", "r");
+ if (f != NULL) {
+ while (fgets(cpuinfo, sizeof(cpuinfo), f))
+ {
+ strtok_r(cpuinfo, delim, &tmp_s);
+ if (strncmp("Hardware", cpuinfo, 9) == 0)
+ {
+ char *v = strtok_r(NULL, delim, &tmp_s);
+ if (v)
+ {
+ if (strncmp("AST2500", v, 8) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "AST2500\n");
+ this_cpu = CPU_AST2500;
+ break;
+ }
+ else if (strncmp("ASpeed SoC", v, 11) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "Found ASpeed SoC\n");
+ this_cpu = CPU_AST2500;
+ break;
+ }
+ else if (strncmp("ServerEngines PILOT3", v, 21) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "Found PILOT3\n");
+ this_cpu = CPU_PILOT3;
+ break;
+ }
+ }
+ }
+ else if (strncmp("CPU", cpuinfo, 4) == 0)
+ {
+ char *v = strtok_r(NULL, delim, &tmp_s);
+ if (!v || strncmp("part", v, 5) != 0)
+ {
+ continue;
+ }
+ v = strtok_r(NULL, delim, &tmp_s);
+ if (v)
+ {
+ if (strncmp("0xb76", v, 6) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "AST2500\n");
+ this_cpu = CPU_AST2500;
+ break;
+ }
+ else if (strncmp("0xc07", v, 6) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "AST2600\n");
+ this_cpu = CPU_AST2600;
+ break;
+ }
+ }
+ }
+ }
+ fclose(f);
+ }
+ }
+ return this_cpu;
+}
+
+static const char *probe_cpu_for_map(void)
+{
+ switch (probe_cpu())
+ {
+ case CPU_PILOT3:
+ return "0:2000000,10000000:8000,40000000:43b000";
+ case CPU_AST2500:
+ return "0:4000000,1e600000:1a0000,20000000:4000000";
+ case CPU_AST2600:
+ return "0:20000000,38000000:8000000,60000000:20000000";
+ default:
+ return "";
+ }
+}
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "Usage: io [-c config] [-m map]\n"
+ " md [-c config] [-m map] <addr> [len]\n"
+ " mw [-c config] [-m map] <addr> <val> [len]\n\n"
+ "With: -c config load mappings from file config\n"
+ " -m map load mappings from string map\n"
+ " addr, val, len are all hex numbers\n\n"
+ "When invoked as io, this will start a shell that will\n"
+ "allow the user to type in md and mw commands much like\n"
+ "the U-Boot environment. By default, it will map in all\n"
+ "the addresses for the known processor type.\n\n"
+ "map string is of the format addr:len[,addr2:len2...]\n"
+ "config file is of the same format as map string\n"
+ "but with each mapping on separate lines instead of\n"
+ "comma separated values\n"
+ );
+ exit(1);
+}
+
+#define shift if (++i >= argc) usage()
+
+int main(int argc, const char *argv[])
+{
+ char *exe_full;
+ char *exe;
+ char *endptr;
+ int i, first_arg = 1;
+ const char *cfg_file = NULL;
+ const char *map_str = NULL;
+ size_t flen = 0;
+ size_t len = 0;
+ unsigned long addr;
+ uint32_t val;
+ int ret = 0;
+
+ i = 1;
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'm':
+ shift;
+ map_str = argv[i];
+ break;
+ case 'c':
+ shift;
+ cfg_file = argv[i];
+ break;
+ default:
+ usage();
+ }
+ }
+ else
+ {
+ first_arg = i;
+ break;
+ }
+ }
+
+ exe_full = strdup(argv[0]);
+ if (exe_full != NULL )
+ exe = basename(exe_full);
+ else
+ return ret;
+
+ if (strncmp(exe, "io", 3) != 0 || !isatty(fileno(stdin)))
+ quiet = 1;
+
+ if (!map_str)
+ {
+ if (!cfg_file)
+ map_str = probe_cpu_for_map();
+ else
+ map_str = map_file(cfg_file, &flen, PROT_READ, MAP_PRIVATE);
+ }
+ else
+ {
+ flen = strlen(map_str);
+ }
+ if (load_maps(map_str, flen) < 0)
+ {
+ fprintf(stderr, "failed to map regions: check map string or config file\n");
+ goto _cleanup;
+ }
+
+ if (strncmp(exe, "md", 3) == 0)
+ {
+ len = 0x40;
+ addr = strtoul(argv[first_arg], &endptr, 16);
+ if ((first_arg + 1) < argc)
+ {
+ len = strtoul(argv[first_arg + 1], &endptr, 16);
+ }
+ ret = md(addr, 0, len);
+ goto _cleanup;
+ }
+
+ if (strncmp(exe, "mw", 3) == 0)
+ {
+ len = 1;
+ addr = strtoul(argv[first_arg], &endptr, 16);
+ if ((first_arg + 1) < argc)
+ {
+ val = strtoul(argv[first_arg + 1], &endptr, 16);
+ }
+ else
+ {
+ usage();
+ }
+ if ((first_arg + 2) < argc)
+ {
+ len = strtoul(argv[first_arg + 2], &endptr, 16);
+ }
+ ret = mw(addr, val, len);
+ goto _cleanup;
+ }
+
+ io();
+
+_cleanup:
+ unmap_all();
+ free(exe_full);
+ return ret;
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/io-app/io-app.bb b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/io-app.bb
new file mode 100644
index 000000000..5ac0f0a75
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/io-app.bb
@@ -0,0 +1,17 @@
+SUMMARY = "IO App"
+DESCRIPTION = "IO application for accessing memory-mapped IO regions on the BMC"
+
+inherit cmake
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM += "\
+ file://io-app.c;beginline=2;endline=14;md5=639666a0bf40bb717b46b378297eeceb \
+ "
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://io-app.c \
+ "
+
+S = "${WORKDIR}"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/CMakeLists.txt
new file mode 100644
index 000000000..1cde22b49
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
+project(lpc-cmds C)
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
+add_executable(lpc_cmds lpc_cmds.c)
+install (TARGETS lpc_cmds DESTINATION bin)
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_cmds.c b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_cmds.c
new file mode 100644
index 000000000..bc215f60b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_cmds.c
@@ -0,0 +1,528 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+*/
+
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "lpc_drv.h"
+
+#define SIO_DEVICE_NAME "/dev/lpc-sio"
+#define KCS_DEVICE_NAME "/dev/ipmi-kcs"
+#define MAILBOX_DEVICE_NAME "/dev/aspeed-mbox"
+#define SNOOP_DEVICE_NAME "/dev/aspeed-lpc-snoop"
+
+#define SNOOP_BUF_SIZE 4096
+
+#define SUPPORT_KCS_ADDR_CMD 0
+#define SUPPORT_MAILBOX 1
+#define SUPPORT_SNOOP 1
+
+/*********************************************************************************/
+static void ProcessKCSReq(int fd, unsigned char *pReq, int ReqLen, int NoPrint)
+{
+ int i;
+ unsigned char SendPkt[16];
+
+ if (!NoPrint) {
+ printf("\nKCS Request >>>>>>>>>>>>>>>>>>>>>>>>>>\n");
+ for (i = 0; i < ReqLen; i++)
+ printf("%02X ", pReq[i]);
+ printf("\n======================================\n");
+ }
+
+ SendPkt[0] = pReq[0] | 0x04;
+ SendPkt[1] = pReq[1];
+ SendPkt[2] = 0xC1; /* Always Invalid Command */
+
+ if (!NoPrint) {
+ printf("\nKCS Response <<<<<<<<<<<<<<<<<<<<<<<<<\n");
+ for (i = 0; i < 3; i++)
+ printf("%02X ", SendPkt[i]);
+ printf("\n======================================\n");
+ }
+
+ write(fd, SendPkt, 3);
+}
+
+static void KCSIfcTask(int KCSIfcIdx, int NoPrint)
+{
+ int fd;
+ int RecvPktLen;
+ char KCSDev[16];
+ struct kcs_ioctl_data IOData;
+ unsigned char RecvPkt[512];
+
+ snprintf(KCSDev, sizeof(KCSDev), KCS_DEVICE_NAME"%d", KCSIfcIdx);
+ fd = open(KCSDev, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open KCS device: %s\n", KCSDev);
+ exit(1);
+ }
+
+ IOData.cmd = KCS_FORCE_ABORT;
+ IOData.data = 0;
+ ioctl(fd, KCS_IOC_COMMAND, &IOData);
+
+ while (1) {
+ RecvPktLen = read(fd, RecvPkt, sizeof(RecvPkt));
+ if (RecvPktLen < 2)
+ continue;
+
+ ProcessKCSReq(fd, RecvPkt, RecvPktLen, NoPrint);
+ }
+}
+
+#if SUPPORT_KCS_ADDR_CMD
+static void KCSIfcSetAddr(int KCSIfcIdx, unsigned int addr)
+{
+ int fd;
+ struct kcs_ioctl_data kcs_data;
+ char KCSDev[16];
+
+ snprintf(KCSDev, sizeof(KCSDev), KCS_DEVICE_NAME"%d", KCSIfcIdx);
+ fd = open(KCSDev, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open KCS device: %s\n", KCSDev);
+ exit(1);
+ }
+
+ kcs_data.cmd = KCS_SET_ADDR;
+ kcs_data.data = addr;
+ if (ioctl(fd, KCS_IOC_COMMAND, &kcs_data) == 0)
+ printf("Set KCS%d addr to 0x%X successfully!\n", KCSIfcIdx + 1, addr);
+
+ close(fd);
+}
+
+static void KCSIfcGetAddr(int KCSIfcIdx)
+{
+ int fd;
+ struct kcs_ioctl_data kcs_data;
+ char KCSDev[16];
+
+ snprintf(KCSDev, sizeof(KCSDev), KCS_DEVICE_NAME"%d", KCSIfcIdx);
+ fd = open(KCSDev, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open KCS device: %s\n", KCSDev);
+ exit(1);
+ }
+
+ kcs_data.cmd = KCS_GET_ADDR;
+ if (ioctl(fd, KCS_IOC_COMMAND, &kcs_data) == 0)
+ printf("KCS%d addr is : 0x%X!\n", KCSIfcIdx + 1, kcs_data.data);
+
+ close(fd);
+}
+#endif
+
+/*********************************************************************************/
+
+#if SUPPORT_SNOOP
+static void ReadBiosPOSTCodes(unsigned int if_idx)
+{
+ char snoop_dev[32];
+ int fd;
+ int i;
+ unsigned char buf[SNOOP_BUF_SIZE];
+ int len;
+
+ snprintf(snoop_dev, sizeof(snoop_dev), SNOOP_DEVICE_NAME"%d", if_idx);
+ fd = open(snoop_dev, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s !\n", snoop_dev);
+ return;
+ }
+
+ len = read(fd, &buf, sizeof(buf));
+
+ if (len == 0 || errno == EAGAIN) {
+ printf("No BIOS POST Codes Found!\n");
+ goto out;
+ } else if (len < 0) {
+ printf("Failed to read the POST Codes! (%s)\n",
+ strerror(errno));
+ goto out;
+ }
+
+ printf("BIOS POST Codes in Hex (%d entries):\n", len);
+
+ for (i = 0; i < len; i++)
+ printf(" %d: %02X\n", i, buf[i]);
+
+ printf("\n");
+
+out:
+ close(fd);
+}
+#endif
+
+/*********************************************************************************/
+
+static void SIOGetACPIState(unsigned short changed)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_GET_ACPI_STATE;
+ sio_data.param = changed;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0) {
+ if (changed)
+ printf("ACPI SLP state is %s!\n",
+ sio_data.param != 0 ? "Changed" : "Same");
+
+ if (sio_data.data == ACPI_STATE_S12)
+ printf("ACPI SLP state --> SLP_12\n");
+ else if (sio_data.data == ACPI_STATE_S3I)
+ printf("ACPI SLP state --> SLP_3I\n");
+ else if (sio_data.data == ACPI_STATE_S45)
+ printf("ACPI SLP state --> SLP_45\n");
+ }
+
+ close(fd);
+}
+
+static void SIOGetPWRGDStatus(unsigned short changed)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_GET_PWRGD_STATUS;
+ sio_data.param = changed;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0) {
+ if (changed)
+ printf("PWRGD status : %s\n",
+ sio_data.param != 0 ? "Changed" : "Same");
+
+ printf("PWRGD status value :%u\n", sio_data.data);
+ }
+
+ close(fd);
+}
+
+static void SIOGetONCTLStatus(void)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_GET_ONCTL_STATUS;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0)
+ printf("ONCTL status value :%u\n", sio_data.data);
+
+ close(fd);
+}
+
+static void SIOSetONCTLGPIO(unsigned short enable, unsigned int value)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_SET_ONCTL_GPIO;
+ sio_data.param = enable;
+ sio_data.data = value;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0)
+ printf("ONCTL GPIO mode setting is Done!\n");
+
+ close(fd);
+}
+
+static void SIOGetPWRBTNOverride(unsigned short clear)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_GET_PWRBTN_OVERRIDE;
+ sio_data.param = clear;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0)
+ printf("PWRBTN Override status : %u\n", sio_data.data);
+
+ close(fd);
+}
+
+static void SIOGetPFailStatus()
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_GET_PFAIL_STATUS;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0)
+ printf("PFail status : %u\n", sio_data.data);
+
+ close(fd);
+}
+
+static void SIOSetBMCSCIEvent(unsigned short set)
+{
+ int fd;
+ struct sio_ioctl_data sio_data;
+
+ fd = open(SIO_DEVICE_NAME, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open %s\n", SIO_DEVICE_NAME);
+ exit(1);
+ }
+
+ sio_data.sio_cmd = SIO_SET_BMC_SCI_EVENT;
+ sio_data.param = set;
+
+ if (ioctl(fd, SIO_IOC_COMMAND, &sio_data) == 0)
+ printf("BMC SCI event is %s\n",
+ sio_data.data ? "set" : "cleared");
+
+ close(fd);
+}
+
+/*********************************************************************************/
+
+#if SUPPORT_MAILBOX
+static void MailBoxRead(int num)
+{
+ int fd;
+ int len;
+ uint8_t data;
+
+ fd = open(MAILBOX_DEVICE_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open mailbox\n");
+ exit(1);
+ }
+
+ len = pread(fd, &data, 1, num);
+ if (len == 0 || errno == EAGAIN) {
+ printf("No mailbox message found!\n");
+ goto out;
+ } else if (len < 0) {
+ printf("Error reading from mailbox%d! (%s)\n", num,
+ strerror(errno));
+ goto out;
+ }
+
+ printf("MailBox%d read value : 0x%02X\n", num, data);
+
+out:
+ close(fd);
+}
+
+static void MailBoxWrite(int num, uint8_t value)
+{
+ int fd;
+ ssize_t rc;
+
+ fd = open(MAILBOX_DEVICE_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0) {
+ printf("Error open mailbox\n");
+ exit(1);
+ }
+
+ rc = pwrite(fd, &value, 1, num);
+
+ if (rc == 1)
+ printf("MailBox%d write value : 0x%02X done!\n", num, value);
+ else
+ printf("Error writing to mailbox%d, rc: %d\n", num, rc);
+
+ close(fd);
+}
+#endif
+
+/*********************************************************************************/
+
+static void usage(void)
+{
+ printf("Usage:\n"
+ "\tlpc_cmds sio get_acpi_state\n"
+ "\tlpc_cmds sio get_acpi_changed\n"
+ "\tlpc_cmds sio get_pwrgd_status\n"
+ "\tlpc_cmds sio get_pwrgd_changed\n"
+ "\tlpc_cmds sio get_onctl_status\n"
+ "\tlpc_cmds sio set_onctl_gpio_disable\n"
+ "\tlpc_cmds sio set_onctl_gpio_high\n"
+ "\tlpc_cmds sio set_onctl_gpio_low\n"
+ "\tlpc_cmds sio get_pwrbtn_override_status\n"
+ "\tlpc_cmds sio get_pwrbtn_override_status_clear\n"
+ "\tlpc_cmds sio get_pfail_status\n"
+ "\tlpc_cmds sio set_bmc_sci_event\n"
+ "\tlpc_cmds sio clear_bmc_sci_event\n"
+ "\n"
+#if SUPPORT_KCS_ADDR_CMD
+ "\tlpc_cmds kcs [1 ~ 4] (getaddr / setaddr / quiet)\n"
+#else
+ "\tlpc_cmds kcs [1 ~ 4] (quiet)\n"
+#endif
+#if SUPPORT_MAILBOX
+ "\n"
+ "\tlpc_cmds mailbox read (0 ~ 15)\n"
+ "\tlpc_cmds mailbox write (0 ~ 15) (0x00 ~ 0xFF)\n"
+#endif
+#if SUPPORT_SNOOP
+ "\n"
+ "\tlpc_cmds snoop [0 ~ 1] read\n"
+#endif
+ );
+
+ exit(-1);
+}
+
+int main(int argc, char** argv)
+{
+ char *cmd;
+
+ if (argc < 2)
+ usage();
+
+ cmd = argv[1];
+
+ if (strcmp(cmd, "sio") == 0) {
+ if (argc < 3)
+ usage();
+
+ if (strcmp(argv[2], "get_acpi_state") == 0)
+ SIOGetACPIState(0);
+ else if (strcmp(argv[2], "get_acpi_changed") == 0)
+ SIOGetACPIState(1);
+ else if (strcmp(argv[2], "get_pwrgd_status") == 0)
+ SIOGetPWRGDStatus(0);
+ else if (strcmp(argv[2], "get_pwrgd_changed") == 0)
+ SIOGetPWRGDStatus(1);
+ else if (strcmp(argv[2], "get_onctl_status") == 0)
+ SIOGetONCTLStatus();
+ else if (strcmp(argv[2], "set_onctl_gpio_disable") == 0)
+ SIOSetONCTLGPIO(0, 0);
+ else if (strcmp(argv[2], "set_onctl_gpio_high") == 0)
+ SIOSetONCTLGPIO(1, 1);
+ else if (strcmp(argv[2], "set_onctl_gpio_low") == 0)
+ SIOSetONCTLGPIO(1, 0);
+ else if (strcmp(argv[2], "get_pwrbtn_override_status") == 0)
+ SIOGetPWRBTNOverride(0);
+ else if (strcmp(argv[2], "get_pwrbtn_override_status_clear") == 0)
+ SIOGetPWRBTNOverride(1);
+ else if (strcmp(argv[2], "get_pfail_status") == 0)
+ SIOGetPFailStatus();
+ else if (strcmp(argv[2], "set_bmc_sci_event") == 0)
+ SIOSetBMCSCIEvent(1);
+ else if (strcmp(argv[2], "clear_bmc_sci_event") == 0)
+ SIOSetBMCSCIEvent(0);
+ } else if (strcmp(cmd, "kcs") == 0) {
+ int ifc;
+
+ if (argc < 3)
+ usage();
+
+ ifc = atoi(argv[2]);
+ if (ifc < 1 || ifc > 4) /* ipmi-kcs1 ~ ipmi-kcs4 */
+ usage();
+
+ if (argc == 3)
+ KCSIfcTask(ifc, 0);
+ else if (argc == 4 && strcmp(argv[3], "quiet") == 0)
+ KCSIfcTask(ifc, 1);
+#if SUPPORT_KCS_ADDR_CMD
+ else if (argc == 4 && strcmp(argv[3], "getaddr") == 0)
+ KCSIfcGetAddr(ifc);
+ else if (argc == 5 && strcmp(argv[3], "setaddr") == 0)
+ KCSIfcSetAddr(ifc, strtoul(argv[4], NULL, 16));
+#endif
+#if SUPPORT_MAILBOX
+ } else if (strcmp(cmd, "mailbox") == 0) {
+ if (argc < 4)
+ usage();
+
+ if (strcmp(argv[2], "read") == 0) {
+ MailBoxRead(atoi(argv[3]));
+ } else {
+ if (argc < 5)
+ usage();
+ MailBoxWrite(atoi(argv[3]), strtoul(argv[4], NULL, 16));
+ }
+#endif
+#if SUPPORT_SNOOP
+ } else if (strcmp(cmd, "snoop") == 0) {
+ int ifc;
+
+ if (argc < 3)
+ usage();
+
+ ifc = atoi(argv[2]);
+ if (ifc < 0 || ifc > 1) /* snoop0 ~ snoop1 */
+ usage();
+
+ if (strcmp(argv[3], "read") == 0)
+ ReadBiosPOSTCodes(ifc);
+ else
+ usage();
+#endif
+ }
+
+ return 0;
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h
new file mode 100644
index 000000000..793e8b49c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h
@@ -0,0 +1,79 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+*/
+
+#ifndef __LPC_DRV_H__
+#define __LPC_DRV_H__
+
+#define LPC_DEV_MAJOR 250
+#define LPC_DEV_MINOR 0
+
+/***********************************************************************************/
+
+enum KCS_CMD {
+ KCS_SET_ADDR = 0,
+ KCS_GET_ADDR,
+ KCS_SMS_ATN,
+ KCS_FORCE_ABORT,
+};
+
+struct kcs_ioctl_data {
+ unsigned int cmd;
+ unsigned int data;
+};
+
+#define KCS_IOC_BASE 'K'
+#define KCS_IOC_COMMAND _IOWR(KCS_IOC_BASE, 1, struct kcs_ioctl_data)
+
+/***********************************************************************************/
+
+enum ACPI_SLP_STATE {
+ ACPI_STATE_S12 = 1,
+ ACPI_STATE_S3I,
+ ACPI_STATE_S45
+};
+
+/* SWC & ACPI for SuperIO IOCTL */
+enum SIO_CMD {
+ SIO_GET_ACPI_STATE = 0,
+ SIO_GET_PWRGD_STATUS,
+ SIO_GET_ONCTL_STATUS,
+ SIO_SET_ONCTL_GPIO,
+ SIO_GET_PWRBTN_OVERRIDE,
+ SIO_GET_PFAIL_STATUS, /* Start from AC Loss */
+ SIO_SET_BMC_SCI_EVENT,
+
+ SIO_MAX_CMD
+};
+
+struct sio_ioctl_data {
+ unsigned short sio_cmd;
+ unsigned short param;
+ unsigned int data;
+};
+
+#define SIO_IOC_BASE 'P'
+#define SIO_IOC_COMMAND _IOWR(SIO_IOC_BASE, 1, struct sio_ioctl_data)
+
+/***********************************************************************************/
+
+#define MAX_MAILBOX_NUM 16
+
+/***********************************************************************************/
+
+#endif
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/lpc-cmds.bb b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/lpc-cmds.bb
new file mode 100644
index 000000000..38489263b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/lpc-cmds.bb
@@ -0,0 +1,16 @@
+SUMMARY = "LPC tools"
+DESCRIPTION = "command tool for LPC interface test on the BMC"
+
+inherit cmake
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRC_URI = "\
+ file://CMakeLists.txt \
+ file://lpc_drv.h \
+ file://lpc_cmds.c \
+ "
+
+S = "${WORKDIR}"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit/0001-Force-nbdkit-to-send-PATCH-as-upload-method.patch b/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit/0001-Force-nbdkit-to-send-PATCH-as-upload-method.patch
new file mode 100644
index 000000000..83f015a76
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit/0001-Force-nbdkit-to-send-PATCH-as-upload-method.patch
@@ -0,0 +1,71 @@
+From ad236d3f04cb2547fea33d72aeeb695ce3035bba Mon Sep 17 00:00:00 2001
+From: Iwona Winiarska <iwona.winiarska@intel.com>
+Date: Mon, 9 Dec 2019 01:58:15 +0100
+Subject: [PATCH] Force nbdkit to send PATCH as upload method
+
+This modifies pwrite to send PATCH rather than default upload method
+used by curl.
+
+FIXME: This patch only works around lack of PATCH method support in curl.
+It's just a hack and it should be removed if/when proper PATCH support
+is implemented in curl.
+
+We've added it to nbdkit rather than curl, because currently PATCH
+support is unlikely to be accepted in upstream curl and it is easier to
+maintain this patch in nbdkit.
+
+Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
+---
+ plugins/curl/curl.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/plugins/curl/curl.c b/plugins/curl/curl.c
+index 0ed3984..804ad78 100644
+--- a/plugins/curl/curl.c
++++ b/plugins/curl/curl.c
+@@ -525,6 +525,7 @@ static int
+ curl_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset)
+ {
+ struct curl_handle *h = handle;
++ struct curl_slist *list = NULL;
+ CURLcode r;
+ char range[128];
+
+@@ -535,15 +536,21 @@ curl_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset)
+ h->read_count = count;
+
+ curl_easy_setopt (h->c, CURLOPT_UPLOAD, 1);
++ curl_easy_setopt (h->c, CURLOPT_CUSTOMREQUEST, "PATCH");
+
+ /* Make an HTTP range request. */
+- snprintf (range, sizeof range, "%" PRIu64 "-%" PRIu64,
++ snprintf (range, sizeof range, "Range: bytes=%" PRIu64 "-%" PRIu64,
+ offset, offset + count);
+- curl_easy_setopt (h->c, CURLOPT_RANGE, range);
++ list = curl_slist_append(list, range);
++ curl_easy_setopt(h->c, CURLOPT_HTTPHEADER, list);
+
+ /* The assumption here is that curl will look after timeouts. */
+ r = curl_easy_perform (h->c);
+ if (r != CURLE_OK) {
++ curl_easy_setopt (h->c, CURLOPT_RANGE, NULL);
++ curl_easy_setopt(h->c, CURLOPT_HTTPHEADER, NULL);
++ curl_slist_free_all(list);
++ curl_easy_setopt (h->c, CURLOPT_CUSTOMREQUEST, NULL);
+ display_curl_error (h, r, "pwrite: curl_easy_perform");
+ return -1;
+ }
+@@ -554,6 +561,10 @@ curl_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset)
+
+ /* As far as I understand the cURL API, this should never happen. */
+ assert (h->read_count == 0);
++ curl_easy_setopt (h->c, CURLOPT_RANGE, NULL);
++ curl_easy_setopt(h->c, CURLOPT_HTTPHEADER, NULL);
++ curl_slist_free_all(list);
++ curl_easy_setopt (h->c, CURLOPT_CUSTOMREQUEST, NULL);
+
+ return 0;
+ }
+--
+2.21.0
+
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit_git.bb b/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit_git.bb
new file mode 100644
index 000000000..207a8ede3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/nbdkit/nbdkit_git.bb
@@ -0,0 +1,35 @@
+SUMMARY = "nbdkit is a toolkit for creating NBD servers."
+DESCRIPTION = "NBD — Network Block Device — is a protocol \
+for accessing Block Devices (hard disks and disk-like things) \
+over a Network. \
+\
+nbdkit is a toolkit for creating NBD servers."
+
+HOMEPAGE = "https://github.com/libguestfs/nbdkit"
+LICENSE = "BSD"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=4332a97808994cf2133a65b6c6f33eaf"
+
+SRC_URI = "git://github.com/libguestfs/nbdkit.git;protocol=https"
+SRC_URI += "file://0001-Force-nbdkit-to-send-PATCH-as-upload-method.patch"
+
+PV = "1.17.5+git${SRCPV}"
+SRCREV = "c8406880c6603bb617dae131dd0a8826c05869ca"
+
+S = "${WORKDIR}/git"
+
+DEPENDS = "curl xz e2fsprogs zlib"
+
+inherit pkgconfig python3native perlnative pythonnative autotools
+inherit autotools-brokensep
+
+# Specify any options you want to pass to the configure script using EXTRA_OECONF:
+EXTRA_OECONF = "--disable-python --disable-perl --disable-ocaml \
+ --disable-rust --disable-ruby --disable-tcl \
+ --disable-lua --disable-vddk --without-libvirt \
+ --without-libguestfs"
+
+do_install_append() {
+ rm -f ${D}/usr/share/bash-completion/completions/nbdkit
+ rmdir ${D}/usr/share/bash-completion/completions
+ rmdir ${D}/usr/share/bash-completion
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/files/peci-hwmon-test.py b/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/files/peci-hwmon-test.py
new file mode 100755
index 000000000..977fcd3a0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/files/peci-hwmon-test.py
@@ -0,0 +1,144 @@
+#!/usr/bin/python
+
+import glob
+import os
+import sys
+import time
+
+if len(sys.argv) == 1:
+ cpuno = 0
+else:
+ cpuno = int(sys.argv[1])
+
+hwmon_path = '/sys/class/hwmon'
+cputemp_name_match = '{}{}'.format('peci_cputemp.cpu', cpuno)
+dimmtemp_name_match = '{}{}'.format('peci_dimmtemp.cpu', cpuno)
+
+dimmtemp_path = ''
+
+os.chdir(hwmon_path)
+
+for dirpath, dirnames, files in os.walk(hwmon_path):
+ for d in dirnames:
+ try:
+ with open('{}/{}'.format(d, 'name')) as f:
+ hwmon_name = f.read().strip()
+ if hwmon_name == cputemp_name_match:
+ cputemp_path = os.path.abspath(d)
+ cputemp_name = hwmon_name
+ elif hwmon_name == dimmtemp_name_match:
+ dimmtemp_path = os.path.abspath(d)
+ dimmtemp_name = hwmon_name
+ except:
+ continue
+
+if not cputemp_path:
+ print "Can't find the " + cputemp_name_match
+ quit()
+
+try:
+ while True:
+ os.system('clear')
+ os.chdir(cputemp_path)
+
+ print '{}/{}: {}'.format(hwmon_path, cputemp_path, cputemp_name)
+ if dimmtemp_path:
+ print '{}/{}: {}'.format(hwmon_path, dimmtemp_path, dimmtemp_name)
+
+ print
+ print 'Package temperature'
+ for input in glob.glob('temp[1-5]_input'):
+ try:
+ with open(input) as f:
+ val = f.read().strip()
+ except IOError:
+ val = 0
+ try:
+ with open(input.replace('input', 'label')) as l:
+ name = l.read().strip()
+ except IOError:
+ name = ''
+ print '{:11s}:{:3d}.{:03d}'.format(
+ name, (int(val) / 1000), (int(val) % 1000))
+
+ print
+ print 'Core temperature'
+ count = 0
+ for input in glob.glob('temp[!1-5]_input'):
+ try:
+ with open(input) as f:
+ val = f.read().strip()
+ except IOError:
+ val = 0
+ try:
+ with open(input.replace('input', 'label')) as l:
+ name = l.read().strip()
+ except IOError:
+ name = ''
+ print ('{:9s}:{:3d}.{:03d}'.format(
+ name, (int(val) / 1000), (int(val) % 1000))),
+ count += 1
+ if count % 3 == 0:
+ print
+ else:
+ print ('\t'),
+ for input in glob.glob('temp??_input'):
+ try:
+ with open(input) as f:
+ val = f.read().strip()
+ except IOError:
+ val = 0
+ try:
+ with open(input.replace('input', 'label')) as l:
+ name = l.read().strip()
+ except IOError:
+ name = ''
+ print ('{:9s}:{:3d}.{:03d}'.format(
+ name, (int(val) / 1000), (int(val) % 1000))),
+ count += 1
+ if count % 3 == 0:
+ print
+ else:
+ print ('\t'),
+ print
+
+ if dimmtemp_path:
+ os.chdir(dimmtemp_path)
+ print
+ print 'DIMM temperature'
+ count = 0
+ for input in glob.glob('temp*_input'):
+ try:
+ with open(input) as f:
+ val = f.read().strip()
+ except IOError:
+ val = 0
+ try:
+ with open(input.replace('input', 'label')) as l:
+ name = l.read().strip()
+ except IOError:
+ name = ''
+ print ('{:9s}:{:3d}.{:03d}'.format(
+ name, (int(val) / 1000), (int(val) % 1000))),
+ count += 1
+ if count % 3 == 0:
+ print
+ else:
+ print ('\t'),
+ print
+ else:
+ os.chdir(hwmon_path)
+ for dirpath, dirnames, files in os.walk(hwmon_path):
+ for d in dirnames:
+ try:
+ with open('{}/{}'.format(d, 'name')) as f:
+ hwmon_name = f.read().strip()
+ if hwmon_name == dimmtemp_name_match:
+ dimmtemp_path = os.path.abspath(d)
+ dimmtemp_name = hwmon_name
+ except:
+ continue
+
+ time.sleep(1)
+except KeyboardInterrupt:
+ print " exiting..."
diff --git a/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/peci-hwmon-test.bb b/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/peci-hwmon-test.bb
new file mode 100644
index 000000000..b3b4096a6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/peci-hwmon-test/peci-hwmon-test.bb
@@ -0,0 +1,20 @@
+SUMMARY = "PECI hwmon test tool"
+DESCRIPTION = "command line python tool for testing PECI hwmon"
+
+SRC_URI = "\
+ file://peci-hwmon-test.py \
+ "
+LICENSE = "CLOSED"
+
+RDEPENDS_${PN} += "python"
+
+S = "${WORKDIR}"
+
+do_compile () {
+}
+
+do_install () {
+ install -d ${D}/${bindir}
+ install -m 0755 ${WORKDIR}/peci-hwmon-test.py ${D}/${bindir}
+}
+
diff --git a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
new file mode 100755
index 000000000..600f9e25f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
@@ -0,0 +1,3 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/x86-power-control.git;protocol=ssh"
+SRCREV = "35aa665e01cf9d735ba4aeb3818a60caab376692"
diff --git a/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample b/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
new file mode 100644
index 000000000..d0d291a92
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
@@ -0,0 +1,25 @@
+# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
+# changes incompatibly
+LCONF_VERSION = "11"
+
+BBPATH = "${TOPDIR}"
+BBFILES ?= ""
+
+BBLAYERS ?= " \
+ ##OEROOT##/meta \
+ ##OEROOT##/meta-poky \
+ ##OEROOT##/meta-openembedded/meta-oe \
+ ##OEROOT##/meta-openembedded/meta-networking \
+ ##OEROOT##/meta-openembedded/meta-perl \
+ ##OEROOT##/meta-openembedded/meta-python \
+ ##OEROOT##/meta-phosphor \
+ ##OEROOT##/meta-aspeed \
+ ##OEROOT##/meta-x86 \
+ ##OEROOT##/meta-openbmc-mods \
+ ##OEROOT##/meta-intel \
+ ##OEROOT##/meta-openbmc-mods/meta-common \
+ ##OEROOT##/meta-openbmc-mods/meta-common-small \
+ ##OEROOT##/meta-openbmc-mods/meta-ast2500 \
+ ##OEROOT##/meta-openbmc-mods/meta-wht \
+ ##OEROOT##/meta-security \
+ "
diff --git a/meta-openbmc-mods/meta-wht/conf/conf-notes.txt b/meta-openbmc-mods/meta-wht/conf/conf-notes.txt
new file mode 100644
index 000000000..91059a72d
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/conf-notes.txt
@@ -0,0 +1,6 @@
+Common targets are:
+ intel-platforms
+ obmc-phosphor-image
+ qemu-helper-native
+ virtual/kernel
+ phosphor-ipmi-host
diff --git a/meta-openbmc-mods/meta-wht/conf/layer.conf b/meta-openbmc-mods/meta-wht/conf/layer.conf
new file mode 100644
index 000000000..3c2354e62
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/layer.conf
@@ -0,0 +1,14 @@
+LOCALCONF_VERSION = "5"
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "wht"
+BBFILE_PATTERN_wht = ""
+BBFILE_PRIORITY_wht = "7"
+LAYERSERIES_COMPAT_wht = "warrior zeus"
+
+PRODUCT_GENERATION = "wht"
diff --git a/meta-openbmc-mods/meta-wht/conf/local.conf.sample b/meta-openbmc-mods/meta-wht/conf/local.conf.sample
new file mode 100644
index 000000000..7d53790cf
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/local.conf.sample
@@ -0,0 +1,32 @@
+MACHINE ??= "intel-ast2500"
+#DL_DIR ?= "/~YoctoDownloads"
+#SSTATE_DIR ?= "/~YoctoSstate-cache"
+DISTRO ?= "openbmc-phosphor"
+PACKAGE_CLASSES ?= "package_rpm"
+SANITY_TESTED_DISTROS_append ?= " RedHatEnterpriseWorkstation-6.*"
+EXTRA_IMAGE_FEATURES = "validation-unsecure"
+# Uncomment the following line to enable debug features / default user account.
+#EXTRA_IMAGE_FEATURES += "debug-tweaks"
+USER_CLASSES ?= "buildstats image-mklibs image-prelink"
+PATCHRESOLVE = "noop"
+
+# PFR image Build
+# Before exporting the conf, please uncomment the below line
+# for building Intel PFR compliant images.
+#IMAGE_FSTYPES += "intel-pfr"
+
+BB_DISKMON_DIRS = "\
+ STOPTASKS,${TMPDIR},1G,100K \
+ STOPTASKS,${DL_DIR},1G,100K \
+ STOPTASKS,${SSTATE_DIR},1G,100K \
+ STOPTASKS,/tmp,100M,100K \
+ ABORT,${TMPDIR},100M,1K \
+ ABORT,${DL_DIR},100M,1K \
+ ABORT,${SSTATE_DIR},100M,1K \
+ ABORT,/tmp,10M,1K"
+CONF_VERSION = "5"
+#BB_NUMBER_THREADS = "70"
+
+FULL_OPTIMIZATION = "-Os -pipe ${DEBUG_FLAGS}"
+require conf/distro/include/security_flags.inc
+
diff --git a/meta-openbmc-mods/meta-wht/conf/machine/intel-ast2500.conf b/meta-openbmc-mods/meta-wht/conf/machine/intel-ast2500.conf
new file mode 100644
index 000000000..907b9f1e1
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/machine/intel-ast2500.conf
@@ -0,0 +1 @@
+require conf/machine/include/intel-ast2500.inc
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample b/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample
new file mode 100644
index 000000000..27d0d5fa4
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample
@@ -0,0 +1,25 @@
+# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
+# changes incompatibly
+LCONF_VERSION = "11"
+
+BBPATH = "${TOPDIR}"
+BBFILES ?= ""
+
+BBLAYERS ?= " \
+ ##OEROOT##/meta \
+ ##OEROOT##/meta-poky \
+ ##OEROOT##/meta-openembedded/meta-oe \
+ ##OEROOT##/meta-openembedded/meta-networking \
+ ##OEROOT##/meta-openembedded/meta-perl \
+ ##OEROOT##/meta-openembedded/meta-python \
+ ##OEROOT##/meta-phosphor \
+ ##OEROOT##/meta-aspeed \
+ ##OEROOT##/meta-x86 \
+ ##OEROOT##/meta-openbmc-mods \
+ ##OEROOT##/meta-intel \
+ ##OEROOT##/meta-openbmc-mods/meta-common \
+ ##OEROOT##/meta-openbmc-mods/meta-common-small \
+ ##OEROOT##/meta-openbmc-mods/meta-ast2500 \
+ ##OEROOT##/meta-openbmc-mods/meta-wolfpass \
+ ##OEROOT##/meta-security \
+ "
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/conf-notes.txt b/meta-openbmc-mods/meta-wolfpass/conf/conf-notes.txt
new file mode 100644
index 000000000..91059a72d
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/conf-notes.txt
@@ -0,0 +1,6 @@
+Common targets are:
+ intel-platforms
+ obmc-phosphor-image
+ qemu-helper-native
+ virtual/kernel
+ phosphor-ipmi-host
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/layer.conf b/meta-openbmc-mods/meta-wolfpass/conf/layer.conf
new file mode 100644
index 000000000..acfeed4e2
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/layer.conf
@@ -0,0 +1,14 @@
+LOCALCONF_VERSION = "4"
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "wolfpass"
+BBFILE_PATTERN_wolfpass = ""
+BBFILE_PRIORITY_wolfpass = "7"
+LAYERSERIES_COMPAT_wolfpass = "warrior zeus"
+
+PRODUCT_GENERATION = "prl"
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample b/meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample
new file mode 100644
index 000000000..d20f54810
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample
@@ -0,0 +1,25 @@
+MACHINE ??= "intel-ast2500"
+#DL_DIR ?= "/~YoctoDownloads"
+#SSTATE_DIR ?= "/~YoctoSstate-cache"
+DISTRO ?= "openbmc-phosphor"
+PACKAGE_CLASSES ?= "package_rpm"
+SANITY_TESTED_DISTROS_append ?= " RedHatEnterpriseWorkstation-6.*"
+EXTRA_IMAGE_FEATURES = "validation-unsecure"
+# Uncomment the following line to enable debug features / default user account.
+#EXTRA_IMAGE_FEATURES += "debug-tweaks"
+USER_CLASSES ?= "buildstats image-mklibs image-prelink"
+PATCHRESOLVE = "noop"
+BB_DISKMON_DIRS = "\
+ STOPTASKS,${TMPDIR},1G,100K \
+ STOPTASKS,${DL_DIR},1G,100K \
+ STOPTASKS,${SSTATE_DIR},1G,100K \
+ STOPTASKS,/tmp,100M,100K \
+ ABORT,${TMPDIR},100M,1K \
+ ABORT,${DL_DIR},100M,1K \
+ ABORT,${SSTATE_DIR},100M,1K \
+ ABORT,/tmp,10M,1K"
+CONF_VERSION = "4"
+#BB_NUMBER_THREADS = "70"
+
+FULL_OPTIMIZATION = "-Os -pipe ${DEBUG_FLAGS}"
+require conf/distro/include/security_flags.inc
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/machine/intel-ast2500.conf b/meta-openbmc-mods/meta-wolfpass/conf/machine/intel-ast2500.conf
new file mode 100644
index 000000000..907b9f1e1
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/machine/intel-ast2500.conf
@@ -0,0 +1 @@
+require conf/machine/include/intel-ast2500.inc