summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2020-02-28 02:57:13 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2020-03-02 22:06:57 +0300
commit6c1caca70063aa707ba809a6b4695d0f0c5646f1 (patch)
tree84da2f29a60cb571686d3a4fb93f9d1f1189d989 /meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed
parent9600a7403ba2848c8751280077503a3e0f2f3481 (diff)
downloadopenbmc-6c1caca70063aa707ba809a6b4695d0f0c5646f1.tar.xz
Update to internal 2020-02-27
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch36
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch403
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch94
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch635
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch457
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch8
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0074-media-aspeed-refine-HSYNC-VSYNC-polarity-setting-log.patch93
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-media-aspeed-clear-garbage-interrupts.patch74
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0082-ARM-dts-aspeed-g6-add-USB-virtual-hub-fixup.patch53
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0083-usb-gadget-aspeed-add-ast2600-compatible-string.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch405
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch136
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch37
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch (renamed from meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Report-link-statistics-for-the-NCSI-channel.patch)25
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch40
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg2
21 files changed, 1587 insertions, 1045 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
index baf9dba9a..31061624c 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch
@@ -1,4 +1,4 @@
-From 89dec433cd2fcfcb8690b315bb4e787d53de2296 Mon Sep 17 00:00:00 2001
+From da2fecd5d5b3f69bcc4d07fd1265415bd350e5a6 Mon Sep 17 00:00:00 2001
From: Yuan Li <yuan.li@linux.intel.com>
Date: Tue, 19 Sep 2017 15:55:39 +0800
Subject: [PATCH] arm: dts: add DTS for Intel ast2500 platforms
@@ -14,17 +14,19 @@ Signed-off-by: Zhu, Yunge <yunge.zhu@linux.intel.com>
Signed-off-by: Qiang XU <qiang.xu@linux.intel.com>
Signed-off-by: Chen Yugang <yugang.chen@linux.intel.com>
Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
---
- arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 471 +++++++++++++++++++++++++
- 1 file changed, 471 insertions(+)
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 460 +++++++++++++++++++++++++
+ 1 file changed, 460 insertions(+)
create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
new file mode 100644
-index 0000000..6ded94d
+index 0000000..1fe6240
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts
-@@ -0,0 +1,470 @@
+@@ -0,0 +1,460 @@
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
@@ -114,7 +116,7 @@ index 0000000..6ded94d
+
+ beeper {
+ compatible = "pwm-beeper";
-+ pwms = <&timer 5 1000000 0>;
++ pwms = <&timer 6 1000000 0>;
+ };
+};
+
@@ -180,8 +182,8 @@ index 0000000..6ded94d
+ /*D0-D7*/ "","","","","","","","",
+ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","DEBUG_EN_N","","",
+ /*F0-F7*/ "NMI_OUT","","","","CPU_ERR0","CPU_ERR1","PLTRST_N","PRDY_N",
-+ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","","","FM_BMC_BOARD_SKU_ID5_N","","",
-+ /*H0-H7*/ "","","","","","","","",
++ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","LCP_ENTER_BUTTON","LCP_LEFT_BUTTON","FM_BMC_BOARD_SKU_ID5_N","","",
++ /*H0-H7*/ "","","","FM_NODE_ID_1","FM_NODE_ID_2","FM_NODE_ID_3","FM_NODE_ID_4","FM_240VA_STATUS",
+ /*I0-I7*/ "FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N","FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","",
+ /*J0-J7*/ "","","","","","","","",
+ /*K0-K7*/ "","","","","","","","",
@@ -191,7 +193,7 @@ index 0000000..6ded94d
+ /*O0-O7*/ "","","","","","","","",
+ /*P0-P7*/ "","","","","","","","",
+ /*Q0-Q7*/ "","","","","","","","PWR_DEBUG_N",
-+ /*R0-R7*/ "","XDP_PRST_N","","","","","","",
++ /*R0-R7*/ "","XDP_PRST_N","","","","","","CHASSIS_INTRUSION",
+ /*S0-S7*/ "REMOTE_DEBUG_ENABLE","SYSPWROK","RSMRST_N","","","","","",
+ /*T0-T7*/ "","","","","","","","",
+ /*U0-U7*/ "","","","","","","","",
@@ -224,8 +226,8 @@ index 0000000..6ded94d
+
+ /* SGPIO input lines */
+ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_ABCD_VRHOT","CPU1_MEM_EFGH_VRHOT","","",
-+ /*IB0-IB7*/ "","","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT",
-+ /*IC0-IC7*/ "","","","","","","","",
++ /*IB0-IB7*/ "CPU1_MISMATCH","CPU1_MEM_THERM_EVENT","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT",
++ /*IC0-IC7*/ "","","CPU2_MISMATCH","CPU2_MEM_THERM_EVENT","","","","",
+ /*ID0-ID7*/ "","","","","","","","",
+ /*IE0-IE7*/ "","","","","","","","",
+ /*IF0-IF7*/ "","","","","","","","",
@@ -365,11 +367,6 @@ index 0000000..6ded94d
+ aspeed,dma-buf-size = <4095>;
+ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
-+
-+ hsbp0@10 {
-+ compatible = "slave-mqueue";
-+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
-+ };
+};
+
+&i2c5 {
@@ -378,11 +375,6 @@ index 0000000..6ded94d
+ aspeed,dma-buf-size = <4095>;
+ aspeed,hw-timeout-ms = <300>;
+ status = "okay";
-+
-+ smlink0@10 {
-+ compatible = "slave-mqueue";
-+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
-+ };
+};
+
+&i2c6 {
@@ -480,9 +472,9 @@ index 0000000..6ded94d
+ * pinctrl-0 = <&pinctrl_timer5_default &pinctrl_timer6_default
+ * &pinctrl_timer7_default &pinctrl_timer8_default>;
+ */
-+ fttmr010,pwm-outputs = <5>;
++ fttmr010,pwm-outputs = <6>;
+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_timer5_default>;
++ pinctrl-0 = <&pinctrl_timer6_default>;
+ #pwm-cells = <3>;
+ status = "okay";
+};
@@ -495,6 +487,6 @@ index 0000000..6ded94d
+&vhub {
+ status = "okay";
+};
---
+--
2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch
index 34490822e..cc025e1f8 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch
@@ -1,4 +1,4 @@
-From 57363b496c6eb832b0c3407ee997fdee09f4007f Mon Sep 17 00:00:00 2001
+From 733ea1e7c0fd70ce372efcc8250bb2baebd74b68 Mon Sep 17 00:00:00 2001
From: Vernon Mauery <vernon.mauery@linux.intel.com>
Date: Tue, 19 Sep 2017 15:55:39 +0800
Subject: [PATCH] arm: dts: add DTS for Intel ast2600 platforms
@@ -8,17 +8,19 @@ Add the DTS file for Intel ast2600-based systems.
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
Signed-off-by: Chen Yugang <yugang.chen@linux.intel.com>
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: arun-pm <arun.p.m@linux.intel.com>
---
- arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 507 +++++++++++++++++++++++++
- 1 file changed, 507 insertions(+)
+ arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 497 +++++++++++++++++++++++++
+ 1 file changed, 497 insertions(+)
create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
new file mode 100644
-index 000000000000..1ad46e8bc69b
+index 000000000000..5bc76dd069af
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts
-@@ -0,0 +1,507 @@
+@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
@@ -76,8 +78,8 @@ index 000000000000..1ad46e8bc69b
+ compatible = "iio-hwmon";
+ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
+ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
-+ <&adc1 8>, <&adc1 9>, <&adc1 10>, <&adc1 11>,
-+ <&adc1 12>, <&adc1 13>, <&adc1 14>, <&adc1 15>;
++ <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>,
++ <&adc1 4>, <&adc1 5>, <&adc1 6>, <&adc1 7>;
+ };
+
+ leds {
@@ -112,14 +114,15 @@ index 000000000000..1ad46e8bc69b
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
-+ spi-max-frequency = <10000000>;
++ spi-max-frequency = <40000000>;
++ spi-tx-bus-width = <4>;
+ m25p,fast-read;
+#include "openbmc-flash-layout-intel-64MB.dtsi"
+ };
+};
+
+&espi {
-+ status = "disabled"; /* FIXME: Use H/W handshaking */
++ status = "okay";
+};
+
+&peci0 {
@@ -173,14 +176,14 @@ index 000000000000..1ad46e8bc69b
+ gpio-line-names =
+ /*A0-A7*/ "","","","","SMB_CPU_PIROM_SCL","SMB_CPU_PIROM_SDA","SMB_IPMB_STBY_LVC3_R_SCL","SMB_IPMB_STBY_LVC3_R_SDA",
+ /*B0-B7*/ "FM_1200VA_OC","NMI_OUT","IRQ_SMB3_M2_ALERT_N","","RGMII_BMC_RMM4_LVC3_R_MDC","RGMII_BMC_RMM4_LVC3_R_MDIO","FM_BMC_BMCINIT_R","FP_ID_LED_N",
-+ /*C0-C7*/ "FM_FORCE_BMC_UPDATE_N","RST_RGMII_PHYRST_N","FM_TPM_EN_PULSE","FM_BMC_CRASHLOG_TRIG_N","IRQ_BMC_PCH_NMI_R","FM_CPU1_DISABLE_COD_N","","",
++ /*C0-C7*/ "FM_FORCE_BMC_UPDATE_N","RST_RGMII_PHYRST_N","FM_TPM_EN_PULSE","FM_BMC_CRASHLOG_TRIG_N","IRQ_BMC_PCH_NMI_R","FM_CPU1_DISABLE_COD_N","FM_4S_8S_N_MODE","FM_STANDALONE_MODE_N",
+ /*D0-D7*/ "CPU_ERR0","CPU_ERR1","CPU_ERR2","PRDY_N","FM_SPD_SWITCH_CTRL_N","","","",
+ /*E0-E7*/ "FM_SKT1_FAULT_LED","FM_SKT0_FAULT_LED","CLK_50M_CKMNG_BMCB","FM_BMC_BOARD_REV_ID2_N","","","","",
+ /*F0-F7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","FM_BMC_BOARD_SKU_ID5_N","ID_BUTTON","PS_PWROK",
+ /*G0-G7*/ "FM_SMB_BMC_NVME_LVC3_ALERT_N","RST_BMC_I2C_M2_R_N","FP_LED_STATUS_GREEN_N","FP_LED_STATUS_AMBER_N","FM_BMC_BOARD_REV_ID0_N","FM_BMC_BOARD_REV_ID1_N","FM_BMC_CPU_FBRK_OUT_R_N","DBP_PRESENT_IN_R2_N",
+ /*H0-H7*/ "SGPIO_BMC_CLK_R","SGPIO_BMC_LD_R","SGPIO_BMC_DOUT_R","SGPIO_BMC_DIN","PLTRST_N","CPU_CATERR","PCH_BMC_THERMTRIP","",
+ /*I0-I7*/ "JTAG_ASD_NTRST_R_N","JTAG_ASD_TDI_R","JTAG_ASD_TCK_R","JTAG_ASD_TMS_R","JTAG_ASD_TDO","FM_BMC_PWRBTN_OUT_R_N","FM_BMC_PWR_BTN_N","",
-+ /*J0-J7*/ "SMB_CHASSENSOR_STBY_LVC3_SCL","SMB_CHASSENSOR_STBY_LVC3_SDA","","","","","","",
++ /*J0-J7*/ "SMB_CHASSENSOR_STBY_LVC3_SCL","SMB_CHASSENSOR_STBY_LVC3_SDA","FM_NODE_ID0","FM_NODE_ID1","","","","",
+ /*K0-K7*/ "SMB_HSBP_STBY_LVC3_R_SCL","SMB_HSBP_STBY_LVC3_R_SDA","SMB_SMLINK0_STBY_LVC3_R2_SCL","SMB_SMLINK0_STBY_LVC3_R2_SDA","SMB_TEMPSENSOR_STBY_LVC3_R_SCL","SMB_TEMPSENSOR_STBY_LVC3_R_SDA","SMB_PMBUS_SML1_STBY_LVC3_R_SCL","SMB_PMBUS_SML1_STBY_LVC3_R_SDA",
+ /*L0-L7*/ "SMB_PCIE_STBY_LVC3_R_SCL","SMB_PCIE_STBY_LVC3_R_SDA","SMB_HOST_STBY_BMC_LVC3_R_SCL","SMB_HOST_STBY_BMC_LVC3_R_SDA","PREQ_N","DEBUG_EN_N","V_BMC_GFX_HSYNC_R","V_BMC_GFX_VSYNC_R",
+ /*M0-M7*/ "SPA_CTS_N","SPA_DCD_N","SPA_DSR_N","PU_SPA_RI_N","SPA_DTR_N","SPA_RTS_N","SPA_SOUT","SPA_SIN",
@@ -385,11 +388,6 @@ index 000000000000..1ad46e8bc69b
+ /* SMB_HSBP_STBY_LVC3_R */
+ multi-master;
+ status = "okay";
-+
-+ hsbp0@10 {
-+ compatible = "slave-mqueue";
-+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
-+ };
+};
+
+&i2c5 {
@@ -397,11 +395,6 @@ index 000000000000..1ad46e8bc69b
+ bus-frequency = <1000000>;
+ multi-master;
+ status = "okay";
-+
-+ smlink0@10 {
-+ compatible = "slave-mqueue";
-+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
-+ };
+};
+
+&i2c6 {
@@ -414,7 +407,6 @@ index 000000000000..1ad46e8bc69b
+ /* SMB_PMBUS_SML1_STBY_LVC3_R */
+ multi-master;
+ #retries = <3>;
-+
+ status = "okay";
+};
+
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
index d66e84beb..b4b1bcad8 100644
--- 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
@@ -1,4 +1,4 @@
-From c111aac36e2f4fa1149662c85883407315ba76a6 Mon Sep 17 00:00:00 2001
+From 39f76bd49fd481999cf51fbdfbea3e820efc7227 Mon Sep 17 00:00:00 2001
From: Yong Li <yong.b.li@intel.com>
Date: Mon, 13 Nov 2017 16:29:44 +0800
Subject: [PATCH] Aspeed LPC SIO driver
@@ -13,9 +13,9 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
arch/arm/boot/dts/aspeed-g5.dtsi | 7 +
drivers/soc/aspeed/Kconfig | 7 +
drivers/soc/aspeed/Makefile | 1 +
- drivers/soc/aspeed/aspeed-lpc-sio.c | 450 +++++++++++++++++++++
- include/uapi/linux/aspeed-lpc-sio.h | 44 ++
- 7 files changed, 533 insertions(+)
+ drivers/soc/aspeed/aspeed-lpc-sio.c | 410 +++++++++++++++++++++
+ include/uapi/linux/aspeed-lpc-sio.h | 45 +++
+ 7 files changed, 494 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt
create mode 100644 drivers/soc/aspeed/aspeed-lpc-sio.c
create mode 100644 include/uapi/linux/aspeed-lpc-sio.h
@@ -110,14 +110,15 @@ index f3ff29b874ed..2e547cc47e62 100644
obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o
diff --git a/drivers/soc/aspeed/aspeed-lpc-sio.c b/drivers/soc/aspeed/aspeed-lpc-sio.c
new file mode 100644
-index 000000000000..c717a3182320
+index 000000000000..d4a4da112ff4
--- /dev/null
+++ b/drivers/soc/aspeed/aspeed-lpc-sio.c
-@@ -0,0 +1,450 @@
+@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2012-2017 ASPEED Technology Inc.
-+// Copyright (c) 2017-2019 Intel Corporation
++// Copyright (c) 2017-2020 Intel Corporation
+
++#include <linux/aspeed-lpc-sio.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/miscdevice.h>
@@ -128,62 +129,67 @@ index 000000000000..c717a3182320
+#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
++#define SOC_NAME "aspeed"
++#define DEVICE_NAME "lpc-sio"
++
++#define AST_LPC_SWCR0300 0x00
++#define LPC_PWRGD_STS BIT(30)
++#define LPC_PWRGD_RISING_EVT_STS BIT(29)
++#define LPC_PWRGD_FALLING_EVT_STS BIT(28)
++#define LPC_PWRBTN_STS BIT(27)
++#define LPC_PWRBTN_RISING_EVT_STS BIT(26)
++#define LPC_PWRBTN_FALLING_EVT_STS BIT(25)
++#define LPC_S5N_STS BIT(21)
++#define LPC_S5N_RISING_EVT_STS BIT(20)
++#define LPC_S5N_FALLING_EVT_STS BIT(19)
++#define LPC_S3N_STS BIT(18)
++#define LPC_S3N_RISING_EVT_STS BIT(17)
++#define LPC_S3N_FALLING_EVT_STS BIT(16)
++#define LPC_PWBTO_RAW_STS BIT(15)
++#define LPC_LAST_ONCTL_STS BIT(14)
++#define LPC_WAS_PFAIL_STS BIT(13)
++#define LPC_POWER_UP_FAIL_STS BIT(12) /* Crowbar */
++#define LPC_PWRBTN_OVERRIDE_STS BIT(11)
++#define LPC_BMC_TRIG_WAKEUP_EVT_STS BIT(8)
++
++#define AST_LPC_SWCR0704 0x04
++#define LPC_BMC_TRIG_WAKEUP_EVT_EN BIT(8)
++
++#define AST_LPC_SWCR0B08 0x08
++#define LPC_PWREQ_OUTPUT_LEVEL BIT(25)
++#define LPC_PWBTO_OUTPUT_LEVEL BIT(24)
++#define LPC_ONCTL_STS BIT(15)
++#define LPC_ONCTL_GPIO_LEVEL BIT(14)
++#define LPC_ONCTL_EN_GPIO_OUTPUT BIT(13)
++#define LPC_ONCTL_EN_GPIO_MODE BIT(12)
++#define LPC_BMC_TRIG_WAKEUP_EVT BIT(6)
++
++#define AST_LPC_SWCR0F0C 0x0C
++#define AST_LPC_SWCR1310 0x10
++#define AST_LPC_SWCR1714 0x14
++#define AST_LPC_SWCR1B18 0x18
++#define AST_LPC_SWCR1F1C 0x1C
++#define AST_LPC_ACPIE3E0 0x20
++#define AST_LPC_ACPIC1C0 0x24
++
++#define AST_LPC_ACPIB3B0 0x28
++#define LPC_BMC_TRIG_SCI_EVT_STS BIT(8)
++
++#define AST_LPC_ACPIB7B4 0x2C
++#define LPC_BMC_TRIG_SCI_EVT_EN BIT(8)
+
+struct aspeed_lpc_sio {
-+ struct miscdevice miscdev;
-+ struct regmap *regmap;
-+ struct clk *clk;
-+ struct semaphore lock;
-+ unsigned int reg_base;
++ 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);
++ miscdev);
+}
+
+static int aspeed_lpc_sio_open(struct inode *inode, struct file *filp)
@@ -196,7 +202,8 @@ index 000000000000..c717a3182320
+ LPC_S5N_FALLING_EVT_STS | \
+ LPC_S3N_RISING_EVT_STS | \
+ LPC_S3N_FALLING_EVT_STS)
-+/*************************************
++
++/*
+ * SLPS3n SLPS5n State
+ * ---------------------------------
+ * 1 1 S12
@@ -205,33 +212,20 @@ index 000000000000..c717a3182320
+ *************************************
+ */
+
-+static long sio_get_acpi_state(struct aspeed_lpc_sio *lpc_sio,
-+ struct sio_ioctl_data *sio_data)
++static void sio_get_acpi_state(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ /* update the ACPI state event status */
+ if (sio_data->param != 0) {
+ if (val & LPC_SLP3N5N_EVENT_STATUS) {
+ sio_data->param = 1;
-+ 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;
-+ }
++ regmap_write(lpc_sio->regmap, reg,
++ LPC_SLP3N5N_EVENT_STATUS);
+ } else {
+ sio_data->param = 0;
+ }
@@ -243,85 +237,52 @@ index 000000000000..c717a3182320
+ 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)
++static void sio_get_pwrgd_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ /* update the PWRGD event status */
+ if (sio_data->param != 0) {
+ if (val & LPC_PWRGD_EVENT_STATUS) {
+ sio_data->param = 1;
-+ 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;
-+ }
++ regmap_write(lpc_sio->regmap, reg,
++ LPC_PWRGD_EVENT_STATUS);
+ } else {
+ sio_data->param = 0;
+ }
+ }
+
+ sio_data->data = (val & LPC_PWRGD_STS) != 0 ? 1 : 0;
-+
-+ return 0;
+}
+
-+static long sio_get_onctl_status(struct aspeed_lpc_sio *lpc_sio,
-+ struct sio_ioctl_data *sio_data)
++static void sio_get_onctl_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ 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)
++static void sio_set_onctl_gpio(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ /* Enable ONCTL GPIO mode */
+ if (sio_data->param != 0) {
@@ -333,112 +294,103 @@ index 000000000000..c717a3182320
+ 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;
-+ }
++ regmap_write(lpc_sio->regmap, reg, val);
+ } 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;
-+ }
++ regmap_write(lpc_sio->regmap, reg, val);
+ }
-+
-+ return 0;
+}
+
-+static long sio_get_pwrbtn_override(struct aspeed_lpc_sio *lpc_sio,
-+ struct sio_ioctl_data *sio_data)
++static void sio_get_pwrbtn_override(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ /* 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;
-+ }
-+ }
-+ }
++ if (sio_data->param != 0 && val & LPC_PWRBTN_OVERRIDE_STS)
++ regmap_write(lpc_sio->regmap, reg, LPC_PWRBTN_OVERRIDE_STS);
+
+ sio_data->data = (val & LPC_PWRBTN_OVERRIDE_STS) != 0 ? 1 : 0;
-+
-+ return 0;
+}
+
-+static long sio_get_pfail_status(struct aspeed_lpc_sio *lpc_sio,
-+ struct sio_ioctl_data *sio_data)
++static void sio_get_pfail_status(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
+{
-+ u32 reg;
-+ u32 val;
-+ int rc;
++ u32 reg, val;
+
+ 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;
-+ }
++ regmap_read(lpc_sio->regmap, reg, &val);
+
+ /* [ASPEED]: SWCR_03_00[13] (Was_pfail: default 1) is used to identify
+ * this current booting is from AC loss (not DC loss) if FW cleans this
+ * bit after booting successfully every time.
+ **********************************************************************/
+ if (val & LPC_WAS_PFAIL_STS) {
-+ 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;
-+ }
++ regmap_write(lpc_sio->regmap, reg, 0); /* W0C */
+ sio_data->data = 1;
+ } else {
+ sio_data->data = 0;
+ }
++}
+
-+ return 0;
++static void sio_set_bmc_sci_event(struct aspeed_lpc_sio *lpc_sio,
++ struct sio_ioctl_data *sio_data)
++{
++ u32 reg;
++
++ if (sio_data->param) {
++ reg = lpc_sio->reg_base + AST_LPC_ACPIB7B4;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_SCI_EVT_EN,
++ LPC_BMC_TRIG_SCI_EVT_EN);
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0704;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT_EN,
++ LPC_BMC_TRIG_WAKEUP_EVT_EN);
++
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT,
++ LPC_BMC_TRIG_WAKEUP_EVT);
++ } else {
++ reg = lpc_sio->reg_base + AST_LPC_SWCR0300;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_WAKEUP_EVT_STS,
++ LPC_BMC_TRIG_WAKEUP_EVT_STS);
++
++ reg = lpc_sio->reg_base + AST_LPC_ACPIB3B0;
++ regmap_write_bits(lpc_sio->regmap, reg,
++ LPC_BMC_TRIG_SCI_EVT_STS,
++ LPC_BMC_TRIG_SCI_EVT_STS);
++ }
++
++ sio_data->data = sio_data->param;
+}
+
-+typedef long (*sio_cmd_fn) (struct aspeed_lpc_sio *sio_dev,
-+ struct sio_ioctl_data *sio_data);
++typedef void (*sio_cmd_fn) (struct aspeed_lpc_sio *sio_dev,
++ struct sio_ioctl_data *sio_data);
++
+static sio_cmd_fn sio_cmd_handle[SIO_MAX_CMD] = {
-+ [SIO_GET_ACPI_STATE] = sio_get_acpi_state,
-+ [SIO_GET_PWRGD_STATUS] = sio_get_pwrgd_status,
-+ [SIO_GET_ONCTL_STATUS] = sio_get_onctl_status,
-+ [SIO_SET_ONCTL_GPIO] = sio_set_onctl_gpio,
-+ [SIO_GET_PWRBTN_OVERRIDE] = sio_get_pwrbtn_override,
-+ [SIO_GET_PFAIL_STATUS] = sio_get_pfail_status,
++ [SIO_GET_ACPI_STATE] = sio_get_acpi_state,
++ [SIO_GET_PWRGD_STATUS] = sio_get_pwrgd_status,
++ [SIO_GET_ONCTL_STATUS] = sio_get_onctl_status,
++ [SIO_SET_ONCTL_GPIO] = sio_set_onctl_gpio,
++ [SIO_GET_PWRBTN_OVERRIDE] = sio_get_pwrbtn_override,
++ [SIO_GET_PFAIL_STATUS] = sio_get_pfail_status,
++ [SIO_SET_BMC_SCI_EVENT] = sio_set_bmc_sci_event,
+};
+
+static long aspeed_lpc_sio_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long param)
++ 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;
-+
++ sio_cmd_fn cmd_fn;
++ long ret;
+
+ if (copy_from_user(&sio_data, (void __user *)param, sizeof(sio_data)))
+ return -EFAULT;
@@ -447,18 +399,14 @@ index 000000000000..c717a3182320
+ return -EINVAL;
+
+ cmd_fn = sio_cmd_handle[sio_data.sio_cmd];
-+ if (cmd_fn == NULL)
++ if (!cmd_fn)
+ 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;
-+ }
++ cmd_fn(lpc_sio, &sio_data);
++ ret = copy_to_user((void __user *)param, &sio_data, sizeof(sio_data));
+
+ up(&lpc_sio->lock);
+
@@ -475,7 +423,8 @@ index 000000000000..c717a3182320
+{
+ struct aspeed_lpc_sio *lpc_sio;
+ struct device *dev;
-+ int rc;
++ u32 val;
++ int ret;
+
+ dev = &pdev->dev;
+
@@ -485,40 +434,51 @@ index 000000000000..c717a3182320
+
+ dev_set_drvdata(&pdev->dev, lpc_sio);
+
-+ rc = of_property_read_u32(dev->of_node, "reg", &lpc_sio->reg_base);
-+ if (rc) {
++ ret = of_property_read_u32(dev->of_node, "reg", &lpc_sio->reg_base);
++ if (ret) {
+ dev_err(dev, "Couldn't read reg device-tree property\n");
-+ return rc;
++ return ret;
+ }
+
-+ lpc_sio->regmap = syscon_node_to_regmap(
-+ pdev->dev.parent->of_node);
++ lpc_sio->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node);
+ if (IS_ERR(lpc_sio->regmap)) {
+ dev_err(dev, "Couldn't get regmap\n");
+ return -ENODEV;
+ }
+
++ /*
++ * We check that the regmap works on this very first access,
++ * but as this is an MMIO-backed regmap, subsequent regmap
++ * access is not going to fail and we skip error checks from
++ * this point.
++ */
++ ret = regmap_read(lpc_sio->regmap, AST_LPC_SWCR0300, &val);
++ if (ret) {
++ dev_err(dev, "failed to read regmap\n");
++ return ret;
++ }
++
+ sema_init(&lpc_sio->lock, 1);
+
+ lpc_sio->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(lpc_sio->clk)) {
-+ rc = PTR_ERR(lpc_sio->clk);
-+ if (rc != -EPROBE_DEFER)
++ ret = PTR_ERR(lpc_sio->clk);
++ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "couldn't get clock\n");
-+ return rc;
++ return ret;
+ }
-+ rc = clk_prepare_enable(lpc_sio->clk);
-+ if (rc) {
++ ret = clk_prepare_enable(lpc_sio->clk);
++ if (ret) {
+ dev_err(dev, "couldn't enable clock\n");
-+ return rc;
++ return ret;
+ }
+
+ lpc_sio->miscdev.minor = MISC_DYNAMIC_MINOR;
+ lpc_sio->miscdev.name = DEVICE_NAME;
+ lpc_sio->miscdev.fops = &aspeed_lpc_sio_fops;
+ lpc_sio->miscdev.parent = dev;
-+ rc = misc_register(&lpc_sio->miscdev);
-+ if (rc) {
++ ret = misc_register(&lpc_sio->miscdev);
++ if (ret) {
+ dev_err(dev, "Unable to register device\n");
+ goto err;
+ }
@@ -531,7 +491,7 @@ index 000000000000..c717a3182320
+err:
+ clk_disable_unprepare(lpc_sio->clk);
+
-+ return rc;
++ return ret;
+}
+
+static int aspeed_lpc_sio_remove(struct platform_device *pdev)
@@ -551,25 +511,25 @@ index 000000000000..c717a3182320
+MODULE_DEVICE_TABLE(of, aspeed_lpc_sio_match);
+
+static struct platform_driver aspeed_lpc_sio_driver = {
-+ .driver = {
++ .driver = {
+ .name = SOC_NAME "-" DEVICE_NAME,
-+ .of_match_table = aspeed_lpc_sio_match,
++ .of_match_table = of_match_ptr(aspeed_lpc_sio_match),
+ },
-+ .probe = aspeed_lpc_sio_probe,
-+ .remove = aspeed_lpc_sio_remove,
++ .probe = aspeed_lpc_sio_probe,
++ .remove = aspeed_lpc_sio_remove,
+};
+module_platform_driver(aspeed_lpc_sio_driver);
+
-+MODULE_LICENSE("GPL");
++MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
+MODULE_AUTHOR("Yong Li <yong.blli@linux.intel.com>");
+MODULE_DESCRIPTION("ASPEED AST LPC SIO device driver");
diff --git a/include/uapi/linux/aspeed-lpc-sio.h b/include/uapi/linux/aspeed-lpc-sio.h
new file mode 100644
-index 000000000000..5dc1efd4a426
+index 000000000000..acf89a7d2b4a
--- /dev/null
+++ b/include/uapi/linux/aspeed-lpc-sio.h
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012-2020 ASPEED Technology Inc.
+ * Copyright (c) 2017 Intel Corporation
@@ -600,6 +560,7 @@ index 000000000000..5dc1efd4a426
+ SIO_SET_ONCTL_GPIO,
+ SIO_GET_PWRBTN_OVERRIDE,
+ SIO_GET_PFAIL_STATUS, /* Start from AC Loss */
++ SIO_SET_BMC_SCI_EVENT,
+
+ SIO_MAX_CMD
+};
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
index 490104cda..64059b1da 100644
--- 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
@@ -1,4 +1,4 @@
-From 1d0c60f1aa8b7b25d8d0d6f6f6443d307d543600 Mon Sep 17 00:00:00 2001
+From 34308f4078361987adfb854bdc6876abdaf323cb Mon Sep 17 00:00:00 2001
From: Haiyue Wang <haiyue.wang@linux.intel.com>
Date: Sat, 24 Feb 2018 11:12:32 +0800
Subject: [PATCH] Add AST2500 eSPI driver
@@ -26,11 +26,12 @@ Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
.../devicetree/bindings/misc/aspeed,espi-slave.txt | 20 +
Documentation/misc-devices/espi-slave.rst | 118 ++++++
arch/arm/boot/dts/aspeed-g5.dtsi | 4 +
- arch/arm/boot/dts/aspeed-g6.dtsi | 12 +
+ arch/arm/boot/dts/aspeed-g6.dtsi | 14 +
drivers/misc/Kconfig | 8 +
drivers/misc/Makefile | 1 +
- drivers/misc/aspeed-espi-slave.c | 421 +++++++++++++++++++++
- 7 files changed, 584 insertions(+)
+ drivers/misc/aspeed-espi-slave.c | 468 +++++++++++++++++++++
+ include/dt-bindings/clock/ast2600-clock.h | 1 +
+ 8 files changed, 634 insertions(+)
create mode 100644 Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt
create mode 100644 Documentation/misc-devices/espi-slave.rst
create mode 100644 drivers/misc/aspeed-espi-slave.c
@@ -208,7 +209,7 @@ index c15be82c3a9d..bd2037e52a94 100644
lpc: lpc@1e789000 {
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
-index 459070693aba..e4c1ab3d274e 100644
+index 62d101dc6926..753770912f0a 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -3,6 +3,7 @@
@@ -219,7 +220,7 @@ index 459070693aba..e4c1ab3d274e 100644
/ {
model = "Aspeed BMC";
-@@ -651,6 +652,17 @@
+@@ -674,6 +675,19 @@
status = "disabled";
};
@@ -230,8 +231,10 @@ index 459070693aba..e4c1ab3d274e 100644
+ <&gpio0 ASPEED_GPIO(W, 7) IRQ_TYPE_EDGE_FALLING>;
+ status = "disabled";
+ clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>;
++ resets = <&syscon ASPEED_RESET_ESPI>;
+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_espi_default>;
++ pinctrl-0 = <&pinctrl_espi_default>,
++ <&pinctrl_espialt_default>;
+ };
+
i2c: bus@1e78a000 {
@@ -270,10 +273,10 @@ index b9e6d4c3e906..53864687e8fd 100644
obj-y += cardreader/
diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c
new file mode 100644
-index 000000000000..d70332d1fef3
+index 000000000000..87bc81948694
--- /dev/null
+++ b/drivers/misc/aspeed-espi-slave.c
-@@ -0,0 +1,421 @@
+@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2015-2019, Intel Corporation.
+
@@ -286,6 +289,7 @@ index 000000000000..d70332d1fef3
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
++#include <linux/reset.h>
+#include <linux/sched/signal.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
@@ -361,7 +365,9 @@ index 000000000000..d70332d1fef3
+ struct regmap *map;
+ struct clk *clk;
+ struct device *dev;
++ struct reset_control *reset;
+ int irq;
++ int rst_irq;
+
+ /* for PLTRST_N signal monitoring interface */
+ struct miscdevice pltrstn_miscdev;
@@ -469,11 +475,17 @@ index 000000000000..d70332d1fef3
+ }
+
+ if (sts & ASPEED_ESPI_HW_RESET) {
++ if (priv->rst_irq < 0) {
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET,
++ ASPEED_ESPI_CTRL_SW_RESET);
++ }
++
+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
-+ ASPEED_ESPI_CTRL_SW_RESET, 0);
-+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
-+ ASPEED_ESPI_CTRL_SW_RESET,
-+ ASPEED_ESPI_CTRL_SW_RESET);
++ ASPEED_ESPI_CTRL_OOB_CHRDY,
++ ASPEED_ESPI_CTRL_OOB_CHRDY);
+ aspeed_espi_boot_ack(priv);
+ sts_handled |= ASPEED_ESPI_HW_RESET;
+ }
@@ -504,8 +516,26 @@ index 000000000000..d70332d1fef3
+ ASPEED_ESPI_SYSEVT1_INT_MASK);
+
+ regmap_write(priv->map, ASPEED_ESPI_INT_EN, ASPEED_ESPI_INT_MASK);
++}
+
-+ aspeed_espi_boot_ack(priv);
++static irqreturn_t aspeed_espi_reset_isr(int irq, void *arg)
++{
++ struct aspeed_espi *priv = arg;
++
++ reset_control_assert(priv->reset);
++ reset_control_deassert(priv->reset);
++
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, 0);
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_SW_RESET, ASPEED_ESPI_CTRL_SW_RESET);
++
++ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL,
++ ASPEED_ESPI_CTRL_OOB_CHRDY, 0);
++
++ aspeed_espi_config_irq(priv);
++
++ return IRQ_HANDLED;
+}
+
+static inline struct aspeed_espi *to_aspeed_espi(struct file *filp)
@@ -610,13 +640,30 @@ index 000000000000..d70332d1fef3
+ if (priv->irq < 0)
+ return priv->irq;
+
-+ aspeed_espi_config_irq(priv);
-+
+ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_espi_irq, 0,
+ "aspeed-espi-irq", priv);
+ if (ret)
+ return ret;
+
++ if (of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2600-espi-slave")) {
++ priv->rst_irq = platform_get_irq(pdev, 1);
++ if (priv->rst_irq < 0)
++ return priv->rst_irq;
++
++ ret = devm_request_irq(&pdev->dev, priv->rst_irq,
++ aspeed_espi_reset_isr, 0,
++ "aspeed-espi-rst-irq", priv);
++ if (ret)
++ return ret;
++
++ priv->reset = devm_reset_control_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->reset))
++ return PTR_ERR(priv->reset);
++ } else {
++ priv->rst_irq = -ENOTSUPP;
++ }
++
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
@@ -654,6 +701,9 @@ index 000000000000..d70332d1fef3
+ goto err_clk_disable_out;
+ }
+
++ aspeed_espi_config_irq(priv);
++ aspeed_espi_boot_ack(priv);
++
+ dev_info(&pdev->dev, "eSPI registered, irq %d\n", priv->irq);
+
+ return 0;
@@ -695,6 +745,18 @@ index 000000000000..d70332d1fef3
+MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
+MODULE_DESCRIPTION("Aspeed eSPI driver");
+MODULE_LICENSE("GPL v2");
+diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h
+index 3d90582a813f..1e18364de03d 100644
+--- a/include/dt-bindings/clock/ast2600-clock.h
++++ b/include/dt-bindings/clock/ast2600-clock.h
+@@ -104,6 +104,7 @@
+ #define ASPEED_RESET_PECI 36
+ #define ASPEED_RESET_MII 35
+ #define ASPEED_RESET_I2C 34
++#define ASPEED_RESET_ESPI 32
+ #define ASPEED_RESET_H2X 31
+ #define ASPEED_RESET_GP_MCU 30
+ #define ASPEED_RESET_DP_MCU 29
--
2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch
index 24032087b..fbf422a35 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch
@@ -1,4 +1,4 @@
-From fcee7b9515140486ad8c58beedf88cf12cd09b8b Mon Sep 17 00:00:00 2001
+From b8d7d0f3513abdf014345b240a79d23c63409c4c Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Tue, 11 Jun 2019 15:07:08 -0700
Subject: [PATCH] i2c: aspeed: add buffer mode transfer support
@@ -31,11 +31,11 @@ It provides buffer based master and slave data transfer.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
.../devicetree/bindings/i2c/i2c-aspeed.txt | 40 ++-
- arch/arm/boot/dts/aspeed-g4.dtsi | 47 ++--
- arch/arm/boot/dts/aspeed-g5.dtsi | 47 ++--
- arch/arm/boot/dts/aspeed-g6.dtsi | 32 +--
- drivers/i2c/busses/i2c-aspeed.c | 294 ++++++++++++++++++---
- 5 files changed, 365 insertions(+), 95 deletions(-)
+ arch/arm/boot/dts/aspeed-g4.dtsi | 47 +--
+ arch/arm/boot/dts/aspeed-g5.dtsi | 47 +--
+ arch/arm/boot/dts/aspeed-g6.dtsi | 32 +-
+ drivers/i2c/busses/i2c-aspeed.c | 376 +++++++++++++++++++--
+ 5 files changed, 451 insertions(+), 91 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
index 7da7e813b2b0..0ff3539cee95 100644
@@ -422,10 +422,10 @@ index eb1f9c9d9cca..51593a0a8a23 100644
clocks = <&syscon ASPEED_CLK_APB>;
resets = <&syscon ASPEED_RESET_I2C>;
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
-index 0e35c4598df5..eeace4b7b725 100644
+index f92a2aa999d1..3ef312543269 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
-@@ -713,7 +713,7 @@
+@@ -712,7 +712,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -434,7 +434,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -728,7 +728,7 @@
+@@ -727,7 +727,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -443,7 +443,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -743,7 +743,7 @@
+@@ -742,7 +742,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -452,7 +452,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -758,7 +758,7 @@
+@@ -757,7 +757,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -461,7 +461,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -773,7 +773,7 @@
+@@ -772,7 +772,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -470,7 +470,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -788,7 +788,7 @@
+@@ -787,7 +787,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -479,7 +479,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -803,7 +803,7 @@
+@@ -802,7 +802,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -488,7 +488,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -818,7 +818,7 @@
+@@ -817,7 +817,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -497,7 +497,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -833,7 +833,7 @@
+@@ -832,7 +832,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -506,7 +506,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -848,7 +848,7 @@
+@@ -847,7 +847,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -515,7 +515,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -863,7 +863,7 @@
+@@ -862,7 +862,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -524,7 +524,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -878,7 +878,7 @@
+@@ -877,7 +877,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -533,7 +533,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -893,7 +893,7 @@
+@@ -892,7 +892,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -542,7 +542,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -908,7 +908,7 @@
+@@ -907,7 +907,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -551,7 +551,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -923,7 +923,7 @@
+@@ -922,7 +922,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -560,7 +560,7 @@ index 0e35c4598df5..eeace4b7b725 100644
compatible = "aspeed,ast2600-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
-@@ -938,7 +938,7 @@
+@@ -937,7 +937,7 @@
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
@@ -570,7 +570,7 @@ index 0e35c4598df5..eeace4b7b725 100644
clocks = <&syscon ASPEED_CLK_APB2>;
resets = <&syscon ASPEED_RESET_I2C>;
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 7becfcd67142..1b338492c68a 100644
+index 7becfcd67142..bf72e151d11f 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -7,6 +7,7 @@
@@ -653,220 +653,338 @@ index 7becfcd67142..1b338492c68a 100644
bool multi_master;
+ /* Buffer mode */
+ void __iomem *buf_base;
-+ size_t buf_size;
+ u8 buf_offset;
+ u8 buf_page;
++ size_t buf_size;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
struct i2c_client *slave;
enum aspeed_i2c_slave_state slave_state;
-@@ -259,6 +281,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -255,6 +277,77 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
+ }
+
+ #if IS_ENABLED(CONFIG_I2C_SLAVE)
++static inline void
++aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
++ u8 *value)
++{
++ if (bus->buf_base &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
++ *value = readb(bus->buf_base);
++ else
++ *value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++}
++
++static inline void
++aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
++ u8 *value)
++{
++ int i, len;
++
++ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ irq_status & ASPEED_I2CD_INTR_RX_DONE) {
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base +
++ ASPEED_I2C_BUF_CTRL_REG));
++ for (i = 0; i < len; i++) {
++ *value = readb(bus->buf_base + i);
++ i2c_slave_event(bus->slave,
++ I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ }
++ }
++}
++
++static inline void
++aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value)
++{
++ if (bus->buf_base) {
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ bus->buf_size - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(ASPEED_I2CD_RX_BUFF_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ }
++}
++
++static inline void
++aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value)
++{
++ int i, len;
++
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base +
++ ASPEED_I2C_BUF_CTRL_REG));
++ for (i = 1; i < len; i++) {
++ *value = readb(bus->buf_base + i);
++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ bus->buf_size - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(ASPEED_I2CD_RX_BUFF_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ }
++}
++
+ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
{
u32 command, irq_handled = 0;
- struct i2c_client *slave = bus->slave;
-+ int i, len;
- u8 value;
-
- if (!slave)
-@@ -281,7 +304,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -281,7 +374,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
/* Slave was sent something. */
if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
- value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
-+ if (bus->buf_base &&
-+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
-+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
-+ value = readb(bus->buf_base);
-+ else
-+ value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value);
/* Handle address frame. */
if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
if (value & 0x1)
-@@ -296,6 +324,20 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -296,9 +389,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
/* Slave was asked to stop. */
if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
-+ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
-+ irq_status & ASPEED_I2CD_INTR_RX_DONE) {
-+ if (bus->buf_base) {
-+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
-+ readl(bus->base +
-+ ASPEED_I2C_BUF_CTRL_REG));
-+ for (i = 0; i < len; i++) {
-+ value = readb(bus->buf_base + i);
-+ i2c_slave_event(slave,
-+ I2C_SLAVE_WRITE_RECEIVED,
-+ &value);
-+ }
-+ }
-+ }
++ aspeed_i2c_slave_handle_normal_stop(bus, irq_status, &value);
irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;
bus->slave_state = ASPEED_I2C_SLAVE_STOP;
}
-@@ -328,9 +370,36 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
++
+ if (irq_status & ASPEED_I2CD_INTR_TX_NAK &&
+ bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {
+ irq_handled |= ASPEED_I2CD_INTR_TX_NAK;
+@@ -328,9 +423,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
case ASPEED_I2C_SLAVE_WRITE_REQUESTED:
bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
-+ 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);
-+ }
++ aspeed_i2c_slave_handle_write_requested(bus, &value);
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);
-+ }
++ aspeed_i2c_slave_handle_write_received(bus, &value);
break;
case ASPEED_I2C_SLAVE_STOP:
i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
-@@ -356,6 +425,8 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+@@ -350,12 +447,76 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ }
+ #endif /* CONFIG_I2C_SLAVE */
+
++static inline u32
++aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u32 command = 0;
++ int len;
++
++ if (msg->len > bus->buf_size) {
++ len = bus->buf_size;
++ } else {
++ len = msg->len;
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ if (bus->buf_base) {
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
++
++ return command;
++}
++
++static inline u32
++aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u8 slave_addr = i2c_8bit_addr_from_msg(msg);
++ u32 command = 0;
++ int len;
++
++ if (msg->len + 1 > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len + 1;
++
++ if (bus->buf_base) {
++ u8 wbuf[4];
++ int i;
++
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++
++ /*
++ * Yeah, it looks bad but byte writing on remapped I2C SRAM
++ * causes corruption so use this way to make dword writings.
++ */
++ wbuf[0] = slave_addr;
++ for (i = 1; i < len; i++) {
++ wbuf[i % 4] = msg->buf[i - 1];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf, bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
++ writel(*(u32 *)wbuf, bus->buf_base + i - (i % 4));
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
++
++ bus->buf_index = len - 1;
++
++ return command;
++}
++
+ /* precondition: bus.lock has been acquired. */
+ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ {
u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
- u8 slave_addr = i2c_8bit_addr_from_msg(msg);
-+ u8 wbuf[4];
-+ int len;
+- u8 slave_addr = i2c_8bit_addr_from_msg(msg);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
/*
-@@ -374,12 +445,66 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+@@ -374,12 +535,21 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
if (msg->flags & I2C_M_RD) {
command |= ASPEED_I2CD_M_RX_CMD;
- /* Need to let the hardware know to NACK after RX. */
- if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN))
- command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ if (!(msg->flags & I2C_M_RECV_LEN)) {
++ if (msg->len && bus->buf_base)
++ command |= aspeed_i2c_prepare_rx_buf(bus, msg);
+
-+ if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
-+ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
-+
-+ 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_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))
++ if (msg->len <= 1)
+ 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;
-+
-+ /*
-+ * Yeah, it looks clumsy but byte writings on a remapped
-+ * I2C SRAM cause corruptions so use this way to make
-+ * dword writings.
-+ */
-+ wbuf[0] = slave_addr;
-+ for (i = 1; i < len; i++) {
-+ wbuf[i % 4] = msg->buf[i - 1];
-+ if (i % 4 == 3)
-+ writel(*(u32 *)wbuf,
-+ bus->buf_base + i - 3);
-+ }
-+ if (--i % 4 != 3)
-+ writel(*(u32 *)wbuf,
-+ bus->buf_base + i - (i % 4));
-+
-+ 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);
-+ }
++ } else if (msg->len && bus->buf_base) {
++ command |= aspeed_i2c_prepare_tx_buf(bus, msg);
}
- writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
+ if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE))
-+ writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
++ writel(i2c_8bit_addr_from_msg(msg),
++ bus->base + ASPEED_I2C_BYTE_BUF_REG);
writel(command, bus->base + ASPEED_I2C_CMD_REG);
}
-@@ -419,7 +544,7 @@ 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;
+@@ -414,6 +584,104 @@ static int aspeed_i2c_is_irq_error(u32 irq_status)
+ return 0;
+ }
- if (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE) {
- bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
-@@ -522,11 +647,43 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- /* fall through */
- case ASPEED_I2C_MASTER_TX_FIRST:
- if (bus->buf_index < msg->len) {
-+ command = ASPEED_I2CD_M_TX_CMD;
++static inline u32
++aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus,
++ struct i2c_msg *msg)
++{
++ u32 command = 0;
+
-+ if (bus->buf_base) {
-+ u8 wbuf[4];
-+ int i;
++ if (bus->buf_base) {
++ u8 wbuf[4];
++ int len;
++ int i;
+
-+ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
+
-+ 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));
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
+
-+ bus->buf_index += len;
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
+
-+ 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);
-+ } else {
-+ writel(msg->buf[bus->buf_index++],
-+ bus->base + ASPEED_I2C_BYTE_BUF_REG);
-+ }
++ for (i = 0; i < len; i++) {
++ wbuf[i % 4] = msg->buf[bus->buf_index + i];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - (i % 4));
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++
++ bus->buf_index += len;
++ } else {
++ writel(msg->buf[bus->buf_index++],
++ bus->base + ASPEED_I2C_BYTE_BUF_REG);
++ }
++
++ return command;
++}
++
++static inline void
++aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
++{
++ u8 recv_byte;
++ int len;
++
++ if (bus->buf_base) {
++ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
++ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG));
++ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len);
++ bus->buf_index += len;
++ } else {
++ recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
++ msg->buf[bus->buf_index++] = recv_byte;
++ }
++}
++
++static inline u32
++aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
++ struct i2c_msg *msg)
++{
++ u32 command = 0;
++
++ if (bus->buf_base) {
++ int len;
++
++ if (msg->len - bus->buf_index > bus->buf_size) {
++ len = bus->buf_size;
++ } else {
++ len = msg->len - bus->buf_index;
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ } else {
++ if (bus->buf_index + 1 == msg->len)
++ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
++ }
++
++ return command;
++}
++
+ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ {
+ u32 irq_handled = 0, command = 0;
+@@ -522,11 +790,10 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ /* fall through */
+ case ASPEED_I2C_MASTER_TX_FIRST:
+ if (bus->buf_index < msg->len) {
++ command = ASPEED_I2CD_M_TX_CMD;
++ command |= aspeed_i2c_master_handle_tx_first(bus, msg);
+ writel(command, bus->base + ASPEED_I2C_CMD_REG);
bus->master_state = ASPEED_I2C_MASTER_TX;
- writel(msg->buf[bus->buf_index++],
@@ -876,44 +994,28 @@ index 7becfcd67142..1b338492c68a 100644
} else {
aspeed_i2c_next_msg_or_stop(bus);
}
-@@ -543,25 +700,56 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -543,26 +810,26 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
}
irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
- recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
- msg->buf[bus->buf_index++] = recv_byte;
-
-- if (msg->flags & I2C_M_RECV_LEN) {
-- 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;
+ if (msg->flags & I2C_M_RECV_LEN) {
++ recv_byte = readl(bus->base +
++ ASPEED_I2C_BYTE_BUF_REG) >> 8;
+ if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
+ bus->cmd_err = -EPROTO;
+ aspeed_i2c_do_stop(bus);
+ goto out_no_complete;
}
- msg->len = recv_byte +
- ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1);
-- msg->flags &= ~I2C_M_RECV_LEN;
++ msg->len = recv_byte + ((msg->flags & I2C_CLIENT_PEC) ?
++ 2 : 1);
+ msg->flags &= ~I2C_M_RECV_LEN;
++ } else if (msg->len) {
++ aspeed_i2c_master_handle_rx(bus, msg);
}
if (bus->buf_index < msg->len) {
@@ -921,33 +1023,13 @@ index 7becfcd67142..1b338492c68a 100644
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;
-+ }
++ command |= aspeed_i2c_master_handle_rx_next(bus, msg);
writel(command, bus->base + ASPEED_I2C_CMD_REG);
++ bus->master_state = ASPEED_I2C_MASTER_RX;
} else {
aspeed_i2c_next_msg_or_stop(bus);
-@@ -924,6 +1112,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+ }
+@@ -924,6 +1191,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
if (ret < 0)
return ret;
@@ -957,34 +1039,24 @@ index 7becfcd67142..1b338492c68a 100644
if (of_property_read_bool(pdev->dev.of_node, "multi-master"))
bus->multi_master = true;
else
-@@ -985,16 +1176,15 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
- {
- const struct of_device_id *match;
- struct aspeed_i2c_bus *bus;
-+ bool sram_enabled = true;
- struct clk *parent_clk;
-- struct resource *res;
- int irq, ret;
-
- bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
- if (!bus)
- return -ENOMEM;
-
-- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- bus->base = devm_ioremap_resource(&pdev->dev, res);
-+ bus->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(bus->base))
- return PTR_ERR(bus->base);
-
-@@ -1028,6 +1218,42 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
- bus->get_clk_reg_val = (u32 (*)(struct device *, u32))
- match->data;
+@@ -964,6 +1234,52 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus)
+ return ret;
+ }
-+ /* Enable I2C SRAM in case of AST2500 */
++static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus)
++{
++ struct platform_device *pdev = to_platform_device(bus->dev);
++ bool sram_enabled = true;
++ int ret;
++
++ /*
++ * Enable I2C SRAM in case of AST2500.
++ * SRAM is enabled by default in AST2400 and AST2600.
++ */
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "aspeed,ast2500-i2c-bus")) {
-+ struct regmap *gr_regmap = syscon_regmap_lookup_by_compatible(
-+ "aspeed,ast2500-i2c-gr");
++ struct regmap *gr_regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2500-i2c-gr");
++
+ if (IS_ERR(gr_regmap))
+ ret = PTR_ERR(gr_regmap);
+ else
@@ -1001,10 +1073,10 @@ index 7becfcd67142..1b338492c68a 100644
+ struct resource *res = platform_get_resource(pdev,
+ IORESOURCE_MEM, 1);
+
-+ if (res)
++ if (res && resource_size(res) >= 2)
+ bus->buf_base = devm_ioremap_resource(&pdev->dev, res);
+
-+ if (!IS_ERR_OR_NULL(bus->buf_base) && resource_size(res) >= 2) {
++ if (!IS_ERR_OR_NULL(bus->buf_base)) {
+ bus->buf_size = resource_size(res);
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "aspeed,ast2400-i2c-bus")) {
@@ -1015,11 +1087,52 @@ index 7becfcd67142..1b338492c68a 100644
+ }
+ }
+ }
++}
++
+ static const struct of_device_id aspeed_i2c_bus_of_table[] = {
+ {
+ .compatible = "aspeed,ast2400-i2c-bus",
+@@ -986,18 +1302,18 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ const struct of_device_id *match;
+ struct aspeed_i2c_bus *bus;
+ struct clk *parent_clk;
+- struct resource *res;
+ int irq, ret;
+
+ bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- bus->base = devm_ioremap_resource(&pdev->dev, res);
++ bus->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bus->base))
+ return PTR_ERR(bus->base);
+
++ bus->dev = &pdev->dev;
++
+ parent_clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+@@ -1028,6 +1344,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ bus->get_clk_reg_val = (u32 (*)(struct device *, u32))
+ match->data;
+
++ aspeed_i2c_set_xfer_mode(bus);
+
/* Initialize the I2C adapter */
spin_lock_init(&bus->lock);
init_completion(&bus->cmd_complete);
-@@ -1063,8 +1289,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+@@ -1038,8 +1356,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
+ i2c_set_adapdata(&bus->adap, bus);
+
+- bus->dev = &pdev->dev;
+-
+ /* Clean up any left over interrupt state. */
+ writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
+ writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
+@@ -1063,8 +1379,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
platform_set_drvdata(pdev, bus);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch
index a66e759e7..994c20b18 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch
@@ -1,4 +1,4 @@
-From 0d237f4b5111aa192a1ae9aaee6e6779761906bc Mon Sep 17 00:00:00 2001
+From 5bf7a202eb0af455675a85a4f1bdad863fd8805d Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Tue, 18 Jun 2019 08:47:50 -0700
Subject: [PATCH] i2c: aspeed: add DMA mode transfer support
@@ -15,9 +15,9 @@ use DMA mode.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
- .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 +++
- drivers/i2c/busses/i2c-aspeed.c | 231 +++++++++++++++++++--
- 2 files changed, 241 insertions(+), 15 deletions(-)
+ .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 ++
+ drivers/i2c/busses/i2c-aspeed.c | 253 +++++++++++++++++----
+ 2 files changed, 234 insertions(+), 44 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
index 0ff3539cee95..d3f4a39f7ba6 100644
@@ -61,7 +61,7 @@ index 0ff3539cee95..d3f4a39f7ba6 100644
+ };
};
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 1b338492c68a..8dc6723bfaaf 100644
+index bf72e151d11f..3c9e491cbe4e 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -10,6 +10,8 @@
@@ -106,242 +106,291 @@ index 1b338492c68a..8dc6723bfaaf 100644
enum aspeed_i2c_master_state {
ASPEED_I2C_MASTER_INACTIVE,
ASPEED_I2C_MASTER_PENDING,
-@@ -185,6 +199,12 @@ struct aspeed_i2c_bus {
- size_t buf_size;
+@@ -184,6 +198,12 @@ struct aspeed_i2c_bus {
+ void __iomem *buf_base;
u8 buf_offset;
u8 buf_page;
+ /* DMA mode */
+ struct dma_pool *dma_pool;
+ dma_addr_t dma_handle;
+ u8 *dma_buf;
-+ size_t dma_buf_size;
+ size_t dma_len;
++ /* Buffer/DMA mode */
+ size_t buf_size;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
struct i2c_client *slave;
- enum aspeed_i2c_slave_state slave_state;
-@@ -304,9 +324,13 @@ 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) {
-- if (bus->buf_base &&
-+ if (bus->dma_buf &&
- bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
- !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
-+ value = bus->dma_buf[0];
-+ else if (bus->buf_base &&
-+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
-+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
- value = readb(bus->buf_base);
- else
- value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
-@@ -326,7 +350,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
- if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
- irq_status & ASPEED_I2CD_INTR_RX_DONE) {
-- if (bus->buf_base) {
-+ if (bus->dma_buf) {
-+ len = bus->dma_buf_size -
-+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
-+ readl(bus->base +
-+ ASPEED_I2C_DMA_LEN_REG));
-+ for (i = 0; i < len; i++) {
-+ value = bus->dma_buf[i];
-+ i2c_slave_event(slave,
-+ I2C_SLAVE_WRITE_RECEIVED,
-+ &value);
-+ }
-+ } else if (bus->buf_base) {
- len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
- readl(bus->base +
- ASPEED_I2C_BUF_CTRL_REG));
-@@ -370,7 +405,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) {
-+ if (bus->dma_buf) {
-+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ bus->dma_buf_size),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ writel(ASPEED_I2CD_RX_DMA_ENABLE,
-+ bus->base + ASPEED_I2C_CMD_REG);
-+ } else if (bus->buf_base) {
- writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
- bus->buf_size - 1) |
- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
-@@ -382,7 +425,25 @@ 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);
+@@ -281,7 +301,11 @@ static inline void
+ aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
+ u8 *value)
+ {
+- if (bus->buf_base &&
++ if (bus->dma_buf &&
++ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
++ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
++ *value = bus->dma_buf[0];
++ else if (bus->buf_base &&
+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))
+ *value = readb(bus->buf_base);
+@@ -297,7 +321,18 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
+
+ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED &&
+ irq_status & ASPEED_I2CD_INTR_RX_DONE) {
- if (bus->buf_base) {
+ if (bus->dma_buf) {
-+ len = bus->dma_buf_size -
++ len = bus->buf_size -
+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
+ readl(bus->base +
+ ASPEED_I2C_DMA_LEN_REG));
-+ for (i = 1; i < len; i++) {
-+ value = bus->dma_buf[i];
-+ i2c_slave_event(slave,
++ for (i = 0; i < len; i++) {
++ *value = bus->dma_buf[i];
++ i2c_slave_event(bus->slave,
+ I2C_SLAVE_WRITE_RECEIVED,
-+ &value);
++ value);
+ }
-+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ bus->dma_buf_size),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ writel(ASPEED_I2CD_RX_DMA_ENABLE,
-+ bus->base + ASPEED_I2C_CMD_REG);
+ } else if (bus->buf_base) {
len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
readl(bus->base +
ASPEED_I2C_BUF_CTRL_REG));
-@@ -446,7 +507,23 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
- if (msg->flags & I2C_M_RD) {
- command |= ASPEED_I2CD_M_RX_CMD;
+@@ -314,7 +349,14 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status,
+ static inline void
+ aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value)
+ {
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ writel(ASPEED_I2CD_RX_DMA_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ } else if (bus->buf_base) {
+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
+ bus->buf_size - 1) |
+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+@@ -330,7 +372,23 @@ aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value)
+ {
+ int i, len;
-- if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
-+ if (bus->dma_buf && !(msg->flags & I2C_M_RECV_LEN)) {
-+ command |= ASPEED_I2CD_RX_DMA_ENABLE;
-+
-+ if (msg->len > bus->dma_buf_size) {
-+ len = bus->dma_buf_size;
-+ } else {
-+ len = msg->len;
-+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
-+ }
-+
-+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ len),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ bus->dma_len = len;
-+ } else if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
- command |= ASPEED_I2CD_RX_BUFF_ENABLE;
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ len = bus->buf_size -
++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
++ readl(bus->base +
++ ASPEED_I2C_DMA_LEN_REG));
++ for (i = 1; i < len; i++) {
++ *value = bus->dma_buf[i];
++ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED,
++ value);
++ }
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ writel(ASPEED_I2CD_RX_DMA_ENABLE,
++ bus->base + ASPEED_I2C_CMD_REG);
++ } else if (bus->buf_base) {
+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
+ readl(bus->base +
+ ASPEED_I2C_BUF_CTRL_REG));
+@@ -460,7 +518,15 @@ aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+ }
- if (msg->len > bus->buf_size) {
-@@ -467,7 +544,26 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
- command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
- }
- } else {
-- if (bus->buf_base) {
-+ if (bus->dma_buf) {
-+ command |= ASPEED_I2CD_TX_DMA_ENABLE;
-+
-+ if (msg->len + 1 > bus->dma_buf_size)
-+ len = bus->dma_buf_size;
-+ else
-+ len = msg->len + 1;
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_RX_DMA_ENABLE;
+
-+ bus->dma_buf[0] = slave_addr;
-+ memcpy(bus->dma_buf + 1, msg->buf, len);
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
+ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
+
+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) |
+@@ -483,7 +549,18 @@ aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ else
+ len = msg->len + 1;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_TX_DMA_ENABLE;
+
-+ bus->buf_index = len - 1;
++ bus->dma_buf[0] = slave_addr;
++ memcpy(bus->dma_buf + 1, msg->buf, len);
+
-+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ len),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ bus->dma_len = len;
-+ } else if (bus->buf_base) {
- int i;
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
+ u8 wbuf[4];
+ int i;
+
+@@ -536,18 +613,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ if (msg->flags & I2C_M_RD) {
+ command |= ASPEED_I2CD_M_RX_CMD;
+ if (!(msg->flags & I2C_M_RECV_LEN)) {
+- if (msg->len && bus->buf_base)
++ if (msg->len && (bus->dma_buf || bus->buf_base))
+ command |= aspeed_i2c_prepare_rx_buf(bus, msg);
- command |= ASPEED_I2CD_TX_BUFF_ENABLE;
-@@ -503,7 +599,8 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
+ /* Need to let the hardware know to NACK after RX. */
+ if (msg->len <= 1)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
}
+- } else if (msg->len && bus->buf_base) {
++ } else if (msg->len && (bus->dma_buf || bus->buf_base)) {
+ command |= aspeed_i2c_prepare_tx_buf(bus, msg);
}
- if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE))
+ if (!(command & (ASPEED_I2CD_TX_BUFF_ENABLE |
+ ASPEED_I2CD_TX_DMA_ENABLE)))
- writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG);
+ writel(i2c_8bit_addr_from_msg(msg),
+ bus->base + ASPEED_I2C_BYTE_BUF_REG);
writel(command, bus->base + ASPEED_I2C_CMD_REG);
- }
-@@ -649,7 +746,28 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- if (bus->buf_index < msg->len) {
- command = ASPEED_I2CD_M_TX_CMD;
+@@ -590,39 +668,52 @@ aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus,
+ {
+ u32 command = 0;
+
+- if (bus->buf_base) {
+- u8 wbuf[4];
++ if (bus->dma_buf || bus->buf_base) {
+ int len;
+- int i;
-- if (bus->buf_base) {
-+ if (bus->dma_buf) {
-+ command |= ASPEED_I2CD_TX_DMA_ENABLE;
+ if (msg->len - bus->buf_index > bus->buf_size)
+ len = bus->buf_size;
+ else
+ len = msg->len - bus->buf_index;
+
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_TX_DMA_ENABLE;
+
+- command |= ASPEED_I2CD_TX_BUFF_ENABLE;
++ memcpy(bus->dma_buf, msg->buf + bus->buf_index, len);
+
+- if (msg->len - bus->buf_index > bus->buf_size)
+- len = bus->buf_size;
+- else
+- len = msg->len - bus->buf_index;
+
+- for (i = 0; i < len; i++) {
+- wbuf[i % 4] = msg->buf[bus->buf_index + i];
+- if (i % 4 == 3)
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
++ u8 wbuf[4];
++ int i;
+
-+ if (msg->len - bus->buf_index >
-+ bus->dma_buf_size)
-+ len = bus->dma_buf_size;
-+ else
-+ len = msg->len - bus->buf_index;
++ command |= ASPEED_I2CD_TX_BUFF_ENABLE;
+
-+ memcpy(bus->dma_buf, msg->buf + bus->buf_index,
-+ len);
++ if (msg->len - bus->buf_index > bus->buf_size)
++ len = bus->buf_size;
++ else
++ len = msg->len - bus->buf_index;
+
-+ bus->buf_index += len;
++ for (i = 0; i < len; i++) {
++ wbuf[i % 4] = msg->buf[bus->buf_index + i];
++ if (i % 4 == 3)
++ writel(*(u32 *)wbuf,
++ bus->buf_base + i - 3);
++ }
++ if (--i % 4 != 3)
+ writel(*(u32 *)wbuf,
+- bus->buf_base + i - 3);
+- }
+- if (--i % 4 != 3)
+- writel(*(u32 *)wbuf,
+- bus->buf_base + i - (i % 4));
++ bus->buf_base + i - (i % 4));
+
+- writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
+- len - 1) |
+- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+- bus->buf_offset),
+- bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
+
+ bus->buf_index += len;
+ } else {
+@@ -639,7 +730,14 @@ aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg)
+ u8 recv_byte;
+ int len;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf) {
++ len = bus->dma_len -
++ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
++ readl(bus->base + ASPEED_I2C_DMA_LEN_REG));
+
-+ writel(bus->dma_handle &
-+ ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ len),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ bus->dma_len = len;
-+ } else if (bus->buf_base) {
- u8 wbuf[4];
- int i;
-
-@@ -700,7 +818,15 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
++ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len);
++ bus->buf_index += len;
++ } else if (bus->buf_base) {
+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
+ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG));
+ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len);
+@@ -656,7 +754,7 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
+ {
+ u32 command = 0;
+
+- if (bus->buf_base) {
++ if (bus->dma_buf || bus->buf_base) {
+ int len;
+
+ if (msg->len - bus->buf_index > bus->buf_size) {
+@@ -666,14 +764,24 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus,
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
}
- irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
-- if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
-+ if (bus->dma_buf && !(msg->flags & I2C_M_RECV_LEN)) {
-+ len = bus->dma_len -
-+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK,
-+ readl(bus->base +
-+ ASPEED_I2C_DMA_LEN_REG));
-+
-+ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len);
-+ bus->buf_index += len;
-+ } else if (bus->buf_base && !(msg->flags & I2C_M_RECV_LEN)) {
- len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK,
- readl(bus->base +
- ASPEED_I2C_BUF_CTRL_REG));
-@@ -728,7 +854,25 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- if (bus->buf_index < msg->len) {
- command = ASPEED_I2CD_M_RX_CMD;
- bus->master_state = ASPEED_I2C_MASTER_RX;
-- if (bus->buf_base) {
-+ if (bus->dma_buf) {
-+ command |= ASPEED_I2CD_RX_DMA_ENABLE;
-+
-+ if (msg->len - bus->buf_index >
-+ bus->dma_buf_size) {
-+ len = bus->dma_buf_size;
-+ } else {
-+ len = msg->len - bus->buf_index;
-+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
-+ }
+- command |= ASPEED_I2CD_RX_BUFF_ENABLE;
++ if (bus->dma_buf) {
++ command |= ASPEED_I2CD_RX_DMA_ENABLE;
+
+- writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
+- len - 1) |
+- FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
+- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
+- bus->buf_offset),
+- bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK,
++ bus->base + ASPEED_I2C_DMA_ADDR_REG);
++ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len),
++ bus->base + ASPEED_I2C_DMA_LEN_REG);
++ bus->dma_len = len;
++ } else {
++ command |= ASPEED_I2CD_RX_BUFF_ENABLE;
+
-+ writel(bus->dma_handle &
-+ ASPEED_I2CD_DMA_ADDR_MASK,
-+ bus->base + ASPEED_I2C_DMA_ADDR_REG);
-+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK,
-+ len),
-+ bus->base + ASPEED_I2C_DMA_LEN_REG);
-+ bus->dma_len = len;
-+ } else if (bus->buf_base) {
- command |= ASPEED_I2CD_RX_BUFF_ENABLE;
-
- if (msg->len - bus->buf_index >
-@@ -1235,7 +1379,51 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
++ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK,
++ len - 1) |
++ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) |
++ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK,
++ bus->buf_offset),
++ bus->base + ASPEED_I2C_BUF_CTRL_REG);
++ }
+ } else {
+ if (bus->buf_index + 1 == msg->len)
+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
+@@ -1260,7 +1368,51 @@ static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus)
sram_enabled = false;
}
- if (sram_enabled) {
+ /*
-+ * Only AST2500 supports DMA mode under some limitations:
++ * Only AST2500 and AST2600 support DMA mode under some limitations:
+ * I2C is sharing the DMA H/W with UHCI host controller and MCTP
+ * controller. Since those controllers operate with DMA mode only, I2C
+ * has to use buffer mode or byte mode instead if one of those
@@ -350,25 +399,25 @@ index 1b338492c68a..8dc6723bfaaf 100644
+ * use DMA mode.
+ */
+ if (sram_enabled && !IS_ENABLED(CONFIG_USB_UHCI_ASPEED) &&
-+ of_device_is_compatible(pdev->dev.of_node,
-+ "aspeed,ast2500-i2c-bus")) {
++ !of_device_is_compatible(pdev->dev.of_node,
++ "aspeed,ast2400-i2c-bus")) {
+ u32 dma_len_max = ASPEED_I2CD_DMA_LEN_MASK >>
+ ASPEED_I2CD_DMA_LEN_SHIFT;
+
+ ret = device_property_read_u32(&pdev->dev,
+ "aspeed,dma-buf-size",
-+ &bus->dma_buf_size);
-+ if (!ret && bus->dma_buf_size > dma_len_max)
-+ bus->dma_buf_size = dma_len_max;
++ &bus->buf_size);
++ if (!ret && bus->buf_size > dma_len_max)
++ bus->buf_size = dma_len_max;
+ }
+
-+ if (bus->dma_buf_size) {
++ if (bus->buf_size) {
+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
+ dev_warn(&pdev->dev, "No suitable DMA available\n");
+ } else {
+ bus->dma_pool = dma_pool_create("i2c-aspeed",
+ &pdev->dev,
-+ bus->dma_buf_size,
++ bus->buf_size,
+ ASPEED_I2CD_DMA_ALIGN,
+ 0);
+ if (bus->dma_pool)
@@ -388,7 +437,7 @@ index 1b338492c68a..8dc6723bfaaf 100644
struct resource *res = platform_get_resource(pdev,
IORESOURCE_MEM, 1);
-@@ -1275,24 +1463,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+@@ -1365,24 +1517,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
*/
ret = aspeed_i2c_init(bus, pdev);
if (ret < 0)
@@ -426,7 +475,7 @@ index 1b338492c68a..8dc6723bfaaf 100644
}
static int aspeed_i2c_remove_bus(struct platform_device *pdev)
-@@ -1310,6 +1507,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
+@@ -1400,6 +1561,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
reset_control_assert(bus->rst);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch
index 2f51c3fc9..899924f61 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch
@@ -1,4 +1,4 @@
-From 3f73215941667176ba05f358f4ee08816299bd32 Mon Sep 17 00:00:00 2001
+From d731b53de05b8d69ea739f02275416126cf5fe4e Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Wed, 1 May 2019 13:27:34 -0700
Subject: [PATCH] i2c: aspeed: add general call support
@@ -28,7 +28,7 @@ index d3f4a39f7ba6..c1ee99398517 100644
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 8dc6723bfaaf..891b2b5c4b7a 100644
+index 3c9e491cbe4e..4420899e2c2d 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -59,6 +59,7 @@
@@ -65,7 +65,7 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
#endif /* CONFIG_I2C_SLAVE */
};
-@@ -315,6 +321,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -423,6 +429,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
bus->slave_state = ASPEED_I2C_SLAVE_START;
}
@@ -78,7 +78,7 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
/* Slave is not currently active, irq was for someone else. */
if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)
return irq_handled;
-@@ -342,6 +354,21 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -441,6 +453,21 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
else
bus->slave_state =
ASPEED_I2C_SLAVE_WRITE_REQUESTED;
@@ -100,9 +100,9 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
}
irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
}
-@@ -462,11 +489,16 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- bus->base + ASPEED_I2C_CMD_REG);
- }
+@@ -487,11 +514,16 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
+ aspeed_i2c_slave_handle_write_received(bus, &value);
break;
+ case ASPEED_I2C_SLAVE_GCALL_REQUESTED:
+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
@@ -117,7 +117,7 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
/* Slave was just started. Waiting for the next event. */;
break;
default:
-@@ -1084,6 +1116,8 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
+@@ -1127,6 +1159,8 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
/* Turn on slave mode. */
func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
@@ -126,7 +126,7 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
}
-@@ -1122,6 +1156,8 @@ static int aspeed_i2c_unreg_slave(struct i2c_client *client)
+@@ -1165,6 +1199,8 @@ static int aspeed_i2c_unreg_slave(struct i2c_client *client)
/* Turn off slave mode. */
func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN;
@@ -135,7 +135,7 @@ index 8dc6723bfaaf..891b2b5c4b7a 100644
writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
bus->slave = NULL;
-@@ -1269,6 +1305,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+@@ -1312,6 +1348,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
bus->base + ASPEED_I2C_FUN_CTRL_REG);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
index a5f4fa216..0e8a2b101 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
@@ -1,4 +1,4 @@
-From 3e359be7e8a96b068479d01aa671ff642d291bca Mon Sep 17 00:00:00 2001
+From b429cf11ecb2f6009dd9e062ea5e053718802d93 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Thu, 11 Jul 2019 13:53:34 -0700
Subject: [PATCH] i2c: aspeed: add H/W timeout support
@@ -11,7 +11,7 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
1 file changed, 76 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 891b2b5c4b7a..71ebf3bbf38b 100644
+index 4420899e2c2d..830b3d2cabad 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -55,6 +55,7 @@
@@ -79,10 +79,10 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
+ return 0;
+}
+
- static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- {
- u32 command, irq_handled = 0;
-@@ -313,6 +331,14 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+ static inline void
+ aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
+ u8 *value)
+@@ -421,6 +439,14 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
if (!slave)
return 0;
@@ -97,7 +97,7 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
command = readl(bus->base + ASPEED_I2C_CMD_REG);
/* Slave was requested, restart state machine. */
-@@ -655,7 +681,7 @@ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
+@@ -681,7 +707,7 @@ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
}
}
@@ -106,7 +106,7 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
{
if (irq_status & ASPEED_I2CD_INTR_ARBIT_LOSS)
return -EAGAIN;
-@@ -686,9 +712,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -840,9 +866,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
* should clear the command queue effectively taking us back to the
* INACTIVE state.
*/
@@ -118,7 +118,7 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
irq_status);
irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS);
if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
-@@ -1264,6 +1290,7 @@ static u32 aspeed_i2c_25xx_get_clk_reg_val(struct device *dev, u32 divisor)
+@@ -1307,6 +1333,7 @@ static u32 aspeed_i2c_25xx_get_clk_reg_val(struct device *dev, u32 divisor)
/* precondition: bus.lock has been acquired. */
static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
{
@@ -126,7 +126,7 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
u32 divisor, clk_reg_val;
divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
-@@ -1272,8 +1299,46 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
+@@ -1315,8 +1342,46 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
ASPEED_I2CD_TIME_THDSTA_MASK |
ASPEED_I2CD_TIME_TACST_MASK);
clk_reg_val |= bus->get_clk_reg_val(bus->dev, divisor);
@@ -174,7 +174,7 @@ index 891b2b5c4b7a..71ebf3bbf38b 100644
return 0;
}
-@@ -1288,6 +1353,11 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
+@@ -1331,6 +1396,11 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
/* Disable everything. */
writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch
index a304de019..104279ace 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch
@@ -1,4 +1,4 @@
-From 78ad5c6291df33b7cba0e6be9a2b6ed6e7bbd571 Mon Sep 17 00:00:00 2001
+From b43bdeb5f3aa297549655e67f0e6a5db5f592e34 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Thu, 11 Jul 2019 14:04:39 -0700
Subject: [PATCH] i2c: aspeed: add SLAVE_ADDR_RECEIVED_PENDING interrupt
@@ -15,7 +15,7 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
1 file changed, 13 insertions(+)
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 71ebf3bbf38b..a15f54f64b50 100644
+index 830b3d2cabad..a308d5896632 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -87,6 +87,7 @@
@@ -26,7 +26,7 @@ index 71ebf3bbf38b..a15f54f64b50 100644
#define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15)
#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
-@@ -360,6 +361,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
+@@ -468,6 +469,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
irq_status, command);
@@ -44,7 +44,7 @@ index 71ebf3bbf38b..a15f54f64b50 100644
+
/* Slave was sent something. */
if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
- if (bus->dma_buf &&
+ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value);
--
2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0074-media-aspeed-refine-HSYNC-VSYNC-polarity-setting-log.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0074-media-aspeed-refine-HSYNC-VSYNC-polarity-setting-log.patch
deleted file mode 100644
index 4118e366c..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0074-media-aspeed-refine-HSYNC-VSYNC-polarity-setting-log.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 1032b062669b7ee041d2f5a9f4729953655efe61 Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Wed, 4 Sep 2019 14:52:40 -0700
-Subject: [PATCH] media: aspeed: refine HSYNC/VSYNC polarity setting logic
-
-Sometimes it detects weird resolutions such as 1024x287 when the
-actual resolution is 1280x768. To resolve this issue, this commit
-refines HSYNC/VSYNC polarity setting code for mode detection by
-clearing the bits as normal polarity at the beginning of the first
-mode detection like datasheet suggested, and refines polarity
-setting logic so that the bits can be set or cleared properly.
-
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- drivers/media/platform/aspeed-video.c | 45 ++++++++++++++++++-----------------
- 1 file changed, 23 insertions(+), 22 deletions(-)
-
-diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
-index 4ef37cfc8446..455c6af81236 100644
---- a/drivers/media/platform/aspeed-video.c
-+++ b/drivers/media/platform/aspeed-video.c
-@@ -614,7 +614,7 @@ static void aspeed_video_check_and_set_polarity(struct aspeed_video *video)
- int i;
- int hsync_counter = 0;
- int vsync_counter = 0;
-- u32 sts;
-+ u32 sts, ctrl;
-
- for (i = 0; i < NUM_POLARITY_CHECKS; ++i) {
- sts = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
-@@ -629,30 +629,29 @@ static void aspeed_video_check_and_set_polarity(struct aspeed_video *video)
- hsync_counter++;
- }
-
-- if (hsync_counter < 0 || vsync_counter < 0) {
-- u32 ctrl = 0;
-+ ctrl = aspeed_video_read(video, VE_CTRL);
-
-- if (hsync_counter < 0) {
-- ctrl = VE_CTRL_HSYNC_POL;
-- video->detected_timings.polarities &=
-- ~V4L2_DV_HSYNC_POS_POL;
-- } else {
-- video->detected_timings.polarities |=
-- V4L2_DV_HSYNC_POS_POL;
-- }
--
-- if (vsync_counter < 0) {
-- ctrl = VE_CTRL_VSYNC_POL;
-- video->detected_timings.polarities &=
-- ~V4L2_DV_VSYNC_POS_POL;
-- } else {
-- video->detected_timings.polarities |=
-- V4L2_DV_VSYNC_POS_POL;
-- }
-+ if (hsync_counter < 0) {
-+ ctrl |= VE_CTRL_HSYNC_POL;
-+ video->detected_timings.polarities &=
-+ ~V4L2_DV_HSYNC_POS_POL;
-+ } else {
-+ ctrl &= ~VE_CTRL_HSYNC_POL;
-+ video->detected_timings.polarities |=
-+ V4L2_DV_HSYNC_POS_POL;
-+ }
-
-- if (ctrl)
-- aspeed_video_update(video, VE_CTRL, 0, ctrl);
-+ if (vsync_counter < 0) {
-+ ctrl |= VE_CTRL_VSYNC_POL;
-+ video->detected_timings.polarities &=
-+ ~V4L2_DV_VSYNC_POS_POL;
-+ } else {
-+ ctrl &= ~VE_CTRL_VSYNC_POL;
-+ video->detected_timings.polarities |=
-+ V4L2_DV_VSYNC_POS_POL;
- }
-+
-+ aspeed_video_write(video, VE_CTRL, ctrl);
- }
-
- static bool aspeed_video_alloc_buf(struct aspeed_video *video,
-@@ -741,6 +740,8 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
- }
-
- set_bit(VIDEO_RES_DETECT, &video->flags);
-+ aspeed_video_update(video, VE_CTRL,
-+ VE_CTRL_VSYNC_POL | VE_CTRL_HSYNC_POL, 0);
- aspeed_video_enable_mode_detect(video);
-
- rc = wait_event_interruptible_timeout(video->wait,
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch
index 009fccacf..52c3617d6 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch
@@ -1,4 +1,4 @@
-From 83c1fcb7dacb59d22b41356e3b7009ff2387d448 Mon Sep 17 00:00:00 2001
+From 93ba2aeb9ad3899e2b72877daa47376a6bf192b6 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Mon, 23 Sep 2019 13:48:49 -0700
Subject: [PATCH] Refine initialization flow in I2C driver
@@ -15,12 +15,12 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index a15f54f64b50..62b803e15ce2 100644
+index a308d5896632..b32611088c82 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
-@@ -1454,6 +1454,11 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
- if (IS_ERR(bus->base))
- return PTR_ERR(bus->base);
+@@ -1588,6 +1588,11 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+
+ bus->dev = &pdev->dev;
+ /* Disable bus and clean up any left over interrupt state. */
+ writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
@@ -30,9 +30,9 @@ index a15f54f64b50..62b803e15ce2 100644
parent_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(parent_clk))
return PTR_ERR(parent_clk);
-@@ -1576,17 +1581,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
-
- bus->dev = &pdev->dev;
+@@ -1630,17 +1635,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+ strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
+ i2c_set_adapdata(&bus->adap, bus);
- /* Clean up any left over interrupt state. */
- writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
@@ -48,7 +48,7 @@ index a15f54f64b50..62b803e15ce2 100644
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq,
0, dev_name(&pdev->dev), bus);
-@@ -1599,6 +1593,10 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
+@@ -1653,6 +1647,10 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
platform_set_drvdata(pdev, bus);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-media-aspeed-clear-garbage-interrupts.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-media-aspeed-clear-garbage-interrupts.patch
deleted file mode 100644
index 0cf9913fe..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-media-aspeed-clear-garbage-interrupts.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From 5f89fa4b6468771b5de6e73454bf0ea546249b7b Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Thu, 26 Sep 2019 12:15:23 -0700
-Subject: [PATCH] media: aspeed: clear garbage interrupts
-
-CAPTURE_COMPLETE and FRAME_COMPLETE interrupts come even when these
-are disabled in the VE_INTERRUPT_CTRL register and eventually this
-behavior causes disabling irq itself like below:
-
-[10055.108784] irq 23: nobody cared (try booting with the "irqpoll" option)
-[10055.115525] CPU: 0 PID: 331 Comm: swampd Tainted: G W 5.3.0-4fde000-dirty-d683e2e #1
-[10055.124565] Hardware name: Generic DT based system
-[10055.129355] Backtrace:
-[10055.131854] [<80107d7c>] (dump_backtrace) from [<80107fb0>] (show_stack+0x20/0x24)
-[10055.139431] r7:00000017 r6:00000001 r5:00000000 r4:9d51dc00
-[10055.145120] [<80107f90>] (show_stack) from [<8074bf50>] (dump_stack+0x20/0x28)
-[10055.152361] [<8074bf30>] (dump_stack) from [<80150ffc>] (__report_bad_irq+0x40/0xc0)
-[10055.160109] [<80150fbc>] (__report_bad_irq) from [<80150f2c>] (note_interrupt+0x23c/0x294)
-[10055.168374] r9:015b6e60 r8:00000000 r7:00000017 r6:00000001 r5:00000000 r4:9d51dc00
-[10055.176136] [<80150cf0>] (note_interrupt) from [<8014df1c>] (handle_irq_event_percpu+0x88/0x98)
-[10055.184835] r10:7eff7910 r9:015b6e60 r8:00000000 r7:9d417600 r6:00000001 r5:00000002
-[10055.192657] r4:9d51dc00 r3:00000000
-[10055.196248] [<8014de94>] (handle_irq_event_percpu) from [<8014df64>] (handle_irq_event+0x38/0x4c)
-[10055.205113] r5:80b56d50 r4:9d51dc00
-[10055.208697] [<8014df2c>] (handle_irq_event) from [<80151f1c>] (handle_level_irq+0xbc/0x12c)
-[10055.217037] r5:80b56d50 r4:9d51dc00
-[10055.220623] [<80151e60>] (handle_level_irq) from [<8014d4b8>] (generic_handle_irq+0x30/0x44)
-[10055.229052] r5:80b56d50 r4:00000017
-[10055.232648] [<8014d488>] (generic_handle_irq) from [<8014d524>] (__handle_domain_irq+0x58/0xb4)
-[10055.241356] [<8014d4cc>] (__handle_domain_irq) from [<801021e4>] (avic_handle_irq+0x68/0x70)
-[10055.249797] r9:015b6e60 r8:00c5387d r7:00c5387d r6:ffffffff r5:9dd33fb0 r4:9d402380
-[10055.257539] [<8010217c>] (avic_handle_irq) from [<80101e34>] (__irq_usr+0x54/0x80)
-[10055.265105] Exception stack(0x9dd33fb0 to 0x9dd33ff8)
-[10055.270152] 3fa0: 015d0530 00000000 00000000 015d0538
-[10055.278328] 3fc0: 015d0530 015b6e60 00000000 00000000 0052c5d0 015b6e60 7eff7910 7eff7918
-[10055.286496] 3fe0: 76ce5614 7eff7908 0050e2f4 76a3a08c 20000010 ffffffff
-[10055.293104] r5:20000010 r4:76a3a08c
-[10055.296673] handlers:
-[10055.298967] [<79f218a5>] irq_default_primary_handler threaded [<1de88514>] aspeed_video_irq
-[10055.307344] Disabling IRQ #23
-
-To fix this issue, this commit makes the interrupt handler clear
-these garbage interrupts. This driver enables and uses only
-COMP_COMPLETE interrupt.
-
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- drivers/media/platform/aspeed-video.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
-index 455c6af81236..0473f3141329 100644
---- a/drivers/media/platform/aspeed-video.c
-+++ b/drivers/media/platform/aspeed-video.c
-@@ -606,6 +606,16 @@ static irqreturn_t aspeed_video_irq(int irq, void *arg)
- aspeed_video_start_frame(video);
- }
-
-+ /*
-+ * CAPTURE_COMPLETE and FRAME_COMPLETE interrupts come even when these
-+ * are disabled in the VE_INTERRUPT_CTRL register so clear them to
-+ * prevent unnecessary interrupt calls.
-+ */
-+ if (sts & VE_INTERRUPT_CAPTURE_COMPLETE)
-+ sts &= ~VE_INTERRUPT_CAPTURE_COMPLETE;
-+ if (sts & VE_INTERRUPT_FRAME_COMPLETE)
-+ sts &= ~VE_INTERRUPT_FRAME_COMPLETE;
-+
- return sts ? IRQ_NONE : IRQ_HANDLED;
- }
-
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0082-ARM-dts-aspeed-g6-add-USB-virtual-hub-fixup.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0082-ARM-dts-aspeed-g6-add-USB-virtual-hub-fixup.patch
deleted file mode 100644
index f950c9262..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0082-ARM-dts-aspeed-g6-add-USB-virtual-hub-fixup.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From e0e33dfafe30f6dfb175caaf6be99aa9cbfe295a Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Wed, 20 Nov 2019 13:06:58 -0800
-Subject: [PATCH] ARM: dts: aspeed-g6: add USB virtual hub fixup
-
-This commit adds dt and pinctrl fixup for USB virtual hub.
-
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi | 5 +++++
- arch/arm/boot/dts/aspeed-g6.dtsi | 10 ++++++++++
- 2 files changed, 15 insertions(+)
-
-diff --git a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
-index 045ce66ca876..6ea66aaf9dd0 100644
---- a/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
-+++ b/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
-@@ -1112,6 +1112,11 @@
- groups = "UART9";
- };
-
-+ pinctrl_usb2adp_default: usb2adp_default {
-+ function = "USB2ADP";
-+ groups = "USBA";
-+ };
-+
- pinctrl_vb_default: vb_default {
- function = "VB";
- groups = "VB";
-diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
-index 33fcd89db6b8..b880e8e8f999 100644
---- a/arch/arm/boot/dts/aspeed-g6.dtsi
-+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
-@@ -272,6 +272,16 @@
- status = "disabled";
- };
-
-+ vhub: usb-vhub@1e6a0000 {
-+ compatible = "aspeed,ast2600-usb-vhub";
-+ reg = <0x1e6a0000 0x300>;
-+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
-+ clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_usb2adp_default>;
-+ status = "disabled";
-+ };
-+
- apb {
- compatible = "simple-bus";
- #address-cells = <1>;
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0083-usb-gadget-aspeed-add-ast2600-compatible-string.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0083-usb-gadget-aspeed-add-ast2600-compatible-string.patch
deleted file mode 100644
index 3f6f3ce91..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0083-usb-gadget-aspeed-add-ast2600-compatible-string.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From eedb53957b507bda2b9f6025149d2052e0598f76 Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Wed, 20 Nov 2019 12:49:46 -0800
-Subject: [PATCH] usb: gadget: aspeed: add ast2600 compatible string
-
-This commit adds "aspeed,ast2600-usb-vhub" compatible string to
-use it for AST2600 USB virtual hub driver. AST2600 support total 7
-downstream device ports so this driver should be modified later to
-support the additional ports.
-
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- drivers/usb/gadget/udc/aspeed-vhub/core.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
-index 90b134d..905e1cf 100644
---- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
-+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
-@@ -407,6 +407,9 @@ static const struct of_device_id ast_vhub_dt_ids[] = {
- {
- .compatible = "aspeed,ast2500-usb-vhub",
- },
-+ {
-+ .compatible = "aspeed,ast2600-usb-vhub",
-+ },
- { }
- };
- MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids);
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch
new file mode 100644
index 000000000..475e9611f
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch
@@ -0,0 +1,405 @@
+From e40f7d10d5306c075e2fc7e538ce1efc70eeb448 Mon Sep 17 00:00:00 2001
+From: ZhikuiRen <zhikui.ren@intel.com>
+Date: Thu, 9 Jan 2020 10:48:00 -0800
+Subject: [PATCH] Add peci-cpupower driver
+
+peci-cpupower reads CPU energy counter through peci
+and computes average power in mW since last read.
+
+Signed-off-by: ZhikuiRen <zhikui.ren@intel.com>
+---
+ Documentation/hwmon/index.rst | 1 +
+ Documentation/hwmon/peci-cpupower.rst | 52 ++++++++
+ arch/arm/configs/aspeed_g5_defconfig | 1 +
+ drivers/hwmon/Kconfig | 14 +++
+ drivers/hwmon/Makefile | 1 +
+ drivers/hwmon/peci-cpupower.c | 231 ++++++++++++++++++++++++++++++++++
+ drivers/mfd/intel-peci-client.c | 1 +
+ include/uapi/linux/peci-ioctl.h | 1 +
+ 8 files changed, 302 insertions(+)
+ create mode 100644 Documentation/hwmon/peci-cpupower.rst
+ create mode 100644 drivers/hwmon/peci-cpupower.c
+
+diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
+index 7d894c9..0bde0ef 100644
+--- a/Documentation/hwmon/index.rst
++++ b/Documentation/hwmon/index.rst
+@@ -130,6 +130,7 @@ Hardware Monitoring Kernel Drivers
+ pcf8591
+ peci-cputemp
+ peci-dimmtemp
++ peci-cpupower
+ pmbus
+ powr1220
+ pxe1610
+diff --git a/Documentation/hwmon/peci-cpupower.rst b/Documentation/hwmon/peci-cpupower.rst
+new file mode 100644
+index 0000000..4d7bd61
+--- /dev/null
++++ b/Documentation/hwmon/peci-cpupower.rst
+@@ -0,0 +1,52 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++Kernel driver peci-cpupower
++==========================
++
++:Copyright: |copy| 2018-2020 Intel Corporation
++
++Supported chips:
++ One of Intel server CPUs listed below which is connected to a PECI bus.
++ * Intel Xeon E5/E7 v3 server processors
++ Intel Xeon E5-14xx v3 family
++ Intel Xeon E5-24xx v3 family
++ Intel Xeon E5-16xx v3 family
++ Intel Xeon E5-26xx v3 family
++ Intel Xeon E5-46xx v3 family
++ Intel Xeon E7-48xx v3 family
++ Intel Xeon E7-88xx v3 family
++ * Intel Xeon E5/E7 v4 server processors
++ Intel Xeon E5-16xx v4 family
++ Intel Xeon E5-26xx v4 family
++ Intel Xeon E5-46xx v4 family
++ Intel Xeon E7-48xx v4 family
++ Intel Xeon E7-88xx v4 family
++ * Intel Xeon Scalable server processors
++ Intel Xeon D family
++ Intel Xeon Bronze family
++ Intel Xeon Silver family
++ Intel Xeon Gold family
++ Intel Xeon Platinum family
++
++ Addresses scanned: PECI client address 0x30 - 0x37
++ Datasheet: Available from http://www.intel.com/design/literature.htm
++
++Author:
++ Zhikui Ren <zhikui.ren@.intel.com>
++
++Description
++-----------
++
++This driver implements a generic PECI hwmon feature which provides
++average power consumption readings of the CPU package based on energy counter
++accessible using the PECI Client Command Suite via the processor PECI client.
++
++Power values are average power since last measure given in milli Watt and
++will be measurable only when the target CPU is powered on.
++
++``sysfs`` interface
++-------------------
++======================= =======================================================
++power1_average Provides average power since last read in milli Watt.
++power1_label Provides string "Average Power".
++======================= =======================================================
+diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
+index 1e589a0..0e50040 100644
+--- a/arch/arm/configs/aspeed_g5_defconfig
++++ b/arch/arm/configs/aspeed_g5_defconfig
+@@ -177,6 +177,7 @@ CONFIG_SENSORS_OCC_P8_I2C=y
+ CONFIG_SENSORS_OCC_P9_SBE=y
+ CONFIG_SENSORS_PECI_CPUTEMP=y
+ CONFIG_SENSORS_PECI_DIMMTEMP=y
++CONFIG_SENSORS_PECI_CPUPOWER=y
+ CONFIG_PMBUS=y
+ CONFIG_SENSORS_ADM1275=y
+ CONFIG_SENSORS_IBM_CFFPS=y
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 8312b37..07d8826 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -1361,6 +1361,20 @@ config SENSORS_PECI_DIMMTEMP
+ This driver can also be built as a module. If so, the module
+ will be called peci-dimmtemp.
+
++config SENSORS_PECI_CPUPOWER
++ tristate "PECI CPU power monitoring support"
++ depends on PECI
++ select MFD_INTEL_PECI_CLIENT
++ help
++ If you say yes here you get support for the generic Intel PECI
++ cputemp driver which provides average engergy
++ readings of the CPU package using
++ the PECI Client Command Suite via the processor PECI client.
++ Check Documentation/hwmon/peci-cpupower for details.
++
++ This driver can also be built as a module. If so, the module
++ will be called peci-cpupower.
++
+ source "drivers/hwmon/pmbus/Kconfig"
+
+ config SENSORS_PWM_FAN
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index e74ea92..fab43fd 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -144,6 +144,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
+ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+ obj-$(CONFIG_SENSORS_PECI_CPUTEMP) += peci-cputemp.o
+ obj-$(CONFIG_SENSORS_PECI_DIMMTEMP) += peci-dimmtemp.o
++obj-$(CONFIG_SENSORS_PECI_CPUPOWER) += peci-cpupower.o
+ obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
+ obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+ obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
+diff --git a/drivers/hwmon/peci-cpupower.c b/drivers/hwmon/peci-cpupower.c
+new file mode 100644
+index 0000000..6907696
+--- /dev/null
++++ b/drivers/hwmon/peci-cpupower.c
+@@ -0,0 +1,231 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018-2020 Intel Corporation
++
++#include <linux/hwmon.h>
++#include <linux/jiffies.h>
++#include <linux/mfd/intel-peci-client.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include "peci-hwmon.h"
++
++#define POWER_DEFAULT_CHANNEL_NUMS 1
++
++struct peci_cpupower {
++ struct peci_client_manager *mgr;
++ struct device *dev;
++ char name[PECI_NAME_SIZE];
++ const struct cpu_gen_info *gen_info;
++ struct peci_sensor_data energy;
++ long avg_power_val;
++ u64 core_mask;
++ u32 power_config[POWER_DEFAULT_CHANNEL_NUMS + 1];
++ uint config_idx;
++ struct hwmon_channel_info power_info;
++ const struct hwmon_channel_info *info[2];
++ struct hwmon_chip_info chip;
++};
++
++enum cpupower_channels {
++ average_power,
++};
++
++static const u32 config_table[POWER_DEFAULT_CHANNEL_NUMS] = {
++ /* average power */
++ HWMON_P_LABEL | HWMON_P_AVERAGE,
++};
++
++static const char *cpupower_label[POWER_DEFAULT_CHANNEL_NUMS] = {
++ "Average Power",
++};
++
++static int get_average_power(struct peci_cpupower *priv)
++{
++ u8 pkg_cfg[4];
++ int ret;
++
++ if (!peci_sensor_need_update(&priv->energy))
++ return 0;
++
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_TDP_UNITS,
++ PECI_PKG_ID_PKG_ENERGY_STATUS,
++ pkg_cfg);
++
++ u32 power_unit = ((le32_to_cpup((__le32 *)pkg_cfg)) & 0x1f00) >> 8;
++
++ dev_dbg(priv->dev, "cpupower units %d (1J/pow(2, unit))\n",
++ power_unit);
++
++ ret = peci_client_read_package_config(priv->mgr,
++ PECI_MBX_INDEX_ENERGY_COUNTER,
++ PECI_PKG_ID_PKG_ENERGY_STATUS,
++ pkg_cfg);
++ if (!ret) {
++ u32 energy_cnt = le32_to_cpup((__le32 *)pkg_cfg);
++ ulong jif = jiffies;
++ ulong elapsed = (jif - priv->energy.last_updated);
++ long power_val = 0;
++ /*
++ * Don't calculate average power for first counter read or
++ * counter wrapped around or last counter read was more than
++ * 60 minutes ago (jiffies did not wrap and power calculation
++ * does not overflow or underflow
++ */
++ if (priv->energy.last_updated > 0 &&
++ energy_cnt > priv->energy.value &&
++ (elapsed < (HZ * 3600))) {
++ power_val = (long)(energy_cnt - priv->energy.value)
++ / elapsed * HZ;
++ dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, raw powerValue %d scale to %d mW\n",
++ (long)(energy_cnt - priv->energy.value),
++ elapsed, power_val,
++ power_val >> (power_unit - 10));
++ } else {
++ dev_dbg(priv->dev, "countDiff %d, jiffes elapsed %d, skipping calculate power, try agin\n",
++ (long)(energy_cnt - priv->energy.value),
++ elapsed);
++ ret = -EAGAIN;
++ }
++
++ priv->energy.value = energy_cnt;
++ priv->avg_power_val = power_val >> ((power_unit - 10));
++ peci_sensor_mark_updated(&priv->energy);
++
++ dev_dbg(priv->dev, "energy counter 0x%8x, average power %dmW, jif %u, HZ is %d jiffies\n",
++ priv->energy.value, priv->avg_power_val,
++ jif, HZ);
++ }
++ return ret;
++}
++
++static int cpupower_read_string(struct device *dev,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel, const char **str)
++{
++ if (attr != hwmon_power_label)
++ return -EOPNOTSUPP;
++ if (channel >= POWER_DEFAULT_CHANNEL_NUMS)
++ return -EOPNOTSUPP;
++ *str = cpupower_label[channel];
++
++ return 0;
++}
++
++static int cpupower_read(struct device *dev,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel, long *val)
++{
++ struct peci_cpupower *priv = dev_get_drvdata(dev);
++ int ret;
++
++ if (channel >= POWER_DEFAULT_CHANNEL_NUMS ||
++ !(priv->power_config[channel] & BIT(attr)))
++ return -EOPNOTSUPP;
++
++ switch (attr) {
++ case hwmon_power_average:
++ switch (channel) {
++ case average_power:
++ ret = get_average_power(priv);
++ if (ret)
++ break;
++
++ *val = priv->avg_power_val;
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++ }
++
++ return ret;
++}
++
++static umode_t cpupower_is_visible(const void *data,
++ enum hwmon_sensor_types type,
++ u32 attr, int channel)
++{
++ const struct peci_cpupower *priv = data;
++
++ if (channel < POWER_DEFAULT_CHANNEL_NUMS ||
++ (priv->power_config[channel] & BIT(attr)))
++ return 0444;
++
++ return 0;
++}
++
++static const struct hwmon_ops cpupower_ops = {
++ .is_visible = cpupower_is_visible,
++ .read_string = cpupower_read_string,
++ .read = cpupower_read,
++};
++
++static int peci_cpupower_probe(struct platform_device *pdev)
++{
++ struct peci_client_manager *mgr = dev_get_drvdata(pdev->dev.parent);
++ struct device *dev = &pdev->dev;
++ struct peci_cpupower *priv;
++ struct device *hwmon_dev;
++
++ if ((mgr->client->adapter->cmd_mask &
++ (BIT(PECI_CMD_RD_PKG_CFG))) !=
++ (BIT(PECI_CMD_RD_PKG_CFG))) {
++ return -ENODEV;
++ }
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ dev_set_drvdata(dev, priv);
++ priv->mgr = mgr;
++ priv->dev = dev;
++ priv->gen_info = mgr->gen_info;
++
++ snprintf(priv->name, PECI_NAME_SIZE, "peci_cpupower.cpu%d",
++ mgr->client->addr - PECI_BASE_ADDR);
++
++ priv->power_config[priv->config_idx++] = config_table[average_power];
++
++ priv->chip.ops = &cpupower_ops;
++ priv->chip.info = priv->info;
++
++ priv->info[0] = &priv->power_info;
++
++ priv->power_info.type = hwmon_power;
++ priv->power_info.config = priv->power_config;
++
++ hwmon_dev = devm_hwmon_device_register_with_info(priv->dev,
++ priv->name,
++ priv,
++ &priv->chip,
++ NULL);
++
++ if (IS_ERR(hwmon_dev))
++ return PTR_ERR(hwmon_dev);
++
++ dev_dbg(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), priv->name);
++
++ return 0;
++}
++
++static const struct platform_device_id peci_cpupower_ids[] = {
++ { .name = "peci-cpupower", .driver_data = 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(platform, peci_cpupower_ids);
++
++static struct platform_driver peci_cpupower_driver = {
++ .probe = peci_cpupower_probe,
++ .id_table = peci_cpupower_ids,
++ .driver = { .name = KBUILD_MODNAME, },
++};
++module_platform_driver(peci_cpupower_driver);
++
++MODULE_AUTHOR("Zhikui Ren <zhikui.ren@intel.com>");
++MODULE_DESCRIPTION("PECI cpupower driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c
+index 9751b04..0c62ad6 100644
+--- a/drivers/mfd/intel-peci-client.c
++++ b/drivers/mfd/intel-peci-client.c
+@@ -21,6 +21,7 @@
+ static struct mfd_cell peci_functions[] = {
+ { .name = "peci-cputemp", },
+ { .name = "peci-dimmtemp", },
++ { .name = "peci-cpupower", },
+ };
+
+ static const struct cpu_gen_info cpu_gen_info_table[] = {
+diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h
+index 843930f..d16f7c9 100644
+--- a/include/uapi/linux/peci-ioctl.h
++++ b/include/uapi/linux/peci-ioctl.h
+@@ -231,6 +231,7 @@ struct peci_rd_pkg_cfg_msg {
+ #define PECI_PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */
+ #define PECI_PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */
+ #define PECI_PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */
++#define PECI_PKG_ID_PKG_ENERGY_STATUS 0x00ff /* Average Energy */
+
+ __u8 rx_len;
+ __u8 cc;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch
new file mode 100644
index 000000000..dd756edbe
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch
@@ -0,0 +1,136 @@
+From 879834a305bd5c0cbf3c60f8fe235cea8783fe35 Mon Sep 17 00:00:00 2001
+From: arun-pm <arun.p.m@linux.intel.com>
+Date: Tue, 3 Dec 2019 17:22:28 +0530
+Subject: [PATCH] SPI Quad IO driver support AST2600
+
+This commit adds spi driver quad io support for AST2600
+
+Note:- Removed n25q00 Quad I/O support for the time being due to clock issue
+ with chip 'Micron 8UA15 - rw182 (128MB)' while enabling Quad I/O mode.
+
+Signed-off-by: arun-pm <arun.p.m@linux.intel.com>
+---
+ drivers/mtd/spi-nor/aspeed-smc.c | 49 ++++++++++++++++++++++++++++++++++------
+ drivers/mtd/spi-nor/spi-nor.c | 7 +++++-
+ 2 files changed, 48 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
+index 0805dcab8cb1..305c1940e822 100644
+--- a/drivers/mtd/spi-nor/aspeed-smc.c
++++ b/drivers/mtd/spi-nor/aspeed-smc.c
+@@ -21,6 +21,11 @@
+ #include <linux/sysfs.h>
+
+ #define DEVICE_NAME "aspeed-smc"
++#define AST2600A0 0x05000303
++#define AST2600A0_MAX_FREQ 50000000
++#define AST2600A0_SAFE_FREQ 40000000
++#define AST_MAX_FREQ 100000000
++#define AST2600_REVISION_ID_SCU 0x1e6e2004
+
+ /*
+ * The driver only support SPI flash
+@@ -542,6 +547,10 @@ static int aspeed_smc_get_io_mode(struct aspeed_smc_chip *chip)
+ return CONTROL_IO_DUAL_DATA;
+ case SNOR_PROTO_1_2_2:
+ return CONTROL_IO_DUAL_ADDR_DATA;
++ case SNOR_PROTO_1_1_4:
++ return CONTROL_IO_QUAD_DATA;
++ case SNOR_PROTO_1_4_4:
++ return CONTROL_IO_QUAD_ADDR_DATA;
+ default:
+ dev_err(chip->nor.dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+@@ -573,7 +582,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from,
+ aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy));
+
+ /* Set IO mode only for data */
+- if (io_mode == CONTROL_IO_DUAL_DATA)
++ if (io_mode == CONTROL_IO_DUAL_DATA || io_mode == CONTROL_IO_QUAD_DATA)
+ aspeed_smc_set_io_mode(chip, io_mode);
+
+ aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len);
+@@ -1222,20 +1231,35 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
+ return 0;
+ }
+
++static void aspeed_allowed_max_freq(struct aspeed_smc_chip *chip)
++{
++ void __iomem *scu_ast_revision_id = ioremap(AST2600_REVISION_ID_SCU, 4);
++ u32 rev_id = readl(scu_ast_revision_id);
++
++ /*Limit max spi frequency less than 50MHz on AST2600-A0 due
++ * to FWSPICLK signal quality issue.
++ */
++ if(rev_id == AST2600A0 && chip->clk_rate >= AST2600A0_MAX_FREQ)
++ chip->clk_rate = AST2600A0_SAFE_FREQ;
++}
++
++static u32 get_hwcaps(unsigned int tx_width){
++ if(tx_width == 4)
++ return SNOR_HWCAPS_READ_1_1_4;
++ else
++ return SNOR_HWCAPS_READ_1_1_2;
++}
++
+ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
+ struct device_node *np, struct resource *r)
+ {
+- const struct spi_nor_hwcaps hwcaps = {
+- .mask = SNOR_HWCAPS_READ |
+- SNOR_HWCAPS_READ_FAST |
+- SNOR_HWCAPS_READ_1_1_2 |
+- SNOR_HWCAPS_PP,
+- };
++ struct spi_nor_hwcaps hwcaps;
+ const struct aspeed_smc_info *info = controller->info;
+ struct device *dev = controller->dev;
+ struct device_node *child;
+ unsigned int cs;
+ int ret = -ENODEV;
++ unsigned int spi_tx_width;
+
+ for_each_available_child_of_node(np, child) {
+ struct aspeed_smc_chip *chip;
+@@ -1276,9 +1300,20 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
+ &chip->clk_rate)) {
+ chip->clk_rate = ASPEED_SPI_DEFAULT_FREQ;
+ }
++ aspeed_allowed_max_freq(chip);
+ dev_info(dev, "Using %d MHz SPI frequency\n",
+ chip->clk_rate / 1000000);
+
++ if (of_property_read_u32(child, "spi-tx-bus-width",
++ &spi_tx_width)) {
++ spi_tx_width = 2;
++ }
++ dev_info(dev, "tx width: %ld\n", spi_tx_width);
++
++ hwcaps.mask = SNOR_HWCAPS_READ |
++ SNOR_HWCAPS_READ_FAST |
++ get_hwcaps(spi_tx_width) |
++ SNOR_HWCAPS_PP;
+ chip->controller = controller;
+ chip->ctl = controller->regs + info->ctl0 + cs * 4;
+ chip->cs = cs;
+diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
+index 19fe44b0965a..c69ef8b56700 100644
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -2310,7 +2310,12 @@ static const struct flash_info spi_nor_ids[] = {
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
++ /* Removed n25q00 Quad I/O support for the time being due to clock issue with chip 'Micron 8UA15 - rw182 (128MB)'
++ * while enabling Quad I/O mode. As this chip is default shipped in platforms, marking it
++ * as Not supported for the time being. Once all chips are replaced with the new model, this can be enabled
++ * back(Note:- Certain other chips having same name(n25q00) but different part number has no issues).
++ */
++ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | NO_CHIP_ERASE) },
+ { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch
new file mode 100644
index 000000000..4b3b6b838
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch
@@ -0,0 +1,37 @@
+From 8be7c34e78bd09fa95ce9972332c8c2bb950ec03 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 28 Jan 2020 16:14:07 -0800
+Subject: [PATCH] ipmi: ipmb_dev_int: add quick fix for raw I2C type
+ registration
+
+This commit adds quick fix for cases of run time registration
+through sysfs. It should be fixed later by adding parsing code for
+ipmb_id instead.
+
+This is a temporary fix. Do not upstream it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/char/ipmi/ipmb_dev_int.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c
+index 382e4a1df510..c5db37266724 100644
+--- a/drivers/char/ipmi/ipmb_dev_int.c
++++ b/drivers/char/ipmi/ipmb_dev_int.c
+@@ -328,8 +328,12 @@ static int ipmb_probe(struct i2c_client *client,
+ if (ret)
+ return ret;
+
++#if 1 /* FIXME: Quick fix. Need to add parsing code for ipmb_id instead */
++ ipmb_dev->is_i2c_protocol = true;
++#else
+ ipmb_dev->is_i2c_protocol
+ = device_property_read_bool(&client->dev, "i2c-protocol");
++#endif
+
+ ipmb_dev->client = client;
+ i2c_set_clientdata(client, ipmb_dev);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Report-link-statistics-for-the-NCSI-channel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch
index 7e38110af..3e426edcd 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Report-link-statistics-for-the-NCSI-channel.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch
@@ -1,20 +1,23 @@
-From b08fba62b18ecb04d3e7dafac6bd819dd9b90d35 Mon Sep 17 00:00:00 2001
+From f280c15c79e7d13e4a59d413a3091eb21b56dd92 Mon Sep 17 00:00:00 2001
From: Johnathan Mantey <johnathanx.mantey@intel.com>
-Date: Thu, 1 Aug 2019 11:29:41 -0700
-Subject: [PATCH] Report link statistics for the NCSI channel
+Date: Mon, 27 Jan 2020 09:03:56 -0800
+Subject: [PATCH] Return link speed and duplex settings for the NCSI channel
-The ftgmac driver does not report the link statistics for the NCSI
-channel used for the shared NICs attached to the BMC. Report a fixed
-value for the NSCI interface.
+The ftgmac100_open function initializes state for the NCSI
+channel. The get link settings function does not return this
+data. This caused the link speed, and the duplex value to be returned
+incorrectly by the PHY driver (0 Mbps, and duplex off).
+
+Update the driver to return either the PHY settings when not using
+NCSI, or the NCSI values that were assigned when the driver is opened.
-Change-Id: Idb65ca1ce07f06a883417ee44df30ea2c8483107
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
---
drivers/net/ethernet/faraday/ftgmac100.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
-index 2e5fba354412..b1eb3abe759b 100644
+index 8ed85037f021..a53878eecfc8 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1218,10 +1218,30 @@ static int ftgmac100_set_pauseparam(struct net_device *netdev,
@@ -31,8 +34,8 @@ index 2e5fba354412..b1eb3abe759b 100644
+ if (phydev) {
+ phy_ethtool_ksettings_get(phydev, cmd);
+ } else if (priv->use_ncsi) {
-+ cmd->base.speed = SPEED_100;
-+ cmd->base.duplex = DUPLEX_FULL;
++ cmd->base.speed = priv->cur_speed;
++ cmd->base.duplex = priv->cur_duplex;
+ cmd->base.autoneg = 0;
+ } else {
+ retval = -ENODEV;
@@ -50,5 +53,5 @@ index 2e5fba354412..b1eb3abe759b 100644
.nway_reset = phy_ethtool_nway_reset,
.get_ringparam = ftgmac100_get_ringparam,
--
-2.7.4
+2.24.1
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch
new file mode 100644
index 000000000..e2196c629
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch
@@ -0,0 +1,40 @@
+From 7555448ab0676ea974ef67ef0c8ebe5d68b73d25 Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Tue, 18 Feb 2020 14:17:22 -0800
+Subject: [PATCH] Fix truncated WrEndPointConfig MMIO command
+
+When address type is 6, the driver is reducing the msg buffer to
+the base size and truncating the additional command data.
+
+This removes the line that sets the msg buffer size to the base
+size. The correct buffer size is already set.
+
+Tested:
+Ran this command:
+peci_cmds WrEndpointConfigMMIO 6 0 0 0x7e 0x1a 0x0 0x224e0 0x5f5a56
+
+and got the full buffer in the driver log:
+[ 795.207278] peci_aspeed 1e78b000.peci-bus: HEAD : 0x00011730
+[ 795.212980] TX : c5 00 05 00 00 00 06 00 d0 7e e0 24 02 00 00 00 .........~.$....
+[ 795.220556] TX : 00 00 56 5a 5f 00 a8 ..VZ_..
+
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ drivers/peci/peci-core.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
+index 9aedb74..efb73b0 100644
+--- a/drivers/peci/peci-core.c
++++ b/drivers/peci/peci-core.c
+@@ -1040,7 +1040,6 @@ static int peci_cmd_wr_end_pt_cfg(struct peci_adapter *adapter, void *vmsg)
+ >> 24); /* MSB - DWORD Register Offset */
+ if (umsg->params.mmio.addr_type ==
+ PECI_ENDPTCFG_ADDR_TYPE_MMIO_Q) {
+- msg->tx_len = PECI_WRENDPTCFG_MMIO_Q_WRITE_LEN_BASE;
+ msg->tx_buf[14] = (u8)(umsg->params.mmio.offset
+ >> 32); /* Register Offset */
+ msg->tx_buf[15] = (u8)(umsg->params.mmio.offset
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg
new file mode 100644
index 000000000..bbc7fa5b6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/debug.cfg
@@ -0,0 +1,2 @@
+CONFIG_DEVMEM = y
+CONFIG_DEVMEM_BOOTPARAM = n
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/intel.cfg
index 714f40bfd..5f453510a 100644
--- 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
@@ -12,6 +12,7 @@ CONFIG_PECI_CHARDEV=y
CONFIG_PECI_ASPEED=y
CONFIG_SENSORS_PECI_CPUTEMP=y
CONFIG_SENSORS_PECI_DIMMTEMP=y
+CONFIG_SENSORS_PECI_CPUPOWER=y
CONFIG_CONFIGFS_FS=y
CONFIG_BLK_DEV_RAM_SIZE=49152
CONFIG_MAGIC_SYSRQ=y
@@ -85,3 +86,4 @@ CONFIG_USB_DYNAMIC_MINORS=n
CONFIG_USB_EHCI_HCD=n
CONFIG_USB_EHCI_ROOT_HUB_TT=n
CONFIG_USB_EHCI_HCD_PLATFORM=n
+CONFIG_IPMB_DEVICE_INTERFACE=y