summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods')
-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.inc25
-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.conf21
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc19
-rw-r--r--meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc31
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-platforms.patch414
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch121
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch70
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0004-Test-code-for-LPC-MBOX.patch112
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch30
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch80
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg67
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend9
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json1355
-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/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.json1830
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json2048
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json2034
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend15
-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_%.bbappend8
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed.bb20
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/fan-default-speed.service10
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/set_fan_speeds.py23
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru.bb27
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600CYP.fru.binbin0 -> 513 bytes
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600TNP.fru.binbin0 -> 512 bytes
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WC.fru.binbin0 -> 511 bytes
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WFT.fru.binbin0 -> 512 bytes
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WP.fru.binbin0 -> 512 bytes
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/SetBaseboardFru.service9
-rwxr-xr-xmeta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/checkFru.sh38
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes-phosphor/workbook/wolfpass-config.bb10
-rw-r--r--meta-openbmc-mods/meta-ast2500/recipes.txt2
-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/COPYING.MIT17
-rw-r--r--meta-openbmc-mods/meta-common/README64
-rw-r--r--meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass77
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass555
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass40
-rw-r--r--meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-dev.bbclass7
-rw-r--r--meta-openbmc-mods/meta-common/conf/layer.conf11
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch424
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch42
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch75
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch389
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0007-Add-espi-support.patch330
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch160
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch414
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch98
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch160
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch144
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch132
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch91
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch114
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch121
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch38
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch108
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch613
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch35
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch332
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch121
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch1520
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch300
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch61
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch1271
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service13
-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/crashdump/crashdump_git.bb27
-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/fw-update/files/fwupd.sh116
-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/ipmi/intel-ipmi-oem_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb32
-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/os-release/os-release.bbappend34
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc78
-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/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/000-ro-rootfs-tmpfile-defaults.patch51
-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/systemd-time-wait-sync.service36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-timesyncd.service53
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend16
-rw-r--r--meta-openbmc-mods/meta-common/recipes-devtools/dtoverlay/dtoverlay.bb31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb20
-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/rsyslog/rsyslog-policy.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy/rsyslog-override.conf2
-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.timer8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.conf62
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver/0001-rfbserver-add-a-hooking-function-to-deliver-rfbFrame.patch54
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Add-flow-control-to-prevent-buffer-over-run.patch119
-rw-r--r--meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb29
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend3
-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.bb33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch120
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch473
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch240
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch5395
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch426
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch620
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch597
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch392
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch93
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch142
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch132
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch556
-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.patch252
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch510
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch511
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch287
-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.patch140
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch125
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch235
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch166
-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/0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch35
-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.patch1294
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch108
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch309
-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/0058-i2c-aspeed-add-general-call-support.patch182
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0065-i2c-aspeed-fix-master-pending-state-handling.patch55
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0066-i2c-aspeed-add-buffer-mode-transfer-support.patch770
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg1
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend46
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers/0001-Enable-passthrough-based-gpio-character-device.patch26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers_%.bbappend5
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0002-IPv6-Network-changes-to-configuration-file.patch208
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch404
-rw-r--r--meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend9
-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-check78
-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/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch61
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch264
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch120
-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/0009-Add-host-restart-cause-property.patch98
-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/0014-Add-multiple-state-signal-for-host-start-and-stop.patch63
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch227
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch116
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0021-Add-interface-suppot-for-provisioning-modes.patch52
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0022-Add-chassis-power-cycle-and-reset-to-Chassis-State.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0023-Add-host-interrupt-to-the-Host-State.patch31
-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_%.bbappend22
-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/fwupd@.service8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend13
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb18
-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/bmcweb.socket9
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend17
-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/0002-Modify-dbus-interface-for-power-control.patch31
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch899
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0010-fix-get-system-GUID-ipmi-command.patch56
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch143
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch71
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch15
-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/0054-Fix-User-commands-require-channel-layer-lib.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch176
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0056-add-SetInProgress-to-get-set-boot-option-cmd.patch102
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch195
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0058-Add-AC-failed-bit-support-for-get-chassis-status-com.patch76
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch415
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch342
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0061-Use-xyz.openbmc_project.State.Chassis-for-IPMI-chass.patch127
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch214
-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.service26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend41
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend2
-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/0007-Adding-support-for-GetSessionInfo-command.patch418
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch282
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0009-Add-dbus-interface-for-sol-commands.patch311
-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_%.bbappend29
-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/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/logging/phosphor-logging_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb15
-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/init203
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend7
-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_%.bbappend7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml209
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.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.bb28
-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/0001-Modify-dbus-interface-for-power-control.patch38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch338
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch71
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch141
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch499
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb34
-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.patch1648
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend9
-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-Add-redfish-log-support-for-IPMI-watchdog-timeout-ac.patch51
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0002-Add-restart-cause-support.patch82
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0003-Add-redfish-log-support-for-IPMI-watchdog-pre-timeou.patch48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog@.service12
-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.bb13
-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/webui/phosphor-webui/0004-Implement-force-boot-to-bios-in-server-power-control.patch199
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend6
-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/libgpiod/libgpiod/0001-Add-pass-through-setting-in-gpioset.patch266
-rw-r--r--meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod_%.bbappend7
-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.c665
-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.c501
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h78
-rw-r--r--meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/lpc-cmds.bb16
-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
-rw-r--r--meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample25
-rw-r--r--meta-openbmc-mods/meta-wht/conf/conf-notes.txt5
-rw-r--r--meta-openbmc-mods/meta-wht/conf/layer.conf14
-rw-r--r--meta-openbmc-mods/meta-wht/conf/local.conf.sample20
-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.txt5
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/layer.conf14
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample20
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/machine/intel-ast2500.conf1
338 files changed, 49111 insertions, 0 deletions
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..35c801089
--- /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"
+
+IMAGE_FEATURES[validitems] += "tools-sdk tools-debug"
+
+# static userid assignments
+USERADDEXTENSION = "useradd-staticids"
+USERADD_UID_TABLES = "files/passwd"
+USERADD_GID_TABLES = "files/group"
+
+LAYER_CONF_VERSION = "10"
+
+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..588a71bbf
--- /dev/null
+++ b/meta-openbmc-mods/conf/machine/include/intel.inc
@@ -0,0 +1,25 @@
+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 = "intel-chassis-control"
+VIRTUAL-RUNTIME_obmc-chassis-state-manager = "intel-chassis-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"
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..99ca15d28
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/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 += "ast2500"
+BBFILE_PATTERN_ast2500 = ""
+BBFILE_PRIORITY_ast2500 = "6"
+LAYERSERIES_COMPAT_ast2500 = "warrior"
+
+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-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..cc9e30495
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/conf/machine/include/intel-ast2500.inc
@@ -0,0 +1,19 @@
+KMACHINE = "aspeed"
+KERNEL_DEVICETREE = "${KMACHINE}-bmc-intel-purley.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
+
+UBOOT_MACHINE = "ast_g5_phy_config"
+
+#Developer to specify the appropriate IMAGE_TYPE and FLASH_SIZE
+#On Intel Whitley platforms PFR feature requires 128MB flash, default is 64MB
+#IMAGE_TYPE = "default" or "pfr" or "non-pfr"
+# "non-pfr" setting for future which is for BMC secure boot
+#for PFR its 128MB in KBs - 128*1024=131072, for non-pfr its 64MB= 64*1024 = 65536
+#pfr IMAGE_TYPE enforces the image signature verification during the image update
+IMAGE_TYPE = "default"
+
+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..24ec3113b
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/conf/machine/include/obmc-bsp-si-common.inc
@@ -0,0 +1,31 @@
+#@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"
+
+INITRAMFS_CTYPE ?= "lzma"
+INITRAMFS_IMAGE = "obmc-phosphor-initramfs"
+
+MACHINE_FEATURES_BACKFILL_CONSIDERED = "qemu-usermode"
+
+KERNEL_IMAGETYPES += "zImage"
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-platforms.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-platforms.patch
new file mode 100644
index 000000000..88a9c5624
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-platforms.patch
@@ -0,0 +1,414 @@
+From fbbad6c3a18ec7f1e9d95c09e44e765de303329c 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 platforms
+
+Add the DTS file for Intel 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>
+---
+ arch/arm/boot/dts/aspeed-bmc-intel-purley.dts | 388 ++++++++++++++++++++++++++
+ 1 file changed, 388 insertions(+)
+ create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+new file mode 100644
+index 0000000..421699c
+--- /dev/null
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+@@ -0,0 +1,388 @@
++/dts-v1/;
++
++#include "aspeed-g5.dtsi"
++#include <dt-bindings/gpio/aspeed-gpio.h>
++#include <dt-bindings/i2c/i2c.h>
++
++/ {
++ model = "Purley BMC";
++ compatible = "intel,purley-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;
++ };
++ };
++
++ 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 = "off";
++ 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 5 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";
++};
++
++&syscon {
++ uart-clock-high-speed;
++ status = "okay";
++};
++
++&adc {
++ status = "okay";
++};
++
++&gpio {
++ status = "okay";
++ gpio-line-names =
++ /*A0-A7*/ "","","","","","","","",
++ /*B0-B7*/ "","","","","","","","",
++ /*C0-C7*/ "","","","","","","","",
++ /*D0-D7*/ "","","","","","","","",
++ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","","","",
++ /*F0-F7*/ "","","","","CPU_ERR0","CPU_ERR1","","",
++ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","","","","","","",
++ /*H0-H7*/ "","","","","","","","",
++ /*I0-I7*/ "","","","","","","","",
++ /*J0-J7*/ "","","","","","","","",
++ /*K0-K7*/ "","","","","","","","",
++ /*L0-L7*/ "","","","","","","","",
++ /*M0-M7*/ "","","","","","","","",
++ /*N0-N7*/ "","","","","","","","",
++ /*O0-O7*/ "","","","","","","","",
++ /*P0-P7*/ "","","","","","","","",
++ /*Q0-Q7*/ "","","","","","","","",
++ /*R0-R7*/ "","","","","","","","",
++ /*S0-S7*/ "","","","","","","","",
++ /*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*/ "","","","","","","","POST_COMPLETE",
++ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","",
++ /*AC0-AC7*/ "","","","","","","","";
++};
++
++&kcs3 {
++ kcs_addr = <0xCA2>;
++ status = "okay";
++};
++
++&kcs4 {
++ kcs_addr = <0xCA4>;
++ status = "okay";
++};
++
++&lpc_sio {
++ status = "okay";
++};
++
++&lpc_snoop {
++ snoop-ports = <0x80>;
++ status = "okay";
++};
++
++&mbox {
++ 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";
++ * };
++ *};
++ */
++
++&sgpio {
++ 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;
++ status = "okay";
++
++ ipmb0@10 {
++ compatible = "slave-mqueue";
++ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
++ };
++};
++
++&i2c1 {
++ multi-master;
++ status = "okay";
++};
++
++&i2c2 {
++ multi-master;
++ status = "okay";
++};
++
++&i2c3 {
++ multi-master;
++ status = "okay";
++};
++
++&i2c4 {
++ multi-master;
++ status = "okay";
++
++ hsbp0@10 {
++ compatible = "slave-mqueue";
++ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
++ };
++};
++
++&i2c5 {
++ bus-frequency = <1000000>;
++ multi-master;
++ status = "okay";
++
++ smlink0@10 {
++ compatible = "slave-mqueue";
++ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
++ };
++};
++
++&i2c6 {
++ multi-master;
++ status = "okay";
++};
++
++&i2c7 {
++ multi-master;
++ #retries = <3>;
++ status = "okay";
++};
++
++&i2c9 {
++ multi-master;
++ status = "okay";
++};
++
++&i2c13 {
++ multi-master;
++ 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 = <5>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_timer5_default>;
++ #pwm-cells = <3>;
++ status = "okay";
++};
++
++&video {
++ status = "okay";
++ memory-region = <&video_engine_memory>;
++};
++
++&vhub {
++ status = "okay";
++};
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch
new file mode 100644
index 000000000..b05ad2502
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch
@@ -0,0 +1,121 @@
+From 9537923d6e6a793cb2bf3c1daacd12562263bc0a 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 | 1 +
+ drivers/pinctrl/aspeed/pinctrl-aspeed.c | 60 ++++++++++++++++++++++++++++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed.h | 3 ++
+ 3 files changed, 64 insertions(+)
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+index 187abd7..beb0729 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+@@ -2498,6 +2498,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_gpio_disable_free,
+ .strict = true,
+ };
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+index eb87ab7..f06d752 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+@@ -538,6 +538,66 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
+ return aspeed_sig_expr_enable(expr, pdata->maps);
+ }
+
++void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev,
++ struct pinctrl_gpio_range *range,
++ unsigned int offset)
++{
++ const 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 we're freeing GPIOE1 (33) or GPIOE3 (35) then re-enable the
++ * pass-through mux setting; otherwise, do nothing.
++ */
++ if (offset != 33 && offset != 35)
++ return;
++
++ dev_dbg(pctldev->dev,
++ "Freeing pass-through pin %s (%d). Re-enabling pass-through.\n",
++ pdesc->name, offset);
++
++ if (!pdesc)
++ return;
++
++ 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(funcs, pdata->maps);
++ 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(expr, pdata->maps);
++}
++
+ 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 d4d7f03..0037b11 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+@@ -595,6 +595,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-ast2500/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch
new file mode 100644
index 000000000..1d26b9667
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch
@@ -0,0 +1,70 @@
+From d26dd7c4ef1a2cb88440420deccc54eb88129c60 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-purley.dts | 4 ++++
+ drivers/gpio/gpio-aspeed.c | 10 ++++++++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+index 45556ac..051e927 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+@@ -124,6 +124,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-A8*/ "","","","","","","","",
+ /*B0-B8*/ "","","","","","","","",
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 2175070..f47d139 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -1157,6 +1157,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ const struct of_device_id *gpio_id;
+ struct aspeed_gpio *gpio;
+ struct resource *res;
++ struct pinctrl *pinctrl;
+ int rc, i, banks;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+@@ -1205,6 +1206,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 E0 and E2. 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 (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-ast2500/recipes-kernel/linux/linux-aspeed/0004-Test-code-for-LPC-MBOX.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0004-Test-code-for-LPC-MBOX.patch
new file mode 100644
index 000000000..dbb163d20
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0004-Test-code-for-LPC-MBOX.patch
@@ -0,0 +1,112 @@
+From 2f3587cf9e44f261fe74413ef6a54467686c910b Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 20 Nov 2018 15:49:15 -0800
+Subject: [PATCH] Test code for LPC MBOX
+
+Blocked interrupt driven code for test.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/misc/aspeed-lpc-mbox.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/misc/aspeed-lpc-mbox.c b/drivers/misc/aspeed-lpc-mbox.c
+index 0f0c711bafee..0933e0553953 100644
+--- a/drivers/misc/aspeed-lpc-mbox.c
++++ b/drivers/misc/aspeed-lpc-mbox.c
+@@ -19,6 +19,8 @@
+
+ #define DEVICE_NAME "aspeed-mbox"
+
++#define MBX_USE_INTERRUPT 0
++
+ #define ASPEED_MBOX_NUM_REGS 16
+
+ #define ASPEED_MBOX_DATA_0 0x00
+@@ -79,12 +81,14 @@ static int aspeed_mbox_open(struct inode *inode, struct file *file)
+ struct aspeed_mbox *mbox = file_mbox(file);
+
+ 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;
+ }
+
+@@ -106,6 +110,7 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ 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))
+@@ -115,6 +120,7 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ ASPEED_MBOX_CTRL_RECV)) {
+ return -ERESTARTSYS;
+ }
++#endif
+
+ mutex_lock(&mbox->mutex);
+
+@@ -129,8 +135,10 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf,
+ 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:
+@@ -180,7 +188,9 @@ static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait)
+
+ 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;
+@@ -206,6 +216,7 @@ static irqreturn_t aspeed_mbox_irq(int irq, void *arg)
+ {
+ struct aspeed_mbox *mbox = arg;
+
++#if MBX_USE_INTERRUPT
+ if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV))
+ return IRQ_NONE;
+
+@@ -216,6 +227,7 @@ static irqreturn_t aspeed_mbox_irq(int irq, void *arg)
+
+ /* Mask it off, we'll clear it when we the data gets read */
+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_MASK, ASPEED_MBOX_BMC_CTRL);
++#endif
+
+ wake_up(&mbox->queue);
+ return IRQ_HANDLED;
+@@ -248,7 +260,14 @@ static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox,
+ 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);
++ aspeed_mbox_outb(mbox, aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) | ASPEED_MBOX_CTRL_MASK, ASPEED_MBOX_BMC_CTRL);
++
++ /*
++ * Because mailbox data register init value is random, need to give a
++ * init value to mailbox data register.
++ */
++ aspeed_mbox_outb(mbox, 0x00, ASPEED_MBOX_DATA_0);
++
+ return 0;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch
new file mode 100644
index 000000000..03b4f4da4
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0005-128MB-flashmap-for-PFR.patch
@@ -0,0 +1,30 @@
+From ddfbe1364c6ecf77f06990e6550dfe5a3791e6bf Mon Sep 17 00:00:00 2001
+From: Vikram Bodireddy <vikram.bodireddy@intel.com>
+Date: Wed, 6 Feb 2019 15:59:34 +0530
+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>
+---
+ arch/arm/boot/dts/aspeed-bmc-intel-purley.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+index 8aba46cdce46..6959a06d04e2 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+@@ -90,7 +90,7 @@
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+-#include "openbmc-flash-layout-intel-64MB.dtsi"
++#include "openbmc-flash-layout-intel-128MB.dtsi"
+ };
+ };
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch
new file mode 100644
index 000000000..d3b850efe
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch
@@ -0,0 +1,80 @@
+From 2e834ae04eba975066f80102c6f4656da314ca1e 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 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+index beb0729..05d1081 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+@@ -250,7 +250,7 @@ FUNC_GROUP_DECL(SD2, F19, E21, F20, D20, D21, E20, G18, C21);
+
+ #define B20 32
+ SIG_EXPR_LIST_DECL_SINGLE(NCTS3, NCTS3, SIG_DESC_SET(SCU80, 16));
+-SIG_EXPR_DECL(GPIE0IN, GPIE0, GPIE0_DESC);
++SIG_EXPR_DECL(GPIE0IN, GPIE0);
+ SIG_EXPR_DECL(GPIE0IN, GPIE, GPIE_DESC);
+ SIG_EXPR_LIST_DECL_DUAL(GPIE0IN, GPIE0, GPIE);
+ MS_PIN_DECL(B20, GPIOE0, NCTS3, GPIE0IN);
+@@ -270,7 +270,7 @@ FUNC_GROUP_DECL(GPIE0, B20, C20);
+
+ #define F18 34
+ SIG_EXPR_LIST_DECL_SINGLE(NDSR3, NDSR3, SIG_DESC_SET(SCU80, 18));
+-SIG_EXPR_DECL(GPIE2IN, GPIE2, GPIE2_DESC);
++SIG_EXPR_DECL(GPIE2IN, GPIE2);
+ SIG_EXPR_DECL(GPIE2IN, GPIE, GPIE_DESC);
+ SIG_EXPR_LIST_DECL_DUAL(GPIE2IN, GPIE2, GPIE);
+ MS_PIN_DECL(F18, GPIOE2, NDSR3, GPIE2IN);
+@@ -1349,7 +1349,7 @@ FUNC_GROUP_DECL(ADC15, H4);
+
+ #define R22 192
+ SIG_EXPR_DECL(SIOS3, SIOS3, SIG_DESC_SET(SCUA4, 8));
+-SIG_EXPR_DECL(SIOS3, ACPI, ACPI_DESC);
++SIG_EXPR_DECL(SIOS3, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(SIOS3, SIOS3, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(DASHR22, DASHR22, SIG_DESC_SET(SCU94, 10));
+ MS_PIN_DECL(R22, GPIOY0, SIOS3, DASHR22);
+@@ -1357,7 +1357,7 @@ FUNC_GROUP_DECL(SIOS3, R22);
+
+ #define R21 193
+ SIG_EXPR_DECL(SIOS5, SIOS5, SIG_DESC_SET(SCUA4, 9));
+-SIG_EXPR_DECL(SIOS5, ACPI, ACPI_DESC);
++SIG_EXPR_DECL(SIOS5, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(SIOS5, SIOS5, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(DASHR21, DASHR21, SIG_DESC_SET(SCU94, 10));
+ MS_PIN_DECL(R21, GPIOY1, SIOS5, DASHR21);
+@@ -1373,7 +1373,7 @@ FUNC_GROUP_DECL(SIOPWREQ, P22);
+
+ #define P21 195
+ SIG_EXPR_DECL(SIOONCTRL, SIOONCTRL, SIG_DESC_SET(SCUA4, 11));
+-SIG_EXPR_DECL(SIOONCTRL, ACPI, ACPI_DESC);
++SIG_EXPR_DECL(SIOONCTRL, ACPI);
+ SIG_EXPR_LIST_DECL_DUAL(SIOONCTRL, SIOONCTRL, ACPI);
+ SIG_EXPR_LIST_DECL_SINGLE(DASHP21, DASHP21, SIG_DESC_SET(SCU94, 11));
+ MS_PIN_DECL(P21, GPIOY3, SIOONCTRL, DASHP21);
+--
+2.7.4
+
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..155ba3ae4
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed/intel-ast2500.cfg
@@ -0,0 +1,67 @@
+CONFIG_HWMON=y
+CONFIG_SENSORS_ASPEED=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_OF_CONFIGFS=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_EEPROM=n
+CONFIG_I2C_SLAVE_MQUEUE=y
+CONFIG_I2C_SLAVE_MQUEUE_MESSAGE_SIZE=256
+CONFIG_I2C_SLAVE_MQUEUE_QUEUE_SIZE=32
+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_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
+
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..0ba716442
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/linux-aspeed:"
+SRC_URI += "file://intel-ast2500.cfg \
+ file://0001-arm-dts-add-DTS-for-Intel-platforms.patch \
+ file://0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch \
+ file://0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch \
+ file://0004-Test-code-for-LPC-MBOX.patch \
+ file://0006-Allow-monitoring-of-power-control-input-GPIOs.patch \
+ "
+SRC_URI += "${@bb.utils.contains('IMAGE_TYPE', 'pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}"
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..2bbaa0238
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/CYP-baseboard.json
@@ -0,0 +1,1355 @@
+{
+ "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"
+ },
+ {
+ "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"
+ },
+ {
+ "BindGpioIntrusion": "Chassis Intrusion GPIO",
+ "Class": "Gpio",
+ "Name": "Chassis Intrusion Sensor",
+ "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": 48,
+ "Name": "Cpu Err2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 49,
+ "Name": "Cpu Caterr",
+ "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": 143,
+ "Name": "Chassis Intrusion GPIO",
+ "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": 214,
+ "Name": "SMI Active",
+ "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": "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': '.*CYP'})",
+ "Type": "Board",
+ "ProductId": 152,
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ }
+}
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/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..39e101e77
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json
@@ -0,0 +1,1830 @@
+{
+ "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"
+ },
+ {
+ "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": 40,
+ "Name": "NMI Out",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 50,
+ "Name": "PCH Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 51,
+ "Name": "Lcp Enter Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 52,
+ "Name": "Lcp Left Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 53,
+ "Name": "Lcp Right Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 49,
+ "Name": "Cpu Caterr",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 48,
+ "Name": "Cpu Err2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 63,
+ "Name": "PU 240VA Status",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 208,
+ "Name": "P3v3bat BridgeEn",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 214,
+ "Name": "Nmi Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 218,
+ "Name": "ID Button",
+ "Polarity": "Low",
+ "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"
+ },
+ {
+ "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",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99
+ },
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99
+ },
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89
+ }
+ ],
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "TNP Baseboard",
+ "Probe": "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*TNP'})",
+ "ProductId": 153,
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ }
+} \ 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..ce98132d6
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WC-Baseboard.json
@@ -0,0 +1,2048 @@
+{
+ "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": 208,
+ "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"
+ },
+ {
+ "AlphaF": 4.352,
+ "AlphaS": 0.512,
+ "Name": "Exit Air Temp",
+ "PowerFactorMax": 1.0,
+ "PowerFactorMin": 0.4,
+ "QMax": 88,
+ "QMin": 15,
+ "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"
+ },
+ {
+ "AllowedFailures": 1,
+ "Name": "FanRedundancy",
+ "Type": "FanRedundancy"
+ },
+ {
+ "Direction": "Out",
+ "Index": 208,
+ "Name": "Bridge P3VBAT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 40,
+ "Name": "NMI Input",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 48,
+ "Name": "CPU ERR2",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 49,
+ "Name": "CPU CATERR",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "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,
+ 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"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 2,
+ "ChannelNames": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 2,
+ "ChannelNames": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "",
+ "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": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "PcieSlot3",
+ "PcieSlot4"
+ ],
+ "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": 60.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": 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": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "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": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "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": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "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": [
+ "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": 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": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "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": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "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": [
+ "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": 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": [
+ "VR 1 Temp"
+ ],
+ "Name": "VR 1 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"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "VR 2 Temp"
+ ],
+ "Name": "VR 2 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": [
+ "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": "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": "0x49",
+ "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": "0x4D",
+ "Bus": "0x1",
+ "Name": "Front Panel Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 55
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 50
+ },
+ {
+ "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": 232,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99,
+ "label": "DIMM"
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89,
+ "label": "DIMM"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": 242,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99,
+ "label": "DIMM"
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89,
+ "label": "DIMM"
+ }
+ ],
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "WC Baseboard",
+ "Probe": "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*WC'})",
+ "ProductId": 145,
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ }
+} \ 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..923924a0b
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager/WP-Baseboard.json
@@ -0,0 +1,2034 @@
+{
+ "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": 208,
+ "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"
+ },
+ {
+ "AlphaF": 4.352,
+ "AlphaS": 0.512,
+ "Name": "Exit Air Temp",
+ "PowerFactorMax": 1.0,
+ "PowerFactorMin": 0.4,
+ "QMax": 88,
+ "QMin": 15,
+ "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"
+ },
+ {
+ "AllowedFailures": 1,
+ "Name": "FanRedundancy",
+ "Type": "FanRedundancy"
+ },
+ {
+ "Direction": "Out",
+ "Index": 208,
+ "Name": "Bridge P3VBAT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 49,
+ "Name": "CPU CATERR",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "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,
+ 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"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2Slot1",
+ "M2Slot2"
+ ],
+ "Name": "M2 Mux",
+ "Type": "PCA9543Mux"
+ },
+ {
+ "Address": "0x72",
+ "Bus": 2,
+ "ChannelNames": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "",
+ "FruChannel"
+ ],
+ "Name": "Riser 1 Mux",
+ "Type": "PCA9545Mux"
+ },
+ {
+ "Address": "0x73",
+ "Bus": 2,
+ "ChannelNames": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "",
+ "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": [
+ "PcieSlot1",
+ "PcieSlot2",
+ "PcieSlot3",
+ "PcieSlot4"
+ ],
+ "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": 60.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": 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": [
+ "DIMM [ABC]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM ABC",
+ "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": [
+ "DIMM [DEF]\\d+ CPU1"
+ ],
+ "Name": "CPU1 DIMM DEF",
+ "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": [
+ "DIMM [ABC]\\d+ CPU2"
+ ],
+ "Name": "CPU2 DIMM ABC",
+ "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": [
+ "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": 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": [
+ "DTS CPU1"
+ ],
+ "Name": "DTS CPU1",
+ "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": [
+ "DTS CPU2"
+ ],
+ "Name": "DTS CPU2",
+ "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": [
+ "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": 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": [
+ "VR 1 Temp"
+ ],
+ "Name": "VR 1 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"
+ ]
+ },
+ {
+ "Class": "temp",
+ "FFGainCoefficient": 0.0,
+ "FFOffCoefficient": 0.0,
+ "ICoefficient": -1.0,
+ "ILimitMax": 100,
+ "ILimitMin": 30,
+ "Inputs": [
+ "VR 2 Temp"
+ ],
+ "Name": "VR 2 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": [
+ "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": "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": "0x49",
+ "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": "0x4D",
+ "Bus": "0x1",
+ "Name": "Front Panel Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 55
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 50
+ },
+ {
+ "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": 232,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99,
+ "label": "DIMM"
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89,
+ "label": "DIMM"
+ }
+ ],
+ "Type": "XeonCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 2,
+ "Name": "CPU 2",
+ "PresenceGpio": 242,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99,
+ "label": "DIMM"
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89,
+ "label": "DIMM"
+ }
+ ],
+ "Type": "XeonCPU"
+ }
+ ],
+ "Name": "WP Baseboard",
+ "Probe": "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*WP'})",
+ "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"
+ }
+}
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..b8b38ecff
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,15 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+SRC_URI_append = " 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://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-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..e808e4929
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/console/obmc-console_%.bbappend
@@ -0,0 +1,8 @@
+FILESEXTRAPATHS_prepend_intel-ast2500 := "${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-ast2500/recipes-phosphor/fans/fan-default-speed.bb b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed.bb
new file mode 100644
index 000000000..9c10c5b3d
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Set Wolfpass fan default speeds"
+DESCRIPTION = "Sets all fans to a single speed"
+
+inherit allarch
+inherit obmc-phosphor-systemd
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+RDEPENDS_${PN} += "python"
+
+S = "${WORKDIR}"
+SRC_URI += "file://set_fan_speeds.py"
+
+SYSTEMD_SERVICE_${PN} += "fan-default-speed.service"
+
+do_install() {
+ install -d ${D}/${bindir}
+ install -m 0755 ${WORKDIR}/set_fan_speeds.py ${D}/${bindir}/set_fan_speeds.py
+}
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/fan-default-speed.service b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/fan-default-speed.service
new file mode 100644
index 000000000..267fdee43
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/fan-default-speed.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Set fans to a default speed
+ConditionFileNotEmpty={bindir}/set_fan_speeds.py
+
+[Service]
+ExecStart={bindir}/set_fan_speeds.py 150
+Type=oneshot
+
+[Install]
+WantedBy=default.target
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/set_fan_speeds.py b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/set_fan_speeds.py
new file mode 100644
index 000000000..70ba64799
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fans/fan-default-speed/set_fan_speeds.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+import os
+import glob
+import time
+import sys
+
+HWMON_DIR = "/sys/class/hwmon/hwmon0"
+
+count = 0
+inputs = None
+while not inputs:
+ count += 1
+ if count > 20:
+ print("pwm missing!")
+ sys.exit(0)
+
+ inputs = glob.glob(os.path.join(HWMON_DIR, "pwm*"))
+ time.sleep(5)
+
+inputs = glob.glob(os.path.join(HWMON_DIR, "pwm*"))
+for pwm in inputs:
+ with open(pwm, 'w') as f:
+ f.write(sys.argv[1])
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru.bb b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru.bb
new file mode 100644
index 000000000..1ae1680e0
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru.bb
@@ -0,0 +1,27 @@
+SUMMARY = "Default Fru"
+DESCRIPTION = "Installs a default fru file to image"
+
+inherit systemd
+
+SYSTEMD_SERVICE_${PN} = "SetBaseboardFru.service"
+
+S = "${WORKDIR}"
+SRC_URI = "file://checkFru.sh \
+ file://SetBaseboardFru.service \
+ file://*.fru.bin"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+RDEPENDS_${PN} = "bash"
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/checkFru.sh ${D}/${bindir}/checkFru.sh
+
+ install -d ${D}${sysconfdir}/fru
+ cp ${S}/*.fru.bin ${D}/${sysconfdir}/fru
+
+ 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-ast2500/recipes-phosphor/fru/default-fru/S2600CYP.fru.bin b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600CYP.fru.bin
new file mode 100644
index 000000000..ba5b96392
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600CYP.fru.bin
Binary files differ
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin
new file mode 100644
index 000000000..afd58e6b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin
Binary files differ
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WC.fru.bin b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WC.fru.bin
new file mode 100644
index 000000000..76c4b8d4b
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WC.fru.bin
Binary files differ
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WFT.fru.bin b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WFT.fru.bin
new file mode 100644
index 000000000..1b9f97ff4
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WFT.fru.bin
Binary files differ
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WP.fru.bin b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WP.fru.bin
new file mode 100644
index 000000000..fb219c0ce
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/S2600WP.fru.bin
Binary files differ
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/SetBaseboardFru.service b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/SetBaseboardFru.service
new file mode 100644
index 000000000..dec53725e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/SetBaseboardFru.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Reads GPIO and Loads the FRU
+
+[Service]
+ExecStart=/usr/bin/checkFru.sh
+Type=oneshot
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/checkFru.sh b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/checkFru.sh
new file mode 100755
index 000000000..1eb79b299
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/fru/default-fru/checkFru.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# this script checks the gpio id and loads the correct baseboard fru
+fruFile="/etc/fru/baseboard.fru.bin"
+idGpio=( 8 9 10 11 12 53)
+result=0
+idx=0
+
+if [ -f $fruFile ]; then
+ exit 0
+fi
+
+cd /etc/fru
+for gpio in "${idGpio[@]}"
+do
+ echo $gpio > /sys/class/gpio/export
+ typeset -i value=$(cat /sys/class/gpio/gpio$gpio/value)
+ value=$((value << idx))
+ result=$((result | value))
+ idx=$((idx+1))
+done
+
+# wp
+if (($result == 62)); then
+ cat S2600WP.fru.bin > $fruFile
+# wc
+elif (($result == 45)); then
+ cat S2600WC.fru.bin > $fruFile
+# cyp
+elif (($result == 60)); then
+ cat S2600CYP.fru.bin > $fruFile
+# tnp
+elif (($result == 12)); then
+ cat S2600TNP.fru.bin > $fruFile
+# default to wft
+else
+ cat S2600WFT.fru.bin > $fruFile
+fi
diff --git a/meta-openbmc-mods/meta-ast2500/recipes-phosphor/workbook/wolfpass-config.bb b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/workbook/wolfpass-config.bb
new file mode 100644
index 000000000..ead62f47e
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes-phosphor/workbook/wolfpass-config.bb
@@ -0,0 +1,10 @@
+SUMMARY = "Wolfpass board wiring"
+DESCRIPTION = "Board wiring information for the Wolfpass system."
+PR = "r1"
+
+inherit config-in-skeleton
+
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SRCREV = "946064239016e38cd1cc346047b1d26960c06cdb"
+SKELETON_URI = "git://git-amr-1.devtools.intel.com:29418/openbmc-skeleton.git;protocol=ssh;branch=intel"
diff --git a/meta-openbmc-mods/meta-ast2500/recipes.txt b/meta-openbmc-mods/meta-ast2500/recipes.txt
new file mode 100644
index 000000000..3ec3f4a42
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2500/recipes.txt
@@ -0,0 +1,2 @@
+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..666ddbcab
--- /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"
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/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_phosphor_auto.bbclass b/meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass
new file mode 100644
index 000000000..24469356f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/image_types_phosphor_auto.bbclass
@@ -0,0 +1,77 @@
+# 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() {
+ # TODO: find partition list in DTS
+ d.setVar('FLASH_UBOOT_OFFSET', str(0))
+ if d.getVar('IMAGE_TYPE', True) == 'pfr':
+ d.setVar('FLASH_SIZE', str(128*1024))
+ DTB_FULL_FIT_IMAGE_OFFSETS = [0x1100000]
+ 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_TYPE=${IMAGE_TYPE} 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..fefa65569
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-full-fitimage.bbclass
@@ -0,0 +1,555 @@
+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 "
+
+python() {
+ if d.getVar('IMAGE_TYPE', True) == 'pfr':
+ d.appendVar('DEPS', ' openssl-native:do_populate_sysroot \
+ ${SIGNING_KEY_DEPENDS} \
+ ${PN}:do_copy_signing_pubkey')
+}
+
+
+# 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')
+}
+
+make_signatures() {
+ signature_files=""
+ for file in "$@"; do
+ openssl dgst -sha256 -sign ${SIGNING_KEY} -out "${file}.sig" $file
+ signature_files="${signature_files} ${file}.sig"
+ done
+}
+
+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
+
+ if [ "${IMAGE_TYPE}" = "pfr" ]; then
+ ln -sf ${S}/publickey publickey
+ make_signatures image-u-boot image-kernel image-rofs image-rwfs image-runtime MANIFEST publickey
+ # tar up the update package
+ tar -h -cvf "${DEPLOY_DIR_IMAGE}/${PN}-image-update-${MACHINE}-${DATETIME}.tar" image-u-boot image-runtime image-kernel image-rofs image-rwfs MANIFEST publickey ${signature_files}
+ else
+ tar -h -cvf "${DEPLOY_DIR_IMAGE}/${PN}-image-update-${MACHINE}-${DATETIME}.tar" MANIFEST image-u-boot image-runtime image-kernel image-rofs image-rwfs
+ fi
+ # 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..4ad3b2b92
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass
@@ -0,0 +1,40 @@
+inherit obmc-phosphor-image
+
+IMAGE_INSTALL_append = " \
+ fan-default-speed \
+ bmcweb \
+ dbus-broker \
+ dtc \
+ dtoverlay \
+ entity-manager \
+ ipmitool \
+ intel-ipmi-oem \
+ phosphor-ipmi-ipmb \
+ phosphor-node-manager-proxy \
+ dbus-sensors \
+ phosphor-webui \
+ rest-dbus-static \
+ phosphor-pid-control \
+ phosphor-host-postd \
+ smbios-mdrv1 \
+ phosphor-certificate-manager \
+ phosphor-sel-logger \
+ gpiodaemon \
+ smbios-mdrv2 \
+ obmc-ikvm \
+ system-watchdog \
+ frb2-watchdog \
+ srvcfg-manager \
+ callback-manager \
+ post-code-manager \
+ preinit-mounts \
+ mtd-utils-ubifs \
+ special-mode-mgr \
+ rsyslog \
+ rsyslog-policy \
+ static-mac-addr \
+ "
+
+# this package was flagged as a security risk
+IMAGE_INSTALL_remove += " lrzsz"
+
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/conf/layer.conf b/meta-openbmc-mods/meta-common/conf/layer.conf
new file mode 100644
index 000000000..03226a8ed
--- /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"
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0001-flash-use-readX-writeX-not-udelay.patch b/meta-openbmc-mods/meta-common/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-common/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-common/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch
new file mode 100644
index 000000000..86fa5b7d5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0002-intel-layout-environment-addr.patch
@@ -0,0 +1,42 @@
+Index: u-boot/include/configs/ast-common.h
+===================================================================
+--- u-boot.orig/include/configs/ast-common.h
++++ u-boot/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
+Index: u-boot/common/board_r.c
+===================================================================
+--- u-boot.orig/common/board_r.c
++++ u-boot/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/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch
new file mode 100644
index 000000000..8bc0a3ed3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0004-Make-sure-debug-uart-is-using-24MHz-clock-source.patch
@@ -0,0 +1,75 @@
+From 2f0e14630abec2c9679d21901072648c7802f2c4 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 d248416..98e6335 100644
+--- a/arch/arm/include/asm/arch-aspeed/ast_scu.h
++++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h
+@@ -45,4 +45,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 c9c7a81..a423052 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 0cc0d67..902263b 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -496,3 +496,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;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch
new file mode 100644
index 000000000..0385a5e31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0005-enable-passthrough-in-uboot.patch
@@ -0,0 +1,56 @@
+From b344cf4462acb1f043ed903ccee713e24ce7226d 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 1/1] 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 902263b28b..c83931ed54 100644
+--- a/arch/arm/mach-aspeed/ast-scu.c
++++ b/arch/arm/mach-aspeed/ast-scu.c
+@@ -502,3 +502,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 5a1fadeedd..b492003f51 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;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch
new file mode 100644
index 000000000..dbaf7b362
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0006-Add-Aspeed-g5-interrupt-support.patch
@@ -0,0 +1,389 @@
+From f33755167ddcdebbf56bc875e4091990273c6997 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/7] 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 | 4 +-
+ 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, 260 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 3ceff25032..d6439d01ca 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 ed83043abb..a96b3aa070 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 d1d7f8525e..d41b11589f 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 0000000000..860f16cf05
+--- /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 0000000000..703eeabf13
+--- /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 b492003f51..2472aa3603 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 0000000000..9fd10eccb3
+--- /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 d69b817c82..33be2407d2 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 2d28c86966..d5b7894a9e 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 74029ed514..9481e5fb6e 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 767f3af605..4aefcf49e8 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
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0007-Add-espi-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0007-Add-espi-support.patch
new file mode 100644
index 000000000..18cc2f9c8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0007-Add-espi-support.patch
@@ -0,0 +1,330 @@
+From 7ad0ea13337550f35c1e726f21d4751bf74078d6 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 2/7] 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>
+Change-Id: Id7072f1408dcf364968b1b74f2192e50a22a82f0
+---
+ arch/arm/include/asm/arch-aspeed/regs-scu.h | 2 +
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-espi.c | 231 ++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 16 ++
+ board/aspeed/ast-g5/ast-g5.c | 3 +
+ 5 files changed, 253 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 b714fa9234..10b983a966 100644
+--- a/arch/arm/include/asm/arch-aspeed/regs-scu.h
++++ b/arch/arm/include/asm/arch-aspeed/regs-scu.h
+@@ -552,6 +552,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 d41b11589f..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..79ef253b86
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-espi.c
+@@ -0,0 +1,231 @@
++/*
++ * 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)
++
++/* ESPI00C bits (Interrupt Enable) */
++#define AST_ESPI_IEN_SYS_EV (1 << 8)
++#define AST_ESPI_IEN_GPIO_EV (1 << 9)
++
++/* 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 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_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 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_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
++ }
++ writel(irq_status, AST_ESPI_BASE + ESPI008); // clear irq_status
++ return 0;
++}
++
++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);
++ }
++}
++
++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 | 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);
++
++ 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_BASE + ESPI00C); // Enable only sys 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 2472aa3603..d41ef9cbd3 100644
+--- a/board/aspeed/ast-g5/ast-g5.c
++++ b/board/aspeed/ast-g5/ast-g5.c
+@@ -18,6 +18,8 @@
+
+ DECLARE_GLOBAL_DATA_PTR;
+
++extern void ast_g5_intel(void);
++
+ int board_early_init_f(void)
+ {
+ /* make sure uart5 is using 24MHz clock */
+@@ -34,6 +36,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-common/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch
new file mode 100644
index 000000000..e16b0f158
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0008-add-sgio-support-for-port80-snoop-post-LEDs.patch
@@ -0,0 +1,160 @@
+From c3b44c02392d33cfec85056fd323d93fdc6e523f 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();
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch
new file mode 100644
index 000000000..a49f196ac
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0009-Add-basic-GPIO-support.patch
@@ -0,0 +1,414 @@
+From 89728d8c255204c8d9ec46a1dc0d412b04708f22 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 4/7] 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>
+---
+ board/aspeed/ast-g5/Makefile | 1 +
+ board/aspeed/ast-g5/ast-g5-gpio.c | 195 +++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5-gpio.h | 102 +++++++++++++++
+ board/aspeed/ast-g5/ast-g5-intel.c | 42 +++++++
+ board/aspeed/ast-g5/ast-g5.h | 1 +
+ 5 files changed, 341 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..d596c15914
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-gpio.c
+@@ -0,0 +1,195 @@
++/*
++ * 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_PORT(gpio_table[n].u8Value);
++ 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_PORT(gpio_table[n].u8Value);
++ 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;
++ 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;
++
++ 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);
++ if (gpio_table[i].u8Value)
++ 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, 16);
++ 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, 16);
++ 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..a820c0fcad
+--- /dev/null
++++ b/board/aspeed/ast-g5/ast-g5-gpio.h
+@@ -0,0 +1,102 @@
++#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 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 fca4d91115..252a05dd73 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -14,6 +14,47 @@
+ #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_FP_LED (GPCFG_OUTPUT_EN)
++// Active High, Pull-up, Level, Output Disabled
++
++// 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_DEFAULT, 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 +148,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-common/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch
new file mode 100644
index 000000000..c97e6d74f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0010-Update-Force-Firmware-Update-Jumper-to-use-new-gpio.patch
@@ -0,0 +1,98 @@
+From 1f710737f2fe8dea4bc5ebef1e6011de294764b4 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>
+---
+ .../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 0000000000..cd9a0994fa
+--- /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 9f339e913a..3ea1c99089 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 252a05dd73..58ad6a55b8 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 c52bad84a4..d66c0fa63a 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);
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch
new file mode 100644
index 000000000..11a474b96
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0011-Add-basic-timer-support-for-Aspeed-g5-in-U-Boot.patch
@@ -0,0 +1,160 @@
+From 83d67b5b3cbffcefda5efdc0060b9e30f44c9aca 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 6/7] 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 2970ae5741..90224333c4 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 58ad6a55b8..23bf4e4352 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 0000000000..56157222d9
+--- /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 0000000000..4b1ac28a9f
+--- /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 908db1477b..28fe5eafcb 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_ */
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch
new file mode 100644
index 000000000..5a2c2206f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0012-Add-status-and-ID-LED-support.patch
@@ -0,0 +1,144 @@
+From f0e3631ea3005640f988727f051106d83b5dfdaf 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 7/7] 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>
+Change-Id: Ic9595621b21000ef465ff57ed2047855296e2714
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 118 +++++++++++++++++++++++++++++
+ 1 file changed, 118 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 23bf4e4352..5ff2cbd0e2 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -146,6 +146,110 @@ 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[] = {
++ [GPIO_ID_LED] = {GPIO_ID_LED, EIDLED_Blink_3HZ, 1, 0},
++ [GPIO_GREEN_LED] = {GPIO_GREEN_LED, EIDLED_Off, 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 +269,10 @@ 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()) {
++ id_led_control(GPIO_AMBER_LED, EIDLED_On);
++ } else {
++ id_led_control(GPIO_GREEN_LED, EIDLED_On);
++ }
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch
new file mode 100644
index 000000000..d235aea62
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0013-aspeed-Add-Pwm-Driver.patch
@@ -0,0 +1,132 @@
+From 3134584998f624bb6c4ee11102b0bd9b7bb1cbba 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
+---
+ board/aspeed/ast-g5/ast-g5-intel.c | 105 +++++++++++++++++++++++++++++
+ 1 file changed, 105 insertions(+)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c
+index 5ff2cbd0e2..f810ded4e7 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -263,9 +263,114 @@ 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 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 pwm_init(void)
++{
++ uint32_t val;
++ uint32_t chan;
++
++ /* 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);
++
++ /* 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)PWM_DUTY_VALUE) << 8) << ch_duty_shift;
++ writel(val, base + PWM_DUTY_CYCLE + ch_pair * 4);
++ }
++
++ /* 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-common/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch
new file mode 100644
index 000000000..91665e064
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0014-Keep-interrupts-enabled-until-last-second.patch
@@ -0,0 +1,91 @@
+From 2078771e0ff84be710250b2e9b2e887f7238f9cc 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 2/3] 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 f810ded4e7..4d399be392 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -263,6 +263,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 2431019b3f..46909ecdbb 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 9ec84bd0db..b56eb39780 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);
+
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch
new file mode 100644
index 000000000..475b8c3ff
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0015-Rewrite-memmove-to-optimize-on-word-transfers.patch
@@ -0,0 +1,114 @@
+From a71794fc928429e199c5ea48181e5edfbb0c4f39 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 67d5f6a421..0bf472f1f6 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
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch
new file mode 100644
index 000000000..1d2b02954
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0019-u-boot-full-platform-reset-espi-oob-ready.patch
@@ -0,0 +1,48 @@
+From bb490aa226dcf261d3d6865be37130765ecbe9f4 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 2ac1ca4721..66427b6f33 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
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch
new file mode 100644
index 000000000..2e541561a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch
@@ -0,0 +1,121 @@
+From 06445210bfda7f9bbbb36133e6818575bd6a0cc1 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.
+
+Signed-off-by: Yong Li <yong.b.li@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 | 30 +++++++++++++++++++++++++++++
+ board/aspeed/ast-g5/ast-g5.c | 7 +++++++
+ 4 files changed, 43 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 bcaf81e..1e8708a 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -303,6 +303,36 @@ static inline void ast_scu_write(uint32_t val, uint32_t reg)
+ #endif
+ }
+
++void ast_g5_intel_late_init(void)
++{
++ char *cmdline = NULL;
++ char *cmdline_new = NULL;
++ char buf[32];
++ u32 rest = 0;
++
++ /* save and clear reset status */
++ rest = ast_scu_read(AST_SCU_SYS_CTRL);
++ snprintf(buf, sizeof(buf), " resetreason=0x%x", rest);
++ ast_scu_write(0, AST_SCU_SYS_CTRL);
++
++ cmdline = getenv("bootargs");
++ if (!cmdline) {
++ printf("Get bootargs fail!\n");
++ return;
++ }
++
++ cmdline_new = malloc(strlen(cmdline) + strlen(buf) + 1);
++ if (!cmdline_new) {
++ printf("Cannot malloc memory!\n");
++ return;
++ }
++
++ /* append the reset status into kernel command line */
++ snprintf(cmdline_new, strlen(cmdline) + strlen(buf) + 1, "%s%s", cmdline, buf);
++ setenv("bootargs", cmdline_new);
++ free(cmdline_new);
++}
++
+ 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();
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch
new file mode 100644
index 000000000..bdf3d2ddd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Enable-PCIe-L1-support.patch
@@ -0,0 +1,38 @@
+From 22c61ba094d8ebdbdcb44f848eef1f5d87a4be87 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 66427b6f33e7..b4043534b083 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
+ ******************************************************************************/
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch
new file mode 100755
index 000000000..310d9359b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0021-Config-host-uart-clock-source-using-environment-vari.patch
@@ -0,0 +1,108 @@
+From c82ba33ea40e0007945cbc93da58f296fdeedeaf 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 1e8708a..f810a40 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;
+@@ -310,6 +313,42 @@ void ast_g5_intel_late_init(void)
+ char buf[32];
+ u32 rest = 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 */
+ rest = ast_scu_read(AST_SCU_SYS_CTRL);
+ snprintf(buf, sizeof(buf), " resetreason=0x%x", rest);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch
new file mode 100644
index 000000000..c79b2f2dc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch
@@ -0,0 +1,613 @@
+From b11377c73c85bdee1975402084c3760b70cc99c4 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] 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>
+---
+ 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 9022433..05972b9 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 409b1a7..41d41ea 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -437,6 +437,7 @@ static void pwm_init(void)
+ }
+
+ extern void espi_init(void);
++extern void kcs_init(void);
+ void ast_g5_intel(void)
+ {
+ pwm_init();
+@@ -446,6 +447,8 @@ 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. */
+ } else {
+ id_led_control(GPIO_GREEN_LED, EIDLED_On);
+ }
+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 0000000..7bff26f
+--- /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 0000000..bb697c4
+--- /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.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch
new file mode 100644
index 000000000..746063a56
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch
@@ -0,0 +1,35 @@
+From 6651a2663ee3e9f02c6ed8377097456528a2ee1a 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
+
+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 b7d7192..dd89d91 100644
+--- a/include/configs/ast-common.h
++++ b/include/configs/ast-common.h
+@@ -103,7 +103,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 */
+
+@@ -111,7 +111,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 21100000"
+ #define CONFIG_ENV_OVERWRITE
+
+ #define ASPEED_ENV_SETTINGS \
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch
new file mode 100644
index 000000000..5e8cd103d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch
@@ -0,0 +1,52 @@
+From f762526077a7af02fc93bacc74fb9d49481d664f 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 f9955c70d2f2..d9ba4a47a413 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;
+@@ -445,6 +452,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();
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch
new file mode 100644
index 000000000..9096b09b2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch
@@ -0,0 +1,332 @@
+From 50d3a7264fc0ecdd61ae1686839b19091b124e8d 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);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch
new file mode 100644
index 000000000..f6f402bc9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0025-Manufacturing-mode-physical-presence-detection.patch
@@ -0,0 +1,121 @@
+From 6b4e1b3672433c0d7d392404e19d114ae25e0eb2 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Wed, 24 Apr 2019 22:35:43 +0530
+Subject: [PATCH] Manufacturing mode physical presence detection
+
+Support for physical presence of manufacturing mode added.
+Front panel power button press for 8 seconds will be detected
+and marked as special mode for manufacturing request
+
+Tested:
+1. Verified by holding the power button when u-boot boots for
+8 seconds, and confirmed that bootargs passed to linux has
+special=mfg string
+2. Verified in normal condition special=mfg string is not passed.
+
+Change-Id: Id7e7c7e7860c7ef3ae8e3a7a7cfda7ff506c0f2b
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ board/aspeed/ast-g5/ast-g5-gpio.h | 2 +-
+ board/aspeed/ast-g5/ast-g5-intel.c | 39 ++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 38 insertions(+), 3 deletions(-)
+
+diff --git a/board/aspeed/ast-g5/ast-g5-gpio.h b/board/aspeed/ast-g5/ast-g5-gpio.h
+index a820c0f..ed2499f 100644
+--- a/board/aspeed/ast-g5/ast-g5-gpio.h
++++ b/board/aspeed/ast-g5/ast-g5-gpio.h
+@@ -72,7 +72,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 881ab89..86b422f 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)
+@@ -55,6 +56,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_DEFAULT, 0,
++ GPIO_DEBOUNCE_8MS},
++
+ };
+
+ #define LPC_SNOOP_ADDR 0x80
+@@ -313,12 +318,35 @@ static inline void ast_scu_write(uint32_t val, uint32_t reg)
+ #endif
+ }
+
++static bool is_mfg_mode_phy_req(void)
++{
++ /*
++ * Assume mfg mode physical request is made, if power button
++ * is pressed continously for 8 seconds, indicate the
++ * same in bootargs
++ */
++ const uint32_t delay_in_ms = 100;
++ const uint32_t read_count = ((8 * 1000) / delay_in_ms);
++ 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");
++
++ return true;
++}
++
+ void ast_g5_intel_late_init(void)
+ {
+ char *cmdline = NULL;
+ char *cmdline_new = NULL;
+ char buf[32];
+ u32 rest = 0;
++ const char *special_mfg_str = " special=mfg";
++ const u32 special_str_size = strlen(special_mfg_str);
++ u32 buf_count = 0;
+
+ /* By default host serail A and B use normal speed */
+ uint32_t host_serial_cfg = 0;
+@@ -367,14 +395,21 @@ void ast_g5_intel_late_init(void)
+ return;
+ }
+
+- cmdline_new = malloc(strlen(cmdline) + strlen(buf) + 1);
++ cmdline_new = malloc(strlen(cmdline) + strlen(buf) +
++ special_str_size + 1);
+ if (!cmdline_new) {
+ printf("Cannot malloc memory!\n");
+ return;
+ }
+
+ /* append the reset status into kernel command line */
+- snprintf(cmdline_new, strlen(cmdline) + strlen(buf) + 1, "%s%s", cmdline, buf);
++ buf_count = snprintf(cmdline_new, strlen(cmdline) + strlen(buf) + 1,
++ "%s%s", cmdline, buf);
++
++ if (is_mfg_mode_phy_req())
++ snprintf(cmdline_new + buf_count - 1, special_str_size + 1,
++ "%s", special_mfg_str);
++
+ setenv("bootargs", cmdline_new);
+ free(cmdline_new);
+ }
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch
new file mode 100644
index 000000000..950763d8e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0026-Aspeed-I2C-support-in-U-Boot.patch
@@ -0,0 +1,1520 @@
+From a1626519109c9bda02119114224f3759add21f00 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 | 849 +++++++++++++++++++++
+ drivers/i2c/ast_i2c.h | 131 ++++
+ include/configs/ast-common.h | 5 +
+ 11 files changed, 1346 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..2847430
+--- /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..7e8d4c8 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..7309589 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 8f09190..47d9563 100644
+--- a/configs/ast_g5_phy_defconfig
++++ b/configs/ast_g5_phy_defconfig
+@@ -15,3 +15,5 @@ CONFIG_SPI_FLASH_MACRONIX=y
+ CONFIG_SPI_FLASH_STMICRO=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..0b12fc2
+--- /dev/null
++++ b/drivers/i2c/ast_i2c.c
+@@ -0,0 +1,849 @@
++/*
++ * 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-common/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch
new file mode 100644
index 000000000..d8e7c4645
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0027-CPLD-u-boot-commands-support-for-PFR.patch
@@ -0,0 +1,300 @@
+From 35a50c959b290ba8a6f0e70a42ae952b65df8a9d 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>
+---
+ 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 a1731be..c8ac0af 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 0000000..63220cb
+--- /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 5
++#define PFR_CPLD_SLAVE_ADDR 0x0E
++
++#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.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch
new file mode 100644
index 000000000..7601f6dea
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0028-Enabling-uart1-uart2-in-u-boot-for-BIOS-messages.patch
@@ -0,0 +1,61 @@
+From 56d13790a713659e34eca884ce36dca76b3bdf3d 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 86b422f..fe5128f 100644
+--- a/board/aspeed/ast-g5/ast-g5-intel.c
++++ b/board/aspeed/ast-g5/ast-g5-intel.c
+@@ -414,6 +414,26 @@ void ast_g5_intel_late_init(void)
+ free(cmdline_new);
+ }
+
++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;
+@@ -482,6 +502,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();
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch
new file mode 100644
index 000000000..00dbd68da
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0029-FFUJ-FW-IPMI-commands-and-flash-support-in-u-boot.patch
@@ -0,0 +1,1271 @@
+From bd4a64d7ea394d0b418d491699853112229f098e 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 | 11 +
+ configs/ast_g5_phy_defconfig | 1 +
+ 10 files changed, 1091 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..45a600e 100644
+--- a/common/autoboot.c
++++ b/common/autoboot.c
+@@ -349,6 +349,17 @@ 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()) {
++ 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 47d9563..f070494 100644
+--- a/configs/ast_g5_phy_defconfig
++++ b/configs/ast_g5_phy_defconfig
+@@ -17,3 +17,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-common/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend
new file mode 100644
index 000000000..acac46d70
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend
@@ -0,0 +1,50 @@
+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 \
+ "
+SRC_URI_append_intel-ast2500 += "${@bb.utils.contains('IMAGE_TYPE', 'pfr', 'file://0022-u-boot-env-change-for-PFR-image.patch', '', d)}"
+
+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-common/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend
new file mode 100644
index 000000000..acac46d70
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/u-boot-fw-utils-aspeed_%.bbappend
@@ -0,0 +1,50 @@
+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 \
+ "
+SRC_URI_append_intel-ast2500 += "${@bb.utils.contains('IMAGE_TYPE', 'pfr', 'file://0022-u-boot-env-change-for-PFR-image.patch', '', d)}"
+
+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-common/recipes-core/at-scale-debug/at-scale-debug.bb b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb
new file mode 100644
index 000000000..37ad5667f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb
@@ -0,0 +1,26 @@
+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"
+
+do_configure[depends] += "virtual/kernel:do_shared_workdir"
+
+SRC_URI = "git://git@github.com/Intel-BMC/at-scale-debug;protocol=ssh"
+
+SRCREV = "3369d2e81f7e5e4bcb5d9e14bcecea7ae5da07fb"
+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..744982703
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/files/com.intel.AtScaleDebug.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Intel BMC At Scale Debug
+Requires=network-online.target
+
+[Service]
+Restart=always
+RestartSec=30
+ExecStart={bindir}/asd -k /home/root/server.pem
+Type=simple
+SyslogIdentifier=asd
+
+[Install]
+WantedBy=multi-user.target
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/crashdump/crashdump_git.bb b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
new file mode 100644
index 000000000..8f876cc9c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/crashdump/crashdump_git.bb
@@ -0,0 +1,27 @@
+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 "
+inherit cmake
+
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = ""
+
+SRC_URI = "git://git@github.com/Intel-BMC/at-scale-debug;protocol=ssh"
+SRCREV = "3369d2e81f7e5e4bcb5d9e14bcecea7ae5da07fb"
+
+S = "${WORKDIR}/git/crashdump"
+PACKAGES += "libpeci"
+
+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/fw-update/files/fwupd.sh b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh
new file mode 100644
index 000000000..dd3b7f69a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/fwupd.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+SSH_ID=$HOME/.ssh/id_rsa.db
+[ -e $HOME/.fwupd.defaults ] && source $HOME/.fwupd.defaults
+
+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
+ URI="$1"
+fi
+
+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)"
+echo "PROTO=$PROTO"
+echo "REMOTE=$REMOTE"
+echo "REMOTE_HOST=$REMOTE_HOST"
+echo "REMOTE_PATH=$REMOTE_PATH"
+if [ ! -e $LOCAL_PATH ] || [ $(stat -c %s $LOCAL_PATH) -eq 0 ]; then
+ echo "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
+ echo "scp $REMOTE $LOCAL_PATH failed!"
+ exit 255
+ fi
+ ;;
+ tftp)
+ cd /tmp
+ tftp -g -r "$REMOTE_PATH" "$REMOTE_HOST"
+ if [ $? -ne 0 ]; then
+ echo "tftp -g -r \"$REMOTE_PATH\" \"$REMOTE_HOST\" failed!"
+ exit 255
+ fi
+ ;;
+ http|https|ftp)
+ wget --no-check-certificate "$URI" -O "$LOCAL_PATH"
+ if [ $? -ne 0 ]; then
+ echo "wget $URI failed!"
+ exit 255
+ fi
+ ;;
+ file)
+ cp "$REMOTE_PATH" "$LOCAL_PATH"
+ ;;
+ *)
+ echo "Invalid URI $URI"
+ exit 1;
+ ;;
+ esac
+fi
+
+# do a quick sanity check on the image
+if [ $(stat -c "%s" "$LOCAL_PATH") -lt 10000000 ]; then
+ echo "Update file "$LOCAL_PATH" seems to be too small"
+ exit 1
+fi
+dtc -I dtb -O dtb "$LOCAL_PATH" > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "Update file $LOCAL_PATH doesn't seem to be in the proper format"
+ exit 1
+fi
+
+#this file being created at build time for PFR images
+#TODO: Need to do runtime detection of PFR platform
+#TODO: Also to check if PFR is provisioned or not
+if [ -e /usr/share/pfr ]
+then
+TGT="/dev/mtd/image-stg"
+echo "Updating $(basename $TGT)"
+flash_erase $TGT 0 0
+echo "Writing $(stat -c "%s" "$LOCAL_PATH") bytes"
+cat "$LOCAL_PATH" > "$TGT"
+#TODO: Add I2C command to write to PFRCPLD about BMC update intent.
+else
+# guess based on fw_env which partition we booted from
+BOOTADDR=$(fw_printenv bootcmd | awk '{print $2}')
+
+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
+echo "Updating $(basename $TGT) (use bootm $BOOTADDR)"
+flash_erase $TGT 0 0
+echo "Writing $(stat -c "%s" "$LOCAL_PATH") bytes"
+cat "$LOCAL_PATH" > "$TGT"
+fw_setenv "bootcmd" "bootm ${BOOTADDR}"
+
+# reboot
+reboot
+fi
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..08d0057ef
--- /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 parted"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+PFR_EN = "${@bb.utils.contains('IMAGE_TYPE', 'pfr', 'pfr', '', d)}"
+
+SRC_URI += "file://fwupd.sh"
+SRC_URI += "file://usb-ctrl"
+
+FILES_${PN} += "${@bb.utils.contains('IMAGE_TYPE', '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/ipmi/intel-ipmi-oem_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
new file mode 100644
index 000000000..70533e540
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend
@@ -0,0 +1,2 @@
+SRC_URI = "git://github.com/openbmc/intel-ipmi-oem.git"
+SRCREV = "ba9c1765f5edc2f0891e012f33b3059a0dbd7ff1"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb b/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb
new file mode 100644
index 000000000..b5448060f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb
@@ -0,0 +1,32 @@
+SUMMARY = "Intel IPMI Providers"
+DESCRIPTION = "IPMI Provider Libraries"
+
+SRC_URI = "git://git@github.com/Intel-BMC/intel-ipmi-providers;protocol=ssh"
+SRCREV = "3f8aa7959d2e8475e50743d32ff178257aafc1e7"
+
+S = "${WORKDIR}/git"
+PV = "0.1+git${SRCPV}"
+
+DEPENDS = "boost phosphor-ipmi-host intel-ipmi-oem systemd microsoft-gsl"
+
+inherit cmake obmc-phosphor-ipmiprovider-symlink
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=2ee41112a44fe7014dce33e26468ba93"
+
+EXTRA_OECMAKE="-DENABLE_TEST=0 -DYOCTO=1"
+
+LIBRARY_NAMES += "libmtmcmds.so"
+LIBRARY_NAMES += "libsmbioshandler.so"
+LIBRARY_NAMES += "libzbridgecmd.so"
+LIBRARY_NAMES += "libsmbiosmdrv2.so"
+LIBRARY_NAMES += "libfwupdcmds.so"
+
+HOSTIPMI_PROVIDER_LIBRARY += "${LIBRARY_NAMES}"
+NETIPMI_PROVIDER_LIBRARY += "${LIBRARY_NAMES}"
+
+FILES_${PN}_append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
+FILES_${PN}_append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
+FILES_${PN}_append = " ${libdir}/net-ipmid/lib*${SOLIBS}"
+FILES_${PN}-dev_append = " ${libdir}/ipmid-providers/lib*${SOLIBSDEV}"
+
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..8cb593bce
--- /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"
+
+# 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/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..b6a2504a2
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/os-release/version-vars.inc
@@ -0,0 +1,78 @@
+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))
+
+ # Until tags in meta-openbmc-mods, interim measure keep builds working.
+ if meta_vers.startswith('fatal:'):
+ meta_vers = '{}-0.0-0'.format(gen)
+
+ meta_hash = irun_git(d, mibase, 'rev-parse HEAD')
+ 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(int(versionList[3])))
+ 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..5061e1e56
--- /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://git@github.com/Intel-BMC/at-scale-debug;protocol=ssh"
+
+DEPENDS = "boost sdbusplus crashdump"
+
+PV = "0.1+git${SRCPV}"
+SRCREV = "3369d2e81f7e5e4bcb5d9e14bcecea7ae5da07fb"
+
+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/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/000-ro-rootfs-tmpfile-defaults.patch b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/000-ro-rootfs-tmpfile-defaults.patch
new file mode 100644
index 000000000..d16f3a2dc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/000-ro-rootfs-tmpfile-defaults.patch
@@ -0,0 +1,51 @@
+From 05e1b853abfd54d117dad25185c602d1791d83f6 Mon Sep 17 00:00:00 2001
+From: David Cobbley <david.j.cobbley@linux.intel.com>
+Date: Tue, 26 Jun 2018 16:10:14 -0700
+Subject: [PATCH] ro-rootfs-tmpfile-defaults
+
+---
+ tmpfiles.d/home.conf | 1 -
+ tmpfiles.d/tmp.conf | 1 -
+ tmpfiles.d/var.conf.m4 | 5 ++++-
+ 3 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/tmpfiles.d/home.conf b/tmpfiles.d/home.conf
+index 9f25b83..5c7513a 100644
+--- a/tmpfiles.d/home.conf
++++ b/tmpfiles.d/home.conf
+@@ -8,4 +8,3 @@
+ # See tmpfiles.d(5) for details
+
+ Q /home 0755 - - -
+-q /srv 0755 - - -
+diff --git a/tmpfiles.d/tmp.conf b/tmpfiles.d/tmp.conf
+index 22555a0..aad1b98 100644
+--- a/tmpfiles.d/tmp.conf
++++ b/tmpfiles.d/tmp.conf
+@@ -9,7 +9,6 @@
+
+ # Clear tmp directories separately, to make them easier to override
+ q /tmp 1777 root root 10d
+-q /var/tmp 1777 root root 30d
+
+ # Exclude namespace mountpoints created with PrivateTmp=yes
+ x /tmp/systemd-private-%b-*
+diff --git a/tmpfiles.d/var.conf.m4 b/tmpfiles.d/var.conf.m4
+index 0e2c509..fa288b8 100644
+--- a/tmpfiles.d/var.conf.m4
++++ b/tmpfiles.d/var.conf.m4
+@@ -11,7 +11,10 @@ q /var 0755 - - -
+
+ L /var/run - - - - ../run
+
+-d /var/log 0755 - - -
++# now /var/log and /var/tmp really live in volatile
++L /var/log - - - - volatile/log
++L /var/tmp - - - - volatile/tmp
++
+ m4_ifdef(`ENABLE_UTMP',
+ f /var/log/wtmp 0664 root utmp -
+ f /var/log/btmp 0660 root utmp -
+--
+2.7.4
+
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..f72052e0c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/0001-Modfiy-system.conf-DefaultTimeoutStopSec.patch
@@ -0,0 +1,28 @@
+From 3016898f4300fdd8db74f821cd6ea54dbf39fdc8 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 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/core/system.conf.in b/src/core/system.conf.in
+index 746572b..ba2a265 100644
+--- a/src/core/system.conf.in
++++ b/src/core/system.conf.in
+@@ -33,7 +33,7 @@
+ #DefaultStandardOutput=journal
+ #DefaultStandardError=inherit
+ #DefaultTimeoutStartSec=90s
+-#DefaultTimeoutStopSec=90s
++DefaultTimeoutStopSec=10s
+ #DefaultRestartSec=100ms
+ #DefaultStartLimitIntervalSec=10s
+ #DefaultStartLimitBurst=5
+--
+2.7.4
+
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/systemd-timesyncd.service b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-timesyncd.service
new file mode 100644
index 000000000..9a5fffbb3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/systemd-timesyncd.service
@@ -0,0 +1,53 @@
+# 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=Network Time Synchronization
+Documentation=man:systemd-timesyncd.service(8)
+ConditionCapability=CAP_SYS_TIME
+ConditionVirtualization=!container
+DefaultDependencies=no
+After=systemd-remount-fs.service systemd-sysusers.service var.mount
+Before=time-set.target sysinit.target shutdown.target
+Conflicts=shutdown.target
+Wants=time-set.target time-sync.target
+
+[Service]
+AmbientCapabilities=CAP_SYS_TIME
+CapabilityBoundingSet=CAP_SYS_TIME
+ExecStart=!!/lib/systemd/systemd-timesyncd
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+NoNewPrivileges=yes
+PrivateDevices=yes
+PrivateTmp=yes
+ProtectControlGroups=yes
+ProtectHome=yes
+ProtectHostname=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+ProtectSystem=strict
+Restart=always
+RestartSec=0
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
+RestrictNamespaces=yes
+RestrictRealtime=yes
+RestrictSUIDSGID=yes
+RuntimeDirectory=systemd/timesync
+StateDirectory=systemd/timesync
+SystemCallArchitectures=native
+SystemCallErrorNumber=EPERM
+SystemCallFilter=@system-service @clock
+Type=notify
+User=systemd-timesync
+WatchdogSec=3min
+
+[Install]
+WantedBy=sysinit.target
+Alias=dbus-org.freedesktop.timesync1.service
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..3e5adf7ce
--- /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://000-ro-rootfs-tmpfile-defaults.patch \
+ file://0001-Modfiy-system.conf-DefaultTimeoutStopSec.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/dtoverlay/dtoverlay.bb b/meta-openbmc-mods/meta-common/recipes-devtools/dtoverlay/dtoverlay.bb
new file mode 100644
index 000000000..66107d81b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-devtools/dtoverlay/dtoverlay.bb
@@ -0,0 +1,31 @@
+SUMMARY = "dtoverlay"
+DESCRIPTION = "device tree overlay application"
+
+SRC_URI = "git://github.com/raspberrypi/userland.git"
+LICENSE = "BSD"
+LIC_FILES_CHKSUM = "file://LICENCE;md5=0448d6488ef8cc380632b1569ee6d196"
+
+SRCREV = "11389772c79685442e0ab8aa9be8ad0e32703f68"
+requires = "chrpath-native"
+
+S = "${WORKDIR}/git"
+
+PV = "1"
+
+inherit cmake
+
+FILES_${PN} += "${libdir} ${libdir}libdtovl.so.${PV}"
+
+do_compile_append(){
+ chrpath -d ${S}/build/bin/dtoverlay
+}
+
+do_install() {
+ install -d ${D}${libdir}
+ install -m 0644 ${S}/build/lib/libdtovl.so ${D}${libdir}/libdtovl.so.${PV}
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/build/bin/dtoverlay ${D}${bindir}/dtoverlay
+
+ ln -sf libdtovl.so.${PV} ${D}{libdir}libdtovl.so
+}
+
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..46a185cdf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-devtools/mtd-util/mtd-util.bb
@@ -0,0 +1,20 @@
+DESCRIPTION = "OpenBMC mtd-util"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b77c43ae4eaf67bd73fb6452b2f113a3"
+
+SRC_URI = "git://git@github.com/Intel-BMC/mtd-util;protocol=ssh"
+
+PV = "1.0+git${SRCPV}"
+SRCREV = "0414bd37ba324867c5c89fc91ab80714309f4c80"
+
+
+S = "${WORKDIR}/git"
+
+DEPENDS += "dbus openssl zlib boost microsoft-gsl"
+
+inherit cmake pkgconfig
+
+# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
+EXTRA_OECMAKE = ""
+
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..5d13a8c44
--- /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://git-amr-2.devtools.intel.com:29418/openbmc_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/rsyslog/rsyslog-policy.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy.bbappend
new file mode 100644
index 000000000..58512234d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://rsyslog-override.conf \
+"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy/rsyslog-override.conf b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy/rsyslog-override.conf
new file mode 100644
index 000000000..14bcc0781
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog-policy/rsyslog-override.conf
@@ -0,0 +1,2 @@
+[Service]
+ExecReload=/bin/kill -HUP $MAINPID
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..fdeefd417
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Rotates the event logs
+
+[Service]
+Type=oneshot
+ExecStart=/usr/sbin/logrotate /etc/logrotate.d/logrotate.rsyslog
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.timer b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.timer
new file mode 100644
index 000000000..148f8e4ae
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rotate-event-logs.timer
@@ -0,0 +1,8 @@
+[Unit]
+Description=Run rotate-event-logs.service every minute
+
+[Timer]
+OnCalendar=*-*-* *:*:00
+
+[Install]
+WantedBy=timers.target
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.conf b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.conf
new file mode 100644
index 000000000..f00046b45
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.conf
@@ -0,0 +1,62 @@
+# if you experience problems, check
+# http://www.rsyslog.com/troubleshoot for assistance
+
+# rsyslog v3: load input modules
+# If you do not load inputs, nothing happens!
+# You may need to set the module load path if modules are not found.
+#
+# Ported from debian's sysklogd.conf
+
+# Journal-style logging
+# Limit to no more than 2000 entries in one minute and enable the
+# journal workaround to avoid duplicate entries
+module(load="imjournal" StateFile="/var/log/state"
+ RateLimit.Interval="60"
+ RateLimit.Burst="2000")
+
+# Template for IPMI SEL messages
+# "<timestamp> <ID>,<Type>,<EventData>,[<Generator ID>,<Path>,<Direction>]"
+template(name="IPMISELTemplate" type="list") {
+ property(name="timereported" dateFormat="rfc3339")
+ constant(value=" ")
+ property(name="$!IPMI_SEL_RECORD_ID")
+ constant(value=",")
+ property(name="$!IPMI_SEL_RECORD_TYPE")
+ constant(value=",")
+ property(name="$!IPMI_SEL_DATA")
+ constant(value=",")
+ property(name="$!IPMI_SEL_GENERATOR_ID")
+ constant(value=",")
+ property(name="$!IPMI_SEL_SENSOR_PATH")
+ constant(value=",")
+ property(name="$!IPMI_SEL_EVENT_DIR")
+ constant(value="\n")
+}
+
+# Template for Redfish messages
+# "<timestamp> <MessageId>,<MessageArgs>"
+template(name="RedfishTemplate" type="list") {
+ property(name="timereported" dateFormat="rfc3339")
+ constant(value=" ")
+ property(name="$!REDFISH_MESSAGE_ID")
+ constant(value=",")
+ property(name="$!REDFISH_MESSAGE_ARGS")
+ constant(value="\n")
+}
+
+# If the journal entry has the IPMI SEL MESSAGE_ID, save as IPMI SEL
+# The MESSAGE_ID string is generated using journalctl and must match the
+# MESSAGE_ID used in IPMI to correctly find the SEL entries.
+if ($!MESSAGE_ID == "b370836ccf2f4850ac5bee185b77893a") then {
+ action(type="omfile" file="/var/log/ipmi_sel" template="IPMISELTemplate")
+}
+
+# If the journal entry has a Redfish MessageId, save as a Redfish event
+if ($!REDFISH_MESSAGE_ID != "") then {
+ action(type="omfile" file="/var/log/redfish" template="RedfishTemplate")
+}
+
+#
+# Include all config files in /etc/rsyslog.d/
+#
+$IncludeConfig /etc/rsyslog.d/*.conf
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate
new file mode 100644
index 000000000..a6ba28d86
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/rsyslog.logrotate
@@ -0,0 +1,22 @@
+# /etc/logrotate.d/rsyslog - Ported from Debian
+
+# Keep up to four 64k files for ipmi_sel (256k total)
+/var/log/ipmi_sel
+{
+ rotate 3
+ size 64k
+ missingok
+ postrotate
+ systemctl reload rsyslog 2> /dev/null || true
+ endscript
+}
+# Keep up to four 64k files for redfish (256k total)
+/var/log/redfish
+{
+ rotate 3
+ size 64k
+ missingok
+ postrotate
+ systemctl reload rsyslog 2> /dev/null || true
+ endscript
+}
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..03a81e2cb
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend
@@ -0,0 +1,25 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+# Pin to rsyslog v8.1904.0 for now
+# v8.1903.0 has a couple issues with the imjournal module:
+# 1. Enabling the "WorkAroundJournalBug" option causes rsyslogd to fail to start
+# 2. Logging data especially while rotating the journal causes a double free error
+PV = "8.1904.0"
+SRC_URI[md5sum] = "b9398b5aa68a829bf2c18a87490d30c0"
+SRC_URI[sha256sum] = "7098b459dfc3f8bfc35d5b114c56e7945614ba76efa4e513b1db9c38b0ff9c3d"
+
+SRC_URI += "file://rsyslog.conf \
+ file://rsyslog.logrotate \
+ file://rotate-event-logs.service \
+ file://rotate-event-logs.timer \
+"
+
+PACKAGECONFIG_append = " imjournal"
+
+do_install_append() {
+ install -m 0644 ${WORKDIR}/rotate-event-logs.service ${D}${systemd_system_unitdir}
+ install -m 0644 ${WORKDIR}/rotate-event-logs.timer ${D}${systemd_system_unitdir}
+ rm ${D}${sysconfdir}/rsyslog.d/imjournal.conf
+}
+
+SYSTEMD_SERVICE_${PN} += " rotate-event-logs.service rotate-event-logs.timer"
diff --git a/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend
new file mode 100644
index 000000000..af5fa8b05
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-extended/sdbusplus/sdbusplus_%.bbappend
@@ -0,0 +1,4 @@
+
+#SRC_URI += "git://github.com/openbmc/sdbusplus"
+SRCREV = "f8bbf17c3db879359b0984b40250e4db3d274be1"
+
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver/0001-rfbserver-add-a-hooking-function-to-deliver-rfbFrame.patch b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver/0001-rfbserver-add-a-hooking-function-to-deliver-rfbFrame.patch
new file mode 100644
index 000000000..6dd1c93f0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver/0001-rfbserver-add-a-hooking-function-to-deliver-rfbFrame.patch
@@ -0,0 +1,54 @@
+From 6d7c437f4d111ed183627c11e9bfc77ad2abc752 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+Date: Thu, 9 May 2019 15:33:55 -0700
+Subject: [PATCH] rfbserver: add a hooking function to deliver
+ rfbFramebufferUpdateRequest messages.
+
+This commit adds a hooking function to deliver
+rfbFramebufferUpdateRequest messages from clients to the frame
+producer for a case the producer needs to handle the messages for
+flow control or etc.
+---
+ libvncserver/rfbserver.c | 2 ++
+ rfb/rfb.h | 5 +++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
+index 42209cf29a0d..3a546f2ed330 100644
+--- a/libvncserver/rfbserver.c
++++ b/libvncserver/rfbserver.c
+@@ -2381,6 +2381,8 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
+ return;
+ }
+
++ if (cl->clientFURHook)
++ cl->clientFURHook(cl, &msg.fur);
+
+ tmpRegion =
+ sraRgnCreateRect(msg.fur.x,
+diff --git a/rfb/rfb.h b/rfb/rfb.h
+index 2a5600e25375..1a2294428288 100644
+--- a/rfb/rfb.h
++++ b/rfb/rfb.h
+@@ -412,6 +412,8 @@ typedef struct sraRegion* sraRegionPtr;
+ */
+
+ typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
++typedef void (*ClientFURHookPtr)(struct _rfbClientRec* cl,
++ rfbFramebufferUpdateRequestMsg* furMsg);
+
+ typedef struct _rfbFileTransferData {
+ int fd;
+@@ -457,6 +459,9 @@ typedef struct _rfbClientRec {
+ void* clientData;
+ ClientGoneHookPtr clientGoneHook;
+
++ /** clientFURHook is called when a client requests a frame buffer update. */
++ ClientFURHookPtr clientFURHook;
++
+ SOCKET sock;
+ char *host;
+
+--
+2.7.4
+
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..e367e97b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/libvncserver/libvncserver_%.bbappend
@@ -0,0 +1,7 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+# Use the latest to support obmc-ikvm properly
+#SRC_URI = "git://github.com/LibVNC/libvncserver"
+SRCREV = "f12b14f275f019673b3ace8fa4d46c8a79beb388"
+
+SRC_URI += "file://0001-rfbserver-add-a-hooking-function-to-deliver-rfbFrame.patch"
diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Add-flow-control-to-prevent-buffer-over-run.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Add-flow-control-to-prevent-buffer-over-run.patch
new file mode 100644
index 000000000..1340e845b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Add-flow-control-to-prevent-buffer-over-run.patch
@@ -0,0 +1,119 @@
+From 336d0e9163a027b2b35ed240c2995f06684637b8 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+Date: Thu, 9 May 2019 16:26:53 -0700
+Subject: [PATCH] Add flow control to prevent buffer over run
+
+This service uses direct frame update with bypassing image
+compression and invalidating logic in libvncserver to achieve
+better performance by using of H/W compressed JPEG frames as those
+come from the video engine driver.
+
+This behavior helps quick frame update using very small amount of
+CPU resources but it causes a side effect which crashes bmcweb
+by OOM killer due to a buffer over run issue. Usually, this issue
+happens often in a slow speed connection because this service
+keeps sending all frames without any handshaking with clients so
+a session buffer in the bmcweb gets bigger and bigger since the
+low speed connection can't send all stream data on time.
+
+To fix this issue, this commit adds flow control logic to make
+frame updating handshakes with client so that it'll send frames
+only when it recieved client frame update messages. All other
+frames when the client doesn't request will be dropped out to
+prevent the buffer over run issue.
+
+Tested:
+bmcweb didn't keep increasing its KVM session buffer.
+KVM worked well with showing good refresh speed.
+
+resolves https://github.com/openbmc/bmcweb/issues/80
+
+Change-Id: I6b09a711137d15a38fce59adada9bf3d00afde86
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
+---
+ ikvm_server.cpp | 19 +++++++++++++++++++
+ ikvm_server.hpp | 10 ++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/ikvm_server.cpp b/ikvm_server.cpp
+index 35310da292be..363eab7e000d 100644
+--- a/ikvm_server.cpp
++++ b/ikvm_server.cpp
+@@ -119,6 +119,12 @@ void Server::sendFrame()
+ continue;
+ }
+
++ if (!cd->needUpdate)
++ {
++ continue;
++ }
++ cd->needUpdate = false;
++
+ if (cl->enableLastRectEncoding)
+ {
+ fu->nRects = 0xFFFF;
+@@ -149,6 +155,18 @@ void Server::sendFrame()
+ rfbReleaseClientIterator(it);
+ }
+
++void Server::clientFUR(rfbClientPtr cl, rfbFramebufferUpdateRequestMsg* furMsg)
++{
++ ClientData* cd = (ClientData*)cl->clientData;
++
++ if (!cd)
++ return;
++
++ // Ignore the furMsg info. This service uses full frame update always.
++
++ cd->needUpdate = true;
++}
++
+ void Server::clientGone(rfbClientPtr cl)
+ {
+ Server* server = (Server*)cl->screen->screenData;
+@@ -170,6 +188,7 @@ enum rfbNewClientAction Server::newClient(rfbClientPtr cl)
+ cl->clientData =
+ new ClientData(server->video.getFrameRate(), &server->input);
+ cl->clientGoneHook = clientGone;
++ cl->clientFURHook = clientFUR;
+ if (!server->numClients++)
+ {
+ server->pendingResize = false;
+diff --git a/ikvm_server.hpp b/ikvm_server.hpp
+index b8062017b8ca..e51e57a19722 100644
+--- a/ikvm_server.hpp
++++ b/ikvm_server.hpp
+@@ -32,6 +32,7 @@ class Server
+ */
+ ClientData(int s, Input* i) : skipFrame(s), input(i)
+ {
++ needUpdate = false;
+ }
+ ~ClientData() = default;
+ ClientData(const ClientData&) = default;
+@@ -41,6 +42,7 @@ class Server
+
+ int skipFrame;
+ Input* input;
++ bool needUpdate;
+ };
+
+ /*
+@@ -85,6 +87,14 @@ class Server
+
+ private:
+ /*
++ * @brief Handler for a client frame update message
++ *
++ * @param[in] cl - Handle to the client object
++ * @param[in] furMsg - Pointer of the FUR message
++ */
++ static void clientFUR(rfbClientPtr cl,
++ rfbFramebufferUpdateRequestMsg* furMsg);
++ /*
+ * @brief Handler for a client disconnecting
+ *
+ * @param[in] cl - Handle to the client object
+--
+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..577a78601
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
@@ -0,0 +1,6 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+#SRC_URI = "git://github.com/openbmc/obmc-ikvm"
+SRCREV = "133bfa2d5b1b3af0b8e819b4cd210a0e1ac0445c"
+
+SRC_URI += "file://0001-Add-flow-control-to-prevent-buffer-over-run.patch"
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb b/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb
new file mode 100644
index 000000000..4b11782e8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb
@@ -0,0 +1,29 @@
+SUMMARY = "Chassis Power Control service for Intel based platform"
+DESCRIPTION = "Chassis Power Control service for Intel based platfrom"
+
+SRC_URI = "git://git@github.com/Intel-BMC/intel-chassis-control.git;protocol=ssh"
+SRCREV = "d98b80a3ce937abe6282b7b9011b47e8b2f162be"
+
+S = "${WORKDIR}/git/services/chassis/"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+inherit cmake systemd
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.Chassis.Control.Power.service"
+
+DEPENDS += " \
+ boost \
+ i2c-tools \
+ libgpiod \
+ sdbusplus \
+ phosphor-logging \
+ "
+
+# linux-libc-headers guides this way to include custom uapi headers
+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-intel/images/intel-platforms.bb b/meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb
new file mode 100644
index 000000000..276e549b9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/images/intel-platforms.bb
@@ -0,0 +1,13 @@
+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
+
+FEATURE_PACKAGES_obmc-sensors = ""
+
+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/packagegroups/packagegroup-intel-apps.bb b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb
new file mode 100644
index 000000000..923133be7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb
@@ -0,0 +1,43 @@
+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 = " \
+ intel-chassis-control \
+ obmc-host-failure-reboots \
+ "
+
+SUMMARY_${PN}-fans = "Intel Fans"
+RDEPENDS_${PN}-fans = " \
+ phosphor-pid-control \
+ "
+
+SUMMARY_${PN}-flash = "Intel Flash"
+RDEPENDS_${PN}-flash = " \
+ obmc-flash-bmc \
+ obmc-mgr-download \
+ obmc-control-bmc \
+ "
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..c71e84bdc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-obmc-apps.bbappend
@@ -0,0 +1,3 @@
+# this is for image signing and signature verification
+RDEPENDS_${PN}-extras += "${@bb.utils.contains('IMAGE_TYPE', 'pfr', ' phosphor-image-signing', '', d)}"
+RDEPENDS_${PN}-extrasdevtools = "libgpiod-tools"
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..24a8c668b
--- /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://git-amr-2.devtools.intel.com:29418/openbmc-provingground.git;protocol=ssh;nobranch=1"
+SRCREV = "fe33964c744f871f3e024dd8d0b6ffba67394c30"
+
+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} += "cold-redundancy.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..c37ea66e1
--- /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://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+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..a41cdb50b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb
@@ -0,0 +1,33 @@
+SUMMARY = "SMBIOS MDR version 2 service for Intel based platform"
+DESCRIPTION = "SMBIOS MDR version 2 service for Intel based platfrom"
+
+SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+S = "${WORKDIR}/git/services/smbios-mdrv2/"
+
+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 \
+ 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-mdrv2/smbios-mdrv2.service b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service
new file mode 100644
index 000000000..b72873406
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2/smbios-mdrv2.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Intel BMC SMBIOS MDR V2
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+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/0005-arm-dts-aspeed-g5-add-espi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch
new file mode 100644
index 000000000..08498cd01
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch
@@ -0,0 +1,56 @@
+From 536b09695117440ed428ff27023cd9167fcf4dfe 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 | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index a79e01ffe9d4..0c74adf739d2 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -261,7 +261,7 @@
+ #gpio-cells = <2>;
+ gpio-controller;
+ compatible = "aspeed,ast2500-gpio";
+- reg = <0x1e780000 0x1000>;
++ reg = <0x1e780000 0x0200>;
+ interrupts = <20>;
+ gpio-ranges = <&pinctrl 0 0 220>;
+ clocks = <&syscon ASPEED_CLK_APB>;
+@@ -269,6 +269,15 @@
+ #interrupt-cells = <2>;
+ };
+
++ sgpio: sgpio@1e780200 {
++ #gpio-cells = <2>;
++ gpio-controller;
++ compatible = "aspeed,ast2500-sgpio";
++ reg = <0x1e780200 0x0100>;
++ interrupts = <40>;
++ interrupt-controller;
++ };
++
+ rtc: rtc@1e781000 {
+ compatible = "aspeed,ast2500-rtc";
+ reg = <0x1e781000 0x18>;
+@@ -344,6 +353,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/0007-New-flash-map-for-intel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch
new file mode 100644
index 000000000..11663c503
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch
@@ -0,0 +1,120 @@
+From 3eabb52efdecfc0da896476ac5567060a6b3788a 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 | 52 ++++++++++++++++++++++
+ .../boot/dts/openbmc-flash-layout-intel-64MB.dtsi | 39 ++++++++++++++++
+ 2 files changed, 91 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..23426acc30c7
+--- /dev/null
++++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
+@@ -0,0 +1,52 @@
++// 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 0xe40000>;
++ label = "rwfs";
++ };
++
++ fit-image-a@1100000 {
++ reg = <0x1100000 0x2500000>;
++ label = "image-a";
++ };
++
++ rc-image@3600000 {
++ reg = <0x3600000 0x2500000>;
++ label = "rc-image";
++ };
++
++ image-staging@5b00000 {
++ reg = <0x5b00000 0x2500000>;
++ 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..6ae8e57087e2
+--- /dev/null
++++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
+@@ -0,0 +1,39 @@
++// 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/0008-Add-ASPEED-SGPIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch
new file mode 100644
index 000000000..beb5087f5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch
@@ -0,0 +1,473 @@
+From 58adbd18074fbf8005d5d7a5ec116c326252f606 Mon Sep 17 00:00:00 2001
+From: "Feist, James" <james.feist@intel.com>
+Date: Mon, 5 Jun 2017 11:13:52 -0700
+Subject: [PATCH] Add ASPEED SGPIO driver.
+
+Port aspeed sgpio driver to OBMC Kernel and
+enable it on Purley config. Based off AST sdk 4.0.
+
+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 | 416 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 425 insertions(+)
+ create mode 100644 drivers/gpio/sgpio-aspeed.c
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index b5a2845347ec..e3ce2b68a1fc 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -124,6 +124,14 @@ config GPIO_ASPEED
+ help
+ Say Y here to support Aspeed AST2400 and AST2500 GPIO controllers.
+
++config SGPIO_ASPEED
++ bool "ASPEED SGPIO support"
++ depends on ARCH_ASPEED
++ 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 37628f8dbf70..069155f1db9e 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
+ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
+ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
+ obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
++obj-$(CONFIG_SGPIO_ASPEED) += sgpio-aspeed.o
+ obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
+ obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
+diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c
+new file mode 100644
+index 000000000000..9c4add74602a
+--- /dev/null
++++ b/drivers/gpio/sgpio-aspeed.c
+@@ -0,0 +1,416 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (C) 2012-2017 ASPEED Technology Inc.
++// Copyright (c) 2018 Intel Corporation
++
++#include <asm/mach/irq.h>
++#include <linux/bitfield.h>
++#include <linux/gpio/driver.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/platform_device.h>
++
++#ifdef ARCH_NR_GPIOS
++#undef ARCH_NR_GPIOS
++#endif
++
++// TODO: move this to aspeed_sgpio_of_table
++#if defined(CONFIG_MACH_ASPEED_G5)
++#define GPIO_PORT_NUM 29
++#elif defined(CONFIG_MACH_ASPEED_G4)
++#define GPIO_PORT_NUM 28
++#endif
++
++// TODO: fix defines
++#define GPIOS_PER_PORT 8
++#define ARCH_NR_GPIOS (GPIOS_PER_PORT * GPIO_PORT_NUM)
++#define ASPEED_SGPIO_CTRL 0x54
++#define SGPIO_CHAIN_CHIP_BASE ARCH_NR_GPIOS
++#define SGPIO_GROUP_NUMS 10
++
++#define ASPEED_VIC_NUMS 64
++#define ASPEED_FIQ_NUMS 64
++#define ARCH_NR_I2C 14
++
++#define IRQ_I2C_CHAIN_START (ASPEED_VIC_NUMS + ASPEED_FIQ_NUMS)
++#define IRQ_GPIO_CHAIN_START (IRQ_I2C_CHAIN_START + ARCH_NR_I2C)
++#define IRQ_SGPIO_CHAIN_START (IRQ_GPIO_CHAIN_START + ARCH_NR_GPIOS)
++
++#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6)
++#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
++#define ASPEED_SGPIO_ENABLE BIT(0)
++
++struct aspeed_sgpio {
++ struct device *dev;
++ int mirq; /* master irq */
++ void __iomem *base;
++// TODO: make below members as a struct member
++ uint index;
++ uint data_offset;
++ uint data_read_offset;
++ uint int_en_offset;
++ uint int_type_offset;
++ uint int_sts_offset;
++ uint rst_tol_offset;
++ struct gpio_chip chip;
++};
++
++uint aspeed_sgpio_to_irq(uint gpio)
++{
++ return (gpio + IRQ_SGPIO_CHAIN_START);
++}
++EXPORT_SYMBOL(aspeed_sgpio_to_irq);
++
++uint aspeed_irq_to_sgpio(uint irq)
++{
++ return (irq - IRQ_SGPIO_CHAIN_START);
++}
++EXPORT_SYMBOL(aspeed_irq_to_sgpio);
++
++static int aspeed_sgpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct aspeed_sgpio *priv = gpiochip_get_data(chip);
++ uint bit_nr = priv->index * GPIOS_PER_PORT + offset;
++ unsigned long flags;
++ u32 v;
++
++ local_irq_save(flags);
++
++ v = readl(priv->base + priv->data_offset);
++ v &= BIT(bit_nr);
++
++ if (v)
++ v = 1;
++ else
++ v = 0;
++
++ local_irq_restore(flags);
++
++ dev_dbg(priv->dev, "%s, %s[%d]: %d\n", __func__, chip->label,
++ offset, v);
++
++ return v;
++}
++
++static void aspeed_sgpio_set(struct gpio_chip *chip, unsigned offset, int val)
++{
++ struct aspeed_sgpio *priv = gpiochip_get_data(chip);
++ uint bit_nr = priv->index * GPIOS_PER_PORT + offset;
++ unsigned long flags;
++ u32 v;
++
++ local_irq_save(flags);
++
++ v = readl(priv->base + priv->data_read_offset);
++
++ if (val)
++ v |= BIT(bit_nr);
++ else
++ v &= ~BIT(bit_nr);
++
++ writel(v, priv->base + priv->data_offset);
++
++ dev_dbg(priv->dev, "%s, %s[%d]: %d\n", __func__, chip->label,
++ offset, val);
++
++ local_irq_restore(flags);
++}
++
++#define SGPIO_BANK(name, index_no, data, read_data, int_en, int_type, \
++ int_sts, rst_tol, chip_base_idx) { \
++ .index = index_no, \
++ .data_offset = data, \
++ .data_read_offset = read_data, \
++ .int_en_offset = int_en, \
++ .int_type_offset = int_type, \
++ .int_sts_offset = int_sts, \
++ .rst_tol_offset = rst_tol, \
++ .chip = { \
++ .label = name, \
++ .get = aspeed_sgpio_get, \
++ .set = aspeed_sgpio_set, \
++ .base = SGPIO_CHAIN_CHIP_BASE + chip_base_idx * 8, \
++ .ngpio = GPIOS_PER_PORT, \
++ }, \
++}
++
++// TODO: use a single priv after changing it as an array member of the priv
++static struct aspeed_sgpio aspeed_sgpio_gp[] = {
++ SGPIO_BANK("SGPIOA", 0, 0x000, 0x070, 0x004, 0x008, 0x014, 0x018, 0),
++ SGPIO_BANK("SGPIOB", 1, 0x000, 0x070, 0x004, 0x008, 0x014, 0x018, 1),
++ SGPIO_BANK("SGPIOC", 2, 0x000, 0x070, 0x004, 0x008, 0x014, 0x018, 2),
++ SGPIO_BANK("SGPIOD", 3, 0x000, 0x070, 0x004, 0x008, 0x014, 0x018, 3),
++ SGPIO_BANK("SGPIOE", 0, 0x01C, 0x074, 0x020, 0x024, 0x030, 0x034, 4),
++ SGPIO_BANK("SGPIOF", 1, 0x01C, 0x074, 0x020, 0x024, 0x030, 0x034, 5),
++ SGPIO_BANK("SGPIOG", 2, 0x01C, 0x074, 0x020, 0x024, 0x030, 0x034, 6),
++ SGPIO_BANK("SGPIOH", 3, 0x01C, 0x074, 0x020, 0x024, 0x030, 0x034, 7),
++ SGPIO_BANK("SGPIOI", 0, 0x038, 0x078, 0x03C, 0x040, 0x04C, 0x050, 8),
++ SGPIO_BANK("SGPIOJ", 1, 0x038, 0x078, 0x03C, 0x040, 0x04C, 0x050, 9),
++};
++
++/**
++ * We need to unmask the GPIO bank interrupt as soon as possible to avoid
++ * missing GPIO interrupts for other lines in the bank. Then we need to
++ * mask-read-clear-unmask the triggered GPIO lines in the bank to avoid missing
++ * nested interrupts for a GPIO line. If we wait to unmask individual GPIO lines
++ * in the bank after the line's interrupt handler has been run, we may miss some
++ * nested interrupts.
++ */
++static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
++{
++ struct irq_chip *chip = irq_desc_get_chip(desc);
++ struct aspeed_sgpio *priv = irq_desc_get_chip_data(desc);
++ u32 isr;
++ int i;
++
++ chained_irq_enter(chip, desc);
++
++ isr = readl(priv->base + priv->int_sts_offset);
++ isr = (isr >> (GPIOS_PER_PORT * priv->index)) & 0xff;
++
++ dev_dbg(priv->dev, "[%s] isr %x \n", priv->chip.label, isr);
++
++ if (isr != 0) {
++ for (i = 0; i < GPIOS_PER_PORT; i++) {
++ if (BIT(i) & isr)
++ generic_handle_irq(i * GPIOS_PER_PORT +
++ i + IRQ_SGPIO_CHAIN_START);
++ }
++ }
++
++ chained_irq_exit(chip, desc);
++}
++
++static void aspeed_sgpio_ack_irq(struct irq_data *d)
++{
++ struct aspeed_sgpio *priv = irq_get_chip_data(d->irq);
++ uint sgpio_irq = (d->irq - IRQ_SGPIO_CHAIN_START) % GPIOS_PER_PORT;
++ uint bit_nr = priv->index * GPIOS_PER_PORT + sgpio_irq;
++
++ dev_dbg(priv->dev, "irq %d: %s [%s] pin %d\n", d->irq, __func__,
++ priv->chip.label, sgpio_irq);
++
++ writel(BIT(bit_nr), priv->base + priv->int_sts_offset);
++}
++
++static void aspeed_sgpio_mask_irq(struct irq_data *d)
++{
++ struct aspeed_sgpio *priv = irq_get_chip_data(d->irq);
++ uint sgpio_irq = (d->irq - IRQ_SGPIO_CHAIN_START) % GPIOS_PER_PORT;
++ uint bit_nr = priv->index * GPIOS_PER_PORT + sgpio_irq;
++
++ /* Disable IRQ */
++ writel(readl(priv->base + priv->int_en_offset) & ~BIT(bit_nr),
++ priv->base + priv->int_en_offset);
++
++ dev_dbg(priv->dev, "irq %d: %s [%s] pin %d\n ", d->irq, __func__,
++ priv->chip.label, sgpio_irq);
++}
++
++static void aspeed_sgpio_unmask_irq(struct irq_data *d)
++{
++ struct aspeed_sgpio *priv = irq_data_get_irq_chip_data(d);
++ u32 sgpio_irq = (d->irq - IRQ_SGPIO_CHAIN_START) % GPIOS_PER_PORT;
++ uint bit_nr = priv->index * GPIOS_PER_PORT + sgpio_irq;
++
++ /* Enable IRQ */
++ writel(BIT(bit_nr), priv->base + priv->int_sts_offset);
++ writel(readl(priv->base + priv->int_en_offset) | BIT(bit_nr),
++ priv->base + priv->int_en_offset);
++
++ dev_dbg(priv->dev, "irq %d: %s [%s] pin %d\n", d->irq, __func__,
++ priv->chip.label, sgpio_irq);
++}
++
++static int aspeed_sgpio_irq_type(struct irq_data *d, unsigned int type)
++{
++ unsigned int irq = d->irq;
++ struct aspeed_sgpio *priv = irq_get_chip_data(irq);
++ u32 sgpio_irq = (irq - IRQ_SGPIO_CHAIN_START) % GPIOS_PER_PORT;
++ u32 type0, type1, type2;
++
++ dev_dbg(priv->dev, "irq: %d, sgpio_irq: %d , irq_type: 0x%x\n",
++ irq, sgpio_irq, type);
++
++ if (type & ~IRQ_TYPE_SENSE_MASK)
++ return -EINVAL;
++
++ type0 = readl(priv->base + priv->int_type_offset);
++ type1 = readl(priv->base + priv->int_type_offset + 0x04);
++ type2 = readl(priv->base + priv->int_type_offset + 0x08);
++
++ switch (type) {
++ /* Edge rising type */
++ case IRQ_TYPE_EDGE_RISING:
++ type0 |= BIT(sgpio_irq);
++ type1 &= ~BIT(sgpio_irq);
++ type2 &= ~BIT(sgpio_irq);
++ break;
++ /* Edge falling type */
++ case IRQ_TYPE_EDGE_FALLING:
++ type2 |= BIT(sgpio_irq);
++ break;
++ case IRQ_TYPE_EDGE_BOTH:
++ type0 &= ~BIT(sgpio_irq);
++ type1 |= BIT(sgpio_irq);
++ type2 &= ~BIT(sgpio_irq);
++ break;
++ case IRQ_TYPE_LEVEL_HIGH:
++ type0 |= BIT(sgpio_irq);
++ type1 |= BIT(sgpio_irq);
++ type2 &= ~BIT(sgpio_irq);
++ break;
++ case IRQ_TYPE_LEVEL_LOW:
++ type0 &= ~BIT(sgpio_irq);
++ type1 |= BIT(sgpio_irq);
++ type2 &= ~BIT(sgpio_irq);
++ break;
++ default:
++ dev_dbg(priv->dev, "not supported trigger type: %d", type);
++ return -EINVAL;
++ break;
++ }
++
++ writel(type0, priv->base + priv->int_type_offset);
++ writel(type1, priv->base + priv->int_type_offset + 0x04);
++ writel(type2, priv->base + priv->int_type_offset + 0x08);
++
++ return 0;
++}
++
++static struct irq_chip aspeed_sgpio_irq_chip = {
++ .name = "aspeed-sgpio",
++ .irq_ack = aspeed_sgpio_ack_irq,
++ .irq_mask = aspeed_sgpio_mask_irq,
++ .irq_unmask = aspeed_sgpio_unmask_irq,
++ .irq_set_type = aspeed_sgpio_irq_type,
++};
++
++static int aspeed_sgpio_config(struct aspeed_sgpio *priv)
++{
++ /**
++ * There is a limitation that SGPIO clock division has to be larger or
++ * equal to 1. And the value of clock division read back is left shift
++ * 1 bit from 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 example, SGPIO clock is 1MHz and number of SGPIO is 80 then each
++ * SGPIO will be updated in every 80us.
++ */
++ writel(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, 10) |
++ FIELD_PREP(ASPEED_SGPIO_PINS_MASK, SGPIO_GROUP_NUMS) |
++ ASPEED_SGPIO_ENABLE,
++ priv->base + ASPEED_SGPIO_CTRL);
++ dev_dbg(priv->dev, "sgpio config reg: 0x%08X\n",
++ readl(priv->base + ASPEED_SGPIO_CTRL));
++
++ return 0;
++}
++
++static int aspeed_sgpio_probe(struct platform_device *pdev)
++{
++ int i, j;
++ uint irq;
++ struct resource *res;
++ struct aspeed_sgpio *priv;
++ void __iomem *base;
++ int mirq;
++
++ // aspeed_scu_multi_func_sgpio(); done via pinctl
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ mirq = platform_get_irq(pdev, 0);
++ if (!mirq)
++ return -ENODEV;
++
++ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_gp); i++) {
++ // TODO: use heap allocation and use a single priv
++ priv = &aspeed_sgpio_gp[i];
++ priv->dev = &pdev->dev;
++ priv->base = base;
++ priv->mirq = mirq;
++ dev_set_drvdata(&pdev->dev, priv);
++
++ dev_dbg(priv->dev, "add gpio_chip [%s]: %d\n", priv->chip.label,
++ i);
++
++ devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
++
++ /* Disable Interrupt & Clear Status & Set Level-High Trigger */
++ writel(0x00000000, priv->base + priv->int_en_offset);
++ writel(0xffffffff, priv->base + priv->int_sts_offset);
++ writel(0xffffffff, priv->base + priv->int_type_offset);
++ writel(0xffffffff, priv->base + priv->int_type_offset + 0x04);
++ writel(0x00000000, priv->base + priv->int_type_offset + 0x08);
++
++ // TODO: no this many chip registration is needed. fix it.
++ for (j = 0; j < GPIOS_PER_PORT; j++) {
++ irq = i * GPIOS_PER_PORT + j + IRQ_SGPIO_CHAIN_START;
++ dev_dbg(priv->dev, "inst chip data %d\n", irq);
++ irq_set_chip_data(irq, priv);
++ irq_set_chip_and_handler(irq, &aspeed_sgpio_irq_chip,
++ handle_level_irq);
++ irq_clear_status_flags(irq, IRQ_NOREQUEST);
++ }
++ }
++
++ irq_set_chained_handler(priv->mirq, aspeed_sgpio_irq_handler);
++
++ aspeed_sgpio_config(priv);
++
++ dev_info(&pdev->dev, "sgpio controller registered, irq %d\n",
++ priv->mirq);
++
++ return 0;
++}
++
++static int aspeed_sgpio_remove(struct platform_device *pdev)
++{
++ struct aspeed_sgpio *priv =
++ &aspeed_sgpio_gp[ARRAY_SIZE(aspeed_sgpio_gp) - 1];
++
++ irq_set_chained_handler(priv->mirq, NULL);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_sgpio_of_table[] = {
++ { .compatible = "aspeed,ast2400-sgpio", },
++ { .compatible = "aspeed,ast2500-sgpio", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
++
++static struct platform_driver aspeed_sgpio_driver = {
++ .probe = aspeed_sgpio_probe,
++ .remove = aspeed_sgpio_remove,
++ .driver = {
++ .name = "sgpio-aspeed",
++ .of_match_table = of_match_ptr(aspeed_sgpio_of_table),
++ },
++};
++
++static int __init aspeed_sgpio_init(void)
++{
++ return platform_driver_register(&aspeed_sgpio_driver);
++}
++subsys_initcall(aspeed_sgpio_init);
++
++static void __exit aspeed_sgpio_exit(void)
++{
++ platform_driver_unregister(&aspeed_sgpio_driver);
++}
++module_exit(aspeed_sgpio_exit);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("ASPEED SGPIO driver");
++MODULE_LICENSE("GPL v2");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch
new file mode 100644
index 000000000..1c5d9ab53
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch
@@ -0,0 +1,240 @@
+From 2f895fe17cd72124b2a04af306f9349e5da90a6c 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 | 54 ++++++++++--------------------
+ arch/arm/boot/dts/aspeed-g5.dtsi | 8 +++++
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c | 48 +++++++++++++-------------
+ drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 4 +++
+ 4 files changed, 54 insertions(+), 60 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 3990aed25ee6..19f721118b52 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -203,6 +203,18 @@
+ #interrupt-cells = <2>;
+ };
+
++ sgpio: sgpio@1e780200 {
++ #gpio-cells = <2>;
++ gpio-controller;
++ compatible = "aspeed,ast2400-sgpio";
++ reg = <0x1e780200 0x0100>;
++ interrupts = <40>;
++ interrupt-controller;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_sgpm_default>;
++ status = "disabled";
++ };
++
+ timer: timer@1e782000 {
+ /* This timer is a Faraday FTTMR010 derivative */
+ compatible = "aspeed,ast2400-timer";
+@@ -1183,44 +1195,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 0c74adf739d2..d4c99b82f7bd 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -276,6 +276,9 @@
+ reg = <0x1e780200 0x0100>;
+ interrupts = <40>;
+ interrupt-controller;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_sgpm_default>;
++ status = "disabled";
+ };
+
+ rtc: rtc@1e781000 {
+@@ -1388,6 +1391,11 @@
+ groups = "SDA2";
+ };
+
++ pinctrl_sgpm_default: sgpm_default {
++ function = "SGPM";
++ groups = "SGPM";
++ };
++
+ pinctrl_sgps1_default: sgps1_default {
+ function = "SGPS1";
+ groups = "SGPS1";
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+index 05b153034517..353af05b8602 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
+@@ -401,16 +401,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(SGPSCK, SGPS, SIG_DESC_SET(SCU84, 0));
++SS_PIN_DECL(A14, GPIOG0, SGPSCK);
+
+ #define E13 49
+-SSSF_PIN_DECL(E13, GPIOG1, SGPSLD, SIG_DESC_SET(SCU84, 1));
++SIG_EXPR_LIST_DECL_SINGLE(SGPSLD, SGPS, SIG_DESC_SET(SCU84, 1));
++SS_PIN_DECL(E13, GPIOG1, SGPSLD);
+
+ #define D13 50
+-SSSF_PIN_DECL(D13, GPIOG2, SGPSI0, SIG_DESC_SET(SCU84, 2));
++SIG_EXPR_LIST_DECL_SINGLE(SGPSIO, SGPS, SIG_DESC_SET(SCU84, 2));
++SS_PIN_DECL(D13, GPIOG2, SGPSIO);
+
+ #define C13 51
+-SSSF_PIN_DECL(C13, GPIOG3, SGPSI1, SIG_DESC_SET(SCU84, 3));
++SIG_EXPR_LIST_DECL_SINGLE(SGPSI1, SGPS, SIG_DESC_SET(SCU84, 3));
++SS_PIN_DECL(C13, GPIOG3, SGPSI1);
++
++FUNC_GROUP_DECL(SGPS, A14, E13, D13, C13);
+
+ #define B13 52
+ SIG_EXPR_LIST_DECL_SINGLE(OSCCLK, OSCCLK, SIG_DESC_SET(SCU2C, 1));
+@@ -576,16 +582,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(SGPMCK, SGPM, SIG_DESC_SET(SCU84, 8));
++SS_PIN_DECL(J5, GPIOJ0, SGPMCK);
+
+ #define J4 73
+-SSSF_PIN_DECL(J4, GPIOJ1, SGPMLD, SIG_DESC_SET(SCU84, 9));
++SIG_EXPR_LIST_DECL_SINGLE(SGPMLD, SGPM, SIG_DESC_SET(SCU84, 9));
++SS_PIN_DECL(J4, GPIOJ1, SGPMLD);
+
+ #define K5 74
+-SSSF_PIN_DECL(K5, GPIOJ2, SGPMO, SIG_DESC_SET(SCU84, 10));
++SIG_EXPR_LIST_DECL_SINGLE(SGPMO, SGPM, SIG_DESC_SET(SCU84, 10));
++SS_PIN_DECL(K5, GPIOJ2, SGPMO);
+
+ #define J3 75
+-SSSF_PIN_DECL(J3, GPIOJ3, SGPMI, SIG_DESC_SET(SCU84, 11));
++SIG_EXPR_LIST_DECL_SINGLE(SGPMI, SGPM, SIG_DESC_SET(SCU84, 11));
++SS_PIN_DECL(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));
+@@ -2083,14 +2095,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),
+@@ -2238,14 +2244,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),
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+index 4230e1038a88..13f749e35001 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+@@ -577,6 +577,8 @@ SS_PIN_DECL(N3, GPIOJ2, SGPMO);
+ SIG_EXPR_LIST_DECL_SINGLE(SGPMI, SGPM, SIG_DESC_SET(SCU84, 11));
+ SS_PIN_DECL(N4, GPIOJ3, SGPMI);
+
++FUNC_GROUP_DECL(SGPM, R2, L2, N3, N4);
++
+ #define N5 76
+ SIG_EXPR_LIST_DECL_SINGLE(VGAHS, VGAHS, SIG_DESC_SET(SCU84, 12));
+ SIG_EXPR_LIST_DECL_SINGLE(DASHN5, DASHN5, SIG_DESC_SET(SCU94, 8));
+@@ -2127,6 +2129,7 @@ static const struct aspeed_pin_group aspeed_g5_groups[] = {
+ ASPEED_PINCTRL_GROUP(SD2),
+ ASPEED_PINCTRL_GROUP(SDA1),
+ ASPEED_PINCTRL_GROUP(SDA2),
++ ASPEED_PINCTRL_GROUP(SGPM),
+ ASPEED_PINCTRL_GROUP(SGPS1),
+ ASPEED_PINCTRL_GROUP(SGPS2),
+ ASPEED_PINCTRL_GROUP(SIOONCTRL),
+@@ -2296,6 +2299,7 @@ static const struct aspeed_pin_function aspeed_g5_functions[] = {
+ ASPEED_PINCTRL_FUNC(SD2),
+ ASPEED_PINCTRL_FUNC(SDA1),
+ ASPEED_PINCTRL_FUNC(SDA2),
++ ASPEED_PINCTRL_FUNC(SGPM),
+ ASPEED_PINCTRL_FUNC(SGPS1),
+ ASPEED_PINCTRL_FUNC(SGPS2),
+ ASPEED_PINCTRL_FUNC(SIOONCTRL),
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch
new file mode 100644
index 000000000..d2ecdfd72
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch
@@ -0,0 +1,5395 @@
+From 9c27803dd432c7a9fc57dd3e16f0fd724919575e Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 7 Jan 2019 09:56:10 -0800
+Subject: [PATCH] Update PECI drivers to sync with linux upstreaming version
+
+Upstreaming is in holding. It's for adding DTS sensor with PECI
+subsystem code update.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ Documentation/hwmon/peci-cputemp | 34 +-
+ drivers/hwmon/Kconfig | 4 +-
+ drivers/hwmon/peci-cputemp.c | 162 ++++--
+ drivers/hwmon/peci-dimmtemp.c | 69 +--
+ drivers/hwmon/peci-hwmon.h | 9 +-
+ drivers/mfd/Kconfig | 5 +-
+ drivers/mfd/intel-peci-client.c | 49 +-
+ drivers/peci/Kconfig | 46 +-
+ drivers/peci/Makefile | 7 +-
+ drivers/peci/busses/Kconfig | 32 ++
+ drivers/peci/busses/Makefile | 7 +
+ drivers/peci/busses/peci-aspeed.c | 494 +++++++++++++++++++
+ drivers/peci/busses/peci-npcm.c | 410 +++++++++++++++
+ drivers/peci/peci-aspeed.c | 505 -------------------
+ drivers/peci/peci-core.c | 905 +++++++++++++++++++---------------
+ drivers/peci/peci-dev.c | 346 +++++++++++++
+ drivers/peci/peci-npcm.c | 410 ---------------
+ include/linux/mfd/intel-peci-client.h | 32 +-
+ include/linux/peci.h | 30 +-
+ include/uapi/linux/peci-ioctl.h | 416 +++++++++-------
+ 20 files changed, 2296 insertions(+), 1676 deletions(-)
+ create mode 100644 drivers/peci/busses/Kconfig
+ create mode 100644 drivers/peci/busses/Makefile
+ create mode 100644 drivers/peci/busses/peci-aspeed.c
+ create mode 100644 drivers/peci/busses/peci-npcm.c
+ delete mode 100644 drivers/peci/peci-aspeed.c
+ create mode 100644 drivers/peci/peci-dev.c
+ delete mode 100644 drivers/peci/peci-npcm.c
+
+diff --git a/Documentation/hwmon/peci-cputemp b/Documentation/hwmon/peci-cputemp
+index 821a9258f2e6..a3a3e465c888 100644
+--- a/Documentation/hwmon/peci-cputemp
++++ b/Documentation/hwmon/peci-cputemp
+@@ -51,28 +51,38 @@ temp1_crit Provides shutdown temperature of the CPU package which
+ temp1_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of
+ the CPU package.
+
+-temp2_label "Tcontrol"
+-temp2_input Provides current Tcontrol temperature of the CPU
++temp2_label "DTS"
++temp2_input Provides current DTS temperature of the CPU package.
++temp2_max Provides thermal control temperature of the CPU package
++ which is also known as Tcontrol.
++temp2_crit Provides shutdown temperature of the CPU package which
++ is also known as the maximum processor junction
++ temperature, Tjmax or Tprochot.
++temp2_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of
++ the CPU package.
++
++temp3_label "Tcontrol"
++temp3_input Provides current Tcontrol temperature of the CPU
+ package which is also known as Fan Temperature target.
+ Indicates the relative value from thermal monitor trip
+ temperature at which fans should be engaged.
+-temp2_crit Provides Tcontrol critical value of the CPU package
++temp3_crit Provides Tcontrol critical value of the CPU package
+ which is same to Tjmax.
+
+-temp3_label "Tthrottle"
+-temp3_input Provides current Tthrottle temperature of the CPU
++temp4_label "Tthrottle"
++temp4_input Provides current Tthrottle temperature of the CPU
+ package. Used for throttling temperature. If this value
+ is allowed and lower than Tjmax - the throttle will
+ occur and reported at lower than Tjmax.
+
+-temp4_label "Tjmax"
+-temp4_input Provides the maximum junction temperature, Tjmax of the
++temp5_label "Tjmax"
++temp5_input Provides the maximum junction temperature, Tjmax of the
+ CPU package.
+
+-temp[5-*]_label Provides string "Core X", where X is resolved core
++temp[6-*]_label Provides string "Core X", where X is resolved core
+ number.
+-temp[5-*]_input Provides current temperature of each core.
+-temp[5-*]_max Provides thermal control temperature of the core.
+-temp[5-*]_crit Provides shutdown temperature of the core.
+-temp[5-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of
++temp[6-*]_input Provides current temperature of each core.
++temp[6-*]_max Provides thermal control temperature of the core.
++temp[6-*]_crit Provides shutdown temperature of the core.
++temp[6-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of
+ the core.
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 18cd3b17f660..0bd06a938526 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -1321,7 +1321,7 @@ config SENSORS_PECI_CPUTEMP
+ the PECI Client Command Suite via the processor PECI client.
+ Check Documentation/hwmon/peci-cputemp for details.
+
+- This driver can also be built as a module. If so, the module
++ This driver can also be built as a module. If so, the module
+ will be called peci-cputemp.
+
+ config SENSORS_PECI_DIMMTEMP
+@@ -1335,7 +1335,7 @@ config SENSORS_PECI_DIMMTEMP
+ Suite via the processor PECI client.
+ Check Documentation/hwmon/peci-dimmtemp for details.
+
+- This driver can also be built as a module. If so, the module
++ This driver can also be built as a module. If so, the module
+ will be called peci-dimmtemp.
+
+ source "drivers/hwmon/pmbus/Kconfig"
+diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c
+index 11880c86a854..3cb2db2fdf0a 100644
+--- a/drivers/hwmon/peci-cputemp.c
++++ b/drivers/hwmon/peci-cputemp.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0
+-// Copyright (c) 2018 Intel Corporation
++// Copyright (c) 2018-2019 Intel Corporation
+
+ #include <linux/hwmon.h>
+ #include <linux/jiffies.h>
+@@ -9,7 +9,7 @@
+ #include <linux/platform_device.h>
+ #include "peci-hwmon.h"
+
+-#define DEFAULT_CHANNEL_NUMS 4
++#define DEFAULT_CHANNEL_NUMS 5
+ #define CORETEMP_CHANNEL_NUMS CORE_NUMS_MAX
+ #define CPUTEMP_CHANNEL_NUMS (DEFAULT_CHANNEL_NUMS + CORETEMP_CHANNEL_NUMS)
+
+@@ -21,6 +21,7 @@
+
+ struct temp_group {
+ struct temp_data die;
++ struct temp_data dts;
+ struct temp_data tcontrol;
+ struct temp_data tthrottle;
+ struct temp_data tjmax;
+@@ -43,6 +44,7 @@ struct peci_cputemp {
+
+ enum cputemp_channels {
+ channel_die,
++ channel_dts,
+ channel_tcontrol,
+ channel_tthrottle,
+ channel_tjmax,
+@@ -54,6 +56,10 @@ static const u32 config_table[DEFAULT_CHANNEL_NUMS + 1] = {
+ HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
+ HWMON_T_CRIT_HYST,
+
++ /* DTS margin */
++ HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
++ HWMON_T_CRIT_HYST,
++
+ /* Tcontrol temperature */
+ HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_CRIT,
+
+@@ -70,6 +76,7 @@ static const u32 config_table[DEFAULT_CHANNEL_NUMS + 1] = {
+
+ static const char *cputemp_label[CPUTEMP_CHANNEL_NUMS] = {
+ "Die",
++ "DTS",
+ "Tcontrol",
+ "Tthrottle",
+ "Tjmax",
+@@ -92,19 +99,20 @@ static int get_temp_targets(struct peci_cputemp *priv)
+ s32 tthrottle_offset;
+ s32 tcontrol_margin;
+ u8 pkg_cfg[4];
+- int rc;
++ int ret;
+
+- /**
++ /*
+ * Just use only the tcontrol marker to determine if target values need
+ * update.
+ */
+ if (!peci_temp_need_update(&priv->temp.tcontrol))
+ return 0;
+
+- rc = peci_client_read_package_config(priv->mgr,
+- MBX_INDEX_TEMP_TARGET, 0, pkg_cfg);
+- if (rc)
+- return rc;
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_TEMP_TARGET, 0,
++ pkg_cfg);
++ if (ret)
++ return ret;
+
+ priv->temp.tjmax.value = pkg_cfg[2] * 1000;
+
+@@ -123,17 +131,16 @@ static int get_temp_targets(struct peci_cputemp *priv)
+ static int get_die_temp(struct peci_cputemp *priv)
+ {
+ struct peci_get_temp_msg msg;
+- int rc;
++ int ret;
+
+ if (!peci_temp_need_update(&priv->temp.die))
+ return 0;
+
+ msg.addr = priv->mgr->client->addr;
+
+- rc = peci_command(priv->mgr->client->adapter, PECI_CMD_GET_TEMP,
+- &msg);
+- if (rc)
+- return rc;
++ ret = peci_command(priv->mgr->client->adapter, PECI_CMD_GET_TEMP, &msg);
++ if (ret)
++ return ret;
+
+ /* Note that the tjmax should be available before calling it */
+ priv->temp.die.value = priv->temp.tjmax.value +
+@@ -144,24 +151,70 @@ static int get_die_temp(struct peci_cputemp *priv)
+ return 0;
+ }
+
++static int get_dts(struct peci_cputemp *priv)
++{
++ struct peci_rd_pkg_cfg_msg msg;
++ s32 dts_margin;
++ int ret;
++
++ if (!peci_temp_need_update(&priv->temp.dts))
++ return 0;
++
++ msg.addr = priv->mgr->client->addr;
++ msg.index = PECI_MBX_INDEX_DTS_MARGIN;
++ msg.param = 0;
++ msg.rx_len = 4;
++
++ ret = peci_command(priv->mgr->client->adapter, PECI_CMD_RD_PKG_CFG,
++ &msg);
++ if (ret)
++ return ret;
++
++ if (msg.cc != PECI_DEV_CC_SUCCESS)
++ return -EAGAIN;
++
++ dts_margin = (msg.pkg_config[1] << 8) | msg.pkg_config[0];
++
++ /**
++ * Processors return a value of DTS reading in 10.6 format
++ * (10 bits signed decimal, 6 bits fractional).
++ * Error codes:
++ * 0x8000: General sensor error
++ * 0x8001: Reserved
++ * 0x8002: Underflow on reading value
++ * 0x8003-0x81ff: Reserved
++ */
++ if (dts_margin >= 0x8000 && dts_margin <= 0x81ff)
++ return -EIO;
++
++ dts_margin = ten_dot_six_to_millidegree(dts_margin);
++
++ /* Note that the tcontrol should be available before calling it */
++ priv->temp.dts.value = priv->temp.tcontrol.value - dts_margin;
++
++ peci_temp_mark_updated(&priv->temp.dts);
++
++ return 0;
++}
++
+ static int get_core_temp(struct peci_cputemp *priv, int core_index)
+ {
+ s32 core_dts_margin;
+ u8 pkg_cfg[4];
+- int rc;
++ int ret;
+
+ if (!peci_temp_need_update(&priv->temp.core[core_index]))
+ return 0;
+
+- rc = peci_client_read_package_config(priv->mgr,
+- MBX_INDEX_PER_CORE_DTS_TEMP,
+- core_index, pkg_cfg);
+- if (rc)
+- return rc;
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_PER_CORE_DTS_TEMP,
++ core_index, pkg_cfg);
++ if (ret)
++ return ret;
+
+ core_dts_margin = le16_to_cpup((__le16 *)pkg_cfg);
+
+- /**
++ /*
+ * Processors return a value of the core DTS reading in 10.6 format
+ * (10 bits signed decimal, 6 bits fractional).
+ * Error codes:
+@@ -192,6 +245,7 @@ static int cputemp_read_string(struct device *dev,
+ return -EOPNOTSUPP;
+
+ *str = cputemp_label[channel];
++
+ return 0;
+ }
+
+@@ -200,26 +254,33 @@ static int cputemp_read(struct device *dev,
+ u32 attr, int channel, long *val)
+ {
+ struct peci_cputemp *priv = dev_get_drvdata(dev);
+- int rc, core_index;
++ int ret, core_index;
+
+ if (channel >= CPUTEMP_CHANNEL_NUMS ||
+ !(priv->temp_config[channel] & BIT(attr)))
+ return -EOPNOTSUPP;
+
+- rc = get_temp_targets(priv);
+- if (rc)
+- return rc;
++ ret = get_temp_targets(priv);
++ if (ret)
++ return ret;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ switch (channel) {
+ case channel_die:
+- rc = get_die_temp(priv);
+- if (rc)
++ ret = get_die_temp(priv);
++ if (ret)
+ break;
+
+ *val = priv->temp.die.value;
+ break;
++ case channel_dts:
++ ret = get_dts(priv);
++ if (ret)
++ break;
++
++ *val = priv->temp.dts.value;
++ break;
+ case channel_tcontrol:
+ *val = priv->temp.tcontrol.value;
+ break;
+@@ -231,8 +292,8 @@ static int cputemp_read(struct device *dev,
+ break;
+ default:
+ core_index = channel - DEFAULT_CHANNEL_NUMS;
+- rc = get_core_temp(priv, core_index);
+- if (rc)
++ ret = get_core_temp(priv, core_index);
++ if (ret)
+ break;
+
+ *val = priv->temp.core[core_index].value;
+@@ -249,11 +310,11 @@ static int cputemp_read(struct device *dev,
+ *val = priv->temp.tjmax.value - priv->temp.tcontrol.value;
+ break;
+ default:
+- rc = -EOPNOTSUPP;
++ ret = -EOPNOTSUPP;
+ break;
+ }
+
+- return rc;
++ return ret;
+ }
+
+ static umode_t cputemp_is_visible(const void *data,
+@@ -262,11 +323,11 @@ static umode_t cputemp_is_visible(const void *data,
+ {
+ const struct peci_cputemp *priv = data;
+
+- if (priv->temp_config[channel] & BIT(attr))
+- if (channel < DEFAULT_CHANNEL_NUMS ||
+- (channel >= DEFAULT_CHANNEL_NUMS &&
+- (priv->core_mask & BIT(channel - DEFAULT_CHANNEL_NUMS))))
+- return 0444;
++ if ((priv->temp_config[channel] & BIT(attr)) &&
++ (channel < DEFAULT_CHANNEL_NUMS ||
++ (channel >= DEFAULT_CHANNEL_NUMS &&
++ (priv->core_mask & BIT(channel - DEFAULT_CHANNEL_NUMS)))))
++ return 0444;
+
+ return 0;
+ }
+@@ -280,7 +341,7 @@ static const struct hwmon_ops cputemp_ops = {
+ static int check_resolved_cores(struct peci_cputemp *priv)
+ {
+ struct peci_rd_pci_cfg_local_msg msg;
+- int rc;
++ int ret;
+
+ /* Get the RESOLVED_CORES register value */
+ msg.addr = priv->mgr->client->addr;
+@@ -290,30 +351,34 @@ static int check_resolved_cores(struct peci_cputemp *priv)
+ msg.reg = REG_RESOLVED_CORES_OFFSET;
+ msg.rx_len = 4;
+
+- rc = peci_command(priv->mgr->client->adapter,
+- PECI_CMD_RD_PCI_CFG_LOCAL, &msg);
+- if (rc)
+- return rc;
++ ret = peci_command(priv->mgr->client->adapter,
++ PECI_CMD_RD_PCI_CFG_LOCAL, &msg);
++ if (ret)
++ return ret;
++
++ if (msg.cc != PECI_DEV_CC_SUCCESS)
++ return -EAGAIN;
+
+ priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config);
+ if (!priv->core_mask)
+ return -EAGAIN;
+
+ dev_dbg(priv->dev, "Scanned resolved cores: 0x%x\n", priv->core_mask);
++
+ return 0;
+ }
+
+ static int create_core_temp_info(struct peci_cputemp *priv)
+ {
+- int rc, i;
++ int ret, i;
+
+- rc = check_resolved_cores(priv);
+- if (rc)
+- return rc;
++ ret = check_resolved_cores(priv);
++ if (ret)
++ return ret;
+
+ for (i = 0; i < priv->gen_info->core_max; i++)
+ if (priv->core_mask & BIT(i))
+- while (i + DEFAULT_CHANNEL_NUMS >= priv->config_idx)
++ while (priv->config_idx <= i + DEFAULT_CHANNEL_NUMS)
+ priv->temp_config[priv->config_idx++] =
+ config_table[channel_core];
+
+@@ -326,7 +391,7 @@ static int peci_cputemp_probe(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+ struct peci_cputemp *priv;
+ struct device *hwmon_dev;
+- int rc;
++ int ret;
+
+ if ((mgr->client->adapter->cmd_mask &
+ (BIT(PECI_CMD_GET_TEMP) | BIT(PECI_CMD_RD_PKG_CFG))) !=
+@@ -346,12 +411,13 @@ static int peci_cputemp_probe(struct platform_device *pdev)
+ mgr->client->addr - PECI_BASE_ADDR);
+
+ priv->temp_config[priv->config_idx++] = config_table[channel_die];
++ priv->temp_config[priv->config_idx++] = config_table[channel_dts];
+ priv->temp_config[priv->config_idx++] = config_table[channel_tcontrol];
+ priv->temp_config[priv->config_idx++] = config_table[channel_tthrottle];
+ priv->temp_config[priv->config_idx++] = config_table[channel_tjmax];
+
+- rc = create_core_temp_info(priv);
+- if (rc)
++ ret = create_core_temp_info(priv);
++ if (ret)
+ dev_dbg(dev, "Skipped creating core temp info\n");
+
+ priv->chip.ops = &cputemp_ops;
+diff --git a/drivers/hwmon/peci-dimmtemp.c b/drivers/hwmon/peci-dimmtemp.c
+index 86a45a90805b..e088366fd138 100644
+--- a/drivers/hwmon/peci-dimmtemp.c
++++ b/drivers/hwmon/peci-dimmtemp.c
+@@ -1,5 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0
+-// Copyright (c) 2018 Intel Corporation
++// Copyright (c) 2018-2019 Intel Corporation
+
+ #include <linux/hwmon.h>
+ #include <linux/jiffies.h>
+@@ -45,16 +45,16 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no)
+ int dimm_order = dimm_no % priv->gen_info->dimm_idx_max;
+ int chan_rank = dimm_no / priv->gen_info->dimm_idx_max;
+ u8 cfg_data[4];
+- int rc;
++ int ret;
+
+ if (!peci_temp_need_update(&priv->temp[dimm_no]))
+ return 0;
+
+- rc = peci_client_read_package_config(priv->mgr,
+- MBX_INDEX_DDR_DIMM_TEMP,
+- chan_rank, cfg_data);
+- if (rc)
+- return rc;
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_DDR_DIMM_TEMP,
++ chan_rank, cfg_data);
++ if (ret)
++ return ret;
+
+ priv->temp[dimm_no].value = cfg_data[dimm_order] * 1000;
+
+@@ -77,6 +77,7 @@ static int dimmtemp_read_string(struct device *dev,
+ chan_rank = channel / dimm_idx_max;
+ dimm_idx = channel % dimm_idx_max;
+ *str = dimmtemp_label[chan_rank][dimm_idx];
++
+ return 0;
+ }
+
+@@ -84,16 +85,17 @@ static int dimmtemp_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+ {
+ struct peci_dimmtemp *priv = dev_get_drvdata(dev);
+- int rc;
++ int ret;
+
+ if (attr != hwmon_temp_input)
+ return -EOPNOTSUPP;
+
+- rc = get_dimm_temp(priv, channel);
+- if (rc)
+- return rc;
++ ret = get_dimm_temp(priv, channel);
++ if (ret)
++ return ret;
+
+ *val = priv->temp[channel].value;
++
+ return 0;
+ }
+
+@@ -120,16 +122,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
+ {
+ u32 chan_rank_max = priv->gen_info->chan_rank_max;
+ u32 dimm_idx_max = priv->gen_info->dimm_idx_max;
+- int chan_rank, dimm_idx, rc;
++ int chan_rank, dimm_idx, ret;
+ u8 cfg_data[4];
+
+ for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) {
+- rc = peci_client_read_package_config(priv->mgr,
+- MBX_INDEX_DDR_DIMM_TEMP,
+- chan_rank, cfg_data);
+- if (rc) {
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_DDR_DIMM_TEMP,
++ chan_rank, cfg_data);
++ if (ret) {
+ priv->dimm_mask = 0;
+- return rc;
++ return ret;
+ }
+
+ for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++)
+@@ -143,17 +145,18 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
+ return -EAGAIN;
+
+ dev_dbg(priv->dev, "Scanned populated DIMMs: 0x%x\n", priv->dimm_mask);
++
+ return 0;
+ }
+
+ static int create_dimm_temp_info(struct peci_dimmtemp *priv)
+ {
+- int rc, i, config_idx, channels;
++ int ret, i, config_idx, channels;
+ struct device *hwmon_dev;
+
+- rc = check_populated_dimms(priv);
+- if (rc) {
+- if (rc == -EAGAIN) {
++ ret = check_populated_dimms(priv);
++ if (ret) {
++ if (ret == -EAGAIN) {
+ if (priv->retry_count < DIMM_MASK_CHECK_RETRY_MAX) {
+ queue_delayed_work(priv->work_queue,
+ &priv->work_handler,
+@@ -164,11 +167,11 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv)
+ } else {
+ dev_err(priv->dev,
+ "Timeout DIMM temp info creation\n");
+- rc = -ETIMEDOUT;
++ ret = -ETIMEDOUT;
+ }
+ }
+
+- return rc;
++ return ret;
+ }
+
+ channels = priv->gen_info->chan_rank_max *
+@@ -192,12 +195,12 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv)
+ priv,
+ &priv->chip,
+ NULL);
+- rc = PTR_ERR_OR_ZERO(hwmon_dev);
+- if (!rc)
++ ret = PTR_ERR_OR_ZERO(hwmon_dev);
++ if (!ret)
+ dev_dbg(priv->dev, "%s: sensor '%s'\n",
+ dev_name(hwmon_dev), priv->name);
+
+- return rc;
++ return ret;
+ }
+
+ static void create_dimm_temp_info_delayed(struct work_struct *work)
+@@ -205,10 +208,10 @@ static void create_dimm_temp_info_delayed(struct work_struct *work)
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct peci_dimmtemp *priv = container_of(dwork, struct peci_dimmtemp,
+ work_handler);
+- int rc;
++ int ret;
+
+- rc = create_dimm_temp_info(priv);
+- if (rc && rc != -EAGAIN)
++ ret = create_dimm_temp_info(priv);
++ if (ret && ret != -EAGAIN)
+ dev_dbg(priv->dev, "Failed to create DIMM temp info\n");
+ }
+
+@@ -217,7 +220,7 @@ static int peci_dimmtemp_probe(struct platform_device *pdev)
+ struct peci_client_manager *mgr = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct peci_dimmtemp *priv;
+- int rc;
++ int ret;
+
+ if ((mgr->client->adapter->cmd_mask &
+ (BIT(PECI_CMD_GET_TEMP) | BIT(PECI_CMD_RD_PKG_CFG))) !=
+@@ -242,8 +245,8 @@ static int peci_dimmtemp_probe(struct platform_device *pdev)
+
+ INIT_DELAYED_WORK(&priv->work_handler, create_dimm_temp_info_delayed);
+
+- rc = create_dimm_temp_info(priv);
+- if (rc && rc != -EAGAIN) {
++ ret = create_dimm_temp_info(priv);
++ if (ret && ret != -EAGAIN) {
+ dev_err(dev, "Failed to create DIMM temp info\n");
+ goto err_free_wq;
+ }
+@@ -252,7 +255,7 @@ static int peci_dimmtemp_probe(struct platform_device *pdev)
+
+ err_free_wq:
+ destroy_workqueue(priv->work_queue);
+- return rc;
++ return ret;
+ }
+
+ static int peci_dimmtemp_remove(struct platform_device *pdev)
+diff --git a/drivers/hwmon/peci-hwmon.h b/drivers/hwmon/peci-hwmon.h
+index 6ca1855a86bb..ce6b470eae63 100644
+--- a/drivers/hwmon/peci-hwmon.h
++++ b/drivers/hwmon/peci-hwmon.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018 Intel Corporation */
++/* Copyright (c) 2018-2019 Intel Corporation */
+
+ #ifndef __PECI_HWMON_H
+ #define __PECI_HWMON_H
+@@ -29,11 +29,8 @@ struct temp_data {
+ */
+ static inline bool peci_temp_need_update(struct temp_data *temp)
+ {
+- if (temp->valid &&
+- time_before(jiffies, temp->last_updated + UPDATE_INTERVAL))
+- return false;
+-
+- return true;
++ return !temp->valid ||
++ time_after(jiffies, temp->last_updated + UPDATE_INTERVAL);
+ }
+
+ /**
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index 9af5730ad7ba..28087e9cd4da 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -606,7 +606,7 @@ config MFD_INTEL_MSIC
+ devices used in Intel Medfield platforms.
+
+ config MFD_INTEL_PECI_CLIENT
+- bool "Intel PECI client"
++ tristate "Intel PECI client"
+ depends on (PECI || COMPILE_TEST)
+ select MFD_CORE
+ help
+@@ -619,6 +619,9 @@ config MFD_INTEL_PECI_CLIENT
+ Additional drivers must be enabled in order to use the functionality
+ of the device.
+
++ This driver can also be built as a module. If so, the module
++ will be called intel-peci-client.
++
+ config MFD_IPAQ_MICRO
+ bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support"
+ depends on SA1100_H3100 || SA1100_H3600
+diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c
+index d53e4f1078ac..466085fd43b9 100644
+--- a/drivers/mfd/intel-peci-client.c
++++ b/drivers/mfd/intel-peci-client.c
+@@ -1,12 +1,12 @@
+ // SPDX-License-Identifier: GPL-2.0
+-// Copyright (c) 2018 Intel Corporation
++// Copyright (c) 2018-2019 Intel Corporation
+
+ #include <linux/bitfield.h>
+ #include <linux/mfd/core.h>
+ #include <linux/mfd/intel-peci-client.h>
+ #include <linux/module.h>
+-#include <linux/peci.h>
+ #include <linux/of_device.h>
++#include <linux/peci.h>
+
+ #define CPU_ID_MODEL_MASK GENMASK(7, 4)
+ #define CPU_ID_FAMILY_MASK GENMASK(11, 8)
+@@ -18,12 +18,6 @@
+ #define LOWER_BYTE_MASK GENMASK(7, 0)
+ #define UPPER_BYTE_MASK GENMASK(16, 8)
+
+-enum cpu_gens {
+- CPU_GEN_HSX = 0, /* Haswell Xeon */
+- CPU_GEN_BRX, /* Broadwell Xeon */
+- CPU_GEN_SKX, /* Skylake Xeon */
+-};
+-
+ static struct mfd_cell peci_functions[] = {
+ { .name = "peci-cputemp", },
+ { .name = "peci-dimmtemp", },
+@@ -31,19 +25,25 @@ static struct mfd_cell peci_functions[] = {
+ };
+
+ static const struct cpu_gen_info cpu_gen_info_table[] = {
+- [CPU_GEN_HSX] = {
++ { /* Haswell Xeon */
+ .family = 6, /* Family code */
+ .model = INTEL_FAM6_HASWELL_X,
+ .core_max = CORE_MAX_ON_HSX,
+ .chan_rank_max = CHAN_RANK_MAX_ON_HSX,
+ .dimm_idx_max = DIMM_IDX_MAX_ON_HSX },
+- [CPU_GEN_BRX] = {
++ { /* Broadwell Xeon */
+ .family = 6, /* Family code */
+ .model = INTEL_FAM6_BROADWELL_X,
+ .core_max = CORE_MAX_ON_BDX,
+ .chan_rank_max = CHAN_RANK_MAX_ON_BDX,
+ .dimm_idx_max = DIMM_IDX_MAX_ON_BDX },
+- [CPU_GEN_SKX] = {
++ { /* Broadwell Xeon D */
++ .family = 6, /* Family code */
++ .model = INTEL_FAM6_BROADWELL_XEON_D,
++ .core_max = CORE_MAX_ON_XD,
++ .chan_rank_max = CHAN_RANK_MAX_ON_XD,
++ .dimm_idx_max = DIMM_IDX_MAX_ON_XD },
++ { /* Skylake Xeon */
+ .family = 6, /* Family code */
+ .model = INTEL_FAM6_SKYLAKE_X,
+ .core_max = CORE_MAX_ON_SKX,
+@@ -53,16 +53,17 @@ static const struct cpu_gen_info cpu_gen_info_table[] = {
+
+ static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv)
+ {
++ struct device *dev = &priv->client->dev;
+ u32 cpu_id;
+ u16 family;
+ u8 model;
+- int rc;
++ int ret;
+ int i;
+
+- rc = peci_get_cpu_id(priv->client->adapter, priv->client->addr,
+- &cpu_id);
+- if (rc)
+- return rc;
++ ret = peci_get_cpu_id(priv->client->adapter, priv->client->addr,
++ &cpu_id);
++ if (ret)
++ return ret;
+
+ family = FIELD_PREP(LOWER_BYTE_MASK,
+ FIELD_GET(CPU_ID_FAMILY_MASK, cpu_id)) |
+@@ -83,11 +84,11 @@ static int peci_client_get_cpu_gen_info(struct peci_client_manager *priv)
+ }
+
+ if (!priv->gen_info) {
+- dev_err(priv->dev, "Can't support this CPU: 0x%x\n", cpu_id);
+- rc = -ENODEV;
++ dev_err(dev, "Can't support this CPU: 0x%x\n", cpu_id);
++ ret = -ENODEV;
+ }
+
+- return rc;
++ return ret;
+ }
+
+ static int peci_client_probe(struct peci_client *client)
+@@ -103,31 +104,29 @@ static int peci_client_probe(struct peci_client *client)
+
+ dev_set_drvdata(dev, priv);
+ priv->client = client;
+- priv->dev = dev;
+ cpu_no = client->addr - PECI_BASE_ADDR;
+
+ ret = peci_client_get_cpu_gen_info(priv);
+ if (ret)
+ return ret;
+
+- ret = devm_mfd_add_devices(priv->dev, cpu_no, peci_functions,
++ ret = devm_mfd_add_devices(dev, cpu_no, peci_functions,
+ ARRAY_SIZE(peci_functions), NULL, 0, NULL);
+ if (ret < 0) {
+- dev_err(priv->dev, "Failed to register child devices: %d\n",
+- ret);
++ dev_err(dev, "Failed to register child devices: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+ }
+
+-#ifdef CONFIG_OF
++#if IS_ENABLED(CONFIG_OF)
+ static const struct of_device_id peci_client_of_table[] = {
+ { .compatible = "intel,peci-client" },
+ { }
+ };
+ MODULE_DEVICE_TABLE(of, peci_client_of_table);
+-#endif
++#endif /* CONFIG_OF */
+
+ static const struct peci_device_id peci_client_ids[] = {
+ { .name = "peci-client" },
+diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig
+index 7293108fb543..9752feee2454 100644
+--- a/drivers/peci/Kconfig
++++ b/drivers/peci/Kconfig
+@@ -2,10 +2,12 @@
+ # Platform Environment Control Interface (PECI) subsystem configuration
+ #
+
++menu "PECI support"
++
+ config PECI
+- bool "PECI support"
+- select RT_MUTEXES
++ tristate "PECI support"
+ select CRC8
++ default n
+ help
+ The Platform Environment Control Interface (PECI) is a one-wire bus
+ interface that provides a communication channel from Intel processors
+@@ -14,37 +16,23 @@ config PECI
+ If you want PECI support, you should say Y here and also to the
+ specific driver for your bus adapter(s) below.
+
+-if PECI
+-
+-#
+-# PECI hardware bus configuration
+-#
+-
+-menu "PECI Hardware Bus support"
+-
+-config PECI_ASPEED
+- tristate "ASPEED PECI support"
+- select REGMAP_MMIO
+- depends on OF
+- depends on ARCH_ASPEED || COMPILE_TEST
+- help
+- Say Y here if you want support for the Platform Environment Control
+- Interface (PECI) bus adapter driver on the ASPEED SoCs.
++ This support is also available as a module. If so, the module
++ will be called peci-core.
+
+- This support is also available as a module. If so, the module
+- will be called peci-aspeed.
++if PECI
+
+-config PECI_NPCM
+- tristate "Nuvoton NPCM PECI support"
+- select REGMAP_MMIO
+- depends on OF
+- depends on ARCH_NPCM || COMPILE_TEST
++config PECI_CHARDEV
++ tristate "PECI device interface"
+ help
+- Say Y here if you want support for the Platform Environment Control
+- Interface (PECI) bus adapter driver on the Nuvoton NPCM SoCs.
++ Say Y here to use peci-* device files, usually found in the /dev
++ directory on your system. They make it possible to have user-space
++ programs use the PECI bus.
+
+ This support is also available as a module. If so, the module
+- will be called peci-npcm.
+-endmenu
++ will be called peci-dev.
++
++source "drivers/peci/busses/Kconfig"
+
+ endif # PECI
++
++endmenu
+diff --git a/drivers/peci/Makefile b/drivers/peci/Makefile
+index 3326da54a21a..da8b0a33fa42 100644
+--- a/drivers/peci/Makefile
++++ b/drivers/peci/Makefile
+@@ -1,10 +1,11 @@
++# SPDX-License-Identifier: GPL-2.0
+ #
+-# Makefile for the PECI core and bus drivers.
++# Makefile for the PECI core drivers.
+ #
+
+ # Core functionality
+ obj-$(CONFIG_PECI) += peci-core.o
++obj-$(CONFIG_PECI_CHARDEV) += peci-dev.o
+
+ # Hardware specific bus drivers
+-obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o
+-obj-$(CONFIG_PECI_NPCM) += peci-npcm.o
++obj-y += busses/
+diff --git a/drivers/peci/busses/Kconfig b/drivers/peci/busses/Kconfig
+new file mode 100644
+index 000000000000..bfacafb7a7ba
+--- /dev/null
++++ b/drivers/peci/busses/Kconfig
+@@ -0,0 +1,32 @@
++#
++# PECI hardware bus configuration
++#
++
++menu "PECI Hardware Bus support"
++
++config PECI_ASPEED
++ tristate "ASPEED PECI support"
++ depends on ARCH_ASPEED || COMPILE_TEST
++ depends on OF
++ depends on PECI
++ help
++ Say Y here if you want support for the Platform Environment Control
++ Interface (PECI) bus adapter driver on the ASPEED SoCs.
++
++ This support is also available as a module. If so, the module
++ will be called peci-aspeed.
++
++config PECI_NPCM
++ tristate "Nuvoton NPCM PECI support"
++ select REGMAP_MMIO
++ depends on OF
++ depends on ARCH_NPCM || COMPILE_TEST
++ depends on PECI
++ help
++ Say Y here if you want support for the Platform Environment Control
++ Interface (PECI) bus adapter driver on the Nuvoton NPCM SoCs.
++
++ This support is also available as a module. If so, the module
++ will be called peci-npcm.
++
++endmenu
+diff --git a/drivers/peci/busses/Makefile b/drivers/peci/busses/Makefile
+new file mode 100644
+index 000000000000..aa8ce3ae5947
+--- /dev/null
++++ b/drivers/peci/busses/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for the PECI hardware bus drivers.
++#
++
++obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o
++obj-$(CONFIG_PECI_NPCM) += peci-npcm.o
+diff --git a/drivers/peci/busses/peci-aspeed.c b/drivers/peci/busses/peci-aspeed.c
+new file mode 100644
+index 000000000000..8a0dd40730cc
+--- /dev/null
++++ b/drivers/peci/busses/peci-aspeed.c
+@@ -0,0 +1,494 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (C) 2012-2017 ASPEED Technology Inc.
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/peci.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++
++/* ASPEED PECI Registers */
++/* Control Register */
++#define ASPEED_PECI_CTRL 0x00
++#define ASPEED_PECI_CTRL_SAMPLING_MASK GENMASK(19, 16)
++#define ASPEED_PECI_CTRL_READ_MODE_MASK GENMASK(13, 12)
++#define ASPEED_PECI_CTRL_READ_MODE_COUNT BIT(12)
++#define ASPEED_PECI_CTRL_READ_MODE_DBG BIT(13)
++#define ASPEED_PECI_CTRL_CLK_SOURCE_MASK BIT(11)
++#define ASPEED_PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8)
++#define ASPEED_PECI_CTRL_INVERT_OUT BIT(7)
++#define ASPEED_PECI_CTRL_INVERT_IN BIT(6)
++#define ASPEED_PECI_CTRL_BUS_CONTENT_EN BIT(5)
++#define ASPEED_PECI_CTRL_PECI_EN BIT(4)
++#define ASPEED_PECI_CTRL_PECI_CLK_EN BIT(0)
++
++/* Timing Negotiation Register */
++#define ASPEED_PECI_TIMING_NEGOTIATION 0x04
++#define ASPEED_PECI_TIMING_MESSAGE_MASK GENMASK(15, 8)
++#define ASPEED_PECI_TIMING_ADDRESS_MASK GENMASK(7, 0)
++
++/* Command Register */
++#define ASPEED_PECI_CMD 0x08
++#define ASPEED_PECI_CMD_PIN_MON BIT(31)
++#define ASPEED_PECI_CMD_STS_MASK GENMASK(27, 24)
++#define ASPEED_PECI_CMD_IDLE_MASK (ASPEED_PECI_CMD_STS_MASK | \
++ ASPEED_PECI_CMD_PIN_MON)
++#define ASPEED_PECI_CMD_FIRE BIT(0)
++
++/* Read/Write Length Register */
++#define ASPEED_PECI_RW_LENGTH 0x0c
++#define ASPEED_PECI_AW_FCS_EN BIT(31)
++#define ASPEED_PECI_READ_LEN_MASK GENMASK(23, 16)
++#define ASPEED_PECI_WRITE_LEN_MASK GENMASK(15, 8)
++#define ASPEED_PECI_TAGET_ADDR_MASK GENMASK(7, 0)
++
++/* Expected FCS Data Register */
++#define ASPEED_PECI_EXP_FCS 0x10
++#define ASPEED_PECI_EXP_READ_FCS_MASK GENMASK(23, 16)
++#define ASPEED_PECI_EXP_AW_FCS_AUTO_MASK GENMASK(15, 8)
++#define ASPEED_PECI_EXP_WRITE_FCS_MASK GENMASK(7, 0)
++
++/* Captured FCS Data Register */
++#define ASPEED_PECI_CAP_FCS 0x14
++#define ASPEED_PECI_CAP_READ_FCS_MASK GENMASK(23, 16)
++#define ASPEED_PECI_CAP_WRITE_FCS_MASK GENMASK(7, 0)
++
++/* Interrupt Register */
++#define ASPEED_PECI_INT_CTRL 0x18
++#define ASPEED_PECI_TIMING_NEGO_SEL_MASK GENMASK(31, 30)
++#define ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO 0
++#define ASPEED_PECI_2ND_BIT_OF_ADDR_NEGO 1
++#define ASPEED_PECI_MESSAGE_NEGO 2
++#define ASPEED_PECI_INT_MASK GENMASK(4, 0)
++#define ASPEED_PECI_INT_BUS_TIMEOUT BIT(4)
++#define ASPEED_PECI_INT_BUS_CONNECT BIT(3)
++#define ASPEED_PECI_INT_W_FCS_BAD BIT(2)
++#define ASPEED_PECI_INT_W_FCS_ABORT BIT(1)
++#define ASPEED_PECI_INT_CMD_DONE BIT(0)
++
++/* Interrupt Status Register */
++#define ASPEED_PECI_INT_STS 0x1c
++#define ASPEED_PECI_INT_TIMING_RESULT_MASK GENMASK(29, 16)
++ /* bits[4..0]: Same bit fields in the 'Interrupt Register' */
++
++/* Rx/Tx Data Buffer Registers */
++#define ASPEED_PECI_W_DATA0 0x20
++#define ASPEED_PECI_W_DATA1 0x24
++#define ASPEED_PECI_W_DATA2 0x28
++#define ASPEED_PECI_W_DATA3 0x2c
++#define ASPEED_PECI_R_DATA0 0x30
++#define ASPEED_PECI_R_DATA1 0x34
++#define ASPEED_PECI_R_DATA2 0x38
++#define ASPEED_PECI_R_DATA3 0x3c
++#define ASPEED_PECI_W_DATA4 0x40
++#define ASPEED_PECI_W_DATA5 0x44
++#define ASPEED_PECI_W_DATA6 0x48
++#define ASPEED_PECI_W_DATA7 0x4c
++#define ASPEED_PECI_R_DATA4 0x50
++#define ASPEED_PECI_R_DATA5 0x54
++#define ASPEED_PECI_R_DATA6 0x58
++#define ASPEED_PECI_R_DATA7 0x5c
++#define ASPEED_PECI_DATA_BUF_SIZE_MAX 32
++
++/* Timing Negotiation */
++#define ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT 8
++#define ASPEED_PECI_RD_SAMPLING_POINT_MAX 15
++#define ASPEED_PECI_CLK_DIV_DEFAULT 0
++#define ASPEED_PECI_CLK_DIV_MAX 7
++#define ASPEED_PECI_MSG_TIMING_DEFAULT 1
++#define ASPEED_PECI_MSG_TIMING_MAX 255
++#define ASPEED_PECI_ADDR_TIMING_DEFAULT 1
++#define ASPEED_PECI_ADDR_TIMING_MAX 255
++
++/* Timeout */
++#define ASPEED_PECI_IDLE_CHECK_TIMEOUT_USEC 50000
++#define ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC 10000
++#define ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT 1000
++#define ASPEED_PECI_CMD_TIMEOUT_MS_MAX 60000
++
++struct aspeed_peci {
++ struct peci_adapter *adapter;
++ struct device *dev;
++ void __iomem *base;
++ struct clk *clk;
++ struct reset_control *rst;
++ int irq;
++ spinlock_t lock; /* to sync completion status handling */
++ struct completion xfer_complete;
++ u32 status;
++ u32 cmd_timeout_ms;
++};
++
++static int aspeed_peci_check_idle(struct aspeed_peci *priv)
++{
++ ulong timeout = jiffies + usecs_to_jiffies(ASPEED_PECI_IDLE_CHECK_TIMEOUT_USEC);
++ u32 cmd_sts;
++
++ for (;;) {
++ cmd_sts = readl(priv->base + ASPEED_PECI_CMD);
++ if (!(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK))
++ break;
++ if (time_after(jiffies, timeout)) {
++ cmd_sts = readl(priv->base + ASPEED_PECI_CMD);
++ break;
++ }
++ usleep_range((ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC >> 2) + 1,
++ ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC);
++ }
++
++ return !(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK) ? 0 : -ETIMEDOUT;
++}
++
++static int aspeed_peci_xfer(struct peci_adapter *adapter,
++ struct peci_xfer_msg *msg)
++{
++ struct aspeed_peci *priv = peci_get_adapdata(adapter);
++ long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms);
++ u32 peci_head, peci_state, rx_data = 0;
++ ulong flags;
++ int i, ret;
++ uint reg;
++
++ if (msg->tx_len > ASPEED_PECI_DATA_BUF_SIZE_MAX ||
++ msg->rx_len > ASPEED_PECI_DATA_BUF_SIZE_MAX)
++ return -EINVAL;
++
++ /* Check command sts and bus idle state */
++ ret = aspeed_peci_check_idle(priv);
++ if (ret)
++ return ret; /* -ETIMEDOUT */
++
++ spin_lock_irqsave(&priv->lock, flags);
++ reinit_completion(&priv->xfer_complete);
++
++ peci_head = FIELD_PREP(ASPEED_PECI_TAGET_ADDR_MASK, msg->addr) |
++ FIELD_PREP(ASPEED_PECI_WRITE_LEN_MASK, msg->tx_len) |
++ FIELD_PREP(ASPEED_PECI_READ_LEN_MASK, msg->rx_len);
++
++ writel(peci_head, priv->base + ASPEED_PECI_RW_LENGTH);
++
++ for (i = 0; i < msg->tx_len; i += 4) {
++ reg = i < 16 ? ASPEED_PECI_W_DATA0 + i % 16 :
++ ASPEED_PECI_W_DATA4 + i % 16;
++ writel(le32_to_cpup((__le32 *)&msg->tx_buf[i]),
++ priv->base + reg);
++ }
++
++ dev_dbg(priv->dev, "HEAD : 0x%08x\n", peci_head);
++ print_hex_dump_debug("TX : ", DUMP_PREFIX_NONE, 16, 1,
++ msg->tx_buf, msg->tx_len, true);
++
++ priv->status = 0;
++ writel(ASPEED_PECI_CMD_FIRE, priv->base + ASPEED_PECI_CMD);
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ err = wait_for_completion_interruptible_timeout(&priv->xfer_complete,
++ timeout);
++
++ spin_lock_irqsave(&priv->lock, flags);
++ dev_dbg(priv->dev, "INT_STS : 0x%08x\n", priv->status);
++ peci_state = readl(priv->base + ASPEED_PECI_CMD);
++ dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n",
++ FIELD_GET(ASPEED_PECI_CMD_STS_MASK, peci_state));
++
++ writel(0, priv->base + ASPEED_PECI_CMD);
++
++ if (err <= 0 || priv->status != ASPEED_PECI_INT_CMD_DONE) {
++ if (err < 0) { /* -ERESTARTSYS */
++ ret = (int)err;
++ goto err_irqrestore;
++ } else if (err == 0) {
++ dev_dbg(priv->dev, "Timeout waiting for a response!\n");
++ ret = -ETIMEDOUT;
++ goto err_irqrestore;
++ }
++
++ dev_dbg(priv->dev, "No valid response!\n");
++ ret = -EIO;
++ goto err_irqrestore;
++ }
++
++ /*
++ * Note that rx_len and rx_buf size can be an odd number.
++ * Byte handling is more efficient.
++ */
++ for (i = 0; i < msg->rx_len; i++) {
++ u8 byte_offset = i % 4;
++
++ if (byte_offset == 0) {
++ reg = i < 16 ? ASPEED_PECI_R_DATA0 + i % 16 :
++ ASPEED_PECI_R_DATA4 + i % 16;
++ rx_data = readl(priv->base + reg);
++ }
++
++ msg->rx_buf[i] = (u8)(rx_data >> (byte_offset << 3));
++ }
++
++ print_hex_dump_debug("RX : ", DUMP_PREFIX_NONE, 16, 1,
++ msg->rx_buf, msg->rx_len, true);
++
++ peci_state = readl(priv->base + ASPEED_PECI_CMD);
++ dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n",
++ FIELD_GET(ASPEED_PECI_CMD_STS_MASK, peci_state));
++ dev_dbg(priv->dev, "------------------------\n");
++
++err_irqrestore:
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return ret;
++}
++
++static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg)
++{
++ struct aspeed_peci *priv = arg;
++ u32 status;
++
++ spin_lock(&priv->lock);
++ status = readl(priv->base + ASPEED_PECI_INT_STS);
++ writel(status, priv->base + ASPEED_PECI_INT_STS);
++ priv->status |= (status & ASPEED_PECI_INT_MASK);
++
++ /*
++ * In most cases, interrupt bits will be set one by one but also note
++ * that multiple interrupt bits could be set at the same time.
++ */
++ if (status & ASPEED_PECI_INT_BUS_TIMEOUT) {
++ dev_dbg(priv->dev, "ASPEED_PECI_INT_BUS_TIMEOUT\n");
++ }
++
++ if (status & ASPEED_PECI_INT_BUS_CONNECT) {
++ dev_dbg(priv->dev, "ASPEED_PECI_INT_BUS_CONNECT\n");
++ }
++
++ if (status & ASPEED_PECI_INT_W_FCS_BAD) {
++ dev_dbg(priv->dev, "ASPEED_PECI_INT_W_FCS_BAD\n");
++ }
++
++ if (status & ASPEED_PECI_INT_W_FCS_ABORT) {
++ dev_dbg(priv->dev, "ASPEED_PECI_INT_W_FCS_ABORT\n");
++ }
++
++ /*
++ * All commands should be ended up with a ASPEED_PECI_INT_CMD_DONE bit
++ * set even in an error case.
++ */
++ if (status & ASPEED_PECI_INT_CMD_DONE) {
++ dev_dbg(priv->dev, "ASPEED_PECI_INT_CMD_DONE\n");
++ complete(&priv->xfer_complete);
++ }
++
++ spin_unlock(&priv->lock);
++ return IRQ_HANDLED;
++}
++
++static int aspeed_peci_init_ctrl(struct aspeed_peci *priv)
++{
++ u32 msg_timing, addr_timing, rd_sampling_point;
++ u32 clk_freq, clk_divisor, clk_div_val = 0;
++ int ret;
++
++ priv->clk = devm_clk_get(priv->dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ dev_err(priv->dev, "Failed to get clk source.\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(priv->dev, "Failed to enable clock.\n");
++ return ret;
++ }
++
++ ret = device_property_read_u32(priv->dev, "clock-frequency", &clk_freq);
++ if (ret) {
++ dev_err(priv->dev,
++ "Could not read clock-frequency property.\n");
++ clk_disable_unprepare(priv->clk);
++ return ret;
++ }
++
++ clk_divisor = clk_get_rate(priv->clk) / clk_freq;
++
++ while ((clk_divisor >> 1) && (clk_div_val < ASPEED_PECI_CLK_DIV_MAX))
++ clk_div_val++;
++
++ ret = device_property_read_u32(priv->dev, "msg-timing", &msg_timing);
++ if (ret || msg_timing > ASPEED_PECI_MSG_TIMING_MAX) {
++ if (!ret)
++ dev_warn(priv->dev,
++ "Invalid msg-timing : %u, Use default : %u\n",
++ msg_timing, ASPEED_PECI_MSG_TIMING_DEFAULT);
++ msg_timing = ASPEED_PECI_MSG_TIMING_DEFAULT;
++ }
++
++ ret = device_property_read_u32(priv->dev, "addr-timing", &addr_timing);
++ if (ret || addr_timing > ASPEED_PECI_ADDR_TIMING_MAX) {
++ if (!ret)
++ dev_warn(priv->dev,
++ "Invalid addr-timing : %u, Use default : %u\n",
++ addr_timing, ASPEED_PECI_ADDR_TIMING_DEFAULT);
++ addr_timing = ASPEED_PECI_ADDR_TIMING_DEFAULT;
++ }
++
++ ret = device_property_read_u32(priv->dev, "rd-sampling-point",
++ &rd_sampling_point);
++ if (ret || rd_sampling_point > ASPEED_PECI_RD_SAMPLING_POINT_MAX) {
++ if (!ret)
++ dev_warn(priv->dev,
++ "Invalid rd-sampling-point : %u. Use default : %u\n",
++ rd_sampling_point,
++ ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT);
++ rd_sampling_point = ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT;
++ }
++
++ ret = device_property_read_u32(priv->dev, "cmd-timeout-ms",
++ &priv->cmd_timeout_ms);
++ if (ret || priv->cmd_timeout_ms > ASPEED_PECI_CMD_TIMEOUT_MS_MAX ||
++ priv->cmd_timeout_ms == 0) {
++ if (!ret)
++ dev_warn(priv->dev,
++ "Invalid cmd-timeout-ms : %u. Use default : %u\n",
++ priv->cmd_timeout_ms,
++ ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT);
++ priv->cmd_timeout_ms = ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT;
++ }
++
++ writel(FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK,
++ ASPEED_PECI_CLK_DIV_DEFAULT) |
++ ASPEED_PECI_CTRL_PECI_CLK_EN, priv->base + ASPEED_PECI_CTRL);
++
++ /*
++ * Timing negotiation period setting.
++ * The unit of the programmed value is 4 times of PECI clock period.
++ */
++ writel(FIELD_PREP(ASPEED_PECI_TIMING_MESSAGE_MASK, msg_timing) |
++ FIELD_PREP(ASPEED_PECI_TIMING_ADDRESS_MASK, addr_timing),
++ priv->base + ASPEED_PECI_TIMING_NEGOTIATION);
++
++ /* Clear interrupts */
++ writel(readl(priv->base + ASPEED_PECI_INT_STS) | ASPEED_PECI_INT_MASK,
++ priv->base + ASPEED_PECI_INT_STS);
++
++ /* Set timing negotiation mode and enable interrupts */
++ writel(FIELD_PREP(ASPEED_PECI_TIMING_NEGO_SEL_MASK,
++ ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO) |
++ ASPEED_PECI_INT_MASK, priv->base + ASPEED_PECI_INT_CTRL);
++
++ /* Read sampling point and clock speed setting */
++ writel(FIELD_PREP(ASPEED_PECI_CTRL_SAMPLING_MASK, rd_sampling_point) |
++ FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, clk_div_val) |
++ ASPEED_PECI_CTRL_PECI_EN | ASPEED_PECI_CTRL_PECI_CLK_EN,
++ priv->base + ASPEED_PECI_CTRL);
++
++ return 0;
++}
++
++static int aspeed_peci_probe(struct platform_device *pdev)
++{
++ struct peci_adapter *adapter;
++ struct aspeed_peci *priv;
++ struct resource *res;
++ int ret;
++
++ adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv));
++ if (!adapter)
++ return -ENOMEM;
++
++ priv = peci_get_adapdata(adapter);
++ priv->adapter = adapter;
++ priv->dev = &pdev->dev;
++ dev_set_drvdata(&pdev->dev, priv);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ priv->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(priv->base)) {
++ ret = PTR_ERR(priv->base);
++ goto err_put_adapter_dev;
++ }
++
++ priv->irq = platform_get_irq(pdev, 0);
++ if (!priv->irq) {
++ ret = -ENODEV;
++ goto err_put_adapter_dev;
++ }
++
++ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler,
++ 0, "peci-aspeed-irq", priv);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ init_completion(&priv->xfer_complete);
++ spin_lock_init(&priv->lock);
++
++ priv->adapter->owner = THIS_MODULE;
++ priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev));
++ strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name));
++ priv->adapter->xfer = aspeed_peci_xfer;
++ priv->adapter->use_dma = false;
++
++ priv->rst = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->rst)) {
++ dev_err(&pdev->dev,
++ "missing or invalid reset controller entry");
++ ret = PTR_ERR(priv->rst);
++ goto err_put_adapter_dev;
++ }
++ reset_control_deassert(priv->rst);
++
++ ret = aspeed_peci_init_ctrl(priv);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ ret = peci_add_adapter(priv->adapter);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ dev_info(&pdev->dev, "peci bus %d registered, irq %d\n",
++ priv->adapter->nr, priv->irq);
++
++ return 0;
++
++err_put_adapter_dev:
++ put_device(&adapter->dev);
++ return ret;
++}
++
++static int aspeed_peci_remove(struct platform_device *pdev)
++{
++ struct aspeed_peci *priv = dev_get_drvdata(&pdev->dev);
++
++ clk_disable_unprepare(priv->clk);
++ reset_control_assert(priv->rst);
++ peci_del_adapter(priv->adapter);
++ of_node_put(priv->adapter->dev.of_node);
++
++ return 0;
++}
++
++static const struct of_device_id aspeed_peci_of_table[] = {
++ { .compatible = "aspeed,ast2400-peci", },
++ { .compatible = "aspeed,ast2500-peci", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, aspeed_peci_of_table);
++
++static struct platform_driver aspeed_peci_driver = {
++ .probe = aspeed_peci_probe,
++ .remove = aspeed_peci_remove,
++ .driver = {
++ .name = "peci-aspeed",
++ .of_match_table = of_match_ptr(aspeed_peci_of_table),
++ },
++};
++module_platform_driver(aspeed_peci_driver);
++
++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("ASPEED PECI driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/peci/busses/peci-npcm.c b/drivers/peci/busses/peci-npcm.c
+new file mode 100644
+index 000000000000..f632365b1416
+--- /dev/null
++++ b/drivers/peci/busses/peci-npcm.c
+@@ -0,0 +1,410 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2019 Nuvoton Technology corporation.
++
++#include <linux/bitfield.h>
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/peci.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/mfd/syscon.h>
++#include <linux/reset.h>
++
++/* NPCM7xx GCR module */
++#define NPCM7XX_INTCR3_OFFSET 0x9C
++#define NPCM7XX_INTCR3_PECIVSEL BIT(19)
++
++/* NPCM PECI Registers */
++#define NPCM_PECI_CTL_STS 0x00
++#define NPCM_PECI_RD_LENGTH 0x04
++#define NPCM_PECI_ADDR 0x08
++#define NPCM_PECI_CMD 0x0C
++#define NPCM_PECI_CTL2 0x10
++#define NPCM_PECI_WR_LENGTH 0x1C
++#define NPCM_PECI_PDDR 0x2C
++#define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4))
++
++#define NPCM_PECI_MAX_REG 0x200
++
++/* NPCM_PECI_CTL_STS - 0x00 : Control Register */
++#define NPCM_PECI_CTRL_DONE_INT_EN BIT(6)
++#define NPCM_PECI_CTRL_ABRT_ERR BIT(4)
++#define NPCM_PECI_CTRL_CRC_ERR BIT(3)
++#define NPCM_PECI_CTRL_DONE BIT(1)
++#define NPCM_PECI_CTRL_START_BUSY BIT(0)
++
++/* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */
++#define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0)
++
++/* NPCM_PECI_CMD - 0x10 : Command Register */
++#define NPCM_PECI_CTL2_MASK GENMASK(7, 6)
++
++/* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */
++#define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0)
++
++/* NPCM_PECI_PDDR - 0x2C : Command Register */
++#define NPCM_PECI_PDDR_MASK GENMASK(4, 0)
++
++#define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \
++ NPCM_PECI_CTRL_CRC_ERR | \
++ NPCM_PECI_CTRL_DONE)
++
++#define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC 50000
++#define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC 10000
++#define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000
++#define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000
++#define NPCM_PECI_HOST_NEG_BIT_RATE_MAX 31
++#define NPCM_PECI_HOST_NEG_BIT_RATE_MIN 7
++#define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15
++#define NPCM_PECI_PULL_DOWN_DEFAULT 0
++#define NPCM_PECI_PULL_DOWN_MAX 2
++
++struct npcm_peci {
++ u32 cmd_timeout_ms;
++ u32 host_bit_rate;
++ struct completion xfer_complete;
++ struct regmap *gcr_regmap;
++ struct peci_adapter *adapter;
++ struct regmap *regmap;
++ u32 status;
++ spinlock_t lock; /* to sync completion status handling */
++ struct device *dev;
++ struct clk *clk;
++ int irq;
++};
++
++static int npcm_peci_xfer_native(struct npcm_peci *priv,
++ struct peci_xfer_msg *msg)
++{
++ long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms);
++ unsigned long flags;
++ unsigned int msg_rd;
++ u32 cmd_sts;
++ int i, rc;
++
++ /* Check command sts and bus idle state */
++ rc = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts,
++ !(cmd_sts & NPCM_PECI_CTRL_START_BUSY),
++ NPCM_PECI_IDLE_CHECK_INTERVAL_USEC,
++ NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC);
++ if (rc)
++ return rc; /* -ETIMEDOUT */
++
++ spin_lock_irqsave(&priv->lock, flags);
++ reinit_completion(&priv->xfer_complete);
++
++ regmap_write(priv->regmap, NPCM_PECI_ADDR, msg->addr);
++ regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH,
++ NPCM_PECI_WR_LEN_MASK & msg->rx_len);
++ regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH,
++ NPCM_PECI_WR_LEN_MASK & msg->tx_len);
++
++ if (msg->tx_len) {
++ regmap_write(priv->regmap, NPCM_PECI_CMD, msg->tx_buf[0]);
++
++ for (i = 0; i < (msg->tx_len - 1); i++)
++ regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i),
++ msg->tx_buf[i + 1]);
++ }
++
++ priv->status = 0;
++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS,
++ NPCM_PECI_CTRL_START_BUSY,
++ NPCM_PECI_CTRL_START_BUSY);
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ err = wait_for_completion_interruptible_timeout(&priv->xfer_complete,
++ timeout);
++
++ spin_lock_irqsave(&priv->lock, flags);
++
++ regmap_write(priv->regmap, NPCM_PECI_CMD, 0);
++
++ if (err <= 0 || priv->status != NPCM_PECI_CTRL_DONE) {
++ if (err < 0) { /* -ERESTARTSYS */
++ rc = (int)err;
++ goto err_irqrestore;
++ } else if (err == 0) {
++ dev_dbg(priv->dev, "Timeout waiting for a response!\n");
++ rc = -ETIMEDOUT;
++ goto err_irqrestore;
++ }
++
++ dev_dbg(priv->dev, "No valid response!\n");
++ rc = -EIO;
++ goto err_irqrestore;
++ }
++
++ for (i = 0; i < msg->rx_len; i++) {
++ regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd);
++ msg->rx_buf[i] = (u8)msg_rd;
++ }
++
++err_irqrestore:
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return rc;
++}
++
++static irqreturn_t npcm_peci_irq_handler(int irq, void *arg)
++{
++ struct npcm_peci *priv = arg;
++ u32 status_ack = 0;
++ u32 status;
++
++ spin_lock(&priv->lock);
++ regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status);
++ priv->status |= (status & NPCM_PECI_INT_MASK);
++
++ if (status & NPCM_PECI_CTRL_CRC_ERR) {
++ dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n");
++ status_ack |= NPCM_PECI_CTRL_CRC_ERR;
++ }
++
++ if (status & NPCM_PECI_CTRL_ABRT_ERR) {
++ dev_dbg(priv->dev, "NPCM_PECI_CTRL_ABRT_ERR\n");
++ status_ack |= NPCM_PECI_CTRL_ABRT_ERR;
++ }
++
++ /*
++ * All commands should be ended up with a NPCM_PECI_CTRL_DONE
++ * bit set even in an error case.
++ */
++ if (status & NPCM_PECI_CTRL_DONE) {
++ dev_dbg(priv->dev, "NPCM_PECI_CTRL_DONE\n");
++ status_ack |= NPCM_PECI_CTRL_DONE;
++ complete(&priv->xfer_complete);
++ }
++
++ regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS,
++ NPCM_PECI_INT_MASK, status_ack);
++
++ spin_unlock(&priv->lock);
++ return IRQ_HANDLED;
++}
++
++static int npcm_peci_init_ctrl(struct npcm_peci *priv)
++{
++ u32 cmd_sts, host_neg_bit_rate = 0, pull_down = 0;
++ int ret;
++ bool volt;
++
++ priv->clk = devm_clk_get(priv->dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ dev_err(priv->dev, "Failed to get clk source.\n");
++ return PTR_ERR(priv->clk);
++ }
++
++ ret = clk_prepare_enable(priv->clk);
++ if (ret) {
++ dev_err(priv->dev, "Failed to enable clock.\n");
++ return ret;
++ }
++
++ ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms",
++ &priv->cmd_timeout_ms);
++ if (ret || priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX ||
++ priv->cmd_timeout_ms == 0) {
++ if (ret)
++ dev_warn(priv->dev,
++ "cmd-timeout-ms not found, use default : %u\n",
++ NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT);
++ else
++ dev_warn(priv->dev,
++ "Invalid cmd-timeout-ms : %u. Use default : %u\n",
++ priv->cmd_timeout_ms,
++ NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT);
++
++ priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT;
++ }
++
++ if (of_device_is_compatible(priv->dev->of_node,
++ "nuvoton,npcm750-peci")) {
++ priv->gcr_regmap = syscon_regmap_lookup_by_compatible
++ ("nuvoton,npcm750-gcr");
++ if (!IS_ERR(priv->gcr_regmap)) {
++ volt = of_property_read_bool(priv->dev->of_node,
++ "high-volt-range");
++ if (volt)
++ regmap_update_bits(priv->gcr_regmap,
++ NPCM7XX_INTCR3_OFFSET,
++ NPCM7XX_INTCR3_PECIVSEL,
++ NPCM7XX_INTCR3_PECIVSEL);
++ else
++ regmap_update_bits(priv->gcr_regmap,
++ NPCM7XX_INTCR3_OFFSET,
++ NPCM7XX_INTCR3_PECIVSEL, 0);
++ }
++ }
++
++ ret = of_property_read_u32(priv->dev->of_node, "pull-down",
++ &pull_down);
++ if (ret || pull_down > NPCM_PECI_PULL_DOWN_MAX) {
++ if (ret)
++ dev_warn(priv->dev,
++ "pull-down not found, use default : %u\n",
++ NPCM_PECI_PULL_DOWN_DEFAULT);
++ else
++ dev_warn(priv->dev,
++ "Invalid pull-down : %u. Use default : %u\n",
++ pull_down,
++ NPCM_PECI_PULL_DOWN_DEFAULT);
++ pull_down = NPCM_PECI_PULL_DOWN_DEFAULT;
++ }
++
++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK,
++ pull_down << 6);
++
++ ret = of_property_read_u32(priv->dev->of_node, "host-neg-bit-rate",
++ &host_neg_bit_rate);
++ if (ret || host_neg_bit_rate > NPCM_PECI_HOST_NEG_BIT_RATE_MAX ||
++ host_neg_bit_rate < NPCM_PECI_HOST_NEG_BIT_RATE_MIN) {
++ if (ret)
++ dev_warn(priv->dev,
++ "host-neg-bit-rate not found, use default : %u\n",
++ NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT);
++ else
++ dev_warn(priv->dev,
++ "Invalid host-neg-bit-rate : %u. Use default : %u\n",
++ host_neg_bit_rate,
++ NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT);
++ host_neg_bit_rate = NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT;
++ }
++
++ regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK,
++ host_neg_bit_rate);
++
++ priv->host_bit_rate = clk_get_rate(priv->clk) /
++ (4 * (host_neg_bit_rate + 1));
++
++ ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts,
++ !(cmd_sts & NPCM_PECI_CTRL_START_BUSY),
++ NPCM_PECI_IDLE_CHECK_INTERVAL_USEC,
++ NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC);
++ if (ret)
++ return ret; /* -ETIMEDOUT */
++
++ /* PECI interrupt enable */
++ regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS,
++ NPCM_PECI_CTRL_DONE_INT_EN,
++ NPCM_PECI_CTRL_DONE_INT_EN);
++
++ return 0;
++}
++
++static const struct regmap_config npcm_peci_regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 8,
++ .max_register = NPCM_PECI_MAX_REG,
++ .fast_io = true,
++};
++
++static int npcm_peci_xfer(struct peci_adapter *adapter,
++ struct peci_xfer_msg *msg)
++{
++ struct npcm_peci *priv = peci_get_adapdata(adapter);
++
++ return npcm_peci_xfer_native(priv, msg);
++}
++
++static int npcm_peci_probe(struct platform_device *pdev)
++{
++ struct peci_adapter *adapter;
++ struct npcm_peci *priv;
++ struct resource *res;
++ void __iomem *base;
++ int ret;
++
++ adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv));
++ if (!adapter)
++ return -ENOMEM;
++
++ priv = peci_get_adapdata(adapter);
++ priv->adapter = adapter;
++ priv->dev = &pdev->dev;
++ dev_set_drvdata(&pdev->dev, priv);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(base)) {
++ ret = PTR_ERR(base);
++ goto err_put_adapter_dev;
++ }
++
++ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
++ &npcm_peci_regmap_config);
++ if (IS_ERR(priv->regmap)) {
++ ret = PTR_ERR(priv->regmap);
++ goto err_put_adapter_dev;
++ }
++
++ priv->irq = platform_get_irq(pdev, 0);
++ if (!priv->irq) {
++ ret = -ENODEV;
++ goto err_put_adapter_dev;
++ }
++
++ ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler,
++ 0, "peci-npcm-irq", priv);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ init_completion(&priv->xfer_complete);
++ spin_lock_init(&priv->lock);
++
++ priv->adapter->owner = THIS_MODULE;
++ priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev));
++ strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name));
++ priv->adapter->xfer = npcm_peci_xfer;
++
++ ret = npcm_peci_init_ctrl(priv);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ ret = peci_add_adapter(priv->adapter);
++ if (ret)
++ goto err_put_adapter_dev;
++
++ dev_info(&pdev->dev, "peci bus %d registered, host negotiation bit rate %dHz",
++ priv->adapter->nr, priv->host_bit_rate);
++
++ return 0;
++
++err_put_adapter_dev:
++ put_device(&adapter->dev);
++ return ret;
++}
++
++static int npcm_peci_remove(struct platform_device *pdev)
++{
++ struct npcm_peci *priv = dev_get_drvdata(&pdev->dev);
++
++ clk_disable_unprepare(priv->clk);
++ peci_del_adapter(priv->adapter);
++ of_node_put(priv->adapter->dev.of_node);
++
++ return 0;
++}
++
++static const struct of_device_id npcm_peci_of_table[] = {
++ { .compatible = "nuvoton,npcm750-peci", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, npcm_peci_of_table);
++
++static struct platform_driver npcm_peci_driver = {
++ .probe = npcm_peci_probe,
++ .remove = npcm_peci_remove,
++ .driver = {
++ .name = "peci-npcm",
++ .of_match_table = of_match_ptr(npcm_peci_of_table),
++ },
++};
++module_platform_driver(npcm_peci_driver);
++
++MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
++MODULE_DESCRIPTION("NPCM Platform Environment Control Interface (PECI) driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/peci/peci-aspeed.c b/drivers/peci/peci-aspeed.c
+deleted file mode 100644
+index 51cb2563ceb6..000000000000
+--- a/drivers/peci/peci-aspeed.c
++++ /dev/null
+@@ -1,505 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-// Copyright (C) 2012-2017 ASPEED Technology Inc.
+-// Copyright (c) 2018 Intel Corporation
+-
+-#include <linux/bitfield.h>
+-#include <linux/clk.h>
+-#include <linux/interrupt.h>
+-#include <linux/jiffies.h>
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/peci.h>
+-#include <linux/platform_device.h>
+-#include <linux/regmap.h>
+-#include <linux/reset.h>
+-
+-/* ASPEED PECI Registers */
+-#define ASPEED_PECI_CTRL 0x00
+-#define ASPEED_PECI_TIMING 0x04
+-#define ASPEED_PECI_CMD 0x08
+-#define ASPEED_PECI_CMD_CTRL 0x0c
+-#define ASPEED_PECI_EXP_FCS 0x10
+-#define ASPEED_PECI_CAP_FCS 0x14
+-#define ASPEED_PECI_INT_CTRL 0x18
+-#define ASPEED_PECI_INT_STS 0x1c
+-#define ASPEED_PECI_W_DATA0 0x20
+-#define ASPEED_PECI_W_DATA1 0x24
+-#define ASPEED_PECI_W_DATA2 0x28
+-#define ASPEED_PECI_W_DATA3 0x2c
+-#define ASPEED_PECI_R_DATA0 0x30
+-#define ASPEED_PECI_R_DATA1 0x34
+-#define ASPEED_PECI_R_DATA2 0x38
+-#define ASPEED_PECI_R_DATA3 0x3c
+-#define ASPEED_PECI_W_DATA4 0x40
+-#define ASPEED_PECI_W_DATA5 0x44
+-#define ASPEED_PECI_W_DATA6 0x48
+-#define ASPEED_PECI_W_DATA7 0x4c
+-#define ASPEED_PECI_R_DATA4 0x50
+-#define ASPEED_PECI_R_DATA5 0x54
+-#define ASPEED_PECI_R_DATA6 0x58
+-#define ASPEED_PECI_R_DATA7 0x5c
+-
+-/* ASPEED_PECI_CTRL - 0x00 : Control Register */
+-#define PECI_CTRL_SAMPLING_MASK GENMASK(19, 16)
+-#define PECI_CTRL_READ_MODE_MASK GENMASK(13, 12)
+-#define PECI_CTRL_READ_MODE_COUNT BIT(12)
+-#define PECI_CTRL_READ_MODE_DBG BIT(13)
+-#define PECI_CTRL_CLK_SOURCE_MASK BIT(11)
+-#define PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8)
+-#define PECI_CTRL_INVERT_OUT BIT(7)
+-#define PECI_CTRL_INVERT_IN BIT(6)
+-#define PECI_CTRL_BUS_CONTENT_EN BIT(5)
+-#define PECI_CTRL_PECI_EN BIT(4)
+-#define PECI_CTRL_PECI_CLK_EN BIT(0)
+-
+-/* ASPEED_PECI_TIMING - 0x04 : Timing Negotiation Register */
+-#define PECI_TIMING_MESSAGE_MASK GENMASK(15, 8)
+-#define PECI_TIMING_ADDRESS_MASK GENMASK(7, 0)
+-
+-/* ASPEED_PECI_CMD - 0x08 : Command Register */
+-#define PECI_CMD_PIN_MON BIT(31)
+-#define PECI_CMD_STS_MASK GENMASK(27, 24)
+-#define PECI_CMD_IDLE_MASK (PECI_CMD_STS_MASK | PECI_CMD_PIN_MON)
+-#define PECI_CMD_FIRE BIT(0)
+-
+-/* ASPEED_PECI_LEN - 0x0C : Read/Write Length Register */
+-#define PECI_AW_FCS_EN BIT(31)
+-#define PECI_READ_LEN_MASK GENMASK(23, 16)
+-#define PECI_WRITE_LEN_MASK GENMASK(15, 8)
+-#define PECI_TAGET_ADDR_MASK GENMASK(7, 0)
+-
+-/* ASPEED_PECI_EXP_FCS - 0x10 : Expected FCS Data Register */
+-#define PECI_EXPECT_READ_FCS_MASK GENMASK(23, 16)
+-#define PECI_EXPECT_AW_FCS_AUTO_MASK GENMASK(15, 8)
+-#define PECI_EXPECT_WRITE_FCS_MASK GENMASK(7, 0)
+-
+-/* ASPEED_PECI_CAP_FCS - 0x14 : Captured FCS Data Register */
+-#define PECI_CAPTURE_READ_FCS_MASK GENMASK(23, 16)
+-#define PECI_CAPTURE_WRITE_FCS_MASK GENMASK(7, 0)
+-
+-/* ASPEED_PECI_INT_CTRL/STS - 0x18/0x1c : Interrupt Register */
+-#define PECI_INT_TIMING_RESULT_MASK GENMASK(31, 30)
+-#define PECI_INT_TIMEOUT BIT(4)
+-#define PECI_INT_CONNECT BIT(3)
+-#define PECI_INT_W_FCS_BAD BIT(2)
+-#define PECI_INT_W_FCS_ABORT BIT(1)
+-#define PECI_INT_CMD_DONE BIT(0)
+-
+-#define PECI_INT_MASK (PECI_INT_TIMEOUT | PECI_INT_CONNECT | \
+- PECI_INT_W_FCS_BAD | PECI_INT_W_FCS_ABORT | \
+- PECI_INT_CMD_DONE)
+-
+-#define PECI_IDLE_CHECK_TIMEOUT_USEC 50000
+-#define PECI_IDLE_CHECK_INTERVAL_USEC 10000
+-
+-#define PECI_RD_SAMPLING_POINT_DEFAULT 8
+-#define PECI_RD_SAMPLING_POINT_MAX 15
+-#define PECI_CLK_DIV_DEFAULT 0
+-#define PECI_CLK_DIV_MAX 7
+-#define PECI_MSG_TIMING_DEFAULT 1
+-#define PECI_MSG_TIMING_MAX 255
+-#define PECI_ADDR_TIMING_DEFAULT 1
+-#define PECI_ADDR_TIMING_MAX 255
+-#define PECI_CMD_TIMEOUT_MS_DEFAULT 1000
+-#define PECI_CMD_TIMEOUT_MS_MAX 60000
+-
+-struct aspeed_peci {
+- struct peci_adapter *adapter;
+- struct device *dev;
+- struct regmap *regmap;
+- struct clk *clk;
+- struct reset_control *rst;
+- int irq;
+- spinlock_t lock; /* to sync completion status handling */
+- struct completion xfer_complete;
+- u32 status;
+- u32 cmd_timeout_ms;
+-};
+-
+-static int aspeed_peci_xfer_native(struct aspeed_peci *priv,
+- struct peci_xfer_msg *msg)
+-{
+- long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms);
+- u32 peci_head, peci_state, rx_data, cmd_sts;
+- unsigned long flags;
+- int i, rc;
+- uint reg;
+-
+- /* Check command sts and bus idle state */
+- rc = regmap_read_poll_timeout(priv->regmap, ASPEED_PECI_CMD, cmd_sts,
+- !(cmd_sts & PECI_CMD_IDLE_MASK),
+- PECI_IDLE_CHECK_INTERVAL_USEC,
+- PECI_IDLE_CHECK_TIMEOUT_USEC);
+- if (rc)
+- return rc; /* -ETIMEDOUT */
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- reinit_completion(&priv->xfer_complete);
+-
+- peci_head = FIELD_PREP(PECI_TAGET_ADDR_MASK, msg->addr) |
+- FIELD_PREP(PECI_WRITE_LEN_MASK, msg->tx_len) |
+- FIELD_PREP(PECI_READ_LEN_MASK, msg->rx_len);
+-
+- regmap_write(priv->regmap, ASPEED_PECI_CMD_CTRL, peci_head);
+-
+- for (i = 0; i < msg->tx_len; i += 4) {
+- reg = i < 16 ? ASPEED_PECI_W_DATA0 + i % 16 :
+- ASPEED_PECI_W_DATA4 + i % 16;
+- regmap_write(priv->regmap, reg,
+- le32_to_cpup((__le32 *)&msg->tx_buf[i]));
+- }
+-
+- dev_dbg(priv->dev, "HEAD : 0x%08x\n", peci_head);
+- print_hex_dump_debug("TX : ", DUMP_PREFIX_NONE, 16, 1,
+- msg->tx_buf, msg->tx_len, true);
+-
+- priv->status = 0;
+- regmap_write(priv->regmap, ASPEED_PECI_CMD, PECI_CMD_FIRE);
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- err = wait_for_completion_interruptible_timeout(&priv->xfer_complete,
+- timeout);
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- dev_dbg(priv->dev, "INT_STS : 0x%08x\n", priv->status);
+- regmap_read(priv->regmap, ASPEED_PECI_CMD, &peci_state);
+- dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n",
+- FIELD_GET(PECI_CMD_STS_MASK, peci_state));
+-
+- regmap_write(priv->regmap, ASPEED_PECI_CMD, 0);
+-
+- if (err <= 0 || priv->status != PECI_INT_CMD_DONE) {
+- if (err < 0) { /* -ERESTARTSYS */
+- rc = (int)err;
+- goto err_irqrestore;
+- } else if (err == 0) {
+- dev_dbg(priv->dev, "Timeout waiting for a response!\n");
+- rc = -ETIMEDOUT;
+- goto err_irqrestore;
+- }
+-
+- dev_dbg(priv->dev, "No valid response!\n");
+- rc = -EIO;
+- goto err_irqrestore;
+- }
+-
+- /**
+- * Note that rx_len and rx_buf size can be an odd number.
+- * Byte handling is more efficient.
+- */
+- for (i = 0; i < msg->rx_len; i++) {
+- u8 byte_offset = i % 4;
+-
+- if (byte_offset == 0) {
+- reg = i < 16 ? ASPEED_PECI_R_DATA0 + i % 16 :
+- ASPEED_PECI_R_DATA4 + i % 16;
+- regmap_read(priv->regmap, reg, &rx_data);
+- }
+-
+- msg->rx_buf[i] = (u8)(rx_data >> (byte_offset << 3));
+- }
+-
+- print_hex_dump_debug("RX : ", DUMP_PREFIX_NONE, 16, 1,
+- msg->rx_buf, msg->rx_len, true);
+-
+- regmap_read(priv->regmap, ASPEED_PECI_CMD, &peci_state);
+- dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n",
+- FIELD_GET(PECI_CMD_STS_MASK, peci_state));
+- dev_dbg(priv->dev, "------------------------\n");
+-
+-err_irqrestore:
+- spin_unlock_irqrestore(&priv->lock, flags);
+- return rc;
+-}
+-
+-static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg)
+-{
+- struct aspeed_peci *priv = arg;
+- u32 status_ack = 0;
+- u32 status;
+-
+- spin_lock(&priv->lock);
+- regmap_read(priv->regmap, ASPEED_PECI_INT_STS, &status);
+- priv->status |= (status & PECI_INT_MASK);
+-
+- /**
+- * In most cases, interrupt bits will be set one by one but also note
+- * that multiple interrupt bits could be set at the same time.
+- */
+- if (status & PECI_INT_TIMEOUT) {
+- dev_dbg(priv->dev, "PECI_INT_TIMEOUT\n");
+- status_ack |= PECI_INT_TIMEOUT;
+- }
+-
+- if (status & PECI_INT_CONNECT) {
+- dev_dbg(priv->dev, "PECI_INT_CONNECT\n");
+- status_ack |= PECI_INT_CONNECT;
+- }
+-
+- if (status & PECI_INT_W_FCS_BAD) {
+- dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n");
+- status_ack |= PECI_INT_W_FCS_BAD;
+- }
+-
+- if (status & PECI_INT_W_FCS_ABORT) {
+- dev_dbg(priv->dev, "PECI_INT_W_FCS_ABORT\n");
+- status_ack |= PECI_INT_W_FCS_ABORT;
+- }
+-
+- /**
+- * All commands should be ended up with a PECI_INT_CMD_DONE bit set
+- * even in an error case.
+- */
+- if (status & PECI_INT_CMD_DONE) {
+- dev_dbg(priv->dev, "PECI_INT_CMD_DONE\n");
+- status_ack |= PECI_INT_CMD_DONE;
+- complete(&priv->xfer_complete);
+- }
+-
+- regmap_write(priv->regmap, ASPEED_PECI_INT_STS, status_ack);
+- spin_unlock(&priv->lock);
+- return IRQ_HANDLED;
+-}
+-
+-static int aspeed_peci_init_ctrl(struct aspeed_peci *priv)
+-{
+- u32 msg_timing, addr_timing, rd_sampling_point;
+- u32 clk_freq, clk_divisor, clk_div_val = 0;
+- int ret;
+-
+- priv->clk = devm_clk_get(priv->dev, NULL);
+- if (IS_ERR(priv->clk)) {
+- dev_err(priv->dev, "Failed to get clk source.\n");
+- return PTR_ERR(priv->clk);
+- }
+-
+- ret = clk_prepare_enable(priv->clk);
+- if (ret) {
+- dev_err(priv->dev, "Failed to enable clock.\n");
+- return ret;
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "clock-frequency",
+- &clk_freq);
+- if (ret) {
+- dev_err(priv->dev,
+- "Could not read clock-frequency property.\n");
+- clk_disable_unprepare(priv->clk);
+- return ret;
+- }
+-
+- clk_divisor = clk_get_rate(priv->clk) / clk_freq;
+-
+- while ((clk_divisor >> 1) && (clk_div_val < PECI_CLK_DIV_MAX))
+- clk_div_val++;
+-
+- ret = of_property_read_u32(priv->dev->of_node, "msg-timing",
+- &msg_timing);
+- if (ret || msg_timing > PECI_MSG_TIMING_MAX) {
+- if (!ret)
+- dev_warn(priv->dev,
+- "Invalid msg-timing : %u, Use default : %u\n",
+- msg_timing, PECI_MSG_TIMING_DEFAULT);
+- msg_timing = PECI_MSG_TIMING_DEFAULT;
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "addr-timing",
+- &addr_timing);
+- if (ret || addr_timing > PECI_ADDR_TIMING_MAX) {
+- if (!ret)
+- dev_warn(priv->dev,
+- "Invalid addr-timing : %u, Use default : %u\n",
+- addr_timing, PECI_ADDR_TIMING_DEFAULT);
+- addr_timing = PECI_ADDR_TIMING_DEFAULT;
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "rd-sampling-point",
+- &rd_sampling_point);
+- if (ret || rd_sampling_point > PECI_RD_SAMPLING_POINT_MAX) {
+- if (!ret)
+- dev_warn(priv->dev,
+- "Invalid rd-sampling-point : %u. Use default : %u\n",
+- rd_sampling_point,
+- PECI_RD_SAMPLING_POINT_DEFAULT);
+- rd_sampling_point = PECI_RD_SAMPLING_POINT_DEFAULT;
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms",
+- &priv->cmd_timeout_ms);
+- if (ret || priv->cmd_timeout_ms > PECI_CMD_TIMEOUT_MS_MAX ||
+- priv->cmd_timeout_ms == 0) {
+- if (!ret)
+- dev_warn(priv->dev,
+- "Invalid cmd-timeout-ms : %u. Use default : %u\n",
+- priv->cmd_timeout_ms,
+- PECI_CMD_TIMEOUT_MS_DEFAULT);
+- priv->cmd_timeout_ms = PECI_CMD_TIMEOUT_MS_DEFAULT;
+- }
+-
+- regmap_write(priv->regmap, ASPEED_PECI_CTRL,
+- FIELD_PREP(PECI_CTRL_CLK_DIV_MASK, PECI_CLK_DIV_DEFAULT) |
+- PECI_CTRL_PECI_CLK_EN);
+-
+- /**
+- * Timing negotiation period setting.
+- * The unit of the programmed value is 4 times of PECI clock period.
+- */
+- regmap_write(priv->regmap, ASPEED_PECI_TIMING,
+- FIELD_PREP(PECI_TIMING_MESSAGE_MASK, msg_timing) |
+- FIELD_PREP(PECI_TIMING_ADDRESS_MASK, addr_timing));
+-
+- /* Clear interrupts */
+- regmap_write(priv->regmap, ASPEED_PECI_INT_STS, PECI_INT_MASK);
+-
+- /* Enable interrupts */
+- regmap_write(priv->regmap, ASPEED_PECI_INT_CTRL, PECI_INT_MASK);
+-
+- /* Read sampling point and clock speed setting */
+- regmap_write(priv->regmap, ASPEED_PECI_CTRL,
+- FIELD_PREP(PECI_CTRL_SAMPLING_MASK, rd_sampling_point) |
+- FIELD_PREP(PECI_CTRL_CLK_DIV_MASK, clk_div_val) |
+- PECI_CTRL_PECI_EN | PECI_CTRL_PECI_CLK_EN);
+-
+- return 0;
+-}
+-
+-static const struct regmap_config aspeed_peci_regmap_config = {
+- .reg_bits = 32,
+- .val_bits = 32,
+- .reg_stride = 4,
+- .max_register = ASPEED_PECI_R_DATA7,
+- .val_format_endian = REGMAP_ENDIAN_LITTLE,
+- .fast_io = true,
+-};
+-
+-static int aspeed_peci_xfer(struct peci_adapter *adapter,
+- struct peci_xfer_msg *msg)
+-{
+- struct aspeed_peci *priv = peci_get_adapdata(adapter);
+-
+- return aspeed_peci_xfer_native(priv, msg);
+-}
+-
+-static int aspeed_peci_probe(struct platform_device *pdev)
+-{
+- struct peci_adapter *adapter;
+- struct aspeed_peci *priv;
+- struct resource *res;
+- void __iomem *base;
+- u32 cmd_sts;
+- int ret;
+-
+- adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv));
+- if (!adapter)
+- return -ENOMEM;
+-
+- priv = peci_get_adapdata(adapter);
+- priv->adapter = adapter;
+- priv->dev = &pdev->dev;
+- dev_set_drvdata(&pdev->dev, priv);
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- base = devm_ioremap_resource(&pdev->dev, res);
+- if (IS_ERR(base)) {
+- ret = PTR_ERR(base);
+- goto err_put_adapter_dev;
+- }
+-
+- priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+- &aspeed_peci_regmap_config);
+- if (IS_ERR(priv->regmap)) {
+- ret = PTR_ERR(priv->regmap);
+- goto err_put_adapter_dev;
+- }
+-
+- /**
+- * 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->regmap, ASPEED_PECI_CMD, &cmd_sts);
+- if (ret) {
+- ret = -EIO;
+- goto err_put_adapter_dev;
+- }
+-
+- priv->irq = platform_get_irq(pdev, 0);
+- if (!priv->irq) {
+- ret = -ENODEV;
+- goto err_put_adapter_dev;
+- }
+-
+- ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler,
+- 0, "peci-aspeed-irq", priv);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- init_completion(&priv->xfer_complete);
+- spin_lock_init(&priv->lock);
+-
+- priv->adapter->owner = THIS_MODULE;
+- priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev));
+- strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name));
+- priv->adapter->xfer = aspeed_peci_xfer;
+-
+- priv->rst = devm_reset_control_get(&pdev->dev, NULL);
+- if (IS_ERR(priv->rst)) {
+- dev_err(&pdev->dev,
+- "missing or invalid reset controller entry");
+- ret = PTR_ERR(priv->rst);
+- goto err_put_adapter_dev;
+- }
+- reset_control_deassert(priv->rst);
+-
+- ret = aspeed_peci_init_ctrl(priv);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- ret = peci_add_adapter(priv->adapter);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- dev_info(&pdev->dev, "peci bus %d registered, irq %d\n",
+- priv->adapter->nr, priv->irq);
+-
+- return 0;
+-
+-err_put_adapter_dev:
+- put_device(&adapter->dev);
+- return ret;
+-}
+-
+-static int aspeed_peci_remove(struct platform_device *pdev)
+-{
+- struct aspeed_peci *priv = dev_get_drvdata(&pdev->dev);
+-
+- clk_disable_unprepare(priv->clk);
+- reset_control_assert(priv->rst);
+- peci_del_adapter(priv->adapter);
+- of_node_put(priv->adapter->dev.of_node);
+-
+- return 0;
+-}
+-
+-static const struct of_device_id aspeed_peci_of_table[] = {
+- { .compatible = "aspeed,ast2400-peci", },
+- { .compatible = "aspeed,ast2500-peci", },
+- { }
+-};
+-MODULE_DEVICE_TABLE(of, aspeed_peci_of_table);
+-
+-static struct platform_driver aspeed_peci_driver = {
+- .probe = aspeed_peci_probe,
+- .remove = aspeed_peci_remove,
+- .driver = {
+- .name = "peci-aspeed",
+- .of_match_table = of_match_ptr(aspeed_peci_of_table),
+- },
+-};
+-module_platform_driver(aspeed_peci_driver);
+-
+-MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
+-MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
+-MODULE_DESCRIPTION("ASPEED PECI driver");
+-MODULE_LICENSE("GPL v2");
+diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
+index 6f241469ec7e..d1f0df8b139a 100644
+--- a/drivers/peci/peci-core.c
++++ b/drivers/peci/peci-core.c
+@@ -1,38 +1,31 @@
+ // SPDX-License-Identifier: GPL-2.0
+-// Copyright (c) 2018 Intel Corporation
++// Copyright (c) 2018-2019 Intel Corporation
+
+ #include <linux/bitfield.h>
+ #include <linux/crc8.h>
+ #include <linux/delay.h>
+-#include <linux/fs.h>
++#include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+ #include <linux/peci.h>
+ #include <linux/pm_domain.h>
+ #include <linux/pm_runtime.h>
++#include <linux/sched/task_stack.h>
+ #include <linux/slab.h>
+-#include <linux/uaccess.h>
+
+ /* Mask for getting minor revision number from DIB */
+ #define REVISION_NUM_MASK GENMASK(15, 8)
+
+-/* CRC8 table for Assure Write Frame Check */
++/* CRC8 table for Assured Write Frame Check */
+ #define PECI_CRC8_POLYNOMIAL 0x07
+ DECLARE_CRC8_TABLE(peci_crc8_table);
+
+-static struct device_type peci_adapter_type;
+-static struct device_type peci_client_type;
+-
+-/* Max number of peci cdev */
+-#define PECI_CDEV_MAX 16
+-
+-static dev_t peci_devt;
+ static bool is_registered;
+
+ static DEFINE_MUTEX(core_lock);
+ static DEFINE_IDR(peci_adapter_idr);
+
+-static struct peci_adapter *peci_get_adapter(int nr)
++struct peci_adapter *peci_get_adapter(int nr)
+ {
+ struct peci_adapter *adapter;
+
+@@ -48,10 +41,12 @@ static struct peci_adapter *peci_get_adapter(int nr)
+
+ out_unlock:
+ mutex_unlock(&core_lock);
++
+ return adapter;
+ }
++EXPORT_SYMBOL_GPL(peci_get_adapter);
+
+-static void peci_put_adapter(struct peci_adapter *adapter)
++void peci_put_adapter(struct peci_adapter *adapter)
+ {
+ if (!adapter)
+ return;
+@@ -59,6 +54,7 @@ static void peci_put_adapter(struct peci_adapter *adapter)
+ put_device(&adapter->dev);
+ module_put(adapter->owner);
+ }
++EXPORT_SYMBOL_GPL(peci_put_adapter);
+
+ static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
+@@ -84,10 +80,11 @@ static struct attribute *peci_device_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(peci_device);
+
+-static struct device_type peci_client_type = {
++struct device_type peci_client_type = {
+ .groups = peci_device_groups,
+ .release = peci_client_dev_release,
+ };
++EXPORT_SYMBOL_GPL(peci_client_type);
+
+ /**
+ * peci_verify_client - return parameter as peci_client, or NULL
+@@ -103,19 +100,120 @@ struct peci_client *peci_verify_client(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(peci_verify_client);
+
+-static u8 peci_aw_fcs(u8 *data, int len)
++/**
++ * peci_get_xfer_msg() - get a DMA safe peci_xfer_msg for the given tx and rx
++ * length
++ * @tx_len: the length of tx_buf. May be 0 if tx_buf isn't needed.
++ * @rx_len: the length of rx_buf. May be 0 if rx_buf isn't needed.
++ *
++ * Return: NULL if a DMA safe buffer was not obtained.
++ * Or a valid pointer to be used with DMA. After use, release it by
++ * calling peci_put_xfer_msg().
++ *
++ * This function must only be called from process context!
++ */
++struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len)
+ {
+- return crc8(peci_crc8_table, data, (size_t)len, 0);
++ struct peci_xfer_msg *msg;
++ u8 *tx_buf, *rx_buf;
++
++ if (tx_len) {
++ tx_buf = kzalloc(tx_len, GFP_KERNEL);
++ if (!tx_buf)
++ return NULL;
++ } else {
++ tx_buf = NULL;
++ }
++
++ if (rx_len) {
++ rx_buf = kzalloc(rx_len, GFP_KERNEL);
++ if (!rx_buf)
++ goto err_free_tx_buf;
++ } else {
++ rx_buf = NULL;
++ }
++
++ msg = kzalloc(sizeof(struct peci_xfer_msg), GFP_KERNEL);
++ if (!msg)
++ goto err_free_tx_rx_buf;
++
++ msg->tx_len = tx_len;
++ msg->tx_buf = tx_buf;
++ msg->rx_len = rx_len;
++ msg->rx_buf = rx_buf;
++
++ return msg;
++
++err_free_tx_rx_buf:
++ kfree(rx_buf);
++err_free_tx_buf:
++ kfree(tx_buf);
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(peci_get_xfer_msg);
++
++/**
++ * peci_put_xfer_msg - release a DMA safe peci_xfer_msg
++ * @msg: the message obtained from peci_get_xfer_msg(). May be NULL.
++ */
++void peci_put_xfer_msg(struct peci_xfer_msg *msg)
++{
++ if (!msg)
++ return;
++
++ kfree(msg->rx_buf);
++ kfree(msg->tx_buf);
++ kfree(msg);
++}
++EXPORT_SYMBOL_GPL(peci_put_xfer_msg);
++
++/* Calculate an Assured Write Frame Check Sequence byte */
++static int peci_aw_fcs(struct peci_xfer_msg *msg, int len, u8 *aw_fcs)
++{
++ u8 *tmp_buf;
++
++ /* Allocate a temporary buffer to use a contiguous byte array */
++ tmp_buf = kmalloc(len, GFP_KERNEL);
++ if (!tmp_buf)
++ return -ENOMEM;
++
++ tmp_buf[0] = msg->addr;
++ tmp_buf[1] = msg->tx_len;
++ tmp_buf[2] = msg->rx_len;
++ memcpy(&tmp_buf[3], msg->tx_buf, len - 3);
++
++ *aw_fcs = crc8(peci_crc8_table, tmp_buf, (size_t)len, 0);
++
++ kfree(tmp_buf);
++
++ return 0;
+ }
+
+ static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg,
+ bool do_retry, bool has_aw_fcs)
+ {
+- ktime_t start, end;
+- s64 elapsed_ms;
+- int rc = 0;
++ ulong timeout = jiffies;
++ u8 aw_fcs;
++ int ret;
++
++ /*
++ * In case if adapter uses DMA, check at here whether tx and rx buffers
++ * are DMA capable or not.
++ */
++ if (IS_ENABLED(CONFIG_HAS_DMA) && adapter->use_dma) {
++ if (is_vmalloc_addr(msg->tx_buf) ||
++ is_vmalloc_addr(msg->rx_buf)) {
++ WARN_ONCE(1, "xfer msg is not dma capable\n");
++ return -EAGAIN;
++ } else if (object_is_on_stack(msg->tx_buf) ||
++ object_is_on_stack(msg->rx_buf)) {
++ WARN_ONCE(1, "xfer msg is on stack\n");
++ return -EAGAIN;
++ }
++ }
+
+- /**
++ /*
+ * For some commands, the PECI originator may need to retry a command if
+ * the processor PECI client responds with a 0x8x completion code. In
+ * each instance, the processor PECI client may have started the
+@@ -125,55 +223,51 @@ static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg,
+ */
+
+ if (do_retry)
+- start = ktime_get();
++ timeout += msecs_to_jiffies(PECI_DEV_RETRY_TIME_MS);
+
+- do {
+- rc = adapter->xfer(adapter, msg);
++ for (;;) {
++ ret = adapter->xfer(adapter, msg);
+
+- if (!do_retry || rc)
+- break;
+-
+- if (msg->rx_buf[0] == DEV_PECI_CC_SUCCESS)
++ if (!do_retry || ret || !msg->rx_buf)
+ break;
+
+ /* Retry is needed when completion code is 0x8x */
+- if ((msg->rx_buf[0] & DEV_PECI_CC_RETRY_CHECK_MASK) !=
+- DEV_PECI_CC_NEED_RETRY) {
+- rc = -EIO;
++ if ((msg->rx_buf[0] & PECI_DEV_CC_RETRY_CHECK_MASK) !=
++ PECI_DEV_CC_NEED_RETRY)
+ break;
+- }
+
+ /* Set the retry bit to indicate a retry attempt */
+- msg->tx_buf[1] |= DEV_PECI_RETRY_BIT;
++ msg->tx_buf[1] |= PECI_DEV_RETRY_BIT;
+
+ /* Recalculate the AW FCS if it has one */
+- if (has_aw_fcs)
+- msg->tx_buf[msg->tx_len - 1] = 0x80 ^
+- peci_aw_fcs((u8 *)msg,
+- 2 + msg->tx_len);
++ if (has_aw_fcs) {
++ ret = peci_aw_fcs(msg, 2 + msg->tx_len, &aw_fcs);
++ if (ret)
++ break;
++
++ msg->tx_buf[msg->tx_len - 1] = 0x80 ^ aw_fcs;
++ }
+
+- /**
++ /*
+ * Retry for at least 250ms before returning an error.
+ * Retry interval guideline:
+ * No minimum < Retry Interval < No maximum
+ * (recommend 10ms)
+ */
+- end = ktime_get();
+- elapsed_ms = ktime_to_ms(ktime_sub(end, start));
+- if (elapsed_ms >= DEV_PECI_RETRY_TIME_MS) {
++ if (time_after(jiffies, timeout)) {
+ dev_dbg(&adapter->dev, "Timeout retrying xfer!\n");
+- rc = -ETIMEDOUT;
++ ret = -ETIMEDOUT;
+ break;
+ }
+
+- usleep_range((DEV_PECI_RETRY_INTERVAL_USEC >> 2) + 1,
+- DEV_PECI_RETRY_INTERVAL_USEC);
+- } while (true);
++ usleep_range((PECI_DEV_RETRY_INTERVAL_USEC >> 2) + 1,
++ PECI_DEV_RETRY_INTERVAL_USEC);
++ }
+
+- if (rc)
+- dev_dbg(&adapter->dev, "xfer error, rc: %d\n", rc);
++ if (ret)
++ dev_dbg(&adapter->dev, "xfer error: %d\n", ret);
+
+- return rc;
++ return ret;
+ }
+
+ static int peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg)
+@@ -190,34 +284,37 @@ static int peci_xfer_with_retries(struct peci_adapter *adapter,
+
+ static int peci_scan_cmd_mask(struct peci_adapter *adapter)
+ {
+- struct peci_xfer_msg msg;
++ struct peci_xfer_msg *msg;
+ u8 revision;
+- int rc = 0;
++ int ret;
+ u64 dib;
+
+ /* Update command mask just once */
+ if (adapter->cmd_mask & BIT(PECI_CMD_XFER))
+ return 0;
+
+- msg.addr = PECI_BASE_ADDR;
+- msg.tx_len = GET_DIB_WR_LEN;
+- msg.rx_len = GET_DIB_RD_LEN;
+- msg.tx_buf[0] = GET_DIB_PECI_CMD;
++ msg = peci_get_xfer_msg(PECI_GET_DIB_WR_LEN, PECI_GET_DIB_RD_LEN);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = PECI_BASE_ADDR;
++ msg->tx_buf[0] = PECI_GET_DIB_CMD;
+
+- rc = peci_xfer(adapter, &msg);
+- if (rc)
+- return rc;
++ ret = peci_xfer(adapter, msg);
++ if (ret)
++ return ret;
+
+- dib = le64_to_cpup((__le64 *)msg.rx_buf);
++ dib = le64_to_cpup((__le64 *)msg->rx_buf);
+
+ /* Check special case for Get DIB command */
+ if (dib == 0) {
+ dev_dbg(&adapter->dev, "DIB read as 0\n");
+- return -EIO;
++ ret = -EIO;
++ goto out;
+ }
+
+- /**
+- * Setting up the supporting commands based on minor revision number.
++ /*
++ * Setting up the supporting commands based on revision number.
+ * See PECI Spec Table 3-1.
+ */
+ revision = FIELD_GET(REVISION_NUM_MASK, dib);
+@@ -243,10 +340,14 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter)
+ adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB);
+ adapter->cmd_mask |= BIT(PECI_CMD_PING);
+
+- return rc;
++out:
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd)
++static int peci_check_cmd_support(struct peci_adapter *adapter,
++ enum peci_cmd cmd)
+ {
+ if (!(adapter->cmd_mask & BIT(PECI_CMD_PING)) &&
+ peci_scan_cmd_mask(adapter) < 0) {
+@@ -262,70 +363,87 @@ static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd)
+ return 0;
+ }
+
+-static int peci_ioctl_xfer(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_xfer(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_xfer_msg *msg = vmsg;
+
+ return peci_xfer(adapter, msg);
+ }
+
+-static int peci_ioctl_ping(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_ping(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_ping_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
++ struct peci_xfer_msg *msg;
++ int ret;
++
++ msg = peci_get_xfer_msg(0, 0);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
+
+- msg.addr = umsg->addr;
+- msg.tx_len = 0;
+- msg.rx_len = 0;
++ ret = peci_xfer(adapter, msg);
+
+- return peci_xfer(adapter, &msg);
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_get_dib(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_get_dib(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_get_dib_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc;
++ struct peci_xfer_msg *msg;
++ int ret;
+
+- msg.addr = umsg->addr;
+- msg.tx_len = GET_DIB_WR_LEN;
+- msg.rx_len = GET_DIB_RD_LEN;
+- msg.tx_buf[0] = GET_DIB_PECI_CMD;
++ msg = peci_get_xfer_msg(PECI_GET_DIB_WR_LEN, PECI_GET_DIB_RD_LEN);
++ if (!msg)
++ return -ENOMEM;
+
+- rc = peci_xfer(adapter, &msg);
+- if (rc)
+- return rc;
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_GET_DIB_CMD;
+
+- umsg->dib = le64_to_cpup((__le64 *)msg.rx_buf);
++ ret = peci_xfer(adapter, msg);
++ if (ret)
++ goto out;
+
+- return 0;
++ umsg->dib = le64_to_cpup((__le64 *)msg->rx_buf);
++
++out:
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_get_temp(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_get_temp(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_get_temp_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc;
++ struct peci_xfer_msg *msg;
++ int ret;
+
+- msg.addr = umsg->addr;
+- msg.tx_len = GET_TEMP_WR_LEN;
+- msg.rx_len = GET_TEMP_RD_LEN;
+- msg.tx_buf[0] = GET_TEMP_PECI_CMD;
++ msg = peci_get_xfer_msg(PECI_GET_TEMP_WR_LEN, PECI_GET_TEMP_RD_LEN);
++ if (!msg)
++ return -ENOMEM;
+
+- rc = peci_xfer(adapter, &msg);
+- if (rc)
+- return rc;
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_GET_TEMP_CMD;
+
+- umsg->temp_raw = le16_to_cpup((__le16 *)msg.rx_buf);
++ ret = peci_xfer(adapter, msg);
++ if (ret)
++ goto out;
+
+- return 0;
++ umsg->temp_raw = le16_to_cpup((__le16 *)msg->rx_buf);
++
++out:
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_rd_pkg_cfg_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc = 0;
++ struct peci_xfer_msg *msg;
++ int ret;
+
+ /* Per the PECI spec, the read length must be a byte, word, or dword */
+ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) {
+@@ -334,29 +452,35 @@ static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+ return -EINVAL;
+ }
+
+- msg.addr = umsg->addr;
+- msg.tx_len = RDPKGCFG_WRITE_LEN;
+- /* read lengths of 1 and 2 result in an error, so only use 4 for now */
+- msg.rx_len = RDPKGCFG_READ_LEN_BASE + umsg->rx_len;
+- msg.tx_buf[0] = RDPKGCFG_PECI_CMD;
+- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
+- /* Host ID is 0 for PECI 3.0 */
+- msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */
+- msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
+- msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
++ msg = peci_get_xfer_msg(PECI_RDPKGCFG_WRITE_LEN,
++ PECI_RDPKGCFG_READ_LEN_BASE + umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDPKGCFG_CMD;
++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
++ /* Host ID is 0 for PECI 3.0 */
++ msg->tx_buf[2] = umsg->index; /* RdPkgConfig index */
++ msg->tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
++ msg->tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
+
+- rc = peci_xfer_with_retries(adapter, &msg, false);
+- if (!rc)
+- memcpy(umsg->pkg_config, &msg.rx_buf[1], umsg->rx_len);
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->pkg_config, &msg->rx_buf[1], umsg->rx_len);
+
+- return rc;
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_wr_pkg_cfg_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc = 0, i;
++ struct peci_xfer_msg *msg;
++ int ret, i;
++ u8 aw_fcs;
+
+ /* Per the PECI spec, the write length must be a dword */
+ if (umsg->tx_len != 4) {
+@@ -365,86 +489,116 @@ static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg)
+ return -EINVAL;
+ }
+
+- msg.addr = umsg->addr;
+- msg.tx_len = WRPKGCFG_WRITE_LEN_BASE + umsg->tx_len;
+- /* read lengths of 1 and 2 result in an error, so only use 4 for now */
+- msg.rx_len = WRPKGCFG_READ_LEN;
+- msg.tx_buf[0] = WRPKGCFG_PECI_CMD;
+- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
++ msg = peci_get_xfer_msg(PECI_WRPKGCFG_WRITE_LEN_BASE + umsg->tx_len,
++ PECI_WRPKGCFG_READ_LEN);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_WRPKGCFG_CMD;
++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+- msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */
+- msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
+- msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
++ msg->tx_buf[2] = umsg->index; /* RdPkgConfig index */
++ msg->tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */
++ msg->tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */
+ for (i = 0; i < umsg->tx_len; i++)
+- msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
++ msg->tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
++
++ /* Add an Assured Write Frame Check Sequence byte */
++ ret = peci_aw_fcs(msg, 8 + umsg->tx_len, &aw_fcs);
++ if (ret)
++ goto out;
+
+- /* Add an Assure Write Frame Check Sequence byte */
+- msg.tx_buf[5 + i] = 0x80 ^
+- peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len);
++ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs;
+
+- rc = peci_xfer_with_retries(adapter, &msg, true);
++ ret = peci_xfer_with_retries(adapter, msg, true);
+
+- return rc;
++out:
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_rd_ia_msr(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_rd_ia_msr(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_rd_ia_msr_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc = 0;
+-
+- msg.addr = umsg->addr;
+- msg.tx_len = RDIAMSR_WRITE_LEN;
+- msg.rx_len = RDIAMSR_READ_LEN;
+- msg.tx_buf[0] = RDIAMSR_PECI_CMD;
+- msg.tx_buf[1] = 0;
+- msg.tx_buf[2] = umsg->thread_id;
+- msg.tx_buf[3] = (u8)umsg->address;
+- msg.tx_buf[4] = (u8)(umsg->address >> 8);
+-
+- rc = peci_xfer_with_retries(adapter, &msg, false);
+- if (!rc)
+- memcpy(&umsg->value, &msg.rx_buf[1], sizeof(uint64_t));
+-
+- return rc;
++ struct peci_xfer_msg *msg;
++ int ret;
++
++ msg = peci_get_xfer_msg(PECI_RDIAMSR_WRITE_LEN, PECI_RDIAMSR_READ_LEN);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDIAMSR_CMD;
++ msg->tx_buf[1] = 0;
++ msg->tx_buf[2] = umsg->thread_id;
++ msg->tx_buf[3] = (u8)umsg->address;
++ msg->tx_buf[4] = (u8)(umsg->address >> 8);
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(&umsg->value, &msg->rx_buf[1], sizeof(uint64_t));
++
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
+ }
+
+-static int peci_ioctl_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_wr_ia_msr(struct peci_adapter *adapter, void *vmsg)
++{
++ return -ENOSYS; /* Not implemented yet */
++}
++
++static int peci_cmd_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_rd_pci_cfg_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
++ struct peci_xfer_msg *msg;
+ u32 address;
+- int rc = 0;
++ int ret;
++
++ msg = peci_get_xfer_msg(PECI_RDPCICFG_WRITE_LEN,
++ PECI_RDPCICFG_READ_LEN);
++ if (!msg)
++ return -ENOMEM;
+
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [27:20] - Bus */
+ /* [31:28] - Reserved */
+- msg.addr = umsg->addr;
+- msg.tx_len = RDPCICFG_WRITE_LEN;
+- msg.rx_len = RDPCICFG_READ_LEN;
+- msg.tx_buf[0] = RDPCICFG_PECI_CMD;
+- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDPCICFG_CMD;
++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
+ /* Host ID is 0 for PECI 3.0 */
+- msg.tx_buf[2] = (u8)address; /* LSB - PCI Config Address */
+- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Config Address */
+- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Config Address */
+- msg.tx_buf[5] = (u8)(address >> 24); /* MSB - PCI Config Address */
++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Config Address */
++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Config Address */
++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Config Address */
++ msg->tx_buf[5] = (u8)(address >> 24); /* MSB - PCI Config Address */
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->pci_config, &msg->rx_buf[1], 4);
+
+- rc = peci_xfer_with_retries(adapter, &msg, false);
+- if (!rc)
+- memcpy(umsg->pci_config, &msg.rx_buf[1], 4);
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
+
+- return rc;
++ return ret;
+ }
+
+-static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_wr_pci_cfg(struct peci_adapter *adapter, void *vmsg)
++{
++ return -ENOSYS; /* Not implemented yet */
++}
++
++static int peci_cmd_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_rd_pci_cfg_local_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
++ struct peci_xfer_msg *msg;
+ u32 address;
+- int rc = 0;
++ int ret;
+
+ /* Per the PECI spec, the read length must be a byte, word, or dword */
+ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) {
+@@ -453,34 +607,42 @@ static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+ return -EINVAL;
+ }
+
++ msg = peci_get_xfer_msg(PECI_RDPCICFGLOCAL_WRITE_LEN,
++ PECI_RDPCICFGLOCAL_READ_LEN_BASE +
++ umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [23:20] - Bus */
+
+- msg.addr = umsg->addr;
+- msg.tx_len = RDPCICFGLOCAL_WRITE_LEN;
+- msg.rx_len = RDPCICFGLOCAL_READ_LEN_BASE + umsg->rx_len;
+- msg.tx_buf[0] = RDPCICFGLOCAL_PECI_CMD;
+- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
+- /* Host ID is 0 for PECI 3.0 */
+- msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
+- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
+- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDPCICFGLOCAL_CMD;
++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
++ /* Host ID is 0 for PECI 3.0 */
++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->pci_config, &msg->rx_buf[1], umsg->rx_len);
+
+- rc = peci_xfer_with_retries(adapter, &msg, false);
+- if (!rc)
+- memcpy(umsg->pci_config, &msg.rx_buf[1], umsg->rx_len);
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
+
+- return rc;
++ return ret;
+ }
+
+-static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
++static int peci_cmd_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+ {
+ struct peci_wr_pci_cfg_local_msg *umsg = vmsg;
+- struct peci_xfer_msg msg;
+- int rc = 0, i;
++ struct peci_xfer_msg *msg;
+ u32 address;
++ int ret, i;
++ u8 aw_fcs;
+
+ /* Per the PECI spec, the write length must be a byte, word, or dword */
+ if (umsg->tx_len != 1 && umsg->tx_len != 2 && umsg->tx_len != 4) {
+@@ -489,47 +651,57 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+ return -EINVAL;
+ }
+
++ msg = peci_get_xfer_msg(PECI_WRPCICFGLOCAL_WRITE_LEN_BASE +
++ umsg->tx_len, PECI_WRPCICFGLOCAL_READ_LEN);
++ if (!msg)
++ return -ENOMEM;
++
+ address = umsg->reg; /* [11:0] - Register */
+ address |= (u32)umsg->function << 12; /* [14:12] - Function */
+ address |= (u32)umsg->device << 15; /* [19:15] - Device */
+ address |= (u32)umsg->bus << 20; /* [23:20] - Bus */
+
+- msg.addr = umsg->addr;
+- msg.tx_len = WRPCICFGLOCAL_WRITE_LEN_BASE + umsg->tx_len;
+- msg.rx_len = WRPCICFGLOCAL_READ_LEN;
+- msg.tx_buf[0] = WRPCICFGLOCAL_PECI_CMD;
+- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
+- /* Host ID is 0 for PECI 3.0 */
+- msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
+- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
+- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_WRPCICFGLOCAL_CMD;
++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */
++ /* Host ID is 0 for PECI 3.0 */
++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */
++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */
++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */
+ for (i = 0; i < umsg->tx_len; i++)
+- msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
++ msg->tx_buf[5 + i] = (u8)(umsg->value >> (i << 3));
++
++ /* Add an Assured Write Frame Check Sequence byte */
++ ret = peci_aw_fcs(msg, 8 + umsg->tx_len, &aw_fcs);
++ if (ret)
++ goto out;
++
++ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs;
+
+- /* Add an Assure Write Frame Check Sequence byte */
+- msg.tx_buf[5 + i] = 0x80 ^
+- peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len);
++ ret = peci_xfer_with_retries(adapter, msg, true);
+
+- rc = peci_xfer_with_retries(adapter, &msg, true);
++out:
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
+
+- return rc;
++ return ret;
+ }
+
+-typedef int (*peci_ioctl_fn_type)(struct peci_adapter *, void *);
+-
+-static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = {
+- peci_ioctl_xfer,
+- peci_ioctl_ping,
+- peci_ioctl_get_dib,
+- peci_ioctl_get_temp,
+- peci_ioctl_rd_pkg_cfg,
+- peci_ioctl_wr_pkg_cfg,
+- peci_ioctl_rd_ia_msr,
+- NULL, /* Reserved */
+- peci_ioctl_rd_pci_cfg,
+- NULL, /* Reserved */
+- peci_ioctl_rd_pci_cfg_local,
+- peci_ioctl_wr_pci_cfg_local,
++typedef int (*peci_cmd_fn_type)(struct peci_adapter *, void *);
++
++static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = {
++ peci_cmd_xfer,
++ peci_cmd_ping,
++ peci_cmd_get_dib,
++ peci_cmd_get_temp,
++ peci_cmd_rd_pkg_cfg,
++ peci_cmd_wr_pkg_cfg,
++ peci_cmd_rd_ia_msr,
++ peci_cmd_wr_ia_msr,
++ peci_cmd_rd_pci_cfg,
++ peci_cmd_wr_pci_cfg,
++ peci_cmd_rd_pci_cfg_local,
++ peci_cmd_wr_pci_cfg_local,
+ };
+
+ /**
+@@ -545,109 +717,28 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = {
+ */
+ int peci_command(struct peci_adapter *adapter, enum peci_cmd cmd, void *vmsg)
+ {
+- int rc = 0;
++ int ret;
+
+ if (cmd >= PECI_CMD_MAX || cmd < PECI_CMD_XFER)
+- return -EINVAL;
++ return -ENOTTY;
+
+ dev_dbg(&adapter->dev, "%s, cmd=0x%02x\n", __func__, cmd);
+
+- if (!peci_ioctl_fn[cmd])
++ if (!peci_cmd_fn[cmd])
+ return -EINVAL;
+
+- rt_mutex_lock(&adapter->bus_lock);
++ mutex_lock(&adapter->bus_lock);
+
+- rc = peci_cmd_support(adapter, cmd);
+- if (!rc)
+- rc = peci_ioctl_fn[cmd](adapter, vmsg);
++ ret = peci_check_cmd_support(adapter, cmd);
++ if (!ret)
++ ret = peci_cmd_fn[cmd](adapter, vmsg);
+
+- rt_mutex_unlock(&adapter->bus_lock);
++ mutex_unlock(&adapter->bus_lock);
+
+- return rc;
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(peci_command);
+
+-static long peci_ioctl(struct file *file, unsigned int iocmd, unsigned long arg)
+-{
+- struct peci_adapter *adapter = file->private_data;
+- void __user *argp = (void __user *)arg;
+- unsigned int msg_len;
+- enum peci_cmd cmd;
+- int rc = 0;
+- u8 *msg;
+-
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+-
+- dev_dbg(&adapter->dev, "ioctl, cmd=0x%x, arg=0x%lx\n", iocmd, arg);
+-
+- switch (iocmd) {
+- case PECI_IOC_XFER:
+- case PECI_IOC_PING:
+- case PECI_IOC_GET_DIB:
+- case PECI_IOC_GET_TEMP:
+- case PECI_IOC_RD_PKG_CFG:
+- case PECI_IOC_WR_PKG_CFG:
+- case PECI_IOC_RD_IA_MSR:
+- case PECI_IOC_RD_PCI_CFG:
+- case PECI_IOC_RD_PCI_CFG_LOCAL:
+- case PECI_IOC_WR_PCI_CFG_LOCAL:
+- cmd = _IOC_NR(iocmd);
+- msg_len = _IOC_SIZE(iocmd);
+- break;
+-
+- default:
+- dev_dbg(&adapter->dev, "Invalid ioctl cmd : 0x%x\n", iocmd);
+- return -ENOTTY;
+- }
+-
+- if (!access_ok(argp, msg_len))
+- return -EFAULT;
+-
+- msg = memdup_user(argp, msg_len);
+- if (IS_ERR(msg))
+- return PTR_ERR(msg);
+-
+- rc = peci_command(adapter, cmd, msg);
+-
+- if (!rc && copy_to_user(argp, msg, msg_len))
+- rc = -EFAULT;
+-
+- kfree(msg);
+- return (long)rc;
+-}
+-
+-static int peci_open(struct inode *inode, struct file *file)
+-{
+- unsigned int minor = iminor(inode);
+- struct peci_adapter *adapter;
+-
+- adapter = peci_get_adapter(minor);
+- if (!adapter)
+- return -ENODEV;
+-
+- file->private_data = adapter;
+-
+- return 0;
+-}
+-
+-static int peci_release(struct inode *inode, struct file *file)
+-{
+- struct peci_adapter *adapter = file->private_data;
+-
+- peci_put_adapter(adapter);
+- file->private_data = NULL;
+-
+- return 0;
+-}
+-
+-static const struct file_operations peci_fops = {
+- .owner = THIS_MODULE,
+- .unlocked_ioctl = peci_ioctl,
+- .open = peci_open,
+- .release = peci_release,
+-};
+-
+ static int peci_detect(struct peci_adapter *adapter, u8 addr)
+ {
+ struct peci_ping_msg msg;
+@@ -666,9 +757,9 @@ peci_of_match_device(const struct of_device_id *matches,
+ return NULL;
+
+ return of_match_device(matches, &client->dev);
+-#else
++#else /* CONFIG_OF */
+ return NULL;
+-#endif
++#endif /* CONFIG_OF */
+ }
+
+ static const struct peci_device_id *
+@@ -737,6 +828,7 @@ static int peci_device_probe(struct device *dev)
+
+ err_detach_pm_domain:
+ dev_pm_domain_detach(&client->dev, true);
++
+ return status;
+ }
+
+@@ -775,13 +867,14 @@ static void peci_device_shutdown(struct device *dev)
+ driver->shutdown(client);
+ }
+
+-static struct bus_type peci_bus_type = {
++struct bus_type peci_bus_type = {
+ .name = "peci",
+ .match = peci_device_match,
+ .probe = peci_device_probe,
+ .remove = peci_device_remove,
+ .shutdown = peci_device_shutdown,
+ };
++EXPORT_SYMBOL_GPL(peci_bus_type);
+
+ static int peci_check_addr_validity(u8 addr)
+ {
+@@ -814,18 +907,23 @@ static int peci_check_client_busy(struct device *dev, void *client_new_p)
+ int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id)
+ {
+ struct peci_rd_pkg_cfg_msg msg;
+- int rc;
++ int ret;
+
+ msg.addr = addr;
+- msg.index = MBX_INDEX_CPU_ID;
+- msg.param = PKG_ID_CPU_ID;
++ msg.index = PECI_MBX_INDEX_CPU_ID;
++ msg.param = PECI_PKG_ID_CPU_ID;
+ msg.rx_len = 4;
+
+- rc = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg);
+- if (!rc)
+- *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config);
++ ret = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg);
++ if (ret)
++ return ret;
++
++ if (msg.cc != PECI_DEV_CC_SUCCESS)
++ return -EAGAIN;
++
++ *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config);
+
+- return rc;
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(peci_get_cpu_id);
+
+@@ -833,7 +931,7 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter,
+ struct peci_board_info const *info)
+ {
+ struct peci_client *client;
+- int rc;
++ int ret;
+
+ /* Increase reference count for the adapter assigned */
+ if (!peci_get_adapter(adapter->nr))
+@@ -847,46 +945,49 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter,
+ client->addr = info->addr;
+ strlcpy(client->name, info->type, sizeof(client->name));
+
+- rc = peci_check_addr_validity(client->addr);
+- if (rc) {
++ ret = peci_check_addr_validity(client->addr);
++ if (ret) {
+ dev_err(&adapter->dev, "Invalid PECI CPU address 0x%02hx\n",
+ client->addr);
+ goto err_free_client_silent;
+ }
+
+ /* Check online status of client */
+- rc = peci_detect(adapter, client->addr);
+- if (rc)
++ ret = peci_detect(adapter, client->addr);
++ if (ret)
+ goto err_free_client;
+
+- rc = device_for_each_child(&adapter->dev, client,
+- peci_check_client_busy);
+- if (rc)
++ ret = device_for_each_child(&adapter->dev, client,
++ peci_check_client_busy);
++ if (ret)
+ goto err_free_client;
+
+ client->dev.parent = &client->adapter->dev;
+ client->dev.bus = &peci_bus_type;
+ client->dev.type = &peci_client_type;
+- client->dev.of_node = info->of_node;
++ client->dev.of_node = of_node_get(info->of_node);
+ dev_set_name(&client->dev, "%d-%02x", adapter->nr, client->addr);
+
+- rc = device_register(&client->dev);
+- if (rc)
+- goto err_free_client;
++ ret = device_register(&client->dev);
++ if (ret)
++ goto err_put_of_node;
+
+ dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+ client->name, dev_name(&client->dev));
+
+ return client;
+
++err_put_of_node:
++ of_node_put(info->of_node);
+ err_free_client:
+ dev_err(&adapter->dev,
+ "Failed to register peci client %s at 0x%02x (%d)\n",
+- client->name, client->addr, rc);
++ client->name, client->addr, ret);
+ err_free_client_silent:
+ kfree(client);
+ err_put_adapter:
+ peci_put_adapter(adapter);
++
+ return NULL;
+ }
+
+@@ -895,8 +996,10 @@ static void peci_unregister_device(struct peci_client *client)
+ if (!client)
+ return;
+
+- if (client->dev.of_node)
++ if (client->dev.of_node) {
+ of_node_clear_flag(client->dev.of_node, OF_POPULATED);
++ of_node_put(client->dev.of_node);
++ }
+
+ device_unregister(&client->dev);
+ }
+@@ -916,7 +1019,7 @@ static void peci_adapter_dev_release(struct device *dev)
+
+ dev_dbg(dev, "%s: %s\n", __func__, adapter->name);
+ mutex_destroy(&adapter->userspace_clients_lock);
+- rt_mutex_destroy(&adapter->bus_lock);
++ mutex_destroy(&adapter->bus_lock);
+ kfree(adapter);
+ }
+
+@@ -928,7 +1031,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev,
+ struct peci_board_info info = {};
+ struct peci_client *client;
+ char *blank, end;
+- int rc;
++ short addr;
++ int ret;
+
+ /* Parse device type */
+ blank = strchr(buf, ' ');
+@@ -943,16 +1047,17 @@ static ssize_t peci_sysfs_new_device(struct device *dev,
+ memcpy(info.type, buf, blank - buf);
+
+ /* Parse remaining parameters, reject extra parameters */
+- rc = sscanf(++blank, "%hi%c", &info.addr, &end);
+- if (rc < 1) {
++ ret = sscanf(++blank, "%hi%c", &addr, &end);
++ if (ret < 1) {
+ dev_err(dev, "%s: Can't parse client address\n", "new_device");
+ return -EINVAL;
+ }
+- if (rc > 1 && end != '\n') {
++ if (ret > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "new_device");
+ return -EINVAL;
+ }
+
++ info.addr = (u8)addr;
+ client = peci_new_device(adapter, &info);
+ if (!client)
+ return -EINVAL;
+@@ -961,8 +1066,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev,
+ mutex_lock(&adapter->userspace_clients_lock);
+ list_add_tail(&client->detected, &adapter->userspace_clients);
+ mutex_unlock(&adapter->userspace_clients_lock);
+- dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
+- info.type, info.addr);
++ dev_dbg(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
++ info.type, info.addr);
+
+ return count;
+ }
+@@ -975,9 +1080,9 @@ static ssize_t peci_sysfs_delete_device(struct device *dev,
+ struct peci_adapter *adapter = to_peci_adapter(dev);
+ struct peci_client *client, *next;
+ struct peci_board_info info = {};
+- struct peci_driver *driver;
+ char *blank, end;
+- int rc;
++ short addr;
++ int ret;
+
+ /* Parse device type */
+ blank = strchr(buf, ' ');
+@@ -992,41 +1097,41 @@ static ssize_t peci_sysfs_delete_device(struct device *dev,
+ memcpy(info.type, buf, blank - buf);
+
+ /* Parse remaining parameters, reject extra parameters */
+- rc = sscanf(++blank, "%hi%c", &info.addr, &end);
+- if (rc < 1) {
++ ret = sscanf(++blank, "%hi%c", &addr, &end);
++ if (ret < 1) {
+ dev_err(dev, "%s: Can't parse client address\n",
+ "delete_device");
+ return -EINVAL;
+ }
+- if (rc > 1 && end != '\n') {
++ if (ret > 1 && end != '\n') {
+ dev_err(dev, "%s: Extra parameters\n", "delete_device");
+ return -EINVAL;
+ }
+
++ info.addr = (u8)addr;
++
+ /* Make sure the device was added through sysfs */
+- rc = -ENOENT;
++ ret = -ENOENT;
+ mutex_lock(&adapter->userspace_clients_lock);
+ list_for_each_entry_safe(client, next, &adapter->userspace_clients,
+ detected) {
+- driver = to_peci_driver(client->dev.driver);
+-
+ if (client->addr == info.addr &&
+ !strncmp(client->name, info.type, PECI_NAME_SIZE)) {
+- dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",
+- "delete_device", client->name, client->addr);
++ dev_dbg(dev, "%s: Deleting device %s at 0x%02hx\n",
++ "delete_device", client->name, client->addr);
+ list_del(&client->detected);
+ peci_unregister_device(client);
+- rc = count;
++ ret = count;
+ break;
+ }
+ }
+ mutex_unlock(&adapter->userspace_clients_lock);
+
+- if (rc < 0)
+- dev_err(dev, "%s: Can't find device in list\n",
++ if (ret < 0)
++ dev_dbg(dev, "%s: Can't find device in list\n",
+ "delete_device");
+
+- return rc;
++ return ret;
+ }
+ static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL,
+ peci_sysfs_delete_device);
+@@ -1039,10 +1144,11 @@ static struct attribute *peci_adapter_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(peci_adapter);
+
+-static struct device_type peci_adapter_type = {
++struct device_type peci_adapter_type = {
+ .groups = peci_adapter_groups,
+ .release = peci_adapter_dev_release,
+ };
++EXPORT_SYMBOL_GPL(peci_adapter_type);
+
+ /**
+ * peci_verify_adapter - return parameter as peci_adapter, or NULL
+@@ -1063,32 +1169,26 @@ static struct peci_client *peci_of_register_device(struct peci_adapter *adapter,
+ struct device_node *node)
+ {
+ struct peci_board_info info = {};
+- struct peci_client *result;
+- const __be32 *addr_be;
+- int len;
++ struct peci_client *client;
++ u32 addr;
++ int ret;
+
+ dev_dbg(&adapter->dev, "register %pOF\n", node);
+
+- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+- dev_err(&adapter->dev, "modalias failure on %pOF\n", node);
+- return ERR_PTR(-EINVAL);
+- }
+-
+- addr_be = of_get_property(node, "reg", &len);
+- if (!addr_be || len < sizeof(*addr_be)) {
++ ret = of_property_read_u32(node, "reg", &addr);
++ if (ret) {
+ dev_err(&adapter->dev, "invalid reg on %pOF\n", node);
+- return ERR_PTR(-EINVAL);
++ return ERR_PTR(ret);
+ }
+
+- info.addr = be32_to_cpup(addr_be);
+- info.of_node = of_node_get(node);
++ info.addr = addr;
++ info.of_node = node;
+
+- result = peci_new_device(adapter, &info);
+- if (!result)
+- result = ERR_PTR(-EINVAL);
++ client = peci_new_device(adapter, &info);
++ if (!client)
++ client = ERR_PTR(-EINVAL);
+
+- of_node_put(node);
+- return result;
++ return client;
+ }
+
+ static void peci_of_register_devices(struct peci_adapter *adapter)
+@@ -1119,7 +1219,7 @@ static void peci_of_register_devices(struct peci_adapter *adapter)
+
+ of_node_put(bus);
+ }
+-#else
++#else /* CONFIG_OF */
+ static void peci_of_register_devices(struct peci_adapter *adapter) { }
+ #endif /* CONFIG_OF */
+
+@@ -1163,9 +1263,7 @@ static struct peci_adapter *peci_of_find_adapter(struct device_node *node)
+ return adapter;
+ }
+
+-static int peci_of_notify(struct notifier_block *nb,
+- unsigned long action,
+- void *arg)
++static int peci_of_notify(struct notifier_block *nb, ulong action, void *arg)
+ {
+ struct of_reconfig_data *rd = arg;
+ struct peci_adapter *adapter;
+@@ -1216,7 +1314,7 @@ static int peci_of_notify(struct notifier_block *nb,
+ static struct notifier_block peci_of_notifier = {
+ .notifier_call = peci_of_notify,
+ };
+-#else
++#else /* CONFIG_OF_DYNAMIC */
+ extern struct notifier_block peci_of_notifier;
+ #endif /* CONFIG_OF_DYNAMIC */
+
+@@ -1240,7 +1338,7 @@ extern struct notifier_block peci_of_notifier;
+ *
+ * Return: the peci_adapter structure on success, else NULL.
+ */
+-struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size)
++struct peci_adapter *peci_alloc_adapter(struct device *dev, uint size)
+ {
+ struct peci_adapter *adapter;
+
+@@ -1263,7 +1361,7 @@ EXPORT_SYMBOL_GPL(peci_alloc_adapter);
+
+ static int peci_register_adapter(struct peci_adapter *adapter)
+ {
+- int rc = -EINVAL;
++ int ret = -EINVAL;
+
+ /* Can't register until after driver model init */
+ if (WARN_ON(!is_registered))
+@@ -1275,27 +1373,17 @@ static int peci_register_adapter(struct peci_adapter *adapter)
+ if (WARN(!adapter->xfer, "peci adapter has no xfer function\n"))
+ goto err_free_idr;
+
+- rt_mutex_init(&adapter->bus_lock);
++ mutex_init(&adapter->bus_lock);
+ mutex_init(&adapter->userspace_clients_lock);
+ INIT_LIST_HEAD(&adapter->userspace_clients);
+
+ dev_set_name(&adapter->dev, "peci-%d", adapter->nr);
+
+- /* cdev */
+- cdev_init(&adapter->cdev, &peci_fops);
+- adapter->cdev.owner = THIS_MODULE;
+- adapter->dev.devt = MKDEV(MAJOR(peci_devt), adapter->nr);
+- rc = cdev_add(&adapter->cdev, adapter->dev.devt, 1);
+- if (rc) {
+- pr_err("adapter '%s': can't add cdev (%d)\n",
+- adapter->name, rc);
+- goto err_free_idr;
+- }
+- rc = device_add(&adapter->dev);
+- if (rc) {
++ ret = device_add(&adapter->dev);
++ if (ret) {
+ pr_err("adapter '%s': can't add device (%d)\n",
+- adapter->name, rc);
+- goto err_del_cdev;
++ adapter->name, ret);
++ goto err_free_idr;
+ }
+
+ dev_dbg(&adapter->dev, "adapter [%s] registered\n", adapter->name);
+@@ -1309,13 +1397,11 @@ static int peci_register_adapter(struct peci_adapter *adapter)
+
+ return 0;
+
+-err_del_cdev:
+- cdev_del(&adapter->cdev);
+ err_free_idr:
+ mutex_lock(&core_lock);
+ idr_remove(&peci_adapter_idr, adapter->nr);
+ mutex_unlock(&core_lock);
+- return rc;
++ return ret;
+ }
+
+ static int peci_add_numbered_adapter(struct peci_adapter *adapter)
+@@ -1411,7 +1497,7 @@ void peci_del_adapter(struct peci_adapter *adapter)
+ }
+ mutex_unlock(&adapter->userspace_clients_lock);
+
+- /**
++ /*
+ * Detach any active clients. This can't fail, thus we do not
+ * check the returned value.
+ */
+@@ -1420,13 +1506,8 @@ void peci_del_adapter(struct peci_adapter *adapter)
+ /* device name is gone after device_unregister */
+ dev_dbg(&adapter->dev, "adapter [%s] unregistered\n", adapter->name);
+
+- /* free cdev */
+- cdev_del(&adapter->cdev);
+-
+ pm_runtime_disable(&adapter->dev);
+-
+ nr = adapter->nr;
+-
+ device_unregister(&adapter->dev);
+
+ /* free bus id */
+@@ -1436,6 +1517,18 @@ void peci_del_adapter(struct peci_adapter *adapter)
+ }
+ EXPORT_SYMBOL_GPL(peci_del_adapter);
+
++int peci_for_each_dev(void *data, int (*fn)(struct device *, void *))
++{
++ int ret;
++
++ mutex_lock(&core_lock);
++ ret = bus_for_each_dev(&peci_bus_type, NULL, data, fn);
++ mutex_unlock(&core_lock);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(peci_for_each_dev);
++
+ /**
+ * peci_register_driver - register a PECI driver
+ * @owner: owner module of the driver being registered
+@@ -1446,7 +1539,7 @@ EXPORT_SYMBOL_GPL(peci_del_adapter);
+ */
+ int peci_register_driver(struct module *owner, struct peci_driver *driver)
+ {
+- int rc;
++ int ret;
+
+ /* Can't register until after driver model init */
+ if (WARN_ON(!is_registered))
+@@ -1456,13 +1549,13 @@ int peci_register_driver(struct module *owner, struct peci_driver *driver)
+ driver->driver.owner = owner;
+ driver->driver.bus = &peci_bus_type;
+
+- /**
++ /*
+ * When registration returns, the driver core
+ * will have called probe() for all matching-but-unbound devices.
+ */
+- rc = driver_register(&driver->driver);
+- if (rc)
+- return rc;
++ ret = driver_register(&driver->driver);
++ if (ret)
++ return ret;
+
+ pr_debug("driver [%s] registered\n", driver->driver.name);
+
+@@ -1492,13 +1585,6 @@ static int __init peci_init(void)
+ return ret;
+ }
+
+- ret = alloc_chrdev_region(&peci_devt, 0, PECI_CDEV_MAX, "peci");
+- if (ret < 0) {
+- pr_err("peci: Failed to allocate chr dev region!\n");
+- bus_unregister(&peci_bus_type);
+- return ret;
+- }
+-
+ crc8_populate_msb(peci_crc8_table, PECI_CRC8_POLYNOMIAL);
+
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+@@ -1514,11 +1600,10 @@ static void __exit peci_exit(void)
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+ WARN_ON(of_reconfig_notifier_unregister(&peci_of_notifier));
+
+- unregister_chrdev_region(peci_devt, PECI_CDEV_MAX);
+ bus_unregister(&peci_bus_type);
+ }
+
+-postcore_initcall(peci_init);
++subsys_initcall(peci_init);
+ module_exit(peci_exit);
+
+ MODULE_AUTHOR("Jason M Biils <jason.m.bills@linux.intel.com>");
+diff --git a/drivers/peci/peci-dev.c b/drivers/peci/peci-dev.c
+new file mode 100644
+index 000000000000..ac9cba0fb429
+--- /dev/null
++++ b/drivers/peci/peci-dev.c
+@@ -0,0 +1,346 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2019 Intel Corporation
++
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/notifier.h>
++#include <linux/peci.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++
++/*
++ * A peci_dev represents an peci_adapter ... an PECI or SMBus master, not a
++ * slave (peci_client) with which messages will be exchanged. It's coupled
++ * with a character special file which is accessed by user mode drivers.
++ *
++ * The list of peci_dev structures is parallel to the peci_adapter lists
++ * maintained by the driver model, and is updated using bus notifications.
++ */
++struct peci_dev {
++ struct list_head list;
++ struct peci_adapter *adapter;
++ struct device *dev;
++ struct cdev cdev;
++};
++
++#define PECI_MINORS MINORMASK
++
++static dev_t peci_devt;
++static LIST_HEAD(peci_dev_list);
++static DEFINE_SPINLOCK(peci_dev_list_lock);
++
++static struct peci_dev *peci_dev_get_by_minor(uint index)
++{
++ struct peci_dev *peci_dev;
++
++ spin_lock(&peci_dev_list_lock);
++ list_for_each_entry(peci_dev, &peci_dev_list, list) {
++ if (peci_dev->adapter->nr == index)
++ goto found;
++ }
++ peci_dev = NULL;
++found:
++ spin_unlock(&peci_dev_list_lock);
++
++ return peci_dev;
++}
++
++static struct peci_dev *peci_dev_alloc(struct peci_adapter *adapter)
++{
++ struct peci_dev *peci_dev;
++
++ if (adapter->nr >= PECI_MINORS) {
++ printk(KERN_ERR "peci-dev: Out of device minors (%d)\n",
++ adapter->nr);
++ return ERR_PTR(-ENODEV);
++ }
++
++ peci_dev = kzalloc(sizeof(*peci_dev), GFP_KERNEL);
++ if (!peci_dev)
++ return ERR_PTR(-ENOMEM);
++ peci_dev->adapter = adapter;
++
++ spin_lock(&peci_dev_list_lock);
++ list_add_tail(&peci_dev->list, &peci_dev_list);
++ spin_unlock(&peci_dev_list_lock);
++
++ return peci_dev;
++}
++
++static void peci_dev_put(struct peci_dev *peci_dev)
++{
++ spin_lock(&peci_dev_list_lock);
++ list_del(&peci_dev->list);
++ spin_unlock(&peci_dev_list_lock);
++ kfree(peci_dev);
++}
++
++static ssize_t name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct peci_dev *peci_dev = peci_dev_get_by_minor(MINOR(dev->devt));
++
++ if (!peci_dev)
++ return -ENODEV;
++
++ return sprintf(buf, "%s\n", peci_dev->adapter->name);
++}
++static DEVICE_ATTR_RO(name);
++
++static struct attribute *peci_dev_attrs[] = {
++ &dev_attr_name.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(peci_dev);
++
++static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg)
++{
++ struct peci_dev *peci_dev = file->private_data;
++ void __user *umsg = (void __user *)arg;
++ struct peci_xfer_msg *xmsg = NULL;
++ struct peci_xfer_msg uxmsg;
++ enum peci_cmd cmd;
++ u8 *msg = NULL;
++ uint msg_len;
++ int ret;
++
++ cmd = _IOC_NR(iocmd);
++ msg_len = _IOC_SIZE(iocmd);
++
++ switch (cmd) {
++ case PECI_CMD_XFER:
++ if (msg_len != sizeof(struct peci_xfer_msg)) {
++ ret = -EFAULT;
++ break;
++ }
++
++ if (copy_from_user(&uxmsg, umsg, msg_len)) {
++ ret = -EFAULT;
++ break;
++ }
++
++ xmsg = peci_get_xfer_msg(uxmsg.tx_len, uxmsg.rx_len);
++ if (IS_ERR(xmsg)) {
++ ret = PTR_ERR(xmsg);
++ break;
++ }
++
++ if (uxmsg.tx_len &&
++ copy_from_user(xmsg->tx_buf, uxmsg.tx_buf, uxmsg.tx_len)) {
++ ret = -EFAULT;
++ break;
++ }
++
++ xmsg->addr = uxmsg.addr;
++ xmsg->tx_len = uxmsg.tx_len;
++ xmsg->rx_len = uxmsg.rx_len;
++
++ ret = peci_command(peci_dev->adapter, cmd, xmsg);
++ if (!ret && xmsg->rx_len &&
++ copy_to_user(uxmsg.rx_buf, xmsg->rx_buf, xmsg->rx_len))
++ ret = -EFAULT;
++
++ break;
++
++ default:
++ msg = memdup_user(umsg, msg_len);
++ if (IS_ERR(msg)) {
++ ret = PTR_ERR(msg);
++ break;
++ }
++
++ ret = peci_command(peci_dev->adapter, cmd, msg);
++ if ((!ret || ret == -ETIMEDOUT) &&
++ copy_to_user(umsg, msg, msg_len))
++ ret = -EFAULT;
++
++ break;
++ }
++
++ peci_put_xfer_msg(xmsg);
++ kfree(msg);
++
++ return (long)ret;
++}
++
++static int peci_dev_open(struct inode *inode, struct file *file)
++{
++ struct peci_adapter *adapter;
++ struct peci_dev *peci_dev;
++
++ peci_dev = peci_dev_get_by_minor(iminor(inode));
++ if (!peci_dev)
++ return -ENODEV;
++
++ adapter = peci_get_adapter(peci_dev->adapter->nr);
++ if (!adapter)
++ return -ENODEV;
++
++ file->private_data = peci_dev;
++
++ return 0;
++}
++
++static int peci_dev_release(struct inode *inode, struct file *file)
++{
++ struct peci_dev *peci_dev = file->private_data;
++
++ peci_put_adapter(peci_dev->adapter);
++ file->private_data = NULL;
++
++ return 0;
++}
++
++static const struct file_operations peci_dev_fops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = peci_dev_ioctl,
++ .open = peci_dev_open,
++ .release = peci_dev_release,
++ .llseek = no_llseek,
++};
++
++static struct class *peci_dev_class;
++
++static int peci_dev_attach_adapter(struct device *dev, void *dummy)
++{
++ struct peci_adapter *adapter;
++ struct peci_dev *peci_dev;
++ dev_t devt;
++ int ret;
++
++ if (dev->type != &peci_adapter_type)
++ return 0;
++
++ adapter = to_peci_adapter(dev);
++ peci_dev = peci_dev_alloc(adapter);
++ if (IS_ERR(peci_dev))
++ return PTR_ERR(peci_dev);
++
++ cdev_init(&peci_dev->cdev, &peci_dev_fops);
++ peci_dev->cdev.owner = THIS_MODULE;
++ devt = MKDEV(MAJOR(peci_devt), adapter->nr);
++
++ ret = cdev_add(&peci_dev->cdev, devt, 1);
++ if (ret)
++ goto err_put_dev;
++
++ /* register this peci device with the driver core */
++ peci_dev->dev = device_create(peci_dev_class, &adapter->dev, devt, NULL,
++ "peci-%d", adapter->nr);
++ if (IS_ERR(peci_dev->dev)) {
++ ret = PTR_ERR(peci_dev->dev);
++ goto err_del_cdev;
++ }
++
++ pr_info("peci-dev: adapter [%s] registered as minor %d\n",
++ adapter->name, adapter->nr);
++
++ return 0;
++
++err_del_cdev:
++ cdev_del(&peci_dev->cdev);
++err_put_dev:
++ peci_dev_put(peci_dev);
++
++ return ret;
++}
++
++static int peci_dev_detach_adapter(struct device *dev, void *dummy)
++{
++ struct peci_adapter *adapter;
++ struct peci_dev *peci_dev;
++ dev_t devt;
++
++ if (dev->type != &peci_adapter_type)
++ return 0;
++
++ adapter = to_peci_adapter(dev);
++ peci_dev = peci_dev_get_by_minor(adapter->nr);
++ if (!peci_dev)
++ return 0;
++
++ cdev_del(&peci_dev->cdev);
++ devt = peci_dev->dev->devt;
++ peci_dev_put(peci_dev);
++ device_destroy(peci_dev_class, devt);
++
++ pr_info("peci-dev: adapter [%s] unregistered\n", adapter->name);
++
++ return 0;
++}
++
++static int peci_dev_notifier_call(struct notifier_block *nb, ulong action,
++ void *data)
++{
++ struct device *dev = data;
++
++ switch (action) {
++ case BUS_NOTIFY_ADD_DEVICE:
++ return peci_dev_attach_adapter(dev, NULL);
++ case BUS_NOTIFY_DEL_DEVICE:
++ return peci_dev_detach_adapter(dev, NULL);
++ }
++
++ return 0;
++}
++
++static struct notifier_block peci_dev_notifier = {
++ .notifier_call = peci_dev_notifier_call,
++};
++
++static int __init peci_dev_init(void)
++{
++ int ret;
++
++ printk(KERN_INFO "peci /dev entries driver\n");
++
++ ret = alloc_chrdev_region(&peci_devt, 0, PECI_MINORS, "peci");
++ if (ret < 0) {
++ pr_err("peci: Failed to allocate chr dev region!\n");
++ bus_unregister(&peci_bus_type);
++ goto err;
++ }
++
++ peci_dev_class = class_create(THIS_MODULE, "peci-dev");
++ if (IS_ERR(peci_dev_class)) {
++ ret = PTR_ERR(peci_dev_class);
++ goto err_unreg_chrdev;
++ }
++ peci_dev_class->dev_groups = peci_dev_groups;
++
++ /* Keep track of adapters which will be added or removed later */
++ ret = bus_register_notifier(&peci_bus_type, &peci_dev_notifier);
++ if (ret)
++ goto err_destroy_class;
++
++ /* Bind to already existing adapters right away */
++ peci_for_each_dev(NULL, peci_dev_attach_adapter);
++
++ return 0;
++
++err_destroy_class:
++ class_destroy(peci_dev_class);
++err_unreg_chrdev:
++ unregister_chrdev_region(peci_devt, PECI_MINORS);
++err:
++ printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
++
++ return ret;
++}
++
++static void __exit peci_dev_exit(void)
++{
++ bus_unregister_notifier(&peci_bus_type, &peci_dev_notifier);
++ peci_for_each_dev(NULL, peci_dev_detach_adapter);
++ class_destroy(peci_dev_class);
++ unregister_chrdev_region(peci_devt, PECI_MINORS);
++}
++
++module_init(peci_dev_init);
++module_exit(peci_dev_exit);
++
++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
++MODULE_DESCRIPTION("PECI /dev entries driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/peci/peci-npcm.c b/drivers/peci/peci-npcm.c
+deleted file mode 100644
+index f632365b1416..000000000000
+--- a/drivers/peci/peci-npcm.c
++++ /dev/null
+@@ -1,410 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-// Copyright (c) 2019 Nuvoton Technology corporation.
+-
+-#include <linux/bitfield.h>
+-#include <linux/clk.h>
+-#include <linux/interrupt.h>
+-#include <linux/jiffies.h>
+-#include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/peci.h>
+-#include <linux/platform_device.h>
+-#include <linux/regmap.h>
+-#include <linux/mfd/syscon.h>
+-#include <linux/reset.h>
+-
+-/* NPCM7xx GCR module */
+-#define NPCM7XX_INTCR3_OFFSET 0x9C
+-#define NPCM7XX_INTCR3_PECIVSEL BIT(19)
+-
+-/* NPCM PECI Registers */
+-#define NPCM_PECI_CTL_STS 0x00
+-#define NPCM_PECI_RD_LENGTH 0x04
+-#define NPCM_PECI_ADDR 0x08
+-#define NPCM_PECI_CMD 0x0C
+-#define NPCM_PECI_CTL2 0x10
+-#define NPCM_PECI_WR_LENGTH 0x1C
+-#define NPCM_PECI_PDDR 0x2C
+-#define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4))
+-
+-#define NPCM_PECI_MAX_REG 0x200
+-
+-/* NPCM_PECI_CTL_STS - 0x00 : Control Register */
+-#define NPCM_PECI_CTRL_DONE_INT_EN BIT(6)
+-#define NPCM_PECI_CTRL_ABRT_ERR BIT(4)
+-#define NPCM_PECI_CTRL_CRC_ERR BIT(3)
+-#define NPCM_PECI_CTRL_DONE BIT(1)
+-#define NPCM_PECI_CTRL_START_BUSY BIT(0)
+-
+-/* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */
+-#define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0)
+-
+-/* NPCM_PECI_CMD - 0x10 : Command Register */
+-#define NPCM_PECI_CTL2_MASK GENMASK(7, 6)
+-
+-/* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */
+-#define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0)
+-
+-/* NPCM_PECI_PDDR - 0x2C : Command Register */
+-#define NPCM_PECI_PDDR_MASK GENMASK(4, 0)
+-
+-#define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \
+- NPCM_PECI_CTRL_CRC_ERR | \
+- NPCM_PECI_CTRL_DONE)
+-
+-#define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC 50000
+-#define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC 10000
+-#define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000
+-#define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000
+-#define NPCM_PECI_HOST_NEG_BIT_RATE_MAX 31
+-#define NPCM_PECI_HOST_NEG_BIT_RATE_MIN 7
+-#define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15
+-#define NPCM_PECI_PULL_DOWN_DEFAULT 0
+-#define NPCM_PECI_PULL_DOWN_MAX 2
+-
+-struct npcm_peci {
+- u32 cmd_timeout_ms;
+- u32 host_bit_rate;
+- struct completion xfer_complete;
+- struct regmap *gcr_regmap;
+- struct peci_adapter *adapter;
+- struct regmap *regmap;
+- u32 status;
+- spinlock_t lock; /* to sync completion status handling */
+- struct device *dev;
+- struct clk *clk;
+- int irq;
+-};
+-
+-static int npcm_peci_xfer_native(struct npcm_peci *priv,
+- struct peci_xfer_msg *msg)
+-{
+- long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms);
+- unsigned long flags;
+- unsigned int msg_rd;
+- u32 cmd_sts;
+- int i, rc;
+-
+- /* Check command sts and bus idle state */
+- rc = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts,
+- !(cmd_sts & NPCM_PECI_CTRL_START_BUSY),
+- NPCM_PECI_IDLE_CHECK_INTERVAL_USEC,
+- NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC);
+- if (rc)
+- return rc; /* -ETIMEDOUT */
+-
+- spin_lock_irqsave(&priv->lock, flags);
+- reinit_completion(&priv->xfer_complete);
+-
+- regmap_write(priv->regmap, NPCM_PECI_ADDR, msg->addr);
+- regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH,
+- NPCM_PECI_WR_LEN_MASK & msg->rx_len);
+- regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH,
+- NPCM_PECI_WR_LEN_MASK & msg->tx_len);
+-
+- if (msg->tx_len) {
+- regmap_write(priv->regmap, NPCM_PECI_CMD, msg->tx_buf[0]);
+-
+- for (i = 0; i < (msg->tx_len - 1); i++)
+- regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i),
+- msg->tx_buf[i + 1]);
+- }
+-
+- priv->status = 0;
+- regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS,
+- NPCM_PECI_CTRL_START_BUSY,
+- NPCM_PECI_CTRL_START_BUSY);
+-
+- spin_unlock_irqrestore(&priv->lock, flags);
+-
+- err = wait_for_completion_interruptible_timeout(&priv->xfer_complete,
+- timeout);
+-
+- spin_lock_irqsave(&priv->lock, flags);
+-
+- regmap_write(priv->regmap, NPCM_PECI_CMD, 0);
+-
+- if (err <= 0 || priv->status != NPCM_PECI_CTRL_DONE) {
+- if (err < 0) { /* -ERESTARTSYS */
+- rc = (int)err;
+- goto err_irqrestore;
+- } else if (err == 0) {
+- dev_dbg(priv->dev, "Timeout waiting for a response!\n");
+- rc = -ETIMEDOUT;
+- goto err_irqrestore;
+- }
+-
+- dev_dbg(priv->dev, "No valid response!\n");
+- rc = -EIO;
+- goto err_irqrestore;
+- }
+-
+- for (i = 0; i < msg->rx_len; i++) {
+- regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd);
+- msg->rx_buf[i] = (u8)msg_rd;
+- }
+-
+-err_irqrestore:
+- spin_unlock_irqrestore(&priv->lock, flags);
+- return rc;
+-}
+-
+-static irqreturn_t npcm_peci_irq_handler(int irq, void *arg)
+-{
+- struct npcm_peci *priv = arg;
+- u32 status_ack = 0;
+- u32 status;
+-
+- spin_lock(&priv->lock);
+- regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status);
+- priv->status |= (status & NPCM_PECI_INT_MASK);
+-
+- if (status & NPCM_PECI_CTRL_CRC_ERR) {
+- dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n");
+- status_ack |= NPCM_PECI_CTRL_CRC_ERR;
+- }
+-
+- if (status & NPCM_PECI_CTRL_ABRT_ERR) {
+- dev_dbg(priv->dev, "NPCM_PECI_CTRL_ABRT_ERR\n");
+- status_ack |= NPCM_PECI_CTRL_ABRT_ERR;
+- }
+-
+- /*
+- * All commands should be ended up with a NPCM_PECI_CTRL_DONE
+- * bit set even in an error case.
+- */
+- if (status & NPCM_PECI_CTRL_DONE) {
+- dev_dbg(priv->dev, "NPCM_PECI_CTRL_DONE\n");
+- status_ack |= NPCM_PECI_CTRL_DONE;
+- complete(&priv->xfer_complete);
+- }
+-
+- regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS,
+- NPCM_PECI_INT_MASK, status_ack);
+-
+- spin_unlock(&priv->lock);
+- return IRQ_HANDLED;
+-}
+-
+-static int npcm_peci_init_ctrl(struct npcm_peci *priv)
+-{
+- u32 cmd_sts, host_neg_bit_rate = 0, pull_down = 0;
+- int ret;
+- bool volt;
+-
+- priv->clk = devm_clk_get(priv->dev, NULL);
+- if (IS_ERR(priv->clk)) {
+- dev_err(priv->dev, "Failed to get clk source.\n");
+- return PTR_ERR(priv->clk);
+- }
+-
+- ret = clk_prepare_enable(priv->clk);
+- if (ret) {
+- dev_err(priv->dev, "Failed to enable clock.\n");
+- return ret;
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms",
+- &priv->cmd_timeout_ms);
+- if (ret || priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX ||
+- priv->cmd_timeout_ms == 0) {
+- if (ret)
+- dev_warn(priv->dev,
+- "cmd-timeout-ms not found, use default : %u\n",
+- NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT);
+- else
+- dev_warn(priv->dev,
+- "Invalid cmd-timeout-ms : %u. Use default : %u\n",
+- priv->cmd_timeout_ms,
+- NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT);
+-
+- priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT;
+- }
+-
+- if (of_device_is_compatible(priv->dev->of_node,
+- "nuvoton,npcm750-peci")) {
+- priv->gcr_regmap = syscon_regmap_lookup_by_compatible
+- ("nuvoton,npcm750-gcr");
+- if (!IS_ERR(priv->gcr_regmap)) {
+- volt = of_property_read_bool(priv->dev->of_node,
+- "high-volt-range");
+- if (volt)
+- regmap_update_bits(priv->gcr_regmap,
+- NPCM7XX_INTCR3_OFFSET,
+- NPCM7XX_INTCR3_PECIVSEL,
+- NPCM7XX_INTCR3_PECIVSEL);
+- else
+- regmap_update_bits(priv->gcr_regmap,
+- NPCM7XX_INTCR3_OFFSET,
+- NPCM7XX_INTCR3_PECIVSEL, 0);
+- }
+- }
+-
+- ret = of_property_read_u32(priv->dev->of_node, "pull-down",
+- &pull_down);
+- if (ret || pull_down > NPCM_PECI_PULL_DOWN_MAX) {
+- if (ret)
+- dev_warn(priv->dev,
+- "pull-down not found, use default : %u\n",
+- NPCM_PECI_PULL_DOWN_DEFAULT);
+- else
+- dev_warn(priv->dev,
+- "Invalid pull-down : %u. Use default : %u\n",
+- pull_down,
+- NPCM_PECI_PULL_DOWN_DEFAULT);
+- pull_down = NPCM_PECI_PULL_DOWN_DEFAULT;
+- }
+-
+- regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK,
+- pull_down << 6);
+-
+- ret = of_property_read_u32(priv->dev->of_node, "host-neg-bit-rate",
+- &host_neg_bit_rate);
+- if (ret || host_neg_bit_rate > NPCM_PECI_HOST_NEG_BIT_RATE_MAX ||
+- host_neg_bit_rate < NPCM_PECI_HOST_NEG_BIT_RATE_MIN) {
+- if (ret)
+- dev_warn(priv->dev,
+- "host-neg-bit-rate not found, use default : %u\n",
+- NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT);
+- else
+- dev_warn(priv->dev,
+- "Invalid host-neg-bit-rate : %u. Use default : %u\n",
+- host_neg_bit_rate,
+- NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT);
+- host_neg_bit_rate = NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT;
+- }
+-
+- regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK,
+- host_neg_bit_rate);
+-
+- priv->host_bit_rate = clk_get_rate(priv->clk) /
+- (4 * (host_neg_bit_rate + 1));
+-
+- ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts,
+- !(cmd_sts & NPCM_PECI_CTRL_START_BUSY),
+- NPCM_PECI_IDLE_CHECK_INTERVAL_USEC,
+- NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC);
+- if (ret)
+- return ret; /* -ETIMEDOUT */
+-
+- /* PECI interrupt enable */
+- regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS,
+- NPCM_PECI_CTRL_DONE_INT_EN,
+- NPCM_PECI_CTRL_DONE_INT_EN);
+-
+- return 0;
+-}
+-
+-static const struct regmap_config npcm_peci_regmap_config = {
+- .reg_bits = 8,
+- .val_bits = 8,
+- .max_register = NPCM_PECI_MAX_REG,
+- .fast_io = true,
+-};
+-
+-static int npcm_peci_xfer(struct peci_adapter *adapter,
+- struct peci_xfer_msg *msg)
+-{
+- struct npcm_peci *priv = peci_get_adapdata(adapter);
+-
+- return npcm_peci_xfer_native(priv, msg);
+-}
+-
+-static int npcm_peci_probe(struct platform_device *pdev)
+-{
+- struct peci_adapter *adapter;
+- struct npcm_peci *priv;
+- struct resource *res;
+- void __iomem *base;
+- int ret;
+-
+- adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv));
+- if (!adapter)
+- return -ENOMEM;
+-
+- priv = peci_get_adapdata(adapter);
+- priv->adapter = adapter;
+- priv->dev = &pdev->dev;
+- dev_set_drvdata(&pdev->dev, priv);
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- base = devm_ioremap_resource(&pdev->dev, res);
+- if (IS_ERR(base)) {
+- ret = PTR_ERR(base);
+- goto err_put_adapter_dev;
+- }
+-
+- priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+- &npcm_peci_regmap_config);
+- if (IS_ERR(priv->regmap)) {
+- ret = PTR_ERR(priv->regmap);
+- goto err_put_adapter_dev;
+- }
+-
+- priv->irq = platform_get_irq(pdev, 0);
+- if (!priv->irq) {
+- ret = -ENODEV;
+- goto err_put_adapter_dev;
+- }
+-
+- ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler,
+- 0, "peci-npcm-irq", priv);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- init_completion(&priv->xfer_complete);
+- spin_lock_init(&priv->lock);
+-
+- priv->adapter->owner = THIS_MODULE;
+- priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev));
+- strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name));
+- priv->adapter->xfer = npcm_peci_xfer;
+-
+- ret = npcm_peci_init_ctrl(priv);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- ret = peci_add_adapter(priv->adapter);
+- if (ret)
+- goto err_put_adapter_dev;
+-
+- dev_info(&pdev->dev, "peci bus %d registered, host negotiation bit rate %dHz",
+- priv->adapter->nr, priv->host_bit_rate);
+-
+- return 0;
+-
+-err_put_adapter_dev:
+- put_device(&adapter->dev);
+- return ret;
+-}
+-
+-static int npcm_peci_remove(struct platform_device *pdev)
+-{
+- struct npcm_peci *priv = dev_get_drvdata(&pdev->dev);
+-
+- clk_disable_unprepare(priv->clk);
+- peci_del_adapter(priv->adapter);
+- of_node_put(priv->adapter->dev.of_node);
+-
+- return 0;
+-}
+-
+-static const struct of_device_id npcm_peci_of_table[] = {
+- { .compatible = "nuvoton,npcm750-peci", },
+- { }
+-};
+-MODULE_DEVICE_TABLE(of, npcm_peci_of_table);
+-
+-static struct platform_driver npcm_peci_driver = {
+- .probe = npcm_peci_probe,
+- .remove = npcm_peci_remove,
+- .driver = {
+- .name = "peci-npcm",
+- .of_match_table = of_match_ptr(npcm_peci_of_table),
+- },
+-};
+-module_platform_driver(npcm_peci_driver);
+-
+-MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
+-MODULE_DESCRIPTION("NPCM Platform Environment Control Interface (PECI) driver");
+-MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/mfd/intel-peci-client.h b/include/linux/mfd/intel-peci-client.h
+index 8f6d823a59cd..7b62a02e46ee 100644
+--- a/include/linux/mfd/intel-peci-client.h
++++ b/include/linux/mfd/intel-peci-client.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018 Intel Corporation */
++/* Copyright (c) 2018-2019 Intel Corporation */
+
+ #ifndef __LINUX_MFD_INTEL_PECI_CLIENT_H
+ #define __LINUX_MFD_INTEL_PECI_CLIENT_H
+@@ -9,14 +9,15 @@
+ #if IS_ENABLED(CONFIG_X86)
+ #include <asm/intel-family.h>
+ #else
+-/**
++/*
+ * Architectures other than x86 cannot include the header file so define these
+ * at here. These are needed for detecting type of client x86 CPUs behind a PECI
+ * connection.
+ */
+-#define INTEL_FAM6_HASWELL_X 0x3F
+-#define INTEL_FAM6_BROADWELL_X 0x4F
+-#define INTEL_FAM6_SKYLAKE_X 0x55
++#define INTEL_FAM6_HASWELL_X 0x3F
++#define INTEL_FAM6_BROADWELL_X 0x4F
++#define INTEL_FAM6_BROADWELL_XEON_D 0x56
++#define INTEL_FAM6_SKYLAKE_X 0x55
+ #endif
+
+ #define CORE_MAX_ON_HSX 18 /* Max number of cores on Haswell */
+@@ -27,6 +28,10 @@
+ #define CHAN_RANK_MAX_ON_BDX 4 /* Max number of channel ranks on Broadwell */
+ #define DIMM_IDX_MAX_ON_BDX 3 /* Max DIMM index per channel on Broadwell */
+
++#define CORE_MAX_ON_XD 16 /* Max number of cores on Xeon D */
++#define CHAN_RANK_MAX_ON_XD 2 /* Max number of channel ranks on Xeon D */
++#define DIMM_IDX_MAX_ON_XD 2 /* Max DIMM index per channel on Xeon D */
++
+ #define CORE_MAX_ON_SKX 28 /* Max number of cores on Skylake */
+ #define CHAN_RANK_MAX_ON_SKX 6 /* Max number of channel ranks on Skylake */
+ #define DIMM_IDX_MAX_ON_SKX 2 /* Max DIMM index per channel on Skylake */
+@@ -58,7 +63,6 @@ struct cpu_gen_info {
+ /**
+ * struct peci_client_manager - PECI client manager information
+ * @client; pointer to the PECI client
+- * @dev: pointer to the struct device
+ * @name: PECI client manager name
+ * @gen_info: CPU generation info of the detected CPU
+ *
+@@ -67,7 +71,6 @@ struct cpu_gen_info {
+ */
+ struct peci_client_manager {
+ struct peci_client *client;
+- struct device *dev;
+ char name[PECI_NAME_SIZE];
+ const struct cpu_gen_info *gen_info;
+ };
+@@ -93,18 +96,23 @@ peci_client_read_package_config(struct peci_client_manager *priv,
+ u8 index, u16 param, u8 *data)
+ {
+ struct peci_rd_pkg_cfg_msg msg;
+- int rc;
++ int ret;
+
+ msg.addr = priv->client->addr;
+ msg.index = index;
+ msg.param = param;
+ msg.rx_len = 4;
+
+- rc = peci_command(priv->client->adapter, PECI_CMD_RD_PKG_CFG, &msg);
+- if (!rc)
+- memcpy(data, msg.pkg_config, 4);
++ ret = peci_command(priv->client->adapter, PECI_CMD_RD_PKG_CFG, &msg);
++ if (ret)
++ return ret;
++
++ if (msg.cc != PECI_DEV_CC_SUCCESS)
++ return -EAGAIN;
++
++ memcpy(data, msg.pkg_config, 4);
+
+- return rc;
++ return 0;
+ }
+
+ #endif /* __LINUX_MFD_INTEL_PECI_CLIENT_H */
+diff --git a/include/linux/peci.h b/include/linux/peci.h
+index d0e47d45d1d0..6fc424dc2a73 100644
+--- a/include/linux/peci.h
++++ b/include/linux/peci.h
+@@ -1,19 +1,18 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018 Intel Corporation */
++/* Copyright (c) 2018-2019 Intel Corporation */
+
+ #ifndef __LINUX_PECI_H
+ #define __LINUX_PECI_H
+
+-#include <linux/cdev.h>
+ #include <linux/device.h>
++#include <linux/mutex.h>
+ #include <linux/peci-ioctl.h>
+-#include <linux/rtmutex.h>
+
+ #define PECI_NAME_SIZE 32
+
+ struct peci_board_info {
+ char type[PECI_NAME_SIZE];
+- unsigned short addr; /* CPU client address */
++ u8 addr; /* CPU client address */
+ struct device_node *of_node;
+ };
+
+@@ -22,29 +21,29 @@ struct peci_board_info {
+ * @owner: owner module of the PECI adpater
+ * @bus_lock: mutex for exclusion of multiple callers
+ * @dev: device interface to this driver
+- * @cdev: character device object to create character device
+ * @nr: the bus number to map
+ * @name: name of the adapter
+ * @userspace_clients_lock: mutex for exclusion of clients handling
+ * @userspace_clients: list of registered clients
+ * @xfer: low-level transfer function pointer of the adapter
+ * @cmd_mask: mask for supportable PECI commands
++ * @use_dma: flag for indicating that adapter uses DMA
+ *
+ * Each PECI adapter can communicate with one or more PECI client children.
+ * These make a small bus, sharing a single wired PECI connection.
+ */
+ struct peci_adapter {
+ struct module *owner;
+- struct rt_mutex bus_lock;
++ struct mutex bus_lock;
+ struct device dev;
+- struct cdev cdev;
+ int nr;
+ char name[PECI_NAME_SIZE];
+ struct mutex userspace_clients_lock; /* clients list mutex */
+ struct list_head userspace_clients;
+ int (*xfer)(struct peci_adapter *adapter,
+ struct peci_xfer_msg *msg);
+- uint cmd_mask;
++ u32 cmd_mask;
++ bool use_dma;
+ };
+
+ static inline struct peci_adapter *to_peci_adapter(void *d)
+@@ -87,8 +86,8 @@ static inline struct peci_client *to_peci_client(void *d)
+ }
+
+ struct peci_device_id {
+- char name[PECI_NAME_SIZE];
+- unsigned long driver_data; /* Data private to the driver */
++ char name[PECI_NAME_SIZE];
++ ulong driver_data; /* Data private to the driver */
+ };
+
+ /**
+@@ -129,13 +128,22 @@ static inline struct peci_driver *to_peci_driver(void *d)
+ /* use a define to avoid include chaining to get THIS_MODULE */
+ #define peci_add_driver(driver) peci_register_driver(THIS_MODULE, driver)
+
++extern struct bus_type peci_bus_type;
++extern struct device_type peci_adapter_type;
++extern struct device_type peci_client_type;
++
+ int peci_register_driver(struct module *owner, struct peci_driver *drv);
+ void peci_del_driver(struct peci_driver *driver);
+ struct peci_client *peci_verify_client(struct device *dev);
+-struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size);
++struct peci_adapter *peci_alloc_adapter(struct device *dev, uint size);
++struct peci_adapter *peci_get_adapter(int nr);
++void peci_put_adapter(struct peci_adapter *adapter);
+ int peci_add_adapter(struct peci_adapter *adapter);
+ void peci_del_adapter(struct peci_adapter *adapter);
+ struct peci_adapter *peci_verify_adapter(struct device *dev);
++int peci_for_each_dev(void *data, int (*fn)(struct device *, void *));
++struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len);
++void peci_put_xfer_msg(struct peci_xfer_msg *msg);
+ int peci_command(struct peci_adapter *adpater, enum peci_cmd cmd, void *vmsg);
+ int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id);
+
+diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
+index a6dae71cbff5..253fb42e38b7 100644
+--- a/include/uapi/linux/peci-ioctl.h
++++ b/include/uapi/linux/peci-ioctl.h
+@@ -1,5 +1,5 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* Copyright (c) 2018 Intel Corporation */
++/* Copyright (c) 2018-2019 Intel Corporation */
+
+ #ifndef __PECI_IOCTL_H
+ #define __PECI_IOCTL_H
+@@ -7,136 +7,35 @@
+ #include <linux/ioctl.h>
+ #include <linux/types.h>
+
+-/* Base Address of 48d */
+-#define PECI_BASE_ADDR 0x30 /* The PECI client's default address of 0x30 */
+-#define PECI_OFFSET_MAX 8 /* Max numver of CPU clients */
+-
+-/* PCI Access */
+-#define MAX_PCI_READ_LEN 24 /* Number of bytes of the PCI Space read */
+-
+-#define PCI_BUS0_CPU0 0x00
+-#define PCI_BUS0_CPU1 0x80
+-#define PCI_CPUBUSNO_BUS 0x00
+-#define PCI_CPUBUSNO_DEV 0x08
+-#define PCI_CPUBUSNO_FUNC 0x02
+-#define PCI_CPUBUSNO 0xcc
+-#define PCI_CPUBUSNO_1 0xd0
+-#define PCI_CPUBUSNO_VALID 0xd4
+-
+-/* Package Identifier Read Parameter Value */
+-#define PKG_ID_CPU_ID 0x0000 /* CPUID Info */
+-#define PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */
+-#define PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */
+-#define PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */
+-#define PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */
+-#define PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */
+-
+-/* RdPkgConfig Index */
+-#define MBX_INDEX_CPU_ID 0 /* Package Identifier Read */
+-#define MBX_INDEX_VR_DEBUG 1 /* VR Debug */
+-#define MBX_INDEX_PKG_TEMP_READ 2 /* Package Temperature Read */
+-#define MBX_INDEX_ENERGY_COUNTER 3 /* Energy counter */
+-#define MBX_INDEX_ENERGY_STATUS 4 /* DDR Energy Status */
+-#define MBX_INDEX_WAKE_MODE_BIT 5 /* "Wake on PECI" Mode bit */
+-#define MBX_INDEX_EPI 6 /* Efficient Performance Indication */
+-#define MBX_INDEX_PKG_RAPL_PERF 8 /* Pkg RAPL Performance Status Read */
+-#define MBX_INDEX_PER_CORE_DTS_TEMP 9 /* Per Core DTS Temperature Read */
+-#define MBX_INDEX_DTS_MARGIN 10 /* DTS thermal margin */
+-#define MBX_INDEX_SKT_PWR_THRTL_DUR 11 /* Socket Power Throttled Duration */
+-#define MBX_INDEX_CFG_TDP_CONTROL 12 /* TDP Config Control */
+-#define MBX_INDEX_CFG_TDP_LEVELS 13 /* TDP Config Levels */
+-#define MBX_INDEX_DDR_DIMM_TEMP 14 /* DDR DIMM Temperature */
+-#define MBX_INDEX_CFG_ICCMAX 15 /* Configurable ICCMAX */
+-#define MBX_INDEX_TEMP_TARGET 16 /* Temperature Target Read */
+-#define MBX_INDEX_CURR_CFG_LIMIT 17 /* Current Config Limit */
+-#define MBX_INDEX_DIMM_TEMP_READ 20 /* Package Thermal Status Read */
+-#define MBX_INDEX_DRAM_IMC_TMP_READ 22 /* DRAM IMC Temperature Read */
+-#define MBX_INDEX_DDR_CH_THERM_STAT 23 /* DDR Channel Thermal Status */
+-#define MBX_INDEX_PKG_POWER_LIMIT1 26 /* Package Power Limit1 */
+-#define MBX_INDEX_PKG_POWER_LIMIT2 27 /* Package Power Limit2 */
+-#define MBX_INDEX_TDP 28 /* Thermal design power minimum */
+-#define MBX_INDEX_TDP_HIGH 29 /* Thermal design power maximum */
+-#define MBX_INDEX_TDP_UNITS 30 /* Units for power/energy registers */
+-#define MBX_INDEX_RUN_TIME 31 /* Accumulated Run Time */
+-#define MBX_INDEX_CONSTRAINED_TIME 32 /* Thermally Constrained Time Read */
+-#define MBX_INDEX_TURBO_RATIO 33 /* Turbo Activation Ratio */
+-#define MBX_INDEX_DDR_RAPL_PL1 34 /* DDR RAPL PL1 */
+-#define MBX_INDEX_DDR_PWR_INFO_HIGH 35 /* DRAM Power Info Read (high) */
+-#define MBX_INDEX_DDR_PWR_INFO_LOW 36 /* DRAM Power Info Read (low) */
+-#define MBX_INDEX_DDR_RAPL_PL2 37 /* DDR RAPL PL2 */
+-#define MBX_INDEX_DDR_RAPL_STATUS 38 /* DDR RAPL Performance Status */
+-#define MBX_INDEX_DDR_HOT_ABSOLUTE 43 /* DDR Hottest Dimm Absolute Temp */
+-#define MBX_INDEX_DDR_HOT_RELATIVE 44 /* DDR Hottest Dimm Relative Temp */
+-#define MBX_INDEX_DDR_THROTTLE_TIME 45 /* DDR Throttle Time */
+-#define MBX_INDEX_DDR_THERM_STATUS 46 /* DDR Thermal Status */
+-#define MBX_INDEX_TIME_AVG_TEMP 47 /* Package time-averaged temperature */
+-#define MBX_INDEX_TURBO_RATIO_LIMIT 49 /* Turbo Ratio Limit Read */
+-#define MBX_INDEX_HWP_AUTO_OOB 53 /* HWP Autonomous Out-of-band */
+-#define MBX_INDEX_DDR_WARM_BUDGET 55 /* DDR Warm Power Budget */
+-#define MBX_INDEX_DDR_HOT_BUDGET 56 /* DDR Hot Power Budget */
+-#define MBX_INDEX_PKG_PSYS_PWR_LIM3 57 /* Package/Psys Power Limit3 */
+-#define MBX_INDEX_PKG_PSYS_PWR_LIM1 58 /* Package/Psys Power Limit1 */
+-#define MBX_INDEX_PKG_PSYS_PWR_LIM2 59 /* Package/Psys Power Limit2 */
+-#define MBX_INDEX_PKG_PSYS_PWR_LIM4 60 /* Package/Psys Power Limit4 */
+-#define MBX_INDEX_PERF_LIMIT_REASON 65 /* Performance Limit Reasons */
+-
+-/* WrPkgConfig Index */
+-#define MBX_INDEX_DIMM_AMBIENT 19
+-#define MBX_INDEX_DIMM_TEMP 24
++/* The PECI client's default address of 0x30 */
++#define PECI_BASE_ADDR 0x30
++
++/* Max number of CPU clients */
++#define PECI_OFFSET_MAX 8
++
++/* PECI read/write data buffer size max */
++#define PECI_BUFFER_SIZE 255
+
+ /* Device Specific Completion Code (CC) Definition */
+-#define DEV_PECI_CC_SUCCESS 0x40
+-#define DEV_PECI_CC_TIMEOUT 0x80
+-#define DEV_PECI_CC_OUT_OF_RESOURCE 0x81
+-#define DEV_PECI_CC_UNAVAIL_RESOURCE 0x82
+-#define DEV_PECI_CC_INVALID_REQ 0x90
++#define PECI_DEV_CC_SUCCESS 0x40
++#define PECI_DEV_CC_NEED_RETRY 0x80
++#define PECI_DEV_CC_OUT_OF_RESOURCE 0x81
++#define PECI_DEV_CC_UNAVAIL_RESOURCE 0x82
++#define PECI_DEV_CC_INVALID_REQ 0x90
++#define PECI_DEV_CC_MCA_ERROR 0x91
++#define PECI_DEV_CC_CATASTROPHIC_MCA_ERROR 0x93
++#define PECI_DEV_CC_FATAL_MCA_DETECTED 0x94
++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB 0x98
++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB_IERR 0x9B
++#define PECI_DEV_CC_PARITY_ERROR_ON_GPSB_OR_PMSB_MCA 0x9C
+
+ /* Completion Code mask to check retry needs */
+-#define DEV_PECI_CC_RETRY_CHECK_MASK 0xf0
+-#define DEV_PECI_CC_NEED_RETRY 0x80
++#define PECI_DEV_CC_RETRY_CHECK_MASK 0xf0
+
+ /* Skylake EDS says to retry for 250ms */
+-#define DEV_PECI_RETRY_TIME_MS 250
+-#define DEV_PECI_RETRY_INTERVAL_USEC 10000
+-#define DEV_PECI_RETRY_BIT 0x01
+-
+-#define GET_TEMP_WR_LEN 1
+-#define GET_TEMP_RD_LEN 2
+-#define GET_TEMP_PECI_CMD 0x01
+-
+-#define GET_DIB_WR_LEN 1
+-#define GET_DIB_RD_LEN 8
+-#define GET_DIB_PECI_CMD 0xf7
+-
+-#define RDPKGCFG_WRITE_LEN 5
+-#define RDPKGCFG_READ_LEN_BASE 1
+-#define RDPKGCFG_PECI_CMD 0xa1
+-
+-#define WRPKGCFG_WRITE_LEN_BASE 6
+-#define WRPKGCFG_READ_LEN 1
+-#define WRPKGCFG_PECI_CMD 0xa5
+-
+-#define RDIAMSR_WRITE_LEN 5
+-#define RDIAMSR_READ_LEN 9
+-#define RDIAMSR_PECI_CMD 0xb1
+-
+-#define WRIAMSR_PECI_CMD 0xb5
+-
+-#define RDPCICFG_WRITE_LEN 6
+-#define RDPCICFG_READ_LEN 5
+-#define RDPCICFG_PECI_CMD 0x61
+-
+-#define WRPCICFG_PECI_CMD 0x65
+-
+-#define RDPCICFGLOCAL_WRITE_LEN 5
+-#define RDPCICFGLOCAL_READ_LEN_BASE 1
+-#define RDPCICFGLOCAL_PECI_CMD 0xe1
+-
+-#define WRPCICFGLOCAL_WRITE_LEN_BASE 6
+-#define WRPCICFGLOCAL_READ_LEN 1
+-#define WRPCICFGLOCAL_PECI_CMD 0xe5
+-
+-#define PECI_BUFFER_SIZE 32
++#define PECI_DEV_RETRY_TIME_MS 250
++#define PECI_DEV_RETRY_INTERVAL_USEC 10000
++#define PECI_DEV_RETRY_BIT 0x01
+
+ /**
+ * enum peci_cmd - PECI client commands
+@@ -186,11 +85,12 @@ enum peci_cmd {
+ * raw PECI transfer
+ */
+ struct peci_xfer_msg {
+- __u8 addr;
+- __u8 tx_len;
+- __u8 rx_len;
+- __u8 tx_buf[PECI_BUFFER_SIZE];
+- __u8 rx_buf[PECI_BUFFER_SIZE];
++ __u8 addr;
++ __u8 tx_len;
++ __u8 rx_len;
++ __u8 padding;
++ __u8 *tx_buf;
++ __u8 *rx_buf;
+ } __attribute__((__packed__));
+
+ /**
+@@ -202,7 +102,8 @@ struct peci_xfer_msg {
+ * powered-off, etc.
+ */
+ struct peci_ping_msg {
+- __u8 addr;
++ __u8 addr;
++ __u8 padding[3];
+ } __attribute__((__packed__));
+
+ /**
+@@ -216,8 +117,13 @@ struct peci_ping_msg {
+ * command.
+ */
+ struct peci_get_dib_msg {
+- __u8 addr;
+- __u64 dib;
++#define PECI_GET_DIB_WR_LEN 1
++#define PECI_GET_DIB_RD_LEN 8
++#define PECI_GET_DIB_CMD 0xf7
++
++ __u8 addr;
++ __u8 padding[3];
++ __u64 dib;
+ } __attribute__((__packed__));
+
+ /**
+@@ -232,8 +138,13 @@ struct peci_get_dib_msg {
+ * below the maximum processor junction temperature.
+ */
+ struct peci_get_temp_msg {
+- __u8 addr;
+- __s16 temp_raw;
++#define PECI_GET_TEMP_WR_LEN 1
++#define PECI_GET_TEMP_RD_LEN 2
++#define PECI_GET_TEMP_CMD 0x01
++
++ __u8 addr;
++ __u8 padding;
++ __s16 temp_raw;
+ } __attribute__((__packed__));
+
+ /**
+@@ -242,6 +153,7 @@ struct peci_get_temp_msg {
+ * @index: encoding index for the requested service
+ * @param: specific data being requested
+ * @rx_len: number of data to be read in bytes
++ * @cc: completion code
+ * @pkg_config: package config data to be read
+ *
+ * The RdPkgConfig() command provides read access to the Package Configuration
+@@ -251,11 +163,73 @@ struct peci_get_temp_msg {
+ * DIMM temperatures and so on.
+ */
+ struct peci_rd_pkg_cfg_msg {
+- __u8 addr;
+- __u8 index;
+- __u16 param;
+- __u8 rx_len;
+- __u8 pkg_config[4];
++#define PECI_RDPKGCFG_WRITE_LEN 5
++#define PECI_RDPKGCFG_READ_LEN_BASE 1
++#define PECI_RDPKGCFG_CMD 0xa1
++
++ __u8 addr;
++ __u8 index;
++#define PECI_MBX_INDEX_CPU_ID 0 /* Package Identifier Read */
++#define PECI_MBX_INDEX_VR_DEBUG 1 /* VR Debug */
++#define PECI_MBX_INDEX_PKG_TEMP_READ 2 /* Package Temperature Read */
++#define PECI_MBX_INDEX_ENERGY_COUNTER 3 /* Energy counter */
++#define PECI_MBX_INDEX_ENERGY_STATUS 4 /* DDR Energy Status */
++#define PECI_MBX_INDEX_WAKE_MODE_BIT 5 /* "Wake on PECI" Mode bit */
++#define PECI_MBX_INDEX_EPI 6 /* Efficient Performance Indication */
++#define PECI_MBX_INDEX_PKG_RAPL_PERF 8 /* Pkg RAPL Performance Status Read */
++#define PECI_MBX_INDEX_PER_CORE_DTS_TEMP 9 /* Per Core DTS Temperature Read */
++#define PECI_MBX_INDEX_DTS_MARGIN 10 /* DTS thermal margin */
++#define PECI_MBX_INDEX_SKT_PWR_THRTL_DUR 11 /* Socket Power Throttled Duration */
++#define PECI_MBX_INDEX_CFG_TDP_CONTROL 12 /* TDP Config Control */
++#define PECI_MBX_INDEX_CFG_TDP_LEVELS 13 /* TDP Config Levels */
++#define PECI_MBX_INDEX_DDR_DIMM_TEMP 14 /* DDR DIMM Temperature */
++#define PECI_MBX_INDEX_CFG_ICCMAX 15 /* Configurable ICCMAX */
++#define PECI_MBX_INDEX_TEMP_TARGET 16 /* Temperature Target Read */
++#define PECI_MBX_INDEX_CURR_CFG_LIMIT 17 /* Current Config Limit */
++#define PECI_MBX_INDEX_DIMM_TEMP_READ 20 /* Package Thermal Status Read */
++#define PECI_MBX_INDEX_DRAM_IMC_TMP_READ 22 /* DRAM IMC Temperature Read */
++#define PECI_MBX_INDEX_DDR_CH_THERM_STAT 23 /* DDR Channel Thermal Status */
++#define PECI_MBX_INDEX_PKG_POWER_LIMIT1 26 /* Package Power Limit1 */
++#define PECI_MBX_INDEX_PKG_POWER_LIMIT2 27 /* Package Power Limit2 */
++#define PECI_MBX_INDEX_TDP 28 /* Thermal design power minimum */
++#define PECI_MBX_INDEX_TDP_HIGH 29 /* Thermal design power maximum */
++#define PECI_MBX_INDEX_TDP_UNITS 30 /* Units for power/energy registers */
++#define PECI_MBX_INDEX_RUN_TIME 31 /* Accumulated Run Time */
++#define PECI_MBX_INDEX_CONSTRAINED_TIME 32 /* Thermally Constrained Time Read */
++#define PECI_MBX_INDEX_TURBO_RATIO 33 /* Turbo Activation Ratio */
++#define PECI_MBX_INDEX_DDR_RAPL_PL1 34 /* DDR RAPL PL1 */
++#define PECI_MBX_INDEX_DDR_PWR_INFO_HIGH 35 /* DRAM Power Info Read (high) */
++#define PECI_MBX_INDEX_DDR_PWR_INFO_LOW 36 /* DRAM Power Info Read (low) */
++#define PECI_MBX_INDEX_DDR_RAPL_PL2 37 /* DDR RAPL PL2 */
++#define PECI_MBX_INDEX_DDR_RAPL_STATUS 38 /* DDR RAPL Performance Status */
++#define PECI_MBX_INDEX_DDR_HOT_ABSOLUTE 43 /* DDR Hottest Dimm Absolute Temp */
++#define PECI_MBX_INDEX_DDR_HOT_RELATIVE 44 /* DDR Hottest Dimm Relative Temp */
++#define PECI_MBX_INDEX_DDR_THROTTLE_TIME 45 /* DDR Throttle Time */
++#define PECI_MBX_INDEX_DDR_THERM_STATUS 46 /* DDR Thermal Status */
++#define PECI_MBX_INDEX_TIME_AVG_TEMP 47 /* Package time-averaged temperature */
++#define PECI_MBX_INDEX_TURBO_RATIO_LIMIT 49 /* Turbo Ratio Limit Read */
++#define PECI_MBX_INDEX_HWP_AUTO_OOB 53 /* HWP Autonomous Out-of-band */
++#define PECI_MBX_INDEX_DDR_WARM_BUDGET 55 /* DDR Warm Power Budget */
++#define PECI_MBX_INDEX_DDR_HOT_BUDGET 56 /* DDR Hot Power Budget */
++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM3 57 /* Package/Psys Power Limit3 */
++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM1 58 /* Package/Psys Power Limit1 */
++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM2 59 /* Package/Psys Power Limit2 */
++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM4 60 /* Package/Psys Power Limit4 */
++#define PECI_MBX_INDEX_PERF_LIMIT_REASON 65 /* Performance Limit Reasons */
++
++ __u16 param;
++/* When index is PECI_MBX_INDEX_CPU_ID */
++#define PECI_PKG_ID_CPU_ID 0x0000 /* CPUID Info */
++#define PECI_PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */
++#define PECI_PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */
++#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 */
++
++ __u8 rx_len;
++ __u8 cc;
++ __u8 padding[2];
++ __u8 pkg_config[4];
+ } __attribute__((__packed__));
+
+ /**
+@@ -264,6 +238,7 @@ struct peci_rd_pkg_cfg_msg {
+ * @index: encoding index for the requested service
+ * @param: specific data being requested
+ * @tx_len: number of data to be written in bytes
++ * @cc: completion code
+ * @value: package config data to be written
+ *
+ * The WrPkgConfig() command provides write access to the Package Configuration
+@@ -272,11 +247,20 @@ struct peci_rd_pkg_cfg_msg {
+ * may include power limiting, thermal averaging constant programming and so on.
+ */
+ struct peci_wr_pkg_cfg_msg {
+- __u8 addr;
+- __u8 index;
+- __u16 param;
+- __u8 tx_len;
+- __u32 value;
++#define PECI_WRPKGCFG_WRITE_LEN_BASE 6
++#define PECI_WRPKGCFG_READ_LEN 1
++#define PECI_WRPKGCFG_CMD 0xa5
++
++ __u8 addr;
++ __u8 index;
++#define PECI_MBX_INDEX_DIMM_AMBIENT 19
++#define PECI_MBX_INDEX_DIMM_TEMP 24
++
++ __u16 param;
++ __u8 tx_len;
++ __u8 cc;
++ __u8 padding[2];
++ __u32 value;
+ } __attribute__((__packed__));
+
+ /**
+@@ -284,16 +268,47 @@ struct peci_wr_pkg_cfg_msg {
+ * @addr: address of the client
+ * @thread_id: ID of the specific logical processor
+ * @address: address of MSR to read from
++ * @cc: completion code
+ * @value: data to be read
+ *
+ * The RdIAMSR() PECI command provides read access to Model Specific Registers
+ * (MSRs) defined in the processor's Intel Architecture (IA).
+ */
+ struct peci_rd_ia_msr_msg {
+- __u8 addr;
+- __u8 thread_id;
+- __u16 address;
+- __u64 value;
++#define PECI_RDIAMSR_WRITE_LEN 5
++#define PECI_RDIAMSR_READ_LEN 9
++#define PECI_RDIAMSR_CMD 0xb1
++
++ __u8 addr;
++ __u8 thread_id;
++ __u16 address;
++ __u8 cc;
++ __u8 padding[3];
++ __u64 value;
++} __attribute__((__packed__));
++
++/**
++ * struct peci_wr_ia_msr_msg - WrIAMSR command
++ * @addr: address of the client
++ * @thread_id: ID of the specific logical processor
++ * @address: address of MSR to write to
++ * @tx_len: number of data to be written in bytes
++ * @cc: completion code
++ * @value: data to be written
++ *
++ * The WrIAMSR() PECI command provides write access to Model Specific Registers
++ * (MSRs) defined in the processor's Intel Architecture (IA).
++ */
++struct peci_wr_ia_msr_msg {
++#define PECI_WRIAMSR_CMD 0xb5
++
++ __u8 addr;
++ __u8 thread_id;
++ __u16 address;
++ __u8 tx_len;
++ __u8 cc;
++ __u8 padding[2];
++ __u64 value;
+ } __attribute__((__packed__));
+
+ /**
+@@ -303,6 +318,7 @@ struct peci_rd_ia_msr_msg {
+ * @device: PCI device number
+ * @function: specific function to read from
+ * @reg: specific register to read from
++ * @cc: completion code
+ * @pci_config: config data to be read
+ *
+ * The RdPCIConfig() command provides sideband read access to the PCI
+@@ -310,12 +326,56 @@ struct peci_rd_ia_msr_msg {
+ * processor.
+ */
+ struct peci_rd_pci_cfg_msg {
+- __u8 addr;
+- __u8 bus;
+- __u8 device;
+- __u8 function;
+- __u16 reg;
+- __u8 pci_config[4];
++#define PECI_RDPCICFG_WRITE_LEN 6
++#define PECI_RDPCICFG_READ_LEN 5
++#define PECI_RDPCICFG_READ_LEN_MAX 24
++#define PECI_RDPCICFG_CMD 0x61
++
++ __u8 addr;
++ __u8 bus;
++#define PECI_PCI_BUS0_CPU0 0x00
++#define PECI_PCI_BUS0_CPU1 0x80
++#define PECI_PCI_CPUBUSNO_BUS 0x00
++#define PECI_PCI_CPUBUSNO_DEV 0x08
++#define PECI_PCI_CPUBUSNO_FUNC 0x02
++#define PECI_PCI_CPUBUSNO 0xcc
++#define PECI_PCI_CPUBUSNO_1 0xd0
++#define PECI_PCI_CPUBUSNO_VALID 0xd4
++
++ __u8 device;
++ __u8 function;
++ __u16 reg;
++ __u8 cc;
++ __u8 padding[1];
++ __u8 pci_config[4];
++} __attribute__((__packed__));
++
++/**
++ * struct peci_wr_pci_cfg_msg - WrPCIConfig command
++ * @addr: address of the client
++ * @bus: PCI bus number
++ * @device: PCI device number
++ * @function: specific function to write to
++ * @reg: specific register to write to
++ * @tx_len: number of data to be written in bytes
++ * @cc: completion code
++ * @pci_config: config data to be written
++ *
++ * The RdPCIConfig() command provides sideband write access to the PCI
++ * configuration space maintained in downstream devices external to the
++ * processor.
++ */
++struct peci_wr_pci_cfg_msg {
++#define PECI_WRPCICFG_CMD 0x65
++
++ __u8 addr;
++ __u8 bus;
++ __u8 device;
++ __u8 function;
++ __u16 reg;
++ __u8 tx_len;
++ __u8 cc;
++ __u8 pci_config[4];
+ } __attribute__((__packed__));
+
+ /**
+@@ -326,6 +386,7 @@ struct peci_rd_pci_cfg_msg {
+ * @function: specific function to read from
+ * @reg: specific register to read from
+ * @rx_len: number of data to be read in bytes
++ * @cc: completion code
+ * @pci_config: config data to be read
+ *
+ * The RdPCIConfigLocal() command provides sideband read access to the PCI
+@@ -333,13 +394,18 @@ struct peci_rd_pci_cfg_msg {
+ * processor IIO and uncore registers within the PCI configuration space.
+ */
+ struct peci_rd_pci_cfg_local_msg {
+- __u8 addr;
+- __u8 bus;
+- __u8 device;
+- __u8 function;
+- __u16 reg;
+- __u8 rx_len;
+- __u8 pci_config[4];
++#define PECI_RDPCICFGLOCAL_WRITE_LEN 5
++#define PECI_RDPCICFGLOCAL_READ_LEN_BASE 1
++#define PECI_RDPCICFGLOCAL_CMD 0xe1
++
++ __u8 addr;
++ __u8 bus;
++ __u8 device;
++ __u8 function;
++ __u16 reg;
++ __u8 rx_len;
++ __u8 cc;
++ __u8 pci_config[4];
+ } __attribute__((__packed__));
+
+ /**
+@@ -350,6 +416,7 @@ struct peci_rd_pci_cfg_local_msg {
+ * @function: specific function to read from
+ * @reg: specific register to read from
+ * @tx_len: number of data to be written in bytes
++ * @cc: completion code
+ * @value: config data to be written
+ *
+ * The WrPCIConfigLocal() command provides sideband write access to the PCI
+@@ -357,13 +424,18 @@ struct peci_rd_pci_cfg_local_msg {
+ * access this space even before BIOS enumeration of the system buses.
+ */
+ struct peci_wr_pci_cfg_local_msg {
+- __u8 addr;
+- __u8 bus;
+- __u8 device;
+- __u8 function;
+- __u16 reg;
+- __u8 tx_len;
+- __u32 value;
++#define PECI_WRPCICFGLOCAL_WRITE_LEN_BASE 6
++#define PECI_WRPCICFGLOCAL_READ_LEN 1
++#define PECI_WRPCICFGLOCAL_CMD 0xe5
++
++ __u8 addr;
++ __u8 bus;
++ __u8 device;
++ __u8 function;
++ __u16 reg;
++ __u8 tx_len;
++ __u8 cc;
++ __u32 value;
+ } __attribute__((__packed__));
+
+ #define PECI_IOC_BASE 0xb7
+@@ -389,9 +461,15 @@ struct peci_wr_pci_cfg_local_msg {
+ #define PECI_IOC_RD_IA_MSR \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_IA_MSR, struct peci_rd_ia_msr_msg)
+
++#define PECI_IOC_WR_IA_MSR \
++ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_IA_MSR, struct peci_wr_ia_msr_msg)
++
+ #define PECI_IOC_RD_PCI_CFG \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG, struct peci_rd_pci_cfg_msg)
+
++#define PECI_IOC_WR_PCI_CFG \
++ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG, struct peci_wr_pci_cfg_msg)
++
+ #define PECI_IOC_RD_PCI_CFG_LOCAL \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG_LOCAL, \
+ struct peci_rd_pci_cfg_local_msg)
+--
+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..391d6f816
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch
@@ -0,0 +1,426 @@
+From 59e2471d9bf64fa7d539520ef66cf5f33c0b0e55 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] i2c: slave-mqueue: add mqueue driver to receive ipmi message
+
+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 | 125 +++++++++++++++++
+ drivers/i2c/Kconfig | 23 +++
+ drivers/i2c/Makefile | 1 +
+ drivers/i2c/i2c-slave-mqueue.c | 217 +++++++++++++++++++++++++++++
+ 4 files changed, 366 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..3966cf0ab8da
+--- /dev/null
++++ b/Documentation/i2c/slave-mqueue-backend.rst
+@@ -0,0 +1,125 @@
++.. 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 efc3354d60ae..04fb851f2c82 100644
+--- a/drivers/i2c/Kconfig
++++ b/drivers/i2c/Kconfig
+@@ -118,6 +118,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/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..d1745ce5f
--- /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,620 @@
+From 7d5cd323d3b05a00f8b8a6eb38a5a1ec7925660a 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>
+---
+ .../devicetree/bindings/misc/aspeed-sio.txt | 18 +
+ arch/arm/boot/dts/aspeed-g4.dtsi | 7 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 7 +
+ drivers/misc/Kconfig | 9 +
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-lpc-sio.c | 450 +++++++++++++++++++++
+ include/uapi/linux/aspeed-lpc-sio.h | 44 ++
+ 7 files changed, 536 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/aspeed-sio.txt
+ create mode 100644 drivers/misc/aspeed-lpc-sio.c
+ create mode 100644 include/uapi/linux/aspeed-lpc-sio.h
+
+diff --git a/Documentation/devicetree/bindings/misc/aspeed-sio.txt b/Documentation/devicetree/bindings/misc/aspeed-sio.txt
+new file mode 100644
+index 000000000000..3530c2b02f5c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/aspeed-sio.txt
+@@ -0,0 +1,18 @@
++* 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 e8bcfc90bf7c..a87fd5ee1c84 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -340,6 +340,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 e5c0ba0f87c8..a568699c28f4 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -451,6 +451,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/misc/Kconfig b/drivers/misc/Kconfig
+index 00d1c547ece7..3ffb18f915e8 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -493,6 +493,15 @@ 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_SIO
++ depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
++ tristate "Aspeed ast2400/2500 HOST LPC SIO support"
++ 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 (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 768278b059c3..de2d5c6d186c 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -53,6 +53,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
+ obj-$(CONFIG_ECHO) += echo/
+ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
+ obj-$(CONFIG_CXL_BASE) += cxl/
++obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
+--- /dev/null
++++ b/drivers/misc/aspeed-lpc-sio.c
+@@ -0,0 +1,450 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (C) 2012-2017 ASPEED Technology Inc.
++// Copyright (c) 2017-2019 Intel Corporation
++
++#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>
++
++#include <linux/aspeed-lpc-sio.h>
++
++#define SOC_NAME "aspeed"
++#define DEVICE_NAME "lpc-sio"
++
++#define AST_LPC_SWCR0300 0x0
++#define LPC_PWRGD_STS (1 << 30)
++#define LPC_PWRGD_RISING_EVT_STS (1 << 29)
++#define LPC_PWRGD_FALLING_EVT_STS (1 << 28)
++#define LPC_PWRBTN_STS (1 << 27)
++#define LPC_PWRBTN_RISING_EVT_STS (1 << 26)
++#define LPC_PWRBTN_FALLING_EVT_STS (1 << 25)
++#define LPC_S5N_STS (1 << 21)
++#define LPC_S5N_RISING_EVT_STS (1 << 20)
++#define LPC_S5N_FALLING_EVT_STS (1 << 19)
++#define LPC_S3N_STS (1 << 18)
++#define LPC_S3N_RISING_EVT_STS (1 << 17)
++#define LPC_S3N_FALLING_EVT_STS (1 << 16)
++#define LPC_PWBTO_RAW_STS (1 << 15)
++#define LPC_LAST_ONCTL_STS (1 << 14)
++#define LPC_WAS_PFAIL_STS (1 << 13)
++#define LPC_POWER_UP_FAIL_STS (1 << 12) /* Crowbar */
++#define LPC_PWRBTN_OVERRIDE_STS (1 << 11)
++
++#define AST_LPC_SWCR0704 0x4
++
++#define AST_LPC_SWCR0B08 0x8
++#define LPC_PWREQ_OUTPUT_LEVEL (1 << 25)
++#define LPC_PWBTO_OUTPUT_LEVEL (1 << 24)
++#define LPC_ONCTL_STS (1 << 15)
++#define LPC_ONCTL_GPIO_LEVEL (1 << 14)
++#define LPC_ONCTL_EN_GPIO_OUTPUT (1 << 13)
++#define LPC_ONCTL_EN_GPIO_MODE (1 << 12)
++
++#define AST_LPC_SWCR0F0C 0xC
++#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 AST_LPC_ACPIB7B4 0x2C
++
++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 long sio_get_acpi_state(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ /* update the ACPI state event status */
++ if (sio_data->param != 0) {
++ if (val & LPC_SLP3N5N_EVENT_STATUS) {
++ sio_data->param = 1;
++ rc = regmap_write(lpc_sio->regmap, reg,
++ LPC_SLP3N5N_EVENT_STATUS);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n",
++ rc, reg);
++ return rc;
++ }
++ } 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;
++
++ return 0;
++}
++
++#define LPC_PWRGD_EVENT_STATUS ( \
++ LPC_PWRGD_RISING_EVT_STS | \
++ LPC_PWRGD_FALLING_EVT_STS)
++
++static long sio_get_pwrgd_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ /* update the PWRGD event status */
++ if (sio_data->param != 0) {
++ if (val & LPC_PWRGD_EVENT_STATUS) {
++ sio_data->param = 1;
++ rc = regmap_write(lpc_sio->regmap, reg,
++ LPC_PWRGD_EVENT_STATUS);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n",
++ rc, reg);
++ return rc;
++ }
++ } else {
++ sio_data->param = 0;
++ }
++ }
++
++ sio_data->data = (val & LPC_PWRGD_STS) != 0 ? 1 : 0;
++
++ return 0;
++}
++
++static long sio_get_onctl_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ sio_data->data = (val & LPC_ONCTL_STS) != 0 ? 1 : 0;
++
++ return 0;
++}
++
++static long sio_set_onctl_gpio(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ /* 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;
++
++ rc = regmap_write(lpc_sio->regmap, reg, val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++ } else {
++ val &= ~LPC_ONCTL_EN_GPIO_MODE;
++ rc = regmap_write(lpc_sio->regmap, reg, val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++ }
++
++ return 0;
++}
++
++static long sio_get_pwrbtn_override(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ /* clear the PWRBTN OVERRIDE status */
++ if (sio_data->param != 0) {
++ if (val & LPC_PWRBTN_OVERRIDE_STS) {
++ rc = regmap_write(lpc_sio->regmap, reg,
++ LPC_PWRBTN_OVERRIDE_STS);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n",
++ rc, reg);
++ return rc;
++ }
++ }
++ }
++
++ sio_data->data = (val & LPC_PWRBTN_OVERRIDE_STS) != 0 ? 1 : 0;
++
++ return 0;
++}
++
++static long sio_get_pfail_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++ u32 val;
++ int rc;
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ rc = regmap_read(lpc_sio->regmap, reg, &val);
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_read() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++
++ /* [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) {
++ rc = regmap_write(lpc_sio->regmap, reg, 0); /* W0C */
++ if (rc) {
++ dev_err(lpc_sio->miscdev.parent,
++ "regmap_write() failed with %d(reg:0x%x)\n", rc, reg);
++ return rc;
++ }
++ sio_data->data = 1;
++ } else {
++ sio_data->data = 0;
++ }
++
++ return 0;
++}
++
++typedef long (*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,
++};
++
++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);
++ long ret;
++ sio_cmd_fn cmd_fn;
++ struct sio_ioctl_data sio_data;
++
++
++ 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 == NULL)
++ return -EINVAL;
++
++ if (down_interruptible(&lpc_sio->lock) != 0)
++ return -ERESTARTSYS;
++
++ ret = cmd_fn(lpc_sio, &sio_data);
++ if (ret == 0) {
++ if (copy_to_user((void __user *)param, &sio_data,
++ sizeof(sio_data)))
++ ret = -EFAULT;
++ }
++
++ 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;
++ int rc;
++
++ 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);
++
++ rc = of_property_read_u32(dev->of_node, "reg", &lpc_sio->reg_base);
++ if (rc) {
++ dev_err(dev, "Couldn't read reg device-tree property\n");
++ return rc;
++ }
++
++ 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;
++ }
++
++ sema_init(&lpc_sio->lock, 1);
++
++ lpc_sio->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(lpc_sio->clk)) {
++ rc = PTR_ERR(lpc_sio->clk);
++ if (rc != -EPROBE_DEFER)
++ dev_err(dev, "couldn't get clock\n");
++ return rc;
++ }
++ rc = clk_prepare_enable(lpc_sio->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
++ 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;
++ rc = misc_register(&lpc_sio->miscdev);
++ if (rc) {
++ 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 rc;
++}
++
++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 = aspeed_lpc_sio_match,
++ },
++ .probe = aspeed_lpc_sio_probe,
++ .remove = aspeed_lpc_sio_remove,
++};
++module_platform_driver(aspeed_lpc_sio_driver);
++
++MODULE_LICENSE("GPL");
++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..5dc1efd4a426
+--- /dev/null
++++ b/include/uapi/linux/aspeed-lpc-sio.h
+@@ -0,0 +1,44 @@
++/*
++ * 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_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..303bff0b1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
@@ -0,0 +1,597 @@
+From 3437db37b2f39a69505338546d9f846338de6c88 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] eSPI: add ASPEED AST2500 eSPI driver to boot a host with PCH
+ runs on eSPI
+
+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
+
+Signed-off-by: Haiyue Wang <haiyue.wang@linux.intel.com>
+---
+ .../devicetree/bindings/misc/aspeed,espi-slave.txt | 20 ++
+ Documentation/misc-devices/espi-slave.rst | 119 +++++++
+ arch/arm/boot/dts/aspeed-g5.dtsi | 4 +
+ drivers/misc/Kconfig | 8 +
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-espi-slave.c | 353 +++++++++++++++++++++
+ 6 files changed, 505 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..4f5d47ecc882
+--- /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"
++
++ - 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..185acd71bd26
+--- /dev/null
++++ b/Documentation/misc-devices/espi-slave.rst
+@@ -0,0 +1,119 @@
++.. 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 da9e903808bc..01d27e845982 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -267,6 +267,7 @@
+ clocks = <&syscon ASPEED_CLK_APB>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
++ status = "disabled";
+ };
+
+ sgpio: sgpio@1e780200 {
+@@ -361,6 +362,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/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index d4ed3777462a..8b1fcf741411 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -485,6 +485,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 ASPEED_LPC_CTRL
+ depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
+ tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 7b018962cad3..89b051f82391 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -54,6 +54,7 @@ obj-$(CONFIG_ECHO) += echo/
+ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
+ obj-$(CONFIG_CXL_BASE) += cxl/
+ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
++obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
+diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c
+new file mode 100644
+index 000000000000..36ae867ca6f9
+--- /dev/null
++++ b/drivers/misc/aspeed-espi-slave.c
+@@ -0,0 +1,353 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2012-2015, ASPEED Technology Inc.
++ * Copyright (c) 2015-2018, Intel Corporation.
++ */
++
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <linux/errno.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/poll.h>
++#include <linux/regmap.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/timer.h>
++
++#define DEVICE_NAME "aspeed-espi-slave"
++
++#define ESPI_CTRL 0x00
++#define ESPI_CTRL_SW_RESET GENMASK(31, 24)
++#define ESPI_CTRL_OOB_CHRDY BIT(4)
++#define ESPI_ISR 0x08
++#define ESPI_ISR_HW_RESET BIT(31)
++#define ESPI_ISR_VW_SYS_EVT1 BIT(22)
++#define ESPI_ISR_VW_SYS_EVT BIT(8)
++#define ESPI_IER 0x0C
++#define ESPI_DATA_PORT 0x28
++#define ESPI_DATA_PORT_ASPEED 0xa8
++#define ESPI_SYS_IER 0x94
++#define ESPI_SYS_EVENT 0x98
++#define ESPI_SYS_INT_T0 0x110
++#define ESPI_SYS_INT_T1 0x114
++#define ESPI_SYS_INT_T2 0x118
++#define ESPI_SYS_ISR 0x11C
++#define ESPI_SYSEVT_HOST_RST_ACK BIT(27)
++#define ESPI_SYSEVT_SLAVE_BOOT_STATUS BIT(23)
++#define ESPI_SYSEVT_SLAVE_BOOT_DONE BIT(20)
++#define ESPI_SYSEVT_OOB_RST_ACK BIT(16)
++#define ESPI_SYSEVT_HOST_RST_WARN BIT(8)
++#define ESPI_SYSEVT_OOB_RST_WARN BIT(6)
++#define ESPI_SYSEVT_PLT_RST_N BIT(5)
++#define ESPI_SYS1_IER 0x100
++#define ESPI_SYS1_EVENT 0x104
++#define ESPI_SYS1_INT_T0 0x120
++#define ESPI_SYS1_INT_T1 0x124
++#define ESPI_SYS1_INT_T2 0x128
++#define ESPI_SYS1_ISR 0x12C
++#define ESPI_SYSEVT1_SUS_ACK BIT(20)
++#define ESPI_SYSEVT1_SUS_WARN BIT(0)
++
++struct aspeed_espi_slave_data {
++ struct regmap *map;
++ struct clk *clk;
++};
++
++static void aspeed_espi_slave_sys_event(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++ u32 sts, evt;
++
++ if (regmap_read(priv->map, ESPI_SYS_ISR, &sts) != 0 ||
++ regmap_read(priv->map, ESPI_SYS_EVENT, &evt) != 0) {
++ dev_err(dev, "regmap_read failed\n");
++ return;
++ }
++
++ dev_dbg(dev, "sys: sts = %08x, evt = %08x\n", sts, evt);
++
++ if ((evt & ESPI_SYSEVT_SLAVE_BOOT_STATUS) == 0) {
++ dev_info(dev, "Setting espi slave boot done\n");
++ regmap_write(priv->map, ESPI_SYS_EVENT,
++ evt | ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ }
++#if 0
++ if (sts & ESPI_SYSEVT_HOST_RST_WARN) {
++ dev_info(dev, "ESPI_SYSEVT_HOST_RST_WARN; %s ack\n",
++ (evt & ESPI_SYSEVT_HOST_RST_WARN ? "send" : "clr"));
++ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
++ ESPI_SYSEVT_HOST_RST_ACK,
++ evt & ESPI_SYSEVT_HOST_RST_WARN ?
++ ESPI_SYSEVT_HOST_RST_ACK : 0);
++ }
++ if (sts & ESPI_SYSEVT_OOB_RST_WARN) {
++ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; %s ack\n",
++ (evt & ESPI_SYSEVT_OOB_RST_WARN ? "send" : "clr"));
++ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
++ ESPI_SYSEVT_OOB_RST_ACK,
++ evt & ESPI_SYSEVT_OOB_RST_WARN ?
++ ESPI_SYSEVT_OOB_RST_ACK : 0);
++ }
++#else
++ if (sts & ESPI_SYSEVT_HOST_RST_WARN) {
++ if (evt & ESPI_SYSEVT_HOST_RST_WARN) {
++ dev_info(dev, "ESPI_SYSEVT_HOST_RST_WARN; send ack\n");
++ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
++ ESPI_SYSEVT_HOST_RST_ACK, ESPI_SYSEVT_HOST_RST_ACK);
++ }
++ }
++ if (sts & ESPI_SYSEVT_OOB_RST_WARN) {
++ if (evt & ESPI_SYSEVT_OOB_RST_WARN) {
++ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; send ack\n");
++ regmap_write_bits(priv->map, ESPI_SYS_EVENT,
++ ESPI_SYSEVT_OOB_RST_ACK, ESPI_SYSEVT_OOB_RST_ACK);
++ }
++ }
++#endif
++ regmap_write(priv->map, ESPI_SYS_ISR, sts);
++}
++
++static void aspeed_espi_slave_sys1_event(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++ u32 sts, evt;
++
++ if (regmap_read(priv->map, ESPI_SYS1_ISR, &sts) != 0 ||
++ regmap_read(priv->map, ESPI_SYS1_EVENT, &evt) != 0) {
++ dev_err(dev, "regmap_read failed\n");
++ return;
++ }
++ dev_dbg(dev, "sys1: sts = %08x, evt = %08x\n", sts, evt);
++
++#if 0
++ if (sts & ESPI_SYSEVT1_SUS_WARN) {
++ dev_info(dev, "ESPI_SYSEVT1_SUS_WARN; %s ack\n",
++ (evt & ESPI_SYSEVT1_SUS_WARN ? "send" : "clr"));
++ regmap_write_bits(priv->map, ESPI_SYS1_EVENT,
++ ESPI_SYSEVT1_SUS_ACK,
++ evt & ESPI_SYSEVT1_SUS_WARN ?
++ ESPI_SYSEVT1_SUS_ACK : 0);
++ }
++#else
++ if (sts & ESPI_SYSEVT1_SUS_WARN) {
++ if (evt & ESPI_SYSEVT1_SUS_WARN) {
++ dev_info(dev, "ESPI_SYSEVT_OOB_RST_WARN; send ack\n");
++ regmap_write_bits(priv->map, ESPI_SYS1_EVENT,
++ ESPI_SYSEVT1_SUS_ACK, ESPI_SYSEVT1_SUS_ACK);
++ }
++ }
++#endif
++ regmap_write(priv->map, ESPI_SYS1_ISR, sts);
++}
++
++static void aspeed_espi_slave_boot_ack(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++ u32 evt;
++
++ if (regmap_read(priv->map, ESPI_SYS_EVENT, &evt) == 0 &&
++ (evt & ESPI_SYSEVT_SLAVE_BOOT_STATUS) == 0) {
++ dev_info(dev, "Setting espi slave boot done\n");
++ regmap_write(priv->map, ESPI_SYS_EVENT,
++ evt | ESPI_SYSEVT_SLAVE_BOOT_STATUS |
++ ESPI_SYSEVT_SLAVE_BOOT_DONE);
++ }
++
++ if (regmap_read(priv->map, ESPI_SYS1_EVENT, &evt) == 0 &&
++ (evt & ESPI_SYSEVT1_SUS_WARN) != 0 &&
++ (evt & ESPI_SYSEVT1_SUS_ACK) == 0) {
++ dev_info(dev, "Boot SUS WARN set; send ack\n");
++ regmap_write(priv->map, ESPI_SYS1_EVENT,
++ evt | ESPI_SYSEVT1_SUS_ACK);
++ }
++}
++
++static irqreturn_t aspeed_espi_slave_irq(int irq, void *arg)
++{
++ struct platform_device *pdev = arg;
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++ u32 sts;
++
++ if (regmap_read(priv->map, ESPI_ISR, &sts) != 0) {
++ dev_err(dev, "regmap_read failed\n");
++ return IRQ_NONE;
++ }
++
++ dev_dbg(dev, "ESPI_ISR: %08x\n", sts);
++
++ if (sts & ESPI_ISR_VW_SYS_EVT)
++ aspeed_espi_slave_sys_event(pdev);
++
++ if (sts & ESPI_ISR_VW_SYS_EVT1)
++ aspeed_espi_slave_sys1_event(pdev);
++
++ /*
++ if (sts & ESPI_ISR_HW_RESET) {
++ regmap_write_bits(priv->map, ESPI_CTRL,
++ ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ESPI_CTRL,
++ ESPI_CTRL_SW_RESET, ESPI_CTRL_SW_RESET);
++
++ aspeed_espi_slave_boot_ack(pdev);
++ }
++ */
++
++ regmap_write(priv->map, ESPI_ISR, sts);
++
++ return IRQ_HANDLED;
++}
++
++/* 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). PLTRST_N : Dual Edge 1 0 0
++ */
++#define ESPI_SYS_INT_T0_SET 0x00000000
++#define ESPI_SYS_INT_T1_SET 0x00000000
++#define ESPI_SYS_INT_T2_SET \
++(ESPI_SYSEVT_HOST_RST_WARN | ESPI_SYSEVT_OOB_RST_WARN | ESPI_SYSEVT_PLT_RST_N)
++#define ESPI_SYS_INT_SET \
++(ESPI_SYSEVT_HOST_RST_WARN | ESPI_SYSEVT_OOB_RST_WARN | ESPI_SYSEVT_PLT_RST_N)
++
++/* Setup Interrupt Type/Enable of System Event 1 from Master
++ * T2 T1 T0
++ * 1). SUS_WARN : Rising Edge 0 0 1
++ */
++#define ESPI_SYS1_INT_T0_SET ESPI_SYSEVT1_SUS_WARN
++#define ESPI_SYS1_INT_T1_SET 0x00000000
++#define ESPI_SYS1_INT_T2_SET 0x00000000
++#define ESPI_SYS1_INT_SET ESPI_SYSEVT1_SUS_WARN
++
++static int aspeed_espi_slave_config_irq(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++ int irq;
++ int rc;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return irq;
++
++ regmap_write_bits(priv->map, ESPI_CTRL, ESPI_CTRL_OOB_CHRDY,
++ ESPI_CTRL_OOB_CHRDY);
++
++ regmap_write(priv->map, ESPI_SYS_INT_T0, ESPI_SYS_INT_T0_SET);
++ regmap_write(priv->map, ESPI_SYS_INT_T1, ESPI_SYS_INT_T1_SET);
++ regmap_write(priv->map, ESPI_SYS_INT_T2, ESPI_SYS_INT_T2_SET);
++ regmap_write(priv->map, ESPI_SYS_IER, ESPI_SYS_INT_SET);
++
++ regmap_write(priv->map, ESPI_SYS1_INT_T0, ESPI_SYS1_INT_T0_SET);
++ regmap_write(priv->map, ESPI_SYS1_INT_T1, ESPI_SYS1_INT_T1_SET);
++ regmap_write(priv->map, ESPI_SYS1_INT_T2, ESPI_SYS1_INT_T2_SET);
++ regmap_write(priv->map, ESPI_SYS1_IER, ESPI_SYS1_INT_SET);
++
++ regmap_write(priv->map, ESPI_IER, 0xFFFFFFFF);
++
++ aspeed_espi_slave_boot_ack(pdev);
++
++ rc = devm_request_irq(dev, irq, aspeed_espi_slave_irq, IRQF_SHARED,
++ dev_name(dev), pdev);
++ if (rc < 0)
++ return rc;
++
++ return 0;
++}
++
++static const struct regmap_config espi_slave_regmap_cfg = {
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++ .max_register = ESPI_SYS1_ISR,
++};
++
++static int aspeed_espi_slave_probe(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv;
++ struct device *dev = &pdev->dev;
++ struct resource *res;
++ void __iomem *regs;
++ int rc;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ 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->map = devm_regmap_init_mmio(dev, regs, &espi_slave_regmap_cfg);
++ if (IS_ERR(priv->map))
++ return PTR_ERR(priv->map);
++
++ priv->clk = devm_clk_get(dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev, "couldn't get clock\n");
++ return PTR_ERR(priv->clk);
++ }
++ rc = clk_prepare_enable(priv->clk);
++ if (rc) {
++ dev_err(dev, "couldn't enable clock\n");
++ return rc;
++ }
++
++ dev_set_name(dev, DEVICE_NAME);
++
++ platform_set_drvdata(pdev, priv);
++
++ rc = aspeed_espi_slave_config_irq(pdev);
++ if (rc) {
++ platform_set_drvdata(pdev, NULL);
++ goto err;
++ }
++
++ dev_info(dev, "aspeed,ast2500-espi-slave probe complete\n");
++ return 0;
++
++err:
++ clk_disable_unprepare(priv->clk);
++ return rc;
++}
++
++
++static int aspeed_espi_slave_remove(struct platform_device *pdev)
++{
++ struct aspeed_espi_slave_data *priv = platform_get_drvdata(pdev);
++
++ clk_disable_unprepare(priv->clk);
++
++ return 0;
++}
++
++static const struct of_device_id of_espi_slave_match_table[] = {
++ { .compatible = "aspeed,ast2500-espi-slave" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, of_espi_slave_match_table);
++
++static struct platform_driver aspeed_espi_slave_driver = {
++ .driver = {
++ .name = DEVICE_NAME,
++ .of_match_table = of_match_ptr(of_espi_slave_match_table),
++ },
++ .probe = aspeed_espi_slave_probe,
++ .remove = aspeed_espi_slave_remove,
++};
++module_platform_driver(aspeed_espi_slave_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
++MODULE_DESCRIPTION("Linux device interface to the eSPI slave");
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch
new file mode 100644
index 000000000..1532a5642
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch
@@ -0,0 +1,392 @@
+From d1d221aedb9b366e3477f253386b1cf829c56193 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@intel.com>
+Date: Wed, 4 Apr 2018 13:52:39 -0700
+Subject: [PATCH] Add support for new PECI commands
+
+Signed-off-by: Jason M. Bills <jason.m.bills@intel.com>
+---
+ drivers/peci/peci-core.c | 226 ++++++++++++++++++++++++++++++++++++++++
+ include/uapi/linux/peci-ioctl.h | 104 ++++++++++++++++++
+ 2 files changed, 330 insertions(+)
+
+diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
+index e282f9ef383b..9af11accc1d4 100644
+--- a/drivers/peci/peci-core.c
++++ b/drivers/peci/peci-core.c
+@@ -345,6 +345,9 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter)
+ adapter->cmd_mask |= BIT(PECI_CMD_GET_TEMP);
+ adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB);
+ adapter->cmd_mask |= BIT(PECI_CMD_PING);
++ adapter->cmd_mask |= BIT(PECI_CMD_RD_END_PT_CFG);
++ adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_DISC);
++ adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_GET_FRAME);
+
+ out:
+ peci_put_xfer_msg(msg);
+@@ -693,6 +696,226 @@ static int peci_cmd_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg)
+ return ret;
+ }
+
++static int peci_cmd_rd_end_pt_cfg(struct peci_adapter *adapter, void *vmsg)
++{
++ struct peci_rd_end_pt_cfg_msg *umsg = vmsg;
++ struct peci_xfer_msg *msg = NULL;
++ u32 address;
++ int ret;
++
++ switch (umsg->msg_type) {
++ case PECI_RDENDPTCFG_TYPE_LOCAL_PCI:
++ case PECI_RDENDPTCFG_TYPE_PCI:
++ /*
++ * Per the PECI spec, the read length must be a byte, word,
++ * or dword
++ */
++ if (umsg->rx_len != 1 && umsg->rx_len != 2 &&
++ umsg->rx_len != 4) {
++ dev_dbg(&adapter->dev,
++ "Invalid read length, rx_len: %d\n",
++ umsg->rx_len);
++ return -EINVAL;
++ }
++
++ msg = peci_get_xfer_msg(PECI_RDENDPTCFG_PCI_WRITE_LEN,
++ PECI_RDENDPTCFG_READ_LEN_BASE +
++ umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
++ address = umsg->params.pci_cfg.reg; /* [11:0] - Register */
++ address |= (u32)umsg->params.pci_cfg.function
++ << 12; /* [14:12] - Function */
++ address |= (u32)umsg->params.pci_cfg.device
++ << 15; /* [19:15] - Device */
++ address |= (u32)umsg->params.pci_cfg.bus
++ << 20; /* [27:20] - Bus */
++ /* [31:28] - Reserved */
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDENDPTCFG_CMD;
++ msg->tx_buf[1] = 0x00; /* request byte for Host ID|Retry bit */
++ msg->tx_buf[2] = umsg->msg_type; /* Message Type */
++ msg->tx_buf[3] = 0x00; /* Endpoint ID */
++ msg->tx_buf[4] = 0x00; /* Reserved */
++ msg->tx_buf[5] = 0x00; /* Reserved */
++ msg->tx_buf[6] = PECI_RDENDPTCFG_ADDR_TYPE_PCI; /* Addr Type */
++ msg->tx_buf[7] = umsg->params.pci_cfg.seg; /* PCI Segment */
++ msg->tx_buf[8] = (u8)address; /* LSB - PCI Config Address */
++ msg->tx_buf[9] = (u8)(address >> 8); /* PCI Config Address */
++ msg->tx_buf[10] = (u8)(address >> 16); /* PCI Config Address */
++ msg->tx_buf[11] =
++ (u8)(address >> 24); /* MSB - PCI Config Address */
++ break;
++
++ case PECI_RDENDPTCFG_TYPE_MMIO:
++ /*
++ * Per the PECI spec, the read length must be a byte, word,
++ * dword, or qword
++ */
++ if (umsg->rx_len != 1 && umsg->rx_len != 2 &&
++ umsg->rx_len != 4 && umsg->rx_len != 8) {
++ dev_dbg(&adapter->dev,
++ "Invalid read length, rx_len: %d\n",
++ umsg->rx_len);
++ return -EINVAL;
++ }
++ /*
++ * Per the PECI spec, the address type must specify either DWORD
++ * or QWORD
++ */
++ if (umsg->params.mmio.addr_type !=
++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_D &&
++ umsg->params.mmio.addr_type !=
++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q) {
++ dev_dbg(&adapter->dev,
++ "Invalid address type, addr_type: %d\n",
++ umsg->params.mmio.addr_type);
++ return -EINVAL;
++ }
++
++ msg = peci_get_xfer_msg(PECI_RDENDPTCFG_MMIO_D_WRITE_LEN,
++ PECI_RDENDPTCFG_READ_LEN_BASE +
++ umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
++ address = umsg->params.mmio.function; /* [2:0] - Function */
++ address |= (u32)umsg->params.mmio.device
++ << 3; /* [7:3] - Device */
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_RDENDPTCFG_CMD;
++ msg->tx_buf[1] = 0x00; /* request byte for Host ID|Retry bit */
++ msg->tx_buf[2] = umsg->msg_type; /* Message Type */
++ msg->tx_buf[3] = 0x00; /* Endpoint ID */
++ msg->tx_buf[4] = 0x00; /* Reserved */
++ msg->tx_buf[5] = umsg->params.mmio.bar; /* BAR # */
++ msg->tx_buf[6] = umsg->params.mmio.addr_type; /* Address Type */
++ msg->tx_buf[7] = umsg->params.mmio.seg; /* PCI Segment */
++ msg->tx_buf[8] = (u8)address; /* Function/Device */
++ msg->tx_buf[9] = umsg->params.mmio.bus; /* PCI Bus */
++ msg->tx_buf[10] = (u8)umsg->params.mmio
++ .offset; /* LSB - Register Offset */
++ msg->tx_buf[11] = (u8)(umsg->params.mmio.offset
++ >> 8); /* Register Offset */
++ msg->tx_buf[12] = (u8)(umsg->params.mmio.offset
++ >> 16); /* Register Offset */
++ msg->tx_buf[13] = (u8)(umsg->params.mmio.offset
++ >> 24); /* MSB - DWORD Register Offset */
++ if (umsg->params.mmio.addr_type ==
++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q) {
++ msg->tx_len = PECI_RDENDPTCFG_MMIO_Q_WRITE_LEN;
++ msg->tx_buf[14] = (u8)(umsg->params.mmio.offset
++ >> 32); /* Register Offset */
++ msg->tx_buf[15] = (u8)(umsg->params.mmio.offset
++ >> 40); /* Register Offset */
++ msg->tx_buf[16] = (u8)(umsg->params.mmio.offset
++ >> 48); /* Register Offset */
++ msg->tx_buf[17] =
++ (u8)(umsg->params.mmio.offset
++ >> 56); /* MSB - QWORD Register Offset */
++ }
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len);
++
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
++}
++
++static int peci_cmd_crashdump_disc(struct peci_adapter *adapter, void *vmsg)
++{
++ struct peci_crashdump_disc_msg *umsg = vmsg;
++ struct peci_xfer_msg *msg;
++ int ret;
++
++ /* Per the EDS, the read length must be a byte, word, or qword */
++ if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 8) {
++ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n",
++ umsg->rx_len);
++ return -EINVAL;
++ }
++
++ msg = peci_get_xfer_msg(PECI_CRASHDUMP_DISC_WRITE_LEN,
++ PECI_CRASHDUMP_DISC_READ_LEN_BASE +
++ umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_CRASHDUMP_CMD;
++ msg->tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
++ /* Host ID is 0 for PECI 3.0 */
++ msg->tx_buf[2] = PECI_CRASHDUMP_DISC_VERSION;
++ msg->tx_buf[3] = PECI_CRASHDUMP_DISC_OPCODE;
++ msg->tx_buf[4] = umsg->subopcode;
++ msg->tx_buf[5] = umsg->param0;
++ msg->tx_buf[6] = (u8)umsg->param1;
++ msg->tx_buf[7] = (u8)(umsg->param1 >> 8);
++ msg->tx_buf[8] = umsg->param2;
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len);
++
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
++}
++
++static int peci_cmd_crashdump_get_frame(struct peci_adapter *adapter,
++ void *vmsg)
++{
++ struct peci_crashdump_get_frame_msg *umsg = vmsg;
++ struct peci_xfer_msg *msg;
++ int ret;
++
++ /* Per the EDS, the read length must be a qword or dqword */
++ if (umsg->rx_len != 8 && umsg->rx_len != 16) {
++ dev_dbg(&adapter->dev, "Invalid read length, rx_len: %d\n",
++ umsg->rx_len);
++ return -EINVAL;
++ }
++
++ msg = peci_get_xfer_msg(PECI_CRASHDUMP_GET_FRAME_WRITE_LEN,
++ PECI_CRASHDUMP_GET_FRAME_READ_LEN_BASE +
++ umsg->rx_len);
++ if (!msg)
++ return -ENOMEM;
++
++ msg->addr = umsg->addr;
++ msg->tx_buf[0] = PECI_CRASHDUMP_CMD;
++ msg->tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */
++ /* Host ID is 0 for PECI 3.0 */
++ msg->tx_buf[2] = PECI_CRASHDUMP_GET_FRAME_VERSION;
++ msg->tx_buf[3] = PECI_CRASHDUMP_GET_FRAME_OPCODE;
++ msg->tx_buf[4] = (u8)umsg->param0;
++ msg->tx_buf[5] = (u8)(umsg->param0 >> 8);
++ msg->tx_buf[6] = (u8)umsg->param1;
++ msg->tx_buf[7] = (u8)(umsg->param1 >> 8);
++ msg->tx_buf[8] = (u8)umsg->param2;
++ msg->tx_buf[8] = (u8)(umsg->param2 >> 8);
++
++ ret = peci_xfer_with_retries(adapter, msg, false);
++ if (!ret)
++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len);
++
++ umsg->cc = msg->rx_buf[0];
++ peci_put_xfer_msg(msg);
++
++ return ret;
++}
++
+ typedef int (*peci_cmd_fn_type)(struct peci_adapter *, void *);
+
+ static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = {
+@@ -708,6 +931,9 @@ static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = {
+ peci_cmd_wr_pci_cfg,
+ peci_cmd_rd_pci_cfg_local,
+ peci_cmd_wr_pci_cfg_local,
++ peci_cmd_rd_end_pt_cfg,
++ peci_cmd_crashdump_disc,
++ peci_cmd_crashdump_get_frame,
+ };
+
+ /**
+diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
+index 4c28abe2c17a..e67b0735f606 100644
+--- a/include/uapi/linux/peci-ioctl.h
++++ b/include/uapi/linux/peci-ioctl.h
+@@ -72,6 +72,9 @@ enum peci_cmd {
+ PECI_CMD_WR_PCI_CFG,
+ PECI_CMD_RD_PCI_CFG_LOCAL,
+ PECI_CMD_WR_PCI_CFG_LOCAL,
++ PECI_CMD_RD_END_PT_CFG,
++ PECI_CMD_CRASHDUMP_DISC,
++ PECI_CMD_CRASHDUMP_GET_FRAME,
+ PECI_CMD_MAX
+ };
+
+@@ -439,6 +442,95 @@ struct peci_wr_pci_cfg_local_msg {
+ __u32 value;
+ } __attribute__((__packed__));
+
++struct peci_rd_end_pt_cfg_msg {
++#define PECI_RDENDPTCFG_PCI_WRITE_LEN 0x0C
++#define PECI_RDENDPTCFG_MMIO_D_WRITE_LEN 0x0E
++#define PECI_RDENDPTCFG_MMIO_Q_WRITE_LEN 0x12
++#define PECI_RDENDPTCFG_READ_LEN_BASE 1
++#define PECI_RDENDPTCFG_CMD 0xC1
++
++ __u8 addr;
++ __u8 msg_type;
++#define PECI_RDENDPTCFG_TYPE_LOCAL_PCI 0x03
++#define PECI_RDENDPTCFG_TYPE_PCI 0x04
++#define PECI_RDENDPTCFG_TYPE_MMIO 0x05
++
++ union {
++ struct {
++ __u8 seg;
++ __u8 bus;
++ __u8 device;
++ __u8 function;
++ __u16 reg;
++ } pci_cfg;
++ struct {
++ __u8 seg;
++ __u8 bus;
++ __u8 device;
++ __u8 function;
++ __u8 bar;
++ __u8 addr_type;
++#define PECI_RDENDPTCFG_ADDR_TYPE_PCI 0x04
++#define PECI_RDENDPTCFG_ADDR_TYPE_MMIO_D 0x05
++#define PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q 0x06
++
++ __u64 offset;
++ } mmio;
++ } params;
++ __u8 rx_len;
++ __u8 cc;
++ __u8 padding[2];
++ __u8 data[8];
++} __attribute__((__packed__));
++
++/* Crashdump Agent */
++#define PECI_CRASHDUMP_CORE 0x00
++#define PECI_CRASHDUMP_TOR 0x01
++
++/* Crashdump Agent Param */
++#define PECI_CRASHDUMP_PAYLOAD_SIZE 0x00
++
++/* Crashdump Agent Data Param */
++#define PECI_CRASHDUMP_AGENT_ID 0x00
++#define PECI_CRASHDUMP_AGENT_PARAM 0x01
++
++struct peci_crashdump_disc_msg {
++ __u8 addr;
++ __u8 subopcode;
++#define PECI_CRASHDUMP_ENABLED 0x00
++#define PECI_CRASHDUMP_NUM_AGENTS 0x01
++#define PECI_CRASHDUMP_AGENT_DATA 0x02
++
++ __u8 cc;
++ __u8 param0;
++ __u16 param1;
++ __u8 param2;
++ __u8 rx_len;
++ __u8 data[8];
++} __attribute__((__packed__));
++
++struct peci_crashdump_get_frame_msg {
++#define PECI_CRASHDUMP_DISC_WRITE_LEN 9
++#define PECI_CRASHDUMP_DISC_READ_LEN_BASE 1
++#define PECI_CRASHDUMP_DISC_VERSION 0
++#define PECI_CRASHDUMP_DISC_OPCODE 1
++#define PECI_CRASHDUMP_GET_FRAME_WRITE_LEN 10
++#define PECI_CRASHDUMP_GET_FRAME_READ_LEN_BASE 1
++#define PECI_CRASHDUMP_GET_FRAME_VERSION 0
++#define PECI_CRASHDUMP_GET_FRAME_OPCODE 3
++#define PECI_CRASHDUMP_CMD 0x71
++
++ __u8 addr;
++ __u8 padding0;
++ __u16 param0;
++ __u16 param1;
++ __u16 param2;
++ __u8 rx_len;
++ __u8 cc;
++ __u8 padding1[2];
++ __u8 data[16];
++} __attribute__((__packed__));
++
+ #define PECI_IOC_BASE 0xb7
+
+ #define PECI_IOC_XFER \
+@@ -479,4 +571,16 @@ struct peci_wr_pci_cfg_local_msg {
+ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG_LOCAL, \
+ struct peci_wr_pci_cfg_local_msg)
+
++#define PECI_IOC_RD_END_PT_CFG \
++ _IOWR(PECI_IOC_BASE, PECI_CMD_RD_END_PT_CFG, \
++ struct peci_rd_end_pt_cfg_msg)
++
++#define PECI_IOC_CRASHDUMP_DISC \
++ _IOWR(PECI_IOC_BASE, PECI_CMD_CRASHDUMP_DISC, \
++ struct peci_crashdump_disc_msg)
++
++#define PECI_IOC_CRASHDUMP_GET_FRAME \
++ _IOWR(PECI_IOC_BASE, PECI_CMD_CRASHDUMP_GET_FRAME, \
++ struct peci_crashdump_get_frame_msg)
++
+ #endif /* __PECI_IOCTL_H */
+--
+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..56dca7345
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
@@ -0,0 +1,93 @@
+From 43470f186979483ba6c1e6374c7ea3a129622862 Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Mon, 1 Mar 2019 11:46:09 -0700
+Subject: [PATCH] Update AST2500d JTAG driver. Step 1
+
+Update AST2500d JTAG driver. Remove Legacy driver but keep headers.
+
+Signed-off-by: Corona, Ernesto <ernesto.corona@intel.com>
+---
+ 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..e984623ba
--- /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,142 @@
+From f4c13be7b95899d6eca3fa7ae38224bc9c7d7902 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 | 25 +++++++++++++++++++++++++
+ drivers/i2c/i2c-slave-mqueue.c | 22 ++++++++++++++++++++++
+ 2 files changed, 47 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 6c8b38fd6e64..77dbd37b7b51 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -166,6 +166,19 @@ 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) \
++ if (dump_debug && bus->adap.nr == dump_debug_bus_id) { \
++ char dump_info[100] = {0,}; \
++ snprintf(dump_info, sizeof(dump_info), \
++ "%s (bus_id:%d, addr:0x%02x, flags:0x%02x): ", \
++ __func__, bus->adap.nr, addr, flags); \
++ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, 16, 1, \
++ buf, len, true); \
++ }
++
+ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
+
+ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+@@ -655,6 +668,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;
+@@ -697,6 +711,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;
+ }
+
+@@ -1064,6 +1083,12 @@ static struct platform_driver aspeed_i2c_bus_driver = {
+ };
+ module_platform_driver(aspeed_i2c_bus_driver);
+
++module_param_named(dump_debug, dump_debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(dump_debug, "debug flag for dump printing");
++module_param_named(dump_debug_bus_id, dump_debug_bus_id, int,
++ S_IRUGO | S_IWUSR);
++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..4548088e1922 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,18 @@ 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) \
++ if (dump_debug && client->adapter->nr == dump_debug_bus_id) { \
++ char dump_info[100] = {0,}; \
++ snprintf(dump_info, sizeof(dump_info), \
++ "%s (bus_id:%d): ", __func__, client->adapter->nr); \
++ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, 16, 1, \
++ buf, len, true); \
++ }
++
+ static int i2c_slave_mqueue_callback(struct i2c_client *client,
+ enum i2c_slave_event event, u8 *val)
+ {
+@@ -101,6 +114,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 +145,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 +228,12 @@ static struct i2c_driver i2c_slave_mqueue_driver = {
+ };
+ module_i2c_driver(i2c_slave_mqueue_driver);
+
++module_param_named(dump_debug, dump_debug, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(dump_debug, "debug flag for dump printing");
++module_param_named(dump_debug_bus_id, dump_debug_bus_id, int,
++ S_IRUGO | S_IWUSR);
++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..8c9d2dce0
--- /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,132 @@
+From 7baa65c9bf638265874838401e27a7b6179559ff 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 | 41 +++++++++++++++++++++++++++-----
+ include/dt-bindings/clock/aspeed-clock.h | 2 ++
+ 2 files changed, 37 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c
+index 5961367..3bbb4fb 100644
+--- a/drivers/clk/clk-aspeed.c
++++ b/drivers/clk/clk-aspeed.c
+@@ -14,7 +14,9 @@
+
+ #include <dt-bindings/clock/aspeed-clock.h>
+
+-#define ASPEED_NUM_CLKS 36
++#define ASPEED_NUM_CLKS ASPEED_CLK_MAX
++#define UART_HIGH_SPEED_CLK 192000000
++#define UART_LOW_SPEED_CLK 24000000
+
+ #define ASPEED_RESET2_OFFSET 32
+
+@@ -28,6 +30,12 @@
+ #define AST2400_HPLL_BYPASS_EN BIT(17)
+ #define ASPEED_MISC_CTRL 0x2c
+ #define UART_DIV13_EN BIT(12)
++#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)
+@@ -425,7 +433,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, uart_clock_div;
+ int i, ret;
+
+ map = syscon_node_to_regmap(dev->of_node);
+@@ -460,15 +468,23 @@ 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;
++ uart_clock_div = 13;
+ else
+- rate = 24000000;
++ uart_clock_div = 1;
++
+ /* TODO: Find the parent data for the uart clock */
+- hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate);
++ hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0,
++ UART_LOW_SPEED_CLK / uart_clock_div);
+ 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,
++ UART_HIGH_SPEED_CLK / uart_clock_div);
++ 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.
+@@ -534,9 +550,22 @@ static int aspeed_clk_probe(struct platform_device *pdev)
+ * Video Engine (ECLK) mux and clock divider
+ */
+
++ /* 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.
+@@ -544,7 +573,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 f437386..3358795 100644
+--- a/include/dt-bindings/clock/aspeed-clock.h
++++ b/include/dt-bindings/clock/aspeed-clock.h
+@@ -39,6 +39,8 @@
+ #define ASPEED_CLK_BCLK 33
+ #define ASPEED_CLK_MPLL 34
+ #define ASPEED_CLK_24M 35
++#define ASPEED_CLK_UART_HS 36
++#define ASPEED_CLK_MAX 37
+
+ #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..e015f2fd9
--- /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,556 @@
+From 37b192b278d5ea5da62b2fcff4fce7cf372e4fe6 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>
+---
+ .../ABI/stable/sysfs-driver-aspeed-uart-routing | 14 +
+ Documentation/misc-devices/aspeed-uart-routing.txt | 49 +++
+ arch/arm/boot/dts/aspeed-bmc-intel-purley.dts | 4 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 6 +
+ drivers/misc/Kconfig | 6 +
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-uart-routing.c | 383 +++++++++++++++++++++
+ 7 files changed, 463 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..afaf17cb7eda
+--- /dev/null
++++ b/Documentation/misc-devices/aspeed-uart-routing.txt
+@@ -0,0 +1,49 @@
++Kernel driver aspeed-uart-routing
++=================================
++
++Supported chips:
++ASPEED AST2500
++
++Author:
++Google LLC
++
++Description
++-----------
++
++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.
++
++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-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+index 8aba46cdce46..d184fdf6dda6 100644
+--- a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
++++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+@@ -227,6 +227,10 @@
+ status = "okay";
+ };
+
++&uart_routing {
++ status = "okay";
++};
++
+ &mac1 {
+ status = "okay";
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index adde826ac1d9..5606ac1d96d5 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -479,6 +479,12 @@
+ status = "disabled";
+ };
+ };
++
++ uart_routing: uart_routing@9c {
++ compatible = "aspeed,ast2500-uart-routing";
++ reg = <0x9c 0x4>;
++ status = "disabled";
++ };
+ };
+
+ peci: bus@1e78b000 {
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 8b1fcf741411..60f203c04b9b 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -560,6 +560,12 @@ config NPCM7XX_PCI_MBOX
+ Expose the NPCM750/730/715/705 PCI MBOX registers found on
+ Nuvoton SOCs to userspace.
+
++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.
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 89b051f82391..8f70b888a9ca 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/
+ obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
++obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
+ obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
+ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
+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..b819be69b
--- /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 9c509b9450f641c169ee3aeb60e398c43810dcb2 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 22eab8a952ed..004bbb08dd4a 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -101,14 +101,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>;
+@@ -117,6 +109,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 92843cc1a8f4..30a7f349feeb 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -142,14 +142,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>;
+@@ -158,6 +150,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..bb6465023
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
@@ -0,0 +1,252 @@
+From dae410353f8681b58907c61eb2eb056513d86f6d 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>
+---
+ .../devicetree/bindings/misc/vga-shared-memory.txt | 20 +++
+ drivers/misc/Kconfig | 10 ++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/aspeed-vga-sharedmem.c | 164 +++++++++++++++++++++
+ 4 files changed, 195 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/vga-shared-memory.txt
+ create mode 100644 drivers/misc/aspeed-vga-sharedmem.c
+
+diff --git a/Documentation/devicetree/bindings/misc/vga-shared-memory.txt b/Documentation/devicetree/bindings/misc/vga-shared-memory.txt
+new file mode 100644
+index 000000000000..03f57c53e844
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/vga-shared-memory.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/misc/Kconfig b/drivers/misc/Kconfig
+index 60f203c04b9b..2d4c6ba87e70 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -566,6 +566,16 @@ config ASPEED_UART_ROUTING
+ If you want to configure UART routing on Aspeed BMC platforms, enable
+ this option.
+
++config ASPEED_VGA_SHAREDMEM
++ tristate "Aspeed VGA Shared memory"
++ depends on (ARCH_ASPEED || COMPILE_TEST)
++ 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.
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 8f70b888a9ca..30ee065491ef 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -55,6 +55,7 @@ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpres
+ obj-$(CONFIG_CXL_BASE) += cxl/
+ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+ obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o
++obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o
+ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
+ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
+diff --git a/drivers/misc/aspeed-vga-sharedmem.c b/drivers/misc/aspeed-vga-sharedmem.c
+new file mode 100644
+index 000000000000..76f60cd67d3a
+--- /dev/null
++++ b/drivers/misc/aspeed-vga-sharedmem.c
+@@ -0,0 +1,164 @@
++// 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)
++{
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file);
++
++ 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;
++ u32 reg[2];
++ 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..3e8f86666
--- /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,510 @@
+From ef2e1d9d2e8c97daf806f4da74738a84de054116 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 | 437 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 448 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 8a7c4257b917..c24197232385 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -300,7 +300,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 a8f47df0655a..92a8fbebe2d9 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -170,6 +170,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 9c676a0dadf5..13b7b20ad5ab 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_IMX) += pwm-imx.o
+diff --git a/drivers/pwm/pwm-fttmr010.c b/drivers/pwm/pwm-fttmr010.c
+new file mode 100644
+index 000000000000..32e508c962dc
+--- /dev/null
++++ b/drivers/pwm/pwm-fttmr010.c
+@@ -0,0 +1,437 @@
++// 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);
++ ulong flags;
++ 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;
++ }
++
++ 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);
++ ulong flags;
++ 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;
++ }
++
++ 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;
++ }
++
++ 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 = chip->variant.chan_min; i < chip->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..1b86e9c04
--- /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,511 @@
+From 80ea6461d77e5b415d9f83fa2f4708fc21eab09b 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 | 99 ++++++++++++++++++++++++++++++++++-----
+ drivers/i2c/i2c-core-smbus.c | 17 ++++++-
+ 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, 233 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
+index 28460f6a60cc..009b0507768e 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1210,6 +1210,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;
+@@ -1291,6 +1310,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:
+@@ -1511,6 +1533,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));
+@@ -1860,7 +1884,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;
+ unsigned long orig_jiffies;
++ unsigned long timeout;
+ int ret, try;
+
+ if (WARN_ON(!msgs || num < 1))
+@@ -1869,6 +1895,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
+@@ -1901,6 +1946,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);
+@@ -1919,6 +1967,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) {
+@@ -1942,19 +1991,47 @@ 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).
+ */
+- if (in_atomic() || irqs_disabled()) {
+- ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
+- if (!ret)
+- /* I2C activity is ongoing. */
+- return -EAGAIN;
+- } else {
+- i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+- }
+
+- ret = __i2c_transfer(adap, msgs, num);
+- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
++ if (adap->algo->master_xfer) {
++#ifdef DEBUG
++ for (ret = 0; ret < num; ret++) {
++ dev_dbg(&adap->dev,
++ "master_xfer[%d] %c, addr=0x%02x, len=%d%s\n",
++ ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W',
++ msgs[ret].addr, msgs[ret].len,
++ (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
++ }
++#endif
++ /*
++ * 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) {
++ if (in_atomic() || irqs_disabled()) {
++ ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
++ if (!ret)
++ /* I2C activity is ongoing. */
++ return -EAGAIN;
++ } else {
++ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
++ }
++ }
+
+- return ret;
++ ret = __i2c_transfer(adap, msgs, num);
++ if (do_bus_lock)
++ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
++
++ return ret;
++ } else {
++ dev_dbg(&adap->dev, "I2C level transfers not supported\n");
++ return -EOPNOTSUPP;
++ }
+ }
+ EXPORT_SYMBOL(i2c_transfer);
+
+diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
+index 9cd66cabb84f..64c58911bf21 100644
+--- a/drivers/i2c/i2c-core-smbus.c
++++ b/drivers/i2c/i2c-core-smbus.c
+@@ -528,12 +528,25 @@ 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;
+
+- i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
++ /*
++ * 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)
++ i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
+ 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 f330690b4125..4d8909a0f90a 100644
+--- a/drivers/i2c/i2c-mux.c
++++ b/drivers/i2c/i2c-mux.c
+@@ -26,6 +26,7 @@
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/slab.h>
++#include <linux/timer.h>
+
+ /* multiplexer per channel data */
+ struct i2c_mux_priv {
+@@ -35,21 +36,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;
+ }
+@@ -60,15 +97,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;
+ }
+@@ -81,16 +135,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;
+ }
+@@ -103,16 +174,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);
+@@ -435,6 +526,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 bd74d5706f3b..bc6f778eaf9d 100644
+--- a/include/linux/i2c-mux.h
++++ b/include/linux/i2c-mux.h
+@@ -41,6 +41,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 65b4eaed1d96..eadde70c0d4a 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -692,6 +692,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)
+
+@@ -949,4 +956,22 @@ static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
+ }
+ #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/0041-Enable-passthrough-based-gpio-character-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch
new file mode 100644
index 000000000..7a4b090ec
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch
@@ -0,0 +1,287 @@
+From 554bc7a7c7aa6e0c0ec49a24063102e17954d06c Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Thu, 31 Jan 2019 17:47:39 +0800
+Subject: [PATCH] Enable passthrough based gpio character device.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ drivers/gpio/gpio-aspeed.c | 47 ++++++++++++++++++++++++++++--
+ drivers/gpio/gpiolib.c | 51 +++++++++++++++++++++++++++++++--
+ drivers/gpio/gpiolib.h | 1 +
+ include/linux/gpio/consumer.h | 9 ++++++
+ include/linux/pinctrl/pinconf-generic.h | 2 ++
+ include/uapi/linux/gpio.h | 1 +
+ 6 files changed, 106 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
+index 854bce4fb9e7..5f1bce3a9274 100644
+--- a/drivers/gpio/gpio-aspeed.c
++++ b/drivers/gpio/gpio-aspeed.c
+@@ -17,9 +17,11 @@
+ #include <linux/init.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
+
+@@ -58,6 +60,7 @@ struct aspeed_gpio {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ void __iomem *base;
++ struct regmap *scu;
+ int irq;
+ const struct aspeed_gpio_config *config;
+
+@@ -91,6 +94,13 @@ struct aspeed_gpio_bank {
+ * and thus can be used to read back what was last written
+ * reliably.
+ */
++#define SCU8C 0x8C /* Multi-function Pin Control #4 */
++#define PASS_THROUGH1 32
++#define PASS_THROUGH2 34
++#define PASS_THROUGH2_MASK 0x2000
++#define PASS_THROUGH1_MASK 0x1000
++#define PASS_THROUGH2_ON 0x2000
++#define PASS_THROUGH1_ON 0x1000
+
+ static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
+
+@@ -988,12 +998,38 @@ static int set_debounce(struct gpio_chip *chip, unsigned int offset,
+ return disable_debounce(chip, offset);
+ }
+
++static int aspeed_gpio_pass_through(struct gpio_chip *chip, unsigned int offset,
++ unsigned long param)
++{
++ struct aspeed_gpio *gpio = gpiochip_get_data(chip);
++ u32 value;
++
++ if (!gpio->scu)
++ return -ENOTSUPP;
++ if (param == PIN_CONFIG_PASS_THROUGH_ENABLE){
++ if (offset == PASS_THROUGH2){
++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH2_MASK, PASS_THROUGH2_ON);
++ } else if (offset == PASS_THROUGH1){
++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH1_MASK, PASS_THROUGH1_ON);
++ }
++ } else if (param == PIN_CONFIG_PASS_THROUGH_DISABLE){
++ if (offset == PASS_THROUGH2){
++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH2_MASK, ~(PASS_THROUGH2_ON));
++ } else if (offset == PASS_THROUGH1){
++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH1_MASK, ~(PASS_THROUGH1_ON));
++ }
++ } else {
++ return -ENOTSUPP;
++ }
++
++ return 0;
++}
++
+ static int aspeed_gpio_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_INPUT_DEBOUNCE)
+ return set_debounce(chip, offset, arg);
+ else if (param == PIN_CONFIG_BIAS_DISABLE ||
+@@ -1006,6 +1042,9 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ return -ENOTSUPP;
+ else if (param == PIN_CONFIG_PERSIST_STATE)
+ return aspeed_gpio_reset_tolerance(chip, offset, arg);
++ else if (param == PIN_CONFIG_PASS_THROUGH_ENABLE ||
++ param == PIN_CONFIG_PASS_THROUGH_DISABLE)
++ return aspeed_gpio_pass_through(chip, offset, param);
+
+ return -ENOTSUPP;
+ }
+@@ -1167,7 +1206,11 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
+ gpio->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(gpio->base))
+ return PTR_ERR(gpio->base);
+-
++ gpio->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2500-scu");
++ if (IS_ERR(gpio->scu)) {
++ dev_err(&pdev->dev, "Failed to find SCU regmap\n");
++ gpio->scu = NULL;
++ }
+ spin_lock_init(&gpio->lock);
+
+ gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index d1adfdf50fb3..4f9fdd25c6d7 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -428,6 +428,7 @@ struct linehandle_state {
+ GPIOHANDLE_REQUEST_OUTPUT | \
+ GPIOHANDLE_REQUEST_ACTIVE_LOW | \
+ GPIOHANDLE_REQUEST_OPEN_DRAIN | \
++ GPIOHANDLE_REQUEST_PASS_THROUGH | \
+ GPIOHANDLE_REQUEST_OPEN_SOURCE)
+
+ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
+@@ -530,7 +531,6 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+ return -EINVAL;
+
+ lflags = handlereq.flags;
+-
+ /* Return an error if an unknown flag is set */
+ if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
+ return -EINVAL;
+@@ -590,6 +590,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+ set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
++ if (lflags & GPIOHANDLE_REQUEST_PASS_THROUGH)
++ set_bit(FLAG_PASS_THROUGH, &desc->flags);
+
+ ret = gpiod_set_transitory(desc, false);
+ if (ret < 0)
+@@ -609,6 +611,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+ ret = gpiod_direction_input(desc);
+ if (ret)
+ goto out_free_descs;
++ } else if (lflags & GPIOHANDLE_REQUEST_PASS_THROUGH) {
++ int val = !!handlereq.default_values[i];
++ ret = gpiod_direction_pass_through(desc, val);
++ if (ret)
++ goto out_free_descs;
+ }
+ dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
+ offset);
+@@ -1027,7 +1034,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ struct gpio_device *gdev = filp->private_data;
+ struct gpio_chip *chip = gdev->chip;
+ void __user *ip = (void __user *)arg;
+-
+ /* We fail any subsequent ioctl():s when the chip is gone */
+ if (!chip)
+ return -ENODEV;
+@@ -1035,7 +1041,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ /* Fill in the struct and pass to userspace */
+ if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
+ struct gpiochip_info chipinfo;
+-
+ memset(&chipinfo, 0, sizeof(chipinfo));
+
+ strncpy(chipinfo.name, dev_name(&gdev->dev),
+@@ -2709,6 +2714,46 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
+ EXPORT_SYMBOL_GPL(gpiod_direction_output);
+
+ /**
++ * gpiod_direction_pass_through - set the GPIO direction to pass-through
++ * @desc: GPIO to set to pass-through
++ *
++ * Set the direction of the passed GPIO to passthrough.
++ *
++ * Return 0 in case of success, else an error code.
++ */
++int gpiod_direction_pass_through(struct gpio_desc *desc, int val)
++{
++ struct gpio_chip *gc;
++
++ VALIDATE_DESC(desc);
++ /* GPIOs used for IRQs shall not be set as pass-through */
++ if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
++ gpiod_err(desc,
++ "%s: tried to set a GPIO tied to an IRQ as pass-through\n",
++ __func__);
++ return -EIO;
++ }
++ gc = desc->gdev->chip;
++ val = !!val;
++ if (test_bit(FLAG_PASS_THROUGH, &desc->flags)) {
++ if (val)
++ gpio_set_config(gc, gpio_chip_hwgpio(desc),
++ PIN_CONFIG_PASS_THROUGH_ENABLE);
++ else
++ gpio_set_config(gc, gpio_chip_hwgpio(desc),
++ PIN_CONFIG_PASS_THROUGH_DISABLE);
++ } else {
++ gpiod_err(desc,
++ "%s: desc->flags is not set to FLAG_PASS_THROUGH\n",
++ __func__);
++ return -EIO;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(gpiod_direction_pass_through);
++
++/**
+ * gpiod_set_debounce - sets @debounce time for a GPIO
+ * @desc: descriptor of the GPIO for which to set debounce time
+ * @debounce: debounce time in microseconds
+diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
+index bc57f0dc5953..a821a04fc04b 100644
+--- a/drivers/gpio/gpiolib.h
++++ b/drivers/gpio/gpiolib.h
+@@ -212,6 +212,7 @@ struct gpio_desc {
+ #define FLAG_IS_OUT 1
+ #define FLAG_EXPORT 2 /* protected by sysfs_lock */
+ #define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
++#define FLAG_PASS_THROUGH 4 /*Gpio is passthrough type*/
+ #define FLAG_ACTIVE_LOW 6 /* value has active low */
+ #define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
+ #define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
+diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
+index 9ddcf50a3c59..f9775be5a46a 100644
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -110,6 +110,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
+ int gpiod_get_direction(struct gpio_desc *desc);
+ int gpiod_direction_input(struct gpio_desc *desc);
+ int gpiod_direction_output(struct gpio_desc *desc, int value);
++int gpiod_direction_pass_through(struct gpio_desc *desc, int val);
+ int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
+
+ /* Value get/set from non-sleeping context */
+@@ -348,6 +349,14 @@ static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
+ WARN_ON(1);
+ return -ENOSYS;
+ }
++
++static inline int gpiod_direction_pass_through(struct gpio_desc *desc, int val)
++{
++ /* GPIO can never have been requested */
++ WARN_ON(1);
++ return -ENOSYS;
++}
++
+ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
+ {
+ /* GPIO can never have been requested */
+diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
+index 6c0680641108..59f0cbabb685 100644
+--- a/include/linux/pinctrl/pinconf-generic.h
++++ b/include/linux/pinctrl/pinconf-generic.h
+@@ -124,6 +124,8 @@ enum pin_config_param {
+ PIN_CONFIG_SLEW_RATE,
+ PIN_CONFIG_SKEW_DELAY,
+ PIN_CONFIG_PERSIST_STATE,
++ PIN_CONFIG_PASS_THROUGH_ENABLE,
++ PIN_CONFIG_PASS_THROUGH_DISABLE,
+ PIN_CONFIG_END = 0x7F,
+ PIN_CONFIG_MAX = 0xFF,
+ };
+diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h
+index 4ebfe0ac6c5b..99864572b7d9 100644
+--- a/include/uapi/linux/gpio.h
++++ b/include/uapi/linux/gpio.h
+@@ -62,6 +62,7 @@ struct gpioline_info {
+ #define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2)
+ #define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3)
+ #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4)
++#define GPIOHANDLE_REQUEST_PASS_THROUGH (1UL << 5)
+
+ /**
+ * struct gpiohandle_request - Information about a GPIO handle request
+--
+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..3588d62d9
--- /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 6515a2134f90f33dbbea8ede5de598d17bb00c12 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 506d867b43d9..84237c5d0aca 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -1012,7 +1012,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 009b0507768e..386aa2dad908 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1231,6 +1231,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 */
+@@ -1257,8 +1258,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..f04824c0e
--- /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,140 @@
+From d82aacea62f2cc3f5c4f6654bd8920255edf24fd 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>
+---
+ .../bindings/ipmi/aspeed,ast2400-ibt-bmc.txt | 3 +++
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ drivers/char/ipmi/bt-bmc.c | 24 +++++++++++++++++++++-
+ 4 files changed, 28 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 6e6f50a0fbab..3a7e31f3de07 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -333,6 +333,7 @@
+ ibt: ibt@c0 {
+ compatible = "aspeed,ast2400-ibt-bmc";
+ reg = <0xc0 0x18>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
+ };
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index 4cd4a8258e42..a6720bc952b0 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -468,6 +468,7 @@
+ ibt: ibt@c0 {
+ compatible = "aspeed,ast2500-ibt-bmc";
+ reg = <0xc0 0x18>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
+ };
+
+diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
+index 40b9927c072c..a4ec9d1743d7 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..0559ef5be
--- /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,125 @@
+From 1ebca05f5cb04162e124e59cac701291f23d9091 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>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ drivers/misc/aspeed-lpc-snoop.c | 30 +++++++++++++++++++++++++++---
+ 3 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 3a7e31f3de07..bedfb77c0158 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -316,6 +316,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 a6720bc952b0..a26e8b3c09bf 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -451,6 +451,7 @@
+ compatible = "aspeed,ast2500-lpc-snoop";
+ reg = <0x0 0x80>;
+ interrupts = <8>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/misc/aspeed-lpc-snoop.c
+index 2feb4347d67f..39a0471f0b8f 100644
+--- a/drivers/misc/aspeed-lpc-snoop.c
++++ b/drivers/misc/aspeed-lpc-snoop.c
+@@ -15,6 +15,7 @@
+ */
+
+ #include <linux/bitops.h>
++#include <linux/clk.h>
+ #include <linux/interrupt.h>
+ #include <linux/fs.h>
+ #include <linux/kfifo.h>
+@@ -71,6 +72,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];
+ };
+
+@@ -286,22 +288,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;
+ }
+
+@@ -313,6 +335,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..d9b6d05f9
--- /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,235 @@
+From 1326920183042bb91583eb56dabd29ec921f8f65 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>
+---
+ .../devicetree/bindings/ipmi/aspeed-kcs-bmc.txt | 3 ++
+ arch/arm/boot/dts/aspeed-g4.dtsi | 35 ++++++++++++++++++++
+ arch/arm/boot/dts/aspeed-g5.dtsi | 6 +++-
+ drivers/char/ipmi/kcs_bmc_aspeed.c | 37 ++++++++++++++++++----
+ 4 files changed, 73 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 bedfb77c0158..a5072ed1f823 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -294,6 +294,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 {
+@@ -305,6 +332,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 a26e8b3c09bf..6a2f161e7548 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -128,7 +128,7 @@
+ };
+
+ vic: interrupt-controller@1e6c0080 {
+- compatible = "aspeed,ast2400-vic";
++ compatible = "aspeed,ast2500-vic";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ valid-sources = <0xfefff7ff 0x0807ffff>;
+@@ -408,18 +408,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";
+ };
+ };
+@@ -437,6 +440,7 @@
+ compatible = "aspeed,ast2500-kcs-bmc";
+ interrupts = <8>;
+ kcs_chan = <4>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+
+diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c
+index 3c955946e647..bd1912dc5a21 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/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch
new file mode 100644
index 000000000..220283e24
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch
@@ -0,0 +1,166 @@
+From db310b43e5b444a4e2854f3d69d002c2f0d0605c Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 13 Mar 2019 15:53:24 -0700
+Subject: [PATCH] misc: Add clock control logic into Aspeed LPC MBOX driver
+
+If LPC MBOX driver is registered ahead of lpc-ctrl module, LPC
+MBOX 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
+MBOX driver.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ drivers/misc/aspeed-lpc-mbox.c | 42 +++++++++++++++++++++++++++++++---------
+ 3 files changed, 35 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index a5072ed1f823..729245b74c13 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -389,6 +389,7 @@
+ 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 6a2f161e7548..df9d63a94264 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -493,6 +493,7 @@
+ reg = <0x180 0x5c>;
+ interrupts = <46>;
+ #mbox-cells = <1>;
++ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ status = "disabled";
+ };
+ };
+diff --git a/drivers/misc/aspeed-lpc-mbox.c b/drivers/misc/aspeed-lpc-mbox.c
+index 0933e0553953..f105d27786ac 100644
+--- a/drivers/misc/aspeed-lpc-mbox.c
++++ b/drivers/misc/aspeed-lpc-mbox.c
+@@ -7,6 +7,7 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/clk.h>
+ #include <linux/interrupt.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/miscdevice.h>
+@@ -37,7 +38,9 @@
+ 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;
+ };
+@@ -237,16 +240,16 @@ static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox,
+ struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+- int rc, irq;
++ int rc;
+
+- irq = irq_of_parse_and_map(dev->of_node, 0);
+- if (!irq)
++ mbox->irq = platform_get_irq(pdev, 0);
++ if (!mbox->irq)
+ return -ENODEV;
+
+- rc = devm_request_irq(dev, irq, aspeed_mbox_irq,
+- IRQF_SHARED, DEVICE_NAME, mbox);
++ 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", irq);
++ dev_err(dev, "Unable to request IRQ %d\n", mbox->irq);
+ return rc;
+ }
+
+@@ -301,6 +304,19 @@ static int aspeed_mbox_probe(struct platform_device *pdev)
+ 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;
+@@ -308,17 +324,24 @@ static int aspeed_mbox_probe(struct platform_device *pdev)
+ rc = misc_register(&mbox->miscdev);
+ if (rc) {
+ dev_err(dev, "Unable to register device\n");
+- return rc;
++ goto err;
+ }
+
+ rc = aspeed_mbox_config_irq(mbox, pdev);
+ if (rc) {
+ dev_err(dev, "Failed to configure IRQ\n");
+ misc_deregister(&mbox->miscdev);
+- return rc;
++ 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)
+@@ -326,6 +349,7 @@ 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;
+ }
+@@ -335,6 +359,7 @@ static const struct of_device_id aspeed_mbox_match[] = {
+ { .compatible = "aspeed,ast2500-mbox" },
+ { },
+ };
++MODULE_DEVICE_TABLE(of, aspeed_mbox_match);
+
+ static struct platform_driver aspeed_mbox_driver = {
+ .driver = {
+@@ -347,7 +372,6 @@ static struct platform_driver aspeed_mbox_driver = {
+
+ module_platform_driver(aspeed_mbox_driver);
+
+-MODULE_DEVICE_TABLE(of, aspeed_mbox_match);
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Cyril Bur <cyrilbur@gmail.com>");
+ MODULE_DESCRIPTION("Aspeed mailbox device driver");
+--
+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..40c26e31b
--- /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 4762687044ec864719ca14d8efa3dccdc3807e70 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/misc/aspeed-lpc-ctrl.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/aspeed-lpc-ctrl.c b/drivers/misc/aspeed-lpc-ctrl.c
+index a024f8042259..c0818c7b0ffb 100644
+--- a/drivers/misc/aspeed-lpc-ctrl.c
++++ b/drivers/misc/aspeed-lpc-ctrl.c
+@@ -239,8 +239,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) {
+@@ -264,6 +266,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/0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.patch
new file mode 100644
index 000000000..efbea1be8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.patch
@@ -0,0 +1,40 @@
+From abf63c03805bf7df31133b720e165eab759ea702 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Thu, 14 Mar 2019 13:11:49 -0700
+Subject: [PATCH] ARM: dts: aspeed: Set default status of LPC BT as 'disabled'
+
+LPC BT is not widely used so set its default status as 'disabled'.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 1 +
+ arch/arm/boot/dts/aspeed-g5.dtsi | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 729245b74c13..d4e1e29c6ed2 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -371,6 +371,7 @@
+ reg = <0xc0 0x18>;
+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
++ status = "disabled";
+ };
+
+ sio_regs: regs {
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index df9d63a94264..a3850644b10e 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -475,6 +475,7 @@
+ reg = <0xc0 0x18>;
+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
+ interrupts = <8>;
++ status = "disabled";
+ };
+
+ sio_regs: regs {
+--
+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..d0f98b9c1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch
@@ -0,0 +1,43 @@
+From 7dd0a7c62e5885bb726ef2bd5007e79a50932c38 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 | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
+index f3816a5c861e..3a94584a9dbc 100644
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -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..d66facdfa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch
@@ -0,0 +1,35 @@
+From a2e0020ef6e03abde6819fb7fc328dcf23d0bd71 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 AST2500d JTAG driver
+
+Adding aspeed jtag device
+
+Signed-off-by: Hunt, Bryan <bryan.hunt@intel.com>
+---
+ arch/arm/boot/dts/aspeed-g5.dtsi | 9 +
+ 1 files changed, 15 insertions(+)
+
+diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
+index bf7ae631a458..2c9f287759ce 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -366,6 +366,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>;
+--
+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..6c9d46d9d
--- /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 0b8b93851bb79e70e91159f310afd4b56084977f 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 4f9f990..0102bae 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -228,4 +228,5 @@ source "drivers/siox/Kconfig"
+
+ source "drivers/slimbus/Kconfig"
+
++source "drivers/jtag/Kconfig"
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index e1ce029..6d756c2 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/
+ obj-$(CONFIG_SIOX) += siox/
+ obj-$(CONFIG_GNSS) += gnss/
+ obj-$(CONFIG_PECI) += peci/
++obj-$(CONFIG_JTAG) += jtag/
+diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig
+new file mode 100644
+index 0000000..47771fc
+--- /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 0000000..af37493
+--- /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 0000000..47503a1
+--- /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 0000000..4153c90
+--- /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 0000000..3f9e195
+--- /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..94722d6c4
--- /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,1294 @@
+From 817a43d1b1e197e7eff43492599469bbc23bf0fd Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Mon, 3 Jun 2019 08:22:09 -0800
+Subject: [PATCH v29 2/6] Add Aspeed SoC 24xx and 25xx families JTAG master
+ driver
+
+Driver adds support of Aspeed 2500/2400 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.
+
+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>
+---
+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 | 1050 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1065 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..1d41a66
+--- /dev/null
++++ b/drivers/jtag/jtag-aspeed.c
+@@ -0,0 +1,1050 @@
++// 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 */
++#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_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_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
++
++/*#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",
++};
++
++#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;
++};
++
++/*
++ * 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(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(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_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_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_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 int aspeed_jtag_probe(struct platform_device *pdev)
++{
++ struct aspeed_jtag *aspeed_jtag;
++ struct jtag *jtag;
++ int err;
++
++ jtag = jtag_alloc(&pdev->dev, sizeof(*aspeed_jtag), &aspeed_jtag_ops);
++ if (!jtag)
++ return -ENOMEM;
++
++ platform_set_drvdata(pdev, jtag);
++ aspeed_jtag = jtag_priv(jtag);
++ aspeed_jtag->dev = &pdev->dev;
++
++ /* 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 const struct of_device_id aspeed_jtag_of_match[] = {
++ { .compatible = "aspeed,ast2400-jtag", },
++ { .compatible = "aspeed,ast2500-jtag", },
++ {}
++};
++
++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..f17bdcd68
--- /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,108 @@
+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 v29 3/6] Documentation: jtag: Add bindings for Aspeed SoC
+ 24xx and 25xx families JTAG master driver
+
+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..b91311d94
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch
@@ -0,0 +1,309 @@
+From c2d57900820475b50affd171f4dc423a278887ae Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Wed, 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 0000000..423baab
+--- /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 0000000..6a5ec33
+--- /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 0000000..76fd0b1
+--- /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..a7dccc4b6
--- /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 ba0c35ae070cffcb384fc76e23a38e00142b128d Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Wed, 10 Mar 2019 11:48:18 -0800
+Subject: [PATCH v29 5/6] 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.txt | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
+index c955814..f732118 100644
+--- a/Documentation/ioctl/ioctl-number.txt
++++ b/Documentation/ioctl/ioctl-number.txt
+@@ -323,6 +323,8 @@ Code Seq#(hex) Include File Comments
+ 0xB0 all RATIO devices in development:
+ <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..8ab4615f0
--- /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 0a563429bc3c34a951db92600681e799b606a01f Mon Sep 17 00:00:00 2001
+From: "Corona, Ernesto" <ernesto.corona@intel.com>
+Date: Wed, 10 Mar 2019 11:49:37 -0800
+Subject: [PATCH v29 6/6] 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 dce5c09..eb710a6 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -8173,6 +8173,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/0058-i2c-aspeed-add-general-call-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0058-i2c-aspeed-add-general-call-support.patch
new file mode 100644
index 000000000..de8bf2355
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0058-i2c-aspeed-add-general-call-support.patch
@@ -0,0 +1,182 @@
+From 551b5192b1074679ca9411cdedb9137d38f7de3d 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 7da7e813b2b0..724ee9f35c10 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+@@ -16,6 +16,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 0060193e1aa4..f96160e01a69 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -50,6 +50,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)
+
+@@ -74,6 +75,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)
+@@ -133,6 +135,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,
+ };
+
+@@ -163,6 +167,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 */
+ };
+
+@@ -267,6 +273,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;
+@@ -285,6 +297,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;
+ }
+@@ -324,6 +351,10 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &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_WRITE_RECEIVED:
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
+ break;
+@@ -332,6 +363,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ 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:
+@@ -739,6 +771,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);
+ }
+
+@@ -777,6 +811,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;
+@@ -921,6 +957,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 4548088e1922..a608846cb1db 100644
+--- a/drivers/i2c/i2c-slave-mqueue.c
++++ b/drivers/i2c/i2c-slave-mqueue.c
+@@ -53,10 +53,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 e1c6b78bdaf1..03ffb70d75f2 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -371,6 +371,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/0065-i2c-aspeed-fix-master-pending-state-handling.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0065-i2c-aspeed-fix-master-pending-state-handling.patch
new file mode 100644
index 000000000..3a86d5b25
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0065-i2c-aspeed-fix-master-pending-state-handling.patch
@@ -0,0 +1,55 @@
+From 50221ac92816333efcf961c5f22f8b9ffdccb31b Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 11 Jun 2019 14:59:53 -0700
+Subject: [PATCH] i2c: aspeed: fix master pending state handling
+
+In case of a master pending state, it should not trigger the master
+command because this H/W is sharing the same byte buffer for slave
+and master operation, so this commit fixes the issue with making
+the master command triggering happens when the state goes to active
+state.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/i2c/busses/i2c-aspeed.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index f96160e01a69..64bc68eaa88f 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -384,18 +384,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
+ u8 slave_addr = i2c_8bit_addr_from_msg(msg);
+
+- bus->master_state = ASPEED_I2C_MASTER_START;
+-
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /*
+ * If it's requested in the middle of a slave session, set the master
+ * state to 'pending' then H/W will continue handling this master
+ * command when the bus comes back to the idle state.
+ */
+- if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE)
++ if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) {
+ bus->master_state = ASPEED_I2C_MASTER_PENDING;
++ return;
++ }
+ #endif /* CONFIG_I2C_SLAVE */
+
++ bus->master_state = ASPEED_I2C_MASTER_START;
+ bus->buf_index = 0;
+
+ if (msg->flags & I2C_M_RD) {
+@@ -480,7 +481,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE)
+ goto out_no_complete;
+
+- bus->master_state = ASPEED_I2C_MASTER_START;
++ aspeed_i2c_do_start(bus);
+ }
+ #endif /* CONFIG_I2C_SLAVE */
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0066-i2c-aspeed-add-buffer-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0066-i2c-aspeed-add-buffer-mode-transfer-support.patch
new file mode 100644
index 000000000..9480daeff
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0066-i2c-aspeed-add-buffer-mode-transfer-support.patch
@@ -0,0 +1,770 @@
+From efb710a6b3a39f28b988af717eefc1b72c4c43bd 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 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>
+---
+ arch/arm/boot/dts/aspeed-g4.dtsi | 42 ++++--
+ arch/arm/boot/dts/aspeed-g5.dtsi | 42 ++++--
+ drivers/i2c/busses/i2c-aspeed.c | 262 ++++++++++++++++++++++++++++++++----
+ drivers/irqchip/irq-aspeed-i2c-ic.c | 8 ++
+ 4 files changed, 301 insertions(+), 53 deletions(-)
+
+diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
+index 47a5029f5bdb..c1c125add9fa 100644
+--- a/arch/arm/boot/dts/aspeed-g4.dtsi
++++ b/arch/arm/boot/dts/aspeed-g4.dtsi
+@@ -482,7 +482,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x40 0x40>;
++ reg = <0x40 0x40>, <0x800 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -498,7 +499,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x80 0x40>;
++ reg = <0x80 0x40>, <0x880 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -514,7 +516,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0xc0 0x40>;
++ reg = <0xc0 0x40>, <0x900 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -531,7 +534,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x100 0x40>;
++ reg = <0x100 0x40>, <0x980 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -548,7 +552,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x140 0x40>;
++ reg = <0x140 0x40>, <0xa00 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -565,7 +570,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x180 0x40>;
++ reg = <0x180 0x40>, <0xa80 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -582,7 +588,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x1c0 0x40>;
++ reg = <0x1c0 0x40>, <0xb00 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -599,7 +606,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x300 0x40>;
++ reg = <0x300 0x40>, <0xb80 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -616,7 +624,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x340 0x40>;
++ reg = <0x340 0x40>, <0xc00 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -633,7 +642,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x380 0x40>;
++ reg = <0x380 0x40>, <0xc80 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -650,7 +660,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x3c0 0x40>;
++ reg = <0x3c0 0x40>, <0xd00 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -667,7 +678,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x400 0x40>;
++ reg = <0x400 0x40>, <0xd80 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -684,7 +696,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x440 0x40>;
++ reg = <0x440 0x40>, <0xe00 0x80>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2400-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -701,7 +714,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x480 0x40>;
++ reg = <0x480 0x40>, <0xe80 0x80>;
++ reg-names = "bus-regs", "buf";
+ 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 9d5ed9499b1f..662249bc15f9 100644
+--- a/arch/arm/boot/dts/aspeed-g5.dtsi
++++ b/arch/arm/boot/dts/aspeed-g5.dtsi
+@@ -599,7 +599,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x40 0x40>;
++ reg = <0x40 0x40>, <0x200 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -615,7 +616,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x80 0x40>;
++ reg = <0x80 0x40>, <0x210 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -631,7 +633,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0xc0 0x40>;
++ reg = <0xc0 0x40>, <0x220 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -648,7 +651,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x100 0x40>;
++ reg = <0x100 0x40>, <0x230 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -665,7 +669,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x140 0x40>;
++ reg = <0x140 0x40>, <0x240 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -682,7 +687,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x180 0x40>;
++ reg = <0x180 0x40>, <0x250 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -699,7 +705,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x1c0 0x40>;
++ reg = <0x1c0 0x40>, <0x260 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -716,7 +723,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x300 0x40>;
++ reg = <0x300 0x40>, <0x270 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -733,7 +741,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x340 0x40>;
++ reg = <0x340 0x40>, <0x280 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -750,7 +759,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x380 0x40>;
++ reg = <0x380 0x40>, <0x290 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -767,7 +777,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x3c0 0x40>;
++ reg = <0x3c0 0x40>, <0x2a0 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -784,7 +795,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x400 0x40>;
++ reg = <0x400 0x40>, <0x2b0 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -801,7 +813,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x440 0x40>;
++ reg = <0x440 0x40>, <0x2c0 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+@@ -818,7 +831,8 @@
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+- reg = <0x480 0x40>;
++ reg = <0x480 0x40>, <0x2d0 0x10>;
++ reg-names = "bus-regs", "buf";
+ compatible = "aspeed,ast2500-i2c-bus";
+ clocks = <&syscon ASPEED_CLK_APB>;
+ resets = <&syscon ASPEED_RESET_I2C>;
+diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
+index 64bc68eaa88f..b21a4c87853e 100644
+--- a/drivers/i2c/busses/i2c-aspeed.c
++++ b/drivers/i2c/busses/i2c-aspeed.c
+@@ -10,6 +10,7 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/completion.h>
+ #include <linux/err.h>
+@@ -38,6 +39,7 @@
+ #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 */
+@@ -46,6 +48,7 @@
+
+ /* 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)
+@@ -107,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)
+@@ -117,6 +122,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,
+@@ -164,6 +176,11 @@ struct aspeed_i2c_bus {
+ int master_xfer_result;
+ /* Multi-master */
+ bool multi_master;
++ /* Buffer/DMA mode */
++ void __iomem *buf_base;
++ size_t buf_size;
++ u8 buf_offset;
++ u8 buf_page;
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ struct i2c_client *slave;
+ enum aspeed_i2c_slave_state slave_state;
+@@ -260,6 +277,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ {
+ u32 command, irq_handled = 0;
+ struct i2c_client *slave = bus->slave;
++ int i, len;
+ u8 value;
+
+ if (!slave)
+@@ -288,7 +306,11 @@ 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;
++ if (bus->buf_base &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED)
++ value = readb(bus->buf_base);
++ else
++ value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ /* Handle address frame. */
+ if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
+ if (value & 0x1)
+@@ -318,6 +340,18 @@ 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) {
++ if (bus->buf_base &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED) {
++ 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(slave,
++ I2C_SLAVE_WRITE_RECEIVED,
++ &value);
++ }
++ }
+ irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;
+ bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+ }
+@@ -350,6 +384,15 @@ 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);
++ 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);
++ }
+ break;
+ case ASPEED_I2C_SLAVE_GCALL_REQUESTED:
+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
+@@ -357,6 +400,24 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ break;
+ case ASPEED_I2C_SLAVE_WRITE_RECEIVED:
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
++ 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(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);
++ }
+ break;
+ case ASPEED_I2C_SLAVE_STOP:
+ i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
+@@ -383,6 +444,8 @@ 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);
++ u8 wbuf[4];
++ int len;
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
+ /*
+@@ -401,12 +464,66 @@ 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 (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE |
++ ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ wbuf[0] = slave_addr;
++ writel(*(u32 *)wbuf, bus->buf_base);
++
++ if (msg->len > bus->buf_size) {
++ len = bus->buf_size;
++ } else {
++ len = msg->len;
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ 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 {
++ /* 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;
++ }
++ } else {
++ if (bus->buf_base) {
++ int i;
++
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++
++ if (msg->len + 1 > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len + 1;
++
++ 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));
++
++ bus->buf_index = len - 1;
++
++ 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(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
++ if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE))
++ writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
+ }
+
+@@ -441,12 +558,22 @@ static int aspeed_i2c_is_irq_error(u32 irq_status)
+ return 0;
+ }
+
++static inline int aspeed_i2c_is_tx_error(struct aspeed_i2c_bus *bus)
++{
++ if (FIELD_GET(ASPEED_I2CD_BUF_TX_COUNT_MASK,
++ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)) !=
++ bus->buf_size - 1)
++ return -EIO;
++
++ return 0;
++}
++
+ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ {
+ u32 irq_handled = 0, command = 0;
+ struct i2c_msg *msg;
+ u8 recv_byte;
+- int ret;
++ int ret, len;
+
+ if (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE) {
+ bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
+@@ -559,11 +686,46 @@ 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) {
++ if (bus->buf_base) {
++ u8 wbuf[4];
++ int i;
++
++ if (unlikely(aspeed_i2c_is_tx_error(bus)))
++ goto error_and_stop;
++
++ 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));
++
++ bus->buf_index += len;
++
++ 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(ASPEED_I2CD_TX_BUFF_ENABLE |
++ ASPEED_I2CD_M_TX_CMD,
++ bus->base + ASPEED_I2C_CMD_REG);
++ } else {
++ 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);
++ }
+ 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);
+ }
+@@ -580,25 +742,57 @@ 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) {
+- if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
+- bus->cmd_err = -EPROTO;
+- aspeed_i2c_do_stop(bus);
+- goto out_no_complete;
++ if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
++ 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;
++
++ if (msg->flags & I2C_M_RECV_LEN) {
++ 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->flags &= ~I2C_M_RECV_LEN;
+ }
+- msg->len = recv_byte +
+- ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1);
+- msg->flags &= ~I2C_M_RECV_LEN;
+ }
+
+ 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;
++ bus->master_state = ASPEED_I2C_MASTER_RX;
++ if (bus->buf_base) {
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ 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;
++ }
++
++ 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;
++ }
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
+ } else {
+ aspeed_i2c_next_msg_or_stop(bus);
+@@ -948,6 +1142,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
+@@ -1010,17 +1207,32 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ struct aspeed_i2c_bus *bus;
+ struct clk *parent_clk;
+ struct resource *res;
++ void __iomem *gc_reg;
+ int irq, ret;
+
+ bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bus-regs");
+ bus->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(bus->base))
+ return PTR_ERR(bus->base);
+
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "buf");
++ bus->buf_base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(bus->buf_base) || resource_size(res) < 2) {
++ bus->buf_base = NULL;
++ } else {
++ 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;
++ }
++ }
++
+ parent_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+diff --git a/drivers/irqchip/irq-aspeed-i2c-ic.c b/drivers/irqchip/irq-aspeed-i2c-ic.c
+index f20200af0992..99985b22a9fa 100644
+--- a/drivers/irqchip/irq-aspeed-i2c-ic.c
++++ b/drivers/irqchip/irq-aspeed-i2c-ic.c
+@@ -18,6 +18,9 @@
+ #include <linux/of_irq.h>
+ #include <linux/io.h>
+
++/* I2C Global Control Register (AST2500) */
++#define ASPEED_I2C_GLOBAL_CTRL_REG 0xc
++#define ASPEED_I2C_SRAM_BUFFER_EN BIT(0)
+
+ #define ASPEED_I2C_IC_NUM_BUS 14
+
+@@ -100,6 +103,11 @@ static int __init aspeed_i2c_ic_of_init(struct device_node *node,
+ irq_set_chained_handler_and_data(i2c_ic->parent_irq,
+ aspeed_i2c_ic_irq_handler, i2c_ic);
+
++ /* Enable I2C SRAM buffer in case of AST2500 */
++ if (of_device_is_compatible(node, "aspeed,ast2500-i2c-ic"))
++ writel(ASPEED_I2C_SRAM_BUFFER_EN,
++ i2c_ic->base + ASPEED_I2C_GLOBAL_CTRL_REG);
++
+ pr_info("i2c controller registered, irq %d\n", i2c_ic->parent_irq);
+
+ return 0;
+--
+2.7.4
+
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..41530dd6e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
@@ -0,0 +1 @@
+CONFIG_BLK_DEV_RAM=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..ed5be3455
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -0,0 +1,46 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+do_compile_prepend(){
+ # device tree compiler flags
+ export DTC_FLAGS=-@
+}
+
+SRC_URI += " \
+ file://intel.cfg \
+ file://0005-arm-dts-aspeed-g5-add-espi.patch \
+ file://0007-New-flash-map-for-intel.patch \
+ file://0008-Add-ASPEED-SGPIO-driver.patch \
+ file://0009-SGPIO-DT-and-pinctrl-fixup.patch \
+ file://0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch \
+ file://0019-Add-I2C-IPMB-support.patch \
+ file://0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch \
+ file://0022-Add-AST2500-eSPI-driver.patch \
+ file://0026-Add-support-for-new-PECI-commands.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://0041-Enable-passthrough-based-gpio-character-device.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://0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch \
+ file://0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch \
+ file://0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.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://0058-i2c-aspeed-add-general-call-support.patch \
+ file://0065-i2c-aspeed-fix-master-pending-state-handling.patch \
+ file://0066-i2c-aspeed-add-buffer-mode-transfer-support.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers/0001-Enable-passthrough-based-gpio-character-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers/0001-Enable-passthrough-based-gpio-character-device.patch
new file mode 100644
index 000000000..15e845ebc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers/0001-Enable-passthrough-based-gpio-character-device.patch
@@ -0,0 +1,26 @@
+From 61a5796d151337fd537d1aeb3fb072dcdf96abbe Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Sun, 3 Feb 2019 16:08:11 +0800
+Subject: [PATCH] Enable passthrough based gpio character device.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ include/uapi/linux/gpio.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h
+index 1bf6e6df..8883ca90 100644
+--- a/include/uapi/linux/gpio.h
++++ b/include/uapi/linux/gpio.h
+@@ -62,7 +62,7 @@ struct gpioline_info {
+ #define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2)
+ #define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3)
+ #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4)
+-
++#define GPIOHANDLE_REQUEST_PASS_THROUGH (1UL << 5)
+ /**
+ * struct gpiohandle_request - Information about a GPIO handle request
+ * @lineoffsets: an array desired lines, specified by offset index for the
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers_%.bbappend
new file mode 100644
index 000000000..703af71df
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-libc-headers_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += " \
+ file://0001-Enable-passthrough-based-gpio-character-device.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0002-IPv6-Network-changes-to-configuration-file.patch b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0002-IPv6-Network-changes-to-configuration-file.patch
new file mode 100644
index 000000000..b46702902
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0002-IPv6-Network-changes-to-configuration-file.patch
@@ -0,0 +1,208 @@
+From 53dbefc9f31dcfca06d7c7705ea3dcfc5e93ae72 Mon Sep 17 00:00:00 2001
+From: David Cobbley <david.j.cobbley@linux.intel.com>
+Date: Wed, 6 Jun 2018 11:11:43 -0700
+Subject: [PATCH 1/2] IPv6 Network changes to configuration file
+
+Allow Additional parameters to be set for IPv6
+
+Change-Id: If662f1ce2d265bc525073890c49231bf6f2b8a30
+---
+ ethernet_interface.cpp | 109 +++++++++++++++++++++++++++++++++++++++--
+ ethernet_interface.hpp | 17 +++++++
+ util.cpp | 3 +-
+ 3 files changed, 123 insertions(+), 6 deletions(-)
+
+diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
+index 154efcb..aa1c895 100644
+--- a/ethernet_interface.cpp
++++ b/ethernet_interface.cpp
+@@ -46,6 +46,8 @@ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ std::replace(intfName.begin(), intfName.end(), '_', '.');
+ interfaceName(intfName);
+ EthernetInterfaceIntf::dHCPEnabled(dhcpEnabled);
++ EthernetInterfaceIntf::iPAddressEnables(getIPAddressEnablesFromConf());
++ EthernetInterfaceIntf::iPv6AcceptRA(getIPv6AcceptRAFromConf());
+ MacAddressIntf::mACAddress(getMACAddress(intfName));
+ EthernetInterfaceIntf::nTPServers(getNTPServersFromConf());
+ EthernetInterfaceIntf::nameservers(getNameServerFromConf());
+@@ -329,7 +331,16 @@ std::string EthernetInterface::generateObjectPath(
+ objectPath /= generateId(ipaddress, prefixLength, gateway);
+ return objectPath.string();
+ }
+-
++bool EthernetInterface::iPv6AcceptRA(bool value)
++{
++ if (value == EthernetInterfaceIntf::iPv6AcceptRA())
++ {
++ return value;
++ }
++ EthernetInterfaceIntf::iPv6AcceptRA(value);
++ manager.writeToConfigurationFile();
++ return value;
++}
+ bool EthernetInterface::dHCPEnabled(bool value)
+ {
+ if (value == EthernetInterfaceIntf::dHCPEnabled())
+@@ -442,7 +453,80 @@ ObjectPath EthernetInterface::createVLAN(VlanId id)
+
+ return path;
+ }
++bool EthernetInterface::getIPv6AcceptRAFromConf()
++{
++ fs::path confPath = manager.getConfDir();
++
++ std::string fileName = systemd::config::networkFilePrefix +
++ interfaceName() + systemd::config::networkFileSuffix;
++ confPath /= fileName;
++ config::ValueList values;
++ config::Parser parser(confPath.string());
++ auto rc = config::ReturnCode::SUCCESS;
++ std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
++ if (rc != config::ReturnCode::SUCCESS)
++ {
++ log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
++ entry("rc=%d", rc));
++ return false;
++ }
++ if (values[0] == "true")
++ {
++ return true;
++ }
++
++ return false;
++}
++EthernetInterface::IPAllowed EthernetInterface::getIPAddressEnablesFromConf()
++{
++ fs::path confPath = manager.getConfDir();
++
++ std::string fileName = systemd::config::networkFilePrefix +
++ interfaceName() + systemd::config::networkFileSuffix;
++ confPath /= fileName;
++ config::ValueList values;
++ config::Parser parser(confPath.string());
++ auto rc = config::ReturnCode::SUCCESS;
++ std::tie(rc, values) = parser.getValues("Network", "DHCP");
++ if (rc != config::ReturnCode::SUCCESS)
++ {
++ log<level::DEBUG>("Unable to get the value for Network[DHCP]",
++ entry("rc=%d", rc));
++ return EthernetInterface::IPAllowed::IPv4AndIPv6;
++ }
++ // true, false, ipv4, ipv6
++ if (values[0] == "ipv6")
++ {
++ return EthernetInterface::IPAllowed::IPv6Only;
++ }
++ else if (values[0] == "ipv4")
++ {
++ return EthernetInterface::IPAllowed::IPv4Only;
++ }
++ else if (values[0] == "off")
++ {
++ // This function should not get called if DHCP == off
++ log<level::DEBUG>("Function not available in static mode");
++ return EthernetInterface::IPAllowed::IPv4AndIPv6;
++ }
++ else
++ {
++ return EthernetInterface::IPAllowed::IPv4AndIPv6;
++ }
++}
++EthernetInterface::IPAllowed
++ EthernetInterface::iPAddressEnables(EthernetInterface::IPAllowed iPAllowed)
++{
++ if (iPAllowed == EthernetInterfaceIntf::iPAddressEnables())
++ {
++ return iPAllowed;
++ }
++
++ EthernetInterfaceIntf::iPAddressEnables(iPAllowed);
++ writeConfigurationFile();
+
++ return iPAllowed;
++}
+ ServerList EthernetInterface::getNTPServersFromConf()
+ {
+ fs::path confPath = manager.getConfDir();
+@@ -524,7 +608,8 @@ void EthernetInterface::writeConfigurationFile()
+ #else
+ stream << "LinkLocalAddressing=no\n";
+ #endif
+- stream << "IPv6AcceptRA=false\n";
++ stream << std::boolalpha
++ << "IPv6AcceptRA=" << EthernetInterfaceIntf::iPv6AcceptRA() << "\n";
+
+ // Add the VLAN entry
+ for (const auto& intf : vlanInterfaces)
+@@ -533,8 +618,24 @@ void EthernetInterface::writeConfigurationFile()
+ << "\n";
+ }
+ // Add the DHCP entry
+- auto value = dHCPEnabled() ? "true"s : "false"s;
+- stream << "DHCP="s + value + "\n";
++ std::string dhcpValue = "false";
++ if (dHCPEnabled())
++ {
++ IPAllowed ipAllowed = EthernetInterfaceIntf::iPAddressEnables();
++ if (ipAllowed == IPAllowed::IPv4AndIPv6)
++ {
++ dhcpValue = "true";
++ }
++ else if (ipAllowed == IPAllowed::IPv4Only)
++ {
++ dhcpValue = "ipv4";
++ }
++ else if (ipAllowed == IPAllowed::IPv6Only)
++ {
++ dhcpValue = "ipv6";
++ }
++ }
++ stream << "DHCP=" << dhcpValue << "\n";
+
+ // When the interface configured as dhcp, we don't need below given entries
+ // in config file.
+diff --git a/ethernet_interface.hpp b/ethernet_interface.hpp
+index c65726a..55fd7d9 100644
+--- a/ethernet_interface.hpp
++++ b/ethernet_interface.hpp
+@@ -207,6 +207,23 @@ class EthernetInterface : public Ifaces
+ /** @brief write the dhcp section **/
+ void writeDHCPSection(std::fstream& stream);
+
++ /** @brief get the IPv6AcceptRA flag from the network configuration file
++ *
++ */
++ bool getIPv6AcceptRAFromConf();
++
++ /** @brief check conf file for Router Advertisements
++ *
++ */
++ bool iPv6AcceptRA(bool value) override;
++
++ /** @brief get the allowed network modes. Similar to DHCP enabled, but
++ * more specific
++ */
++ IPAllowed getIPAddressEnablesFromConf();
++
++ IPAllowed iPAddressEnables(IPAllowed) override;
++
+ /** @brief get the NTP server list from the network conf
+ *
+ */
+diff --git a/util.cpp b/util.cpp
+index 6bc1497..6c60d54 100644
+--- a/util.cpp
++++ b/util.cpp
+@@ -461,8 +461,7 @@ bool getDHCPValue(const std::string& confDir, const std::string& intf)
+ entry("RC=%d", rc));
+ return dhcp;
+ }
+- // There will be only single value for DHCP key.
+- if (values[0] == "true")
++ if (values[0] != "false")
+ {
+ dhcp = true;
+ }
+--
+2.17.1
+
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..79e8d96cc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network/0003-Adding-channel-specific-privilege-to-network.patch
@@ -0,0 +1,404 @@
+From f28e3694f4b15c6eee58733f57213d360fc5ac7a Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 5 Sep 2018 14:16:54 +0530
+Subject: [PATCH 2/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 | 116 +++++++++++++++++++++++++++++++++++++++++
+ ethernet_interface.hpp | 39 +++++++++++++-
+ network_manager.cpp | 104 ++++++++++++++++++++++++++++++++++++
+ network_manager.hpp | 9 ++++
+ 4 files changed, 267 insertions(+), 1 deletion(-)
+
+diff --git a/ethernet_interface.cpp b/ethernet_interface.cpp
+index aa1c895..e3ea33c 100644
+--- a/ethernet_interface.cpp
++++ b/ethernet_interface.cpp
+@@ -35,6 +35,9 @@ 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";
+ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ const std::string& objPath,
+ bool dhcpEnabled, Manager& parent,
+@@ -51,6 +54,7 @@ EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
+ MacAddressIntf::mACAddress(getMACAddress(intfName));
+ EthernetInterfaceIntf::nTPServers(getNTPServersFromConf());
+ EthernetInterfaceIntf::nameservers(getNameServerFromConf());
++ getChannelPrivilege(intfName);
+
+ // Emit deferred signal.
+ if (emitSignal)
+@@ -837,5 +841,117 @@ 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 (!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 55fd7d9..7bf93a6 100644
+--- a/ethernet_interface.hpp
++++ b/ethernet_interface.hpp
+@@ -2,10 +2,13 @@
+
+ #include "types.hpp"
+ #include "util.hpp"
++#include "xyz/openbmc_project/Channel/ChannelAccess/server.hpp"
+ #include "xyz/openbmc_project/Network/IP/Create/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>
+@@ -21,7 +24,8 @@ using Ifaces = sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface,
+ sdbusplus::xyz::openbmc_project::Network::server::MACAddress,
+ sdbusplus::xyz::openbmc_project::Network::IP::server::Create,
+- 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;
+
+@@ -29,10 +33,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.
+@@ -153,6 +162,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 MacAddressIntf::mACAddress;
+@@ -256,6 +273,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 fa5da0f..a5020f0 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..e16b205 100644
+--- a/network_manager.hpp
++++ b/network_manager.hpp
+@@ -137,6 +137,9 @@ class Manager : public details::VLANCreateIface
+ return (interfaces.find(intf) != interfaces.end());
+ }
+
++ /** supported privilege list **/
++ std::vector<std::string> supportedPrivList;
++
+ protected:
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+@@ -159,6 +162,12 @@ class Manager : public details::VLANCreateIface
+
+ /** @brief Network Configuration directory. */
+ fs::path confDir;
++
++ /** Get the user management service name dynamically **/
++ std::string getUserServiceName();
++
++ /** @brief initializes the supportedPrivilege List */
++ void initSupportedPrivilges();
+ };
+
+ } // namespace network
+--
+2.17.1
+
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..afec5d41f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/phosphor-network_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+DEPENDS += "nlohmann-json"
+
+SRC_URI += "file://0002-IPv6-Network-changes-to-configuration-file.patch \
+ file://0003-Adding-channel-specific-privilege-to-network.patch \
+ "
+SRCREV = "f273d2b5629d2a7d96802dc7a7ddb92e303ac8de"
+
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..67b8afd5e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
@@ -0,0 +1,78 @@
+#!/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.
+
+read_hw_mac() {
+ local iface="$1"
+ cat /sys/class/net/"$iface"/address
+}
+
+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
+}
+
+SOFS_MNT=/var/sofs
+read_sofs_mac() {
+ local iface="$1"
+ cat "${SOFS_MNT}/factory-settings/network/mac/${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"
+}
+
+mac_check() {
+ local iface="$1"
+ local envname="$2"
+
+ # read current HW MAC addr
+ local hw_mac=$(read_hw_mac "$iface")
+
+ # read saved sofs MAC addr
+ local sofs_mac=$(read_sofs_mac "$iface")
+
+ # if set and not the same as HW addr, set HW addr
+ if [ -n "$sofs_mac" ] && [ "$hw_mac" != "$sofs_mac" ]; then
+ set_hw_mac "$iface" "$sofs_mac"
+ hw_mac="$sofs_mac"
+ fi
+
+ # read saved fw_env MAC addr
+ local fw_env_mac=$(read_fw_env_mac "$envname")
+
+ # save to fw_env if not the same as HW addr
+ if [ -z "$fw_env_mac" ] || [ "$fw_env_mac" != "$hw_mac" ]; then
+ set_fw_env_mac "$envname" "$hw_mac"
+ fi
+}
+
+while read IFACE UBDEV; do
+ mac_check "$IFACE" "$UBDEV"
+done <<-END_CONF
+ eth0 eth1addr
+ eth1 ethaddr
+END_CONF
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/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service
new file mode 100644
index 000000000..bc05fa1a1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/xyz.openbmc_project.CloseMuxes.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Close Muxes
+ConditionFileNotEmpty=/usr/bin/CloseMuxes.py
+
+[Service]
+ExecStart=/usr/bin/env CloseMuxes.py
+Type=oneshot
+
+[Install]
+WantedBy=basic.target
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..8b9da74f0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend
@@ -0,0 +1,18 @@
+# this is here just to bump faster than upstream
+SRC_URI = "git://github.com/openbmc/entity-manager.git"
+SRCREV = "15c49902cf030a91a5b4bd325d185ee74b760359"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+RDEPENDS_${PN} += "python"
+SRC_URI += " file://xyz.openbmc_project.CloseMuxes.service"
+SYSTEMD_SERVICE_${PN} += " xyz.openbmc_project.CloseMuxes.service"
+
+EXTRA_OECMAKE = "-DYOCTO=1 -DUSE_OVERLAYS=0"
+
+do_install_prepend() {
+ install -d ${D}${bindir}
+ install -m 0755 ${S}/scripts/CloseMuxes.py ${D}${bindir}
+ install -d ${D}${base_libdir}/systemd/system
+ install -m 0644 ${WORKDIR}/xyz.openbmc_project.CloseMuxes.service ${D}${base_libdir}/systemd/system
+}
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch
new file mode 100644
index 000000000..3ca81c388
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0002-Modify-Dbus-for-IPv6.patch
@@ -0,0 +1,61 @@
+From 068b816b3c9bf75dcd2a808fc81c67a32fbe29ea Mon Sep 17 00:00:00 2001
+From: David Cobbley <david.j.cobbley@linux.intel.com>
+Date: Wed, 6 Jun 2018 10:11:58 -0700
+Subject: [PATCH] Modify Dbus for IPv6.
+
+Add additional interfaces for IPv6 use.
+---
+ .../Network/EthernetInterface.interface.yaml | 17 ++++++++++++++++-
+ xyz/openbmc_project/Network/IP.interface.yaml | 4 ++++
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+index 744ac77..6b7cd9a 100644
+--- a/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
++++ b/xyz/openbmc_project/Network/EthernetInterface.interface.yaml
+@@ -42,6 +42,14 @@ properties:
+ description: >
+ This indicates link local auto configuration on this ethernet
+ interface and configured on this ethernet interface.
++ - name: IPv6AcceptRA
++ type: boolean
++ description: >
++ Boolean for accepting router advertisements in IPv6
++ - name: IPAddressEnables
++ type: enum[self.IPAllowed]
++ description: >
++ The type of IP connection is allowed on this channel
+
+ enumerations:
+ - name: LinkLocalConf
+@@ -52,4 +60,11 @@ enumerations:
+ - name: v4
+ - name: v6
+ - name: none
+-
++ - name: IPAllowed
++ description: >
++ Determines whether the system allows both IPv6 & IPv4, or disables on
++ or the other
++ values:
++ - name: IPv4AndIPv6
++ - name: IPv4Only
++ - name: IPv6Only
+diff --git a/xyz/openbmc_project/Network/IP.interface.yaml b/xyz/openbmc_project/Network/IP.interface.yaml
+index 565dcd6..2ffb016 100644
+--- a/xyz/openbmc_project/Network/IP.interface.yaml
++++ b/xyz/openbmc_project/Network/IP.interface.yaml
+@@ -22,6 +22,10 @@ properties:
+ type: string
+ description: >
+ This is the IP gateway for this address.
++ - name: BackupGateway
++ type: string
++ description: >
++ This is the IP address of the backup gateway.
+ - name: Type
+ type: enum[self.Protocol]
+ description: >
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch
new file mode 100644
index 000000000..0e25856ac
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0003-Chassis-Power-Control-are-implemented.patch
@@ -0,0 +1,264 @@
+From a20f9fa9941533b591b6bbfe6b22a74b7c0dfe64 Mon Sep 17 00:00:00 2001
+From: Ed Tanous <ed.tanous@intel.com>
+Date: Thu, 24 Jan 2019 09:29:01 -0800
+Subject: [PATCH] Chassis Power Control are implemented.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Feature level:
+Power on server is ready
+Power off server is ready
+Power cycle server is ready
+Power reset server is ready
+
+Framework level:
+WebUI is enabled.
+IPMI Commands is enabled.
+Restful API is enabled.
+Physical buttons (Power/Reset/ID) are enabled.
+Chassis state manager is enabled.
+Host state manager is enabled.
+
+Enabled IPMI commands:
+ipmitool -H <ip_addr> -P <pass_word> -I lanplus chassis status
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power status
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power on
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power off
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power cycle
+ipmitool -H <ip_addr>  -P <pass_word> -I lanplus chassis power reset
+
+Enabled Restful APIs:
+Login: curl --noproxy <ip_addr> -c cjar -b cjar -k -H "Content-Type: application/json" -X POST https://<ip_addr>/login -d "{\"data\": [ \"root\", \"0penBmc\" ] }“
+Host State: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/state/host0
+Chassis State: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/state/chassis0
+Power state: curl --noproxy <ip_addr> -b cjar -k https://<ip_addr>/xyz/openbmc_project/Chassis/Control/Power0
+Power on/off: curl --noproxy <ip_addr> -q1c cjar -b cjar -k -H "Content-Type: application/json" -d '{"data": "xyz.openbmc_project.State.Host.Transition.Off"}' -X PUT https://<ip_addr>/xyz/openbmc_project/state/host0/attr/RequestedHostTransition
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ .../Chassis/Control/Chassis.interface.yaml | 94 ++++++++++++++++++++++
+ .../Chassis/Control/Power.interface.yaml | 92 ++++++++++++++++++---
+ 2 files changed, 173 insertions(+), 13 deletions(-)
+ create mode 100644 xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+
+diff --git a/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml b/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+new file mode 100644
+index 0000000..c28492a
+--- /dev/null
++++ b/xyz/openbmc_project/Chassis/Control/Chassis.interface.yaml
+@@ -0,0 +1,94 @@
++description: >
++ chassis control service
++methods:
++ - name: powerOn
++ description: >
++ Power on system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: powerOff
++ description: >
++ Power Off system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: softPowerOff
++ description: >
++ Soft Power off system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: reboot
++ description: >
++ reboot system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: softReboot
++ description: >
++ Soft Reboot system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: quiesce
++ description: >
++ Quiesce system.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: getPowerState
++ description: >
++ Get system power state.
++ returns:
++ - name: state
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
+diff --git a/xyz/openbmc_project/Chassis/Control/Power.interface.yaml b/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
+index 082586f..368beca 100644
+--- a/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
++++ b/xyz/openbmc_project/Chassis/Control/Power.interface.yaml
+@@ -1,31 +1,97 @@
+ description: >
+- Power control service
++ Chassis control service
+ methods:
++ - name: setPowerState
++ description: >
++ set host power state.
++ parameters:
++ - name: state
++ type: int32
++ description: >
++ 0 for force power off host
++ 1 for power on host
++ returns:
++ - name: status
++ type: int32
++ description: >
++ The result of command.
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
++ - name: getPowerState
++ description: >
++ Get current host power status.
++ returns:
++ - name: status
++ type: int32
++ description: >
++ Current host status,
++ 0 for host power off
++ 1 for host power on
++ errors:
++ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
++ - xyz.openbmc_project.Chassis.Common.Error.IOError
++
+ - name: forcePowerOff
+ description: >
+ Force power off the host.
+ returns:
+ - name: status
+- type: boolean
++ type: int32
+ description: >
+ The result of power off command.
+ errors:
+ - xyz.openbmc_project.Chassis.Common.Error.UnsupportedCommand
++
+ - xyz.openbmc_project.Chassis.Common.Error.IOError
+
+ properties:
+- - name: PGood
+- type: boolean
+- default: false
++ - name: vrd_good
++ type: int32
++ default: 0
++ description: >
++ ACPI status
++ - name: s4s5_state
++ type: int32
++ default: 0
++ description: >
++ ACPI status
++ - name: pgood
++ type: int32
++ default: 0
+ description: >
+- PSU Power good property
+- It is a read-only property.
+- - name: State
++ pgood property
++ - name: state
+ type: int32
+ default: 0
+ description: >
+- System power status
+- 0: power is off
+- 1: power is on
+- Setting its value to change the system state
+- Read its value to get the system state.
+\ No newline at end of file
++ state property
++ - name: pgood_timeout
++ type: int32
++ default: 0
++ description: >
++ pgoodtimeout property
++ - name: post_complete
++ type: boolean
++ default: false
++ description: >
++ The current BIOS POST state,
++ false means not completed or system reset,
++ true means BIOS POST completed.
++ - name: PFail
++ type: boolean
++ default: true
++ description: >
++ The current booting status,
++ true means booting from AC loss,
++ false means not booting from AC loss.
++signals:
++ - name: PowerGood
++ description: >
++ Signal for powergood
++ - name: PowerLost
++ description: >
++ Signal for powerlost
+--
+2.7.4
+
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..7568f8ce9
--- /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,120 @@
+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 and Memory's properties Feature
+ Support: SMBIOS service interface. CPU DIMM 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 +++++++++++++++++++
+ .../Inventory/Item/Dimm.interface.yaml | 46 +++++++++++++++++++++-
+ 2 files changed, 86 insertions(+), 1 deletion(-)
+
+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
+diff --git a/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml b/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
+index d85326d..b750320 100644
+--- a/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
++++ b/xyz/openbmc_project/Inventory/Item/Dimm.interface.yaml
+@@ -1,4 +1,48 @@
+ description: >
+ Implement to provide DIMM attributes.
+-
++properties:
++ - name: MemoryDataWidth
++ type: uint16
++ description: >
++ Data width of Memory.
++ - name: MemorySizeInKB
++ type: uint32
++ description: >
++ Memory size of DIMM in Kilobyte.
++ - name: MemoryDeviceLocator
++ type: string
++ description: >
++ Socket on base board where Memory located.
++ - name: MemoryType
++ type: string
++ description: >
++ Type of memory.
++ - name: MemoryTypeDetail
++ type: string
++ description: >
++ Additional detail on Memory.
++ - name: MemorySpeed
++ type: uint16
++ description: >
++ The maximun capable speed of Memory.
++ - name: MemoryManufacturer
++ type: string
++ description: >
++ Manufacturer of memory.
++ - name: MemorySerialNum
++ type: string
++ description: >
++ Memory Serial Number.
++ - name: MemoryPartNum
++ type: string
++ description: >
++ Memory Part Number.
++ - name: MemoryAttributes
++ type: byte
++ description: >
++ Rank attributes of Memory.
++ - name: MemoryConfClockSpeed
++ type: uint16
++ description: >
++ Configured clock speed to Memory.
+ # 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/0009-Add-host-restart-cause-property.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch
new file mode 100644
index 000000000..1221a0ab4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0009-Add-host-restart-cause-property.patch
@@ -0,0 +1,98 @@
+From 72b7b30a5dda56c170ee2ce82c1082c26f4663e3 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 31 Jul 2018 16:55:21 +0800
+Subject: [PATCH] Add host restart cause property.
+
+Add host restart cause property to track the information about what
+action last caused the system to restart.
+According to IPMI Spec, it includes 12 types as following:
+1. Unknown 0x0
+2. IpmiCommand 0x1
+3. ResetButton 0x2
+4. PowerButton 0x3
+5. WatchdogTimer 0x4
+6. OEM 0x5
+7. PowerPolicyAlwaysOn 0x6
+8. PowerPolicyPreviousState 0x7
+9. PEF-Reset 0x8
+10. PEF-PowerCycle 0x9
+11. SoftReset 0xA
+12. RTC-Wakeup 0xB
+
+Change-Id: Id2cc6a18b98e485a978940e5ffc085bf5c4fbed8
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ xyz/openbmc_project/State/Host.interface.yaml | 52 +++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/xyz/openbmc_project/State/Host.interface.yaml b/xyz/openbmc_project/State/Host.interface.yaml
+index 8f481b8..a4d88d0 100644
+--- a/xyz/openbmc_project/State/Host.interface.yaml
++++ b/xyz/openbmc_project/State/Host.interface.yaml
+@@ -17,6 +17,12 @@ properties:
+ comparing the CurrentHostState and the RequestedHostTransition
+ properties.
+
++ - name: HostRestartCause
++ type: enum[self.RestartCause]
++ default: Unknown
++ description: >
++ The information about what action last caused the system to restart.
++
+ enumerations:
+ - name: Transition
+ description: >
+@@ -45,3 +51,49 @@ enumerations:
+ - name: 'Quiesced'
+ description: >
+ Host firmware is quiesced
++
++ - name: RestartCause
++ description: >
++ The information about what action last caused the system to restart.
++ values:
++ - name: Unknown
++ description: >
++ System start/restart detected but the reason is unknown.
++ - name: IpmiCommand
++ description: >
++ System start/restart detected and caused by ipmi command.
++ - name: ResetButton
++ description: >
++ System start/restart detected and caused by reset button.
++ - name: PowerButton
++ description: >
++ System start/restart detected and caused by power button.
++ - name: WatchdogTimer
++ description: >
++ System start/restart detected and casued by watchdog expiration.
++ - name: OEM
++ description: >
++ System start/restart detected and caused by OEM command.
++ - name: PowerPolicyAlwaysOn
++ description: >
++ System start/restart detected and caused by power restore policy
++ "chassis always powers up after AC/mains is applied or returns".
++ - name: PowerPolicyPreviousState
++ description: >
++ System start/restart detected and caused by power restore policy
++ "after AC/mains is applied or returns, power is restored to the
++ state was in effect when AC/mains removed or lost".
++ - name: PEFReset
++ description: >
++ System start/restart detected and caused by PEF(reset).
++ - name: PEFPowerCycle
++ description: >
++ System start/restart detected and caused by PEF(power-cycle).
++ - name: SoftReset
++ description: >
++ System start/restart detected and caused by soft reset like
++ "CTRL-ALT-DEL".
++ - name: RTCWakeup
++ description: >
++ System start/restart detected and caused by system real time
++ clock(RTC) wakeup.
+\ No newline at end of file
+--
+2.17.0
+
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/0014-Add-multiple-state-signal-for-host-start-and-stop.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch
new file mode 100644
index 000000000..a8d732dab
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0014-Add-multiple-state-signal-for-host-start-and-stop.patch
@@ -0,0 +1,63 @@
+From 6d0069f4a2b4637c58fd321c9db3034ac9dd17c7 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Wed, 12 Sep 2018 15:03:26 +0800
+Subject: [PATCH] Add multiple state signal for host start and stop
+
+Add six host state signals like following:
+ - name: PreHostStart
+ description: >
+ This is the signal to indicate host is at pre start stage.
+ - name: PostHostStart
+ description: >
+ This is the signal to indicate host is at start complete stage.
+ - name: HostStarting
+ description: >
+ This is the signal to indicate host is at starting stage.
+ - name: HostStoping
+ description: >
+ This is the signal to indicate host is at stoping stage.
+ - name: PreHostStop
+ description: >
+ This is the signal to indicate host is at pre stop stage.
+ - name: PostHostStop
+ description: >
+ This is the signal to indicate host is at stop complete stage.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ xyz/openbmc_project/State/Host.interface.yaml | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/State/Host.interface.yaml b/xyz/openbmc_project/State/Host.interface.yaml
+index 8531a27..1ceba13 100644
+--- a/xyz/openbmc_project/State/Host.interface.yaml
++++ b/xyz/openbmc_project/State/Host.interface.yaml
+@@ -96,4 +96,23 @@ enumerations:
+ - name: RTCWakeup
+ description: >
+ System start/restart detected and caused by system real time
+- clock(RTC) wakeup.
+\ No newline at end of file
++ clock(RTC) wakeup.
++signals:
++ - name: PreHostStart
++ description: >
++ This is the signal to indicate host is at pre start stage.
++ - name: PostHostStart
++ description: >
++ This is the signal to indicate host is at start complete stage.
++ - name: HostStarting
++ description: >
++ This is the signal to indicate host is at starting stage.
++ - name: HostStoping
++ description: >
++ This is the signal to indicate host is at stoping stage.
++ - name: PreHostStop
++ description: >
++ This is the signal to indicate host is at pre stop stage.
++ - name: PostHostStop
++ description: >
++ This is the signal to indicate host is at stop complete stage.
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch
new file mode 100644
index 000000000..576bae81a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch
@@ -0,0 +1,227 @@
+From 9490574667485cd407193ff9f0d6a96f8c2c87d3 Mon Sep 17 00:00:00 2001
+From: cyang29 <cheng.c.yang@intel.com>
+Date: Wed, 12 Sep 2018 00:27:23 +0800
+Subject: [PATCH] Add DBUS interface of SMBIOS MDR V2
+
+Support:
+ SMBIOS MDR V2 service interface.
+ SMBIOS MDR V2 IPMI Command
+ SMBIOS MDR V2 Redfish interface.
+Base on SMBIOS spec DSP0134_3.0.0 and Managed Data Region
+Specification Revision 4
+---
+ xyz/openbmc_project/Smbios/MDR_V2.errors.yaml | 9 +
+ xyz/openbmc_project/Smbios/MDR_V2.interface.yaml | 158 +++++++++++++++++++++++
+ xyz/openbmc_project/Smbios/README.md | 21 +++
+ 3 files changed, 188 insertions(+)
+ create mode 100644 xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+ create mode 100644 xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+ create mode 100644 xyz/openbmc_project/Smbios/README.md
+
+diff --git a/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml b/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+new file mode 100644
+index 0000000..88bd6db
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/MDR_V2.errors.yaml
+@@ -0,0 +1,9 @@
++- name: InvalidParameter
++ description: >
++ An invalid parameter is attempted.
++- name: UpdateInProgress
++ description: >
++ Update is in progress.
++- name: InvalidId
++ description: >
++ An invalid Id is attempted.
+diff --git a/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml b/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+new file mode 100644
+index 0000000..f97700a
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/MDR_V2.interface.yaml
+@@ -0,0 +1,158 @@
++description: >
++ SMBIOS MDR V2 service
++methods:
++ - name: GetDirectoryInformation
++ description: >
++ Get the directory with directory index.
++ parameters:
++ - name: dirIndex
++ type: byte
++ description: >
++ Directory index of SMBIOS.
++ returns:
++ - name: dir
++ type: array[byte]
++ description: >
++ Directory of agent.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: GetDataInformation
++ description: >
++ Get the data info with id index and data set ID.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ returns:
++ - name: dataInfo
++ type: array[byte]
++ description: >
++ Data information of SMBIOS.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: SendDirectoryInformation
++ description: >
++ Send directory information to SMBIOS directory.
++ parameters:
++ - name: dirVersion
++ type: byte
++ description: >
++ A counter which increments each time directory updated.
++ - name: dirIndex
++ type: byte
++ description: >
++ Directory index of SMBIOS.
++ - name: returnedEntries
++ type: byte
++ description: >
++ Indicates number of directory entries.
++ - name: remainingEntries
++ type: byte
++ description: >
++ Remaining entries which are higher than index in this transfer.
++ - name: dirEntry
++ type: array[byte]
++ description: >
++ Data set ID of SMBIOS table.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Need to continue directory transmisson or not.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: GetDataOffer
++ description: >
++ Get data set ID.
++ returns:
++ - name: offer
++ type: array[byte]
++ description: >
++ Data set ID.
++ errors:
++ - self.Error.UpdateInProgress
++
++ - name: SendDataInformation
++ description: >
++ Send data information with directory index.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ - name: flag
++ type: byte
++ description: >
++ Valid flag to set dir entry status.
++ - name: dataLen
++ type: uint32
++ description: >
++ The length of the data in bytes.
++ - name: dataVer
++ type: uint32
++ description: >
++ The version number of this data.
++ - name: timeStamp
++ type: uint32
++ description: >
++ Timestamp determinded by the agent.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Whether data changes.
++ errors:
++ - self.Error.InvalidParameter
++
++ - name: FindIdIndex
++ description: >
++ Find id index by data info.
++ parameters:
++ - name: dataInfo
++ type: array[byte]
++ description: >
++ Data info of data entry.
++ returns:
++ - name: idIndex
++ type: int32
++ description: >
++ Id index of data entry.
++ errors:
++ - self.Error.InvalidId
++
++ - name: AgentSynchronizeData
++ description: >
++ Synchronize SMBIOS data from file.
++ returns:
++ - name: status
++ type: boolean
++ description: >
++ Whether synchronization succeed or not.
++
++ - name: SynchronizeDirectoryCommonData
++ description: >
++ Synchronize directory common data.
++ parameters:
++ - name: idIndex
++ type: byte
++ description: >
++ Index of SMBIOS directory.
++ - name: size
++ type: uint32
++ description: >
++ Size of data that BIOS prepare to transfer.
++ returns:
++ - name: commonData
++ type: array[uint32]
++ description: >
++ Directory common data includes data size, version and timestamp.
++
++properties:
++ - name: DirectoryEntries
++ type: byte
++ description: >
++ Numbers of directory entries.
+diff --git a/xyz/openbmc_project/Smbios/README.md b/xyz/openbmc_project/Smbios/README.md
+new file mode 100644
+index 0000000..415ac52
+--- /dev/null
++++ b/xyz/openbmc_project/Smbios/README.md
+@@ -0,0 +1,22 @@
++# SMBIOS MDR V2
++
++## Overview
++SMBIOS MDR V2 service exposes D-Bus methods for SMBIOS Version 2 operations.
++
++### SMBIOS MDR V2 Interface
++SMBIOS MDR V2 interface `xyz.openbmc_project.Smbios.MDR_V2` provides following
++methods.
++#### methods
++* GetDirectoryInformation - Get the directory with directory index.
++* GetDataInformation - Get the data information with id index and data set ID.
++* SendDirectoryInformation - Send directory information to SMBIOS directory.
++* GetDataOffer - Get data set ID.
++* SendDataInformation - Send data information with directory index.
++* FindIdIndex - Find id index by data info.
++* SynchronizeDirectoryCommonData - Synchronize directory common data before
++SMBIOS data start to transfer.
++* AgentSynchronizeData - Synchronize SMBIOS data from file after data transfer
++complete.
++
++#### properties
++* DirEntries - Numbers of directory entries. Default: 0
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch
new file mode 100644
index 000000000..ce23c222b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0018-Define-post-code-interfaces-for-post-code-manager.patch
@@ -0,0 +1,64 @@
+From f88cac8364d5312e29208018909827d2da4a0f87 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 19 Feb 2019 16:52:51 +0800
+Subject: [PATCH] Define post code interfaces for post code manager
+
+It includes one method and 2 properties.
+properties:
+ - name: CurrentBootCycleIndex
+ description: >
+ It is used to indicate current boot cycle index.
+ - name: MaxBootCycleNum
+ description: >
+ The max cached boot cycles for post code.
+methods:
+ - name: GetPostCodes
+ description: >
+ Method to get the cached post code for each boot cycle.
+TestBy: bitbake build
+
+Signeoff-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ .../State/Boot/PostCode.interface.yaml | 30 ++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+ create mode 100644 xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+
+diff --git a/xyz/openbmc_project/State/Boot/PostCode.interface.yaml b/xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+new file mode 100644
+index 0000000..711749d
+--- /dev/null
++++ b/xyz/openbmc_project/State/Boot/PostCode.interface.yaml
+@@ -0,0 +1,30 @@
++description: >
++ Monitor Post code coming and buffer all of them based on boot cycle
++ into file system.
++
++properties:
++ - name: CurrentBootCycleIndex
++ type: uint16
++ description: >
++ It is used to indicate current boot cycle index.
++ - name: MaxBootCycleNum
++ type: uint16
++ description: >
++ The max cached boot cycles for post code.
++methods:
++ - name: GetPostCodes
++ description: >
++ Method to get the cached post code for each boot cycle.
++ parameters:
++ - name: Index
++ type: uint16
++ description: >
++ Index indicates which boot cycle of post codes is requested.
++ returns:
++ - name: codes
++ type: array[uint64]
++ description: >
++ An array of post codes of one boot cycle.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - xyz.openbmc_project.Common.Error.InvalidArgument
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch
new file mode 100644
index 000000000..47fab819b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch
@@ -0,0 +1,116 @@
+From 28fac58dc6ef975e1e9283163d9f1e4c7764c3cc Mon Sep 17 00:00:00 2001
+From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+Date: Sat, 2 Mar 2019 03:31:09 +0530
+Subject: [PATCH] Creating the Session interface- for Host and LAN
+
+Defined all needed session properites to manage the session in
+host and also in LAN
+
+Change-Id: Ic7cccfc3333a602ee07fcd60077ec58fd8f06304
+Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+
+%% original patch: 0019-Creating-the-Session-interface-for-Host-and-LAN.patch
+---
+ xyz/openbmc_project/Ipmi/SESSION_README.md | 25 ++++++++++
+ .../Ipmi/SessionInfo.interface.yaml | 57 ++++++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+ create mode 100644 xyz/openbmc_project/Ipmi/SESSION_README.md
+ create mode 100644 xyz/openbmc_project/Ipmi/SessionInfo.interface.yaml
+
+diff --git a/xyz/openbmc_project/Ipmi/SESSION_README.md b/xyz/openbmc_project/Ipmi/SESSION_README.md
+new file mode 100644
+index 0000000..c59b251
+--- /dev/null
++++ b/xyz/openbmc_project/Ipmi/SESSION_README.md
+@@ -0,0 +1,25 @@
++# Session Management
++
++## Overview
++IPMI RMCP+ sessions are created and maintained by phosphor-ipmi-net daemon,
++whereas we need to provide details about the same using phosphor-ipmi-host.
++Hence IPMI RMCP+ session details has to be exposed through D-Bus interface,
++so that both phosphor-ipmi-host & phosphr-ipmi-net will be in sync.
++
++
++#### xyz.openbmc_project.Ipmi.SessionInfo interface
++##### properties
++* SessionHandle - SessionHandle,unique one-byte number to locate the session.
++* Channel - Session created channel.
++* SessionPrivilege - Privilege of the session.
++* RemoteIPAddr – Remote IP address.
++* RemotePort - Remote port address.
++* RemoteMACAddress -Remote MAC Address.
++* UserID - Session created by given user id.
++
++
++
++#### xyz.openbmc_project.Object.Delete
++#### methods
++* Delete - To delete the session object in the system.
++
+diff --git a/xyz/openbmc_project/Ipmi/SessionInfo.interface.yaml b/xyz/openbmc_project/Ipmi/SessionInfo.interface.yaml
+new file mode 100644
+index 0000000..d461628
+--- /dev/null
++++ b/xyz/openbmc_project/Ipmi/SessionInfo.interface.yaml
+@@ -0,0 +1,57 @@
++description: >
++ Provides properties for IPMI RMCP+ session objects.
++ Provides RMCP+ session information as session objects
++ with Session ID (unique identifier) as path suffix.
++
++properties:
++ - name: SessionHandle
++ type: byte
++ description: >
++ Session Handle,unique number to locate the session.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: ChannelNum
++ type: byte
++ description: >
++ channelnumber which session is created.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: CurrentPrivilege
++ type: byte
++ description: >
++ Privilege of the session.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: RemoteIPAddr
++ type: uint32
++ description: >
++ Remote IP address.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: RemotePort
++ type: uint16
++ description: >
++ Remote IP Port.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: RemoteMACAddress
++ type: array[byte]
++ description: >
++ Remote MAC address.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: UserID
++ type: byte
++ description: >
++ Session created by given user ID.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++ - name: State
++ type: byte
++ default: 0
++ description: >
++ Session state.
++ errors:
++ - xyz.openbmc_project.Common.Error.InternalFailure
++
++# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch
new file mode 100644
index 000000000..68d2c92b7
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch
@@ -0,0 +1,76 @@
+From 2820ca36ab21c52341cdbde477756f960eaeb68b Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Wed, 13 Mar 2019 11:19:07 +0800
+Subject: [PATCH] Create dbus interface for SOL commands
+
+Create dbus properties for Set/Get SOL config parameter command.
+Some platforms need to call Set/Get SOL config parameter command
+through KCS, and since sol manager in net-ipmid cannot be accessed
+by commands in host-ipmid, need to create a dbus interface in
+phospher-settings to transfer properties from host-ipmid to
+net-ipmid.
+
+TestedBy:
+With the related code change in net-ipmid, busctl introspect
+xyz.openbmc_project.Ipmi.SOL /xyz/openbmc_project/SOL
+can show all the properties needed.
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ xyz/openbmc_project/Ipmi/SOL.interface.yaml | 44 ++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+ create mode 100644 xyz/openbmc_project/Ipmi/SOL.interface.yaml
+
+diff --git a/xyz/openbmc_project/Ipmi/SOL.interface.yaml b/xyz/openbmc_project/Ipmi/SOL.interface.yaml
+new file mode 100644
+index 0000000..94db59f
+--- /dev/null
++++ b/xyz/openbmc_project/Ipmi/SOL.interface.yaml
+@@ -0,0 +1,44 @@
++description: >
++ SOL properties use for Get/Set SOL config parameter command in host-ipmid
++ sending config to SOL process in net-ipmid.
++ Since some platforms need to access Get/Set SOL config parameter command
++ through KCS, and current sol manager is implemented in net-ipmid and
++ cannot be accessed by host-ipmid, add a dbus interface for host-ipmid
++ command to transfer properties to net-ipmid.
++ This interface will be implemented in phosphor-settings.
++properties:
++ - name: Progress
++ type: byte
++ description: >
++ Set In Progress property, indicate when any parameters are being
++ updated.
++ - name: Enable
++ type: boolean
++ description: >
++ SOL Enable property, this controls whether the SOL payload type
++ can be activated.
++ - name: Authentication
++ type: byte
++ description: >
++ If SOL enable Force Payload Encryption and Authenticaton.
++ And the minimun operating privilege level SOL required.
++ - name: AccumulateIntervalMS
++ type: byte
++ description: >
++ Character Accumulate Interval in 5ms increments.
++ BMC will wait this time before transmitting a packet.
++ - name: Threshold
++ type: byte
++ description: >
++ BMC will automatically send an SOL character data packet containing
++ this number of characters as soon as this number of characters
++ (or greater) has been accepted from the baseboard serial controller.
++ - name: RetryCount
++ type: byte
++ description: >
++ Packet will be dropped if no ACK/NACK received by time retries
++ expire.
++ - name: RetryIntervalMS
++ type: byte
++ description: >
++ Retry Interval in 10ms increments.
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0021-Add-interface-suppot-for-provisioning-modes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0021-Add-interface-suppot-for-provisioning-modes.patch
new file mode 100644
index 000000000..f6e200cab
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0021-Add-interface-suppot-for-provisioning-modes.patch
@@ -0,0 +1,52 @@
+From 94fb1ac5dd4d54ea5a6d49597e1f15c384be7fd6 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Mon, 8 Apr 2019 11:48:22 +0530
+Subject: [PATCH] Add interface suppot for provisioning modes
+
+Support for provisioning modes are added in
+RestrictionMode.interface.yaml
+
+Tested:
+1. Verified build, and verified specified modes are available
+and able to set / get the same using busctl command
+
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ .../Security/RestrictionMode.interface.yaml | 24 ++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/xyz/openbmc_project/Control/Security/RestrictionMode.interface.yaml b/xyz/openbmc_project/Control/Security/RestrictionMode.interface.yaml
+index 8e4fd8d..d328dac 100644
+--- a/xyz/openbmc_project/Control/Security/RestrictionMode.interface.yaml
++++ b/xyz/openbmc_project/Control/Security/RestrictionMode.interface.yaml
+@@ -21,3 +21,27 @@ enumerations:
+ - name: Blacklist
+ description: >
+ Prevent, if in the blacklist.
++ - name: Provisioning
++ description: >
++ Indicate that system is in provisioning mode
++ and all commands are allowed in KCS inteface
++ in both pre and post BIOS boot.
++ - name: ProvisionedKCSWhiteList
++ description: >
++ Commands in the whitelist will only be executed
++ through KCS interface after BIOS POST complete.
++ All KCS commands are supported before POST complete.
++ - name: ProvisionedKCSDisabled
++ description: >
++ Commands through KCS interface are executed only
++ till BIOS POST complete notification, after
++ which no KCS commands will be executed(other
++ than BIOS SMI based ones).
++ - name: ValidationUnsecure
++ description: >
++ To indicate that BMC is in unsecure mode, and many
++ operations which are not meant for end-user will be
++ allowed in this mode. Interface which sets this
++ property has to make sure due diligence is made
++ as in this mode, many security intrinsic commands
++ can be executed.
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0022-Add-chassis-power-cycle-and-reset-to-Chassis-State.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0022-Add-chassis-power-cycle-and-reset-to-Chassis-State.patch
new file mode 100644
index 000000000..181d12428
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0022-Add-chassis-power-cycle-and-reset-to-Chassis-State.patch
@@ -0,0 +1,40 @@
+From b55c6847b18fdee5a72d601b871d73085481e4d9 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 3 Jun 2019 16:31:29 -0700
+Subject: [PATCH] Add chassis power-cycle and reset to Chassis State
+
+This adds chassis PowerCycle and Reset as possible Transition
+values for the Chassis State. These are to support chassis
+power cycle and a chassis reset button, respectively.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ xyz/openbmc_project/State/Chassis.interface.yaml | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/xyz/openbmc_project/State/Chassis.interface.yaml b/xyz/openbmc_project/State/Chassis.interface.yaml
+index 4ae6274..470a3a2 100644
+--- a/xyz/openbmc_project/State/Chassis.interface.yaml
++++ b/xyz/openbmc_project/State/Chassis.interface.yaml
+@@ -31,10 +31,17 @@ enumerations:
+ values:
+ - name: 'Off'
+ description: >
+- Chassis power should be off
++ Chassis power should be off
+ - name: 'On'
+ description: >
+ Chassis power should be on
++ - name: 'PowerCycle'
++ description: >
++ Chassis power should be cycled
++ - name: 'Reset'
++ description: >
++ Chassis should be reset
++
+
+ - name: PowerState
+ description: >
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0023-Add-host-interrupt-to-the-Host-State.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0023-Add-host-interrupt-to-the-Host-State.patch
new file mode 100644
index 000000000..650fd3bc9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0023-Add-host-interrupt-to-the-Host-State.patch
@@ -0,0 +1,31 @@
+From 9c94439a5a55efbb72bee10e9cfa0827dbedf511 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Mon, 3 Jun 2019 16:35:46 -0700
+Subject: [PATCH] Add host interrupt to the Host State
+
+This adds host Interrupt as possible Transition value for the
+Host State. This is to support an interrupt signal to the host
+firmware or software.
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ xyz/openbmc_project/State/Host.interface.yaml | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/xyz/openbmc_project/State/Host.interface.yaml b/xyz/openbmc_project/State/Host.interface.yaml
+index 1ceba13..3d71280 100644
+--- a/xyz/openbmc_project/State/Host.interface.yaml
++++ b/xyz/openbmc_project/State/Host.interface.yaml
+@@ -28,6 +28,9 @@ enumerations:
+ description: >
+ The desired transition for host firmware
+ values:
++ - name: 'Interrupt'
++ description: >
++ Host firmware should be interrupted
+ - name: 'Off'
+ description: >
+ Host firmware should be off
+--
+2.7.4
+
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_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
new file mode 100644
index 000000000..89b8da753
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend
@@ -0,0 +1,22 @@
+SRC_URI = "git://github.com/openbmc/phosphor-dbus-interfaces.git"
+SRCREV = "1f0e2ce6e1cb78a59a0015b160816b71156b03c6"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0002-Modify-Dbus-for-IPv6.patch \
+ file://0003-Chassis-Power-Control-are-implemented.patch \
+ file://0005-Add-DBUS-interface-of-CPU-and-Memory-s-properties.patch \
+ file://0007-ipmi-set-BIOS-id.patch \
+ file://0009-Add-host-restart-cause-property.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://0014-Add-multiple-state-signal-for-host-start-and-stop.patch \
+ file://0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch \
+ file://0018-Define-post-code-interfaces-for-post-code-manager.patch \
+ file://0019-Creating-the-Session-interface-for-Host-and-LAN.patch \
+ file://0021-Add-interface-suppot-for-provisioning-modes.patch \
+ file://0022-Add-chassis-power-cycle-and-reset-to-Chassis-State.patch \
+ file://0023-Add-host-interrupt-to-the-Host-State.patch \
+ file://0024-Add-the-pre-timeout-interrupt-defined-in-IPMI-spec.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..e8baaa23e
--- /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
+After=xyz.openbmc_project.ObjectMapper
+
+[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..e1ec04ff6
--- /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 = "1dad21b935b8359806de9a9cc3aa7b7463cc8df3"
+
+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..aa5d900e0
--- /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 7f29c255dd2af7fa6d38b02ad63a8b8940fbce84 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 5/6] 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>
+Change-Id: Id805deea75b21fab86f6bb6edbf50ddb3be42564
+---
+ activation.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 7 +++++++
+ static/flash.cpp | 41 +++++++++++++++++++++++++++++++++++++++--
+ ubi/flash.cpp | 9 +++------
+ 4 files changed, 93 insertions(+), 8 deletions(-)
+
+diff --git a/activation.cpp b/activation.cpp
+index f918221..f2923ae 100644
+--- a/activation.cpp
++++ b/activation.cpp
+@@ -163,6 +163,50 @@ 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();
++ activationProgress->progress(10);
++ }
++ 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 2da97ad..720e704 100755
+--- a/configure.ac
++++ b/configure.ac
+@@ -184,6 +184,13 @@ AS_IF([test "x$enable_ubifs_layout" == "xyes"], \
+ [AC_DEFINE([UBIFS_LAYOUT],[],[Enable ubifs support.])])
+ AM_CONDITIONAL([UBIFS_LAYOUT], [test "x$enable_ubifs_layout" == "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/fwupd@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/fwupd@.service
new file mode 100644
index 000000000..d51fee312
--- /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 file:////tmp/images/%i/image-runtime
+SyslogIdentifier=fwupd \ No newline at end of file
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..719c2562a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend
@@ -0,0 +1,13 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+EXTRA_OECONF += "--enable-fwupd_script"
+
+SYSTEMD_SERVICE_${PN}-updater += "fwupd@.service"
+
+#Currently enforcing image signature validation only for PFR images
+PACKAGECONFIG_append = "${@bb.utils.contains('IMAGE_TYPE', 'pfr', ' verify_signature', '', 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 \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb
new file mode 100644
index 000000000..cef2fdcaa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Gpio daemon service for handling gpio operations"
+DESCRIPTION = "Daemon allows to block gpio access under certain conditions"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/gpiodaemon"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "gpiodaemon.service"
+
+DEPENDS = "boost systemd sdbusplus phosphor-logging"
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/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..3f870103b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -0,0 +1,17 @@
+SRC_URI = "git://github.com/openbmc/bmcweb.git"
+SRCREV = "fa1a5a38551bd1b9f04ad2d4f9fea2e5ade5cc4c"
+
+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 "
+
+# Enable CPU Log and Raw PECI support
+EXTRA_OECMAKE += "-DBMCWEB_ENABLE_REDFISH_CPU_LOG=ON"
+EXTRA_OECMAKE += "-DBMCWEB_ENABLE_REDFISH_RAW_PECI=ON"
+
+# Enable Redfish BMC Journal support
+EXTRA_OECMAKE += "-DBMCWEB_ENABLE_REDFISH_BMC_JOURNAL=ON"
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..c2f3c9a0e
--- /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" : "eth2",
+ "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
+ }
+ },
+ "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" : "EMP",
+ "is_valid" : true,
+ "active_sessions" : 0,
+ "channel_info" : {
+ "medium_type" : "ipmb",
+ "protocol_type" : "ipmb-1.0",
+ "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/0002-Modify-dbus-interface-for-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Modify-dbus-interface-for-power-control.patch
new file mode 100644
index 000000000..236bd18f4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Modify-dbus-interface-for-power-control.patch
@@ -0,0 +1,31 @@
+From 39df500f277eca01d6a0538d4db8ec34894d9441 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 12:59:12 +0800
+Subject: [PATCH] Modify dbus interface for power control
+
+Switch power control service namespace from "org" to "xyz",
+to compatible with new intel-chassis services
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 6002e7a..0e83bba 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -786,8 +786,8 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_data_len_t data_len,
+ ipmi_context_t context)
+ {
+- const char* objname = "/org/openbmc/control/power0";
+- const char* intf = "org.openbmc.control.Power";
++ const char* objname = "/xyz/openbmc_project/Chassis/Control/Power0";
++ const char* intf = "xyz.openbmc_project.Chassis.Control.Power";
+
+ sd_bus* bus = NULL;
+ sd_bus_message* reply = NULL;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch
new file mode 100644
index 000000000..b54b22213
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0009-IPv6-Network-changes.patch
@@ -0,0 +1,899 @@
+From c20bc8eb6a08d177d951012eb91b37398b15d81d Mon Sep 17 00:00:00 2001
+From: Vernon Mauery <vernon.mauery@linux.intel.com>
+Date: Tue, 27 Nov 2018 11:01:15 -0800
+Subject: [PATCH] IPv6 Network changes
+
+Allow IPv6 IPMI set/get commands
+
+Signed-off-by: David Cobbley <david.j.cobbley@linux.intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+
+Change-Id: If5528d3b7294c5f8c17db5919439235d0fad0446
+---
+ include/ipmid/types.hpp | 9 +
+ include/ipmid/utils.hpp | 1 +
+ transporthandler.cpp | 654 +++++++++++++++++++++++++++++++++++++++-
+ transporthandler.hpp | 50 +++
+ 4 files changed, 713 insertions(+), 1 deletion(-)
+
+diff --git a/include/ipmid/types.hpp b/include/ipmid/types.hpp
+index 57c5873..c06fd8c 100644
+--- a/include/ipmid/types.hpp
++++ b/include/ipmid/types.hpp
+@@ -224,6 +224,7 @@ constexpr auto ADDR_TYPE_FORMAT = "%hhx";
+
+ constexpr auto IPV4_ADDRESS_SIZE_BYTE = 4;
+ constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16;
++constexpr auto IPV6_ADDRESS_STATUS_SIZE = 22;
+
+ constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00";
+ constexpr auto DEFAULT_ADDRESS = "0.0.0.0";
+@@ -235,6 +236,7 @@ constexpr auto BITS_32 = 32;
+ constexpr auto MASK_32_BIT = 0xFFFFFFFF;
+ constexpr auto VLAN_ID_MASK = 0x00000FFF;
+ constexpr auto VLAN_ENABLE_MASK = 0x8000;
++constexpr auto IPV6_DUID_SIZE = 18;
+
+ enum class IPOrigin : uint8_t
+ {
+@@ -243,5 +245,12 @@ enum class IPOrigin : uint8_t
+ DHCP = 2,
+ };
+
++enum class AddressingEnables : uint8_t
++{
++ IPv4Only = 0,
++ IPv6Only = 1,
++ IPv4AndIPv6 = 2,
++};
++
+ } // namespace network
+ } // namespace ipmi
+diff --git a/include/ipmid/utils.hpp b/include/ipmid/utils.hpp
+index 9ef1488..8b91b12 100644
+--- a/include/ipmid/utils.hpp
++++ b/include/ipmid/utils.hpp
+@@ -256,6 +256,7 @@ namespace network
+ constexpr auto ROOT = "/xyz/openbmc_project/network";
+ constexpr auto SERVICE = "xyz.openbmc_project.Network";
+ constexpr auto IP_TYPE = "ipv4";
++constexpr auto IPV6_TYPE = "ipv6";
+ constexpr auto IPV4_PREFIX = "169.254";
+ constexpr auto IPV6_PREFIX = "fe80";
+ constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 8172cc4..12d224a 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -30,6 +30,12 @@ std::unique_ptr<phosphor::Timer> networkTimer = nullptr;
+
+ const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
+ constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
++constexpr auto ipv6Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
++
++static const std::array<std::string, 3> ipAddressEnablesType = {
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4Only",
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv6Only",
++ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4AndIPv6"};
+
+ std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
+
+@@ -389,7 +395,6 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_context_t context)
+ {
+ ipmi_ret_t rc = IPMI_CC_OK;
+- *data_len = 0;
+
+ using namespace std::chrono_literals;
+
+@@ -403,6 +408,9 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ auto reqptr = reinterpret_cast<const set_lan_t*>(request);
+ sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+
++ size_t reqLen = *data_len;
++ *data_len = 0;
++
+ // channel number is the lower nibble
+ int channel = reqptr->channel & CHANNEL_MASK;
+ auto ethdevice = ipmi::getChannelName(channel);
+@@ -426,6 +434,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::IPSRC:
+ {
++ if (reqLen != LAN_PARAM_IPSRC_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ uint8_t ipsrc{};
+ std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
+ channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
+@@ -434,6 +447,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::MAC:
+ {
++ if (reqLen != LAN_PARAM_MAC_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ char mac[SIZE_MAC];
+
+ std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
+@@ -454,6 +472,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::SUBNET:
+ {
++ if (reqLen != LAN_PARAM_SUBNET_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ std::snprintf(netmask, INET_ADDRSTRLEN,
+ ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
+ reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+@@ -463,6 +486,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::GATEWAY:
+ {
++ if (reqLen != LAN_PARAM_GATEWAY_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ std::snprintf(gateway, INET_ADDRSTRLEN,
+ ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
+ reqptr->data[1], reqptr->data[2], reqptr->data[3]);
+@@ -472,6 +500,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::VLAN:
+ {
++ if (reqLen != LAN_PARAM_VLAN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ uint16_t vlan{};
+ std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
+ // We are not storing the enable bit
+@@ -484,6 +517,11 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ case LanParam::INPROGRESS:
+ {
++ if (reqLen != LAN_PARAM_INPROGRESS_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
+ if (reqptr->data[0] == SET_COMPLETE)
+ {
+ channelConf->lan_set_in_progress = SET_COMPLETE;
+@@ -512,6 +550,122 @@ ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ }
+ break;
+
++ case LanParam::IPV6_AND_IPV4_ENABLES:
++ {
++ if (reqLen != LAN_PARAM_IPV6_AND_IPV4_ENABLES_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6AddressingEnables = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ADDRESSES:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ADDRESSES_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6AddressSource =
++ reqptr->data[1] & 0x81; // Looking at bit 0 and bit 7
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, &reqptr->data[2], tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6Addr.assign(tmpIPV6);
++ channelConf->ipv6Prefix = reqptr->data[19];
++ break;
++ }
++
++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL:
++ {
++ if (reqLen != LAN_PARAM_IPV6_ROUTER_ADDRESS_CONF_CTRL_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6RouterAddressConfigControl = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_1_IP_ADDR_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6GatewayAddr.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_LEN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6GatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_VAL_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6GatewayPrefixValue.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_2_IP_ADDR_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6BackupGatewayAddr.assign(tmpIPV6);
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_LEN_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ channelConf->ipv6BackupGatewayPrefixLength = reqptr->data[0];
++ break;
++ }
++
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL:
++ {
++ if (reqLen != LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_VAL_SIZE)
++ {
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ char tmpIPV6[INET6_ADDRSTRLEN];
++ inet_ntop(AF_INET6, reinterpret_cast<const void*>(reqptr->data),
++ tmpIPV6, INET6_ADDRSTRLEN);
++ channelConf->ipv6BackupGatewayPrefixValue.assign(tmpIPV6);
++ break;
++ }
++
+ default:
+ {
+ rc = IPMI_CC_PARM_NOT_SUPPORTED;
+@@ -538,6 +692,7 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_ret_t rc = IPMI_CC_OK;
+ *data_len = 0;
+ const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
++ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+
+ get_lan_t* reqptr = (get_lan_t*)request;
+ // channel number is the lower nibble
+@@ -676,6 +831,476 @@ ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ static_cast<uint8_t>(cipherList.size());
+ break;
+ }
++ case LanParam::IPV6_AND_IPV4_SUPPORTED:
++ {
++ uint8_t addressSupport =
++ 0x1; // Allow both IPv4 & IPv6 simultaneously
++ std::array<uint8_t, 2> buf = {current_revision, addressSupport};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_AND_IPV4_ENABLES:
++ {
++ // If DHCP, check if you have an ipv6 and ipv4 address. If static
++ // return not supported
++
++ // 00h check if conf DHCP == ipv4 or off
++ // 01h check if conf DHCP == ipv6
++ // 02h check if DHCP == true
++
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ std::string networkInterfacePath;
++ uint8_t ipVAddressEnables = 0;
++
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ ipmi::ObjectTree ancestorMap;
++ // if the system has an ip object,then
++ // get the IP object.
++ auto ipObject =
++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++ // Get the parent interface of the IP object.
++ try
++ {
++ ipmi::InterfaceList interfaces;
++ interfaces.emplace_back(
++ ipmi::network::ETHERNET_INTERFACE);
++
++ ancestorMap = ipmi::getAllAncestors(
++ bus, ipObject.first, std::move(interfaces));
++ }
++ catch (InternalFailure& e)
++ {
++ // if unable to get the parent interface
++ // then commit the error and return.
++ log<level::ERR>(
++ "Unable to get the parent interface",
++ entry("PATH=%s", ipObject.first.c_str()),
++ entry("INTERFACE=%s",
++ ipmi::network::ETHERNET_INTERFACE));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ // for an ip object there would be single parent
++ // interface.
++ networkInterfacePath = ancestorMap.begin()->first;
++ }
++ catch (InternalFailure& e)
++ {
++ // if there is no ip configured on the system,then
++ // get the network interface object.
++ auto networkInterfaceObject = ipmi::getDbusObject(
++ bus, ipmi::network::ETHERNET_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ networkInterfacePath = networkInterfaceObject.first;
++ }
++
++ ipmi::Value ipEnablesProp = ipmi::getDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfacePath,
++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables");
++ std::string ipEnables = std::get<std::string>(ipEnablesProp);
++
++ // check if on off ipv4 ipv6, etc.
++ bool found = false;
++ for (uint8_t ii = 0; ii < ipAddressEnablesType.size(); ii++)
++ {
++ if (ipEnables == ipAddressEnablesType[ii])
++ {
++ ipVAddressEnables = ii;
++ found = true;
++ break;
++ }
++ }
++ if (!found)
++ {
++ return IPMI_CC_PARM_NOT_SUPPORTED;
++ }
++ }
++ else
++ {
++ ipVAddressEnables = channelConf->ipv6AddressingEnables;
++ }
++
++ std::array<uint8_t, 2> buf = {current_revision, ipVAddressEnables};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATUS:
++ {
++ // Number of IPV6 addresses that are supported
++ constexpr std::array<uint8_t, 3> statusData = {1, 1, 3};
++
++ std::array<uint8_t, 4> buf = {current_revision, statusData[0],
++ statusData[1], statusData[2]};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ADDRESSES:
++ {
++ // Only return set selector 0
++ uint8_t ipv6SetSelector = 0;
++ std::string ipaddress;
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ uint8_t ipv6AddressSource = 0;
++ uint8_t prefixLength = 0;
++ uint8_t status = 0;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ auto ipObjectInfo =
++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ auto properties = ipmi::getAllDbusProperties(
++ bus, ipObjectInfo.second, ipObjectInfo.first,
++ ipmi::network::IP_INTERFACE);
++
++ if (std::get<std::string>(properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
++ {
++ ipaddress =
++ std::get<std::string>(properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ std::get<uint8_t>(properties["PrefixLength"]);
++ status = 0;
++ }
++ }
++ // ignore the exception, as it is a valid condition that
++ // the system is not configured with any IP.
++ catch (InternalFailure& e)
++ {
++ // nothing to do.
++ }
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ ipv6AddressSource = channelConf->ipv6AddressSource;
++ ipaddress = channelConf->ipv6Addr.c_str();
++ prefixLength = channelConf->ipv6Prefix;
++ status = 1;
++ }
++
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_STATUS_SIZE> buf = {
++ current_revision, ipv6SetSelector, ipv6AddressSource};
++ inet_pton(AF_INET6, ipaddress.c_str(),
++ reinterpret_cast<void*>(&buf[3]));
++ buf[20] = prefixLength;
++ buf[21] = status;
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_STATIC_DUID_STORAGE_LENGTH:
++ {
++ // DHCP unique identified
++ // Only 1 read-only 16-byte Block needed
++ uint8_t duidLength = 1;
++ std::array<uint8_t, 2> buf = {current_revision, duidLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_STATIC_DUIDS:
++ {
++ std::string macAddress;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ auto macObjectInfo =
++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ auto variant = ipmi::getDbusProperty(
++ bus, macObjectInfo.second, macObjectInfo.first,
++ ipmi::network::MAC_INTERFACE, "MACAddress");
++
++ macAddress = std::get<std::string>(variant);
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ macAddress = channelConf->macAddress;
++ }
++
++ std::array<uint8_t,
++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)>
++ buf;
++ buf = {current_revision,
++ reqptr->parameter_set,
++ reqptr->parameter_block,
++ DUID_LEN,
++ 0, // Filler byte
++ DUID_LL_TYPE,
++ 0, // Filler byte
++ DUIC_ETH_HW_TYPE};
++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]),
++ (&buf[13]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DYNAMIC_ADDRESSES:
++ {
++ std::string ipaddress;
++ uint8_t ipv6AddressSource = 0;
++ uint8_t prefixLength = 0;
++ uint8_t status = 0;
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ try
++ {
++ auto ipObjectInfo =
++ ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ auto properties = ipmi::getAllDbusProperties(
++ bus, ipObjectInfo.second, ipObjectInfo.first,
++ ipmi::network::IP_INTERFACE);
++
++ if (std::get<std::string>(properties["Origin"]) ==
++ "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
++ {
++ ipaddress =
++ std::get<std::string>(properties["Address"]);
++ ipv6AddressSource = 0x81; // Looking at bit 0 and bit 7
++ prefixLength =
++ std::get<uint8_t>(properties["PrefixLength"]);
++ status = 0;
++ }
++ else
++ {
++ status = 1;
++ }
++ }
++ // ignore the exception, as it is a valid condition that
++ // the system is not configured with any IP.
++ catch (InternalFailure& e)
++ {
++ // nothing to do.
++ }
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ ipaddress = channelConf->ipv6Addr;
++ ipv6AddressSource = channelConf->ipv6AddressSource;
++ prefixLength = channelConf->ipv6Prefix;
++ status = channelConf->ipv6AddressStatus;
++ }
++
++ uint8_t ipv6SetSelector = 0;
++ std::array<uint8_t, 22> buf = {current_revision, ipv6SetSelector,
++ ipv6AddressSource};
++ inet_pton(AF_INET6, ipaddress.c_str(),
++ reinterpret_cast<void*>(&buf[3]));
++ buf[20] = prefixLength;
++ buf[21] = status;
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUID_STOR_LEN:
++ {
++ uint8_t duidLength = 0;
++ // Only 1 read-only 16-byte Block needed
++ duidLength = 1;
++
++ std::array<uint8_t, 2> buf = {current_revision, duidLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_DHCPV6_DYNAMIC_DUIDS:
++ {
++ std::string macAddress;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++ auto macObjectInfo =
++ ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ auto variant = ipmi::getDbusProperty(
++ bus, macObjectInfo.second, macObjectInfo.first,
++ ipmi::network::MAC_INTERFACE, "MACAddress");
++
++ macAddress = std::get<std::string>(variant);
++ }
++ else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
++ {
++ macAddress = channelConf->macAddress;
++ }
++
++ std::array<uint8_t,
++ ipmi::network::IPV6_DUID_SIZE + sizeof(current_revision)>
++ buf;
++ buf = {current_revision,
++ reqptr->parameter_set,
++ reqptr->parameter_block,
++ DUID_LEN,
++ 0, // Filler byte
++ DUID_LL_TYPE,
++ 0, // Filler byte
++ DUIC_ETH_HW_TYPE};
++
++ sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
++ (&buf[8]), (&buf[9]), (&buf[10]), (&buf[11]), (&buf[12]),
++ (&buf[13]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_ROUTER_ADDRESS_CONF_CTRL:
++ {
++ // Determine if automated router discovery occurs when static
++ // addresses are used for the bmc
++
++ auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE;
++ std::string networkInterfacePath;
++ uint8_t dynamicRA;
++ if (channelConf->lan_set_in_progress == SET_COMPLETE)
++ {
++
++ try
++ {
++ ipmi::ObjectTree ancestorMap;
++ // if the system is having ip object,then
++ // get the IP object.
++ auto ipObject =
++ ipmi::getDbusObject(bus, ipmi::network::IP_INTERFACE,
++ ipmi::network::ROOT, ethIP);
++
++ // Get the parent interface of the IP object.
++ try
++ {
++ ipmi::InterfaceList interfaces;
++ interfaces.emplace_back(
++ ipmi::network::ETHERNET_INTERFACE);
++
++ ancestorMap = ipmi::getAllAncestors(
++ bus, ipObject.first, std::move(interfaces));
++ }
++ catch (InternalFailure& e)
++ {
++ // if unable to get the parent interface
++ // then commit the error and return.
++ log<level::ERR>(
++ "Unable to get the parent interface",
++ entry("PATH=%s", ipObject.first.c_str()),
++ entry("INTERFACE=%s",
++ ipmi::network::ETHERNET_INTERFACE));
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ // for an ip object there would be single parent
++ // interface.
++ networkInterfacePath = ancestorMap.begin()->first;
++ }
++ catch (InternalFailure& e)
++ {
++ // if there is no ip configured on the system,then
++ // get the network interface object.
++ auto networkInterfaceObject = ipmi::getDbusObject(
++ bus, ipmi::network::ETHERNET_INTERFACE,
++ ipmi::network::ROOT, ethdevice);
++
++ networkInterfacePath = networkInterfaceObject.first;
++ }
++
++ auto variant = ipmi::getDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfacePath,
++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA");
++ dynamicRA = std::get<bool>(variant);
++ }
++ else
++ {
++ dynamicRA = channelConf->ipv6RouterAddressConfigControl;
++ }
++
++ std::array<uint8_t, 2> buf = {current_revision, dynamicRA};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_IP_ADDR:
++ {
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision};
++ inet_pton(AF_INET6, channelConf->ipv6GatewayAddr.c_str(),
++ reinterpret_cast<void*>(&buf[1]));
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_LEN:
++ {
++ std::array<uint8_t, 2> buf = {current_revision,
++ channelConf->ipv6GatewayPrefixLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_1_PREFIX_VAL:
++ {
++ constexpr uint8_t setSelector = 0;
++ std::array<uint8_t, sizeof(setSelector) +
++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision, setSelector};
++
++ inet_pton(AF_INET6, channelConf->ipv6GatewayPrefixValue.c_str(),
++ reinterpret_cast<void*>(&buf[2]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_IP_ADDR:
++ {
++ std::array<uint8_t, ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision};
++ inet_pton(AF_INET6, channelConf->ipv6BackupGatewayAddr.c_str(),
++ reinterpret_cast<void*>(&buf[1]));
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_LEN:
++ {
++ std::array<uint8_t, 2> buf = {
++ current_revision, channelConf->ipv6BackupGatewayPrefixLength};
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
++ case LanParam::IPV6_STATIC_ROUTER_2_PREFIX_VAL:
++ {
++
++ constexpr uint8_t setSelector = 0;
++ std::array<uint8_t, sizeof(setSelector) +
++ ipmi::network::IPV6_ADDRESS_SIZE_BYTE +
++ sizeof(current_revision)>
++ buf = {current_revision, setSelector};
++ inet_pton(AF_INET6,
++ channelConf->ipv6BackupGatewayPrefixValue.c_str(),
++ reinterpret_cast<void*>(&buf[2]));
++
++ std::copy(buf.begin(), buf.end(), static_cast<uint8_t*>(response));
++ *data_len = buf.size();
++ break;
++ }
+ default:
+ log<level::ERR>("Unsupported parameter",
+ entry("PARAMETER=0x%x", reqptr->parameter));
+@@ -921,6 +1546,16 @@ void applyChanges(int channel)
+ ipaddress, prefix);
+ }
+
++ if (!channelConf->ipv6Addr.empty() &&
++ channelConf->ipv6AddressSource ==
++ 0x80) // Check if IPv6 static addresses are enabled
++ {
++ ipmi::network::createIP(bus, ipmi::network::SERVICE,
++ networkInterfacePath, ipv6Protocol,
++ channelConf->ipv6Addr,
++ channelConf->ipv6Prefix);
++ }
++
+ if (!gateway.empty())
+ {
+ ipmi::setDbusProperty(bus, systemObject.second,
+@@ -928,7 +1563,24 @@ void applyChanges(int channel)
+ ipmi::network::SYSTEMCONFIG_INTERFACE,
+ "DefaultGateway", std::string(gateway));
+ }
++ else if (!channelConf->ipv6GatewayAddr.empty())
++ {
++ ipmi::setDbusProperty(
++ bus, systemObject.second, systemObject.first,
++ ipmi::network::SYSTEMCONFIG_INTERFACE, "DefaultGateway",
++ std::string(channelConf->ipv6GatewayAddr));
++ }
+ }
++ // set IPAddress Enables
++ ipmi::setDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfaceObject.first,
++ ipmi::network::ETHERNET_INTERFACE, "IPAddressEnables",
++ ipAddressEnablesType[channelConf->ipv6AddressingEnables]);
++
++ ipmi::setDbusProperty(
++ bus, ipmi::network::SERVICE, networkInterfaceObject.first,
++ ipmi::network::ETHERNET_INTERFACE, "IPv6AcceptRA",
++ (bool)channelConf->ipv6RouterAddressConfigControl);
+ }
+ catch (InternalFailure& e)
+ {
+diff --git a/transporthandler.hpp b/transporthandler.hpp
+index 04d4673..bd23391 100644
+--- a/transporthandler.hpp
++++ b/transporthandler.hpp
+@@ -79,6 +79,28 @@ enum class LanParam : uint8_t
+ IPV6_NEIGHBOR_TIMING_CONFIGURATION = 80,
+ };
+
++// Data length of parameters
++constexpr size_t LAN_PARAM_INPROGRESS_SIZE = 3;
++constexpr size_t LAN_PARAM_IP_SIZE = 6;
++constexpr size_t LAN_PARAM_IPSRC_SIZE = 3;
++constexpr size_t LAN_PARAM_MAC_SIZE = 8;
++constexpr size_t LAN_PARAM_SUBNET_SIZE = 6;
++constexpr size_t LAN_PARAM_GATEWAY_SIZE = 6;
++constexpr size_t LAN_PARAM_VLAN_SIZE = 4;
++constexpr size_t LAN_PARAM_IPV6_AND_IPV4_ENABLES_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ADDRESSES_SIZE = 23;
++constexpr size_t LAN_PARAM_IPV6_ROUTER_ADDRESS_CONF_CTRL_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_IP_ADDR_SIZE = 18;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_LEN_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_1_PREFIX_VAL_SIZE = 19;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_IP_ADDR_SIZE = 18;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_LEN_SIZE = 3;
++constexpr size_t LAN_PARAM_IPV6_STATIC_ROUTER_2_PREFIX_VAL_SIZE = 19;
++
++constexpr uint8_t DUID_LEN = 10;
++constexpr uint8_t DUID_LL_TYPE = 3;
++constexpr uint8_t DUIC_ETH_HW_TYPE = 1;
++
+ constexpr uint8_t SET_COMPLETE = 0;
+ constexpr uint8_t SET_IN_PROGRESS = 1;
+ constexpr uint8_t SET_COMMIT_WRITE = 2; // Optional
+@@ -101,6 +123,20 @@ struct ChannelConfig_t
+ uint8_t lan_set_in_progress = SET_COMPLETE;
+ bool flush = false;
+
++ // IPV6 parameters
++ uint8_t ipv6AddressSource = 0x0;
++ uint8_t ipv6AddressingEnables = 0x2;
++ std::string ipv6Addr;
++ uint8_t ipv6Prefix = 32;
++ uint8_t ipv6AddressStatus = 0x0;
++ uint8_t ipv6RouterAddressConfigControl = 0x0;
++ std::string ipv6GatewayAddr;
++ std::string ipv6BackupGatewayAddr;
++ uint8_t ipv6GatewayPrefixLength;
++ std::string ipv6GatewayPrefixValue;
++ uint8_t ipv6BackupGatewayPrefixLength = 0x0;
++ std::string ipv6BackupGatewayPrefixValue;
++
+ void clear()
+ {
+ ipaddr.clear();
+@@ -111,6 +147,20 @@ struct ChannelConfig_t
+ ipsrc = ipmi::network::IPOrigin::UNSPECIFIED;
+ lan_set_in_progress = SET_COMPLETE;
+ flush = false;
++
++ // IPv6
++ ipv6Addr.clear();
++ ipv6GatewayAddr.clear();
++ ipv6BackupGatewayAddr.clear();
++ ipv6AddressingEnables = 0x2;
++ ipv6AddressSource = 0x0;
++ ipv6Prefix = 32;
++ ipv6AddressStatus = 0x0;
++ ipv6RouterAddressConfigControl = 0x0;
++ ipv6GatewayPrefixLength = 0x0;
++ ipv6GatewayPrefixValue.clear();
++ ipv6BackupGatewayPrefixLength = 0x0;
++ ipv6BackupGatewayPrefixValue.clear();
+ }
+ };
+
+--
+2.17.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..c1ec6ac6e
--- /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,56 @@
+From 4953a9f2233fd24a28da84443cea6aebecd14fbc Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 17 Sep 2018 13:20:54 +0800
+Subject: [PATCH] fix "get system GUID" ipmi command
+
+Change-Id: I15c71607c24ad8b3e2c9065a5470002ecb1761bb
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ apphandler.cpp | 7 ++-----
+ host-ipmid-whitelist.conf | 1 +
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/apphandler.cpp b/apphandler.cpp
+index f2889c5..9149373 100644
+--- a/apphandler.cpp
++++ b/apphandler.cpp
+@@ -48,7 +48,7 @@ extern sd_bus* bus;
+
+ constexpr auto bmc_state_interface = "xyz.openbmc_project.State.BMC";
+ constexpr auto bmc_state_property = "CurrentBMCState";
+-constexpr auto bmc_interface = "xyz.openbmc_project.Inventory.Item.Bmc";
++// phosphor-setting-manager is the unique service that holds this interface
+ constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
+ constexpr auto bmc_guid_property = "UUID";
+ constexpr auto bmc_guid_len = 16;
+@@ -546,8 +545,7 @@ ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ {
+ // Get the Inventory object implementing BMC interface
+ ipmi::DbusObjectInfo bmcObject =
+- ipmi::getDbusObject(bus, bmc_interface);
+-
++ ipmi::getDbusObject(bus, bmc_guid_interface);
+ // Read UUID property value from bmcObject
+ // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
+ auto variant =
+@@ -591,7 +589,6 @@ ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ catch (const InternalFailure& e)
+ {
+ log<level::ERR>("Failed in reading BMC UUID property",
+- entry("INTERFACE=%s", bmc_interface),
+ entry("PROPERTY_INTERFACE=%s", bmc_guid_interface),
+ entry("PROPERTY=%s", bmc_guid_property));
+ return IPMI_CC_UNSPECIFIED_ERROR;
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 2c37ac9..164edbe 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -40,3 +40,4 @@
+ 0x2C:0x06 //<Group Extension>:<Get Asset Tag>
+ 0x2C:0x07 //<Group Extension>:<Get Sensor Info>
+ 0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
++0x30:0x41 //<OEM>:<Set System GUID>
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch
new file mode 100644
index 000000000..ae10ab60a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0013-ipmi-add-set-bios-id-to-whitelist.patch
@@ -0,0 +1,25 @@
+From ad7276f3aedb6f5aed315db57406c98f2bf71a09 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 24 Jul 2018 13:21:52 +0800
+Subject: [PATCH] [ipmi] add set bios id to whitelist
+
+Add "SetBIOSId" and "GetDeviceInfo" 2 OEM commands into whitelist
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ host-ipmid-whitelist.conf | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 164edbe..db54a49 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -41,3 +41,5 @@
+ 0x2C:0x07 //<Group Extension>:<Get Sensor Info>
+ 0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
+ 0x30:0x41 //<OEM>:<Set System GUID>
++0x30:0x26 //<OEM>:<Set BIOS ID>
++0x30:0x27 //<OEM>:<Get Device Info>
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch
new file mode 100644
index 000000000..cba0cde32
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch
@@ -0,0 +1,143 @@
+From 6d5a372e0cf98de4d97a88d2cd42a00b7a8f034f Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 16 Sep 2018 21:32:38 +0800
+Subject: [PATCH] Implement IPMI Commmand - Get Host Restart Cause.
+
+It supports to track the information about what
+action last caused the system to restart.
+Return value includes: restart_cause and channel_number.
+
+According to IPMI Spec, it includes 12 types as following:
+1. Unknown 0x0
+2. IpmiCommand 0x1
+3. ResetButton 0x2
+4. PowerButton 0x3
+5. WatchdogTimer 0x4
+6. OEM 0x5
+7. PowerPolicyAlwaysOn 0x6
+8. PowerPolicyPreviousState 0x7
+9. PEF-Reset 0x8
+10. PEF-PowerCycle 0x9
+11. SoftReset 0xA
+12. RTC-Wakeup 0xB
+
+Change-Id: Id3b32e271b85b5fc4c69d5ca40227f8f9c08ce48
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 54 +++++++++++++++++++++++++++++++++++++++
+ chassishandler.hpp | 1 +
+ host-ipmid-whitelist.conf | 1 +
+ 3 files changed, 56 insertions(+)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index d20b220..8a8cb26 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -90,6 +90,11 @@ static constexpr auto chassisPOHStateIntf =
+ "xyz.openbmc_project.State.PowerOnHours";
+ static constexpr auto pOHCounterProperty = "POHCounter";
+ static constexpr auto match = "chassis0";
++const static constexpr char* stateHostInterface =
++ "xyz.openbmc_project.State.Host";
++const static constexpr char* hostRestartCauseInterface =
++ "xyz.openbmc_project.State.Host.HostRestartCause";
++const static constexpr char* hostRestartCause = "HostRestartCause";
+ const static constexpr char chassisCapIntf[] =
+ "xyz.openbmc_project.Control.ChassisCapabilities";
+ const static constexpr char chassisCapFlagsProp[] = "CapabilitiesFlags";
+@@ -176,6 +181,13 @@ struct set_sys_boot_options_t
+ uint8_t data[SIZE_BOOT_OPTION];
+ } __attribute__((packed));
+
++struct GetSysRestartCauseResponse
++{
++ uint8_t restartCause;
++ uint8_t channelNum;
++
++} __attribute__((packed));
++
+ int getHostNetworkData(get_sys_boot_options_response_t* respptr)
+ {
+ ipmi::PropertyMap properties;
+@@ -1584,6 +1596,44 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ return rc;
+ }
+
++ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
++ ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
++ ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
++{
++ ipmi_ret_t rc = IPMI_CC_OK;
++
++ GetSysRestartCauseResponse* resp = (GetSysRestartCauseResponse*)response;
++ std::fill(reinterpret_cast<uint8_t*>(resp),
++ reinterpret_cast<uint8_t*>(resp) + sizeof(*resp), 0);
++ if (*data_len != 0)
++ {
++ rc = IPMI_CC_REQ_DATA_LEN_INVALID;
++ return rc;
++ }
++
++ try
++ {
++ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
++ ipmi::DbusObjectInfo hostObject =
++ ipmi::getDbusObject(bus, stateHostInterface);
++ ipmi::Value variant =
++ ipmi::getDbusProperty(bus, hostObject.second, hostObject.first,
++ hostRestartCauseInterface, hostRestartCause);
++ resp->restartCause = variant.get<uint8_t>();
++ }
++
++ catch (std::exception& e)
++ {
++ log<level::ERR>(e.what());
++ rc = IPMI_CC_UNSPECIFIED_ERROR;
++ return rc;
++ }
++ resp->channelNum = 0; // Fix to primary channel.
++ *data_len = sizeof(GetSysRestartCauseResponse);
++
++ return rc;
++}
++
+ /** @brief implements Get POH counter command
+ * @parameter
+ * - none
+@@ -1739,4 +1789,8 @@ void register_netfn_chassis_functions()
+ ipmi::chassis::cmdSetPowerRestorePolicy,
+ ipmi::Privilege::Operator,
+ ipmiChassisSetPowerRestorePolicy);
++
++ // <get Host Restart Cause>
++ ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_RESTART_CAUSE, NULL,
++ ipmi_chassis_get_sys_restart_cause, PRIVILEGE_USER);
+ }
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 49b5ef8..2c42b11 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -17,6 +17,7 @@ enum ipmi_netfn_chassis_cmds
+ // Set Power Restore Policy
+ IPMI_CMD_SET_RESTORE_POLICY = 0x06,
+ // Get capability bits
++ IPMI_CMD_GET_SYS_RESTART_CAUSE = 0x07,
+ IPMI_CMD_SET_SYS_BOOT_OPTIONS = 0x08,
+ IPMI_CMD_GET_SYS_BOOT_OPTIONS = 0x09,
+ IPMI_CMD_GET_POH_COUNTER = 0x0F,
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index c1fca1d..94232de 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -4,6 +4,7 @@
+ 0x00:0x02 //<Chassis>:<Chassis Control>
+ 0x00:0x05 //<Chassis>:<Set Chassis Capabilities>
+ 0x00:0x06 //<Chassis>:<Set Power Restore Policy>
++0x00:0x07 //<Chassis>:<Get System Restart Cause>
+ 0x00:0x08 //<Chassis>:<Set System Boot Options>
+ 0x00:0x09 //<Chassis>:<Get System Boot Options>
+ 0x00:0x0F //<Chassis>:<Get POH Counter Command>
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch
new file mode 100644
index 000000000..fdaa91085
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch
@@ -0,0 +1,25 @@
+From cf466ba2c66a95825ae0014d7c378ad63b050d2f Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Wed, 15 Aug 2018 14:50:04 +0800
+Subject: [PATCH] [ipmi] add oem command "get AIC FRU" to whitelist
+
+Intel BIOS requires this oem command to get addon card FRU info.
+Add to whitelist to unblock.
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index db54a49..49746a2 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -43,3 +43,4 @@
+ 0x30:0x41 //<OEM>:<Set System GUID>
+ 0x30:0x26 //<OEM>:<Set BIOS ID>
+ 0x30:0x27 //<OEM>:<Get Device Info>
++0x30:0x31 //<OEM>:<Get AIC card FRU>
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch
new file mode 100644
index 000000000..aba5eb095
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch
@@ -0,0 +1,71 @@
+From 59287a8869b5253a1b4203e0cc8a92f063dcc7e6 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Tue, 25 Sep 2018 16:08:22 +0800
+Subject: [PATCH] Fix "Unspecified error" on ipmi restart cause command
+
+Needs to convert the dbus value(enum) into ipmi value(uint8)
+
+Tested by:
+ipmitool chassis restart_cause
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 40eb4f5..c3d4931 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -106,7 +106,7 @@ static constexpr auto match = "chassis0";
+ const static constexpr char* stateHostInterface =
+ "xyz.openbmc_project.State.Host";
+ const static constexpr char* hostRestartCauseInterface =
+- "xyz.openbmc_project.State.Host.HostRestartCause";
++ "xyz.openbmc_project.State.Host";
+ const static constexpr char* hostRestartCause = "HostRestartCause";
+ const static constexpr char chassisCapIntf[] =
+ "xyz.openbmc_project.Control.ChassisCapabilities";
+@@ -1764,6 +1764,26 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ return rc;
+ }
+
++namespace restart_cause
++{
++
++using namespace sdbusplus::xyz::openbmc_project::State::server;
++
++std::map<Host::RestartCause, uint8_t> dbusToIpmi = {
++ {Host::RestartCause::Unknown, 0x0},
++ {Host::RestartCause::IpmiCommand, 0x1},
++ {Host::RestartCause::ResetButton, 0x2},
++ {Host::RestartCause::PowerButton, 0x3},
++ {Host::RestartCause::WatchdogTimer, 0x4},
++ {Host::RestartCause::OEM, 0x5},
++ {Host::RestartCause::PowerPolicyAlwaysOn, 0x6},
++ {Host::RestartCause::PowerPolicyPreviousState, 0x7},
++ {Host::RestartCause::PEFReset, 0x8},
++ {Host::RestartCause::PEFPowerCycle, 0x9},
++ {Host::RestartCause::SoftReset, 0xa},
++ {Host::RestartCause::RTCWakeup, 0xb}};
++} // namespace restart_cause
++
+ ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
+ ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
+ ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
+@@ -1787,7 +1807,11 @@ ipmi_ret_t ipmi_chassis_get_sys_restart_cause(
+ ipmi::Value variant =
+ ipmi::getDbusProperty(bus, hostObject.second, hostObject.first,
+ hostRestartCauseInterface, hostRestartCause);
+- resp->restartCause = variant.get<uint8_t>();
++
++ std::string restartCause =
++ sdbusplus::message::variant_ns::get<std::string>(variant);
++ resp->restartCause = restart_cause::dbusToIpmi.at(
++ restart_cause::Host::convertRestartCauseFromString(restartCause));
+ }
+
+ catch (std::exception& e)
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch
new file mode 100644
index 000000000..b800632cc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0050-enable-6-oem-commands.patch
@@ -0,0 +1,15 @@
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 22a2a3c..5d71698 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -49,3 +49,10 @@
+ 0x30:0x26 //<OEM>:<Set BIOS ID>
+ 0x30:0x27 //<OEM>:<Get Device Info>
+ 0x30:0x31 //<OEM>:<Get AIC card FRU>
++0x30:0x54 //<OEM>:<Set Power Restore Delay>
++0x30:0x55 //<OEM>:<Get Power Restore Delay>
++0x30:0x9A //<OEM>:<Get Processor Error Config>
++0x30:0x9B //<OEM>:<Set Processor Error Config>
++0x30:0xB0 //<OEM>:<Get LED Status>
++0x30:0xE9 //<OEM>:<Get BIOS Post Codes>
++
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/0054-Fix-User-commands-require-channel-layer-lib.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch
new file mode 100644
index 000000000..bf6f672cf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch
@@ -0,0 +1,37 @@
+From 5d0c9d2217dbe369daffb8a92d7b5e7d7d34d566 Mon Sep 17 00:00:00 2001
+From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+Date: Sat, 2 Mar 2019 20:08:32 +0530
+Subject: [PATCH] Fix: User commands require channel layer lib
+
+As channel layer is separated out from user layer lib, it
+has to be manually included in libusercommands, as user
+command handlers use channel layer API's
+
+Tested-by:
+1. Made sure that libusercommands are loaded on it's own
+without any undefined symbol error.
+2. ipmitool user list 1 works on host interface
+
+Change-Id: I6652ad248e01afc1349e3a9612754dbdb84b96ad
+Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
+---
+ Makefile.am | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index bb7bdbf..4e9101e 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -120,7 +120,8 @@ libipmi20_la_CXXFLAGS = $(COMMON_CXX)
+ providers_LTLIBRARIES += libusercmds.la
+ libusercmds_la_LIBADD = \
+ libipmid/libipmid.la \
+- user_channel/libuserlayer.la
++ user_channel/libuserlayer.la \
++ user_channel/libchannellayer.la
+ libusercmds_la_SOURCES = \
+ user_channel/usercommands.cpp
+ libusercmds_la_LDFLAGS = \
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch
new file mode 100644
index 000000000..fd7cf1851
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch
@@ -0,0 +1,176 @@
+From b8b88a5c0f9e9cb6023cb8d5453e5cfadaa1a375 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Fri, 4 Jan 2019 10:50:21 +0800
+Subject: [PATCH] Implement set front panel button enables command
+
+Through modify buttons' property "Enabled" to disable/enable
+corresponding button.
+Currently support power and reset button.
+
+Test-By: ipmitool raw 0x0 0xa 0x2 //disable reset button
+ ipmitool raw 0x0 0xa 0x1 //disable power button
+ ipmitool raw 0x0 0xa 0x0 //enable all buttons
+
+Change-Id: Ice6f58edb898689f7a7fa08ad078d25fccaab27e
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ chassishandler.cpp | 98 +++++++++++++++++++++++++++++++++++++++
+ chassishandler.hpp | 1 +
+ host-ipmid-whitelist.conf | 1 +
+ 3 files changed, 100 insertions(+)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 4b42b3c..1a5b805 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -112,6 +112,8 @@ const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress";
+ const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress";
+ static constexpr uint8_t chassisCapFlagMask = 0x0f;
+ static constexpr uint8_t chassisCapAddrMask = 0xfe;
++static constexpr uint8_t disableResetButton = 0x2;
++static constexpr uint8_t disablePowerButton = 0x1;
+ static constexpr const char* powerButtonIntf =
+ "xyz.openbmc_project.Chassis.Buttons.Power";
+ static constexpr const char* powerButtonPath =
+@@ -140,6 +142,19 @@ struct GetPOHCountResponse
+ uint8_t front_panel_button_cap_status;
+ } __attribute__((packed)) ipmi_get_chassis_status_t;
+
++typedef struct
++{
++ uint8_t disables; // Front Panel Button Enables
++ //[7:4] - reserved
++ //[3] - 1b = disable Standby (sleep) button for entering standby (sleep)
++ //(control can still be used to wake the system)
++ //[2] - 1b = disable Diagnostic Interrupt button
++ //[1] - 1b = disable Reset button
++ //[0] - 1b = disable Power off button for power off only (in the case there
++ // is a single combined power/standby (sleep) button, then this also
++ // disables sleep requests via that button)
++} __attribute__((packed)) IPMISetFrontPanelButtonEnablesReq;
++
+ // Phosphor Host State manager
+ namespace State = sdbusplus::xyz::openbmc_project::State::server;
+
+@@ -1721,6 +1738,82 @@ ipmi_ret_t ipmi_chassis_set_power_restore_policy(
+ return ipmi::responseSuccess(power_policy::allSupport);
+ }
+
++ipmi_ret_t ipmiSetFrontPanelButtonEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
++ ipmi_request_t request,
++ ipmi_response_t response,
++ ipmi_data_len_t data_len,
++ ipmi_context_t context)
++{
++ bool enable = false;
++ constexpr const char* powerButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Power";
++ constexpr const char* powerButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Power0";
++ constexpr const char* resetButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Reset";
++ constexpr const char* resetButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Reset0";
++ using namespace chassis::internal;
++
++ IPMISetFrontPanelButtonEnablesReq* req =
++ static_cast<IPMISetFrontPanelButtonEnablesReq*>(request);
++ if (*data_len != 1)
++ {
++ *data_len = 0;
++ log<level::ERR>("IPMI request len is invalid");
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++ *data_len = 0;
++ if (req->disables & disablePowerButton)
++ {
++ // Disable power button
++ enable = false;
++ }
++ else
++ {
++ // Enable power button
++ enable = true;
++ }
++ // set power button Enabled property
++ try
++ {
++ auto service = ipmi::getService(dbus, powerButtonIntf, powerButtonPath);
++ ipmi::setDbusProperty(dbus, service, powerButtonPath, powerButtonIntf,
++ "Enabled", enable);
++ }
++ catch (sdbusplus::exception::SdBusError& e)
++ {
++ log<level::ERR>(e.what());
++ log<level::ERR>("Fail to set power button Enabled property");
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ if (req->disables & disableResetButton)
++ {
++ // disable reset button
++ enable = false;
++ }
++ else
++ {
++ // enable reset button
++ enable = true;
++ }
++ // set reset button Enabled property
++ try
++ {
++ auto service = ipmi::getService(dbus, resetButtonIntf, resetButtonPath);
++ ipmi::setDbusProperty(dbus, service, resetButtonPath, resetButtonIntf,
++ "Enabled", enable);
++ }
++ catch (sdbusplus::exception::SdBusError& e)
++ {
++ log<level::ERR>(e.what());
++ log<level::ERR>("Fail to set reset button Enabled property");
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ return IPMI_CC_OK;
++}
++
+ void register_netfn_chassis_functions()
+ {
+ createIdentifyTimer();
+@@ -1733,6 +1826,11 @@ void register_netfn_chassis_functions()
+ ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL,
+ ipmi_get_chassis_cap, PRIVILEGE_USER);
+
++ // Set Front Panel Button Enables
++ ipmi_register_callback(NETFUN_CHASSIS,
++ IPMI_CMD_SET_FRONT_PANEL_BUTTON_ENABLES, NULL,
++ ipmiSetFrontPanelButtonEnables, PRIVILEGE_ADMIN);
++
+ // Set Chassis Capabilities
+ ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_CHASSIS_CAP, NULL,
+ ipmi_set_chassis_cap, PRIVILEGE_USER);
+diff --git a/chassishandler.hpp b/chassishandler.hpp
+index 49b5ef8..f4a6bff 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -19,6 +19,7 @@ enum ipmi_netfn_chassis_cmds
+ IPMI_CMD_GET_SYS_RESTART_CAUSE = 0x07,
+ IPMI_CMD_SET_SYS_BOOT_OPTIONS = 0x08,
+ IPMI_CMD_GET_SYS_BOOT_OPTIONS = 0x09,
++ IPMI_CMD_SET_FRONT_PANEL_BUTTON_ENABLES = 0x0A,
+ IPMI_CMD_GET_POH_COUNTER = 0x0F,
+ };
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index e5cd0b5..d96d9ed 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -6,6 +6,7 @@
+ 0x00:0x07 //<Chassis>:<Get System Restart Cause>
+ 0x00:0x08 //<Chassis>:<Set System Boot Options>
+ 0x00:0x09 //<Chassis>:<Get System Boot Options>
++0x00:0x0A //<Chassis>:<Set Front Panel Button Enables>
+ 0x00:0x0F //<Chassis>:<Get POH Counter Command>
+ 0x04:0x02 //<Sensor/Event>:<Platform event>
+ 0x04:0x2D //<Sensor/Event>:<Get Sensor Reading>
+--
+2.19.1
+
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..3a77887a0
--- /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,102 @@
+From 949db3a985719335d3df77db368eb2b296756749 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>
+---
+ chassishandler.cpp | 26 +++++++++++++++++++++++++-
+ chassishandler.hpp | 3 +++
+ 2 files changed, 28 insertions(+), 1 deletion(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 6d14d1b..553afa8 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -1351,6 +1351,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,
+@@ -1365,11 +1369,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.
+@@ -1505,6 +1519,16 @@ 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) {
++ 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 2c42b11..6a24507 100644
+--- a/chassishandler.hpp
++++ b/chassishandler.hpp
+@@ -28,6 +28,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,
+@@ -49,6 +50,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
+@@ -56,6 +58,7 @@ enum class BootOptionParameter : size_t
+
+ enum class BootOptionResponseSize : size_t
+ {
++ SET_IN_PROGRESS = 3,
+ BOOT_FLAGS = 5,
+ OPAL_NETWORK_SETTINGS = 50
+ };
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch
new file mode 100644
index 000000000..a96707d44
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch
@@ -0,0 +1,195 @@
+From 6e37e02a4f200507627a82f6dba00a9c9d877cb2 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Mon, 18 Mar 2019 23:05:16 +0800
+Subject: [PATCH] Add timer use/actions support
+
+Based on IPMI spec, add timer use/actions support,
+and add input data checking
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ app/watchdog.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++-----
+ app/watchdog_service.cpp | 8 +++++++
+ app/watchdog_service.hpp | 8 +++++++
+ 3 files changed, 72 insertions(+), 6 deletions(-)
+
+diff --git a/app/watchdog.cpp b/app/watchdog.cpp
+index 1a5d19c..3b61055 100644
+--- a/app/watchdog.cpp
++++ b/app/watchdog.cpp
+@@ -89,6 +89,13 @@ static constexpr uint8_t wd_dont_stop = 0x1 << 6;
+ static constexpr uint8_t wd_timeout_action_mask = 0x3;
+
+ static constexpr uint8_t wdTimerUseMask = 0x7;
++static constexpr uint8_t wdTimerUseResTimer1 = 0x0;
++static constexpr uint8_t wdTimerUseResTimer2 = 0x6;
++static constexpr uint8_t wdTimerUseResTimer3 = 0x7;
++static constexpr uint8_t wdTimerUseRes = 0x38;
++
++static constexpr uint8_t wdTimerActionMask = 0xcc;
++static constexpr uint8_t wdTimerUseExpMask = 0xc1;
+
+ enum class IpmiAction : uint8_t
+ {
+@@ -186,6 +193,11 @@ static_assert(sizeof(wd_set_req) == 6, "wd_set_req has invalid size.");
+ static_assert(sizeof(wd_set_req) <= MAX_IPMI_BUFFER,
+ "wd_get_res can't fit in request buffer.");
+
++static uint8_t timerLogFlags = 0;
++static uint8_t timerActions = 0;
++
++static uint8_t timerUseExpirationFlags = 0;
++
+ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+@@ -203,6 +215,24 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ req.initial_countdown = le16toh(req.initial_countdown);
+ *data_len = 0;
+
++ if (((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer1) ||
++ ((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer2) ||
++ ((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer3) ||
++ (req.timer_use & wdTimerUseRes) ||
++ (req.timer_action & wdTimerActionMask) ||
++ (req.expire_flags & wdTimerUseExpMask))
++ {
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
++
++ if (req.pretimeout > (req.initial_countdown / 10))
++ {
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
++
++ timerLogFlags = req.timer_use & 0x80;
++ timerActions = req.timer_action;
++
+ try
+ {
+ WatchdogService wd_service;
+@@ -221,6 +251,10 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ static_cast<IpmiTimerUse>(req.timer_use & wdTimerUseMask);
+ wd_service.setTimerUse(ipmiTimerUseToWdTimerUse(ipmiTimerUse));
+
++ wd_service.setExpiredTimerUse(WatchdogService::TimerUse::Reserved);
++
++ timerUseExpirationFlags &= ~req.expire_flags;
++
+ // Set the new interval and the time remaining deci -> mill seconds
+ const uint64_t interval = req.initial_countdown * 100;
+ wd_service.setInterval(interval);
+@@ -339,7 +373,6 @@ static_assert(sizeof(wd_get_res) == 8, "wd_get_res has invalid size.");
+ static_assert(sizeof(wd_get_res) <= MAX_IPMI_BUFFER,
+ "wd_get_res can't fit in response buffer.");
+
+-static constexpr uint8_t wd_dont_log = 0x1 << 7;
+ static constexpr uint8_t wd_running = 0x1 << 6;
+
+ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+@@ -358,20 +391,37 @@ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ // Build and return the response
+ wd_get_res res;
+- res.timer_use = wd_dont_log;
+- res.timer_action =
+- static_cast<uint8_t>(wdActionToIpmiAction(wd_prop.expireAction));
++ res.timer_use |= timerLogFlags;
++ res.timer_action = timerActions;
+
+ // Interval and timeRemaining need converted from milli -> deci seconds
+ res.initial_countdown = htole16(wd_prop.interval / 100);
++
++ if (wd_prop.expiredTimerUse != WatchdogService::TimerUse::Reserved)
++ {
++ timerUseExpirationFlags |=
++ 1 << static_cast<uint8_t>(
++ wdTimerUseToIpmiTimerUse(wd_prop.expiredTimerUse));
++ }
++
+ if (wd_prop.enabled)
+ {
+ res.timer_use |= wd_running;
+ res.present_countdown = htole16(wd_prop.timeRemaining / 100);
++ res.expire_flags = 0;
+ }
+ else
+ {
+- res.present_countdown = res.initial_countdown;
++ if (wd_prop.expiredTimerUse == WatchdogService::TimerUse::Reserved)
++ {
++ res.present_countdown = res.initial_countdown;
++ res.expire_flags = 0;
++ }
++ else
++ {
++ res.present_countdown = 0;
++ res.expire_flags = timerUseExpirationFlags;
++ }
+ }
+
+ res.timer_use |=
+@@ -379,7 +429,7 @@ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ // TODO: Do something about having pretimeout support
+ res.pretimeout = 0;
+- res.expire_flags = 0;
++
+ memcpy(response, &res, sizeof(res));
+ *data_len = sizeof(res);
+ lastCallSuccessful = true;
+diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp
+index e65ea63..8b1aa47 100644
+--- a/app/watchdog_service.cpp
++++ b/app/watchdog_service.cpp
+@@ -83,6 +83,9 @@ WatchdogService::Properties WatchdogService::getProperties()
+ wd_prop.timerUse = Watchdog::convertTimerUseFromString(
+ std::get<std::string>(properties.at("CurrentTimerUse")));
+
++ wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString(
++ std::get<std::string>(properties.at("ExpiredTimerUse")));
++
+ wd_prop.interval = std::get<uint64_t>(properties.at("Interval"));
+ wd_prop.timeRemaining =
+ std::get<uint64_t>(properties.at("TimeRemaining"));
+@@ -187,6 +190,11 @@ void WatchdogService::setTimerUse(TimerUse timerUse)
+ setProperty("CurrentTimerUse", convertForMessage(timerUse));
+ }
+
++void WatchdogService::setExpiredTimerUse(TimerUse timerUse)
++{
++ setProperty("ExpiredTimerUse", convertForMessage(timerUse));
++}
++
+ void WatchdogService::setInterval(uint64_t interval)
+ {
+ setProperty("Interval", interval);
+diff --git a/app/watchdog_service.hpp b/app/watchdog_service.hpp
+index 75afc1e..d0cc1a8 100644
+--- a/app/watchdog_service.hpp
++++ b/app/watchdog_service.hpp
+@@ -36,6 +36,7 @@ class WatchdogService
+ bool enabled;
+ Action expireAction;
+ TimerUse timerUse;
++ TimerUse expiredTimerUse;
+ uint64_t interval;
+ uint64_t timeRemaining;
+ };
+@@ -79,6 +80,13 @@ class WatchdogService
+ */
+ void setTimerUse(TimerUse timerUse);
+
++ /** @brief Sets the value of the ExpiredTimerUse property on the host
++ * watchdog
++ *
++ * @param[in] timerUse - The new timerUse value
++ */
++ void setExpiredTimerUse(TimerUse timerUse);
++
+ /** @brief Sets the value of the interval property on the host watchdog
+ *
+ * @param[in] interval - The new interval value
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0058-Add-AC-failed-bit-support-for-get-chassis-status-com.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0058-Add-AC-failed-bit-support-for-get-chassis-status-com.patch
new file mode 100644
index 000000000..42bb682c4
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0058-Add-AC-failed-bit-support-for-get-chassis-status-com.patch
@@ -0,0 +1,76 @@
+From f51bef8f7c5785405ee5c83a921efb1bc05e4947 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Wed, 27 Mar 2019 16:11:25 +0800
+Subject: [PATCH] =?UTF-8?q?Add=20=E2=80=9CAC=20failed=E2=80=9D=20bit=20sup?=
+ =?UTF-8?q?port=20for=20get=20chassis=20status=20command?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+PFail property is provided by power control service,
+ture means the booting is from AC loss.
+
+Tested:
+Remove the AC cable and reconnect it
+Ipmitool chassis status to check the status:
+Last Power Event : ac-failed
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassishandler.cpp | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 7a522ad..40d2018 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -844,6 +844,7 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ sd_bus_message* reply = NULL;
+ int r = 0;
+ int pgood = 0;
++ bool pFail = true;
+ char* busname = NULL;
+ ipmi_ret_t rc = IPMI_CC_OK;
+ ipmi_get_chassis_status_t chassis_status{};
+@@ -904,6 +905,26 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ goto finish;
+ }
+
++ r = sd_bus_get_property(bus, busname, objname, intf, "PFail", NULL, &reply,
++ "b");
++ if (r < 0)
++ {
++ log<level::ERR>("Failed to call sd_bus_get_property",
++ entry("PROPERTY=%s", "PFail"), entry("ERRNO=0x%X", -r),
++ entry("BUS=%s", busname), entry("PATH=%s", objname),
++ entry("INTERFACE=%s", intf));
++ rc = IPMI_CC_UNSPECIFIED_ERROR;
++ goto finish;
++ }
++
++ r = sd_bus_message_read(reply, "b", &pFail);
++ if (r < 0)
++ {
++ log<level::ERR>("Failed to read PFail:", entry("ERRNO=0x%X", -r));
++ rc = IPMI_CC_UNSPECIFIED_ERROR;
++ goto finish;
++ }
++
+ s = dbusToIpmi.at(powerRestore);
+
+ // Current Power State
+@@ -952,6 +973,11 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+
+ chassis_status.last_power_event = 0;
+
++ if (pFail)
++ {
++ chassis_status.last_power_event |= 1;
++ }
++
+ // Misc. Chassis State
+ // [7] – reserved
+ // [6] – 1b = Chassis Identify command and state info supported (Optional)
+--
+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..1dc55e2f4
--- /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,415 @@
+From 1c15df9d82254286d0773086836767f23711c5d9 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Tue, 2 Apr 2019 00:34:34 +0800
+Subject: [PATCH] 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>
+---
+ host-ipmid-whitelist.conf | 1 +
+ include/ipmid/api.h | 1 +
+ transporthandler.cpp | 222 ++++++++++++++++++++++++++++++++++++++
+ transporthandler.hpp | 97 +++++++++++++++++
+ 4 files changed, 321 insertions(+)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 2a83347..544b766 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/include/ipmid/api.h b/include/ipmid/api.h
+index f08ee11..2f366b4 100644
+--- a/include/ipmid/api.h
++++ b/include/ipmid/api.h
+@@ -113,6 +113,7 @@ enum ipmi_return_codes
+ IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT = 0x80,
+ IPMI_WDOG_CC_NOT_INIT = 0x80,
+ IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED = 0x80,
++ IPMI_CC_SET_IN_PROGRESS_ACTIVE = 0x81,
+ IPMI_CC_SYSTEM_INFO_PARAMETER_SET_READ_ONLY = 0x82,
+ IPMI_CC_BUSY = 0xC0,
+ IPMI_CC_INVALID = 0xC1,
+diff --git a/transporthandler.cpp b/transporthandler.cpp
+index 8f18b76..a693279 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -36,6 +36,9 @@ static const std::array<std::string, 3> ipAddressEnablesType = {
+ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv6Only",
+ "xyz.openbmc_project.Network.EthernetInterface.IPAllowed.IPv4AndIPv6"};
+
++constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
++constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol";
++
+ std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
+
+ using namespace phosphor::logging;
+@@ -1633,6 +1636,219 @@ void createNetworkTimer()
+ }
+ }
+
++static int setSOLParameter(std::string property, const ipmi::Value& value)
++{
++ auto dbus = getSdBus();
++
++ static std::string solService{};
++ if (solService.empty())
++ {
++ try
++ {
++ solService = ipmi::getService(*dbus, solInterface, solPath);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return -1;
++ }
++ }
++ try
++ {
++ ipmi::setDbusProperty(*dbus, solService, solPath, 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(std::string property, ipmi::Value& value)
++{
++ auto dbus = getSdBus();
++
++ static std::string solService{};
++ if (solService.empty())
++ {
++ try
++ {
++ solService = ipmi::getService(*dbus, solInterface, solPath);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ solService.clear();
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error: get SOL service failed");
++ return -1;
++ }
++ }
++ try
++ {
++ value = ipmi::getDbusProperty(*dbus, solService, solPath, solInterface,
++ property);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error getting sol parameter");
++ return -1;
++ }
++
++ return 0;
++}
++
++void initializeSOLInProgress()
++{
++ if (setSOLParameter("Progress", static_cast<uint8_t>(0)) < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error initialize sol progress");
++ }
++}
++
++ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
++ ipmi_request_t request, ipmi_response_t response,
++ ipmi_data_len_t dataLen, ipmi_context_t context)
++{
++ auto reqData = reinterpret_cast<const SetConfParamsRequest*>(request);
++
++ // Check request length first
++ switch (static_cast<sol::Parameter>(reqData->paramSelector))
++ {
++ case sol::Parameter::progress:
++ case sol::Parameter::enable:
++ case sol::Parameter::authentication:
++ {
++ if (*dataLen != sizeof(SetConfParamsRequest) - 1)
++ {
++ *dataLen = 0;
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++ break;
++ }
++ case sol::Parameter::accumulate:
++ case sol::Parameter::retry:
++ {
++ if (*dataLen != sizeof(SetConfParamsRequest))
++ {
++ *dataLen = 0;
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++ break;
++ }
++ default:
++ break;
++ }
++
++ *dataLen = 0;
++
++ switch (static_cast<sol::Parameter>(reqData->paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ uint8_t progress = reqData->value & progressMask;
++ ipmi::Value currentProgress = 0;
++ if (getSOLParameter("Progress", currentProgress) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ if ((std::get<uint8_t>(currentProgress) == 1) && (progress == 1))
++ {
++ return IPMI_CC_SET_IN_PROGRESS_ACTIVE;
++ }
++
++ if (setSOLParameter("Progress", progress) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ break;
++ }
++ case sol::Parameter::enable:
++ {
++ bool enable = reqData->value & enableMask;
++ if (setSOLParameter("Enable", enable) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ break;
++ }
++ case sol::Parameter::authentication:
++ {
++ // if encryption is used authentication must also be used.
++ if (reqData->auth.encrypt && !reqData->auth.auth)
++ {
++ return IPMI_CC_SYSTEM_INFO_PARAMETER_SET_READ_ONLY;
++ }
++ else if (reqData->auth.privilege <
++ static_cast<uint8_t>(sol::Privilege::userPriv) ||
++ reqData->auth.privilege >
++ static_cast<uint8_t>(sol::Privilege::oemPriv))
++ {
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
++
++ if ((setSOLParameter("Privilege", reqData->auth.privilege) < 0) ||
++ (setSOLParameter("ForceEncryption",
++ static_cast<bool>(reqData->auth.encrypt)) <
++ 0) ||
++ (setSOLParameter("ForceAuthentication",
++ static_cast<bool>(reqData->auth.auth)) < 0))
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ break;
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (reqData->acc.threshold == 0)
++ {
++ return IPMI_CC_INVALID_FIELD_REQUEST;
++ }
++ if (setSOLParameter("AccumulateIntervalMS", reqData->acc.interval) <
++ 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ if (setSOLParameter("Threshold", reqData->acc.threshold) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ break;
++ }
++ case sol::Parameter::retry:
++ {
++ if ((setSOLParameter("RetryCount", reqData->retry.count) < 0) ||
++ (setSOLParameter("RetryIntervalMS", reqData->retry.interval) <
++ 0))
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++
++ break;
++ }
++ case sol::Parameter::port:
++ {
++ return IPMI_CC_SYSTEM_INFO_PARAMETER_SET_READ_ONLY;
++ }
++ case sol::Parameter::nvbitrate:
++ case sol::Parameter::vbitrate:
++ case sol::Parameter::channel:
++ default:
++ return IPMI_CC_PARM_NOT_SUPPORTED;
++ }
++
++ return IPMI_CC_OK;
++}
++
+ void register_netfn_transport_functions()
+ {
+ // As this timer is only for transport handler
+@@ -1650,5 +1866,11 @@ void register_netfn_transport_functions()
+ ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
+ ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
+
++ ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_SOL_CONF_PARAMS, NULL,
++ setConfParams, PRIVILEGE_ADMIN);
++
++ // Initialize dbus property progress to 0 every time sol manager restart.
++ initializeSOLInProgress();
++
+ return;
+ }
+diff --git a/transporthandler.hpp b/transporthandler.hpp
+index bd23391..3b5e9e1 100644
+--- a/transporthandler.hpp
++++ b/transporthandler.hpp
+@@ -8,6 +8,8 @@ enum ipmi_netfn_storage_cmds
+ // Get capability bits
+ IPMI_CMD_SET_LAN = 0x01,
+ IPMI_CMD_GET_LAN = 0x02,
++ IPMI_CMD_SET_SOL_CONF_PARAMS = 0x21,
++ IPMI_CMD_GET_SOL_CONF_PARAMS = 0x22,
+ };
+
+ // Command specific completion codes
+@@ -186,3 +188,98 @@ void commitNetworkChanges();
+ * @param[in] channel: channel number.
+ */
+ void applyChanges(int channel);
++
++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;
++
++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
++{
++ uint8_t interval; //!< Character accumulate interval.
++ uint8_t threshold; //!< Character send threshold.
++} __attribute__((packed));
++
++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));
++
++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
++{
++ uint8_t completionCode; //!< Completion code.
++} __attribute__((packed));
+--
+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..24f355d80
--- /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,342 @@
+From 3c95de833eba73b3585941ade42ad1775e723280 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Tue, 7 May 2019 08:03:56 +0800
+Subject: [PATCH] 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
+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 : 14 (0x0e)
+Payload Port : 623
+
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
+---
+ host-ipmid-whitelist.conf | 1 +
+ transporthandler.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++++--
+ transporthandler.hpp | 27 ++++++-
+ 3 files changed, 217 insertions(+), 9 deletions(-)
+
+diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
+index 2ce44c6..383b412 100644
+--- a/host-ipmid-whitelist.conf
++++ b/host-ipmid-whitelist.conf
+@@ -43,6 +43,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 850172d..0c1223a 100644
+--- a/transporthandler.cpp
++++ b/transporthandler.cpp
+@@ -38,6 +38,8 @@ static const std::array<std::string, 3> ipAddressEnablesType = {
+
+ constexpr const char* solInterface = "xyz.openbmc_project.Ipmi.SOL";
+ constexpr const char* solPath = "/xyz/openbmc_project/ipmi/sol";
++constexpr const char* consoleInterface = "xyz.openbmc_project.console";
++constexpr const char* consolePath = "/xyz/openbmc_project/console";
+
+ std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
+
+@@ -1668,6 +1670,26 @@ static int setSOLParameter(std::string property, const ipmi::Value& value)
+ return 0;
+ }
+
++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 int getSOLParameter(std::string property, ipmi::Value& value)
+ {
+ auto dbus = getSdBus();
+@@ -1711,11 +1733,170 @@ void initializeSOLInProgress()
+ }
+ }
+
+-ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+- ipmi_request_t request, ipmi_response_t response,
+- ipmi_data_len_t dataLen, ipmi_context_t context)
++static const constexpr uint8_t retryCountMask = 0x07;
++// For getsetSOLConfParams, there are still three tings TODO:
++// 1. session less channel number request has to return error.
++// 2. convert 0xE channel number.
++// 3. have unique object for every session based channel.
++ipmi_ret_t getSOLConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
++ ipmi_request_t request, ipmi_response_t response,
++ ipmi_data_len_t dataLen, ipmi_context_t context)
++{
++ auto reqData = reinterpret_cast<const GetSOLConfParamsRequest*>(request);
++ std::vector<uint8_t> outPayload;
++
++ if (*dataLen < sizeof(GetSOLConfParamsRequest) - 2)
++ {
++ *dataLen = 0;
++ return IPMI_CC_REQ_DATA_LEN_INVALID;
++ }
++
++ *dataLen = 0;
++
++ outPayload.push_back(solParameterRevision);
++ if (reqData->getParamRev)
++ {
++ std::copy(outPayload.begin(), outPayload.end(),
++ static_cast<uint8_t*>(response));
++ *dataLen = outPayload.size();
++ return IPMI_CC_OK;
++ }
++
++ ipmi::Value value;
++ switch (static_cast<sol::Parameter>(reqData->paramSelector))
++ {
++ case sol::Parameter::progress:
++ {
++ if (getSOLParameter("Progress", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(std::get<uint8_t>(value));
++ break;
++ }
++ case sol::Parameter::enable:
++ {
++ if (getSOLParameter("Enable", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(static_cast<uint8_t>(std::get<bool>(value)));
++ break;
++ }
++ case sol::Parameter::authentication:
++ {
++ uint8_t authentication = 0;
++ if (getSOLParameter("Privilege", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ authentication = (std::get<uint8_t>(value) & 0x0f);
++
++ if (getSOLParameter("ForceAuthentication", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 6);
++
++ if (getSOLParameter("ForceEncryption", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ authentication |=
++ (static_cast<uint8_t>(std::get<bool>(value)) << 7);
++ outPayload.push_back(authentication);
++ break;
++ }
++ case sol::Parameter::accumulate:
++ {
++ if (getSOLParameter("AccumulateIntervalMS", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(std::get<uint8_t>(value));
++
++ if (getSOLParameter("Threshold", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(std::get<uint8_t>(value));
++ break;
++ }
++ case sol::Parameter::retry:
++ {
++ if (getSOLParameter("RetryCount", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(std::get<uint8_t>(value) & retryCountMask);
++
++ if (getSOLParameter("RetryIntervalMS", value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ outPayload.push_back(std::get<uint8_t>(value));
++ break;
++ }
++ case sol::Parameter::port:
++ {
++ uint16_t port = htole16(ipmiStdPort);
++ auto buffer = reinterpret_cast<const uint8_t*>(&port);
++ std::copy(buffer, buffer + sizeof(port),
++ std::back_inserter(outPayload));
++ break;
++ }
++ case sol::Parameter::nvbitrate:
++ {
++ if (getSOLBaudRate(value) < 0)
++ {
++ return IPMI_CC_UNSPECIFIED_ERROR;
++ }
++ 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;
++ }
++ outPayload.push_back(bitRate);
++ break;
++ }
++ default:
++ return IPMI_CC_PARM_NOT_SUPPORTED;
++ }
++ std::copy(outPayload.begin(), outPayload.end(),
++ static_cast<uint8_t*>(response));
++ *dataLen = outPayload.size();
++
++ return IPMI_CC_OK;
++}
++
++ipmi_ret_t setSOLConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
++ ipmi_request_t request, ipmi_response_t response,
++ ipmi_data_len_t dataLen, ipmi_context_t context)
+ {
+- auto reqData = reinterpret_cast<const SetConfParamsRequest*>(request);
++ auto reqData = reinterpret_cast<const SetSOLConfParamsRequest*>(request);
+
+ // Check request length first
+ switch (static_cast<sol::Parameter>(reqData->paramSelector))
+@@ -1724,7 +1905,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ case sol::Parameter::enable:
+ case sol::Parameter::authentication:
+ {
+- if (*dataLen != sizeof(SetConfParamsRequest) - 1)
++ if (*dataLen != sizeof(SetSOLConfParamsRequest) - 1)
+ {
+ *dataLen = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+@@ -1734,7 +1915,7 @@ ipmi_ret_t setConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ case sol::Parameter::accumulate:
+ case sol::Parameter::retry:
+ {
+- if (*dataLen != sizeof(SetConfParamsRequest))
++ if (*dataLen != sizeof(SetSOLConfParamsRequest))
+ {
+ *dataLen = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+@@ -1865,7 +2046,10 @@ void register_netfn_transport_functions()
+ ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
+
+ ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_SOL_CONF_PARAMS, NULL,
+- setConfParams, PRIVILEGE_ADMIN);
++ setSOLConfParams, PRIVILEGE_ADMIN);
++
++ ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_SOL_CONF_PARAMS, NULL,
++ getSOLConfParams, PRIVILEGE_ADMIN);
+
+ // Initialize dbus property progress to 0 every time sol manager restart.
+ initializeSOLInProgress();
+diff --git a/transporthandler.hpp b/transporthandler.hpp
+index 3b5e9e1..a21862b 100644
+--- a/transporthandler.hpp
++++ b/transporthandler.hpp
+@@ -1,6 +1,7 @@
+ #pragma once
+
+ #include <ipmid/types.hpp>
++#include <map>
+ #include <string>
+ // IPMI commands for Transport net functions.
+ enum ipmi_netfn_storage_cmds
+@@ -257,7 +258,7 @@ struct Retry
+ uint8_t interval; //!< SOL retry interval.
+ } __attribute__((packed));
+
+-struct SetConfParamsRequest
++struct SetSOLConfParamsRequest
+ {
+ #if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t channelNumber : 4; //!< Channel number.
+@@ -279,7 +280,29 @@ struct SetConfParamsRequest
+ };
+ } __attribute__((packed));
+
+-struct SetConfParamsResponse
++struct SetSOLConfParamsResponse
+ {
+ uint8_t completionCode; //!< Completion code.
+ } __attribute__((packed));
++
++struct GetSOLConfParamsRequest
++{
++#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));
++
++static constexpr uint16_t ipmiStdPort = 623;
++static constexpr uint8_t solParameterRevision = 0x11;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0061-Use-xyz.openbmc_project.State.Chassis-for-IPMI-chass.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0061-Use-xyz.openbmc_project.State.Chassis-for-IPMI-chass.patch
new file mode 100644
index 000000000..877c5336a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0061-Use-xyz.openbmc_project.State.Chassis-for-IPMI-chass.patch
@@ -0,0 +1,127 @@
+From 514b76d1c05d7ed7fb7e1df27833e423e04c9a1c Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Tue, 21 May 2019 09:57:16 -0700
+Subject: [PATCH] Use xyz.openbmc_project.State.Chassis for IPMI chassis status
+
+Instead of directly using pgood on dbus, this change uses the
+xyz.openbmc_project.State.Chassis "CurrentPowerState" property
+for the IPMI chassis status command. This will allow us to
+remove pgood from dbus.
+
+Tested:
+Ran IPMI chassis commands and confirmed that they behave as
+expected:
+ipmitool power status
+Chassis Power is on
+
+ipmitool power off
+Chassis Power Control: Down/Off
+
+ipmitool power status
+Chassis Power is off
+
+ipmitool power on
+Chassis Power Control: Up/On
+
+ipmitool power status
+Chassis Power is on
+
+Change-Id: I7836c16b76c3b309f176186f3e2453082e4cd1af
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ chassishandler.cpp | 61 ++++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 41 insertions(+), 20 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index 1738ccc..e4e842d 100644
+--- a/chassishandler.cpp
++++ b/chassishandler.cpp
+@@ -824,44 +824,65 @@ std::optional<uint2_t> getPowerRestorePolicy()
+ */
+ std::optional<bool> getPowerStatus()
+ {
+- constexpr const char* powerControlObj =
+- "/xyz/openbmc_project/Chassis/Control/Power0";
+- constexpr const char* powerControlIntf =
+- "xyz.openbmc_project.Chassis.Control.Power";
+ bool powerGood = false;
+ std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
+ try
+ {
++ constexpr const char* chassisStatePath =
++ "/xyz/openbmc_project/state/chassis0";
++ constexpr const char* chassisStateIntf =
++ "xyz.openbmc_project.State.Chassis";
+ auto service =
+- ipmi::getService(*busp, powerControlIntf, powerControlObj);
++ ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
+
+- ipmi::Value variant = ipmi::getDbusProperty(
+- *busp, service, powerControlObj, powerControlIntf, "pgood");
+- powerGood = static_cast<bool>(std::get<int>(variant));
++ ipmi::Value variant =
++ ipmi::getDbusProperty(*busp, service, chassisStatePath,
++ chassisStateIntf, "CurrentPowerState");
++ std::string powerState = std::get<std::string>(variant);
++ if (powerState == "xyz.openbmc_project.State.Chassis.PowerState.On")
++ {
++ powerGood = true;
++ }
+ }
+ catch (const std::exception& e)
+ {
+ try
+ {
+- // FIXME: some legacy modules use the older path; try that next
+- constexpr const char* legacyPwrCtrlObj =
+- "/org/openbmc/control/power0";
+- constexpr const char* legacyPwrCtrlIntf =
+- "org.openbmc.control.Power";
++ // FIXME: some modules use pgood; try that next
++ constexpr const char* powerControlObj =
++ "/xyz/openbmc_project/Chassis/Control/Power0";
++ constexpr const char* powerControlIntf =
++ "xyz.openbmc_project.Chassis.Control.Power";
+ auto service =
+- ipmi::getService(*busp, legacyPwrCtrlIntf, legacyPwrCtrlObj);
++ ipmi::getService(*busp, powerControlIntf, powerControlObj);
+
+ ipmi::Value variant = ipmi::getDbusProperty(
+- *busp, service, legacyPwrCtrlObj, legacyPwrCtrlIntf, "pgood");
++ *busp, service, powerControlObj, powerControlIntf, "pgood");
+ powerGood = static_cast<bool>(std::get<int>(variant));
+ }
+ catch (const std::exception& e)
+ {
+- log<level::ERR>("Failed to fetch pgood property",
+- entry("ERROR=%s", e.what()),
+- entry("PATH=%s", powerControlObj),
+- entry("INTERFACE=%s", powerControlIntf));
+- return std::nullopt;
++ try
++ {
++ // FIXME: some legacy modules use the older path; try that next
++ constexpr const char* legacyPwrCtrlObj =
++ "/org/openbmc/control/power0";
++ constexpr const char* legacyPwrCtrlIntf =
++ "org.openbmc.control.Power";
++ auto service = ipmi::getService(*busp, legacyPwrCtrlIntf,
++ legacyPwrCtrlObj);
++
++ ipmi::Value variant =
++ ipmi::getDbusProperty(*busp, service, legacyPwrCtrlObj,
++ legacyPwrCtrlIntf, "pgood");
++ powerGood = static_cast<bool>(std::get<int>(variant));
++ }
++ catch (const std::exception& e)
++ {
++ log<level::ERR>("Failed to fetch pgood property",
++ entry("ERROR=%s", e.what()));
++ return std::nullopt;
++ }
+ }
+ }
+ return std::make_optional(powerGood);
+--
+2.7.4
+
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..498233881
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0062-Update-IPMI-Chassis-Control-command.patch
@@ -0,0 +1,214 @@
+From f11928c6b39052c679c9300e9d836837ef60be06 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
+chassis state transitions. This allows each chassis control action
+to more closely follow the behavior defined in the IPMI spec.
+
+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 | 138 +++++++++++++++++++++--------------------------------
+ 1 file changed, 54 insertions(+), 84 deletions(-)
+
+diff --git a/chassishandler.cpp b/chassishandler.cpp
+index e4e842d..d71b95f 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>
+
+@@ -712,59 +713,63 @@ ipmi_ret_t ipmi_set_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ //------------------------------------------
+ // 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)
++ try
+ {
+- log<level::ERR>("Failed to initiate transition",
+- entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
++ 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;
+ }
+
+ namespace power_policy
+@@ -1138,61 +1143,26 @@ 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 = initiateChassisStateTransition(
++ State::Chassis::Transition::Reset);
++ 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 = initiateChassisStateTransition(
++ State::Chassis::Transition::PowerCycle);
+ 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 =
++ initiateHostStateTransition(State::Host::Transition::Interrupt);
+ break;
+
+ default:
+--
+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..685e7c39d
--- /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>((req.timer_action >> 4) &
++ wdPreTimeoutInterruptMask);
++ 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..d855eaa5b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/phosphor-ipmi-host.service
@@ -0,0 +1,26 @@
+[Unit]
+Description=Phosphor Inband IPMI
+# TODO openbmc/openbmc#2059 - The wants/after below should be based on providers
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-boot.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-boot.service
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-boot-one_time.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-boot-one_time.service
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-power_restore_policy.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-power_restore_policy.service
+Wants=mapper-wait@-xyz-openbmc_project-control-host0-restriction_mode.service
+After=mapper-wait@-xyz-openbmc_project-control-host0-restriction_mode.service
+Wants=clear-once.service
+After=clear-once.service
+
+[Service]
+Restart=always
+RestartSec=5
+StartLimitBurst=10
+ExecStart=/usr/bin/env ipmid
+SyslogIdentifier=ipmid
+RuntimeDirectory = ipmi
+RuntimeDirectoryPreserve = yes
+StateDirectory = ipmi
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
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..a6a142ec8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -0,0 +1,41 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+# TODO: This should be removed, once up-stream bump up
+# issue is resolved
+#SRC_URI = "git://github.com/openbmc/phosphor-host-ipmid"
+SRCREV = "0b979b61c12ffe6ab8a27acf8ad2a0165d687195"
+
+SRC_URI += "file://phosphor-ipmi-host.service \
+ file://0009-IPv6-Network-changes.patch \
+ file://0010-fix-get-system-GUID-ipmi-command.patch \
+ file://0013-ipmi-add-set-bios-id-to-whitelist.patch \
+ file://0021-Implement-IPMI-Commmand-Get-Host-Restart-Cause.patch \
+ file://0039-ipmi-add-oem-command-get-AIC-FRU-to-whitelist.patch \
+ file://0049-Fix-Unspecified-error-on-ipmi-restart-cause-command.patch \
+ file://0050-enable-6-oem-commands.patch \
+ file://0053-Fix-keep-looping-issue-when-entering-OS.patch \
+ file://0055-Implement-set-front-panel-button-enables-command.patch \
+ file://0056-add-SetInProgress-to-get-set-boot-option-cmd.patch \
+ file://0057-Add-timer-use-actions-support.patch \
+ file://0059-Move-Set-SOL-config-parameter-to-host-ipmid.patch \
+ file://0060-Move-Get-SOL-config-parameter-to-host-ipmid.patch \
+ file://0061-Use-xyz.openbmc_project.State.Chassis-for-IPMI-chass.patch \
+ file://0062-Update-IPMI-Chassis-Control-command.patch \
+ file://0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch \
+ "
+
+# 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_install_append(){
+ rm -f ${D}/${bindir}/phosphor-softpoweroff
+}
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..13d908ad1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-ipmb_%.bbappend
@@ -0,0 +1,2 @@
+SRC_URI = "git://github.com/openbmc/ipmbbridge.git"
+SRCREV = "8188d7651c23502f88f9bf850ab7e549f6463997"
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..140d1b302
--- /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 = "2cdc49585235a6557c9cbb6c8b75c064fc02681a"
+
+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/0007-Adding-support-for-GetSessionInfo-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0007-Adding-support-for-GetSessionInfo-command.patch
new file mode 100644
index 000000000..bbbe6ae4f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0007-Adding-support-for-GetSessionInfo-command.patch
@@ -0,0 +1,418 @@
+From b05fb3231810865ef1b6e627bb0452ae7a6c61f8 Mon Sep 17 00:00:00 2001
+From: ssekar <suryakanth.sekar@linux.intel.com>
+Date: Wed, 12 Dec 2018 16:04:15 +0530
+Subject: [PATCH 1/2] Adding support for GetSessionInfo command
+
+Description: user can get all session info (remote ip,port,
+session id, priv, etc) using this command.
+
+Verification :we can get all active and non active session
+info by session handle session id.
+Updated the Remote IP addr and Port update for sessioninfo.
+Unit testing are done.
+
+Change-Id: I662ef2b9f0c1d6bda331eb6481d7b9f34534541b
+Signed-off-by: ssekar <suryakanth.sekar@linux.intel.com>
+---
+ comm_module.cpp | 8 +++
+ command/session_cmds.cpp | 147 +++++++++++++++++++++++++++++++++++++++
+ command/session_cmds.hpp | 55 +++++++++++++++
+ message_handler.cpp | 1 +
+ sessions_manager.cpp | 55 +++++++++++++++
+ sessions_manager.hpp | 7 ++
+ socket_channel.hpp | 17 +++++
+ 7 files changed, 290 insertions(+)
+
+diff --git a/comm_module.cpp b/comm_module.cpp
+index acc9089..7a1a17d 100644
+--- a/comm_module.cpp
++++ b/comm_module.cpp
+@@ -53,6 +53,14 @@ void sessionSetupCommands()
+ &closeSession,
+ session::Privilege::CALLBACK,
+ false},
++ // Session Info Command
++ {
++ {
++ (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
++ static_cast<uint16_t>(command::NetFns::APP) | 0x3D
++ },
++ &getSessionInfo, session::Privilege::USER, false
++ },
+ };
+
+ for (auto& iter : commands)
+diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
+index 8606ce5..4beeb6e 100644
+--- a/command/session_cmds.cpp
++++ b/command/session_cmds.cpp
+@@ -8,6 +8,14 @@
+ namespace command
+ {
+
++// Defined as per IPMI sepcification
++static constexpr uint8_t searchCurrentSession = 0x00;
++static constexpr uint8_t searchSessionByHandle = 0xFE;
++static constexpr uint8_t searchSessionByID = 0xFF;
++
++static constexpr uint8_t ipmi15VerSession = 0x00;
++static constexpr uint8_t ipmi20VerSession = 0x01;
++
+ std::vector<uint8_t>
+ setSessionPrivilegeLevel(const std::vector<uint8_t>& inPayload,
+ const message::Handler& handler)
+@@ -92,4 +100,143 @@ std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
+ return outPayload;
+ }
+
++std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
++ const message::Handler& handler)
++
++{
++ std::vector<uint8_t> outPayload(sizeof(GetSessionInfoResponse));
++ auto request =
++ reinterpret_cast<const GetSessionInfoRequest*>(inPayload.data());
++ auto response =
++ reinterpret_cast<GetSessionInfoResponse*>(outPayload.data());
++ uint32_t reqSessionID = handler.sessionID;
++ response->completionCode = IPMI_CC_OK;
++ if (inPayload.size() == 1 && request->sessionIndex != 0)
++ {
++ if (request->sessionIndex <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID = std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionIndex);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ }
++
++ // Here we look for session info according to session index parameter
++ switch (request->sessionIndex)
++ {
++ // Look for current active session which this cmd is received over
++ case searchCurrentSession:
++ // Request data should only contain session index byte
++ if (inPayload.size() != 1)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ // To look for current active session which the command came over,
++ // the session ID cannot be 0.
++ if (0 == reqSessionID)
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ break;
++ case searchSessionByHandle:
++ // Request data should only contain session index byte and Session
++ // handle
++ if (inPayload.size() != 2)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++
++ // Retrieve session id based on session handle
++ if (request->sessionHandle <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID =
++ std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionHandle);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ break;
++ case searchSessionByID:
++ // Request data should only contain session index byte and Session
++ // handle
++ if (inPayload.size() != sizeof(GetSessionInfoRequest))
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ reqSessionID = endian::from_ipmi(request->sessionID);
++
++ break;
++ default:
++ if (inPayload.size() != 1)
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ }
++
++ response->totalSessionCount = session::MAX_SESSION_COUNT;
++ response->activeSessioncount =
++ std::get<session::Manager&>(singletonPool).getNoOfActiveSession();
++ response->sessionHandle = 0;
++ if (reqSessionID != 0)
++ {
++
++ std::shared_ptr<session::Session> sessionInfo;
++ try
++ {
++ sessionInfo = std::get<session::Manager&>(singletonPool)
++ .getSession(reqSessionID);
++ }
++ catch (std::exception& e)
++ {
++ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ response->sessionHandle = std::get<session::Manager&>(singletonPool)
++ .getSessionHandle(reqSessionID);
++ uint8_t userId = ipmi::ipmiUserGetUserId(sessionInfo->userName);
++ if (userId == ipmi::invalidUserId)
++ {
++ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ outPayload.resize(sizeof(response->completionCode));
++ return std::move(outPayload);
++ }
++ response->userID = userId; // userId;
++ response->privLevel = static_cast<uint8_t>(sessionInfo->curPrivLevel);
++ response->chanNum = sessionInfo->chNum; // byte7 3:0
++ response->ipmiVer = ipmi20VerSession; // byte7 7:4
++ response->remoteIpAddr =
++ sessionInfo->channelPtr->getRemoteAddressInbytes();
++ response->remotePort =
++ sessionInfo->channelPtr->getPort(); // remoteSessionPort;
++
++ std::cerr << "\nSessionInfo:" << (int)reqSessionID;
++ // TODO: Filling the Remote MACAddress
++ }
++ else
++ {
++ outPayload.resize(4);
++ }
++ return std::move(outPayload);
++}
++
+ } // namespace command
+diff --git a/command/session_cmds.hpp b/command/session_cmds.hpp
+index 9737fdb..741de23 100644
+--- a/command/session_cmds.hpp
++++ b/command/session_cmds.hpp
+@@ -116,4 +116,59 @@ struct CloseSessionResponse
+ std::vector<uint8_t> closeSession(const std::vector<uint8_t>& inPayload,
+ const message::Handler& handler);
+
++/**
++ * @struct GetSessionInfoRequest
++ *
++ * IPMI Request data for getSession info command
++ */
++struct GetSessionInfoRequest
++{
++ uint8_t sessionIndex;
++ union
++ {
++ uint8_t sessionHandle;
++ uint32_t sessionID;
++ };
++} __attribute__((packed));
++
++/**
++ * @struct getSessionInfoResponse
++ *
++ * IPMI Response data for getSession info command
++ */
++struct GetSessionInfoResponse
++{
++ uint8_t completionCode;
++ uint8_t sessionHandle;
++ uint8_t totalSessionCount;
++ uint8_t activeSessioncount;
++ uint8_t userID;
++ uint8_t privLevel;
++#if BYTE_ORDER == LITTLE_ENDIAN
++ uint8_t chanNum : 4;
++ uint8_t ipmiVer : 4;
++#endif
++#if BYTE_ORDER == BIG_ENDIAN
++ uint8_t ipmiVer : 4;
++ uint8_t chanNum : 4;
++#endif
++ uint32_t remoteIpAddr; // for channel private data
++ uint8_t remoteMACAddr[6];
++ uint16_t remotePort;
++} __attribute__((packed));
++
++/**
++ * @brief GetSessionInfo Command
++ *
++ * This command is used to get the session information based on
++ * session handle or session ID. Retreive all session information.
++
++ * @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> getSessionInfo(const std::vector<uint8_t>& inPayload,
++ const message::Handler& handler);
++
+ } // namespace command
+diff --git a/message_handler.cpp b/message_handler.cpp
+index e2aafb3..b335236 100644
+--- a/message_handler.cpp
++++ b/message_handler.cpp
+@@ -43,6 +43,7 @@ bool Handler::receive()
+ sessionID = inMessage->bmcSessionID;
+ inMessage->rcSessionID = session->getRCSessionID();
+ session->updateLastTransactionTime();
++ session->channelPtr = channel;
+
+ return true;
+ }
+diff --git a/sessions_manager.cpp b/sessions_manager.cpp
+index 95a8a15..9f3210b 100644
+--- a/sessions_manager.cpp
++++ b/sessions_manager.cpp
+@@ -88,6 +88,9 @@ std::shared_ptr<Session>
+ }
+ sessionID = session->getBMCSessionID();
+ sessionsMap.emplace(sessionID, session);
++ storeSessionHandle(sessionID);
++
++
+ return session;
+ }
+
+@@ -149,12 +152,15 @@ std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
+
+ void Manager::cleanStaleEntries()
+ {
++ uint8_t sessionIndex = 0;
+ for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
+ {
+ auto session = iter->second;
+ if ((session->getBMCSessionID() != SESSION_ZERO) &&
+ !(session->isSessionActive()))
+ {
++ sessionIndex = getSessionHandle(session->getBMCSessionID());
++ sessionHandleMap[sessionIndex] = 0;
+ iter = sessionsMap.erase(iter);
+ }
+ else
+@@ -164,4 +170,53 @@ void Manager::cleanStaleEntries()
+ }
+ }
+
++uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
++{
++ // Zero handler is reserved for invalid session.
++ //index starts with 1, for direct usage. Index 0 reserved
++ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
++ {
++ if (sessionHandleMap[i] == 0)
++ {
++ sessionHandleMap[i] = bmcSessionID;
++ break;
++ }
++ }
++ return 0;
++}
++
++uint32_t Manager::getSessionIDbyHandle(uint8_t sessionHandle) const
++{
++ if (sessionHandle <= MAX_SESSION_COUNT)
++ {
++ return sessionHandleMap[sessionHandle];
++ }
++ return 0;
++}
++
++uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
++{
++
++ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
++ {
++ if (sessionHandleMap[i] == bmcSessionID)
++ {
++ return i;
++ }
++ }
++ return 0;
++}
++uint8_t Manager::getNoOfActiveSession() const
++{
++ uint8_t count = 0;
++ for (const auto& it : sessionsMap)
++ {
++ const auto& session = it.second;
++ if (session->state == State::ACTIVE)
++ {
++ count++;
++ }
++ }
++ return count;
++}
+ } // namespace session
+diff --git a/sessions_manager.hpp b/sessions_manager.hpp
+index 9fd38b1..f6ed1c3 100644
+--- a/sessions_manager.hpp
++++ b/sessions_manager.hpp
+@@ -82,8 +82,15 @@ class Manager
+ std::shared_ptr<Session>
+ getSession(SessionID sessionID,
+ RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
++ uint8_t getNoOfActiveSession() const;
++ uint8_t getSessionHandle(SessionID bmcSessionID) const;
++ uint8_t storeSessionHandle(SessionID bmcSessionID);
++ uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
+
+ private:
++ //+1 for session, as 0 is reserved for sessionless command
++ std::array<uint32_t, MAX_SESSION_COUNT + 1> sessionHandleMap;
++
+ /**
+ * @brief Session Manager keeps the session objects as a sorted
+ * associative container with Session ID as the unique key
+diff --git a/socket_channel.hpp b/socket_channel.hpp
+index ebe0c8f..349701e 100644
+--- a/socket_channel.hpp
++++ b/socket_channel.hpp
+@@ -64,6 +64,23 @@ class Channel
+ return endpoint.port();
+ }
+
++ /**
++ * @brief Return the binary representation of the remote IPv4 address
++ *
++ * getSessionInfo needs to return the remote IPv4 addresses of each session
++ *
++ * @return A uint32_t representation of the remote IPv4 address
++ */
++ std::uint32_t getRemoteAddressInbytes()
++ {
++ const boost::asio::ip::address& addr = endpoint.address();
++ if (addr.is_v4())
++ {
++ return addr.to_v4().to_uint();
++ }
++ return 0;
++ }
++
+ /**
+ * @brief Read the incoming packet
+ *
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch
new file mode 100644
index 000000000..c6b87bf4f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net/0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch
@@ -0,0 +1,282 @@
+From a413e390563205476656a9005ca447f5b626872f Mon Sep 17 00:00:00 2001
+From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+Date: Wed, 6 Mar 2019 10:35:56 +0530
+Subject: [PATCH 2/2] Sync GetSession Info cmd based on Upstream review
+
+Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
+---
+ comm_module.cpp | 12 +++----
+ command/session_cmds.cpp | 71 ++++++++++++++++++----------------------
+ sessions_manager.cpp | 10 +++---
+ sessions_manager.hpp | 2 +-
+ socket_channel.hpp | 33 ++++++++++---------
+ 5 files changed, 59 insertions(+), 69 deletions(-)
+
+diff --git a/comm_module.cpp b/comm_module.cpp
+index 7a1a17d..2546583 100644
+--- a/comm_module.cpp
++++ b/comm_module.cpp
+@@ -54,13 +54,11 @@ void sessionSetupCommands()
+ session::Privilege::CALLBACK,
+ false},
+ // Session Info Command
+- {
+- {
+- (static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
+- static_cast<uint16_t>(command::NetFns::APP) | 0x3D
+- },
+- &getSessionInfo, session::Privilege::USER, false
+- },
++ {{(static_cast<uint32_t>(message::PayloadType::IPMI) << 16) |
++ static_cast<uint16_t>(command::NetFns::APP) | 0x3D},
++ &getSessionInfo,
++ session::Privilege::USER,
++ false},
+ };
+
+ for (auto& iter : commands)
+diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
+index 4beeb6e..0c3a4ed 100644
+--- a/command/session_cmds.cpp
++++ b/command/session_cmds.cpp
+@@ -8,7 +8,7 @@
+ namespace command
+ {
+
+-// Defined as per IPMI sepcification
++// Defined as per IPMI specification
+ static constexpr uint8_t searchCurrentSession = 0x00;
+ static constexpr uint8_t searchSessionByHandle = 0xFE;
+ static constexpr uint8_t searchSessionByID = 0xFF;
+@@ -111,20 +111,6 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ reinterpret_cast<GetSessionInfoResponse*>(outPayload.data());
+ uint32_t reqSessionID = handler.sessionID;
+ response->completionCode = IPMI_CC_OK;
+- if (inPayload.size() == 1 && request->sessionIndex != 0)
+- {
+- if (request->sessionIndex <= session::MAX_SESSION_COUNT)
+- {
+- reqSessionID = std::get<session::Manager&>(singletonPool)
+- .getSessionIDbyHandle(request->sessionIndex);
+- }
+- else
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
+- }
+- }
+
+ // Here we look for session info according to session index parameter
+ switch (request->sessionIndex)
+@@ -132,29 +118,22 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ // Look for current active session which this cmd is received over
+ case searchCurrentSession:
+ // Request data should only contain session index byte
+- if (inPayload.size() != 1)
++ if (inPayload.size() != sizeof(request->sessionIndex))
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
+- }
+- // To look for current active session which the command came over,
+- // the session ID cannot be 0.
+- if (0 == reqSessionID)
+- {
+- response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+- outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ break;
+ case searchSessionByHandle:
+ // Request data should only contain session index byte and Session
+ // handle
+- if (inPayload.size() != 2)
++ if (inPayload.size() != (sizeof(request->sessionIndex) +
++ sizeof(request->sessionHandle)))
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+
+ // Retrieve session id based on session handle
+@@ -168,7 +147,7 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ break;
+ case searchSessionByID:
+@@ -178,23 +157,38 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ reqSessionID = endian::from_ipmi(request->sessionID);
+
+ break;
+ default:
+- if (inPayload.size() != 1)
++ if (inPayload.size() == sizeof(request->sessionIndex))
++ {
++ if (request->sessionIndex <= session::MAX_SESSION_COUNT)
++ {
++ reqSessionID =
++ std::get<session::Manager&>(singletonPool)
++ .getSessionIDbyHandle(request->sessionIndex);
++ }
++ else
++ {
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
++ outPayload.resize(sizeof(response->completionCode));
++ return outPayload;
++ }
++ }
++ else
+ {
+ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ }
+
+ response->totalSessionCount = session::MAX_SESSION_COUNT;
+ response->activeSessioncount =
+- std::get<session::Manager&>(singletonPool).getNoOfActiveSession();
++ std::get<session::Manager&>(singletonPool).getActiveSessionCount();
+ response->sessionHandle = 0;
+ if (reqSessionID != 0)
+ {
+@@ -207,9 +201,9 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ }
+ catch (std::exception& e)
+ {
+- response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
++ response->completionCode = IPMI_CC_REQ_DATA_LEN_INVALID;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ response->sessionHandle = std::get<session::Manager&>(singletonPool)
+ .getSessionHandle(reqSessionID);
+@@ -218,25 +212,24 @@ std::vector<uint8_t> getSessionInfo(const std::vector<uint8_t>& inPayload,
+ {
+ response->completionCode = IPMI_CC_UNSPECIFIED_ERROR;
+ outPayload.resize(sizeof(response->completionCode));
+- return std::move(outPayload);
++ return outPayload;
+ }
+ response->userID = userId; // userId;
+ response->privLevel = static_cast<uint8_t>(sessionInfo->curPrivLevel);
+ response->chanNum = sessionInfo->chNum; // byte7 3:0
+ response->ipmiVer = ipmi20VerSession; // byte7 7:4
+- response->remoteIpAddr =
+- sessionInfo->channelPtr->getRemoteAddressInbytes();
+ response->remotePort =
+ sessionInfo->channelPtr->getPort(); // remoteSessionPort;
++ response->remoteIpAddr =
++ sessionInfo->channelPtr->getRemoteAddressInBytes();
+
+- std::cerr << "\nSessionInfo:" << (int)reqSessionID;
+ // TODO: Filling the Remote MACAddress
+ }
+ else
+ {
+ outPayload.resize(4);
+ }
+- return std::move(outPayload);
++ return outPayload;
+ }
+
+ } // namespace command
+diff --git a/sessions_manager.cpp b/sessions_manager.cpp
+index 9f3210b..c6897c6 100644
+--- a/sessions_manager.cpp
++++ b/sessions_manager.cpp
+@@ -152,15 +152,13 @@ std::shared_ptr<Session> Manager::getSession(SessionID sessionID,
+
+ void Manager::cleanStaleEntries()
+ {
+- uint8_t sessionIndex = 0;
+ for (auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
+ {
+ auto session = iter->second;
+ if ((session->getBMCSessionID() != SESSION_ZERO) &&
+ !(session->isSessionActive()))
+ {
+- sessionIndex = getSessionHandle(session->getBMCSessionID());
+- sessionHandleMap[sessionIndex] = 0;
++ sessionHandleMap[getSessionHandle(session->getBMCSessionID())] = 0;
+ iter = sessionsMap.erase(iter);
+ }
+ else
+@@ -172,8 +170,8 @@ void Manager::cleanStaleEntries()
+
+ uint8_t Manager::storeSessionHandle(SessionID bmcSessionID)
+ {
+- // Zero handler is reserved for invalid session.
+- //index starts with 1, for direct usage. Index 0 reserved
++ // Handler index 0 is reserved for invalid session.
++ // index starts with 1, for direct usage. Index 0 reserved
+ for (uint8_t i = 1; i <= MAX_SESSION_COUNT; i++)
+ {
+ if (sessionHandleMap[i] == 0)
+@@ -206,7 +204,7 @@ uint8_t Manager::getSessionHandle(SessionID bmcSessionID) const
+ }
+ return 0;
+ }
+-uint8_t Manager::getNoOfActiveSession() const
++uint8_t Manager::getActiveSessionCount() const
+ {
+ uint8_t count = 0;
+ for (const auto& it : sessionsMap)
+diff --git a/sessions_manager.hpp b/sessions_manager.hpp
+index f6ed1c3..3ff213e 100644
+--- a/sessions_manager.hpp
++++ b/sessions_manager.hpp
+@@ -82,7 +82,7 @@ class Manager
+ std::shared_ptr<Session>
+ getSession(SessionID sessionID,
+ RetrieveOption option = RetrieveOption::BMC_SESSION_ID);
+- uint8_t getNoOfActiveSession() const;
++ uint8_t getActiveSessionCount() const;
+ uint8_t getSessionHandle(SessionID bmcSessionID) const;
+ uint8_t storeSessionHandle(SessionID bmcSessionID);
+ uint32_t getSessionIDbyHandle(uint8_t sessionHandle) const;
+diff --git a/socket_channel.hpp b/socket_channel.hpp
+index 349701e..8b64740 100644
+--- a/socket_channel.hpp
++++ b/socket_channel.hpp
+@@ -107,14 +107,15 @@ class Channel
+ *
+ * @return A uint32_t representation of the remote IPv4 address
+ */
+- std::uint32_t getRemoteAddressInbytes()
++ uint32_t getRemoteAddressInBytes() const
+ {
+- const boost::asio::ip::address& addr = endpoint.address();
+- if (addr.is_v4())
++ uint32_t v4addr = 0;
++ if (sockAddrSize == sizeof(sockaddr_in))
+ {
+- return addr.to_v4().to_uint();
++ auto saddr = reinterpret_cast<const sockaddr_in*>(&remoteSockAddr);
++ v4addr = ntohl(saddr->sin_addr.s_addr);
+ }
+- return 0;
++ return v4addr;
+ }
+
+ /**
+--
+2.17.1
+
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..c90cccf34
--- /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,311 @@
+From 6b9aaf0304aed06e4b5ac53e7c163089568d4171 Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
+Date: Sat, 23 Mar 2019 04:03:07 +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 | 1 +
+ command/sol_cmds.cpp | 84 ---------------------------------
+ sol/sol_manager.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++
+ sol/sol_manager.hpp | 1 +
+ sol_module.cpp | 6 ---
+ 5 files changed, 121 insertions(+), 90 deletions(-)
+
+diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
+index 3b5b4f8..570cdff 100644
+--- a/command/payload_cmds.cpp
++++ b/command/payload_cmds.cpp
+@@ -34,6 +34,7 @@ std::vector<uint8_t> activatePayload(const std::vector<uint8_t>& inPayload,
+ return outPayload;
+ }
+
++ std::get<sol::Manager&>(singletonPool).updateSOLParameter();
+ 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..de36723 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,119 @@ 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()
++{
++ std::variant<uint8_t, bool> value;
++ sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
++ static std::string solService{};
++ ipmi::PropertyMap properties;
++ if (solService.empty())
++ {
++ try
++ {
++ solService = getService(dbus, solInterface, solPath);
++ }
++ 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, solPath, 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"]);
++
++ solMinPrivilege = static_cast<session::Privilege>(
++ std::get<uint8_t>(properties["Authentication"]));
++
++ 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..b7eb89e 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(void);
+
+ 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.16.2
+
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_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
new file mode 100644
index 000000000..214bea189
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-net_%.bbappend
@@ -0,0 +1,29 @@
+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 = "b31e969504645f653b58b676d56b01d632dc395c"
+
+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://0006-Modify-dbus-namespace-of-chassis-control-for-guid.patch \
+ file://0007-Adding-support-for-GetSessionInfo-command.patch \
+ file://0008-Sync-GetSession-Info-cmd-based-on-Upstream-review.patch \
+ file://0009-Add-dbus-interface-for-sol-commands.patch \
+ file://00010-Change-Authentication-Parameter.patch \
+ file://0011-Remove-Get-SOL-Config-Command-from-Netipmid.patch \
+ "
+
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..af83facf6
--- /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://git@github.com/Intel-BMC/node-manager;protocol=ssh"
+SRCREV = "2ab90332828614c95e0ce22c0c95285734b55b65"
+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/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/logging/phosphor-logging_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend
new file mode 100644
index 000000000..b1f4c1ce5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/logging/phosphor-logging_%.bbappend
@@ -0,0 +1,2 @@
+SRCREV = "30047bf9647215951ba5dfe21ceb3e58a1b405a4"
+
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..65f578338
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/multi-node-manager/multi-node-manager.bb
@@ -0,0 +1,15 @@
+SUMMARY = "Multi node manager"
+DESCRIPTION = "Daemon to handle chassis level shared resources on multi-node platform"
+
+SRC_URI = "git://git@github.com/Intel-BMC/multi-node-manager.git;protocol=ssh"
+SRCREV = "6a4cd36c0d46df11bdcd3b897bcc9c87e549a076"
+
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+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/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..c7f78b1e3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/preinit-mounts/preinit-mounts/init
@@ -0,0 +1,203 @@
+#!/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
+
+# start with /proc and /tmp mounted
+[ -e /proc/mounts ] || mount -t proc proc /proc
+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
+
+# list of things that need to be rw at boot
+NV_OVERLAYS="/etc /var /home"
+
+# place to mount the real ubifs backing store
+RWFS_MNT=/tmp/.rwfs
+
+if grep -q "$RWFS_MNT" /proc/mounts; then
+ # quit - we have already run
+ exit 0
+fi
+mkdir -p "$RWFS_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 "${RWFS_MNT}${p}.work"
+ mkdir -p "${RWFS_MNT}${p}" "${RWFS_MNT}${p}.work"
+ local mname=$(echo "rwnv${p}" | sed 's,/,,g')
+ local opts="lowerdir=${p},upperdir=${RWFS_MNT}${p},workdir=${RWFS_MNT}${p}.work,sync"
+ mount -t overlay -o "$opts" "$mname" "$p"
+}
+
+targetted_clean() {
+ local LOG_TAG="restore-defaults"
+ # Do not delete server certificates for the web server or ssh
+ echo "removing targetted contents:"
+ cd "${RWFS_MNT}/etc"
+ for file in *; do
+ case $file in
+ # The only files that stay are here:
+ CA|RestoreDefaultConfiguration|dropbear|sdr|server.pem);;
+ # All else get removed.
+ *) echo "remove $file"
+ rm -rf $file;;
+ esac
+ done
+ # nothing should be in the workdir, but clear it just in case
+ rm -rf "${RWFS_MNT}/etc.work"
+
+ # Log files remaining - but not to stdout.
+ echo "Files remaining: $(ls)"
+
+ # clean everything out of /var
+ rm -rf "${RWFS_MNT}/var" "${RWFS_MNT}/var.work"
+}
+
+full_clean() {
+ local OVL=''
+ for OVL in $NV_OVERLAYS; do
+ rm -rf "${RWFS_MNT}${OVL}" "${RWFS_MNT}${OVL}.work"
+ done
+}
+
+# check for full factory reset: if so, ubiformat $NV_MTD_DEV
+bootflags="0x$(sed -n 's/^.*bootflags=\([0-9a-f]*\).*$/\1/p' /proc/cmdline)"
+bootflags=$((bootflags + 0))
+let "restore_op = $bootflags & 0x3"
+if [ $restore_op -eq 3 ]; then
+ ubiformat -y "$NV_MTD_DEV"
+fi
+
+# attach a UBI device to the MTD device
+NV_UBI_DEV="/dev/ubi${NV_MTD_NUM}"
+if [ ! -e $NV_UBI_DEV ]; then
+ if ! ubiattach -m "$NV_MTD_NUM" -d "$NV_MTD_NUM"; then
+ # the attach failed, so format the MTD device and try again
+ echo "Warning! Failed to attach $NV_UBI_DEV to $NV_MTD_DEV."
+ echo "UBI-formatting $NV_MTD_DEV to attach again. Data on this device will be lost."
+ ubiformat -y "$NV_MTD_DEV"
+ ubiattach -m "$NV_MTD_NUM" -d "$NV_MTD_NUM"
+ fi
+fi
+
+# make a UBI volume on the UBI device
+NV_UBI_VOL="${NV_UBI_DEV}_0"
+if [ ! -e $NV_UBI_VOL ]; then
+ ubimkvol "$NV_UBI_DEV" -N "$NV_MTD" -m
+fi
+
+# mount a UBIFS on the UBI volume
+mount -t ubifs "$NV_UBI_VOL" "$RWFS_MNT"
+
+if [ $restore_op -eq 1 ]; then
+ targetted_clean
+elif [ $restore_op -eq 2 ]; then
+ full_clean
+fi
+
+for FS in $NV_OVERLAYS; do
+ nvrw "$FS"
+done
+
+# make sure that /etc/fw_env.config mirrors our current uboot environment
+UENV_MTD_INFO=$(grep UENV /proc/mtd)
+if [ -n "$UENV_MTD_INFO" ]; then
+ UENV_MTD_INFO=$(echo "$UENV_MTD_INFO" | sed 's,^\([^:]*\): \([0-9a-f]*\) \([0-9a-f]*\) .*,/dev/\1 0 0x\2 0x\3,')
+ if ! grep -q "^${UENV_MTD_INFO}$" /etc/fw_env.config; then
+ echo "${UENV_MTD_INFO}" > /etc/fw_env.config
+ echo "Updated fw_env.config"
+ fi
+fi
+
+# 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 "$RWFS_MNT$MACHINE_ID" ]; then
+ umount "/etc"
+ rm -f "$RWFS_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
+ echo "Remounted /etc for machine-id origin mismatch"
+ else
+ generate_machine_id
+ fi
+fi
+
+# mount persistent NV filesystem, where immortal settings live
+if ! grep -q sofs /proc/mounts; then
+ mkdir -p /var/sofs
+ SOFS_MTD=sofs
+ SOFS_MTD_DEV="$(mtd_by_name ${SOFS_MTD})"
+ SOFS_MTD_NUM="$(mtdnum_by_name ${SOFS_MTD})"
+ SOFS_UBI_DEV="/dev/ubi${SOFS_MTD_NUM}"
+
+ # attach a UBI device to the MTD device
+ if [ ! -e $SOFS_UBI_DEV ]; then
+ if ! ubiattach -m "$SOFS_MTD_NUM" -d "$SOFS_MTD_NUM"; then
+ # the attach failed, so format the MTD device and try again
+ echo "Warning! Failed to attach $SOFS_UBI_DEV to $SOFS_MTD_DEV."
+ echo "UBI-formatting $SOFS_MTD_DEV to attach again. Data on this device will be lost."
+ ubiformat -y "$SOFS_MTD_DEV"
+ ubiattach -m "$SOFS_MTD_NUM" -d "$SOFS_MTD_NUM"
+ fi
+ fi
+
+ # make a UBI volume on the UBI device
+ SOFS_UBI_VOL="${SOFS_UBI_DEV}_0"
+ if [ ! -e $SOFS_UBI_VOL ]; then
+ ubimkvol "$SOFS_UBI_DEV" -N "$SOFS_MTD" -m
+ fi
+
+ # mount a UBIFS on the UBI volume
+ mount -t ubifs "$SOFS_UBI_VOL" /var/sofs
+fi
+
+echo "Finished mounting non-volatile overlays"
+
+exec /lib/systemd/systemd
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..2cdc93e29
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sel-logger/phosphor-sel-logger_%.bbappend
@@ -0,0 +1,7 @@
+# Enable downstream autobump
+SRC_URI = "git://github.com/openbmc/phosphor-sel-logger.git"
+SRCREV = "c4a336fb15464b9f4a7328c02cb43285a6eb1e58"
+
+# Enable threshold monitoring
+EXTRA_OECMAKE += "-DSEL_LOGGER_MONITOR_THRESHOLD_EVENTS=ON"
+EXTRA_OECMAKE += "-DREDFISH_LOG_MONITOR_PULSE_EVENTS=ON"
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..da1d74207
--- /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://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..ca3c2eba0
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -0,0 +1,7 @@
+SRCREV = "52497fd0fbd8adfe099a99f23515cd0341898e2e"
+SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
+
+DEPENDS_append = " libgpiod"
+
+#todo(cheng) remove this when synced upstream
+SYSTEMD_SERVICE_${PN} += " xyz.openbmc_project.psusensor.service"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend
new file mode 100644
index 000000000..436623234
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://defaults.yaml \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml
new file mode 100644
index 000000000..05d3df07e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-defaults-native/defaults.yaml
@@ -0,0 +1,209 @@
+/xyz/openbmc_project/control/minimum_ship_level_required:
+ - Interface: xyz.openbmc_project.Control.MinimumShipLevel
+ Properties:
+ MinimumShipLevelRequired:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/auto_reboot:
+ - Interface: xyz.openbmc_project.Control.Boot.RebootPolicy
+ Properties:
+ AutoReboot:
+ Default: 'false'
+
+/xyz/openbmc_project/control/host0/boot:
+ - Interface: xyz.openbmc_project.Control.Boot.Source
+ Properties:
+ BootSource:
+ Default: Source::Sources::Default
+ - Interface: xyz.openbmc_project.Control.Boot.Mode
+ Properties:
+ BootMode:
+ Default: Mode::Modes::Regular
+
+/xyz/openbmc_project/control/host0/boot/one_time:
+ - Interface: xyz.openbmc_project.Control.Boot.Source
+ Properties:
+ BootSource:
+ Default: Source::Sources::Default
+ - Interface: xyz.openbmc_project.Control.Boot.Mode
+ Properties:
+ BootMode:
+ Default: Mode::Modes::Regular
+ - Interface: xyz.openbmc_project.Object.Enable
+ Properties:
+ Enabled:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/power_cap:
+ - Interface: xyz.openbmc_project.Control.Power.Cap
+ Properties:
+ PowerCap:
+ Default: 0
+ Validation:
+ Type: "range"
+ Validator: "0..1000"
+ Unit: "Watts"
+ PowerCapEnable:
+ Default: 'false'
+
+/xyz/openbmc_project/control/host0/power_restore_policy:
+ - Interface: xyz.openbmc_project.Control.Power.RestorePolicy
+ Properties:
+ PowerRestorePolicy:
+ Default: RestorePolicy::Policy::AlwaysOff
+
+/xyz/openbmc_project/control/power_restore_delay:
+ - Interface: xyz.openbmc_project.Control.Power.RestoreDelay
+ Properties:
+ PowerRestoreDelay:
+ Default: 0
+
+/xyz/openbmc_project/control/host0/acpi_power_state:
+ - Interface: xyz.openbmc_project.Control.Power.ACPIPowerState
+ Properties:
+ SysACPIStatus:
+ Default: ACPIPowerState::ACPI::Unknown
+ DevACPIStatus:
+ Default: ACPIPowerState::ACPI::Unknown
+
+/xyz/openbmc_project/time/owner:
+ - Interface: xyz.openbmc_project.Time.Owner
+ Properties:
+ TimeOwner:
+ Default: Owner::Owners::BMC
+
+/xyz/openbmc_project/time/sync_method:
+ - Interface: xyz.openbmc_project.Time.Synchronization
+ Properties:
+ TimeSyncMethod:
+ Default: Synchronization::Method::NTP
+
+/xyz/openbmc_project/network/host0/intf:
+ - Interface: xyz.openbmc_project.Network.MACAddress
+ Properties:
+ MACAddress:
+ Default: '"00:00:00:00:00:00"'
+ Validation:
+ Type: "regex"
+ Validator: '^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'
+
+#needs to implement address validation TODO openbmc/issues/2046
+/xyz/openbmc_project/network/host0/intf/addr:
+ - Interface: xyz.openbmc_project.Network.IP
+ Properties:
+ Address:
+ Default: '"0.0.0.0"'
+ PrefixLength:
+ Default: 0
+ Validation:
+ Type: "range"
+ Validator: 0..128
+ Unit: "bits"
+ Origin:
+ Default: IP::AddressOrigin::Static
+ Gateway:
+ Default: '"0.0.0.0"'
+ Type:
+ Default: IP::Protocol::IPv4
+
+/xyz/openbmc_project/control/host0/restriction_mode:
+ - Interface: xyz.openbmc_project.Control.Security.RestrictionMode
+ Properties:
+ RestrictionMode:
+ Default: RestrictionMode::Modes::Provisioning
+
+/xyz/openbmc_project/control/host0/TPMEnable:
+ - Interface: xyz.openbmc_project.Control.TPM.Policy
+ Properties:
+ TPMEnable:
+ Default: 'false'
+
+/xyz/openbmc_project/control/power_supply_redundancy:
+ - Interface: xyz.openbmc_project.Control.PowerSupplyRedundancy
+ Properties:
+ PowerSupplyRedundancyEnabled:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/turbo_allowed:
+ - Interface: xyz.openbmc_project.Control.Host.TurboAllowed
+ Properties:
+ TurboAllowed:
+ Default: 'true'
+
+/xyz/openbmc_project/control/host0/systemGUID:
+ - Interface: xyz.openbmc_project.Common.UUID
+ Properties:
+ UUID:
+ Default: '"00000000-0000-0000-0000-000000000000"'
+
+/xyz/openbmc_project/bios:
+ - Interface: xyz.openbmc_project.Inventory.Item.Bios
+ Properties:
+ BiosId:
+ Default: '"NA"'
+
+/xyz/openbmc_project/control/processor_error_config:
+ - Interface: xyz.openbmc_project.Control.Processor.ErrConfig
+ Properties:
+ ResetCfg:
+ Default: 0
+ ResetErrorOccurrenceCounts:
+ Default: 0
+
+/com/intel/control/ocotshutdown_policy_config:
+ - Interface: com.intel.Control.OCOTShutdownPolicy
+ Properties:
+ OCOTPolicy:
+ Default: OCOTShutdownPolicy::Policy::NoShutdownOnOCOT
+
+/xyz/openbmc_project/control/chassis_capabilities_config:
+ - Interface: xyz.openbmc_project.Control.ChassisCapabilities
+ Properties:
+ CapabilitiesFlags:
+ Default: 0
+ FRUDeviceAddress:
+ Default: 0x20
+ SDRDeviceAddress:
+ Default: 0x20
+ SELDeviceAddress:
+ Default: 0x20
+ SMDeviceAddress:
+ Default: 0x20
+ BridgeDeviceAddress:
+ Default: 0x20
+
+/xyz/openbmc_project/control/thermal_mode:
+ - Interface: xyz.openbmc_project.Control.ThermalMode
+ Properties:
+ Current:
+ Default: '"Performance"'
+ Supported:
+ Default: '{"Acoustic", "Performance"}'
+
+/xyz/openbmc_project/control/cfm_limit:
+ - Interface: xyz.openbmc_project.Control.CFMLimit
+ Properties:
+ Limit:
+ Default: 0
+
+/xyz/openbmc_project/ipmi/sol:
+ - Interface: xyz.openbmc_project.Ipmi.SOL
+ Properties:
+ Progress:
+ Default: 0
+ Enable:
+ Default: 'true'
+ ForceEncryption:
+ Default: 'true'
+ ForceAuthentication:
+ Default: 'true'
+ Privilege:
+ Default: 4
+ AccumulateIntervalMS:
+ Default: 12
+ Threshold:
+ Default: 96
+ RetryCount:
+ Default: 6
+ RetryIntervalMS:
+ Default: 20
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch
new file mode 100644
index 000000000..fcf2415d6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager/0001-settings-initialize-data-file-with-default-setting.patch
@@ -0,0 +1,37 @@
+From 9e99aa4f72f4420e03ec2e4a29816eae43c5e748 Mon Sep 17 00:00:00 2001
+From: "Jia, Chunhui" <chunhui.jia@intel.com>
+Date: Tue, 29 May 2018 16:16:06 +0800
+Subject: [PATCH] [settings] initialize data file with default setting
+
+Current code trys to load settings from file at startup. When file
+does not exist, it will just use default setting. However, it will
+still load default on next reboot because no one create files.
+
+This change creates file as well when daemon loads default so next
+time daemon could load/save from file.
+
+Signed-off-by: Jia, Chunhui <chunhui.jia@intel.com>
+---
+ settings_manager.mako.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+ mode change 100644 => 100755 settings_manager.mako.hpp
+
+diff --git a/settings_manager.mako.hpp b/settings_manager.mako.hpp
+old mode 100644
+new mode 100755
+index 09a5a1f..cd592a0
+--- a/settings_manager.mako.hpp
++++ b/settings_manager.mako.hpp
+@@ -323,6 +323,9 @@ class Manager
+ else
+ {
+ initSetting${index}();
++ std::ofstream ostr(path.c_str(), std::ios::out);
++ cereal::JSONOutputArchive oarchive(ostr);
++ oarchive(*std::get<${index}>(settings)); //create file with default
+ }
+ }
+ catch (cereal::Exception& e)
+--
+2.16.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend
new file mode 100644
index 000000000..f5c924b31
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/phosphor-settings-manager_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-settings-initialize-data-file-with-default-setting.patch \
+ "
+
+DEPENDS += "intel-dbus-interfaces intel-dbus-interfaces-native"
+RDEPENDS_${PN} += "intel-dbus-interfaces"
+
+EXTRA_OEMAKE += "LDFLAGS='${LDFLAGS} -lintel_dbus'"
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..aadb48fbf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/settings/settings_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "Settings"
+
+SRC_URI = "git://git-amr-2.devtools.intel.com:29418/openbmc-provingground.git;protocol=ssh"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+PV = "0.1+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658"
+
+SYSTEMD_SERVICE_${PN} = "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..99cac7931
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/special-mode-mgr/special-mode-mgr_git.bb
@@ -0,0 +1,28 @@
+SUMMARY = "Special mode manager daemon to handle manufacturing modes"
+DESCRIPTION = "Daemon exposes the manufacturing mode property"
+
+PV = "1.0+git${SRCPV}"
+
+S = "${WORKDIR}/git/special-mode-mgr"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
+
+SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+inherit cmake systemd
+SYSTEMD_SERVICE_${PN} = "specialmodemgr.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/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..52ebdfd88
--- /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://git@github.com/Intel-BMC/provingground.git;protocol=ssh"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+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/0001-Modify-dbus-interface-for-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
new file mode 100644
index 000000000..fac9b52f1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
@@ -0,0 +1,38 @@
+From d34a2a5f6ca0564275ed0e2664624525cad64585 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 13 Jul 2018 09:08:52 +0800
+Subject: [PATCH] Modify dbus interface for power control
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch power control service namespace from “org” to “xyz”,
+to compatible with new intel-chassis services
+
+Change-Id: I1bf5e218f72eb9fd4fb6f203c35479818d12b1fa
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassis_state_manager.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
+index 03dd176..05e2440 100644
+--- a/chassis_state_manager.cpp
++++ b/chassis_state_manager.cpp
+@@ -63,10 +63,11 @@ void Chassis::determineInitialState()
+ {
+ sdbusplus::message::variant<int> pgood = -1;
+ auto method = this->bus.new_method_call(
+- "org.openbmc.control.Power", "/org/openbmc/control/power0",
++ "xyz.openbmc_project.Chassis.Control.Power",
++ "/xyz/openbmc_project/Chassis/Control/Power0",
+ "org.freedesktop.DBus.Properties", "Get");
+
+- method.append("org.openbmc.control.Power", "pgood");
++ method.append("xyz.openbmc_project.Chassis.Control.Power", "pgood");
+ try
+ {
+ auto reply = this->bus.call(method);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
new file mode 100644
index 000000000..2adff372e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
@@ -0,0 +1,338 @@
+From ed64fe7379a259a822aca69e70426a2b07aad25d Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 7 Aug 2018 16:43:00 +0800
+Subject: [PATCH] Capture host restart cause
+
+Capture host restart cause on power/reset button pressed,
+ipmi command/webui, host OS reboot(Ctrl-Alt-Del),
+and power restore policy settings.
+Save the restart cause into file system,
+and restore it when BMC boot up.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ configure.ac | 4 +-
+ discover_system_state.cpp | 14 +++++
+ host_state_manager.cpp | 17 ++++++
+ host_state_manager.hpp | 148 +++++++++++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 178 insertions(+), 5 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 7919ec5..051a0c0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -52,9 +52,9 @@ AC_ARG_VAR(HOST_RUNNING_FILE, [File to create if host is running])
+ AS_IF([test "x$HOST_RUNNING_FILE" == "x"], [HOST_RUNNING_FILE="/run/openbmc/host@%u-on"])
+ AC_DEFINE_UNQUOTED([HOST_RUNNING_FILE], ["$HOST_RUNNING_FILE"], [File to create if host is running])
+
+-AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing requested host state.])
++AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing host state.])
+ AS_IF([test "x$HOST_STATE_PERSIST_PATH" == "x"], \
+- [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/requestedHostTransition"])
++ [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/hostState"])
+ AC_DEFINE_UNQUOTED([HOST_STATE_PERSIST_PATH], ["$HOST_STATE_PERSIST_PATH"], \
+ [Path of file for storing requested host state.])
+
+diff --git a/discover_system_state.cpp b/discover_system_state.cpp
+index 3a38152..0b5798a 100644
+--- a/discover_system_state.cpp
++++ b/discover_system_state.cpp
+@@ -12,6 +12,7 @@
+ #include "settings.hpp"
+ #include "xyz/openbmc_project/Common/error.hpp"
+ #include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
++#include <xyz/openbmc_project/State/Host/server.hpp>
+
+ namespace phosphor
+ {
+@@ -181,6 +182,10 @@ int main(int argc, char** argv)
+ log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ convertForMessage(server::Host::Transition::On));
++
++ setProperty(
++ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
++ convertForMessage(server::Host::RestartCause::PowerPolicyAlwaysOn));
+ }
+ else if (RestorePolicy::Policy::Restore ==
+ RestorePolicy::convertPolicyFromString(powerPolicy))
+@@ -192,6 +197,15 @@ int main(int argc, char** argv)
+ getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ hostReqState);
++
++ if (server::Host::convertTransitionFromString(hostReqState) ==
++ server::Host::Transition::On)
++ {
++ setProperty(
++ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
++ convertForMessage(
++ server::Host::RestartCause::PowerPolicyPreviousState));
++ }
+ }
+
+ return 0;
+diff --git a/host_state_manager.cpp b/host_state_manager.cpp
+index 7d661dd..0e00e78 100644
+--- a/host_state_manager.cpp
++++ b/host_state_manager.cpp
+@@ -308,6 +308,15 @@ bool Host::deserialize(const fs::path& path)
+ }
+ }
+
++void Host::restoreHostRestartCause()
++{
++ if (!deserialize(HOST_STATE_PERSIST_PATH))
++ {
++ // set to default value
++ server::Host::hostRestartCause(server::Host::RestartCause::Unknown);
++ }
++}
++
+ Host::Transition Host::requestedHostTransition(Transition value)
+ {
+ log<level::INFO>("Host State transaction request",
+@@ -321,6 +330,7 @@ Host::Transition Host::requestedHostTransition(Transition value)
+ // check of this count will occur
+ if (value != server::Host::Transition::Off)
+ {
++ hostRestartCause(RestartCause::IpmiCommand);
+ decrementRebootCount();
+ }
+
+@@ -353,6 +363,13 @@ Host::HostState Host::currentHostState(HostState value)
+ return server::Host::currentHostState(value);
+ }
+
++Host::RestartCause Host::hostRestartCause(RestartCause value)
++{
++ auto retVal = server::Host::hostRestartCause(value);
++ serialize();
++ return retVal;
++}
++
+ } // namespace manager
+ } // namespace state
+ } // namespace phosphor
+diff --git a/host_state_manager.hpp b/host_state_manager.hpp
+index 2b00777..afd8aa3 100644
+--- a/host_state_manager.hpp
++++ b/host_state_manager.hpp
+@@ -32,6 +32,22 @@ using namespace phosphor::logging;
+ namespace sdbusRule = sdbusplus::bus::match::rules;
+ namespace fs = std::experimental::filesystem;
+
++const static constexpr char* powerButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Power0";
++const static constexpr char* powerButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Power";
++const static constexpr char* resetButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Reset0";
++const static constexpr char* resetButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Reset";
++
++const static constexpr char* powerControlService =
++ "xyz.openbmc_project.Chassis.Control.Power";
++const static constexpr char* powerControlPath =
++ "/xyz/openbmc_project/Chassis/Control/Power0";
++const static constexpr char* powerControlInterface =
++ "xyz.openbmc_project.Chassis.Control.Power";
++
+ /** @class Host
+ * @brief OpenBMC host state management implementation.
+ * @details A concrete implementation for xyz.openbmc_project.State.Host
+@@ -59,8 +75,93 @@ class Host : public HostInherit
+ sdbusRule::interface("org.freedesktop.systemd1.Manager"),
+ std::bind(std::mem_fn(&Host::sysStateChange), this,
+ std::placeholders::_1)),
+- settings(bus)
++ settings(bus),
++ powerButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(powerButtonPath) +
++ sdbusRule::interface(powerButtonIntf),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "powerButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::PowerButton);
++ this->powerButtonPressed = true;
++ return;
++ }),
++ resetButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(resetButtonPath) +
++ sdbusRule::interface(resetButtonIntf),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "resetButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::ResetButton);
++ this->resetButtonPressed = true;
++ return;
++ }),
++ postCompletePropSignal(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(
++ powerControlPath, powerControlInterface),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "postCompletePropSignal callback function is called...");
++
++ using DbusVariant = sdbusplus::message::variant<
++ std::string, bool, uint8_t, uint16_t, int16_t, uint32_t,
++ int32_t, uint64_t, int64_t, double>;
++
++ std::map<std::string, DbusVariant> props;
++ std::vector<std::string> inval;
++ std::string iface;
++ msg.read(iface, props, inval);
++
++ for (const auto& t : props)
++ {
++ auto key = t.first;
++ auto value = t.second;
++
++ if (key == "state")
++ {
++ this->powerStateChanged = true;
++ }
++
++ else if (key == "pgood")
++ {
++ this->pgood =
++ sdbusplus::message::variant_ns::get<int32_t>(value);
++ }
++
++ else if (key == "post_complete")
++ {
++ bool postState =
++ sdbusplus::message::variant_ns::get<bool>(value);
++
++ if (!postState && this->pgood)
++ {
++ if (!this->resetButtonPressed &&
++ !this->powerButtonPressed &&
++ !this->powerStateChanged)
++ {
++ phosphor::logging::log<
++ phosphor::logging::level::INFO>(
++ "OEM Reset");
++ this->hostRestartCause(this->RestartCause::OEM);
++ }
++ this->powerButtonPressed = false;
++ this->powerStateChanged = false;
++ this->resetButtonPressed = false;
++ }
++ }
++ }
++ })
+ {
++ powerButtonPressed = false;
++ powerStateChanged = false;
++ resetButtonPressed = false;
++ pgood = 0;
++
+ // Enable systemd signals
+ subscribeToSystemdSignals();
+
+@@ -69,8 +170,29 @@ class Host : public HostInherit
+
+ attemptsLeft(BOOT_COUNT_MAX_ALLOWED);
+
++ restoreHostRestartCause(); // restore host restart cause from persisted
++ // file
++
+ // We deferred this until we could get our property correct
+ this->emit_object_added();
++ sdbusplus::message::variant<int32_t> pgoodProp = -1;
++ auto method =
++ this->bus.new_method_call(powerControlService, powerControlPath,
++ "org.freedesktop.DBus.Properties", "Get");
++
++ method.append(powerControlInterface, "pgood");
++ try
++ {
++ auto reply = this->bus.call(method);
++ reply.read(pgoodProp);
++ pgood = sdbusplus::message::variant_ns::get<int>(pgoodProp);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ log<level::ERR>("Error performing call to get pgood",
++ entry("NAME=%s", e.name()),
++ entry("ERROR=%s", e.what()));
++ }
+ }
+
+ /** @brief Set value of HostTransition */
+@@ -85,6 +207,9 @@ class Host : public HostInherit
+ /** @brief Set value of CurrentHostState */
+ HostState currentHostState(HostState value) override;
+
++ /** @brief Set value of HostRestartCause */
++ RestartCause hostRestartCause(RestartCause value) override;
++
+ /**
+ * @brief Set host reboot count to default
+ *
+@@ -192,7 +317,9 @@ class Host : public HostInherit
+ server::Progress::bootProgress()),
+ convertForMessage(
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::
+- server::Status::operatingSystemState()));
++ server::Status::operatingSystemState()),
++ convertForMessage(sdbusplus::xyz::openbmc_project::State::
++ server::Host::hostRestartCause()));
+ }
+
+ /** @brief Function required by Cereal to perform deserialization.
+@@ -208,7 +335,8 @@ class Host : public HostInherit
+ std::string reqTranState;
+ std::string bootProgress;
+ std::string osState;
+- archive(reqTranState, bootProgress, osState);
++ std::string restartCause;
++ archive(reqTranState, bootProgress, osState, restartCause);
+ auto reqTran = Host::convertTransitionFromString(reqTranState);
+ // When restoring, set the requested state with persistent value
+ // but don't call the override which would execute it
+@@ -219,6 +347,8 @@ class Host : public HostInherit
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::
+ Status::operatingSystemState(
+ Host::convertOSStatusFromString(osState));
++ sdbusplus::xyz::openbmc_project::State::server::Host::hostRestartCause(
++ Host::convertRestartCauseFromString(restartCause));
+ }
+
+ /** @brief Serialize and persist requested host state
+@@ -239,6 +369,9 @@ class Host : public HostInherit
+ */
+ bool deserialize(const fs::path& path);
+
++ /** @brief Used to restore HostRestartCause value from persisted file */
++ void restoreHostRestartCause();
++
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+
+@@ -247,6 +380,15 @@ class Host : public HostInherit
+
+ // Settings objects of interest
+ settings::Objects settings;
++
++ bool resetButtonPressed;
++ bool powerButtonPressed;
++ bool powerStateChanged;
++ int32_t pgood;
++
++ sdbusplus::bus::match_t powerButtonPressedSignal;
++ sdbusplus::bus::match_t resetButtonPressedSignal;
++ sdbusplus::bus::match_t postCompletePropSignal;
+ };
+
+ } // namespace manager
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch
new file mode 100644
index 000000000..40722c3c9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch
@@ -0,0 +1,71 @@
+From 8a7f73a0688524c71023da89e8cb5578dac16f5d Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 8 Mar 2019 17:21:49 +0800
+Subject: [PATCH] Use warm-reboot for the Reboot host state transition
+
+The same as reset button pressing, the pgood signal will keep on during the reboot
+
+Tested By:
+ipmitool chassis power reset
+The pgood(gpio219) will be keep high during the reset process
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ host_state_manager.cpp | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/host_state_manager.cpp b/host_state_manager.cpp
+index 03d210d..8fac348 100644
+--- a/host_state_manager.cpp
++++ b/host_state_manager.cpp
+@@ -44,8 +44,9 @@ constexpr auto HOST_STATE_SOFT_POWEROFF_TGT = "obmc-host-shutdown@0.target";
+ constexpr auto HOST_STATE_POWEROFF_TGT = "obmc-host-stop@0.target";
+ constexpr auto HOST_STATE_POWERON_TGT = "obmc-host-start@0.target";
+ constexpr auto HOST_STATE_POWERON_MIN_TGT = "obmc-host-startmin@0.target";
+-constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-reboot@0.target";
++constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-warm-reset@0.target";
+ constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target";
++constexpr auto hostStateRebootService = "intel-power-warm-reset@0.service";
+
+ constexpr auto ACTIVE_STATE = "active";
+ constexpr auto ACTIVATING_STATE = "activating";
+@@ -168,6 +169,7 @@ bool Host::stateActive(const std::string& target)
+
+ const auto& currentStateStr =
+ sdbusplus::message::variant_ns::get<std::string>(currentState);
++
+ return currentStateStr == ACTIVE_STATE ||
+ currentStateStr == ACTIVATING_STATE;
+ }
+@@ -236,18 +238,22 @@ void Host::sysStateChange(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- if ((newStateUnit == HOST_STATE_POWEROFF_TGT) &&
+- (newStateResult == "done") &&
+- (!stateActive(HOST_STATE_POWERON_MIN_TGT)))
++ if (((newStateUnit == HOST_STATE_POWEROFF_TGT) &&
++ (newStateResult == "done") &&
++ (!stateActive(HOST_STATE_POWERON_MIN_TGT))) ||
++ ((newStateUnit == hostStateRebootService) &&
++ (newStateResult == "done")))
+ {
+ log<level::INFO>("Received signal that host is off");
+ this->currentHostState(server::Host::HostState::Off);
+ this->bootProgress(bootprogress::Progress::ProgressStages::Unspecified);
+ this->operatingSystemState(osstatus::Status::OSStatus::Inactive);
+ }
+- else if ((newStateUnit == HOST_STATE_POWERON_MIN_TGT) &&
+- (newStateResult == "done") &&
+- (stateActive(HOST_STATE_POWERON_MIN_TGT)))
++ else if (((newStateUnit == HOST_STATE_POWERON_MIN_TGT) &&
++ (newStateResult == "done") &&
++ (stateActive(HOST_STATE_POWERON_MIN_TGT))) ||
++ ((newStateUnit == HOST_STATE_REBOOT_TGT) &&
++ (newStateResult == "done")))
+ {
+ log<level::INFO>("Received signal that host is running");
+ this->currentHostState(server::Host::HostState::Running);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch
new file mode 100644
index 000000000..31cb31079
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch
@@ -0,0 +1,141 @@
+From 0edff651156ae63b6a73d9cb81e5e76cc6ae501a Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 12 Apr 2019 18:43:06 +0800
+Subject: [PATCH] Add Power Restore delay support
+
+That takes effect whenever the BMC
+automatically turns on the system due
+to the Power Restore Policy setting
+
+Tested:
+Set power restore delay:
+ipmitool raw 0x30 0x54 0 7
+Set restore policy as always-on:
+ipmitool chassis policy always-on
+AC off/on, check the journal log, the host will start boot after 7 seconds delay
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ discover_system_state.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 68 insertions(+), 3 deletions(-)
+
+diff --git a/discover_system_state.cpp b/discover_system_state.cpp
+index 0b5798a..298ae5b 100644
+--- a/discover_system_state.cpp
++++ b/discover_system_state.cpp
+@@ -1,5 +1,4 @@
+ #include <getopt.h>
+-#include <iostream>
+ #include <map>
+ #include <string>
+ #include <config.h>
+@@ -114,6 +113,49 @@ void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
+ return;
+ }
+
++int getPowerRestoreDelay(sdbusplus::bus::bus& bus, uint16_t& delay)
++{
++ static constexpr const char* powerRestoreDelayObjPath =
++ "/xyz/openbmc_project/control/power_restore_delay";
++ static constexpr const char* powerRestoreDelayIntf =
++ "xyz.openbmc_project.Control.Power.RestoreDelay";
++ static constexpr const char* powerRestoreDelayProp = "PowerRestoreDelay";
++
++ std::string service =
++ getService(bus, powerRestoreDelayObjPath, powerRestoreDelayIntf);
++
++ sdbusplus::message::message method = bus.new_method_call(
++ service.c_str(), powerRestoreDelayObjPath, PROPERTY_INTERFACE, "Get");
++
++ method.append(powerRestoreDelayIntf, powerRestoreDelayProp);
++
++ try
++ {
++ auto reply = bus.call(method);
++ sdbusplus::message::variant<uint16_t> variant;
++ reply.read(variant);
++ delay = sdbusplus::message::variant_ns::get<uint16_t>(variant);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get property",
++ phosphor::logging::entry("PROPERTY=%s", powerRestoreDelayProp),
++ phosphor::logging::entry("PATH=%s", powerRestoreDelayObjPath),
++ phosphor::logging::entry("INTERFACE=%s", powerRestoreDelayIntf));
++ return -1;
++ }
++ return 0;
++}
++
++void applyPowerRestoreDelay(uint16_t delay)
++{
++ if (delay > 0)
++ {
++ log<level::INFO>("Apply Power Restore Delay", entry("DELAY=%d", delay));
++ std::this_thread::sleep_for(std::chrono::milliseconds(1000 * delay));
++ }
++}
+ } // namespace manager
+ } // namespace state
+ } // namespace phosphor
+@@ -176,13 +218,27 @@ int main(int argc, char** argv)
+ log<level::INFO>("Host power is off, checking power policy",
+ entry("POWER_POLICY=%s", powerPolicy.c_str()));
+
++ uint16_t delay = 0;
++ int ret = getPowerRestoreDelay(bus, delay);
++
++ if (ret != 0)
++ {
++ log<level::WARNING>("getPowerRestoreDelay failed!");
++ delay = 0;
++ }
++
+ if (RestorePolicy::Policy::AlwaysOn ==
+ RestorePolicy::convertPolicyFromString(powerPolicy))
+ {
++ applyPowerRestoreDelay(delay);
++
+ log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
++
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ convertForMessage(server::Host::Transition::On));
+
++ // Host on, needs to set the restart cause after host transition
++ // since host transition will change the restart cause
+ setProperty(
+ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
+ convertForMessage(server::Host::RestartCause::PowerPolicyAlwaysOn));
+@@ -195,17 +251,26 @@ int main(int argc, char** argv)
+ // Read last requested state and re-request it to execute it
+ auto hostReqState =
+ getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
+- setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+- hostReqState);
+
+ if (server::Host::convertTransitionFromString(hostReqState) ==
+ server::Host::Transition::On)
+ {
++ applyPowerRestoreDelay(delay);
++ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
++ hostReqState);
++
++ // Host on, needs to set the restart cause after host transition
++ // since host transition will change the restart cause
+ setProperty(
+ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
+ convertForMessage(
+ server::Host::RestartCause::PowerPolicyPreviousState));
+ }
++ else
++ {
++ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
++ hostReqState);
++ }
+ }
+
+ return 0;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
new file mode 100644
index 000000000..ffde01ca3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Reboot host%i
+Wants=obmc-host-stop@%i.target
+After=obmc-host-stop@%i.target
+
+[Service]
+#ExecStart={base_bindir}/systemctl start obmc-host-start@%i.target
+# This service is starting another target that conflicts with the
+# target this service is running in. OpenBMC needs a refactor of
+# how it does its host reset path. Until then, this short term
+# solution does the job.
+# Since this is a part of the reboot target, call the startmin
+# target which does the minimum required to start the host.
+ExecStart=/bin/sh -c "sleep 10 && systemctl start obmc-host-startmin@%i.target"
+
+
+[Install]
+WantedBy=obmc-host-reboot@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
new file mode 100644
index 000000000..13b8f0fca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Check Host%i status on BMC reset
+Wants=mapper-wait@-xyz-openbmc_project-control-host%i.service
+After=mapper-wait@-xyz-openbmc_project-control-host%i.service
+Wants=obmc-host-reset-running@%i.target
+Before=obmc-host-reset-running@%i.target
+Wants=op-reset-chassis-on@%i.service
+After=op-reset-chassis-on@%i.service
+Conflicts=obmc-host-stop@%i.target
+ConditionPathExists=/run/openbmc/chassis@%i-on
+
+[Service]
+RemainAfterExit=yes
+Type=oneshot
+ExecStart=/bin/sh -c "if [ $(busctl get-property `mapper get-service /xyz/openbmc_project/Chassis/Control/Power%i` /xyz/openbmc_project/Chassis/Control/Power%i xyz.openbmc_project.Chassis.Control.Power vrd_good | sed 's/i\s*[1]/on/' | grep on | wc -l) != 0 ]; then mkdir -p /run/openbmc/ && touch /run/openbmc/host@%i-on; fi"
+SyslogIdentifier=phosphor-host-check
+
+[Install]
+WantedBy=obmc-host-reset@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
new file mode 100644
index 000000000..87c750c57
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Reset host reboot counter
+Wants=mapper-wait@-xyz-openbmc_project-state-host%i.service
+After=mapper-wait@-xyz-openbmc_project-state-host%i.service
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=no
+Type=oneshot
+ExecStart=/bin/sh -c "busctl set-property `mapper get-service /xyz/openbmc_project/state/host%i` /xyz/openbmc_project/state/host%i xyz.openbmc_project.Control.Boot.RebootAttempts AttemptsLeft u 3"
+StartLimitInterval=0
+
+[Install]
+WantedBy=obmc-host-start@%i.target
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..63155ce0d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
@@ -0,0 +1,10 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Modify-dbus-interface-for-power-control.patch \
+ file://phosphor-reboot-host@.service \
+ file://phosphor-reset-host-reboot-attempts@.service \
+ file://phosphor-reset-host-check@.service \
+ file://0002-Capture-host-restart-cause.patch \
+ file://0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch \
+ file://0004-Add-Power-Restore-delay-support.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch
new file mode 100644
index 000000000..8915484cd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch
@@ -0,0 +1,499 @@
+From 7d78e70735e1bce51ef34cfe128be68758de3447 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 19 Feb 2019 15:00:11 +0800
+Subject: [PATCH] Implement post code manager
+
+Implement method and properties defined in PostCode.interface.yaml
+under phosphor-dbus-interfaces/xyz/openbmc_project/State/Boot
+1. Method: std::vector<uint64_t> PostCode::getPostCodes(uint16_t index)
+2. Properties: CurrentBootCycleIndex/MaxBootCycleNum
+
+Test-By:
+ Every cycle post codes is saved in "/var/lib/phosphor-post-code-manager"
+ "1" file is saved all post codes for cycle 1
+ "2" file is saved all post codes for cycle 2
+ "CurrentBootCycleIndex" file is saved the current boot cycle number.
+ root@wolfpass:/var/lib/phosphor-post-code-manager# ls
+ 1 2 CurrentBootCycleIndex
+
+Change-Id: Ia89b9121983261fef5573092d890beb84626ceeb
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ CMakeLists.txt | 45 ++++++
+ MAINTAINERS | 45 ++++++
+ inc/post_code.hpp | 152 ++++++++++++++++++
+ ...penbmc_project.State.Boot.PostCode.service | 11 ++
+ src/main.cpp | 61 +++++++
+ src/post_code.cpp | 109 +++++++++++++
+ 6 files changed, 423 insertions(+)
+ create mode 100644 CMakeLists.txt
+ create mode 100644 MAINTAINERS
+ create mode 100644 inc/post_code.hpp
+ create mode 100644 service_files/xyz.openbmc_project.State.Boot.PostCode.service
+ create mode 100644 src/main.cpp
+ create mode 100644 src/post_code.cpp
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+new file mode 100644
+index 0000000..594d839
+--- /dev/null
++++ b/CMakeLists.txt
+@@ -0,0 +1,45 @@
++cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
++project(post-code-manager CXX)
++set(CMAKE_CXX_STANDARD 17)
++set(CMAKE_CXX_STANDARD_REQUIRED ON)
++
++set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
++include(GNUInstallDirs)
++include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
++include_directories(${CMAKE_CURRENT_BINARY_DIR})
++
++set(DBUS_OBJECT_NAME "xyz/openbmc_project/State/Boot/PostCode")
++set(DBUS_INTF_NAME "xyz.openbmc_project.State.Boot.PostCode")
++
++add_definitions(-DDBUS_OBJECT_NAME="/${DBUS_OBJECT_NAME}")
++add_definitions(-DDBUS_INTF_NAME="${DBUS_INTF_NAME}")
++set(SRC_FILES src/post_code.cpp
++ src/main.cpp )
++set ( SERVICE_FILES
++ service_files/xyz.openbmc_project.State.Boot.PostCode.service )
++
++# import sdbusplus
++find_package(PkgConfig REQUIRED)
++pkg_check_modules(SDBUSPLUSPLUS sdbusplus REQUIRED)
++include_directories(${SDBUSPLUSPLUS_INCLUDE_DIRS})
++link_directories(${SDBUSPLUSPLUS_LIBRARY_DIRS})
++find_program(SDBUSPLUSPLUS sdbus++)
++
++# import phosphor-logging
++find_package(PkgConfig REQUIRED)
++pkg_check_modules(LOGGING phosphor-logging REQUIRED)
++include_directories(${LOGGING_INCLUDE_DIRS})
++link_directories(${LOGGING_LIBRARY_DIRS})
++
++# 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(${PROJECT_NAME} ${SRC_FILES})
++target_link_libraries(${PROJECT_NAME} ${DBUSINTERFACE_LIBRARIES} )
++target_link_libraries(${PROJECT_NAME} "${SDBUSPLUSPLUS_LIBRARIES} -lstdc++fs -lphosphor_dbus")
++
++install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
++install (FILES ${SERVICE_FILES} DESTINATION /lib/systemd/system/)
+\ No newline at end of file
+diff --git a/MAINTAINERS b/MAINTAINERS
+new file mode 100644
+index 0000000..de6cc54
+--- /dev/null
++++ b/MAINTAINERS
+@@ -0,0 +1,45 @@
++How to use this list:
++ Find the most specific section entry (described below) that matches where
++ your change lives and add the reviewers (R) and maintainers (M) as
++ reviewers. You can use the same method to track down who knows a particular
++ code base best.
++
++ Your change/query may span multiple entries; that is okay.
++
++ If you do not find an entry that describes your request at all, someone
++ forgot to update this list; please at least file an issue or send an email
++ to a maintainer, but preferably you should just update this document.
++
++Description of section entries:
++
++ Section entries are structured according to the following scheme:
++
++ X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>
++ X: ...
++ .
++ .
++ .
++
++ Where REPO_NAME is the name of the repository within the OpenBMC GitHub
++ organization; FILE_PATH is a file path within the repository, possibly with
++ wildcards; X is a tag of one of the following types:
++
++ M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
++ if omitted from an entry, assume one of the maintainers from the
++ MAINTAINERS entry.
++ R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
++ these people are to be added as reviewers for a change matching the repo
++ path.
++ F: Denotes forked from an external repository; has fields URL.
++
++ Line comments are to be denoted "# SOME COMMENT" (typical shell style
++ comment); it is important to follow the correct syntax and semantics as we
++ may want to use automated tools with this file in the future.
++
++ A change cannot be added to an OpenBMC repository without a MAINTAINER's
++ approval; thus, a MAINTAINER should always be listed as a reviewer.
++
++START OF MAINTAINERS LIST
++-------------------------
++
++M: Kuiying Wang <kuiying.wang@intel.com> <kuiyingw>
+\ No newline at end of file
+diff --git a/inc/post_code.hpp b/inc/post_code.hpp
+new file mode 100644
+index 0000000..84c8b3e
+--- /dev/null
++++ b/inc/post_code.hpp
+@@ -0,0 +1,152 @@
++/*
++// 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.
++*/
++#pragma once
++#include <fcntl.h>
++#include <unistd.h>
++#include <cereal/cereal.hpp>
++#include <experimental/filesystem>
++#include <cereal/access.hpp>
++#include <cereal/archives/json.hpp>
++#include <iostream>
++#include <fstream>
++#include <cereal/types/vector.hpp>
++
++#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
++#include <xyz/openbmc_project/Common/error.hpp>
++#include <phosphor-logging/elog-errors.hpp>
++#include <xyz/openbmc_project/State/Host/server.hpp>
++
++#define MaxPostCodeCycles 100
++
++const static constexpr char *PostCodePath =
++ "/xyz/openbmc_project/state/boot/raw";
++const static constexpr char *PropertiesIntf =
++ "org.freedesktop.DBus.Properties";
++const static constexpr char *PostCodeListPath =
++ "/var/lib/phosphor-post-code-manager/";
++const static constexpr char *CurrentBootCycleIndexName =
++ "CurrentBootCycleIndex";
++const static constexpr char *HostStatePath =
++ "/xyz/openbmc_project/state/host0";
++
++
++struct EventDeleter
++{
++ void operator()(sd_event *event) const
++ {
++ event = sd_event_unref(event);
++ }
++};
++using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
++namespace fs = std::experimental::filesystem;
++namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
++
++using post_code =
++ sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
++
++struct PostCode : sdbusplus::server::object_t<post_code>
++{
++ PostCode(sdbusplus::bus::bus& bus, const char* path,
++ EventPtr &event) :
++ sdbusplus::server::object_t<post_code>(bus, path),
++ bus(bus),
++ propertiesChangedSignalRaw(
++ bus,
++ sdbusplus::bus::match::rules::type::signal() +
++ sdbusplus::bus::match::rules::member("PropertiesChanged") +
++ sdbusplus::bus::match::rules::path(PostCodePath) +
++ sdbusplus::bus::match::rules::interface(PropertiesIntf),
++ [this](sdbusplus::message::message &msg) {
++ std::string objectName;
++ std::map<std::string, sdbusplus::message::variant<uint64_t>> msgData;
++ msg.read(objectName, msgData);
++ // Check if it was the Value property that changed.
++ auto valPropMap = msgData.find("Value");
++ {
++ if (valPropMap != msgData.end())
++ {
++ this->savePostCodes(sdbusplus::message::variant_ns::get<uint64_t>(valPropMap->second));
++ }
++ }
++ }),
++ propertiesChangedSignalCurrentHostState(
++ bus,
++ sdbusplus::bus::match::rules::type::signal() +
++ sdbusplus::bus::match::rules::member("PropertiesChanged") +
++ sdbusplus::bus::match::rules::path(HostStatePath) +
++ sdbusplus::bus::match::rules::interface(PropertiesIntf),
++ [this](sdbusplus::message::message &msg) {
++ std::string objectName;
++ std::map<std::string, sdbusplus::message::variant<std::string>> msgData;
++ msg.read(objectName, msgData);
++ // Check if it was the Value property that changed.
++ auto valPropMap = msgData.find("CurrentHostState");
++ {
++ if (valPropMap != msgData.end())
++ {
++ StateServer::Host::HostState currentHostState =
++ StateServer::Host::convertHostStateFromString(
++ sdbusplus::message::variant_ns::get<std::string>(valPropMap->second));
++ if (currentHostState == StateServer::Host::HostState::Off)
++ {
++ if (this->currentBootCycleIndex() >= this->maxBootCycleNum())
++ {
++ this->currentBootCycleIndex(1);
++ } else{
++ this->currentBootCycleIndex(this->currentBootCycleIndex() + 1);
++ }
++ this->postCodes.clear();
++ }
++ }
++ }
++ })
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "PostCode is created");
++ auto dir = fs::path(PostCodeListPath);
++ fs::create_directories(dir);
++ strPostCodeListPath = PostCodeListPath;
++ strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
++ uint16_t index = 0;
++ deserialize(fs::path(strPostCodeListPath + strCurrentBootCycleIndexName), index);
++ currentBootCycleIndex(index);
++ maxBootCycleNum(MaxPostCodeCycles);
++ if (currentBootCycleIndex() >= maxBootCycleNum())
++ {
++ currentBootCycleIndex(1);
++ } else{
++ currentBootCycleIndex(currentBootCycleIndex() + 1);
++ }
++ }
++ ~PostCode()
++ {
++
++ }
++
++ std::vector<uint64_t> getPostCodes(uint16_t index) override;
++
++ private:
++ sdbusplus::bus::bus& bus;
++ std::vector<uint64_t> postCodes;
++ std::string strPostCodeListPath;
++ std::string strCurrentBootCycleIndexName;
++ void savePostCodes(uint64_t code);
++ sdbusplus::bus::match_t propertiesChangedSignalRaw;
++ sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
++ fs::path serialize(const std::string& path);
++ bool deserialize(const fs::path& path, uint16_t& index);
++ bool deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes);
++};
+diff --git a/service_files/xyz.openbmc_project.State.Boot.PostCode.service b/service_files/xyz.openbmc_project.State.Boot.PostCode.service
+new file mode 100644
+index 0000000..67bc43f
+--- /dev/null
++++ b/service_files/xyz.openbmc_project.State.Boot.PostCode.service
+@@ -0,0 +1,11 @@
++[Unit]
++Description=Post code manager
++
++[Service]
++ExecStart=/usr/bin/env post-code-manager
++SyslogIdentifier=post-code-manager
++Type=dbus
++BusName=xyz.openbmc_project.State.Boot.PostCode
++
++[Install]
++WantedBy=obmc-standby.target
+diff --git a/src/main.cpp b/src/main.cpp
+new file mode 100644
+index 0000000..4a74b29
+--- /dev/null
++++ b/src/main.cpp
+@@ -0,0 +1,61 @@
++/*
++// 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.
++*/
++#include "post_code.hpp"
++
++int main(int argc, char* argv[])
++{
++ int ret = 0;
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Start post code manager service...");
++
++ sd_event* event = nullptr;
++ ret = sd_event_default(&event);
++ if (ret < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error creating a default sd_event handler");
++ return ret;
++ }
++ EventPtr eventP{event};
++ event = nullptr;
++
++ sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
++ sdbusplus::server::manager_t m{bus, DBUS_OBJECT_NAME};
++
++ bus.request_name(DBUS_INTF_NAME);
++
++ PostCode postCode{bus, DBUS_OBJECT_NAME, eventP};
++
++ try
++ {
++ bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
++ ret = sd_event_loop(eventP.get());
++ if (ret < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error occurred during the sd_event_loop",
++ phosphor::logging::entry("RET=%d", ret));
++ }
++ }
++ catch (std::exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return -1;
++ }
++ return 0;
++
++}
+diff --git a/src/post_code.cpp b/src/post_code.cpp
+new file mode 100644
+index 0000000..983eeee
+--- /dev/null
++++ b/src/post_code.cpp
+@@ -0,0 +1,109 @@
++/*
++// 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.
++*/
++#include "post_code.hpp"
++std::vector<uint64_t> PostCode::getPostCodes(uint16_t index)
++{
++ std::vector<uint64_t> codes;
++
++ if (currentBootCycleIndex() == index)
++ return postCodes;
++ deserializePostCodes(fs::path(strPostCodeListPath + std::to_string(index)), codes);
++ return codes;
++}
++void PostCode::savePostCodes(uint64_t code)
++{
++ postCodes.push_back(code);
++ serialize(fs::path(PostCodeListPath));
++ return;
++}
++
++fs::path PostCode::serialize(const std::string& path)
++{
++ try
++ {
++ uint16_t index = currentBootCycleIndex();
++ fs::path fullPath(path + strCurrentBootCycleIndexName);
++ std::ofstream os(fullPath.c_str(), std::ios::binary);
++ cereal::JSONOutputArchive oarchive(os);
++ oarchive(index);
++
++ std::ofstream osPostCodes((path + std::to_string(currentBootCycleIndex())).c_str(), std::ios::binary);
++ cereal::JSONOutputArchive oarchivePostCodes(osPostCodes);
++ oarchivePostCodes(postCodes);
++
++ return path;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ }
++}
++
++bool PostCode::deserialize(const fs::path& path, uint16_t& index)
++{
++ try
++ {
++ if (fs::exists(path))
++ {
++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
++ cereal::JSONInputArchive iarchive(is);
++ iarchive(index);
++ return true;
++ }
++ return false;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return false;
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ return false;
++ }
++
++ return false;
++}
++
++bool PostCode::deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes)
++{
++ try
++ {
++ if (fs::exists(path))
++ {
++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
++ cereal::JSONInputArchive iarchive(is);
++ iarchive(codes);
++ return true;
++ }
++ return false;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return false;
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ return false;
++ }
++
++ return false;
++}
+--
+2.19.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb
new file mode 100644
index 000000000..8f2ead18a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb
@@ -0,0 +1,34 @@
+SUMMARY = "Phosphor post code manager"
+DESCRIPTION = "Post Code Manager"
+
+SRC_URI = "git://github.com/openbmc/phosphor-post-code-manager.git"
+SRCREV = "7f50dcaa6feb66cf5307b8a0e4742a36a50eed29"
+
+S = "${WORKDIR}/git"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+inherit cmake pkgconfig systemd
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.State.Boot.PostCode.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 \
+ "
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += "file://0001-Implement-post-code-manager.patch"
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..e272fdc96
--- /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://git@github.com/Intel-BMC/provingground;protocol=ssh"
+
+inherit cmake systemd
+DEPENDS = "boost sdbusplus"
+
+PV = "0.1+git${SRCPV}"
+SRCREV = "4373d99e1edcbb4c7233abde3a5e53690693007b"
+
+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..5c2879d8f
--- /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,1648 @@
+From 726be648df955f5ae94f34391adc0e88f6956345 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 | 293 +++------------------
+ user_mgr.hpp | 9 +-
+ user_service.cpp | 781 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ user_service.hpp | 233 +++++++++++++++++
+ 6 files changed, 1141 insertions(+), 269 deletions(-)
+ create mode 100644 user_service.cpp
+ create mode 100644 user_service.hpp
+
+diff --git a/Makefile.am b/Makefile.am
+index b138aea..288b780 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,11 +1,12 @@
+ sbin_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 47edf7d..32f3f4c 100644
+--- a/user_mgr.cpp
++++ b/user_mgr.cpp
+@@ -14,26 +14,20 @@
+ // limitations under the License.
+ */
+
+-#include <shadow.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <sys/wait.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"
+@@ -43,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;
+@@ -94,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())
+@@ -293,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(
+@@ -339,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);
+
+@@ -362,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();
+@@ -403,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();
+@@ -420,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()));
+@@ -638,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()),
+@@ -728,49 +570,8 @@ bool UserMgr::userLockedForFailedAttempt(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;
+- }
+- // 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)))
+- {
+- 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()
+@@ -781,49 +582,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)
+@@ -1018,11 +784,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())
+ {
+@@ -1077,8 +841,10 @@ void UserMgr::initUserObjects(void)
+ }
+ }
+
+-UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+- UserMgrIface(bus, path), AccountPolicyIface(bus, path), bus(bus), path(path)
++UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path,
++ UserService::ServiceType srvc) :
++ UserMgrIface(bus, path),
++ AccountPolicyIface(bus, path), bus(bus), path(path)
+ {
+ UserMgrIface::allPrivileges(privMgr);
+ std::sort(groupsMgr.begin(), groupsMgr.end());
+@@ -1186,6 +952,7 @@ UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) :
+ }
+ AccountPolicyIface::accountUnlockTimeout(value32);
+ }
++ userSrvc = std::make_unique<UserService>(srvc, groupsMgr, privMgr);
+ initUserObjects();
+ }
+
+diff --git a/user_mgr.hpp b/user_mgr.hpp
+index c78174d..9d9c842 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;
+
+@@ -71,8 +70,10 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
+ *
+ * @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
+@@ -181,6 +182,8 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
+ /** @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-callback"};
+diff --git a/user_service.cpp b/user_service.cpp
+new file mode 100644
+index 0000000..9bb602c
+--- /dev/null
++++ b/user_service.cpp
+@@ -0,0 +1,781 @@
++/*
++// 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;
++ }
++ // 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)))
++ {
++ 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_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
new file mode 100644
index 000000000..2cc081433
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+#SRC_URI = "git://github.com/openbmc/phosphor-user-manager"
+SRCREV = "75b5a6fc4c0c06f43623fe0e746fd55e667dceb3"
+
+
+SRC_URI += " \
+ file://0005-Added-suport-for-multiple-user-manager-services.patch \
+ "
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..950f4932d
--- /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://${PHOSPHORBASE}/LICENSE;md5=19407077e42b1ba3d653da313f1f5b4e"
+
+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-Add-redfish-log-support-for-IPMI-watchdog-timeout-ac.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Add-redfish-log-support-for-IPMI-watchdog-timeout-ac.patch
new file mode 100644
index 000000000..28995d14b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Add-redfish-log-support-for-IPMI-watchdog-timeout-ac.patch
@@ -0,0 +1,51 @@
+From 38faf5c040660e752741dcf7f03e4bb1e9f3411b Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Thu, 4 Apr 2019 18:24:54 +0800
+Subject: [PATCH] Add redfish log support for IPMI watchdog timeout actions
+
+The current plan is that only threshold sensor events
+will be logged to the IPMI SEL,
+and all other events will be logged to the Redfish Event Log.
+
+Tested:
+Config IPMI watchdog: OEM hard reset after 10 seconds:
+ipmitool raw 0x06 0x24 0x5 0x1 0x0 0x0 0x64 0x00
+Start watchdog:
+Ipmitool mc watchdog reset
+Check the redfish logs in 10 seconds:
+https://BMCIP/redfish/v1/Systems/system/LogServices/EventLog/Entries
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ watchdog.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/watchdog.cpp b/watchdog.cpp
+index bc3ba95..4774fd8 100644
+--- a/watchdog.cpp
++++ b/watchdog.cpp
+@@ -1,5 +1,7 @@
+ #include "watchdog.hpp"
+
++#include <systemd/sd-journal.h>
++
+ #include <chrono>
+ #include <phosphor-logging/elog.hpp>
+ #include <phosphor-logging/log.hpp>
+@@ -101,6 +103,13 @@ void Watchdog::timeOutHandler()
+ action = fallback->action;
+ }
+
++ // 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",
++ convertForMessage(action).c_str(), NULL);
++
+ expiredTimerUse(currentTimerUse());
+
+ auto target = actionTargetMap.find(action);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0002-Add-restart-cause-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0002-Add-restart-cause-support.patch
new file mode 100644
index 000000000..05374e9db
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0002-Add-restart-cause-support.patch
@@ -0,0 +1,82 @@
+From af3a7d07b801c22a03350897c2186b1ee9507ff2 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Sun, 14 Apr 2019 11:14:09 +0800
+Subject: [PATCH] Add restart cause support
+
+Add restart cause support for watchdog expiration, to support
+Get system restart cause command defined in IPMI spec
+
+Tested:
+Set a hard reset watchdog:
+ipmitool raw 0x06 0x24 0x5 0x1 0x0 0x0 0x64 0x00
+
+Start the timer:
+ipmitool mc watchdog reset
+
+Wait for 10 seconds, host will be restart, query the restart cause:
+Ipmitool chassis restart_cause
+System restart cause: watchdog expired
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ watchdog.cpp | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/watchdog.cpp b/watchdog.cpp
+index 008cde5..7f1ec05 100644
+--- a/watchdog.cpp
++++ b/watchdog.cpp
+@@ -7,6 +7,7 @@
+ #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
+ {
+@@ -24,6 +25,12 @@ constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
+ constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
+ constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
+
++// host state manager service
++static constexpr const char* hostService = "xyz.openbmc_project.State.Host";
++static constexpr const char* hostPath = "/xyz/openbmc_project/state/host0";
++static constexpr const char* hostInterface = "xyz.openbmc_project.State.Host";
++static constexpr const char* dbusPropIf = "org.freedesktop.DBus.Properties";
++
+ void Watchdog::resetTimeRemaining(bool enableWatchdog)
+ {
+ timeRemaining(interval());
+@@ -139,6 +146,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))
++ {
++ sdbusplus::message::variant<std::string> property =
++ convertForMessage(
++ (sdbusplus::xyz::openbmc_project::State::server::Host::
++ RestartCause::WatchdogTimer));
++ try
++ {
++ auto method = bus.new_method_call(hostService, hostPath,
++ dbusPropIf, "Set");
++ method.append(hostInterface, "HostRestartCause", property);
++ bus.call(method);
++ }
++ catch (sdbusplus::exception_t& e)
++ {
++ log<level::ERR>("Failed to set HostRestartCause property",
++ entry("ERROR=%s", e.what()));
++ commit<InternalFailure>();
++ }
++ }
+ }
+
+ tryFallbackOrDisable();
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0003-Add-redfish-log-support-for-IPMI-watchdog-pre-timeou.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0003-Add-redfish-log-support-for-IPMI-watchdog-pre-timeou.patch
new file mode 100644
index 000000000..309a8c646
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0003-Add-redfish-log-support-for-IPMI-watchdog-pre-timeou.patch
@@ -0,0 +1,48 @@
+From 46e8e4fe6cb48145152e37380a4064c8957d2ff7 Mon Sep 17 00:00:00 2001
+From: Ren Yu <yux.ren@intel.com>
+Date: Tue, 28 May 2019 17:04:10 +0800
+Subject: [PATCH] Add redfish log support for IPMI watchdog pre-timeout
+ interrupt
+
+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 redfish logs in 1 seconds:
+https://BMCIP/redfish/v1/Systems/system/LogServices/EventLog/Entries
+
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+---
+ watchdog.cpp | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/watchdog.cpp b/watchdog.cpp
+index d893237..5062049 100644
+--- a/watchdog.cpp
++++ b/watchdog.cpp
+@@ -104,6 +104,8 @@ uint64_t Watchdog::timeRemaining(uint64_t value)
+ // Optional callback function on timer expiration
+ void Watchdog::timeOutHandler()
+ {
++ PreTimeoutInterruptAction preTimeoutInterruptAction = preTimeoutInterrupt();
++
+ Action action = expireAction();
+ if (!this->enabled())
+ {
+@@ -117,6 +119,12 @@ void Watchdog::timeOutHandler()
+ "REDFISH_MESSAGE_ARGS=%s",
+ convertForMessage(action).c_str(), NULL);
+
++ 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=%s",
++ convertForMessage(preTimeoutInterruptAction).c_str(), NULL);
++
+ expiredTimerUse(currentTimerUse());
+
+ auto target = actionTargetMap.find(action);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service
new file mode 100644
index 000000000..87a662f7c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/obmc-enable-host-watchdog@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Start FRB2 Watchdog%i
+Wants=obmc-host-started@%i.target
+After=obmc-host-started@%i.target
+Wants=mapper-wait@-xyz-openbmc_project-watchdog-host%i.service
+After=mapper-wait@-xyz-openbmc_project-watchdog-host%i.service
+Conflicts=obmc-host-stop@%i.target
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=always
+ExecStart=/usr/bin/env frb2-watchdog
+ExecStopPost=/bin/sh -c "busctl call `mapper get-service /xyz/openbmc_project/watchdog/host%i` /xyz/openbmc_project/watchdog/host%i org.freedesktop.DBus.Properties Set ssv xyz.openbmc_project.State.Watchdog Enabled b false"
+SyslogIdentifier=obmc-enable-host-watchdog
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..251c2257b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/phosphor-watchdog@.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Phosphor %I watchdog
+
+[Service]
+Restart=no
+EnvironmentFile={envfiledir}/obmc/watchdog/%I
+ExecStart=/usr/bin/env phosphor-watchdog --continue --service=${{SERVICE}} --path=${{DEVPATH}} \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.HardReset=obmc-host-warm-reset@0.target \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.PowerOff=obmc-host-shutdown@0.target \
+ --action_target=xyz.openbmc_project.State.Watchdog.Action.PowerCycle=obmc-host-reboot@0.target
+
+SyslogIdentifier=phosphor-watchdog
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..c117102ee
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog_%.bbappend
@@ -0,0 +1,9 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+SRC_URI += "file://0001-Add-redfish-log-support-for-IPMI-watchdog-timeout-ac.patch \
+ file://0002-Add-restart-cause-support.patch \
+ file://0003-Add-redfish-log-support-for-IPMI-watchdog-pre-timeou.patch \
+ "
+
+# Remove the override to keep service running after DC cycle
+SYSTEMD_OVERRIDE_${PN}_remove = "poweron.conf:phosphor-watchdog@poweron.service.d/poweron.conf"
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..5da053f1d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/system-watchdog.bb
@@ -0,0 +1,13 @@
+SUMMARY = "System watchdog"
+DESCRIPTION = "BMC hardware watchdog service that is used to reset BMC \
+ when unrecoverable events occurs"
+
+inherit allarch
+inherit obmc-phosphor-systemd
+
+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"
+
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/webui/phosphor-webui/0004-Implement-force-boot-to-bios-in-server-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0004-Implement-force-boot-to-bios-in-server-power-control.patch
new file mode 100644
index 000000000..0e2d400a3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0004-Implement-force-boot-to-bios-in-server-power-control.patch
@@ -0,0 +1,199 @@
+From a4f948f98e9bfd8b019699b4e23281448f7b7313 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Wed, 27 Mar 2019 19:35:12 +0800
+Subject: [PATCH] Implement force to BIOS
+
+UI page review use below link:
+https://projects.invisionapp.com/share/UER87D98GPM#/screens
+
+Tested:
+ Switch on "Boot To BIOS", could enter BIOS setup page directly
+ when power on system.
+
+Change-Id: Ib46dc5d84df51d31cc5ff8635fa0c0f52de0e194
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ app/common/services/api-utils.js | 49 +++++++++++++++++++
+ app/common/services/constants.js | 4 ++
+ app/common/services/dataService.js | 1 +
+ .../power-operations-controller.html | 12 +++++
+ .../power-operations-controller.js | 32 ++++++++++++
+ 5 files changed, 98 insertions(+)
+
+diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
+index 840db8e..193c172 100644
+--- a/app/common/services/api-utils.js
++++ b/app/common/services/api-utils.js
+@@ -31,6 +31,7 @@ window.angular && (function(angular) {
+ HOST_STATE: Constants.HOST_STATE,
+ LED_STATE: Constants.LED_STATE,
+ LED_STATE_TEXT: Constants.LED_STATE_TEXT,
++ FORCE_TO_BIOS_STATE_TEXT: Constants.FORCE_TO_BIOS_STATE_TEXT,
+ HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
+ getChassisState: function() {
+ var deferred = $q.defer();
+@@ -451,6 +452,32 @@ window.angular && (function(angular) {
+ });
+ return deferred.promise;
+ },
++ getForceToBIOSState: function() {
++ var deferred = $q.defer();
++
++ if (DataService.configJson.redfishSupportEnabled == true) {
++ $http({
++ method: 'GET',
++ url:
++ DataService.getHost() + '/redfish/v1/Systems/system',
++ withCredentials: true
++ }).then(
++ function(response) {
++ var json = JSON.stringify(response.data);
++ var content = JSON.parse(json);
++ deferred.resolve(content.Boot.BootSourceOverrideTarget);
++ },
++ function(error) {
++ console.log(error);
++ deferred.reject(error);
++ });
++ } else {
++ var err = "Redfish is not enabled!";
++ console.log(err);
++ deferred.reject(err);
++ }
++ return deferred.promise;
++ },
+ login: function(username, password, callback) {
+ $http({
+ method: 'POST',
+@@ -872,6 +899,28 @@ window.angular && (function(angular) {
+ }
+ });
+ },
++ setForceToBIOSState: function(state) {
++ if (DataService.configJson.redfishSupportEnabled == true) {
++ var data = JSON.stringify({'Boot':
++ {
++ 'BootSourceOverrideTarget': state
++ }
++ });
++ return $http({
++ method: 'PATCH',
++ url:
++ DataService.getHost() + '/redfish/v1/Systems/system',
++ withCredentials: true,
++ data: data
++ });
++ } else {
++ var deferred = $q.defer();
++ var err = "Redfish is not enabled!";
++ console.log(err);
++ deferred.reject(err);
++ return deferred.promise;
++ }
++ },
+ getLastRebootTime: function() {
+ return $http({
+ method: 'GET',
+diff --git a/app/common/services/constants.js b/app/common/services/constants.js
+index 9931f01..8da0b12 100644
+--- a/app/common/services/constants.js
++++ b/app/common/services/constants.js
+@@ -38,6 +38,10 @@ window.angular && (function(angular) {
+ HOST_STATE: {on: 1, off: -1, error: 0, unreachable: -2},
+ LED_STATE: {on: true, off: false},
+ LED_STATE_TEXT: {on: 'on', off: 'off'},
++ FORCE_TO_BIOS_STATE_TEXT: {
++ on: 'BiosSetup',
++ off: 'None'
++ },
+ SEVERITY_TO_PRIORITY_MAP: {
+ Emergency: 'High',
+ Alert: 'High',
+diff --git a/app/common/services/dataService.js b/app/common/services/dataService.js
+index 76ab381..bcd7142 100644
+--- a/app/common/services/dataService.js
++++ b/app/common/services/dataService.js
+@@ -18,6 +18,7 @@ window.angular && (function(angular) {
+ this.server_status = -2;
+ this.chassis_state = 'On';
+ this.LED_state = Constants.LED_STATE_TEXT.off;
++ this.ForceToBIOS_state = Constants.FORCE_TO_BIOS_STATE_TEXT.off;
+ this.last_updated = new Date();
+
+ this.loading = false;
+diff --git a/app/server-control/controllers/power-operations-controller.html b/app/server-control/controllers/power-operations-controller.html
+index 3dc69d2..1f00f4a 100644
+--- a/app/server-control/controllers/power-operations-controller.html
++++ b/app/server-control/controllers/power-operations-controller.html
+@@ -10,6 +10,18 @@
+ <div class="row column">
+ <div id="power-indicator-bar" class="power__indicator-bar" ng-class="{'power__state-on': dataService.server_state == 'Running', 'power__state-off': dataService.server_state == 'Off', 'power__state-indet': dataService.server_state == 'Standby', 'power__state-error': dataService.server_state == 'Quiesced'}">
+ <p class="inline">{{dataService.hostname}} - {{dataService.server_id}}</p>
++ <div class="toggle float-right">
++ <input id="toggle__switch-round"
++ class="toggle-switch toggle-switch__round-flat"
++ type="checkbox"
++ tabindex="0"
++ ng-click="toggleForceToBIOS()"
++ ng-checked="dataService.ForceToBIOS_state == 'BiosSetup'"
++ ng-disabled="dataService.server_unreachable">
++ <label for="toggle__switch-round" tabindex="0"> </label>
++ <h3 class="inline">Boot to BIOS</h3>
++ </div>
++
+ <h3 class="power__state inline no-margin h3"><span>{{dataService.server_state | quiescedToError}}</span></h3>
+ </div>
+ </div>
+diff --git a/app/server-control/controllers/power-operations-controller.js b/app/server-control/controllers/power-operations-controller.js
+index 1a1f355..9a832e8 100644
+--- a/app/server-control/controllers/power-operations-controller.js
++++ b/app/server-control/controllers/power-operations-controller.js
+@@ -26,6 +26,17 @@ window.angular && (function(angular) {
+
+ var pollChassisStatusTimer = undefined;
+ var pollStartTime = null;
++ APIUtils.getForceToBIOSState().then(
++ function(data) {
++ if (data == APIUtils.FORCE_TO_BIOS_STATE_TEXT.on) {
++ dataService.ForceToBIOS_state = APIUtils.FORCE_TO_BIOS_STATE_TEXT.on;
++ } else {
++ dataService.ForceToBIOS_state = APIUtils.FORCE_TO_BIOS_STATE_TEXT.off;
++ }
++ },
++ function(error) {
++ console.log(JSON.stringify(error));
++ });
+
+ //@TODO: call api and get proper state
+
+@@ -50,6 +61,27 @@ window.angular && (function(angular) {
+ (dataService.server_state == 'Running') ? 'Off' : 'Running';
+ };
+
++ $scope.toggleForceToBIOS = function() {
++ var toggleState =
++ (dataService.ForceToBIOS_state == APIUtils.FORCE_TO_BIOS_STATE_TEXT.on) ?
++ APIUtils.FORCE_TO_BIOS_STATE_TEXT.off :
++ APIUtils.FORCE_TO_BIOS_STATE_TEXT.on;
++ dataService.ForceToBIOS_state =
++ (dataService.ForceToBIOS_state == APIUtils.FORCE_TO_BIOS_STATE_TEXT.on) ?
++ APIUtils.FORCE_TO_BIOS_STATE_TEXT.off :
++ APIUtils.FORCE_TO_BIOS_STATE_TEXT.on;
++ APIUtils.setForceToBIOSState(toggleState)
++ .then(
++ function(response) {},
++ function(errors) {
++ toastService.error(
++ 'Failed to set Boot to BIOS ');
++ console.log(JSON.stringify(errors));
++ // Reload to get correct current state
++ $route.reload();
++ })
++ };
++
+ $scope.powerOn = function() {
+ $scope.loading = true;
+ dataService.setUnreachableState();
+--
+2.19.1
+
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..f4b054acf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend
@@ -0,0 +1,6 @@
+FILESEXTRAPATHS_append := ":${THISDIR}/${PN}"
+
+#SRC_URI = "git://github.com/openbmc/phosphor-webui.git"
+SRCREV = "e4ae854c217344b4f35717e922083a253f43bfa0"
+
+SRC_URI += "file://0004-Implement-force-boot-to-bios-in-server-power-control.patch"
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/libgpiod/libgpiod/0001-Add-pass-through-setting-in-gpioset.patch b/meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod/0001-Add-pass-through-setting-in-gpioset.patch
new file mode 100644
index 000000000..b9082468c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod/0001-Add-pass-through-setting-in-gpioset.patch
@@ -0,0 +1,266 @@
+From 0c393ec7a71f21506334caa3a321fa013a9723ef Mon Sep 17 00:00:00 2001
+From: Ed Tanous <ed.tanous@intel.com>
+Date: Mon, 8 Apr 2019 11:46:09 -0700
+Subject: [PATCH] [PATCH] Add pass through setting in gpioset
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Ed Tanous <ed.tanous@intel.com>
+---
+ aclocal.m4 | 2 +-
+ configure | 2 +-
+ include/gpiod.h | 10 ++++++++--
+ lib/core.c | 13 +++++++------
+ lib/ctxless.c | 8 +++++---
+ lib/helpers.c | 3 ++-
+ tests/tests-ctxless.c | 2 +-
+ tools/gpioset.c | 13 +++++++++----
+ 8 files changed, 34 insertions(+), 19 deletions(-)
+
+diff --git a/aclocal.m4 b/aclocal.m4
+index b0db596..a5e28ad 100644
+--- a/aclocal.m4
++++ b/aclocal.m4
+@@ -911,7 +911,7 @@ AS_VAR_IF([$1], [""], [$5], [$4])dnl
+ # generated from the m4 files accompanying Automake X.Y.
+ # (This private macro should not be called outside this file.)
+ AC_DEFUN([AM_AUTOMAKE_VERSION],
+-[am__api_version='1.15'
++[am__api_version='1.16'
+ dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+ dnl require some minimum version. Point them to the right macro.
+ m4_if([$1], [1.15], [],
+diff --git a/configure b/configure
+index f5a0a23..c0cdbf1 100755
+--- a/configure
++++ b/configure
+@@ -2484,7 +2484,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+
+-am__api_version='1.15'
++am__api_version='1.16'
+
+ # Find a good install program. We prefer a C program (faster),
+ # so one script is as good as another. But avoid the broken or
+diff --git a/include/gpiod.h b/include/gpiod.h
+index 2679478..7b5c186 100644
+--- a/include/gpiod.h
++++ b/include/gpiod.h
+@@ -121,6 +121,7 @@ typedef void (*gpiod_ctxless_set_value_cb)(void *);
+ * @param offset The offset of the GPIO line.
+ * @param value New value (0 or 1).
+ * @param active_low The active state of this line - true if low.
++ * @param pass_through The pass-through state of the lines - true if enabled.
+ * @param consumer Name of the consumer.
+ * @param cb Optional callback function that will be called right after setting
+ * the value. Users can use this, for example, to pause the execution
+@@ -129,7 +130,7 @@ typedef void (*gpiod_ctxless_set_value_cb)(void *);
+ * @return 0 if the operation succeeds, -1 on error.
+ */
+ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+- bool active_low, const char *consumer,
++ bool active_low, bool pass_through, const char *consumer,
+ gpiod_ctxless_set_value_cb cb,
+ void *data) GPIOD_API;
+
+@@ -140,6 +141,7 @@ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+ * @param values Array of integers containing new values.
+ * @param num_lines Number of lines, must be > 0.
+ * @param active_low The active state of the lines - true if low.
++ * @param pass_through The pass-through state of the lines - true if enabled.
+ * @param consumer Name of the consumer.
+ * @param cb Optional callback function that will be called right after setting
+ * all values. Works the same as in ::gpiod_ctxless_set_value.
+@@ -149,7 +151,7 @@ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+ int gpiod_ctxless_set_value_multiple(const char *device,
+ const unsigned int *offsets,
+ const int *values, unsigned int num_lines,
+- bool active_low, const char *consumer,
++ bool active_low, bool pass_through, const char *consumer,
+ gpiod_ctxless_set_value_cb cb,
+ void *data) GPIOD_API;
+
+@@ -766,6 +768,8 @@ enum {
+ /**< Request the line(s) for reading the GPIO line state. */
+ GPIOD_LINE_REQUEST_DIRECTION_OUTPUT,
+ /**< Request the line(s) for setting the GPIO line state. */
++ GPIOD_LINE_REQUEST_DIRECTION_PASS_THROUGH,
++ /**< Request the line(s) for setting the GPIO line state. */
+ GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE,
+ /**< Monitor both types of events. */
+ GPIOD_LINE_REQUEST_EVENT_RISING_EDGE,
+@@ -784,6 +788,8 @@ enum {
+ /**< The line is an open-source port. */
+ GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW = GPIOD_BIT(2),
+ /**< The active state of the line is low (high is the default). */
++ GPIOD_LINE_REQUEST_FLAG_PASS_THROUGH = GPIOD_BIT(5),
++ /**< The line is a pass-through port*/
+ };
+
+ /**
+diff --git a/lib/core.c b/lib/core.c
+index 05e5a46..635569c 100644
+--- a/lib/core.c
++++ b/lib/core.c
+@@ -470,7 +470,6 @@ static int line_request_values(struct gpiod_line_bulk *bulk,
+ struct gpiohandle_request req;
+ unsigned int i;
+ int rv, fd;
+-
+ if ((config->request_type != GPIOD_LINE_REQUEST_DIRECTION_OUTPUT) &&
+ (config->flags & (GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN |
+ GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE))) {
+@@ -497,14 +496,15 @@ static int line_request_values(struct gpiod_line_bulk *bulk,
+ req.flags |= GPIOHANDLE_REQUEST_INPUT;
+ else if (config->request_type == GPIOD_LINE_REQUEST_DIRECTION_OUTPUT)
+ req.flags |= GPIOHANDLE_REQUEST_OUTPUT;
+-
++ else if (config->request_type == GPIOD_LINE_REQUEST_DIRECTION_PASS_THROUGH)
++ req.flags |= GPIOHANDLE_REQUEST_PASS_THROUGH;
+ req.lines = gpiod_line_bulk_num_lines(bulk);
+
+ gpiod_line_bulk_foreach_line_off(bulk, line, i) {
+ req.lineoffsets[i] = gpiod_line_offset(line);
+- if (config->request_type ==
+- GPIOD_LINE_REQUEST_DIRECTION_OUTPUT &&
+- default_vals)
++ if ((config->request_type == GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ||
++ config->request_type == GPIOD_LINE_REQUEST_DIRECTION_PASS_THROUGH)&&
++ default_vals)
+ req.default_values[i] = !!default_vals[i];
+ }
+
+@@ -615,7 +615,8 @@ static bool line_request_is_direction(int request)
+ {
+ return request == GPIOD_LINE_REQUEST_DIRECTION_AS_IS ||
+ request == GPIOD_LINE_REQUEST_DIRECTION_INPUT ||
+- request == GPIOD_LINE_REQUEST_DIRECTION_OUTPUT;
++ request == GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ||
++ request == GPIOD_LINE_REQUEST_DIRECTION_PASS_THROUGH;
+ }
+
+ static bool line_request_is_events(int request)
+diff --git a/lib/ctxless.c b/lib/ctxless.c
+index ba85018..88b0388 100644
+--- a/lib/ctxless.c
++++ b/lib/ctxless.c
+@@ -76,17 +76,17 @@ int gpiod_ctxless_get_value_multiple(const char *device,
+ }
+
+ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,
+- bool active_low, const char *consumer,
++ bool active_low, bool pass_through, const char *consumer,
+ gpiod_ctxless_set_value_cb cb, void *data)
+ {
+ return gpiod_ctxless_set_value_multiple(device, &offset, &value, 1,
+- active_low, consumer, cb, data);
++ active_low, pass_through, consumer, cb, data);
+ }
+
+ int gpiod_ctxless_set_value_multiple(const char *device,
+ const unsigned int *offsets,
+ const int *values, unsigned int num_lines,
+- bool active_low, const char *consumer,
++ bool active_low, bool pass_through, const char *consumer,
+ gpiod_ctxless_set_value_cb cb, void *data)
+ {
+ struct gpiod_line_bulk bulk;
+@@ -118,6 +118,8 @@ int gpiod_ctxless_set_value_multiple(const char *device,
+
+ flags = active_low ? GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW : 0;
+
++ flags |= pass_through ? GPIOD_LINE_REQUEST_FLAG_PASS_THROUGH : 0;
++
+ rv = gpiod_line_request_bulk_output_flags(&bulk, consumer,
+ flags, values);
+ if (rv < 0) {
+diff --git a/lib/helpers.c b/lib/helpers.c
+index 479f370..7b2884f 100644
+--- a/lib/helpers.c
++++ b/lib/helpers.c
+@@ -360,7 +360,8 @@ int gpiod_line_request_bulk_output_flags(struct gpiod_line_bulk *bulk,
+ .request_type = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT,
+ .flags = flags,
+ };
+-
++ if (flags & GPIOD_LINE_REQUEST_FLAG_PASS_THROUGH)
++ config.request_type = GPIOD_LINE_REQUEST_DIRECTION_PASS_THROUGH;
+ return gpiod_line_request_bulk(bulk, &config, default_vals);
+ }
+
+diff --git a/tests/tests-ctxless.c b/tests/tests-ctxless.c
+index 638274f..b215f9c 100644
+--- a/tests/tests-ctxless.c
++++ b/tests/tests-ctxless.c
+@@ -20,7 +20,7 @@ static void ctxless_set_get_value(void)
+ TEST_ASSERT_EQ(rv, 0);
+
+ rv = gpiod_ctxless_set_value(test_chip_name(0), 3, 1,
+- false, TEST_CONSUMER, NULL, NULL);
++ false, false, TEST_CONSUMER, NULL, NULL);
+ TEST_ASSERT_RET_OK(rv);
+
+ rv = gpiod_ctxless_get_value(test_chip_name(0), 3,
+diff --git a/tools/gpioset.c b/tools/gpioset.c
+index d9977a7..094d609 100644
+--- a/tools/gpioset.c
++++ b/tools/gpioset.c
+@@ -22,7 +22,8 @@
+ static const struct option longopts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+- { "active-low", no_argument, NULL, 'l' },
++ { "active-low", no_argument, NULL, 'l' },
++ { "pass-through", no_argument, NULL, 'p' },
+ { "mode", required_argument, NULL, 'm' },
+ { "sec", required_argument, NULL, 's' },
+ { "usec", required_argument, NULL, 'u' },
+@@ -30,7 +31,7 @@ static const struct option longopts[] = {
+ { GETOPT_NULL_LONGOPT },
+ };
+
+-static const char *const shortopts = "+hvlm:s:u:b";
++static const char *const shortopts = "+hvlpm:s:u:b";
+
+ static void print_help(void)
+ {
+@@ -40,8 +41,9 @@ static void print_help(void)
+ printf("\n");
+ printf("Options:\n");
+ printf(" -h, --help:\t\tdisplay this message and exit\n");
+- printf(" -v, --version:\tdisplay the version and exit\n");
+ printf(" -l, --active-low:\tset the line active state to low\n");
++ printf(" -v, --version:\tdisplay the version and exit\n");
++ printf(" -p, --pass-through:\tset it to pass through mode\n");
+ printf(" -m, --mode=[exit|wait|time|signal] (defaults to 'exit'):\n");
+ printf(" tell the program what to do after setting values\n");
+ printf(" -s, --sec=SEC:\tspecify the number of seconds to wait (only valid for --mode=time)\n");
+@@ -185,6 +187,7 @@ int main(int argc, char **argv)
+ int *values, rv, optc, opti;
+ struct callback_data cbdata;
+ bool active_low = false;
++ bool pass_through = false;
+ char *device, *end;
+
+ memset(&cbdata, 0, sizeof(cbdata));
+@@ -203,6 +206,8 @@ int main(int argc, char **argv)
+ return EXIT_SUCCESS;
+ case 'l':
+ active_low = true;
++ case 'p':
++ pass_through = true;
+ break;
+ case 'm':
+ mode = parse_mode(optarg);
+@@ -269,7 +274,7 @@ int main(int argc, char **argv)
+ }
+
+ rv = gpiod_ctxless_set_value_multiple(device, offsets, values,
+- num_lines, active_low, "gpioset",
++ num_lines, active_low, pass_through, "gpioset",
+ mode->callback, &cbdata);
+ if (rv < 0)
+ die_perror("error setting the GPIO line values");
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod_%.bbappend b/meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod_%.bbappend
new file mode 100644
index 000000000..5c3c24ec5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-support/libgpiod/libgpiod_%.bbappend
@@ -0,0 +1,7 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+PACKAGECONFIG += " cxx"
+
+SRC_URI += " \
+ file://0001-Add-pass-through-setting-in-gpioset.patch \
+ "
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..619570dbb
--- /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-purley.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..a5ffabd88
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/io-app/files/io-app.c
@@ -0,0 +1,665 @@
+/*
+// 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_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;
+ }
+ else if (strncmp("ASpeed SoC", v, 11) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "Found ASpeed SoC\n");
+ this_cpu = CPU_AST2500;
+ }
+ else if (strncmp("ServerEngines PILOT3", v, 21) == 0)
+ {
+ if (!quiet)
+ fprintf(stderr, "Found PILOT3\n");
+ this_cpu = CPU_PILOT3;
+ }
+ }
+ 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";
+ 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..467231372
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_cmds.c
@@ -0,0 +1,501 @@
+/*
+// 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);
+}
+
+/*********************************************************************************/
+
+#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"
+ "\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(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..56c79d1c1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-utilities/lpc-cmds/files/lpc_drv.h
@@ -0,0 +1,78 @@
+/*
+// 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_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..2fbb1eb2f
--- /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://${PHOSPHORBASE}/LICENSE;md5=19407077e42b1ba3d653da313f1f5b4e"
+
+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/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-wht/conf/bblayers.conf.sample b/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
new file mode 100644
index 000000000..09c2bbc4a
--- /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 = "10"
+
+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..558487db6
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/conf-notes.txt
@@ -0,0 +1,5 @@
+Common targets are:
+ intel-platforms
+ obmc-phosphor-image
+ 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..99d7ee689
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/layer.conf
@@ -0,0 +1,14 @@
+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 += "wht"
+BBFILE_PATTERN_wht = ""
+BBFILE_PRIORITY_wht = "7"
+LAYERSERIES_COMPAT_wht = "warrior"
+
+PRODUCT_GENERATION_pn-os-release = "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..31b18a76e
--- /dev/null
+++ b/meta-openbmc-mods/meta-wht/conf/local.conf.sample
@@ -0,0 +1,20 @@
+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 = "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 = "3"
+#BB_NUMBER_THREADS = "70"
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..f3a4bc513
--- /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 = "10"
+
+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..558487db6
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/conf-notes.txt
@@ -0,0 +1,5 @@
+Common targets are:
+ intel-platforms
+ obmc-phosphor-image
+ 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..711850f6d
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/layer.conf
@@ -0,0 +1,14 @@
+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 += "wolfpass"
+BBFILE_PATTERN_wolfpass = ""
+BBFILE_PRIORITY_wolfpass = "7"
+LAYERSERIES_COMPAT_wolfpass = "warrior"
+
+PRODUCT_GENERATION_pn-os-release = "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..31b18a76e
--- /dev/null
+++ b/meta-openbmc-mods/meta-wolfpass/conf/local.conf.sample
@@ -0,0 +1,20 @@
+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 = "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 = "3"
+#BB_NUMBER_THREADS = "70"
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