From 82dbc15a05125a812c140a3c8cff81c366482229 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" Date: Mon, 7 Dec 2020 13:45:20 -0800 Subject: Update to internal 0.26 Signed-off-by: Jason M. Bills --- ...m-dts-add-DTS-for-Intel-ast2500-platforms.patch | 510 ------ ...m-dts-add-DTS-for-Intel-ast2600-platforms.patch | 563 ------- .../0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch | 212 --- .../0001-arm-dts-intel-s2600wf-dts-fixups.patch | 477 ------ .../0002-Add-Aspeed-fmc-spi-driver.patch | 645 ------- ...le-pass-through-on-GPIOE1-and-GPIOE3-free.patch | 173 -- ...GPIOE0-and-GPIOE2-pass-through-by-default.patch | 70 - ...w-monitoring-of-power-control-input-GPIOs.patch | 123 -- ...aspeed-pwm-tacho-change-default-fan-speed.patch | 28 - .../0014-arm-dts-aspeed-g5-add-espi.patch | 31 - .../0015-New-flash-map-for-intel.patch | 117 -- .../0016-Add-ASPEED-SGPIO-driver.patch | 760 --------- .../0017-SGPIO-DT-and-pinctrl-fixup.patch | 227 --- .../linux-aspeed/0019-Add-I2C-IPMB-support.patch | 425 ----- .../0020-misc-aspeed-add-lpc-mbox-driver.patch | 491 ------ ...021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch | 580 ------- .../0022-Add-AST2500-eSPI-driver.patch | 762 --------- .../0028-Add-AST2500-JTAG-driver.patch | 95 -- ...0030-Add-dump-debug-code-into-I2C-drivers.patch | 145 -- ...Add-high-speed-baud-rate-support-for-UART.patch | 135 -- ...ed-Add-Aspeed-UART-routing-control-driver.patch | 559 ------ ...m-dts-aspeed-Swap-the-mac-nodes-numbering.patch | 85 - ...35-Implement-a-memory-driver-share-memory.patch | 245 --- ...d-PWM-driver-which-uses-FTTMR010-timer-IP.patch | 514 ------ .../0040-i2c-Add-mux-hold-unhold-msg-types.patch | 488 ------ ...eout-ms-and-retries-device-tree-propertie.patch | 105 -- ...dd-clock-control-logic-into-Aspeed-LPC-BT.patch | 154 -- ...ock-control-logic-into-Aspeed-LPC-SNOOP-d.patch | 139 -- ...dd-clock-control-logic-into-Aspeed-LPC-KC.patch | 273 --- ...error-printing-on-probe-defer-case-in-Asp.patch | 43 - ...-Suppress-excessive-HID-gadget-error-logs.patch | 52 - .../0051-Add-AST2500-JTAG-device.patch | 67 - .../0052-drivers-jtag-Add-JTAG-core-driver.patch | 920 ---------- ...dd-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch | 1780 -------------------- ...entation-jtag-Add-bindings-for-Aspeed-SoC.patch | 107 -- ...-Documentation-jtag-Add-ABI-documentation.patch | 310 ---- ...on-jtag-Add-JTAG-core-driver-ioctl-number.patch | 57 - ...ers-jtag-Add-JTAG-core-driver-Maintainers.patch | 50 - ...c-aspeed-add-buffer-mode-transfer-support.patch | 1148 ------------- ...-i2c-aspeed-add-DMA-mode-transfer-support.patch | 491 ------ .../0063-i2c-aspeed-add-general-call-support.patch | 180 -- ...-set-idle-disconnect-to-true-in-all-cases.patch | 34 - .../0068-i2c-aspeed-add-H-W-timeout-support.patch | 191 --- ...add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch | 50 - ...-temporary-fix-for-gpiochip-range-setting.patch | 44 - .../0072-pmbus-add-fault-and-beep-attributes.patch | 88 - ...-IO-statistics-to-USB-Mass-storage-gadget.patch | 155 -- ...-Refine-initialization-flow-in-I2C-driver.patch | 64 - ...-ast2600-add-pwm_tacho-driver-from-aspeed.patch | 1107 ------------ ...soc-aspeed-Add-read-only-property-support.patch | 47 - ...NCSI-driver-issue-caused-by-host-shutdown.patch | 70 - ...-i2c-aspeed-filter-garbage-interrupts-out.patch | 56 - .../0084-ARM-dts-aspeed-g6-add-GFX-node.patch | 35 - .../0085-drm-add-AST2600-GFX-support.patch | 105 -- .../0086-ADC-linux-driver-for-AST2600.patch | 271 --- .../0086-ARM-dts-aspeed-g6-add-video-node.patch | 36 - ...d-add-aspeed-ast2600-video-engine-compati.patch | 63 - .../0088-clk-ast2600-enable-ESPICLK-always.patch | 30 - ...-ast2600-enable-high-speed-uart-in-kernel.patch | 97 -- .../linux-aspeed/0090-peci-cpupower-driver-1.patch | 405 ----- .../0092-SPI-Quad-IO-driver-support-AST2600.patch | 136 -- ...ev_int-add-quick-fix-for-raw-I2C-type-reg.patch | 37 - ...-speed-and-duplex-settings-for-the-NCSI-c.patch | 57 - ...5-pwm-and-tach-driver-changes-for-ast2600.patch | 783 --------- ...x-truncated-WrEndPointConfig-MMIO-command.patch | 40 - ...-Mailbox-Enabling-interrupt-based-mailbox.patch | 237 --- .../0101-Add-poll-fops-in-eSPI-driver.patch | 151 -- ...Fix-for-dirty-node-in-jffs2-summary-entry.patch | 94 -- .../linux-aspeed/0103-Refine-clock-settings.patch | 129 -- ...0104-Add-chip-unique-id-reading-interface.patch | 215 --- ...speed-fix-arbitration-loss-handling-logic.patch | 38 - .../linux-aspeed/0106-enable-AST2600-I3C.patch | 910 ---------- ...7-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch | 79 - ...-mctp-Add-initial-driver-for-ast2600-mctp.patch | 1265 -------------- ...fix-illegal-array-access-in-binding-with-.patch | 75 - ...Unconditionally-calculate-the-PECI-AW-FCS.patch | 73 - .../0112-AST2600-enable-UART-routing.patch | 45 - .../0116-watchdog-aspeed-fix-AST2600-support.patch | 68 - ...aw-PECI-response-to-user-space-on-timeout.patch | 54 - ...culate-AW-FCS-on-WrEndPointConfig-command.patch | 34 - .../recipes-kernel/linux/linux-aspeed/intel.cfg | 2 + .../recipes-kernel/linux/linux-aspeed_%.bbappend | 85 +- 82 files changed, 8 insertions(+), 21883 deletions(-) delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0111-Unconditionally-calculate-the-PECI-AW-FCS.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0112-AST2600-enable-UART-routing.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch delete mode 100644 meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux') 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 deleted file mode 100644 index 088e1a02b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch +++ /dev/null @@ -1,510 +0,0 @@ -From 7ad89fd032d56cc20622d34cf9d0d09adacb2796 Mon Sep 17 00:00:00 2001 -From: Yuan Li -Date: Tue, 19 Sep 2017 15:55:39 +0800 -Subject: [PATCH] arm: dts: add DTS for Intel ast2500 platforms - -Add the DTS file for Intel ast2500-based systems. - -Signed-off-by: Yuan Li -Signed-off-by: Yong Li -Signed-off-by: James Feist -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Jason M. Bills -Signed-off-by: Zhu, Yunge -Signed-off-by: Qiang XU -Signed-off-by: Chen Yugang -Signed-off-by: Zhikui Ren -Signed-off-by: jayaprakash Mutyala -Signed-off-by: AppaRao Puli -Signed-off-by: Arun P. Mohanan ---- - .../arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 477 ++++++++++++++++++ - 1 file changed, 477 insertions(+) - create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts - -diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts -new file mode 100644 -index 000000000000..7a09ca54f161 ---- /dev/null -+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts -@@ -0,0 +1,477 @@ -+/dts-v1/; -+ -+#include "aspeed-g5.dtsi" -+#include -+#include -+ -+/ { -+ model = "Intel AST2500 BMC"; -+ compatible = "intel,ast2500-bmc", "aspeed,ast2500"; -+ -+ aliases { -+ serial4 = &uart5; -+ }; -+ -+ chosen { -+ stdout-path = &uart5; -+ bootargs = "console=ttyS4,115200 earlyprintk"; -+ }; -+ -+ memory@80000000 { -+ reg = <0x80000000 0x20000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ vga_memory: framebuffer@7f000000 { -+ no-map; -+ reg = <0x7f000000 0x01000000>; -+ }; -+ -+ gfx_memory: framebuffer { -+ size = <0x01000000>; -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ -+ video_engine_memory: jpegbuffer { -+ size = <0x02000000>; /* 32M */ -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ -+ ramoops@9eff0000{ -+ compatible = "ramoops"; -+ reg = <0x9eff0000 0x10000>; -+ record-size = <0x2000>; -+ console-size = <0x2000>; -+ }; -+ }; -+ -+ vga-shared-memory { -+ compatible = "aspeed,ast2500-vga-sharedmem"; -+ reg = <0x9ff00000 0x100000>; -+ }; -+ -+ iio-hwmon { -+ compatible = "iio-hwmon"; -+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, -+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>, -+ <&adc 8>, <&adc 9>, <&adc 10>, <&adc 11>, -+ <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ identify { -+ default-state = "on"; -+ gpios = <&gpio ASPEED_GPIO(S, 6) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_amber { -+ default-state = "off"; -+ gpios = <&gpio ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_green { -+ default-state = "keep"; -+ gpios = <&gpio ASPEED_GPIO(S, 4) GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ beeper { -+ compatible = "pwm-beeper"; -+ pwms = <&timer 6 1000000 0>; -+ }; -+}; -+ -+&fmc { -+ status = "okay"; -+ flash@0 { -+ status = "okay"; -+ m25p,fast-read; -+#include "openbmc-flash-layout-intel-64MB.dtsi" -+ }; -+}; -+ -+&espi { -+ status = "okay"; -+}; -+ -+&jtag { -+ status = "okay"; -+}; -+ -+&peci0 { -+ status = "okay"; -+ gpios = <&gpio ASPEED_GPIO(F, 6) 0>; -+}; -+ -+&syscon { -+ uart-clock-high-speed; -+ status = "okay"; -+ -+ misc_control { -+ compatible = "aspeed,bmc-misc"; -+ uart_port_debug { -+ offset = <0x2c>; -+ bit-mask = <0x1>; -+ bit-shift = <10>; -+ read-only; -+ }; -+ p2a-bridge { -+ offset = <0x180>; -+ bit-mask = <0x1>; -+ bit-shift = <1>; -+ read-only; -+ }; -+ boot-2nd-flash { -+ offset = <0x70>; -+ bit-mask = <0x1>; -+ bit-shift = <17>; -+ read-only; -+ }; -+ chip_id { -+ offset = <0x150>; -+ bit-mask = <0x0fffffff 0xffffffff>; -+ bit-shift = <0>; -+ read-only; -+ reg-width = <64>; -+ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474"; -+ }; -+ }; -+}; -+ -+&adc { -+ status = "okay"; -+}; -+ -+&gpio { -+ status = "okay"; -+ gpio-line-names = -+ /*A0-A7*/ "","","","","","","","", -+ /*B0-B7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","","","", -+ /*C0-C7*/ "","","","","","","","", -+ /*D0-D7*/ "","","","","","","","", -+ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","DEBUG_EN_N","","", -+ /*F0-F7*/ "NMI_OUT","","","","CPU_ERR0","CPU_ERR1","PLTRST_N","PRDY_N", -+ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","LCP_ENTER_BUTTON","LCP_LEFT_BUTTON","FM_BMC_BOARD_SKU_ID5_N","","", -+ /*H0-H7*/ "","","","FM_NODE_ID_1","FM_NODE_ID_2","FM_NODE_ID_3","FM_NODE_ID_4","FM_240VA_STATUS", -+ /*I0-I7*/ "FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N","FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","", -+ /*J0-J7*/ "","","","","","","","", -+ /*K0-K7*/ "","","","","","","","", -+ /*L0-L7*/ "","","","","","","","", -+ /*M0-M7*/ "","","","","","","","", -+ /*N0-N7*/ "","","","","","","","", -+ /*O0-O7*/ "","","","","","","","", -+ /*P0-P7*/ "","","","","","","","", -+ /*Q0-Q7*/ "","","","","","","","PWR_DEBUG_N", -+ /*R0-R7*/ "","XDP_PRST_N","","","","","","CHASSIS_INTRUSION", -+ /*S0-S7*/ "REMOTE_DEBUG_ENABLE","SYSPWROK","RSMRST_N","","","","","", -+ /*T0-T7*/ "","","","","","","","", -+ /*U0-U7*/ "","","","","","","","", -+ /*V0-V7*/ "","","","","","","","", -+ /*W0-W7*/ "","","","","","","","", -+ /*X0-X7*/ "","","","","","","","", -+ /*Y0-Y7*/ "SIO_S3","SIO_S5","","SIO_ONCONTROL","","","","", -+ /*Z0-Z7*/ "","SIO_POWER_GOOD","","","","","","", -+ /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE", -+ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","", -+ /*AC0-AC7*/ "","","","","","","",""; -+}; -+ -+&sgpio { -+ status = "okay"; -+ gpio-line-names = -+ /* SGPIO output lines */ -+ /*OA0-OA7*/ "","","","","","","","", -+ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT", -+ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT", -+ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT", -+ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT", -+ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT", -+ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT", -+ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT", -+ /*OI0-OI7*/ "","","","","","","","", -+ /*OJ0-OJ7*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", -+ -+ /* SGPIO input lines */ -+ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_ABCD_VRHOT","CPU1_MEM_EFGH_VRHOT","","", -+ /*IB0-IB7*/ "CPU1_MISMATCH","CPU1_MEM_THERM_EVENT","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT", -+ /*IC0-IC7*/ "","","CPU2_MISMATCH","CPU2_MEM_THERM_EVENT","","","","", -+ /*ID0-ID7*/ "","","","","","","","", -+ /*IE0-IE7*/ "","","","","","","","", -+ /*IF0-IF7*/ "SGPIO_PLD_MINOR_REV_BIT0","SGPIO_PLD_MINOR_REV_BIT1","SGPIO_PLD_MINOR_REV_BIT2","SGPIO_PLD_MINOR_REV_BIT3","SGPIO_PLD_MAJOR_REV_BIT0","SGPIO_PLD_MAJOR_REV_BIT1","SGPIO_PLD_MAJOR_REV_BIT2","SGPIO_PLD_MAJOR_REV_BIT3", -+ /*IG0-IG7*/ "MAIN_PLD_MINOR_REV_BIT0","MAIN_PLD_MINOR_REV_BIT1","MAIN_PLD_MINOR_REV_BIT2","MAIN_PLD_MINOR_REV_BIT3","MAIN_PLD_MAJOR_REV_BIT0","MAIN_PLD_MAJOR_REV_BIT1","MAIN_PLD_MAJOR_REV_BIT2","MAIN_PLD_MAJOR_REV_BIT3", -+ /*IH0-IH7*/ "","","","","","","","", -+ /*II0-II7*/ "","","","","","","","", -+ /*IJ0-IJ7*/ "","","","","","","",""; -+}; -+ -+&kcs3 { -+ kcs_addr = <0xCA2>; -+ status = "okay"; -+}; -+ -+&kcs4 { -+ kcs_addr = <0xCA4>; -+ status = "okay"; -+}; -+ -+&sio_regs { -+ status = "okay"; -+ sio_status { -+ offset = <0x8C>; -+ bit-mask = <0x1F>; -+ bit-shift = <4>; -+ }; -+}; -+ -+&lpc_sio { -+ status = "okay"; -+}; -+ -+&lpc_snoop { -+ snoop-ports = <0x80>; -+ status = "okay"; -+}; -+ -+&mbox { -+ status = "okay"; -+}; -+ -+&uart_routing { -+ status = "okay"; -+}; -+ -+/** -+ * SAFS through SPI1 is available only on Wilson Point. -+ * These pins are used as fan presence checking gpios in WFP -+ * so commenting it out for now. -+ * &spi1 { -+ * status = "okay"; -+ * -+ * flash@0 { -+ * m25p,fast-read; -+ * status = "okay"; -+ * }; -+ *}; -+ */ -+ -+&uart1 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_txd1_default -+ &pinctrl_rxd1_default -+ &pinctrl_nrts1_default -+ &pinctrl_ndtr1_default -+ &pinctrl_ndsr1_default -+ &pinctrl_ncts1_default -+ &pinctrl_ndcd1_default -+ &pinctrl_nri1_default>; -+}; -+ -+&uart2 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_txd2_default -+ &pinctrl_rxd2_default -+ &pinctrl_nrts2_default -+ &pinctrl_ndtr2_default -+ &pinctrl_ndsr2_default -+ &pinctrl_ncts2_default -+ &pinctrl_ndcd2_default -+ &pinctrl_nri2_default>; -+}; -+ -+&uart3 { -+ status = "okay"; -+}; -+ -+&uart4 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <>; -+}; -+ -+&uart5 { -+ status = "okay"; -+}; -+ -+&mac1 { -+ status = "okay"; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; -+}; -+ -+&mac0 { -+ status = "okay"; -+ use-ncsi; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_rmii1_default>; -+}; -+ -+&i2c0 { -+ multi-master; -+ general-call; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c2 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c3 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c4 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c5 { -+ bus-frequency = <1000000>; -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c6 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c7 { -+ multi-master; -+ #retries = <3>; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c9 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c11 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&i2c13 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ -+&gfx { -+ status = "okay"; -+ memory-region = <&gfx_memory>; -+}; -+ -+&vuart { -+ status = "okay"; -+}; -+ -+&pwm_tacho { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default -+ &pinctrl_pwm2_default &pinctrl_pwm3_default -+ &pinctrl_pwm4_default &pinctrl_pwm5_default -+ &pinctrl_pwm6_default &pinctrl_pwm7_default>; -+ -+ fan@0 { -+ reg = <0x00>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x00 0x01>; -+ }; -+ fan@1 { -+ reg = <0x01>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x02 0x03>; -+ }; -+ fan@2 { -+ reg = <0x02>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x04 0x05>; -+ }; -+ fan@3 { -+ reg = <0x03>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x06 0x07>; -+ }; -+ fan@4 { -+ reg = <0x04>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x08 0x09>; -+ }; -+ fan@5 { -+ reg = <0x05>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0A 0x0B>; -+ }; -+ fan@6 { -+ reg = <0x06>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0C 0x0D>; -+ }; -+ fan@7 { -+ reg = <0x07>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0E 0x0F>; -+ }; -+ -+}; -+ -+&timer { -+/* -+ * Available settings: -+ * fttmr010,pwm-outputs = <5>, <6>, <7>, <8>; -+ * pinctrl-0 = <&pinctrl_timer5_default &pinctrl_timer6_default -+ * &pinctrl_timer7_default &pinctrl_timer8_default>; -+ */ -+ fttmr010,pwm-outputs = <6>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_timer6_default>; -+ #pwm-cells = <3>; -+ status = "okay"; -+}; -+ -+&video { -+ status = "okay"; -+ memory-region = <&video_engine_memory>; -+}; -+ -+&vhub { -+ status = "okay"; -+}; --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch deleted file mode 100644 index 6e58657ec..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch +++ /dev/null @@ -1,563 +0,0 @@ -From eeecdb993d9e5dbf8cb45eb11ad367e9eb67018d Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Tue, 19 Sep 2017 15:55:39 +0800 -Subject: [PATCH] arm: dts: add DTS for Intel ast2600 platforms - -Add the DTS file for Intel ast2600-based systems. - -Signed-off-by: Vernon Mauery -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Chen Yugang -Signed-off-by: Kuiying Wang -Signed-off-by: arun-pm -Signed-off-by: Ayushi Smriti -Signed-off-by: Arun P. Mohanan -Signed-off-by: Iwona Winiarska ---- - .../arm/boot/dts/aspeed-bmc-intel-ast2600.dts | 534 ++++++++++++++++++ - 1 file changed, 534 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..e9cea7b63836 ---- /dev/null -+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2600.dts -@@ -0,0 +1,534 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/dts-v1/; -+ -+#include "aspeed-g6.dtsi" -+#include -+#include -+ -+/ { -+ model = "AST2600 EVB"; -+ compatible = "aspeed,ast2600"; -+ -+ chosen { -+ stdout-path = &uart5; -+ bootargs = "console=ttyS4,115200n8 root=/dev/ram rw init=/linuxrc earlyprintk"; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x80000000 0x40000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ gfx_memory: framebuffer { -+ size = <0x01000000>; -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ -+ video_engine_memory: jpegbuffer { -+ size = <0x02000000>; /* 32M */ -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ video_memory: video { -+ size = <0x04000000>; -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ no-map; -+ }; -+ }; -+ -+ iio-hwmon { -+ compatible = "iio-hwmon"; -+ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>, -+ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>, -+ <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>, -+ <&adc1 4>, <&adc1 5>, <&adc1 6>, <&adc1 7>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ identify { -+ default-state = "off"; -+ gpios = <&gpio1 ASPEED_GPIO(B, 7) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_amber { -+ default-state = "off"; -+ gpios = <&gpio1 ASPEED_GPIO(G, 3) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_green { -+ default-state = "keep"; -+ gpios = <&gpio1 ASPEED_GPIO(G, 2) GPIO_ACTIVE_LOW>; -+ }; -+ }; -+/* -+ beeper { -+ compatible = "pwm-beeper"; -+ pwms = <&timer 7 1000000 0>; -+ }; */ -+}; -+ -+&fmc { -+ status = "okay"; -+ flash@0 { -+ status = "okay"; -+ spi-max-frequency = <50000000>; -+ spi-tx-bus-width = <4>; -+ m25p,fast-read; -+#include "openbmc-flash-layout-intel-64MB.dtsi" -+ }; -+}; -+ -+&espi { -+ status = "okay"; -+}; -+ -+&mctp { -+ status = "okay"; -+}; -+ -+&peci0 { -+ status = "okay"; -+ gpios = <&gpio0 ASPEED_GPIO(F, 6) 0>; -+}; -+ -+&syscon { -+ uart-clock-high-speed; -+ status = "okay"; -+ -+ misc_control { -+ compatible = "aspeed,bmc-misc"; -+ chip_id { -+ offset = <0x5b0>; -+ bit-mask = <0xffffffff 0xffffffff>; -+ bit-shift = <0>; -+ read-only; -+ reg-width = <64>; -+ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474"; -+ }; -+ }; -+}; -+ -+#if 0 -+ GPIO Alias: (runtime alias -> schematic name) -+ ID_BUTTON -> FP_ID_BTN_N -+ CPU_CATERR -> FM_PLT_BMC_THERMTRIP_N -+ PCH_BMC_THERMTRIP -> FM_PLT_BMC_THERMTRIP_N -+ RESET_BUTTON -> FP_BMC_RST_BTN_N -+ RESET_OUT -> RST_BMC_RSTBTN_OUT_R_N -+ POWER_BUTTON -> FP_BMC_PWR_BTN_R_N -+ POWER_OUT -> FM_BMC_PWR_BTN_N -+ PREQ_N -> DBP_ASD_BMC_PREQ_R_N -+ POST_COMPLETE -> FM_BIOS_POST_CMPLT_BMC_N -+ CPU_ERR0 -> FM_CPU_ERR0_LVT3_N -+ CPU_ERR1 -> FM_CPU_ERR1_LVT3_N -+ CPU_ERR2 -> FM_CPU_ERR2_LVT3_N -+ DEBUG_EN_N -> FM_JTAG_TCK_MUX_SEL_R -+ NMI_OUT -> IRQ_BMC_CPU_NMI_R -+ PLTRST_N -> RST_PLTRST_BMC_N -+ PRDY_N -> DBP_ASD_BMC_PRDY_R_N -+ PWR_DEBUG_N -> -+ XDP_PRST_N -> -+ SYSPWROK -> -+ RSMRST_N -> -+ SIO_S3 -> FM_SLPS3_R_N -+ SIO_S5 -> FM_SLPS4_R_N -+ SIO_ONCONTROL -> FM_BMC_ONCTL_R_N -+ SIO_POWER_GOOD -> PWRGD_CPU0_LVC3_R -+ PS_PWROK -> PWRGD_BMC_PS_PWROK_R -+ P3VBAT_BRIDGE_EN -> -+ TCK_MUX_SEL -> -+ SMI -> IRQ_SMI_ACTIVE_BMC_N -+ NMI_BUTTON -> FP_NMI_BTN_N -+#endif -+&gpio0 { -+ status = "okay"; -+ /* Enable GPIOP0 and GPIOP2 pass-through by default */ -+ /* pinctrl-names = "pass-through"; -+ pinctrl-0 = <&pinctrl_thru0_default -+ &pinctrl_thru1_default>; */ -+ gpio-line-names = -+ /*A0-A7*/ "","","","","SMB_CPU_PIROM_SCL","SMB_CPU_PIROM_SDA","SMB_IPMB_STBY_LVC3_R_SCL","SMB_IPMB_STBY_LVC3_R_SDA", -+ /*B0-B7*/ "FM_1200VA_OC","NMI_OUT","IRQ_SMB3_M2_ALERT_N","","RGMII_BMC_RMM4_LVC3_R_MDC","RGMII_BMC_RMM4_LVC3_R_MDIO","FM_BMC_BMCINIT_R","FP_ID_LED_N", -+ /*C0-C7*/ "FM_FORCE_BMC_UPDATE_N","RST_RGMII_PHYRST_N","FM_TPM_EN_PULSE","FM_BMC_CRASHLOG_TRIG_N","IRQ_BMC_PCH_NMI_R","FM_CPU1_DISABLE_COD_N","FM_4S_8S_N_MODE","FM_STANDALONE_MODE_N", -+ /*D0-D7*/ "CPU_ERR0","CPU_ERR1","CPU_ERR2","PRDY_N","FM_SPD_SWITCH_CTRL_N","","","", -+ /*E0-E7*/ "FM_SKT1_FAULT_LED","FM_SKT0_FAULT_LED","CLK_50M_CKMNG_BMCB","FM_BMC_BOARD_REV_ID2_N","","","","", -+ /*F0-F7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","FM_BMC_BOARD_SKU_ID5_N","ID_BUTTON","PS_PWROK", -+ /*G0-G7*/ "FM_SMB_BMC_NVME_LVC3_ALERT_N","RST_BMC_I2C_M2_R_N","FP_LED_STATUS_GREEN_N","FP_LED_STATUS_AMBER_N","FM_BMC_BOARD_REV_ID0_N","FM_BMC_BOARD_REV_ID1_N","FM_BMC_CPU_FBRK_OUT_R_N","DBP_PRESENT_IN_R2_N", -+ /*H0-H7*/ "SGPIO_BMC_CLK_R","SGPIO_BMC_LD_R","SGPIO_BMC_DOUT_R","SGPIO_BMC_DIN","PLTRST_N","CPU_CATERR","PCH_BMC_THERMTRIP","", -+ /*I0-I7*/ "JTAG_ASD_NTRST_R_N","JTAG_ASD_TDI_R","JTAG_ASD_TCK_R","JTAG_ASD_TMS_R","JTAG_ASD_TDO","FM_BMC_PWRBTN_OUT_R_N","FM_BMC_PWR_BTN_N","", -+ /*J0-J7*/ "SMB_CHASSENSOR_STBY_LVC3_SCL","SMB_CHASSENSOR_STBY_LVC3_SDA","FM_NODE_ID0","FM_NODE_ID1","","","","", -+ /*K0-K7*/ "SMB_HSBP_STBY_LVC3_R_SCL","SMB_HSBP_STBY_LVC3_R_SDA","SMB_SMLINK0_STBY_LVC3_R2_SCL","SMB_SMLINK0_STBY_LVC3_R2_SDA","SMB_TEMPSENSOR_STBY_LVC3_R_SCL","SMB_TEMPSENSOR_STBY_LVC3_R_SDA","SMB_PMBUS_SML1_STBY_LVC3_R_SCL","SMB_PMBUS_SML1_STBY_LVC3_R_SDA", -+ /*L0-L7*/ "SMB_PCIE_STBY_LVC3_R_SCL","SMB_PCIE_STBY_LVC3_R_SDA","SMB_HOST_STBY_BMC_LVC3_R_SCL","SMB_HOST_STBY_BMC_LVC3_R_SDA","PREQ_N","TCK_MUX_SEL","V_BMC_GFX_HSYNC_R","V_BMC_GFX_VSYNC_R", -+ /*M0-M7*/ "SPA_CTS_N","SPA_DCD_N","SPA_DSR_N","PU_SPA_RI_N","SPA_DTR_N","SPA_RTS_N","SPA_SOUT","SPA_SIN", -+ /*N0-N7*/ "SPB_CTS_N","SPB_DCD_N","SPB_DSR_N","PU_SPB_RI_N","SPB_DTR_N","SPB_RTS_N","SPB_SOUT","SPB_SIN", -+ /*O0-O7*/ "FAN_BMC_PWM0","FAN_BMC_PWM1","FAN_BMC_PWM2","FAN_BMC_PWM3","FAN_BMC_PWM4","FAN_BMC_PWM5","NMI_BUTTON","SPEAKER_BMC_R", -+ /*P0-P7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","FAN_BMC_PWM6","FAN_BMC_PWM7","FAN_BMC_PWM8","FAN_BMC_PWM9", -+ /*Q0-Q7*/ "FAN_BMC_TACH0","FAN_BMC_TACH1","FAN_BMC_TACH2","FAN_BMC_TACH3","FAN_BMC_TACH4","FAN_BMC_TACH5","FAN_BMC_TACH6","FAN_BMC_TACH7", -+ /*R0-R7*/ "FAN_BMC_TACH8","FAN_BMC_TACH9","","","","","","", -+ /*S0-S7*/ "RST_BMC_PCIE_MUX_N","FM_BMC_EUP_LOT6_N","","","","A_P3V_BAT_SCALED_EN","REMOTE_DEBUG_ENABLE","FM_PCHHOT_N", -+ /*T0-T7*/ "A_P12V_PSU_SCALED","A_P12V_AUX_SCALED","A_P3V3_SCALED","A_P5V_SCALED","A_PVNN_PCH_AUX_SENSOR","A_P1V05_PCH_AUX_SENSOR","A_P1V8_AUX_SENSOR","A_P3V_BAT_SCALED", -+ /*U0-U7*/ "A_PVCCIN_CPU0_SENSOR","A_PVCCIN_CPU1_SENSOR","A_PVCCINFAON_CPU0_SENSOR","A_PVCCINFAON_CPU1_SENSOR","A_PVCCFA_EHV_FIVRA_CPU0_SENSOR","A_PVCCFA_EHV_FIVRA_CPU1_SENSOR","A_PVCCD_HV_CPU0_SENSOR","A_PVCCD_HV_CPU1_SENSOR", -+ /*V0-V7*/ "SIO_S3","SIO_S5","TP_BMC_SIO_PWREQ_N","SIO_ONCONTROL","SIO_POWER_GOOD","LED_BMC_HB_LED_N","FM_BMC_SUSACK_N","", -+ /*W0-W7*/ "LPC_LAD0_ESPI_R_IO0","LPC_LAD1_ESPI_R_IO1","LPC_LAD2_ESPI_R_IO2","LPC_LAD3_ESPI_R_IO3","CLK_24M_66M_LPC0_ESPI_BMC","LPC_LFRAME_N_ESPI_CS0_BMC_N","IRQ_LPC_SERIRQ_ESPI_ALERT_N","RST_LPC_LRST_ESPI_RST_BMC_R_N", -+ /*X0-X7*/ "","SMI","POST_COMPLETE","","","","","", -+ /*Y0-Y7*/ "","IRQ_SML0_ALERT_BMC_R2_N","","IRQ_SML1_PMBUS_BMC_ALERT_N","SPI_BMC_BOOT_R_IO2","SPI_BMC_BOOT_R_IO3","PU_SPI_BMC_BOOT_ABR","PU_SPI_BMC_BOOT_WP_N", -+ /*Z0-Z7*/ "PWRGD_P3V3_RISER1","PWRGD_P3V3_RISER2","","HW_STRAP_5","HW_STRAP_6","HW_STRAP_7","HW_STRAP_2","HW_STRAP_3"; -+}; -+ -+&gpio1 { -+ status = "disabled"; -+ gpio-line-names = /* GPIO18 A-E */ -+ /*A0-A7*/ "","","RST_EMMC_BMC_R_N","FM_SYS_FAN6_PRSNT_D_N","FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N", -+ /*B0-B7*/ "FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","FM_SYS_FAN7_PRSNT_D_N","RGMII_BMC_RMM4_TX_R_CLK","RGMII_BMC_RMM4_TX_R_CTRL","RGMII_BMC_RMM4_R_TXD0","RGMII_BMC_RMM4_R_TXD1", -+ /*C0-C7*/ "RGMII_BMC_RMM4_R_TXD2","RGMII_BMC_RMM4_R_TXD3","RGMII_BMC_RMM4_RX_CLK","RGMII_BMC_RMM4_RX_CTRL","RGMII_BMC_RMM4_RXD0","RGMII_BMC_RMM4_RXD1","RGMII_BMC_RMM4_RXD2","RGMII_BMC_RMM4_RXD3", -+ /*D0-D7*/ "EMMC_BMC_R_CLK","EMMC_BMC_R_CMD","EMMC_BMC_R_DATA0","EMMC_BMC_R_DATA1","EMMC_BMC_R_DATA2","EMMC_BMC_R_DATA3","EMMC_BMC_CD_N","EMMC_BMC_WP_N", -+ /*E0-E3*/ "EMMC_BMC_R_DATA4","EMMC_BMC_R_DATA5","EMMC_BMC_R_DATA6","EMMC_BMC_R_DATA7"; -+}; -+ -+&sgpio { -+ status = "okay"; -+ gpio-line-names = -+ /* SGPIO output lines */ -+ /*OA0-OA7*/ "","","","","","","","", -+ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT", -+ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT", -+ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT", -+ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT", -+ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT", -+ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT", -+ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT", -+ /*OI0-OI7*/ "","","","","","","","", -+ /*OJ0-OJ7*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", -+ -+ /* SGPIO input lines */ -+/* SGPIO Alias: (runtime alias -> net name) -+ CPU1_PRESENCE -> FM_CPU0_SKTOCC_LVT3_N -+ CPU1_THERMTRIP -> H_CPU0_THERMTRIP_LVC1_N -+ CPU1_VRHOT -> IRQ_CPU0_VRHOT_N -+ CPU1_FIVR_FAULT -> EV_MON_FAIL_CPU0_N -+ CPU1_MEM_VRHOT -> IRQ_CPU0_MEM_VRHOT_N -+ CPU1_MEM_THERM_EVENT -> H_CPU0_MEMHOT_OUT_LVC1_N -+ CPU1_MISMATCH -> FM_CPU0_MISMATCH -+ CPU2_PRESENCE -> FM_CPU1_SKTOCC_LVT3_N -+ CPU2_THERMTRIP -> H_CPU1_THERMTRIP_LVC1_N -+ CPU2_VRHOT -> IRQ_CPU1_VRHOT_N -+ CPU2_FIVR_FAULT -> EV_MON_FAIL_CPU1_N -+ CPU2_MEM_VRHOT -> IRQ_CPU1_MEM_VRHOT_N -+ CPU2_MEM_THERM_EVENT -> H_CPU1_MEMHOT_OUT_LVC1_N -+ CPU2_MISMATCH -> FM_CPU1_MISMATCH -+*/ -+ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_VRHOT","CPU1_MEM_THERM_EVENT","FM_CPU0_PROC_ID0","FM_CPU0_PROC_ID1", -+ /*IB0-IB7*/ "CPU1_MISMATCH","IRQ_PSYS_CRIT_N","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU1_MEM_VRHOT","CPU2_MEM_THERM_EVENT", -+ /*IC0-IC7*/ "FM_CPU1_PROC_ID0","FM_CPU1_PROC_ID1","CPU2_MISMATCH","","","","","", -+ /*ID0-ID7*/ "","","","","","","","", -+ /*IE0-IE7*/ "","","","","","","","CPU1_CPLD_CRC_ERROR", -+ /*IF0-IF7*/ "CPU2_CPLD_CRC_ERROR","","","","","","","", -+ /*IG0-IG7*/ "MAIN_PLD_MINOR_REV_BIT0","MAIN_PLD_MINOR_REV_BIT1","MAIN_PLD_MINOR_REV_BIT2","MAIN_PLD_MINOR_REV_BIT3","MAIN_PLD_MAJOR_REV_BIT0","MAIN_PLD_MAJOR_REV_BIT1","MAIN_PLD_MAJOR_REV_BIT2","MAIN_PLD_MAJOR_REV_BIT3", -+ /*IH0-IH7*/ "","WMEMX_PWR_FLT","WCPUX_MEM_PWR_FLT","PWRGD_P3V3_FF","WPSU_PWR_FLT","","","WPCH_PWR_FLT", -+ /*II0-II7*/ "FM_CPU0_PKGID0","FM_CPU0_PKGID1","FM_CPU0_PKGID2","H_CPU0_MEMTRIP_LVC1_N","FM_CPU1_PKGID0","FM_CPU1_PKGID1","FM_CPU1_PKGID2","H_CPU1_MEMTRIP_LVC1_N", -+ /*IJ0-IJ7*/ "","","","","","","",""; -+}; -+ -+&kcs3 { -+ kcs_addr = <0xCA2>; -+ status = "okay"; -+}; -+ -+&kcs4 { -+ kcs_addr = <0xCA4>; -+ status = "okay"; -+}; -+ -+&sio_regs { -+ status = "okay"; -+ sio_status { -+ offset = <0x8C>; -+ bit-mask = <0x1F>; -+ bit-shift = <4>; -+ }; -+}; -+ -+&lpc_sio { -+ status = "okay"; -+}; -+ -+&lpc_snoop { -+ snoop-ports = <0x80>; -+ status = "okay"; -+}; -+ -+&mbox { -+ status = "okay"; -+}; -+ -+&mdio1 { -+ status = "okay"; -+ -+ ethphy1: ethernet-phy@0 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ }; -+}; -+ -+&mac1 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_rgmii2_default>; -+ clocks = <&syscon ASPEED_CLK_GATE_MAC2CLK>, -+ <&syscon ASPEED_CLK_MAC2RCLK>; -+ clock-names = "MACCLK", "RCLK"; -+ phy-mode = "rgmii"; -+ phy-handle = <ðphy1>; -+}; -+ -+&mdio2 { -+ status = "okay"; -+ -+ ethphy2: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ }; -+}; -+ -+&adc0 { -+ status = "okay"; -+}; -+ -+&adc1 { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; -+ pinctrl-0 = <&pinctrl_txd1_default -+ &pinctrl_rxd1_default -+ &pinctrl_nrts1_default -+ &pinctrl_ndtr1_default -+ &pinctrl_ndsr1_default -+ &pinctrl_ncts1_default -+ &pinctrl_ndcd1_default -+ &pinctrl_nri1_default>; -+}; -+ -+&uart2 { -+ status = "okay"; -+ pinctrl-0 = <&pinctrl_txd2_default -+ &pinctrl_rxd2_default -+ &pinctrl_nrts2_default -+ &pinctrl_ndtr2_default -+ &pinctrl_ndsr2_default -+ &pinctrl_ncts2_default -+ &pinctrl_ndcd2_default -+ &pinctrl_nri2_default>; -+}; -+ -+&uart3 { -+ status = "okay"; -+ pinctrl-0 = <>; -+}; -+ -+&uart4 { -+ status = "okay"; -+ pinctrl-0 = <>; -+}; -+ -+&uart5 { -+ status = "okay"; -+ // Workaround for A0 -+ compatible = "snps,dw-apb-uart"; -+}; -+ -+&uart_routing { -+ status = "okay"; -+}; -+ -+&emmc_controller{ -+ status = "okay"; -+}; -+ -+&emmc { -+ non-removable; -+ bus-width = <4>; -+ max-frequency = <52000000>; -+}; -+ -+&i2c0 { -+ /* SMB_CHASSENSOR_STBY_LVC3 */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c4 { -+ /* SMB_HSBP_STBY_LVC3_R */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c5 { -+ /* SMB_SMLINK0_STBY_LVC3_R2 */ -+ bus-frequency = <1000000>; -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c6 { -+ /* SMB_TEMPSENSOR_STBY_LVC3_R */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c7 { -+ /* SMB_PMBUS_SML1_STBY_LVC3_R */ -+ multi-master; -+ #retries = <3>; -+ status = "okay"; -+}; -+ -+&i2c8 { -+ /* SMB_PCIE_STBY_LVC3_R */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c9 { -+ /* SMB_HOST_STBY_BMC_LVC3_R */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c12 { -+ /* SMB_CPU_PIROM */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i2c13 { -+ /* SMB_IPMB_STBY_LVC3_R */ -+ multi-master; -+ status = "okay"; -+}; -+ -+&i3cglobal { -+ status = "okay"; -+}; -+ -+&i3c0 { -+ /* I3C_SPD_DDRABCD_CPU0_BMC */ -+ status = "okay"; -+}; -+ -+&i3c1 { -+ /* I3C_SPD_DDREFGH_CPU0_BMC */ -+ status = "okay"; -+}; -+ -+&i3c2 { -+ /* I3C_SPD_DDRABCD_CPU1_BMC */ -+ status = "okay"; -+}; -+ -+&i3c3 { -+ /* I3C_SPD_DDREFGH_CPU1_BMC */ -+ status = "okay"; -+}; -+ -+&gfx { -+ status = "okay"; -+ memory-region = <&gfx_memory>; -+}; -+ -+&pcieh { -+ status = "okay"; -+}; -+ -+&pwm_tacho { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_tach0_default -+ &pinctrl_pwm1_default &pinctrl_tach1_default -+ &pinctrl_pwm2_default &pinctrl_tach2_default -+ &pinctrl_pwm3_default &pinctrl_tach3_default -+ &pinctrl_pwm4_default &pinctrl_tach4_default -+ &pinctrl_pwm5_default &pinctrl_tach5_default -+ &pinctrl_pwm12g1_default &pinctrl_tach6_default -+ &pinctrl_pwm13g1_default &pinctrl_tach7_default -+ &pinctrl_pwm14g1_default &pinctrl_tach8_default -+ &pinctrl_pwm15g1_default &pinctrl_tach9_default>; /*pwm 6-11 used for some other functionality*/ -+ -+ fan@0 { -+ reg = <0x00>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x00>; -+ }; -+ fan@1 { -+ reg = <0x01>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x01>; -+ }; -+ fan@2 { -+ reg = <0x02>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x02>; -+ }; -+ fan@3 { -+ reg = <0x03>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x03>; -+ }; -+ fan@4 { -+ reg = <0x04>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x04>; -+ }; -+ fan@5 { -+ reg = <0x05>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x05>; -+ }; -+ fan@6 { -+ reg = <0x0c>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x06>; -+ }; -+ fan@7 { -+ reg = <0x0d>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x07>; -+ }; -+ fan@8 { -+ reg = <0x0e>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x08>; -+ }; -+ fan@9 { -+ reg = <0x0f>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x09>; -+ }; -+}; -+ -+&video { -+ status = "okay"; -+ memory-region = <&video_engine_memory>; -+}; -+ -+&vhub { -+ status = "okay"; -+}; -+ -+&jtag1 { -+ status = "okay"; -+}; -+ -+&wdt2 { -+ status = "okay"; -+}; --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch deleted file mode 100644 index d75229a15..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 5e5758fe5929766a9b4677b86f9343a777526fe8 Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Thu, 12 Sep 2019 15:55:39 +0800 -Subject: [PATCH] arm: dts: base aspeed g6 dtsi fixups - -Additions to the base g6 dtsi file for Aspeed ast2600 systems. -This mostly includes entries for the drivers that are not upstream. - -Signed-off-by: Vernon Mauery ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 129 +++++++++++++++++++++++++++++- - include/dt-bindings/clock/ast2600-clock.h | 8 ++ - 2 files changed, 135 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 2af9efa1faa1..54add29d8217 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -28,6 +28,12 @@ - i2c13 = &i2c13; - i2c14 = &i2c14; - i2c15 = &i2c15; -+ i3c0 = &i3c0; -+ i3c1 = &i3c1; -+ i3c2 = &i3c2; -+ i3c3 = &i3c3; -+ i3c4 = &i3c4; -+ i3c5 = &i3c5; - serial0 = &uart1; - serial1 = &uart2; - serial2 = &uart3; -@@ -297,11 +303,21 @@ - quality = <100>; - }; - -+ adc: adc@1e6e9000 { -+ compatible = "aspeed,ast2500-adc"; -+ reg = <0x1e6e9000 0x100>; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ interrupts = ; -+ resets = <&syscon ASPEED_RESET_ADC>; -+ #io-channel-cells = <1>; -+ status = "disabled"; -+ }; -+ - gpio0: gpio@1e780000 { - #gpio-cells = <2>; - gpio-controller; - compatible = "aspeed,ast2600-gpio"; -- reg = <0x1e780000 0x800>; -+ reg = <0x1e780000 0x200>; - interrupts = ; - gpio-ranges = <&pinctrl 0 0 208>; - ngpios = <208>; -@@ -314,7 +330,7 @@ - #gpio-cells = <2>; - gpio-controller; - compatible = "aspeed,ast2600-gpio"; -- reg = <0x1e780800 0x800>; -+ reg = <0x1e780800 0x200>; - interrupts = ; - gpio-ranges = <&pinctrl 0 208 36>; - ngpios = <36>; -@@ -398,6 +414,13 @@ - ranges = <0x0 0x1e78b000 0x100>; - }; - -+ i3c: bus@1e7a0000 { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0x1e7a0000 0x8000>; -+ }; -+ - lpc: lpc@1e789000 { - compatible = "aspeed,ast2600-lpc", "simple-mfd"; - reg = <0x1e789000 0x1000>; -@@ -486,6 +509,20 @@ - sio_regs: regs { - compatible = "aspeed,bmc-misc"; - }; -+ -+ lpc_sio: lpc-sio@100 { -+ compatible = "aspeed,ast2500-lpc-sio"; -+ reg = <0x100 0x20>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ -+ mbox: mbox@180 { -+ compatible = "aspeed,ast2600-mbox"; -+ reg = <0x180 0x5c>; -+ interrupts = ; -+ #mbox-cells = <1>; -+ }; - }; - }; - -@@ -871,3 +908,91 @@ - status = "disabled"; - }; - }; -+ -+&i3c { -+ i3c0: i3c0@2000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x2000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C0>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ i3c1: i3c1@3000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x3000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C1>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ i3c2: i3c2@4000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x4000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C2>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i3c3_default>; -+ status = "disabled"; -+ }; -+ -+ i3c3: i3c3@5000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x5000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C3>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i3c4_default>; -+ status = "disabled"; -+ }; -+ -+ i3c4: i3c4@6000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x6000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C4>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i3c5_default>; -+ status = "disabled"; -+ }; -+ -+ i3c5: i3c5@7000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x7000 0x1000>; -+ compatible = "snps,dw-i3c-master-1.00a"; -+ clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_I3C5>; -+ bus-frequency = <100000>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i3c6_default>; -+ status = "disabled"; -+ }; -+}; -diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h -index 62b9520a00fd..3d90582a813f 100644 ---- a/include/dt-bindings/clock/ast2600-clock.h -+++ b/include/dt-bindings/clock/ast2600-clock.h -@@ -91,6 +91,14 @@ - /* Only list resets here that are not part of a gate */ - #define ASPEED_RESET_ADC 55 - #define ASPEED_RESET_JTAG_MASTER2 54 -+#define ASPEED_RESET_I3C7 47 -+#define ASPEED_RESET_I3C6 46 -+#define ASPEED_RESET_I3C5 45 -+#define ASPEED_RESET_I3C4 44 -+#define ASPEED_RESET_I3C3 43 -+#define ASPEED_RESET_I3C2 42 -+#define ASPEED_RESET_I3C1 41 -+#define ASPEED_RESET_I3C0 40 - #define ASPEED_RESET_I3C_DMA 39 - #define ASPEED_RESET_PWM 37 - #define ASPEED_RESET_PECI 36 --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch deleted file mode 100644 index d88fc2383..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0001-arm-dts-intel-s2600wf-dts-fixups.patch +++ /dev/null @@ -1,477 +0,0 @@ -From 92c28f515166e4478dd447eb1d33409d14aed954 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 7 Jul 2020 22:27:10 -0700 -Subject: [PATCH] arm: dts: intel s2600wf dts fixups - -Add fixups for Intel S2600WF dts. - -Signed-off-by: Jae Hyun Yoo ---- - .../arm/boot/dts/aspeed-bmc-intel-s2600wf.dts | 362 +++++++++++++++++- - 1 file changed, 343 insertions(+), 19 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts -index 1deb30ec912c..daa85e947d48 100644 ---- a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts -+++ b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts -@@ -3,14 +3,20 @@ - /dts-v1/; - - #include "aspeed-g5.dtsi" -+#include -+#include - - / { -- model = "S2600WF BMC"; -+ model = "Intel S2600WF BMC"; - compatible = "intel,s2600wf-bmc", "aspeed,ast2500"; - -+ aliases { -+ serial4 = &uart5; -+ }; -+ - chosen { - stdout-path = &uart5; -- bootargs = "earlyprintk"; -+ bootargs = "console=ttyS4,115200 earlyprintk"; - }; - - memory@80000000 { -@@ -26,6 +32,32 @@ - no-map; - reg = <0x7f000000 0x01000000>; - }; -+ -+ gfx_memory: framebuffer { -+ size = <0x01000000>; -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ -+ video_engine_memory: jpegbuffer { -+ size = <0x02000000>; /* 32M */ -+ alignment = <0x01000000>; -+ compatible = "shared-dma-pool"; -+ reusable; -+ }; -+ -+ ramoops@9eff0000{ -+ compatible = "ramoops"; -+ reg = <0x9eff0000 0x10000>; -+ record-size = <0x2000>; -+ console-size = <0x2000>; -+ }; -+ }; -+ -+ vga-shared-memory { -+ compatible = "aspeed,ast2500-vga-sharedmem"; -+ reg = <0x9ff00000 0x100000>; - }; - - iio-hwmon { -@@ -36,6 +68,29 @@ - <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>; - }; - -+ leds { -+ compatible = "gpio-leds"; -+ -+ identify { -+ default-state = "on"; -+ gpios = <&gpio ASPEED_GPIO(S, 6) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_amber { -+ default-state = "off"; -+ gpios = <&gpio ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>; -+ }; -+ -+ status_green { -+ default-state = "keep"; -+ gpios = <&gpio ASPEED_GPIO(S, 4) GPIO_ACTIVE_LOW>; -+ }; -+ }; -+ -+ beeper { -+ compatible = "pwm-beeper"; -+ pwms = <&timer 5 1000000 0>; -+ }; - }; - - &fmc { -@@ -44,35 +99,204 @@ - status = "okay"; - m25p,fast-read; - label = "bmc"; --#include "openbmc-flash-layout.dtsi" -+#include "openbmc-flash-layout-intel-64MB.dtsi" - }; - }; - --&spi1 { -+&espi { - status = "okay"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_spi1_default>; -+}; - -- flash@0 { -- status = "okay"; -- m25p,fast-read; -- label = "pnor"; -+&jtag { -+ status = "okay"; -+}; -+ -+&peci0 { -+ status = "okay"; -+ gpios = <&gpio ASPEED_GPIO(F, 6) 0>; -+}; -+ -+&syscon { -+ uart-clock-high-speed; -+ status = "okay"; -+ -+ misc_control { -+ compatible = "aspeed,bmc-misc"; -+ uart_port_debug { -+ offset = <0x2c>; -+ bit-mask = <0x1>; -+ bit-shift = <10>; -+ read-only; -+ }; -+ p2a-bridge { -+ offset = <0x180>; -+ bit-mask = <0x1>; -+ bit-shift = <1>; -+ read-only; -+ }; -+ boot-2nd-flash { -+ offset = <0x70>; -+ bit-mask = <0x1>; -+ bit-shift = <17>; -+ read-only; -+ }; -+ chip_id { -+ offset = <0x150>; -+ bit-mask = <0x0fffffff 0xffffffff>; -+ bit-shift = <0>; -+ read-only; -+ reg-width = <64>; -+ hash-data = "d44f9b804976fa23c2e25d62f16154d26520a7e24c5555095fd1b55c027804f1570dcd16189739c640cd7d9a6ce14944a2c4eaf1dc429eed6940e8a83498a474"; -+ }; - }; - }; - --&uart5 { -+&adc { - status = "okay"; - }; - --&mac0 { -+&gpio { -+ status = "okay"; -+ /* Enable GPIOE0 and GPIOE2 pass-through by default */ -+ pinctrl-names = "pass-through"; -+ pinctrl-0 = <&pinctrl_gpie0_default -+ &pinctrl_gpie2_default>; -+ gpio-line-names = -+ /*A0-A7*/ "","","","","","","","", -+ /*B0-B7*/ "","","","","","","","", -+ /*C0-C7*/ "","","","","","","","", -+ /*D0-D7*/ "","","","","","","","", -+ /*E0-E7*/ "RESET_BUTTON","RESET_OUT","POWER_BUTTON","POWER_OUT","","","","", -+ /*F0-F7*/ "NMI_OUT","","","","CPU_ERR0","CPU_ERR1","","", -+ /*G0-G7*/ "CPU_ERR2","CPU_CATERR","PCH_BMC_THERMTRIP","LCP_ENTER_BUTTON","LCP_LEFT_BUTTON","FM_BMC_BOARD_SKU_ID5_N","","", -+ /*H0-H7*/ "","","","FM_NODE_ID_1","FM_NODE_ID_2","FM_NODE_ID_3","FM_NODE_ID_4","FM_240VA_STATUS", -+ /*I0-I7*/ "FM_SYS_FAN0_PRSNT_D_N","FM_SYS_FAN1_PRSNT_D_N","FM_SYS_FAN2_PRSNT_D_N","FM_SYS_FAN3_PRSNT_D_N","FM_SYS_FAN4_PRSNT_D_N","FM_SYS_FAN5_PRSNT_D_N","","", -+ /*J0-J7*/ "","","","","","","","", -+ /*K0-K7*/ "","","","","","","","", -+ /*L0-L7*/ "","","","","","","","", -+ /*M0-M7*/ "","","","","","","","", -+ /*N0-N7*/ "","","","","","","","", -+ /*O0-O7*/ "","","","","","","","", -+ /*P0-P7*/ "","","","","","","","", -+ /*Q0-Q7*/ "","","","","","","","PWR_DEBUG_N", -+ /*R0-R7*/ "","XDP_PRST_N","","","","","","CHASSIS_INTRUSION", -+ /*S0-S7*/ "REMOTE_DEBUG_ENABLE","SYSPWROK","RSMRST_N","","","","","", -+ /*T0-T7*/ "","","","","","","","", -+ /*U0-U7*/ "","","","","","","","", -+ /*V0-V7*/ "","","","","","","","", -+ /*W0-W7*/ "","","","","","","","", -+ /*X0-X7*/ "","","","","","","","", -+ /*Y0-Y7*/ "SIO_S3","SIO_S5","","SIO_ONCONTROL","","","","", -+ /*Z0-Z7*/ "","SIO_POWER_GOOD","","","","","","", -+ /*AA0-AA7*/ "P3VBAT_BRIDGE_EN","","","","PREQ_N","TCK_MUX_SEL","SMI","POST_COMPLETE", -+ /*AB0-AB7*/ "","NMI_BUTTON","ID_BUTTON","PS_PWROK","","","","", -+ /*AC0-AC7*/ "","","","","","","",""; -+}; -+ -+&sgpio { - status = "okay"; -+ gpio-line-names = -+ /* SGPIO output lines */ -+ /*OA0-OA7*/ "","","","","","","","", -+ /*OB0-OB7*/ "LED_CPU1_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU1_CH2_DIMM1_FAULT","LED_CPU1_CH2_DIMM2_FAULT","LED_CPU1_CH3_DIMM1_FAULT","LED_CPU1_CH3_DIMM2_FAULT","LED_CPU1_CH4_DIMM1_FAULT","LED_CPU1_CH4_DIMM2_FAULT", -+ /*OC0-OC7*/ "LED_CPU1_CH5_DIMM1_FAULT","LED_CPU1_CH5_DIMM2_FAULT","LED_CPU1_CH6_DIMM1_FAULT","LED_CPU1_CH6_DIMM2_FAULT","LED_FAN1_FAULT","LED_FAN2_FAULT","LED_FAN3_FAULT","LED_FAN4_FAULT", -+ /*OD0-OD7*/ "LED_FAN5_FAULT","LED_FAN6_FAULT","LED_FAN7_FAULT","LED_FAN8_FAULT","LED_CPU2_CH1_DIMM1_FAULT","LED_CPU1_CH1_DIMM2_FAULT","LED_CPU2_CH2_DIMM1_FAULT","LED_CPU2_CH2_DIMM2_FAULT", -+ /*OE0-OE7*/ "LED_CPU2_CH3_DIMM1_FAULT","LED_CPU2_CH3_DIMM2_FAULT","LED_CPU2_CH4_DIMM1_FAULT","LED_CPU2_CH4_DIMM2_FAULT","LED_CPU2_CH5_DIMM1_FAULT","LED_CPU2_CH5_DIMM2_FAULT","LED_CPU2_CH6_DIMM1_FAULT","LED_CPU2_CH6_DIMM2_FAULT", -+ /*OF0-OF7*/ "LED_CPU3_CH1_DIMM1_FAULT","LED_CPU3_CH1_DIMM2_FAULT","LED_CPU3_CH2_DIMM1_FAULT","LED_CPU3_CH2_DIMM2_FAULT","LED_CPU3_CH3_DIMM1_FAULT","LED_CPU3_CH3_DIMM2_FAULT","LED_CPU3_CH4_DIMM1_FAULT","LED_CPU3_CH4_DIMM2_FAULT", -+ /*OG0-OG7*/ "LED_CPU3_CH5_DIMM1_FAULT","LED_CPU3_CH5_DIMM2_FAULT","LED_CPU3_CH6_DIMM1_FAULT","LED_CPU3_CH6_DIMM2_FAULT","LED_CPU4_CH1_DIMM1_FAULT","LED_CPU4_CH1_DIMM2_FAULT","LED_CPU4_CH2_DIMM1_FAULT","LED_CPU4_CH2_DIMM2_FAULT", -+ /*OH0-OH7*/ "LED_CPU4_CH3_DIMM1_FAULT","LED_CPU4_CH3_DIMM2_FAULT","LED_CPU4_CH4_DIMM1_FAULT","LED_CPU4_CH4_DIMM2_FAULT","LED_CPU4_CH5_DIMM1_FAULT","LED_CPU4_CH5_DIMM2_FAULT","LED_CPU4_CH6_DIMM1_FAULT","LED_CPU4_CH6_DIMM2_FAULT", -+ /*OI0-OI7*/ "","","","","","","","", -+ /*OJ0-OJ7*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", -+ /*DUMMY*/ "","","","","","","","", - -+ /* SGPIO input lines */ -+ /*IA0-IA7*/ "CPU1_PRESENCE","CPU1_THERMTRIP","CPU1_VRHOT","CPU1_FIVR_FAULT","CPU1_MEM_ABCD_VRHOT","CPU1_MEM_EFGH_VRHOT","","", -+ /*IB0-IB7*/ "CPU1_MISMATCH","CPU1_MEM_THERM_EVENT","CPU2_PRESENCE","CPU2_THERMTRIP","CPU2_VRHOT","CPU2_FIVR_FAULT","CPU2_MEM_ABCD_VRHOT","CPU2_MEM_EFGH_VRHOT", -+ /*IC0-IC7*/ "","","CPU2_MISMATCH","CPU2_MEM_THERM_EVENT","","","","", -+ /*ID0-ID7*/ "","","","","","","","", -+ /*IE0-IE7*/ "","","","","","","","", -+ /*IF0-IF7*/ "SGPIO_PLD_MINOR_REV_BIT0","SGPIO_PLD_MINOR_REV_BIT1","SGPIO_PLD_MINOR_REV_BIT2","SGPIO_PLD_MINOR_REV_BIT3","SGPIO_PLD_MAJOR_REV_BIT0","SGPIO_PLD_MAJOR_REV_BIT1","SGPIO_PLD_MAJOR_REV_BIT2","SGPIO_PLD_MAJOR_REV_BIT3", -+ /*IG0-IG7*/ "MAIN_PLD_MINOR_REV_BIT0","MAIN_PLD_MINOR_REV_BIT1","MAIN_PLD_MINOR_REV_BIT2","MAIN_PLD_MINOR_REV_BIT3","MAIN_PLD_MAJOR_REV_BIT0","MAIN_PLD_MAJOR_REV_BIT1","MAIN_PLD_MAJOR_REV_BIT2","MAIN_PLD_MAJOR_REV_BIT3", -+ /*IH0-IH7*/ "","","","","","","","", -+ /*II0-II7*/ "","","","","","","","", -+ /*IJ0-IJ7*/ "","","","","","","",""; -+}; -+ -+&kcs3 { -+ kcs_addr = <0xCA2>; -+ status = "okay"; -+}; -+ -+&kcs4 { -+ kcs_addr = <0xCA4>; -+ status = "okay"; -+}; -+ -+&sio_regs { -+ status = "okay"; -+ sio_status { -+ offset = <0x8C>; -+ bit-mask = <0x1F>; -+ bit-shift = <4>; -+ }; -+}; -+ -+&lpc_sio { -+ status = "okay"; -+}; -+ -+&lpc_snoop { -+ snoop-ports = <0x80>; -+ status = "okay"; -+}; -+ -+&mbox { -+ status = "okay"; -+}; -+ -+&uart_routing { -+ status = "okay"; -+}; -+ -+&uart1 { -+ status = "okay"; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_rmii1_default>; -- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>, -- <&syscon ASPEED_CLK_MAC1RCLK>; -- clock-names = "MACCLK", "RCLK"; -- use-ncsi; -+ pinctrl-0 = <&pinctrl_txd1_default -+ &pinctrl_rxd1_default -+ &pinctrl_nrts1_default -+ &pinctrl_ndtr1_default -+ &pinctrl_ndsr1_default -+ &pinctrl_ncts1_default -+ &pinctrl_ndcd1_default -+ &pinctrl_nri1_default>; -+}; -+ -+&uart2 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_txd2_default -+ &pinctrl_rxd2_default -+ &pinctrl_nrts2_default -+ &pinctrl_ndtr2_default -+ &pinctrl_ndsr2_default -+ &pinctrl_ncts2_default -+ &pinctrl_ndcd2_default -+ &pinctrl_nri2_default>; -+}; -+ -+&uart3 { -+ status = "okay"; -+}; -+ -+&uart4 { -+ status = "okay"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <>; -+}; -+ -+&uart5 { -+ status = "okay"; - }; - - &mac1 { -@@ -82,44 +306,87 @@ - pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>; - }; - -+&mac0 { -+ status = "okay"; -+ use-ncsi; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_rmii1_default>; -+}; -+ -+&i2c0 { -+ multi-master; -+ general-call; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; -+ status = "okay"; -+}; -+ - &i2c1 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c2 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c3 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c4 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c5 { -+ bus-frequency = <1000000>; -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c6 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c7 { -+ multi-master; -+ #retries = <3>; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &i2c13 { -+ multi-master; -+ aspeed,dma-buf-size = <4095>; -+ aspeed,hw-timeout-ms = <300>; - status = "okay"; - }; - - &gfx { - status = "okay"; -+ memory-region = <&gfx_memory>; - }; - --&pinctrl { -- aspeed,external-nodes = <&gfx &lhc>; -+&vuart { -+ status = "okay"; - }; - - &pwm_tacho { -@@ -129,4 +396,61 @@ - &pinctrl_pwm2_default &pinctrl_pwm3_default - &pinctrl_pwm4_default &pinctrl_pwm5_default - &pinctrl_pwm6_default &pinctrl_pwm7_default>; -+ -+ fan@0 { -+ reg = <0x00>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x00 0x01>; -+ }; -+ fan@1 { -+ reg = <0x01>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x02 0x03>; -+ }; -+ fan@2 { -+ reg = <0x02>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x04 0x05>; -+ }; -+ fan@3 { -+ reg = <0x03>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x06 0x07>; -+ }; -+ fan@4 { -+ reg = <0x04>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x08 0x09>; -+ }; -+ fan@5 { -+ reg = <0x05>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0A 0x0B>; -+ }; -+ fan@6 { -+ reg = <0x06>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0C 0x0D>; -+ }; -+ fan@7 { -+ reg = <0x07>; -+ aspeed,fan-tach-ch = /bits/ 8 <0x0E 0x0F>; -+ }; -+ -+}; -+ -+&timer { -+/* -+ * Available settings: -+ * fttmr010,pwm-outputs = <5>, <6>, <7>, <8>; -+ * pinctrl-0 = <&pinctrl_timer5_default &pinctrl_timer6_default -+ * &pinctrl_timer7_default &pinctrl_timer8_default>; -+ */ -+ fttmr010,pwm-outputs = <6>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_timer6_default>; -+ #pwm-cells = <3>; -+ status = "okay"; -+}; -+ -+&video { -+ status = "okay"; -+ memory-region = <&video_engine_memory>; -+}; -+ -+&vhub { -+ status = "okay"; - }; --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch deleted file mode 100644 index 08e350c15..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Add-Aspeed-fmc-spi-driver.patch +++ /dev/null @@ -1,645 +0,0 @@ -From 1365492683b47f63d470d0666fee258a5c7ca3c3 Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Thu, 12 Sep 2019 15:26:08 -0700 -Subject: [PATCH 04/52] Add Aspeed fmc-spi driver - -Add the Aspeed fmc-spi driver from the Apeed SDK v5.02 - -Signed-off-by: Vernon Mauery ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 43 ++- - drivers/spi/Kconfig | 6 + - drivers/spi/Makefile | 1 + - drivers/spi/fmc_spi.c | 530 +++++++++++++++++++++++++++++++ - 4 files changed, 579 insertions(+), 1 deletion(-) - create mode 100644 drivers/spi/fmc_spi.c - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 42f644ac8111..1aab48fbf49e 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -90,7 +90,7 @@ - <0x40464000 0x2000>, - <0x40466000 0x2000>; - }; -- -+#if 1 - fmc: spi@1e620000 { - reg = < 0x1e620000 0xc4 - 0x20000000 0x10000000 >; -@@ -169,6 +169,47 @@ - status = "disabled"; - }; - }; -+#else -+ spi0: spi@1e620000 { -+ /* reg : cs0 : cs1 : cs2 */ -+ reg = <0x1e620000 0x100 -+ 0x20000000 0x40 -+ 0x28000000 0x40>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "aspeed,fmc-spi"; -+ clocks = <&syscon ASPEED_CLK_AHB>; -+ status = "disable"; -+ number_of_chip_select = /bits/ 16 <2>; -+ interrupts = ; -+ }; -+ -+ spi1: spi1@1e630000 { -+ /* reg : cs0 : cs1 */ -+ reg = <0x1e630000 0x100 -+ 0x30000000 0x20 -+ 0x32000000 0x20>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "aspeed,fmc-spi"; -+ clocks = <&syscon ASPEED_CLK_AHB>; -+ status = "disable"; -+ number_of_chip_select = /bits/ 16 <2>; -+ }; -+ -+ spi2: spi2@1e631000 { -+ /* reg : cs0 : cs1 */ -+ reg = <0x1e631000 0x100 -+ 0x38000000 0x20 -+ 0x3A000000 0x20>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "aspeed,fmc-spi"; -+ clocks = <&syscon ASPEED_CLK_AHB>; -+ status = "disable"; -+ number_of_chip_select = /bits/ 16 <2>; -+ }; -+#endif - - mdio0: mdio@1e650000 { - compatible = "aspeed,ast2600-mdio"; -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 6ee514fd0920..9f32c31ffa3c 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -57,6 +57,12 @@ config SPI_MEM - - comment "SPI Master Controller Drivers" - -+config SPI_FMC -+ tristate "Aspeed FMC SPI Controller" -+ depends on ARCH_ASPEED -+ help -+ This selects a driver for the AST FMC SPI Controller -+ - config SPI_ALTERA - tristate "Altera SPI Controller" - help -diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile -index adbebee93a75..224b9b71e29c 100644 ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_SPI_SPIDEV) += spidev.o - obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o - - # SPI master controller drivers (bus) -+obj-$(CONFIG_SPI_FMC) += fmc_spi.o - obj-$(CONFIG_SPI_ALTERA) += spi-altera.o - obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o - obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o -diff --git a/drivers/spi/fmc_spi.c b/drivers/spi/fmc_spi.c -new file mode 100644 -index 000000000000..f21f7a00496e ---- /dev/null -+++ b/drivers/spi/fmc_spi.c -@@ -0,0 +1,530 @@ -+/* -+ * fmc_spi.c - FMC SPI driver for the Aspeed SoC -+ * -+ * Copyright (C) ASPEED Technology Inc. -+ * Ryan Chen -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/******************************************************************************/ -+/* AST_SPI_CONFIG 0x00 : SPI00 CE Type Setting Register */ -+#define AST_G5_SPI_CONF_CE1_WEN (0x1 << 17) -+#define AST_G5_SPI_CONF_CE0_WEN (0x1 << 16) -+ -+#define SPI_CONF_CE0_WEN (0x1) -+ -+/* Register offsets */ -+#define FMC_SPI_CONFIG 0x00 -+#define FMC_SPI_CTRL 0x04 -+#define FMC_SPI_DMA_STS 0x08 -+ -+#define FMC_SPI_CE0_CTRL 0x10 -+#define FMC_SPI_CE1_CTRL 0x14 -+ -+#define AST_SPI_DMA_CTRL 0x80 -+#define AST_SPI_DMA_FLASH_BASE 0x84 -+#define AST_SPI_DMA_DRAM_BASE 0x88 -+#define AST_SPI_DMA_LENGTH 0x8c -+ -+/* AST_FMC_CONFIG 0x00 : FMC00 CE Type Setting Register */ -+#define FMC_CONF_LAGACY_DIS (0x1 << 31) -+#define FMC_CONF_CE1_WEN (0x1 << 17) -+#define FMC_CONF_CE0_WEN (0x1 << 16) -+#define FMC_CONF_CE1_SPI (0x2 << 2) -+#define FMC_CONF_CE0_SPI (0x2) -+ -+/* FMC_SPI_CTRL : 0x04 : FMC04 CE Control Register */ -+#define FMC_CTRL_CE1_4BYTE_MODE (0x1 << 1) -+#define FMC_CTRL_CE0_4BYTE_MODE (0x1) -+ -+/* FMC_SPI_DMA_STS : 0x08 : FMC08 Interrupt Control and Status Register */ -+#define FMC_STS_DMA_READY 0x0800 -+#define FMC_STS_DMA_CLEAR 0x0800 -+ -+/* FMC_CE0_CTRL for SPI 0x10, 0x14, 0x18, 0x1c, 0x20 */ -+#define SPI_IO_MODE_MASK (3 << 28) -+#define SPI_SINGLE_BIT (0 << 28) -+#define SPI_DUAL_MODE (0x2 << 28) -+#define SPI_DUAL_IO_MODE (0x3 << 28) -+#define SPI_QUAD_MODE (0x4 << 28) -+#define SPI_QUAD_IO_MODE (0x5 << 28) -+ -+#define SPI_CE_WIDTH(x) (x << 24) -+#define SPI_CMD_DATA_MASK (0xff << 16) -+#define SPI_CMD_DATA(x) (x << 16) -+#define SPI_DUMMY_CMD (1 << 15) -+#define SPI_DUMMY_HIGH (1 << 14) -+//#define SPI_CLK_DIV (1 << 13) ?? TODO ask.... -+//#define SPI_ADDR_CYCLE (1 << 13) ?? TODO ask.... -+#define SPI_CMD_MERGE_DIS (1 << 12) -+#define SPI_CLK_DIV(x) (x << 8) -+#define SPI_CLK_DIV_MASK (0xf << 8) -+ -+#define SPI_DUMMY_LOW_MASK (0x3 << 6) -+#define SPI_DUMMY_LOW(x) ((x) << 6) -+#define SPI_LSB_FIRST_CTRL (1 << 5) -+#define SPI_CPOL_1 (1 << 4) -+#define SPI_DUAL_DATA (1 << 3) -+#define SPI_CE_INACTIVE (1 << 2) -+#define SPI_CMD_MODE_MASK (0x3) -+#define SPI_CMD_NORMAL_READ_MODE 0 -+#define SPI_CMD_READ_CMD_MODE 1 -+#define SPI_CMD_WRITE_CMD_MODE 2 -+#define SPI_CMD_USER_MODE 3 -+ -+/* AST_SPI_DMA_CTRL 0x80 */ -+#define FMC_DMA_ENABLE (0x1) -+ -+/******************************************************************************/ -+struct fmc_spi_host { -+ void __iomem *base; -+ void __iomem *ctrl_reg; -+ u32 buff[5]; -+ struct spi_master *master; -+ struct spi_device *spi_dev; -+ struct device *dev; -+ u32 ahb_clk; -+ spinlock_t lock; -+}; -+ -+static u32 ast_spi_calculate_divisor(struct fmc_spi_host *host, -+ u32 max_speed_hz) -+{ -+ // [0] ->15 : HCLK , HCLK/16 -+ u8 SPI_DIV[16] = { -+ 16, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0 -+ }; -+ u32 i, spi_cdvr = 0; -+ -+ for (i = 1; i < 17; i++) { -+ if (max_speed_hz >= (host->ahb_clk / i)) { -+ spi_cdvr = SPI_DIV[i - 1]; -+ break; -+ } -+ } -+ -+ // printk("hclk is %d, divisor is %d, target :%d , cal speed %d\n", host->ahb_clk, spi_cdvr, spi->max_speed_hz, hclk/i); -+ return spi_cdvr; -+} -+ -+/* the spi->mode bits understood by this driver: */ -+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) -+ -+static int fmc_spi_setup(struct spi_device *spi) -+{ -+ struct fmc_spi_host *host = -+ (struct fmc_spi_host *)spi_master_get_devdata(spi->master); -+ unsigned int bits = spi->bits_per_word; -+ u32 fmc_config = 0; -+ u32 spi_ctrl = 0; -+ u32 divisor; -+ -+ // dev_dbg(host->dev, "fmc_spi_setup() cs: %d, spi->mode %d \n", spi->chip_select, spi->mode); -+ // printk("fmc_spi_setup() cs: %d, spi->mode %d spi->max_speed_hz %d , spi->bits_per_word %d \n", spi->chip_select, spi->mode, spi->max_speed_hz, spi->bits_per_word); -+ -+ switch (spi->chip_select) { -+ case 0: -+ fmc_config |= FMC_CONF_CE0_WEN | FMC_CONF_CE0_SPI; -+ host->ctrl_reg = host->base + FMC_SPI_CE0_CTRL; -+ break; -+ case 1: -+ fmc_config |= FMC_CONF_CE1_WEN | FMC_CONF_CE1_SPI; -+ host->ctrl_reg = host->base + FMC_SPI_CE0_CTRL; -+ break; -+ default: -+ dev_dbg(&spi->dev, -+ "setup: invalid chipselect %u (%u defined)\n", -+ spi->chip_select, spi->master->num_chipselect); -+ return -EINVAL; -+ break; -+ } -+ writel(fmc_config, host->base); -+ -+ if (bits == 0) -+ bits = 8; -+ -+ if (bits < 8 || bits > 16) { -+ dev_dbg(&spi->dev, -+ "setup: invalid bits_per_word %u (8 to 16)\n", bits); -+ return -EINVAL; -+ } -+ -+ if (spi->mode & ~MODEBITS) { -+ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", -+ spi->mode & ~MODEBITS); -+ return -EINVAL; -+ } -+ -+ /* see notes above re chipselect */ -+ if ((spi->chip_select == 0) && (spi->mode & SPI_CS_HIGH)) { -+ dev_dbg(&spi->dev, "setup: can't be active-high\n"); -+ return -EINVAL; -+ } -+ -+ /* -+ * Pre-new_1 chips start out at half the peripheral -+ * bus speed. -+ */ -+ -+ if (spi->max_speed_hz) { -+ /* Set the SPI slaves select and characteristic control register */ -+ divisor = ast_spi_calculate_divisor(host, spi->max_speed_hz); -+ } else { -+ /* speed zero means "as slow as possible" */ -+ divisor = 15; -+ } -+ -+ spi_ctrl &= ~SPI_CLK_DIV_MASK; -+ // printk("set div %x \n",divisor); -+ //TODO MASK first -+ spi_ctrl |= SPI_CLK_DIV(divisor); -+ -+ /* only support mode 0 (CPOL=0, CPHA=0) and cannot support mode 1 ~ mode 3 */ -+ -+#if 0 -+ if (SPI_CPHA & spi->mode) -+ cpha = SPI_CPHA_1; -+ else -+ cpha = SPI_CPHA_0; -+#endif -+ -+ // if (SPI_CPOL & spi->mode) -+ // spi_ctrl |= SPI_CPOL_1; -+ // else -+ // spi_ctrl &= ~SPI_CPOL_1; -+ -+ //ISSUE : ast spi ctrl couldn't use mode 3, so fix mode 0 -+ spi_ctrl &= ~SPI_CPOL_1; -+ -+ if (SPI_LSB_FIRST & spi->mode) -+ spi_ctrl |= SPI_LSB_FIRST_CTRL; -+ else -+ spi_ctrl &= ~SPI_LSB_FIRST_CTRL; -+ -+ /* Configure SPI controller */ -+ writel(spi_ctrl, host->ctrl_reg); -+ -+ // printk("ctrl %x, ", spi_ctrl); -+ return 0; -+} -+ -+static int fmc_spi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ struct fmc_spi_host *host = -+ (struct fmc_spi_host *)spi_master_get_devdata(spi->master); -+ struct spi_transfer *xfer; -+ const u8 *tx_buf; -+ u8 *rx_buf; -+ unsigned long flags; -+ -+ int i = 0, j = 0; -+ -+ // dev_dbg(host->dev, "xfer %s \n", dev_name(&spi->dev)); -+ // printk("xfer spi->chip_select %d \n", spi->chip_select); -+ -+ host->spi_dev = spi; -+ spin_lock_irqsave(&host->lock, flags); -+ -+ writel(readl(host->ctrl_reg) | SPI_CMD_USER_MODE, host->ctrl_reg); -+ msg->actual_length = 0; -+ msg->status = 0; -+ -+ list_for_each_entry (xfer, &msg->transfers, transfer_list) { -+ dev_dbg(host->dev, -+ "xfer[%d] %p: width %d, len %u, tx %p/%08x, rx %p/%08x\n", -+ j, xfer, xfer->bits_per_word, xfer->len, xfer->tx_buf, -+ xfer->tx_dma, xfer->rx_buf, xfer->rx_dma); -+ -+ tx_buf = xfer->tx_buf; -+ rx_buf = xfer->rx_buf; -+ -+ if (tx_buf != 0) { -+#if 0 -+ printk("tx : "); -+ if(xfer->len > 10) { -+ for(i=0;i<10;i++) -+ printk("%x ",tx_buf[i]); -+ } else { -+ for(i=0;ilen;i++) -+ printk("%x ",tx_buf[i]); -+ } -+ printk("\n"); -+#endif -+ for (i = 0; i < xfer->len; i++) { -+ writeb(tx_buf[i], -+ (void *)host->buff -+ [host->spi_dev->chip_select]); -+ } -+ } -+ //Issue need clarify -+ udelay(1); -+ if (rx_buf != 0) { -+ for (i = 0; i < xfer->len; i++) { -+ rx_buf[i] = readb( -+ (void *)host->buff -+ [host->spi_dev->chip_select]); -+ } -+#if 0 -+ printk("rx : "); -+ if(xfer->len > 10) { -+ for(i=0;i<10;i++) -+ printk(" %x",rx_buf[i]); -+ } else { -+ for(i=0;ilen;i++) -+ printk(" %x",rx_buf[i]); -+ } -+ printk("\n"); -+#endif -+ } -+ dev_dbg(host->dev, "old msg->actual_length %d , +len %d \n", -+ msg->actual_length, xfer->len); -+ msg->actual_length += xfer->len; -+ dev_dbg(host->dev, "new msg->actual_length %d \n", -+ msg->actual_length); -+ // j++; -+ } -+ -+ // writel( SPI_CE_INACTIVE | readl(host->spi_data->ctrl_reg),host->spi_data->ctrl_reg); -+ writel(readl(host->ctrl_reg) & ~SPI_CMD_USER_MODE, host->ctrl_reg); -+ msg->status = 0; -+ -+ msg->complete(msg->context); -+ -+ // spin_unlock(&host->lock); -+ spin_unlock_irqrestore(&host->lock, flags); -+ -+ return 0; -+} -+ -+static void fmc_spi_cleanup(struct spi_device *spi) -+{ -+ struct fmc_spi_host *host = spi_master_get_devdata(spi->master); -+ unsigned long flags; -+ dev_dbg(host->dev, "fmc_spi_cleanup() \n"); -+ -+ spin_lock_irqsave(&host->lock, flags); -+ // if (host->stay == spi) { -+ // host->stay = NULL; -+ // cs_deactivate(host, spi); -+ // } -+ spin_unlock_irqrestore(&host->lock, flags); -+} -+ -+#if 0 -+static int fmc_spi_flash_read(struct spi_device *spi, -+ struct spi_flash_read_message *msg) -+{ -+// struct fmc_spi_host *host = spi_master_get_devdata(spi->master); -+ int ret = 0; -+ -+// printk("read msg->from %x, msg->len %x , msg->buf %x , msg->addr_width %d , msg->dummy_bytes %x , msg->read_opcode %x \n", msg->from, msg->len, msg->buf, msg->addr_width, msg->dummy_bytes, msg->read_opcode); -+ -+// memcpy_fromio(msg->buf, b53spi->mmio_base + msg->from, msg->len); -+ msg->retlen = msg->len; -+ -+ return ret; -+} -+#endif -+ -+static int fmc_spi_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct fmc_spi_host *host; -+ struct spi_master *master; -+ struct clk *clk; -+ int cs_num = 0; -+ int err = 0; -+ -+ dev_dbg(&pdev->dev, "fmc_spi_probe() \n"); -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(struct fmc_spi_host)); -+ if (NULL == master) { -+ dev_err(&pdev->dev, "No memory for spi_master\n"); -+ err = -ENOMEM; -+ goto err_nomem; -+ } -+ -+ /* the spi->mode bits understood by this driver: */ -+ master->mode_bits = -+ SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_RX_DUAL | SPI_TX_DUAL; -+ master->bits_per_word_mask = SPI_BPW_MASK(8); -+ -+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_RX_DUAL; -+ // master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); -+ master->dev.of_node = pdev->dev.of_node; -+ master->bus_num = pdev->id; -+ // master->num_chipselect = master->dev.of_node ? 0 : 4; -+ platform_set_drvdata(pdev, master); -+ -+ host = spi_master_get_devdata(master); -+ memset(host, 0, sizeof(struct fmc_spi_host)); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "cannot get IORESOURCE_MEM 0\n"); -+ err = -ENXIO; -+ goto err_no_io_res; -+ } -+ -+ host->base = devm_ioremap_resource(&pdev->dev, res); -+ if (!host->base) { -+ dev_err(&pdev->dev, "cannot remap register\n"); -+ err = -EIO; -+ goto err_no_io_res; -+ } -+ -+ clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "no clock defined\n"); -+ return -ENODEV; -+ } -+ host->ahb_clk = clk_get_rate(clk); -+ -+ dev_dbg(&pdev->dev, "remap phy %x, virt %x \n", (u32)res->start, -+ (u32)host->base); -+ -+ host->master = spi_master_get(master); -+ -+ if (of_property_read_u16(pdev->dev.of_node, "number_of_chip_select", -+ &host->master->num_chipselect)) -+ goto err_register; -+ -+ for (cs_num = 0; cs_num < host->master->num_chipselect; cs_num++) { -+ res = platform_get_resource(pdev, IORESOURCE_MEM, cs_num + 1); -+ if (!res) { -+ dev_err(&pdev->dev, "cannot get IORESOURCE_IO 0\n"); -+ return -ENXIO; -+ } -+ -+ host->buff[cs_num] = -+ (u32)devm_ioremap_resource(&pdev->dev, res); -+ if (!host->buff[cs_num]) { -+ dev_err(&pdev->dev, "cannot remap buffer \n"); -+ err = -EIO; -+ goto err_no_io_res; -+ } -+ -+ dev_dbg(&pdev->dev, "remap io phy %x, virt %x \n", -+ (u32)res->start, (u32)host->buff[cs_num]); -+ } -+ -+ host->master->bus_num = pdev->id; -+ host->dev = &pdev->dev; -+ -+ /* Setup the state for bitbang driver */ -+ host->master->setup = fmc_spi_setup; -+ host->master->transfer = fmc_spi_transfer; -+ host->master->cleanup = fmc_spi_cleanup; -+ // host->master->spi_flash_read = fmc_spi_flash_read; -+ -+ platform_set_drvdata(pdev, host); -+ -+ /* Register our spi controller */ -+ err = devm_spi_register_master(&pdev->dev, host->master); -+ if (err) { -+ dev_err(&pdev->dev, "failed to register SPI master\n"); -+ goto err_register; -+ } -+ -+ dev_dbg(&pdev->dev, "fmc_spi : driver load \n"); -+ -+ return 0; -+ -+err_register: -+ spi_master_put(host->master); -+ iounmap(host->base); -+ for (cs_num = 0; cs_num < host->master->num_chipselect; cs_num++) { -+ iounmap((void *)host->buff[cs_num]); -+ } -+ -+err_no_io_res: -+ kfree(master); -+ kfree(host); -+ -+err_nomem: -+ return err; -+} -+ -+static int fmc_spi_remove(struct platform_device *pdev) -+{ -+ struct resource *res0; -+ struct fmc_spi_host *host = platform_get_drvdata(pdev); -+ -+ dev_dbg(host->dev, "fmc_spi_remove()\n"); -+ -+ if (!host) -+ return -1; -+ -+ res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ release_mem_region(res0->start, res0->end - res0->start + 1); -+ iounmap(host->base); -+ iounmap(host->buff); -+ -+ platform_set_drvdata(pdev, NULL); -+ spi_unregister_master(host->master); -+ spi_master_put(host->master); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int fmc_spi_suspend(struct platform_device *pdev, pm_message_t msg) -+{ -+ return 0; -+} -+ -+static int fmc_spi_resume(struct platform_device *pdev) -+{ -+ return 0; -+} -+#else -+#define fmc_spi_suspend NULL -+#define fmc_spi_resume NULL -+#endif -+ -+static const struct of_device_id fmc_spi_of_match[] = { -+ { .compatible = "aspeed,fmc-spi" }, -+ {}, -+}; -+ -+static struct platform_driver fmc_spi_driver = { -+ .probe = fmc_spi_probe, -+ .remove = fmc_spi_remove, -+#ifdef CONFIG_PM -+ .suspend = fmc_spi_suspend, -+ .resume = fmc_spi_resume, -+#endif -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .of_match_table = fmc_spi_of_match, -+ }, -+}; -+ -+module_platform_driver(fmc_spi_driver); -+ -+MODULE_DESCRIPTION("FMC SPI Driver"); -+MODULE_AUTHOR("Ryan Chen"); -+MODULE_LICENSE("GPL"); --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch deleted file mode 100644 index 6123b8701..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 12ef9a4189cd44212a5a5bd2e1c6fce0756ace9f Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -Date: Fri, 3 May 2019 16:12:39 -0700 -Subject: [PATCH] Enable pass-through on GPIOE1 and GPIOE3 free - -This change adds a gpio_disable_free() implementation that checks -if the GPIO being freed is GPIOE1 (33) or GPIOE3 (35) and will -re-enable the pass-through mux. - -Tested: -Requested GPIOs 33 and 35 and used devmem to check that pass-through -was disabled. Then freed them and checked that pass-through was -enabled again. - -Signed-off-by: Jason M. Bills ---- - drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 17 ++++++++++ - drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c | 17 ++++++++++ - drivers/pinctrl/aspeed/pinctrl-aspeed.c | 53 ++++++++++++++++++++++++++++++ - drivers/pinctrl/aspeed/pinctrl-aspeed.h | 3 ++ - 4 files changed, 90 insertions(+) - -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -index 0cab4c2576e2..c5406e2da320 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -@@ -2780,6 +2780,22 @@ static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx, - return 0; - } - -+#define GPIOE1 33 -+#define GPIOE3 35 -+static void aspeed_g5_gpio_disable_free(struct pinctrl_dev *pctldev, -+ struct pinctrl_gpio_range *range, -+ unsigned int offset) -+{ -+ /* -+ * If we're freeing GPIOE1 (33) or GPIOE3 (35) then re-enable the -+ * pass-through mux setting; otherwise, do nothing. -+ */ -+ if (offset != GPIOE1 && offset != GPIOE3) -+ return; -+ -+ aspeed_gpio_disable_free(pctldev, range, offset); -+} -+ - static const struct aspeed_pin_config_map aspeed_g5_pin_config_map[] = { - { PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)}, - { PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)}, -@@ -2815,6 +2831,7 @@ static const struct pinmux_ops aspeed_g5_pinmux_ops = { - .get_function_groups = aspeed_pinmux_get_fn_groups, - .set_mux = aspeed_pinmux_set_mux, - .gpio_request_enable = aspeed_gpio_request_enable, -+ .gpio_disable_free = aspeed_g5_gpio_disable_free, - .strict = true, - }; - -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -index fb96e8d2e6c8..bcd8c5656265 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -@@ -2655,6 +2655,22 @@ static int aspeed_g6_sig_expr_set(struct aspeed_pinmux_data *ctx, - return 0; - } - -+#define GPIOP1 121 -+#define GPIOP3 123 -+static void aspeed_g6_gpio_disable_free(struct pinctrl_dev *pctldev, -+ struct pinctrl_gpio_range *range, -+ unsigned int offset) -+{ -+ /* -+ * If we're freeing GPIOP1 (121) or GPIOP3 (123) then re-enable the -+ * pass-through mux setting; otherwise, do nothing. -+ */ -+ if (offset != GPIOP1 && offset != GPIOP3) -+ return; -+ -+ aspeed_gpio_disable_free(pctldev, range, offset); -+} -+ - static const struct aspeed_pin_config_map aspeed_g6_pin_config_map[] = { - { PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)}, - { PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)}, -@@ -2695,6 +2711,7 @@ static const struct pinmux_ops aspeed_g6_pinmux_ops = { - .get_function_groups = aspeed_pinmux_get_fn_groups, - .set_mux = aspeed_pinmux_set_mux, - .gpio_request_enable = aspeed_gpio_request_enable, -+ .gpio_disable_free = aspeed_g6_gpio_disable_free, - .strict = true, - }; - -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c -index 53f3f8aec695..ca53f3743d16 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c -@@ -375,6 +375,59 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev, - return 0; - } - -+void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev, -+ struct pinctrl_gpio_range *range, -+ unsigned int offset) -+{ -+ struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); -+ const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data; -+ const struct aspeed_sig_expr ***prios, **funcs, *expr; -+ int ret; -+ -+ if (!pdesc) -+ return; -+ -+ dev_dbg(pctldev->dev, -+ "Freeing pass-through pin %s (%d). Re-enabling pass-through.\n", -+ pdesc->name, offset); -+ -+ prios = pdesc->prios; -+ -+ if (!prios) -+ return; -+ -+ /* Disable any functions of higher priority than GPIO just in case */ -+ while ((funcs = *prios)) { -+ if (aspeed_gpio_in_exprs(funcs)) -+ break; -+ -+ ret = aspeed_disable_sig(&pdata->pinmux, funcs); -+ if (ret) -+ return; -+ -+ prios++; -+ } -+ -+ if (!funcs) { -+ char *signals = get_defined_signals(pdesc); -+ -+ pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n", -+ pdesc->name, offset, signals); -+ kfree(signals); -+ -+ return; -+ } -+ -+ /* -+ * Pass-through should be one priority higher than the GPIO function, -+ * so decrement our prios and enable that function -+ */ -+ prios--; -+ funcs = *prios; -+ expr = *funcs; -+ aspeed_sig_expr_enable(&pdata->pinmux, expr); -+} -+ - int aspeed_pinctrl_probe(struct platform_device *pdev, - struct pinctrl_desc *pdesc, - struct aspeed_pinctrl_data *pdata) -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h -index 4dcde3bc29c8..bd497c20a15f 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h -@@ -101,6 +101,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function, - int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, - unsigned int offset); -+void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev, -+ struct pinctrl_gpio_range *range, -+ unsigned int offset); - int aspeed_pinctrl_probe(struct platform_device *pdev, - struct pinctrl_desc *pdesc, - struct aspeed_pinctrl_data *pdata); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch deleted file mode 100644 index 1ee1c68de..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch +++ /dev/null @@ -1,70 +0,0 @@ -From b34fdedc21c98db698150d5014e12927a017b07f Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -Date: Mon, 6 May 2019 14:18:27 -0700 -Subject: [PATCH] Enable GPIOE0 and GPIOE2 pass-through by default - -This change sets the gpio DT pinctrl default configuration to -enable GPIOE0 and GPIOE2 pass-through. Since this causes -pinctrl_get_select_default() to be called automatically for -the gpio driver to claim the GPIO pins in those groups, we -also need to call pinctrl_put() to release claim on the -pass-through GPIOs so they can be requested at runtime. - -Tested: -Disabled pass-through in uboot and confirmed that after booting -Linux, pass-through is enabled and 'cat /sys/kernel/debug/pinctrl/ -1e6e2000.syscon\:pinctrl-aspeed-g5-pinctrl/pinmux-pins' shows that -the pass-through GPIOs are UNCLAIMED. - -Signed-off-by: Jason M. Bills ---- - arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts | 4 ++++ - drivers/gpio/gpio-aspeed.c | 10 ++++++++++ - 2 files changed, 14 insertions(+) - -diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts -index 72bb1b3..ea1d9cd3 100644 ---- a/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts -+++ b/arch/arm/boot/dts/aspeed-bmc-intel-ast2500.dts -@@ -134,6 +134,10 @@ - - &gpio { - status = "okay"; -+ /* Enable GPIOE0 and GPIOE2 pass-through by default */ -+ pinctrl-names = "pass-through"; -+ pinctrl-0 = <&pinctrl_gpie0_default -+ &pinctrl_gpie2_default>; - gpio-line-names = - /*A0-A7*/ "","","","","","","","", - /*B0-B7*/ "FM_BMC_BOARD_SKU_ID0_N","FM_BMC_BOARD_SKU_ID1_N","FM_BMC_BOARD_SKU_ID2_N","FM_BMC_BOARD_SKU_ID3_N","FM_BMC_BOARD_SKU_ID4_N","","","", -diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c -index 09e53c5..6165b44 100644 ---- a/drivers/gpio/gpio-aspeed.c -+++ b/drivers/gpio/gpio-aspeed.c -@@ -1140,6 +1140,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) - { - const struct of_device_id *gpio_id; - struct aspeed_gpio *gpio; -+ struct pinctrl *pinctrl; - int rc, i, banks, err; - u32 ngpio; - -@@ -1190,6 +1191,15 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) - return -ENOMEM; - - /* -+ * Select the pass-through pinctrl config to enable the pass-through -+ * mux for GPIOs marked as pass-through. Then call pinctrl_put() to -+ * release claim of the GPIO pins, so they can be requested at runtime. -+ */ -+ pinctrl = pinctrl_get_select(&pdev->dev, "pass-through"); -+ if (!IS_ERR(pinctrl)) -+ pinctrl_put(pinctrl); -+ -+ /* - * Populate it with initial values read from the HW and switch - * all command sources to the ARM by default - */ --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch deleted file mode 100644 index b9c14c1ac..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0006-Allow-monitoring-of-power-control-input-GPIOs.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 5f984831a3f451e299ecaf42d65dee36ff0ffeee Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -Date: Fri, 24 May 2019 12:42:59 -0700 -Subject: [PATCH] Allow monitoring of power control input GPIOs - -The pass-through input GPIOs cannot be monitored because when -requested, pass-through is disabled which causes a change on the -pass-through output. - -The SIO GPIOs cannot be monitored because when requested, the -request is rejected based on the value of the ACPI strap. - -This change removes the register check condition from the pass- -through and desired SIO GPIOs so they can be requsted and -monitored from power control. - -Tested: -For pass-through, I used gpioset to hold a request on the input -GPIOs and confirmed that pass-through remained enabled. - -For SIO, I used gpioget to confirm that I can successfully request -and read the GPIO value. - -Signed-off-by: Jason M. Bills ---- - drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 10 +++++----- - drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c | 10 +++++----- - 2 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -index c5406e2da320..fde74c23ca7f 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c -@@ -279,7 +279,7 @@ FUNC_GROUP_DECL(SD2, F19, E21, F20, D20, D21, E20, G18, C21); - - #define B20 32 - SIG_EXPR_LIST_DECL_SINGLE(B20, NCTS3, NCTS3, SIG_DESC_SET(SCU80, 16)); --SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE0, GPIE0_DESC); -+SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE0); - SIG_EXPR_DECL_SINGLE(GPIE0IN, GPIE, GPIE_DESC); - SIG_EXPR_LIST_DECL_DUAL(B20, GPIE0IN, GPIE0, GPIE); - PIN_DECL_2(B20, GPIOE0, NCTS3, GPIE0IN); -@@ -299,7 +299,7 @@ FUNC_GROUP_DECL(GPIE0, B20, C20); - - #define F18 34 - SIG_EXPR_LIST_DECL_SINGLE(F18, NDSR3, NDSR3, SIG_DESC_SET(SCU80, 18)); --SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE2, GPIE2_DESC); -+SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE2); - SIG_EXPR_DECL_SINGLE(GPIE2IN, GPIE, GPIE_DESC); - SIG_EXPR_LIST_DECL_DUAL(F18, GPIE2IN, GPIE2, GPIE); - PIN_DECL_2(F18, GPIOE2, NDSR3, GPIE2IN); -@@ -1412,7 +1412,7 @@ FUNC_GROUP_DECL(ADC15, H4); - - #define R22 192 - SIG_EXPR_DECL_SINGLE(SIOS3, SIOS3, SIG_DESC_SET(SCUA4, 8)); --SIG_EXPR_DECL_SINGLE(SIOS3, ACPI, ACPI_DESC); -+SIG_EXPR_DECL_SINGLE(SIOS3, ACPI); - SIG_EXPR_LIST_DECL_DUAL(R22, SIOS3, SIOS3, ACPI); - SIG_EXPR_LIST_DECL_SINGLE(R22, DASHR22, DASHR22, SIG_DESC_SET(SCU94, 10)); - PIN_DECL_2(R22, GPIOY0, SIOS3, DASHR22); -@@ -1420,7 +1420,7 @@ FUNC_GROUP_DECL(SIOS3, R22); - - #define R21 193 - SIG_EXPR_DECL_SINGLE(SIOS5, SIOS5, SIG_DESC_SET(SCUA4, 9)); --SIG_EXPR_DECL_SINGLE(SIOS5, ACPI, ACPI_DESC); -+SIG_EXPR_DECL_SINGLE(SIOS5, ACPI); - SIG_EXPR_LIST_DECL_DUAL(R21, SIOS5, SIOS5, ACPI); - SIG_EXPR_LIST_DECL_SINGLE(R21, DASHR21, DASHR21, SIG_DESC_SET(SCU94, 10)); - PIN_DECL_2(R21, GPIOY1, SIOS5, DASHR21); -@@ -1436,7 +1436,7 @@ FUNC_GROUP_DECL(SIOPWREQ, P22); - - #define P21 195 - SIG_EXPR_DECL_SINGLE(SIOONCTRL, SIOONCTRL, SIG_DESC_SET(SCUA4, 11)); --SIG_EXPR_DECL_SINGLE(SIOONCTRL, ACPI, ACPI_DESC); -+SIG_EXPR_DECL_SINGLE(SIOONCTRL, ACPI); - SIG_EXPR_LIST_DECL_DUAL(P21, SIOONCTRL, SIOONCTRL, ACPI); - SIG_EXPR_LIST_DECL_SINGLE(P21, DASHP21, DASHP21, SIG_DESC_SET(SCU94, 11)); - PIN_DECL_2(P21, GPIOY3, SIOONCTRL, DASHP21); -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -index bcd8c5656265..c18ceb52c289 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -@@ -762,7 +762,7 @@ SSSF_PIN_DECL(AC23, GPIOO7, PWM7, SIG_DESC_SET(SCU41C, 23)); - - #define AB22 120 - SIG_EXPR_LIST_DECL_SEMG(AB22, PWM8, PWM8G1, PWM8, SIG_DESC_SET(SCU41C, 24)); --SIG_EXPR_LIST_DECL_SESG(AB22, THRUIN0, THRU0, SIG_DESC_SET(SCU4BC, 24)); -+SIG_EXPR_LIST_DECL_SESG(AB22, THRUIN0, THRU0); - PIN_DECL_2(AB22, GPIOP0, PWM8, THRUIN0); - GROUP_DECL(PWM8G1, AB22); - FUNC_DECL_2(PWM8, PWM8G0, PWM8G1); -@@ -779,7 +779,7 @@ FUNC_DECL_2(PWM9, PWM9G0, PWM9G1); - - #define AA23 122 - SIG_EXPR_LIST_DECL_SEMG(AA23, PWM10, PWM10G1, PWM10, SIG_DESC_SET(SCU41C, 26)); --SIG_EXPR_LIST_DECL_SESG(AA23, THRUIN1, THRU1, SIG_DESC_SET(SCU4BC, 26)); -+SIG_EXPR_LIST_DECL_SESG(AA23, THRUIN1, THRU1); - PIN_DECL_2(AA23, GPIOP2, PWM10, THRUIN1); - GROUP_DECL(PWM10G1, AA23); - FUNC_DECL_2(PWM10, PWM10G0, PWM10G1); -@@ -1070,16 +1070,16 @@ FUNC_GROUP_DECL(GPIU7, AC17); - FUNC_GROUP_DECL(ADC15, AC17); - - #define AB15 168 --SSSF_PIN_DECL(AB15, GPIOV0, SIOS3, SIG_DESC_SET(SCU434, 8)); -+SSSF_PIN_DECL(AB15, GPIOV0, SIOS3); - - #define AF14 169 --SSSF_PIN_DECL(AF14, GPIOV1, SIOS5, SIG_DESC_SET(SCU434, 9)); -+SSSF_PIN_DECL(AF14, GPIOV1, SIOS5); - - #define AD14 170 - SSSF_PIN_DECL(AD14, GPIOV2, SIOPWREQ, SIG_DESC_SET(SCU434, 10)); - - #define AC15 171 --SSSF_PIN_DECL(AC15, GPIOV3, SIOONCTRL, SIG_DESC_SET(SCU434, 11)); -+SSSF_PIN_DECL(AC15, GPIOV3, SIOONCTRL); - - #define AE15 172 - SSSF_PIN_DECL(AE15, GPIOV4, SIOPWRGD, SIG_DESC_SET(SCU434, 12)); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch deleted file mode 100644 index 476a07043..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-aspeed-pwm-tacho-change-default-fan-speed.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b7e8941cf3b1c1c42330207600c91fb23781a77b Mon Sep 17 00:00:00 2001 -From: James Feist -Date: Tue, 2 Jul 2019 10:14:59 -0700 -Subject: [PATCH] aspeed-pwm-tacho: change default fan speed - -Change it from max to 58% - -Signed-off-by: James Feist ---- - drivers/hwmon/aspeed-pwm-tacho.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c -index 40c489be62ea..ae5771f881b5 100644 ---- a/drivers/hwmon/aspeed-pwm-tacho.c -+++ b/drivers/hwmon/aspeed-pwm-tacho.c -@@ -160,7 +160,7 @@ - */ - #define M_TACH_MODE 0x02 /* 10b */ - #define M_TACH_UNIT 0x0210 --#define INIT_FAN_CTRL 0xFF -+#define INIT_FAN_CTRL 150 /* 58% */ - - /* How long we sleep in us while waiting for an RPM result. */ - #define ASPEED_RPM_STATUS_SLEEP_USEC 500 --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch deleted file mode 100644 index 993beb9ec..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0014-arm-dts-aspeed-g5-add-espi.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ea37c85db4d2a593d4f3392e21ec2cc108b111e5 Mon Sep 17 00:00:00 2001 -From: Juston Li -Date: Mon, 27 Mar 2017 11:16:00 -0700 -Subject: [PATCH] arm: dts: aspeed-g5: add espi - -Signed-off-by: Juston Li ---- - arch/arm/boot/dts/aspeed-g5.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 6580b232771e..452ec323534f 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -408,6 +408,13 @@ - status = "disabled"; - }; - -+ espi: espi@1e6ee000 { -+ compatible = "aspeed,ast2500-espi-slave"; -+ reg = <0x1e6ee000 0x100>; -+ interrupts = <23>; -+ status = "disabled"; -+ }; -+ - lpc: lpc@1e789000 { - compatible = "aspeed,ast2500-lpc", "simple-mfd"; - reg = <0x1e789000 0x1000>; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch deleted file mode 100644 index b9de9f5a9..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0015-New-flash-map-for-intel.patch +++ /dev/null @@ -1,117 +0,0 @@ -From f57d473a30f208754457bdb63512c307f7499ac8 Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Mon, 4 Jun 2018 13:45:42 -0700 -Subject: [PATCH] New flash map for intel - -Signed-off-by: Vernon Mauery -Signed-off-by: Vikram Bodireddy ---- - .../boot/dts/openbmc-flash-layout-intel-128MB.dtsi | 50 ++++++++++++++++++++++ - .../boot/dts/openbmc-flash-layout-intel-64MB.dtsi | 38 ++++++++++++++++ - 2 files changed, 88 insertions(+) - create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi - create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi - -diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi -new file mode 100644 -index 000000000000..0d3794423aed ---- /dev/null -+++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi -@@ -0,0 +1,50 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// 128MB flash layout: PFR (active + tmp1/tmp2 + extra) -+// image with common RW partition -+ -+partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ u-boot@0 { -+ reg = <0x0 0x80000>; -+ label = "u-boot"; -+ }; -+ -+ pfm@80000 { -+ reg = <0x80000 0x20000>; -+ label = "pfm"; -+ }; -+ -+ u-boot-env@a0000 { -+ reg = <0xa0000 0x20000>; -+ label = "u-boot-env"; -+ }; -+ -+ sofs@c0000 { -+ reg = <0xc0000 0x200000>; -+ label = "sofs"; -+ }; -+ -+ rwfs@2c0000 { -+ reg = <0x2c0000 0x840000>; -+ label = "rwfs"; -+ }; -+ -+ fit-image-a@b00000 { -+ reg = <0xb00000 0x1f00000>; -+ label = "image-a"; -+ }; -+ -+ rc-image@2a00000 { -+ reg = <0x2a00000 0x2000000>; -+ label = "rc-image"; -+ }; -+ -+ image-staging@4a00000 { -+ reg = <0x4a00000 0x3600000>; -+ label = "image-stg"; -+ }; -+ -+}; -diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi -new file mode 100644 -index 000000000000..092708f5021f ---- /dev/null -+++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi -@@ -0,0 +1,38 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// 64MB flash layout: redundant image with common RW partition -+ -+partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ u-boot@0 { -+ reg = <0x0 0x80000>; -+ label = "u-boot"; -+ }; -+ -+ fit-image-a@80000 { -+ reg = <0x80000 0x1b80000>; -+ label = "image-a"; -+ }; -+ -+ sofs@1c00000 { -+ reg = <0x1c00000 0x200000>; -+ label = "sofs"; -+ }; -+ -+ rwfs@1e00000 { -+ reg = <0x1e00000 0x600000>; -+ label = "rwfs"; -+ }; -+ -+ u-boot-env@2400000 { -+ reg = <0x2400000 0x20000>; -+ label = "u-boot-env"; -+ }; -+ -+ fit-image-b@2480000 { -+ reg = <0x2480000 0x1b80000>; -+ label = "image-b"; -+ }; -+}; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch deleted file mode 100644 index 950272e1b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0016-Add-ASPEED-SGPIO-driver.patch +++ /dev/null @@ -1,760 +0,0 @@ -From a49e262cca260d15dc245fdd1870c89068042063 Mon Sep 17 00:00:00 2001 -From: "Feist, James" -Date: Tue, 4 Jun 2019 14:00:39 -0700 -Subject: [PATCH] Add ASPEED SGPIO driver - -Add SGPIO driver support for Aspeed SoCs. - -Signed-off-by: James Feist -Signed-off-by: Jae Hyun Yoo ---- - drivers/gpio/Kconfig | 8 + - drivers/gpio/Makefile | 1 + - drivers/gpio/sgpio-aspeed.c | 704 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 713 insertions(+) - create mode 100644 drivers/gpio/sgpio-aspeed.c - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 7138290cdd36..0235b20a95f6 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -128,6 +128,14 @@ config GPIO_ASPEED_SGPIO - help - Say Y here to support Aspeed AST2500 SGPIO functionality. - -+config SGPIO_ASPEED -+ tristate "ASPEED SGPIO support" -+ depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO -+ select GPIO_GENERIC -+ select GPIOLIB_IRQCHIP -+ help -+ Say Y here to support ASPEED SGPIO functionality. -+ - config GPIO_ATH79 - tristate "Atheros AR71XX/AR724X/AR913X GPIO support" - default y if ATH79 -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index e4599f90f702..0e80c8cd5ae7 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o - obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o - obj-$(CONFIG_GPIO_ASPEED_SGPIO) += gpio-aspeed-sgpio.o -+obj-$(CONFIG_SGPIO_ASPEED) += sgpio-aspeed.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o - obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o -diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c -new file mode 100644 -index 000000000000..5028e9144a75 ---- /dev/null -+++ b/drivers/gpio/sgpio-aspeed.c -@@ -0,0 +1,704 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+// Copyright (c) 2019 Intel Corporation -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ASPEED_SGPIO_CTRL 0x54 -+#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) -+#define ASPEED_SGPIO_CLK_DIV_MIN 1 -+#define ASPEED_SGPIO_CLK_DIV_MAX 65535 -+#define ASPEED_SGPIO_PINBYTES_MASK GENMASK(9, 6) -+#define ASPEED_SGPIO_PINBYTES_MIN 1 -+#define ASPEED_SGPIO_PINBYTES_MAX 10 -+#define ASPEED_SGPIO_ENABLE BIT(0) -+ -+#define ASPEED_SGPIO_BUS_FREQ_DEFAULT 1000000 -+ -+struct aspeed_bank_props { -+ unsigned int bank; -+ u32 input; -+ u32 output; -+}; -+ -+struct aspeed_sgpio_config { -+ unsigned int nr_pgpios; -+ unsigned int nr_gpios; -+ const struct aspeed_bank_props *props; -+}; -+ -+struct aspeed_sgpio { -+ struct gpio_chip chip; -+ struct irq_chip irqc; -+ spinlock_t lock; -+ void __iomem *base; -+ int irq; -+ const struct aspeed_sgpio_config *config; -+}; -+ -+struct aspeed_sgpio_bank { -+ uint16_t val_reg; -+ uint16_t rdata_reg; -+ uint16_t tolerance_reg; -+ uint16_t irq_regs; -+ bool support_irq; -+ const char names[4][3]; -+}; -+ -+/* -+ * Note: The "val" register returns the input value sampled on the line. -+ * Or, it can be used for writing a value on the line. -+ * -+ * The "rdata" register returns the content of the write latch and thus -+ * can be used to read back what was last written reliably. -+ */ -+ -+static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = { -+ { -+ .val_reg = 0x0000, -+ .rdata_reg = 0x0070, -+ .tolerance_reg = 0x0018, -+ .irq_regs = 0x0004, -+ .support_irq = false, -+ .names = { "OA", "OB", "OC", "OD" }, -+ }, -+ { -+ .val_reg = 0x001C, -+ .rdata_reg = 0x0074, -+ .tolerance_reg = 0x0034, -+ .irq_regs = 0x0020, -+ .support_irq = false, -+ .names = { "OE", "OF", "OG", "OH" }, -+ }, -+ { -+ .val_reg = 0x0038, -+ .rdata_reg = 0x0078, -+ .tolerance_reg = 0x0050, -+ .irq_regs = 0x003C, -+ .support_irq = false, -+ .names = { "OI", "OJ" }, -+ }, -+ { -+ .val_reg = 0x0000, -+ .rdata_reg = 0x0070, -+ .tolerance_reg = 0x0018, -+ .irq_regs = 0x0004, -+ .support_irq = true, -+ .names = { "IA", "IB", "IC", "ID" }, -+ }, -+ { -+ .val_reg = 0x001C, -+ .rdata_reg = 0x0074, -+ .tolerance_reg = 0x0034, -+ .irq_regs = 0x0020, -+ .support_irq = true, -+ .names = { "IE", "IF", "IG", "IH" }, -+ }, -+ { -+ .val_reg = 0x0038, -+ .rdata_reg = 0x0078, -+ .tolerance_reg = 0x0050, -+ .irq_regs = 0x003C, -+ .support_irq = true, -+ .names = { "II", "IJ" }, -+ }, -+}; -+ -+enum aspeed_sgpio_reg { -+ reg_val, -+ reg_rdata, -+ reg_irq_enable, -+ reg_irq_type0, -+ reg_irq_type1, -+ reg_irq_type2, -+ reg_irq_status, -+ reg_tolerance, -+}; -+ -+#define GPIO_IRQ_ENABLE 0x00 -+#define GPIO_IRQ_TYPE0 0x04 -+#define GPIO_IRQ_TYPE1 0x08 -+#define GPIO_IRQ_TYPE2 0x0c -+#define GPIO_IRQ_STATUS 0x10 -+ -+/* This will be resolved at compile time */ -+static inline void __iomem *bank_reg(struct aspeed_sgpio *gpio, -+ const struct aspeed_sgpio_bank *bank, -+ const enum aspeed_sgpio_reg reg) -+{ -+ switch (reg) { -+ case reg_val: -+ return gpio->base + bank->val_reg; -+ case reg_rdata: -+ return gpio->base + bank->rdata_reg; -+ case reg_irq_enable: -+ return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE; -+ case reg_irq_type0: -+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0; -+ case reg_irq_type1: -+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1; -+ case reg_irq_type2: -+ return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; -+ case reg_irq_status: -+ return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; -+ case reg_tolerance: -+ return gpio->base + bank->tolerance_reg; -+ default: -+ WARN_ON(1); -+ } -+ -+ return NULL; -+} -+ -+#define GPIO_BANK(x) ((x) >> 5) -+#define GPIO_OFFSET(x) ((x) & 0x1f) -+#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) -+ -+static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) -+{ -+ unsigned int bank = GPIO_BANK(offset); -+ -+ WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks)); -+ return &aspeed_sgpio_banks[bank]; -+} -+ -+static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props) -+{ -+ return !(props->input || props->output); -+} -+ -+static inline const struct aspeed_bank_props *find_bank_props( -+ struct aspeed_sgpio *gpio, unsigned int offset) -+{ -+ const struct aspeed_bank_props *props = gpio->config->props; -+ -+ while (!is_bank_props_sentinel(props)) { -+ if (props->bank == GPIO_BANK(offset)) -+ return props; -+ props++; -+ } -+ -+ return NULL; -+} -+ -+static inline bool have_input(struct aspeed_sgpio *gpio, unsigned int offset) -+{ -+ const struct aspeed_bank_props *props = find_bank_props(gpio, offset); -+ -+ return !props || (props->input & GPIO_BIT(offset)); -+} -+ -+static inline bool have_output(struct aspeed_sgpio *gpio, unsigned int offset) -+{ -+ const struct aspeed_bank_props *props = find_bank_props(gpio, offset); -+ -+ return !props || (props->output & GPIO_BIT(offset)); -+} -+ -+static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ const struct aspeed_sgpio_bank *bank = to_bank(offset); -+ enum aspeed_sgpio_reg reg; -+ -+ if (have_output(gpio, offset)) -+ reg = reg_rdata; -+ else -+ reg = reg_val; -+ -+ return !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset)); -+} -+ -+static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) -+{ -+ const struct aspeed_sgpio_bank *bank = to_bank(offset); -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ unsigned long flags; -+ u32 reg; -+ -+ if (!have_output(gpio, offset)) -+ return; -+ -+ spin_lock_irqsave(&gpio->lock, flags); -+ -+ reg = ioread32(bank_reg(gpio, bank, reg_rdata)); -+ -+ if (val) -+ reg |= GPIO_BIT(offset); -+ else -+ reg &= ~GPIO_BIT(offset); -+ -+ iowrite32(reg, bank_reg(gpio, bank, reg_val)); -+ -+ spin_unlock_irqrestore(&gpio->lock, flags); -+} -+ -+static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ -+ if (!have_input(gpio, offset)) -+ return -ENOTSUPP; -+ -+ return 0; -+} -+ -+static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, -+ int val) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ -+ if (!have_output(gpio, offset)) -+ return -ENOTSUPP; -+ -+ aspeed_sgpio_set(gc, offset, val); -+ -+ return 0; -+} -+ -+static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ -+ if (have_output(gpio, offset)) -+ return 0; -+ else if (have_input(gpio, offset)) -+ return 1; -+ -+ return -ENOTSUPP; -+} -+ -+static inline int -+irqd_to_aspeed_sgpio_data(struct irq_data *d, struct aspeed_sgpio **gpio, -+ const struct aspeed_sgpio_bank **bank, -+ u32 *bit, int *offset) -+{ -+ struct aspeed_sgpio *internal; -+ -+ *offset = irqd_to_hwirq(d); -+ -+ internal = irq_data_get_irq_chip_data(d); -+ -+ *gpio = internal; -+ *bank = to_bank(*offset); -+ *bit = GPIO_BIT(*offset); -+ -+ return 0; -+} -+ -+static void aspeed_sgpio_irq_ack(struct irq_data *d) -+{ -+ const struct aspeed_sgpio_bank *bank; -+ struct aspeed_sgpio *gpio; -+ void __iomem *status_addr; -+ unsigned long flags; -+ int rc, offset; -+ u32 bit; -+ -+ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); -+ if (rc) -+ return; -+ -+ status_addr = bank_reg(gpio, bank, reg_irq_status); -+ -+ spin_lock_irqsave(&gpio->lock, flags); -+ -+ iowrite32(bit, status_addr); -+ -+ spin_unlock_irqrestore(&gpio->lock, flags); -+} -+ -+static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) -+{ -+ const struct aspeed_sgpio_bank *bank; -+ struct aspeed_sgpio *gpio; -+ unsigned long flags; -+ u32 reg, bit; -+ void __iomem *addr; -+ int rc, offset; -+ -+ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); -+ if (rc) -+ return; -+ -+ if (!bank->support_irq) -+ return; -+ -+ addr = bank_reg(gpio, bank, reg_irq_enable); -+ -+ spin_lock_irqsave(&gpio->lock, flags); -+ -+ reg = ioread32(addr); -+ if (set) -+ reg |= bit; -+ else -+ reg &= ~bit; -+ -+ iowrite32(reg, addr); -+ -+ spin_unlock_irqrestore(&gpio->lock, flags); -+} -+ -+static void aspeed_sgpio_irq_mask(struct irq_data *d) -+{ -+ aspeed_sgpio_irq_set_mask(d, false); -+} -+ -+static void aspeed_sgpio_irq_unmask(struct irq_data *d) -+{ -+ aspeed_sgpio_irq_set_mask(d, true); -+} -+ -+static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) -+{ -+ u32 type0 = 0; -+ u32 type1 = 0; -+ u32 type2 = 0; -+ u32 bit, reg; -+ const struct aspeed_sgpio_bank *bank; -+ irq_flow_handler_t handler; -+ struct aspeed_sgpio *gpio; -+ unsigned long flags; -+ void __iomem *addr; -+ int rc, offset; -+ -+ rc = irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); -+ if (rc) -+ return -EINVAL; -+ -+ if (!bank->support_irq) -+ return -ENOTSUPP; -+ -+ switch (type & IRQ_TYPE_SENSE_MASK) { -+ case IRQ_TYPE_EDGE_BOTH: -+ type2 |= bit; -+ /* fall through */ -+ case IRQ_TYPE_EDGE_RISING: -+ type0 |= bit; -+ /* fall through */ -+ case IRQ_TYPE_EDGE_FALLING: -+ handler = handle_edge_irq; -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ type0 |= bit; -+ /* fall through */ -+ case IRQ_TYPE_LEVEL_LOW: -+ type1 |= bit; -+ handler = handle_level_irq; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&gpio->lock, flags); -+ -+ addr = bank_reg(gpio, bank, reg_irq_type0); -+ reg = ioread32(addr); -+ reg = (reg & ~bit) | type0; -+ iowrite32(reg, addr); -+ -+ addr = bank_reg(gpio, bank, reg_irq_type1); -+ reg = ioread32(addr); -+ reg = (reg & ~bit) | type1; -+ iowrite32(reg, addr); -+ -+ addr = bank_reg(gpio, bank, reg_irq_type2); -+ reg = ioread32(addr); -+ reg = (reg & ~bit) | type2; -+ iowrite32(reg, addr); -+ -+ spin_unlock_irqrestore(&gpio->lock, flags); -+ -+ irq_set_handler_locked(d, handler); -+ -+ return 0; -+} -+ -+static void aspeed_sgpio_irq_handler(struct irq_desc *desc) -+{ -+ struct gpio_chip *gc = irq_desc_get_handler_data(desc); -+ struct aspeed_sgpio *data = gpiochip_get_data(gc); -+ struct irq_chip *ic = irq_desc_get_chip(desc); -+ unsigned int i, p, girq; -+ unsigned long reg; -+ -+ chained_irq_enter(ic, desc); -+ -+ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { -+ const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i]; -+ -+ if (!bank->support_irq) -+ continue; -+ -+ reg = ioread32(bank_reg(data, bank, reg_irq_status)); -+ -+ for_each_set_bit(p, ®, 32) { -+ girq = irq_find_mapping(gc->irq.domain, i * 32 + p); -+ generic_handle_irq(girq); -+ } -+ } -+ -+ chained_irq_exit(ic, desc); -+} -+ -+static void aspeed_sgpio_init_irq_valid_mask(struct gpio_chip *gc, -+ unsigned long *valid_mask, -+ unsigned int ngpios) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(gc); -+ const struct aspeed_bank_props *props = gpio->config->props; -+ -+ while (!is_bank_props_sentinel(props)) { -+ unsigned int offset; -+ const unsigned long int input = props->input; -+ -+ /* Pretty crummy approach, but similar to GPIO core */ -+ for_each_clear_bit(offset, &input, 32) { -+ unsigned int i = props->bank * 32 + offset; -+ -+ if (i >= gpio->chip.ngpio) -+ break; -+ -+ clear_bit(i, valid_mask); -+ } -+ -+ props++; -+ } -+} -+ -+static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, -+ struct platform_device *pdev) -+{ -+ const struct aspeed_sgpio_bank *bank; -+ struct gpio_irq_chip *girq; -+ int rc, i; -+ -+ /* Initialize IRQ and tolerant settings */ -+ for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { -+ bank = &aspeed_sgpio_banks[i]; -+ -+ /* Value will be reset by WDT reset */ -+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_tolerance)); -+ -+ if (!bank->support_irq) -+ continue; -+ -+ /* disable irq enable bits */ -+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable)); -+ /* clear status bits */ -+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); -+ /* set rising or level-high irq */ -+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type0)); -+ /* trigger type is level */ -+ iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type1)); -+ /* single trigger mode */ -+ iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2)); -+ } -+ -+ rc = platform_get_irq(pdev, 0); -+ if (rc < 0) -+ return rc; -+ -+ gpio->irq = rc; -+ girq = &gpio->chip.irq; -+ girq->chip = &gpio->irqc; -+ girq->chip->name = dev_name(&pdev->dev); -+ girq->chip->irq_ack = aspeed_sgpio_irq_ack; -+ girq->chip->irq_mask = aspeed_sgpio_irq_mask; -+ girq->chip->irq_unmask = aspeed_sgpio_irq_unmask; -+ girq->chip->irq_set_type = aspeed_sgpio_set_type; -+ girq->parent_handler = aspeed_sgpio_irq_handler; -+ girq->num_parents = 1; -+ girq->parents = devm_kcalloc(&pdev->dev, 1, -+ sizeof(*girq->parents), -+ GFP_KERNEL); -+ if (!girq->parents) -+ return -ENOMEM; -+ girq->parents[0] = gpio->irq; -+ girq->default_type = IRQ_TYPE_NONE; -+ girq->handler = handle_bad_irq; -+ girq->init_valid_mask = aspeed_sgpio_init_irq_valid_mask; -+ -+ return 0; -+} -+ -+static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, -+ unsigned int offset, bool enable) -+{ -+ struct aspeed_sgpio *gpio = gpiochip_get_data(chip); -+ unsigned long flags; -+ void __iomem *treg; -+ u32 val; -+ -+ treg = bank_reg(gpio, to_bank(offset), reg_tolerance); -+ -+ spin_lock_irqsave(&gpio->lock, flags); -+ -+ val = readl(treg); -+ -+ if (enable) -+ val |= GPIO_BIT(offset); -+ else -+ val &= ~GPIO_BIT(offset); -+ -+ writel(val, treg); -+ -+ spin_unlock_irqrestore(&gpio->lock, flags); -+ -+ return 0; -+} -+ -+static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset, -+ unsigned long config) -+{ -+ unsigned long param = pinconf_to_config_param(config); -+ u32 arg = pinconf_to_config_argument(config); -+ -+ if (param == PIN_CONFIG_PERSIST_STATE) -+ return aspeed_sgpio_reset_tolerance(chip, offset, arg); -+ -+ return -ENOTSUPP; -+} -+ -+/* -+ * Any banks not specified in a struct aspeed_bank_props array are assumed to -+ * have the properties: -+ * -+ * { .input = 0xffffffff, .output = 0xffffffff } -+ */ -+ -+static const struct aspeed_bank_props ast_sgpio_bank_props[] = { -+ /* input output */ -+ { 0, 0x00000000, 0xffffffff }, /* OA/OB/OC/OD */ -+ { 1, 0x00000000, 0xffffffff }, /* OE/OF/OG/OH */ -+ { 2, 0x00000000, 0x0000ffff }, /* OI/OJ */ -+ { 3, 0xffffffff, 0x00000000 }, /* IA/IB/IC/ID */ -+ { 4, 0xffffffff, 0x00000000 }, /* IE/IF/IG/IH */ -+ { 5, 0x0000ffff, 0x00000000 }, /* II/IJ */ -+ { } -+}; -+ -+/* -+ * This H/W has 80 bidirectional lines so this driver provides total 160 lines -+ * for 80 outputs and 80 inputs. To simplify bank register manipulation, it -+ * uses 96 lines per each input and output set so total 192 lines it has. -+ */ -+static const struct aspeed_sgpio_config ast2400_config = -+ { .nr_pgpios = 224, .nr_gpios = 192, .props = ast_sgpio_bank_props }; -+ -+static const struct aspeed_sgpio_config ast2500_config = -+ { .nr_pgpios = 232, .nr_gpios = 192, .props = ast_sgpio_bank_props }; -+ -+static const struct of_device_id aspeed_sgpio_of_table[] = { -+ { .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_config }, -+ { .compatible = "aspeed,ast2500-sgpio", .data = &ast2500_config }, -+ { .compatible = "aspeed,ast2600-sgpio", .data = &ast2500_config }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); -+ -+static int __init aspeed_sgpio_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *gpio_id; -+ u32 sgpio_freq, clk_div, nb_gpios; -+ struct aspeed_sgpio *gpio; -+ unsigned long src_freq; -+ struct clk *clk; -+ int rc; -+ -+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); -+ if (!gpio) -+ return -ENOMEM; -+ -+ gpio->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(gpio->base)) -+ return PTR_ERR(gpio->base); -+ -+ spin_lock_init(&gpio->lock); -+ -+ gpio_id = of_match_node(aspeed_sgpio_of_table, pdev->dev.of_node); -+ if (!gpio_id) -+ return -EINVAL; -+ -+ gpio->config = gpio_id->data; -+ -+ rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq); -+ if (rc < 0) { -+ dev_warn(&pdev->dev, "Could not read bus-frequency property. Use default.\n"); -+ sgpio_freq = ASPEED_SGPIO_BUS_FREQ_DEFAULT; -+ } -+ -+ clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ rc = PTR_ERR(clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "Failed to get clk source.\n"); -+ return rc; -+ } -+ -+ /* -+ * There is a limitation that SGPIO clock division has to be larger or -+ * equal to 1. And a read back value of clock division is 1-bit left -+ * shifted from the actual value. -+ * -+ * GPIO254[31:16] - Serial GPIO clock division: -+ * Serial GPIO clock period = period of PCLK * 2 * (GPIO254[31:16] + 1) -+ * -+ * SGPIO master controller updates every data input when SGPMLD is low. -+ * For an example, SGPIO clock is 1MHz and number of SGPIO is 80. Each -+ * SGPIO will be updated every 80us. -+ */ -+ src_freq = clk_get_rate(clk); -+ clk_div = src_freq / (2 * sgpio_freq) - 1; -+ if (clk_div < ASPEED_SGPIO_CLK_DIV_MIN) -+ clk_div = ASPEED_SGPIO_CLK_DIV_MIN; -+ else if (clk_div > ASPEED_SGPIO_CLK_DIV_MAX) -+ clk_div = ASPEED_SGPIO_CLK_DIV_MAX; -+ -+ nb_gpios = gpio->config->nr_gpios / 16; -+ if (nb_gpios < ASPEED_SGPIO_PINBYTES_MIN) -+ nb_gpios = ASPEED_SGPIO_PINBYTES_MIN; -+ else if (nb_gpios > ASPEED_SGPIO_PINBYTES_MAX) -+ nb_gpios = ASPEED_SGPIO_PINBYTES_MAX; -+ -+ iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, clk_div) | -+ FIELD_PREP(ASPEED_SGPIO_PINBYTES_MASK, nb_gpios) | -+ ASPEED_SGPIO_ENABLE, -+ gpio->base + ASPEED_SGPIO_CTRL); -+ -+ gpio->chip.parent = &pdev->dev; -+ gpio->chip.ngpio = gpio->config->nr_gpios; -+ -+ gpio->chip.direction_input = aspeed_sgpio_dir_in; -+ gpio->chip.direction_output = aspeed_sgpio_dir_out; -+ gpio->chip.get_direction = aspeed_sgpio_get_direction; -+ gpio->chip.get = aspeed_sgpio_get; -+ gpio->chip.set = aspeed_sgpio_set; -+ gpio->chip.set_config = aspeed_sgpio_set_config; -+ gpio->chip.label = dev_name(&pdev->dev); -+ gpio->chip.base = -1; -+ -+ rc = aspeed_sgpio_setup_irqs(gpio, pdev); -+ if (rc < 0) -+ return rc; -+ -+ return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); -+} -+ -+static struct platform_driver aspeed_sgpio_driver = { -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .of_match_table = aspeed_sgpio_of_table, -+ }, -+}; -+ -+module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); -+ -+MODULE_AUTHOR("Jae Hyun Yoo "); -+MODULE_DESCRIPTION("Aspeed SGPIO Master Driver"); -+MODULE_LICENSE("GPL v2"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch deleted file mode 100644 index 50c31f625..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0017-SGPIO-DT-and-pinctrl-fixup.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 89b5ebd26fc44b4bf820aa507bc88eec028ba218 Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Wed, 16 May 2018 10:03:14 -0700 -Subject: [PATCH] SGPIO DT and pinctrl fixup - -This commit fixes DT and pinctrl for SGPIO use. - -Signed-off-by: Vernon Mauery -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g4.dtsi | 56 +++++++++++------------------- - arch/arm/boot/dts/aspeed-g5.dtsi | 3 +- - arch/arm/boot/dts/aspeed-g6.dtsi | 15 ++++++++ - drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c | 48 ++++++++++++------------- - 4 files changed, 60 insertions(+), 62 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index b875c0785833..e9fd66ab3099 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -254,6 +254,20 @@ - #interrupt-cells = <2>; - }; - -+ sgpio: sgpio@1e780200 { -+ #gpio-cells = <2>; -+ gpio-controller; -+ compatible = "aspeed,ast2400-sgpio"; -+ reg = <0x1e780200 0x0100>; -+ interrupts = <40>; -+ interrupt-controller; -+ clocks = <&syscon ASPEED_CLK_APB>; -+ bus-frequency = <1000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_sgpm_default>; -+ status = "disabled"; -+ }; -+ - timer: timer@1e782000 { - /* This timer is a Faraday FTTMR010 derivative */ - compatible = "aspeed,ast2400-timer"; -@@ -1227,44 +1241,14 @@ - groups = "SD2"; - }; - -- pinctrl_sgpmck_default: sgpmck_default { -- function = "SGPMCK"; -- groups = "SGPMCK"; -- }; -- -- pinctrl_sgpmi_default: sgpmi_default { -- function = "SGPMI"; -- groups = "SGPMI"; -- }; -- -- pinctrl_sgpmld_default: sgpmld_default { -- function = "SGPMLD"; -- groups = "SGPMLD"; -- }; -- -- pinctrl_sgpmo_default: sgpmo_default { -- function = "SGPMO"; -- groups = "SGPMO"; -- }; -- -- pinctrl_sgpsck_default: sgpsck_default { -- function = "SGPSCK"; -- groups = "SGPSCK"; -- }; -- -- pinctrl_sgpsi0_default: sgpsi0_default { -- function = "SGPSI0"; -- groups = "SGPSI0"; -- }; -- -- pinctrl_sgpsi1_default: sgpsi1_default { -- function = "SGPSI1"; -- groups = "SGPSI1"; -+ pinctrl_sgpm_default: sgpm_default { -+ function = "SGPM"; -+ groups = "SGPM"; - }; - -- pinctrl_sgpsld_default: sgpsld_default { -- function = "SGPSLD"; -- groups = "SGPSLD"; -+ pinctrl_sgps_default: sgps_default { -+ function = "SGPS"; -+ groups = "SGPS"; - }; - - pinctrl_sioonctrl_default: sioonctrl_default { -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 452ec323534f..20b2eb8052b7 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -326,8 +326,7 @@ - reg = <0x1e780200 0x0100>; - clocks = <&syscon ASPEED_CLK_APB>; - interrupt-controller; -- ngpios = <8>; -- bus-frequency = <12000000>; -+ bus-frequency = <1000000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sgpm_default>; - status = "disabled"; -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 54add29d8217..459070693aba 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -339,6 +339,21 @@ - #interrupt-cells = <2>; - }; - -+ sgpio: sgpio@1e780500 { -+ #gpio-cells = <2>; -+ gpio-controller; -+ compatible = "aspeed,ast2600-sgpio"; -+ reg = <0x1e780500 0x0100>; -+ #interrupt-cells = <2>; -+ interrupts = ; -+ interrupt-controller; -+ bus-frequency = <1000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_sgpm1_default>; -+ clocks = <&syscon ASPEED_CLK_APB1>; -+ status = "disabled"; -+ }; -+ - rtc: rtc@1e781000 { - compatible = "aspeed,ast2600-rtc"; - reg = <0x1e781000 0x18>; -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c -index bfed0e274643..10dadfd0e6e1 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c -@@ -430,16 +430,22 @@ SSSF_PIN_DECL(E16, GPIOF6, TXD4, SIG_DESC_SET(SCU80, 30)); - SSSF_PIN_DECL(C17, GPIOF7, RXD4, SIG_DESC_SET(SCU80, 31)); - - #define A14 48 --SSSF_PIN_DECL(A14, GPIOG0, SGPSCK, SIG_DESC_SET(SCU84, 0)); -+SIG_EXPR_LIST_DECL_SINGLE(A14, SGPSCK, SGPS, SIG_DESC_SET(SCU84, 0)); -+PIN_DECL_1(A14, GPIOG0, SGPSCK); - - #define E13 49 --SSSF_PIN_DECL(E13, GPIOG1, SGPSLD, SIG_DESC_SET(SCU84, 1)); -+SIG_EXPR_LIST_DECL_SINGLE(E13, SGPSLD, SGPS, SIG_DESC_SET(SCU84, 1)); -+PIN_DECL_1(E13, GPIOG1, SGPSLD); - - #define D13 50 --SSSF_PIN_DECL(D13, GPIOG2, SGPSI0, SIG_DESC_SET(SCU84, 2)); -+SIG_EXPR_LIST_DECL_SINGLE(D13, SGPSIO, SGPS, SIG_DESC_SET(SCU84, 2)); -+PIN_DECL_1(D13, GPIOG2, SGPSIO); - - #define C13 51 --SSSF_PIN_DECL(C13, GPIOG3, SGPSI1, SIG_DESC_SET(SCU84, 3)); -+SIG_EXPR_LIST_DECL_SINGLE(C13, SGPSI1, SGPS, SIG_DESC_SET(SCU84, 3)); -+PIN_DECL_1(C13, GPIOG3, SGPSI1); -+ -+FUNC_GROUP_DECL(SGPS, A14, E13, D13, C13); - - #define B13 52 - SIG_EXPR_LIST_DECL_SINGLE(B13, OSCCLK, OSCCLK, SIG_DESC_SET(SCU2C, 1)); -@@ -613,16 +619,22 @@ FUNC_GROUP_DECL(SPI1PASSTHRU, C22, G18, D19, C20, B22, G19, C18, E20); - FUNC_GROUP_DECL(VGABIOS_ROM, B22, G19, C18, E20); - - #define J5 72 --SSSF_PIN_DECL(J5, GPIOJ0, SGPMCK, SIG_DESC_SET(SCU84, 8)); -+SIG_EXPR_LIST_DECL_SINGLE(J5, SGPMCK, SGPM, SIG_DESC_SET(SCU84, 8)); -+PIN_DECL_1(J5, GPIOJ0, SGPMCK); - - #define J4 73 --SSSF_PIN_DECL(J4, GPIOJ1, SGPMLD, SIG_DESC_SET(SCU84, 9)); -+SIG_EXPR_LIST_DECL_SINGLE(J4, SGPMLD, SGPM, SIG_DESC_SET(SCU84, 9)); -+PIN_DECL_1(J4, GPIOJ1, SGPMLD); - - #define K5 74 --SSSF_PIN_DECL(K5, GPIOJ2, SGPMO, SIG_DESC_SET(SCU84, 10)); -+SIG_EXPR_LIST_DECL_SINGLE(K5, SGPMO, SGPM, SIG_DESC_SET(SCU84, 10)); -+PIN_DECL_1(K5, GPIOJ2, SGPMO); - - #define J3 75 --SSSF_PIN_DECL(J3, GPIOJ3, SGPMI, SIG_DESC_SET(SCU84, 11)); -+SIG_EXPR_LIST_DECL_SINGLE(J3, SGPMI, SGPM, SIG_DESC_SET(SCU84, 11)); -+PIN_DECL_1(J3, GPIOJ3, SGPMI); -+ -+FUNC_GROUP_DECL(SGPM, J5, J4, K5, J3); - - #define T4 76 - SSSF_PIN_DECL(T4, GPIOJ4, VGAHS, SIG_DESC_SET(SCU84, 12)); -@@ -2234,14 +2246,8 @@ static const struct aspeed_pin_group aspeed_g4_groups[] = { - ASPEED_PINCTRL_GROUP(SALT4), - ASPEED_PINCTRL_GROUP(SD1), - ASPEED_PINCTRL_GROUP(SD2), -- ASPEED_PINCTRL_GROUP(SGPMCK), -- ASPEED_PINCTRL_GROUP(SGPMI), -- ASPEED_PINCTRL_GROUP(SGPMLD), -- ASPEED_PINCTRL_GROUP(SGPMO), -- ASPEED_PINCTRL_GROUP(SGPSCK), -- ASPEED_PINCTRL_GROUP(SGPSI0), -- ASPEED_PINCTRL_GROUP(SGPSI1), -- ASPEED_PINCTRL_GROUP(SGPSLD), -+ ASPEED_PINCTRL_GROUP(SGPM), -+ ASPEED_PINCTRL_GROUP(SGPS), - ASPEED_PINCTRL_GROUP(SIOONCTRL), - ASPEED_PINCTRL_GROUP(SIOPBI), - ASPEED_PINCTRL_GROUP(SIOPBO), -@@ -2389,14 +2395,8 @@ static const struct aspeed_pin_function aspeed_g4_functions[] = { - ASPEED_PINCTRL_FUNC(SALT4), - ASPEED_PINCTRL_FUNC(SD1), - ASPEED_PINCTRL_FUNC(SD2), -- ASPEED_PINCTRL_FUNC(SGPMCK), -- ASPEED_PINCTRL_FUNC(SGPMI), -- ASPEED_PINCTRL_FUNC(SGPMLD), -- ASPEED_PINCTRL_FUNC(SGPMO), -- ASPEED_PINCTRL_FUNC(SGPSCK), -- ASPEED_PINCTRL_FUNC(SGPSI0), -- ASPEED_PINCTRL_FUNC(SGPSI1), -- ASPEED_PINCTRL_FUNC(SGPSLD), -+ ASPEED_PINCTRL_FUNC(SGPM), -+ ASPEED_PINCTRL_FUNC(SGPS), - ASPEED_PINCTRL_FUNC(SIOONCTRL), - ASPEED_PINCTRL_FUNC(SIOPBI), - ASPEED_PINCTRL_FUNC(SIOPBO), --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch deleted file mode 100644 index 128b11ecf..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0019-Add-I2C-IPMB-support.patch +++ /dev/null @@ -1,425 +0,0 @@ -From f588865f8180a6370ac639bdfc186ffc5b926246 Mon Sep 17 00:00:00 2001 -From: Haiyue Wang -Date: Tue, 13 Feb 2018 14:28:12 +0800 -Subject: [PATCH] Add I2C IPMB support - -Some protocols over I2C are designed for bi-directional transferring -messages by using I2C Master Write protocol. Like the MCTP (Management -Component Transport Protocol) and IPMB (Intelligent Platform Management -Bus), they both require that the userspace can receive messages from -I2C dirvers under slave mode. - -This new slave mqueue backend is used to receive and queue messages, it -will exposes these messages to userspace by sysfs bin file. - -Signed-off-by: Haiyue Wang ---- - Documentation/i2c/slave-mqueue-backend.rst | 124 +++++++++++++++++ - drivers/i2c/Kconfig | 23 +++ - drivers/i2c/Makefile | 1 + - drivers/i2c/i2c-slave-mqueue.c | 217 +++++++++++++++++++++++++++++ - 4 files changed, 365 insertions(+) - create mode 100644 Documentation/i2c/slave-mqueue-backend.rst - create mode 100644 drivers/i2c/i2c-slave-mqueue.c - -diff --git a/Documentation/i2c/slave-mqueue-backend.rst b/Documentation/i2c/slave-mqueue-backend.rst -new file mode 100644 -index 000000000000..2d0d06d8df9d ---- /dev/null -+++ b/Documentation/i2c/slave-mqueue-backend.rst -@@ -0,0 +1,124 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+===================================== -+Linux I2C slave message queue backend -+===================================== -+ -+:Author: Haiyue Wang -+ -+Some protocols over I2C/SMBus are designed for bi-directional transferring -+messages by using I2C Master Write protocol. This requires that both sides -+of the communication have slave addresses. -+ -+Like MCTP (Management Component Transport Protocol) and IPMB (Intelligent -+Platform Management Bus), they both require that the userspace can receive -+messages from i2c dirvers under slave mode. -+ -+This I2C slave mqueue (message queue) backend is used to receive and queue -+messages from the remote i2c intelligent device; and it will add the target -+slave address (with R/W# bit is always 0) into the message at the first byte, -+so that userspace can use this byte to dispatch the messages into different -+handling modules. Also, like IPMB, the address byte is in its message format, -+it needs it to do checksum. -+ -+For messages are time related, so this backend will flush the oldest message -+to queue the newest one. -+ -+Link -+---- -+`Intelligent Platform Management Bus -+Communications Protocol Specification -+`_ -+ -+`Management Component Transport Protocol (MCTP) -+SMBus/I2C Transport Binding Specification -+`_ -+ -+How to use -+---------- -+For example, the I2C5 bus has slave address 0x10, the below command will create -+the related message queue interface: -+ -+ echo slave-mqueue 0x1010 > /sys/bus/i2c/devices/i2c-5/new_device -+ -+Then you can dump the messages like this: -+ -+ hexdump -C /sys/bus/i2c/devices/5-1010/slave-mqueue -+ -+Code Example -+------------ -+*Note: call 'lseek' before 'read', this is a requirement from kernfs' design.* -+ -+:: -+ -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ #include -+ -+ int main(int argc, char *argv[]) -+ { -+ int i, r; -+ struct pollfd pfd; -+ struct timespec ts; -+ unsigned char data[256]; -+ -+ pfd.fd = open(argv[1], O_RDONLY | O_NONBLOCK); -+ if (pfd.fd < 0) -+ return -1; -+ -+ pfd.events = POLLPRI; -+ -+ while (1) { -+ r = poll(&pfd, 1, 5000); -+ -+ if (r < 0) -+ break; -+ -+ if (r == 0 || !(pfd.revents & POLLPRI)) -+ continue; -+ -+ lseek(pfd.fd, 0, SEEK_SET); -+ r = read(pfd.fd, data, sizeof(data)); -+ if (r <= 0) -+ continue; -+ -+ clock_gettime(CLOCK_MONOTONIC, &ts); -+ printf("[%ld.%.9ld] :", ts.tv_sec, ts.tv_nsec); -+ for (i = 0; i < r; i++) -+ printf(" %02x", data[i]); -+ printf("\n"); -+ } -+ -+ close(pfd.fd); -+ -+ return 0; -+ } -+ -+Result -+------ -+*./a.out "/sys/bus/i2c/devices/5-1010/slave-mqueue"* -+ -+:: -+ -+ [10183.232500449] : 20 18 c8 2c 78 01 5b -+ [10183.479358348] : 20 18 c8 2c 78 01 5b -+ [10183.726556812] : 20 18 c8 2c 78 01 5b -+ [10183.972605863] : 20 18 c8 2c 78 01 5b -+ [10184.220124772] : 20 18 c8 2c 78 01 5b -+ [10184.467764166] : 20 18 c8 2c 78 01 5b -+ [10193.233421784] : 20 18 c8 2c 7c 01 57 -+ [10193.480273460] : 20 18 c8 2c 7c 01 57 -+ [10193.726788733] : 20 18 c8 2c 7c 01 57 -+ [10193.972781945] : 20 18 c8 2c 7c 01 57 -+ [10194.220487360] : 20 18 c8 2c 7c 01 57 -+ [10194.468089259] : 20 18 c8 2c 7c 01 57 -+ [10203.233433099] : 20 18 c8 2c 80 01 53 -+ [10203.481058715] : 20 18 c8 2c 80 01 53 -+ [10203.727610472] : 20 18 c8 2c 80 01 53 -+ [10203.974044856] : 20 18 c8 2c 80 01 53 -+ [10204.220734634] : 20 18 c8 2c 80 01 53 -+ [10204.468461664] : 20 18 c8 2c 80 01 53 -diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig -index abedd55a1264..49a2379876c6 100644 ---- a/drivers/i2c/Kconfig -+++ b/drivers/i2c/Kconfig -@@ -119,6 +119,29 @@ if I2C_SLAVE - config I2C_SLAVE_EEPROM - tristate "I2C eeprom slave driver" - -+config I2C_SLAVE_MQUEUE_MESSAGE_SIZE -+ int "The message size of I2C mqueue slave" -+ default 120 -+ -+config I2C_SLAVE_MQUEUE_QUEUE_SIZE -+ int "The queue size of I2C mqueue slave" -+ default 32 -+ help -+ This number MUST be power of 2. -+ -+config I2C_SLAVE_MQUEUE -+ tristate "I2C mqueue (message queue) slave driver" -+ help -+ Some protocols over I2C are designed for bi-directional transferring -+ messages by using I2C Master Write protocol. This driver is used to -+ receive and queue messages from the remote I2C device. -+ -+ Userspace can get the messages by reading sysfs file that this driver -+ exposes. -+ -+ This support is also available as a module. If so, the module will be -+ called i2c-slave-mqueue. -+ - endif - - config I2C_DEBUG_CORE -diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile -index bed6ba63c983..9a31bc75a446 100644 ---- a/drivers/i2c/Makefile -+++ b/drivers/i2c/Makefile -@@ -16,5 +16,6 @@ obj-$(CONFIG_I2C_MUX) += i2c-mux.o - obj-y += algos/ busses/ muxes/ - obj-$(CONFIG_I2C_STUB) += i2c-stub.o - obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o -+obj-$(CONFIG_I2C_SLAVE_MQUEUE) += i2c-slave-mqueue.o - - ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG -diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c -new file mode 100644 -index 000000000000..6014bca0ff2a ---- /dev/null -+++ b/drivers/i2c/i2c-slave-mqueue.c -@@ -0,0 +1,217 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2017 - 2018, Intel Corporation. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MQ_MSGBUF_SIZE CONFIG_I2C_SLAVE_MQUEUE_MESSAGE_SIZE -+#define MQ_QUEUE_SIZE CONFIG_I2C_SLAVE_MQUEUE_QUEUE_SIZE -+#define MQ_QUEUE_NEXT(x) (((x) + 1) & (MQ_QUEUE_SIZE - 1)) -+ -+struct mq_msg { -+ int len; -+ u8 *buf; -+}; -+ -+struct mq_queue { -+ struct bin_attribute bin; -+ struct kernfs_node *kn; -+ -+ spinlock_t lock; /* spinlock for queue index handling */ -+ int in; -+ int out; -+ -+ struct mq_msg *curr; -+ int truncated; /* drop current if truncated */ -+ struct mq_msg *queue; -+}; -+ -+static int i2c_slave_mqueue_callback(struct i2c_client *client, -+ enum i2c_slave_event event, u8 *val) -+{ -+ struct mq_queue *mq = i2c_get_clientdata(client); -+ struct mq_msg *msg = mq->curr; -+ int ret = 0; -+ -+ switch (event) { -+ case I2C_SLAVE_WRITE_REQUESTED: -+ mq->truncated = 0; -+ -+ msg->len = 1; -+ msg->buf[0] = client->addr << 1; -+ break; -+ -+ case I2C_SLAVE_WRITE_RECEIVED: -+ if (msg->len < MQ_MSGBUF_SIZE) { -+ msg->buf[msg->len++] = *val; -+ } else { -+ dev_err(&client->dev, "message is truncated!\n"); -+ mq->truncated = 1; -+ ret = -EINVAL; -+ } -+ break; -+ -+ case I2C_SLAVE_STOP: -+ if (unlikely(mq->truncated || msg->len < 2)) -+ break; -+ -+ spin_lock(&mq->lock); -+ mq->in = MQ_QUEUE_NEXT(mq->in); -+ mq->curr = &mq->queue[mq->in]; -+ mq->curr->len = 0; -+ -+ /* Flush the oldest message */ -+ if (mq->out == mq->in) -+ mq->out = MQ_QUEUE_NEXT(mq->out); -+ spin_unlock(&mq->lock); -+ -+ kernfs_notify(mq->kn); -+ break; -+ -+ default: -+ *val = 0xFF; -+ break; -+ } -+ -+ return ret; -+} -+ -+static ssize_t i2c_slave_mqueue_bin_read(struct file *filp, -+ struct kobject *kobj, -+ struct bin_attribute *attr, -+ char *buf, loff_t pos, size_t count) -+{ -+ struct mq_queue *mq; -+ struct mq_msg *msg; -+ unsigned long flags; -+ bool more = false; -+ ssize_t ret = 0; -+ -+ mq = dev_get_drvdata(container_of(kobj, struct device, kobj)); -+ -+ spin_lock_irqsave(&mq->lock, flags); -+ if (mq->out != mq->in) { -+ msg = &mq->queue[mq->out]; -+ -+ if (msg->len <= count) { -+ ret = msg->len; -+ memcpy(buf, msg->buf, ret); -+ } else { -+ ret = -EOVERFLOW; /* Drop this HUGE one. */ -+ } -+ -+ mq->out = MQ_QUEUE_NEXT(mq->out); -+ if (mq->out != mq->in) -+ more = true; -+ } -+ spin_unlock_irqrestore(&mq->lock, flags); -+ -+ if (more) -+ kernfs_notify(mq->kn); -+ -+ return ret; -+} -+ -+static int i2c_slave_mqueue_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct device *dev = &client->dev; -+ struct mq_queue *mq; -+ int ret, i; -+ void *buf; -+ -+ mq = devm_kzalloc(dev, sizeof(*mq), GFP_KERNEL); -+ if (!mq) -+ return -ENOMEM; -+ -+ BUILD_BUG_ON(!is_power_of_2(MQ_QUEUE_SIZE)); -+ -+ buf = devm_kmalloc_array(dev, MQ_QUEUE_SIZE, MQ_MSGBUF_SIZE, -+ GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ mq->queue = devm_kzalloc(dev, sizeof(*mq->queue) * MQ_QUEUE_SIZE, -+ GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ for (i = 0; i < MQ_QUEUE_SIZE; i++) -+ mq->queue[i].buf = buf + i * MQ_MSGBUF_SIZE; -+ -+ i2c_set_clientdata(client, mq); -+ -+ spin_lock_init(&mq->lock); -+ mq->curr = &mq->queue[0]; -+ -+ sysfs_bin_attr_init(&mq->bin); -+ mq->bin.attr.name = "slave-mqueue"; -+ mq->bin.attr.mode = 0400; -+ mq->bin.read = i2c_slave_mqueue_bin_read; -+ mq->bin.size = MQ_MSGBUF_SIZE * MQ_QUEUE_SIZE; -+ -+ ret = sysfs_create_bin_file(&dev->kobj, &mq->bin); -+ if (ret) -+ return ret; -+ -+ mq->kn = kernfs_find_and_get(dev->kobj.sd, mq->bin.attr.name); -+ if (!mq->kn) { -+ sysfs_remove_bin_file(&dev->kobj, &mq->bin); -+ return -EFAULT; -+ } -+ -+ ret = i2c_slave_register(client, i2c_slave_mqueue_callback); -+ if (ret) { -+ kernfs_put(mq->kn); -+ sysfs_remove_bin_file(&dev->kobj, &mq->bin); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int i2c_slave_mqueue_remove(struct i2c_client *client) -+{ -+ struct mq_queue *mq = i2c_get_clientdata(client); -+ -+ i2c_slave_unregister(client); -+ -+ kernfs_put(mq->kn); -+ sysfs_remove_bin_file(&client->dev.kobj, &mq->bin); -+ -+ return 0; -+} -+ -+static const struct i2c_device_id i2c_slave_mqueue_id[] = { -+ { "slave-mqueue", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, i2c_slave_mqueue_id); -+ -+#if IS_ENABLED(CONFIG_OF) -+static const struct of_device_id i2c_slave_mqueue_of_match[] = { -+ { .compatible = "slave-mqueue", .data = (void *)0 }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, i2c_slave_mqueue_of_match); -+#endif -+ -+static struct i2c_driver i2c_slave_mqueue_driver = { -+ .driver = { -+ .name = "i2c-slave-mqueue", -+ .of_match_table = of_match_ptr(i2c_slave_mqueue_of_match), -+ }, -+ .probe = i2c_slave_mqueue_probe, -+ .remove = i2c_slave_mqueue_remove, -+ .id_table = i2c_slave_mqueue_id, -+}; -+module_i2c_driver(i2c_slave_mqueue_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Haiyue Wang "); -+MODULE_DESCRIPTION("I2C slave mode for receiving and queuing messages"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch deleted file mode 100644 index c5add2dd5..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0020-misc-aspeed-add-lpc-mbox-driver.patch +++ /dev/null @@ -1,491 +0,0 @@ -From 42326dfecd45c52918272cf6b65e6eb5b8499c46 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 10 Jul 2019 16:19:33 -0700 -Subject: [PATCH] misc: aspeed: add lpc mbox driver - -This commit adds back the lpc mbox driver which was removed from -the openbmc linux dev-5.2 tree. - -This driver should be rewritten later. - -Signed-off-by: Cyril Bur " -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Arun P. Mohanan ---- - arch/arm/boot/dts/aspeed-g4.dtsi | 9 + - arch/arm/boot/dts/aspeed-g5.dtsi | 9 + - arch/arm/boot/dts/aspeed-g6.dtsi | 1 + - drivers/soc/aspeed/Kconfig | 7 + - drivers/soc/aspeed/Makefile | 1 + - drivers/soc/aspeed/aspeed-lpc-mbox.c | 377 +++++++++++++++++++++++++++ - 6 files changed, 404 insertions(+) - create mode 100644 drivers/soc/aspeed/aspeed-lpc-mbox.c - -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index e9fd66ab3099..f3edda4ae477 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -393,6 +393,15 @@ - sio_regs: regs { - compatible = "aspeed,bmc-misc"; - }; -+ -+ mbox: mbox@180 { -+ compatible = "aspeed,ast2400-mbox"; -+ reg = <0x180 0x5c>; -+ interrupts = <46>; -+ #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; - }; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index b4ae3827ed1d..b69110b9eab9 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -522,6 +522,15 @@ - sio_regs: regs { - compatible = "aspeed,bmc-misc"; - }; -+ -+ mbox: mbox@180 { -+ compatible = "aspeed,ast2500-mbox"; -+ reg = <0x180 0x5c>; -+ interrupts = <46>; -+ #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; - }; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 825e64ce317a..183869eaf79a 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -594,6 +594,7 @@ - reg = <0x180 0x5c>; - interrupts = ; - #mbox-cells = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - }; - }; - }; -diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig -index a4b3cac87ce2..464a55c7eb39 100644 ---- a/drivers/soc/aspeed/Kconfig -+++ b/drivers/soc/aspeed/Kconfig -@@ -21,6 +21,13 @@ config ASPEED_LPC_CTRL - ioctl()s, the driver also provides a read/write interface to a BMC ram - region where the host LPC read/write region can be buffered. - -+config ASPEED_LPC_MBOX -+ tristate "Aspeed LPC Mailbox Controller" -+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON -+ ---help--- -+ Expose the ASPEED LPC MBOX registers found on Aspeed SOCs (AST2400 -+ and AST2500) to userspace. -+ - config ASPEED_LPC_SNOOP - tristate "Aspeed ast2500 HOST LPC snoop support" - depends on SOC_ASPEED && REGMAP && MFD_SYSCON -diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile -index 217d876fec25..26924c111af3 100644 ---- a/drivers/soc/aspeed/Makefile -+++ b/drivers/soc/aspeed/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0-only - obj-$(CONFIG_ASPEED_BMC_MISC) += aspeed-bmc-misc.o - obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o -+obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o - obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o - obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o - obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o -diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c -new file mode 100644 -index 000000000000..583feecc4f18 ---- /dev/null -+++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c -@@ -0,0 +1,377 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+// Copyright 2017 IBM Corporation -+// TODO: Rewrite this driver -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DEVICE_NAME "aspeed-mbox" -+ -+#define MBX_USE_INTERRUPT 0 -+ -+#define ASPEED_MBOX_NUM_REGS 16 -+ -+#define ASPEED_MBOX_DATA_0 0x00 -+#define ASPEED_MBOX_STATUS_0 0x40 -+#define ASPEED_MBOX_STATUS_1 0x44 -+#define ASPEED_MBOX_BMC_CTRL 0x48 -+#define ASPEED_MBOX_CTRL_RECV BIT(7) -+#define ASPEED_MBOX_CTRL_MASK BIT(1) -+#define ASPEED_MBOX_CTRL_SEND BIT(0) -+#define ASPEED_MBOX_HOST_CTRL 0x4c -+#define ASPEED_MBOX_INTERRUPT_0 0x50 -+#define ASPEED_MBOX_INTERRUPT_1 0x54 -+ -+struct aspeed_mbox { -+ struct miscdevice miscdev; -+ struct regmap *regmap; -+ struct clk *clk; -+ unsigned int base; -+ int irq; -+ wait_queue_head_t queue; -+ struct mutex mutex; -+}; -+ -+static atomic_t aspeed_mbox_open_count = ATOMIC_INIT(0); -+ -+static u8 aspeed_mbox_inb(struct aspeed_mbox *mbox, int reg) -+{ -+ /* -+ * The mbox registers are actually only one byte but are addressed -+ * four bytes apart. The other three bytes are marked 'reserved', -+ * they *should* be zero but lets not rely on it. -+ * I am going to rely on the fact we can casually read/write to them... -+ */ -+ unsigned int val = 0xff; /* If regmap throws an error return 0xff */ -+ int rc = regmap_read(mbox->regmap, mbox->base + reg, &val); -+ -+ if (rc) -+ dev_err(mbox->miscdev.parent, "regmap_read() failed with " -+ "%d (reg: 0x%08x)\n", rc, reg); -+ -+ return val & 0xff; -+} -+ -+static void aspeed_mbox_outb(struct aspeed_mbox *mbox, u8 data, int reg) -+{ -+ int rc = regmap_write(mbox->regmap, mbox->base + reg, data); -+ -+ if (rc) -+ dev_err(mbox->miscdev.parent, "regmap_write() failed with " -+ "%d (data: %u reg: 0x%08x)\n", rc, data, reg); -+} -+ -+static struct aspeed_mbox *file_mbox(struct file *file) -+{ -+ return container_of(file->private_data, struct aspeed_mbox, miscdev); -+} -+ -+static int aspeed_mbox_open(struct inode *inode, struct file *file) -+{ -+#if MBX_USE_INTERRUPT -+ struct aspeed_mbox *mbox = file_mbox(file); -+#endif -+ -+ if (atomic_inc_return(&aspeed_mbox_open_count) == 1) { -+#if MBX_USE_INTERRUPT -+ /* -+ * Clear the interrupt status bit if it was left on and unmask -+ * interrupts. -+ * ASPEED_MBOX_CTRL_RECV bit is W1C, this also unmasks in 1 step -+ */ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+#endif -+ return 0; -+ } -+ -+ atomic_dec(&aspeed_mbox_open_count); -+ return -EBUSY; -+} -+ -+static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ char __user *p = buf; -+ ssize_t ret; -+ int i; -+ -+ if (!access_ok(buf, count)) -+ return -EFAULT; -+ -+ if (count + *ppos > ASPEED_MBOX_NUM_REGS) -+ return -EINVAL; -+ -+#if MBX_USE_INTERRUPT -+ if (file->f_flags & O_NONBLOCK) { -+ if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -+ ASPEED_MBOX_CTRL_RECV)) -+ return -EAGAIN; -+ } else if (wait_event_interruptible(mbox->queue, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -+ ASPEED_MBOX_CTRL_RECV)) { -+ return -ERESTARTSYS; -+ } -+#endif -+ -+ mutex_lock(&mbox->mutex); -+ -+ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) { -+ uint8_t reg = aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4)); -+ -+ ret = __put_user(reg, p); -+ if (ret) -+ goto out_unlock; -+ -+ p++; -+ count--; -+ } -+ -+#if MBX_USE_INTERRUPT -+ /* ASPEED_MBOX_CTRL_RECV bit is write to clear, this also unmasks in 1 step */ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+#endif -+ ret = p - buf; -+ -+out_unlock: -+ mutex_unlock(&mbox->mutex); -+ return ret; -+} -+ -+static ssize_t aspeed_mbox_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ const char __user *p = buf; -+ ssize_t ret; -+ char c; -+ int i; -+ -+ if (!access_ok(buf, count)) -+ return -EFAULT; -+ -+ if (count + *ppos > ASPEED_MBOX_NUM_REGS) -+ return -EINVAL; -+ -+ mutex_lock(&mbox->mutex); -+ -+ for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) { -+ ret = __get_user(c, p); -+ if (ret) -+ goto out_unlock; -+ -+ aspeed_mbox_outb(mbox, c, ASPEED_MBOX_DATA_0 + (i * 4)); -+ p++; -+ count--; -+ } -+ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV | ASPEED_MBOX_CTRL_MASK | ASPEED_MBOX_CTRL_SEND, ASPEED_MBOX_BMC_CTRL); -+ ret = p - buf; -+ -+out_unlock: -+ mutex_unlock(&mbox->mutex); -+ return ret; -+} -+ -+static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait) -+{ -+ struct aspeed_mbox *mbox = file_mbox(file); -+ unsigned int mask = 0; -+ -+ poll_wait(file, &mbox->queue, wait); -+ -+#if MBX_USE_INTERRUPT -+ if (aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV) -+#endif -+ mask |= POLLIN; -+ -+ return mask; -+} -+ -+static int aspeed_mbox_release(struct inode *inode, struct file *file) -+{ -+ atomic_dec(&aspeed_mbox_open_count); -+ return 0; -+} -+ -+static const struct file_operations aspeed_mbox_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_seek_end_llseek, -+ .read = aspeed_mbox_read, -+ .write = aspeed_mbox_write, -+ .open = aspeed_mbox_open, -+ .release = aspeed_mbox_release, -+ .poll = aspeed_mbox_poll, -+}; -+ -+static irqreturn_t aspeed_mbox_irq(int irq, void *arg) -+{ -+ struct aspeed_mbox *mbox = arg; -+#if MBX_USE_INTERRUPT -+ int i; -+ -+// if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV)) -+// return IRQ_NONE; -+ -+ printk(KERN_ERR "BMC_CTRL: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL)); -+ printk(KERN_ERR "STATUS_0: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_0)); -+ printk(KERN_ERR "STATUS_1: 0x%02x\n", -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_1)); -+ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) { -+ printk(KERN_ERR "DATA_%d: 0x%02x\n", i, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4))); -+ } -+#endif -+ -+ /* Clear interrupt status */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+ -+ wake_up(&mbox->queue); -+ return IRQ_HANDLED; -+} -+ -+static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox, -+ struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ int rc; -+ -+ mbox->irq = platform_get_irq(pdev, 0); -+ if (!mbox->irq) -+ return -ENODEV; -+ -+ rc = devm_request_irq(dev, mbox->irq, aspeed_mbox_irq, -+ IRQF_SHARED, DEVICE_NAME, mbox); -+ if (rc < 0) { -+ dev_err(dev, "Unable to request IRQ %d\n", mbox->irq); -+ return rc; -+ } -+ -+ /* Disable all register based interrupts. */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_0); /* regs 0 - 7 */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_INTERRUPT_1); /* regs 8 - 15 */ -+ -+ /* These registers are write one to clear. Clear them. */ -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_0); -+ aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STATUS_1); -+ -+ aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+ return 0; -+} -+ -+static int aspeed_mbox_probe(struct platform_device *pdev) -+{ -+ struct aspeed_mbox *mbox; -+ struct device *dev; -+ int rc; -+ -+ dev = &pdev->dev; -+ -+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL); -+ if (!mbox) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&pdev->dev, mbox); -+ -+ rc = of_property_read_u32(dev->of_node, "reg", &mbox->base); -+ if (rc) { -+ dev_err(dev, "Couldn't read reg device-tree property\n"); -+ return rc; -+ } -+ -+ mbox->regmap = syscon_node_to_regmap( -+ pdev->dev.parent->of_node); -+ if (IS_ERR(mbox->regmap)) { -+ dev_err(dev, "Couldn't get regmap\n"); -+ return -ENODEV; -+ } -+ -+ mutex_init(&mbox->mutex); -+ init_waitqueue_head(&mbox->queue); -+ -+ mbox->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(mbox->clk)) { -+ rc = PTR_ERR(mbox->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; -+ } -+ rc = clk_prepare_enable(mbox->clk); -+ if (rc) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return rc; -+ } -+ -+ mbox->miscdev.minor = MISC_DYNAMIC_MINOR; -+ mbox->miscdev.name = DEVICE_NAME; -+ mbox->miscdev.fops = &aspeed_mbox_fops; -+ mbox->miscdev.parent = dev; -+ rc = misc_register(&mbox->miscdev); -+ if (rc) { -+ dev_err(dev, "Unable to register device\n"); -+ goto err; -+ } -+ -+ rc = aspeed_mbox_config_irq(mbox, pdev); -+ if (rc) { -+ dev_err(dev, "Failed to configure IRQ\n"); -+ misc_deregister(&mbox->miscdev); -+ goto err; -+ } -+ -+ dev_info(&pdev->dev, "LPC mbox registered, irq %d\n", mbox->irq); -+ -+ return 0; -+ -+err: -+ clk_disable_unprepare(mbox->clk); -+ -+ return rc; -+} -+ -+static int aspeed_mbox_remove(struct platform_device *pdev) -+{ -+ struct aspeed_mbox *mbox = dev_get_drvdata(&pdev->dev); -+ -+ misc_deregister(&mbox->miscdev); -+ clk_disable_unprepare(mbox->clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_mbox_match[] = { -+ { .compatible = "aspeed,ast2400-mbox" }, -+ { .compatible = "aspeed,ast2500-mbox" }, -+ { .compatible = "aspeed,ast2600-mbox" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, aspeed_mbox_match); -+ -+static struct platform_driver aspeed_mbox_driver = { -+ .driver = { -+ .name = DEVICE_NAME, -+ .of_match_table = aspeed_mbox_match, -+ }, -+ .probe = aspeed_mbox_probe, -+ .remove = aspeed_mbox_remove, -+}; -+ -+module_platform_driver(aspeed_mbox_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Cyril Bur "); -+MODULE_DESCRIPTION("Aspeed mailbox device driver"); --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch deleted file mode 100644 index b4b1bcad8..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch +++ /dev/null @@ -1,580 +0,0 @@ -From 39f76bd49fd481999cf51fbdfbea3e820efc7227 Mon Sep 17 00:00:00 2001 -From: Yong Li -Date: Mon, 13 Nov 2017 16:29:44 +0800 -Subject: [PATCH] Aspeed LPC SIO driver - -Add lpc sio device driver for AST2500/2400 - -Signed-off-by: Yong Li -Signed-off-by: Jae Hyun Yoo ---- - .../bindings/soc/aspeed/aspeed-lpc-sio.txt | 17 + - arch/arm/boot/dts/aspeed-g4.dtsi | 7 + - arch/arm/boot/dts/aspeed-g5.dtsi | 7 + - drivers/soc/aspeed/Kconfig | 7 + - drivers/soc/aspeed/Makefile | 1 + - drivers/soc/aspeed/aspeed-lpc-sio.c | 410 +++++++++++++++++++++ - include/uapi/linux/aspeed-lpc-sio.h | 45 +++ - 7 files changed, 494 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt - create mode 100644 drivers/soc/aspeed/aspeed-lpc-sio.c - create mode 100644 include/uapi/linux/aspeed-lpc-sio.h - -diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt -new file mode 100644 -index 000000000000..c74ea3a4e5ac ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-lpc-sio.txt -@@ -0,0 +1,17 @@ -+* Aspeed LPC SIO driver. -+ -+Required properties: -+- compatible : Should be one of: -+ "aspeed,ast2400-lpc-sio" -+ "aspeed,ast2500-lpc-sio" -+- reg : Should contain lpc-sio registers location and length -+- clocks: contains a phandle to the syscon node describing the clocks. -+ There should then be one cell representing the clock to use. -+ -+Example: -+lpc_sio: lpc-sio@100 { -+ compatible = "aspeed,ast2500-lpc-sio"; -+ reg = <0x100 0x20>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index f3edda4ae477..a70bee24d058 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -394,6 +394,13 @@ - compatible = "aspeed,bmc-misc"; - }; - -+ lpc_sio: lpc-sio@100 { -+ compatible = "aspeed,ast2400-lpc-sio"; -+ reg = <0x100 0x20>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ - mbox: mbox@180 { - compatible = "aspeed,ast2400-mbox"; - reg = <0x180 0x5c>; -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index bd6d1461e4bd..c15be82c3a9d 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -503,6 +503,13 @@ - compatible = "aspeed,bmc-misc"; - }; - -+ lpc_sio: lpc-sio@100 { -+ compatible = "aspeed,ast2500-lpc-sio"; -+ reg = <0x100 0x20>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ - mbox: mbox@180 { - compatible = "aspeed,ast2500-mbox"; - reg = <0x180 0x5c>; -diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig -index a4be8e566bc7..285c19042c65 100644 ---- a/drivers/soc/aspeed/Kconfig -+++ b/drivers/soc/aspeed/Kconfig -@@ -28,6 +28,13 @@ config ASPEED_LPC_MBOX - Expose the ASPEED LPC MBOX registers found on Aspeed SOCs (AST2400 - and AST2500) to userspace. - -+config ASPEED_LPC_SIO -+ tristate "Aspeed ast2400/2500 HOST LPC SIO support" -+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON -+ help -+ Provides a driver to control the LPC SIO interface on ASPEED platform -+ through ioctl()s. -+ - config ASPEED_LPC_SNOOP - tristate "Aspeed ast2500 HOST LPC snoop support" - depends on SOC_ASPEED && REGMAP && MFD_SYSCON -diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile -index f3ff29b874ed..2e547cc47e62 100644 ---- a/drivers/soc/aspeed/Makefile -+++ b/drivers/soc/aspeed/Makefile -@@ -2,5 +2,6 @@ - obj-$(CONFIG_ASPEED_BMC_MISC) += aspeed-bmc-misc.o - obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o - obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o -+obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o - obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o - obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o -diff --git a/drivers/soc/aspeed/aspeed-lpc-sio.c b/drivers/soc/aspeed/aspeed-lpc-sio.c -new file mode 100644 -index 000000000000..d4a4da112ff4 ---- /dev/null -+++ b/drivers/soc/aspeed/aspeed-lpc-sio.c -@@ -0,0 +1,410 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2012-2017 ASPEED Technology Inc. -+// Copyright (c) 2017-2020 Intel Corporation -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define SOC_NAME "aspeed" -+#define DEVICE_NAME "lpc-sio" -+ -+#define AST_LPC_SWCR0300 0x00 -+#define LPC_PWRGD_STS BIT(30) -+#define LPC_PWRGD_RISING_EVT_STS BIT(29) -+#define LPC_PWRGD_FALLING_EVT_STS BIT(28) -+#define LPC_PWRBTN_STS BIT(27) -+#define LPC_PWRBTN_RISING_EVT_STS BIT(26) -+#define LPC_PWRBTN_FALLING_EVT_STS BIT(25) -+#define LPC_S5N_STS BIT(21) -+#define LPC_S5N_RISING_EVT_STS BIT(20) -+#define LPC_S5N_FALLING_EVT_STS BIT(19) -+#define LPC_S3N_STS BIT(18) -+#define LPC_S3N_RISING_EVT_STS BIT(17) -+#define LPC_S3N_FALLING_EVT_STS BIT(16) -+#define LPC_PWBTO_RAW_STS BIT(15) -+#define LPC_LAST_ONCTL_STS BIT(14) -+#define LPC_WAS_PFAIL_STS BIT(13) -+#define LPC_POWER_UP_FAIL_STS BIT(12) /* Crowbar */ -+#define LPC_PWRBTN_OVERRIDE_STS BIT(11) -+#define LPC_BMC_TRIG_WAKEUP_EVT_STS BIT(8) -+ -+#define AST_LPC_SWCR0704 0x04 -+#define LPC_BMC_TRIG_WAKEUP_EVT_EN BIT(8) -+ -+#define AST_LPC_SWCR0B08 0x08 -+#define LPC_PWREQ_OUTPUT_LEVEL BIT(25) -+#define LPC_PWBTO_OUTPUT_LEVEL BIT(24) -+#define LPC_ONCTL_STS BIT(15) -+#define LPC_ONCTL_GPIO_LEVEL BIT(14) -+#define LPC_ONCTL_EN_GPIO_OUTPUT BIT(13) -+#define LPC_ONCTL_EN_GPIO_MODE BIT(12) -+#define LPC_BMC_TRIG_WAKEUP_EVT BIT(6) -+ -+#define AST_LPC_SWCR0F0C 0x0C -+#define AST_LPC_SWCR1310 0x10 -+#define AST_LPC_SWCR1714 0x14 -+#define AST_LPC_SWCR1B18 0x18 -+#define AST_LPC_SWCR1F1C 0x1C -+#define AST_LPC_ACPIE3E0 0x20 -+#define AST_LPC_ACPIC1C0 0x24 -+ -+#define AST_LPC_ACPIB3B0 0x28 -+#define LPC_BMC_TRIG_SCI_EVT_STS BIT(8) -+ -+#define AST_LPC_ACPIB7B4 0x2C -+#define LPC_BMC_TRIG_SCI_EVT_EN BIT(8) -+ -+struct aspeed_lpc_sio { -+ struct miscdevice miscdev; -+ struct regmap *regmap; -+ struct clk *clk; -+ struct semaphore lock; -+ unsigned int reg_base; -+}; -+ -+static struct aspeed_lpc_sio *file_aspeed_lpc_sio(struct file *file) -+{ -+ return container_of(file->private_data, struct aspeed_lpc_sio, -+ miscdev); -+} -+ -+static int aspeed_lpc_sio_open(struct inode *inode, struct file *filp) -+{ -+ return 0; -+} -+ -+#define LPC_SLP3N5N_EVENT_STATUS (\ -+ LPC_S5N_RISING_EVT_STS | \ -+ LPC_S5N_FALLING_EVT_STS | \ -+ LPC_S3N_RISING_EVT_STS | \ -+ LPC_S3N_FALLING_EVT_STS) -+ -+/* -+ * SLPS3n SLPS5n State -+ * --------------------------------- -+ * 1 1 S12 -+ * 0 1 S3I -+ * x 0 S45 -+ ************************************* -+ */ -+ -+static void sio_get_acpi_state(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0300; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ /* update the ACPI state event status */ -+ if (sio_data->param != 0) { -+ if (val & LPC_SLP3N5N_EVENT_STATUS) { -+ sio_data->param = 1; -+ regmap_write(lpc_sio->regmap, reg, -+ LPC_SLP3N5N_EVENT_STATUS); -+ } else { -+ sio_data->param = 0; -+ } -+ } -+ -+ if ((val & LPC_S3N_STS) && (val & LPC_S5N_STS)) -+ sio_data->data = ACPI_STATE_S12; -+ else if ((val & LPC_S3N_STS) == 0 && (val & LPC_S5N_STS)) -+ sio_data->data = ACPI_STATE_S3I; -+ else -+ sio_data->data = ACPI_STATE_S45; -+} -+ -+#define LPC_PWRGD_EVENT_STATUS ( \ -+ LPC_PWRGD_RISING_EVT_STS | \ -+ LPC_PWRGD_FALLING_EVT_STS) -+ -+static void sio_get_pwrgd_status(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0300; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ /* update the PWRGD event status */ -+ if (sio_data->param != 0) { -+ if (val & LPC_PWRGD_EVENT_STATUS) { -+ sio_data->param = 1; -+ regmap_write(lpc_sio->regmap, reg, -+ LPC_PWRGD_EVENT_STATUS); -+ } else { -+ sio_data->param = 0; -+ } -+ } -+ -+ sio_data->data = (val & LPC_PWRGD_STS) != 0 ? 1 : 0; -+} -+ -+static void sio_get_onctl_status(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ sio_data->data = (val & LPC_ONCTL_STS) != 0 ? 1 : 0; -+} -+ -+static void sio_set_onctl_gpio(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ /* Enable ONCTL GPIO mode */ -+ if (sio_data->param != 0) { -+ val |= LPC_ONCTL_EN_GPIO_MODE; -+ val |= LPC_ONCTL_EN_GPIO_OUTPUT; -+ -+ if (sio_data->data != 0) -+ val |= LPC_ONCTL_GPIO_LEVEL; -+ else -+ val &= ~LPC_ONCTL_GPIO_LEVEL; -+ -+ regmap_write(lpc_sio->regmap, reg, val); -+ } else { -+ val &= ~LPC_ONCTL_EN_GPIO_MODE; -+ regmap_write(lpc_sio->regmap, reg, val); -+ } -+} -+ -+static void sio_get_pwrbtn_override(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0300; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ /* clear the PWRBTN OVERRIDE status */ -+ if (sio_data->param != 0 && val & LPC_PWRBTN_OVERRIDE_STS) -+ regmap_write(lpc_sio->regmap, reg, LPC_PWRBTN_OVERRIDE_STS); -+ -+ sio_data->data = (val & LPC_PWRBTN_OVERRIDE_STS) != 0 ? 1 : 0; -+} -+ -+static void sio_get_pfail_status(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg, val; -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0300; -+ regmap_read(lpc_sio->regmap, reg, &val); -+ -+ /* [ASPEED]: SWCR_03_00[13] (Was_pfail: default 1) is used to identify -+ * this current booting is from AC loss (not DC loss) if FW cleans this -+ * bit after booting successfully every time. -+ **********************************************************************/ -+ if (val & LPC_WAS_PFAIL_STS) { -+ regmap_write(lpc_sio->regmap, reg, 0); /* W0C */ -+ sio_data->data = 1; -+ } else { -+ sio_data->data = 0; -+ } -+} -+ -+static void sio_set_bmc_sci_event(struct aspeed_lpc_sio *lpc_sio, -+ struct sio_ioctl_data *sio_data) -+{ -+ u32 reg; -+ -+ if (sio_data->param) { -+ reg = lpc_sio->reg_base + AST_LPC_ACPIB7B4; -+ regmap_write_bits(lpc_sio->regmap, reg, -+ LPC_BMC_TRIG_SCI_EVT_EN, -+ LPC_BMC_TRIG_SCI_EVT_EN); -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0704; -+ regmap_write_bits(lpc_sio->regmap, reg, -+ LPC_BMC_TRIG_WAKEUP_EVT_EN, -+ LPC_BMC_TRIG_WAKEUP_EVT_EN); -+ -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0B08; -+ regmap_write_bits(lpc_sio->regmap, reg, -+ LPC_BMC_TRIG_WAKEUP_EVT, -+ LPC_BMC_TRIG_WAKEUP_EVT); -+ } else { -+ reg = lpc_sio->reg_base + AST_LPC_SWCR0300; -+ regmap_write_bits(lpc_sio->regmap, reg, -+ LPC_BMC_TRIG_WAKEUP_EVT_STS, -+ LPC_BMC_TRIG_WAKEUP_EVT_STS); -+ -+ reg = lpc_sio->reg_base + AST_LPC_ACPIB3B0; -+ regmap_write_bits(lpc_sio->regmap, reg, -+ LPC_BMC_TRIG_SCI_EVT_STS, -+ LPC_BMC_TRIG_SCI_EVT_STS); -+ } -+ -+ sio_data->data = sio_data->param; -+} -+ -+typedef void (*sio_cmd_fn) (struct aspeed_lpc_sio *sio_dev, -+ struct sio_ioctl_data *sio_data); -+ -+static sio_cmd_fn sio_cmd_handle[SIO_MAX_CMD] = { -+ [SIO_GET_ACPI_STATE] = sio_get_acpi_state, -+ [SIO_GET_PWRGD_STATUS] = sio_get_pwrgd_status, -+ [SIO_GET_ONCTL_STATUS] = sio_get_onctl_status, -+ [SIO_SET_ONCTL_GPIO] = sio_set_onctl_gpio, -+ [SIO_GET_PWRBTN_OVERRIDE] = sio_get_pwrbtn_override, -+ [SIO_GET_PFAIL_STATUS] = sio_get_pfail_status, -+ [SIO_SET_BMC_SCI_EVENT] = sio_set_bmc_sci_event, -+}; -+ -+static long aspeed_lpc_sio_ioctl(struct file *file, unsigned int cmd, -+ unsigned long param) -+{ -+ struct aspeed_lpc_sio *lpc_sio = file_aspeed_lpc_sio(file); -+ struct sio_ioctl_data sio_data; -+ sio_cmd_fn cmd_fn; -+ long ret; -+ -+ if (copy_from_user(&sio_data, (void __user *)param, sizeof(sio_data))) -+ return -EFAULT; -+ -+ if (cmd != SIO_IOC_COMMAND || sio_data.sio_cmd >= SIO_MAX_CMD) -+ return -EINVAL; -+ -+ cmd_fn = sio_cmd_handle[sio_data.sio_cmd]; -+ if (!cmd_fn) -+ return -EINVAL; -+ -+ if (down_interruptible(&lpc_sio->lock) != 0) -+ return -ERESTARTSYS; -+ -+ cmd_fn(lpc_sio, &sio_data); -+ ret = copy_to_user((void __user *)param, &sio_data, sizeof(sio_data)); -+ -+ up(&lpc_sio->lock); -+ -+ return ret; -+} -+ -+static const struct file_operations aspeed_lpc_sio_fops = { -+ .owner = THIS_MODULE, -+ .open = aspeed_lpc_sio_open, -+ .unlocked_ioctl = aspeed_lpc_sio_ioctl, -+}; -+ -+static int aspeed_lpc_sio_probe(struct platform_device *pdev) -+{ -+ struct aspeed_lpc_sio *lpc_sio; -+ struct device *dev; -+ u32 val; -+ int ret; -+ -+ dev = &pdev->dev; -+ -+ lpc_sio = devm_kzalloc(dev, sizeof(*lpc_sio), GFP_KERNEL); -+ if (!lpc_sio) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&pdev->dev, lpc_sio); -+ -+ ret = of_property_read_u32(dev->of_node, "reg", &lpc_sio->reg_base); -+ if (ret) { -+ dev_err(dev, "Couldn't read reg device-tree property\n"); -+ return ret; -+ } -+ -+ lpc_sio->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node); -+ if (IS_ERR(lpc_sio->regmap)) { -+ dev_err(dev, "Couldn't get regmap\n"); -+ return -ENODEV; -+ } -+ -+ /* -+ * We check that the regmap works on this very first access, -+ * but as this is an MMIO-backed regmap, subsequent regmap -+ * access is not going to fail and we skip error checks from -+ * this point. -+ */ -+ ret = regmap_read(lpc_sio->regmap, AST_LPC_SWCR0300, &val); -+ if (ret) { -+ dev_err(dev, "failed to read regmap\n"); -+ return ret; -+ } -+ -+ sema_init(&lpc_sio->lock, 1); -+ -+ lpc_sio->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(lpc_sio->clk)) { -+ ret = PTR_ERR(lpc_sio->clk); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return ret; -+ } -+ ret = clk_prepare_enable(lpc_sio->clk); -+ if (ret) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return ret; -+ } -+ -+ lpc_sio->miscdev.minor = MISC_DYNAMIC_MINOR; -+ lpc_sio->miscdev.name = DEVICE_NAME; -+ lpc_sio->miscdev.fops = &aspeed_lpc_sio_fops; -+ lpc_sio->miscdev.parent = dev; -+ ret = misc_register(&lpc_sio->miscdev); -+ if (ret) { -+ dev_err(dev, "Unable to register device\n"); -+ goto err; -+ } -+ -+ dev_info(dev, "Loaded at %pap (0x%08x)\n", &lpc_sio->regmap, -+ lpc_sio->reg_base); -+ -+ return 0; -+ -+err: -+ clk_disable_unprepare(lpc_sio->clk); -+ -+ return ret; -+} -+ -+static int aspeed_lpc_sio_remove(struct platform_device *pdev) -+{ -+ struct aspeed_lpc_sio *lpc_sio = dev_get_drvdata(&pdev->dev); -+ -+ misc_deregister(&lpc_sio->miscdev); -+ clk_disable_unprepare(lpc_sio->clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_lpc_sio_match[] = { -+ { .compatible = "aspeed,ast2500-lpc-sio" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, aspeed_lpc_sio_match); -+ -+static struct platform_driver aspeed_lpc_sio_driver = { -+ .driver = { -+ .name = SOC_NAME "-" DEVICE_NAME, -+ .of_match_table = of_match_ptr(aspeed_lpc_sio_match), -+ }, -+ .probe = aspeed_lpc_sio_probe, -+ .remove = aspeed_lpc_sio_remove, -+}; -+module_platform_driver(aspeed_lpc_sio_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Ryan Chen "); -+MODULE_AUTHOR("Yong Li "); -+MODULE_DESCRIPTION("ASPEED AST LPC SIO device driver"); -diff --git a/include/uapi/linux/aspeed-lpc-sio.h b/include/uapi/linux/aspeed-lpc-sio.h -new file mode 100644 -index 000000000000..acf89a7d2b4a ---- /dev/null -+++ b/include/uapi/linux/aspeed-lpc-sio.h -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2012-2020 ASPEED Technology Inc. -+ * Copyright (c) 2017 Intel Corporation -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ */ -+ -+#ifndef _UAPI_LINUX_ASPEED_LPC_SIO_H -+#define _UAPI_LINUX_ASPEED_LPC_SIO_H -+ -+#include -+ -+enum ACPI_SLP_STATE { -+ ACPI_STATE_S12 = 1, -+ ACPI_STATE_S3I, -+ ACPI_STATE_S45 -+}; -+ -+/* SWC & ACPI for SuperIO IOCTL */ -+enum SIO_CMD { -+ SIO_GET_ACPI_STATE = 0, -+ SIO_GET_PWRGD_STATUS, -+ SIO_GET_ONCTL_STATUS, -+ SIO_SET_ONCTL_GPIO, -+ SIO_GET_PWRBTN_OVERRIDE, -+ SIO_GET_PFAIL_STATUS, /* Start from AC Loss */ -+ SIO_SET_BMC_SCI_EVENT, -+ -+ SIO_MAX_CMD -+}; -+ -+struct sio_ioctl_data { -+ unsigned short sio_cmd; -+ unsigned short param; -+ unsigned int data; -+}; -+ -+#define SIO_IOC_BASE 'P' -+#define SIO_IOC_COMMAND _IOWR(SIO_IOC_BASE, 1, struct sio_ioctl_data) -+ -+#endif /* _UAPI_LINUX_ASPEED_LPC_SIO_H */ --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch deleted file mode 100644 index c409dec50..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch +++ /dev/null @@ -1,762 +0,0 @@ -From e6e186acacc16fd95251b2d0fb024993a66ffa0a Mon Sep 17 00:00:00 2001 -From: Haiyue Wang -Date: Sat, 24 Feb 2018 11:12:32 +0800 -Subject: [PATCH] Add AST2500 eSPI driver - -When PCH works under eSPI mode, the PMC (Power Management Controller) in -PCH is waiting for SUS_ACK from BMC after it alerts SUS_WARN. It is in -dead loop if no SUS_ACK assert. This is the basic requirement for the BMC -works as eSPI slave. - -Also for the host power on / off actions, from BMC side, the following VW -(Virtual Wire) messages are done in firmware: -1. SLAVE_BOOT_LOAD_DONE / SLAVE_BOOT_LOAD_STATUS -2. SUS_ACK -3. OOB_RESET_ACK -4. HOST_RESET_ACK - -Also, it provides monitoring interface of PLTRST_N signal through -/dev/espi-pltrstn - -Signed-off-by: Haiyue Wang -Signed-off-by: Jae Hyun Yoo -Signed-off-by: James Feist -Signed-off-by: Vernon Mauery ---- - .../devicetree/bindings/misc/aspeed,espi-slave.txt | 20 + - Documentation/misc-devices/espi-slave.rst | 118 ++++++ - arch/arm/boot/dts/aspeed-g5.dtsi | 4 + - arch/arm/boot/dts/aspeed-g6.dtsi | 14 + - drivers/misc/Kconfig | 8 + - drivers/misc/Makefile | 1 + - drivers/misc/aspeed-espi-slave.c | 468 +++++++++++++++++++++ - include/dt-bindings/clock/ast2600-clock.h | 1 + - 8 files changed, 634 insertions(+) - create mode 100644 Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt - create mode 100644 Documentation/misc-devices/espi-slave.rst - create mode 100644 drivers/misc/aspeed-espi-slave.c - -diff --git a/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt b/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt -new file mode 100644 -index 000000000000..f72d9ae32f3e ---- /dev/null -+++ b/Documentation/devicetree/bindings/misc/aspeed,espi-slave.txt -@@ -0,0 +1,20 @@ -+ASPEED eSPI Slave Controller -+ -+Required properties: -+ - compatible: must be one of: -+ - "aspeed,ast2500-espi-slave" -+ - "aspeed,ast2600-espi-slave" -+ -+ - reg: physical base address of the controller and length of memory mapped -+ region -+ -+ - interrupts: interrupt generated by the controller -+ -+Example: -+ -+ espi: espi@1e6ee000 { -+ compatible = "aspeed,ast2500-espi-slave"; -+ reg = <0x1e6ee000 0x100>; -+ interrupts = <23>; -+ status = "disabled"; -+}; -diff --git a/Documentation/misc-devices/espi-slave.rst b/Documentation/misc-devices/espi-slave.rst -new file mode 100644 -index 000000000000..887a69a7130a ---- /dev/null -+++ b/Documentation/misc-devices/espi-slave.rst -@@ -0,0 +1,118 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+========== -+eSPI Slave -+========== -+ -+:Author: Haiyue Wang -+ -+The PCH (**eSPI master**) provides the eSPI to support connection of a -+BMC (**eSPI slave**) to the platform. -+ -+The LPC and eSPI interfaces are mutually exclusive. Both use the same -+pins, but on power-up, a HW strap determines if the eSPI or the LPC bus -+is operational. Once selected, it’s not possible to change to the other -+interface. -+ -+``eSPI Channels and Supported Transactions`` -+ +------+---------------------+----------------------+--------------------+ -+ | CH # | Channel | Posted Cycles | Non-Posted Cycles | -+ +======+=====================+======================+====================+ -+ | 0 | Peripheral | Memory Write, | Memory Read, | -+ | | | Completions | I/O Read/Write | -+ +------+---------------------+----------------------+--------------------+ -+ | 1 | Virtual Wire | Virtual Wire GET/PUT | N/A | -+ +------+---------------------+----------------------+--------------------+ -+ | 2 | Out-of-Band Message | SMBus Packet GET/PUT | N/A | -+ +------+---------------------+----------------------+--------------------+ -+ | 3 | Flash Access | N/A | Flash Read, Write, | -+ | | | | Erase | -+ +------+---------------------+----------------------+--------------------+ -+ | N/A | General | Register Accesses | N/A | -+ +------+---------------------+----------------------+--------------------+ -+ -+Virtual Wire Channel (Channel 1) Overview -+----------------------------------------- -+ -+The Virtual Wire channel uses a standard message format to communicate -+several types of signals between the components on the platform:: -+ -+ - Sideband and GPIO Pins: System events and other dedicated signals -+ between the PCH and eSPI slave. These signals are tunneled between the -+ two components over eSPI. -+ -+ - Serial IRQ Interrupts: Interrupts are tunneled from the eSPI slave to -+ the PCH. Both edge and triggered interrupts are supported. -+ -+When PCH runs on eSPI mode, from BMC side, the following VW messages are -+done in firmware:: -+ -+ 1. SLAVE_BOOT_LOAD_DONE / SLAVE_BOOT_LOAD_STATUS -+ 2. SUS_ACK -+ 3. OOB_RESET_ACK -+ 4. HOST_RESET_ACK -+ -+``eSPI Virtual Wires (VW)`` -+ +----------------------+---------+---------------------------------------+ -+ |Virtual Wire |PCH Pin |Comments | -+ | |Direction| | -+ +======================+=========+=======================================+ -+ |SUS_WARN# |Output |PCH pin is a GPIO when eSPI is enabled.| -+ | | |eSPI controller receives as VW message.| -+ +----------------------+---------+---------------------------------------+ -+ |SUS_ACK# |Input |PCH pin is a GPIO when eSPI is enabled.| -+ | | |eSPI controller receives as VW message.| -+ +----------------------+---------+---------------------------------------+ -+ |SLAVE_BOOT_LOAD_DONE |Input |Sent when the BMC has completed its | -+ | | |boot process as an indication to | -+ | | |eSPI-MC to continue with the G3 to S0 | -+ | | |exit. | -+ | | |The eSPI Master waits for the assertion| -+ | | |of this virtual wire before proceeding | -+ | | |with the SLP_S5# deassertion. | -+ | | |The intent is that it is never changed | -+ | | |except on a G3 exit - it is reset on a | -+ | | |G3 entry. | -+ +----------------------+---------+---------------------------------------+ -+ |SLAVE_BOOT_LOAD_STATUS|Input |Sent upon completion of the Slave Boot | -+ | | |Load from the attached flash. A stat of| -+ | | |1 indicates that the boot code load was| -+ | | |successful and that the integrity of | -+ | | |the image is intact. | -+ +----------------------+---------+---------------------------------------+ -+ |HOST_RESET_WARN |Output |Sent from the MC just before the Host | -+ | | |is about to enter reset. Upon receiving| -+ | | |, the BMC must flush and quiesce its | -+ | | |upstream Peripheral Channel request | -+ | | |queues and assert HOST_RESET_ACK VWire.| -+ | | |The MC subsequently completes any | -+ | | |outstanding posted transactions or | -+ | | |completions and then disables the | -+ | | |Peripheral Channel via a write to | -+ | | |the Slave's Configuration Register. | -+ +----------------------+---------+---------------------------------------+ -+ |HOST_RESET_ACK |Input |ACK for the HOST_RESET_WARN message | -+ +----------------------+---------+---------------------------------------+ -+ |OOB_RESET_WARN |Output |Sent from the MC just before the OOB | -+ | | |processor is about to enter reset. Upon| -+ | | |receiving, the BMC must flush and | -+ | | |quiesce its OOB Channel upstream | -+ | | |request queues and assert OOB_RESET_ACK| -+ | | |VWire. The-MC subsequently completes | -+ | | |any outstanding posted transactions or | -+ | | |completions and then disables the OOB | -+ | | |Channel via a write to the Slave's | -+ | | |Configuration Register. | -+ +----------------------+---------+---------------------------------------+ -+ |OOB_RESET_ACK |Input |ACK for OOB_RESET_WARN message | -+ +----------------------+---------+---------------------------------------+ -+ -+`Intel C620 Series Chipset Platform Controller Hub -+`_ -+ -+ -- 17. Enhanced Serial Peripheral Interface -+ -+ -+`Enhanced Serial Peripheral Interface (eSPI) -+- Interface Base Specification (for Client and Server Platforms) -+`_ -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 26d885d2bd8a..7b798c49cb95 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -336,6 +336,7 @@ - clocks = <&syscon ASPEED_CLK_APB>; - interrupt-controller; - #interrupt-cells = <2>; -+ status = "disabled"; - }; - - sgpio: sgpio@1e780200 { -@@ -432,6 +433,9 @@ - reg = <0x1e6ee000 0x100>; - interrupts = <23>; - status = "disabled"; -+ clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_espi_default>; - }; - - lpc: lpc@1e789000 { -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 825e64ce317a..315d35c15208 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - / { - model = "Aspeed BMC"; -@@ -708,6 +709,19 @@ - status = "disabled"; - }; - -+ espi: espi@1e6ee000 { -+ compatible = "aspeed,ast2600-espi-slave"; -+ reg = <0x1e6ee000 0x200>; -+ interrupts-extended = <&gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, -+ <&gpio0 ASPEED_GPIO(W, 7) IRQ_TYPE_EDGE_FALLING>; -+ status = "disabled"; -+ clocks = <&syscon ASPEED_CLK_GATE_ESPICLK>; -+ resets = <&syscon ASPEED_RESET_ESPI>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_espi_default>, -+ <&pinctrl_espialt_default>; -+ }; -+ - i2c: bus@1e78a000 { - compatible = "simple-bus"; - #address-cells = <1>; -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 06a2b753cc7c..0f9b5a356c93 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -433,6 +433,14 @@ config VEXPRESS_SYSCFG - bus. System Configuration interface is one of the possible means - of generating transactions on this bus. - -+config ASPEED_ESPI_SLAVE -+ depends on ARCH_ASPEED || COMPILE_TEST -+ depends on REGMAP_MMIO -+ tristate "Aspeed ast2500 eSPI slave device driver" -+ ---help--- -+ Control Aspeed ast2500 eSPI slave controller to handle event -+ which needs the firmware's processing. -+ - config PCI_ENDPOINT_TEST - depends on PCI - select CRC32 -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index b9e6d4c3e906..53864687e8fd 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -51,6 +51,7 @@ obj-$(CONFIG_GENWQE) += genwqe/ - obj-$(CONFIG_ECHO) += echo/ - obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o - obj-$(CONFIG_CXL_BASE) += cxl/ -+obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o - obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o - obj-$(CONFIG_OCXL) += ocxl/ - obj-y += cardreader/ -diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c -new file mode 100644 -index 000000000000..87bc81948694 ---- /dev/null -+++ b/drivers/misc/aspeed-espi-slave.c -@@ -0,0 +1,468 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2015-2019, Intel Corporation. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ASPEED_ESPI_CTRL 0x00 -+#define ASPEED_ESPI_CTRL_SW_RESET GENMASK(31, 24) -+#define ASPEED_ESPI_CTRL_OOB_CHRDY BIT(4) -+#define ASPEED_ESPI_INT_STS 0x08 -+#define ASPEED_ESPI_HW_RESET BIT(31) -+#define ASPEED_ESPI_VW_SYSEVT1 BIT(22) -+#define ASPEED_ESPI_VW_SYSEVT BIT(8) -+#define ASPEED_ESPI_INT_EN 0x0C -+#define ASPEED_ESPI_DATA_PORT 0x28 -+#define ASPEED_ESPI_SYSEVT_INT_EN 0x94 -+#define ASPEED_ESPI_SYSEVT 0x98 -+#define ASPEED_ESPI_SYSEVT_HOST_RST_ACK BIT(27) -+#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS BIT(23) -+#define ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE BIT(20) -+#define ASPEED_ESPI_SYSEVT_OOB_RST_ACK BIT(16) -+#define ASPEED_ESPI_SYSEVT_INT_T0 0x110 -+#define ASPEED_ESPI_SYSEVT_INT_T1 0x114 -+#define ASPEED_ESPI_SYSEVT_INT_T2 0x118 -+#define ASPEED_ESPI_SYSEVT_INT_STS 0x11C -+#define ASPEED_ESPI_SYSEVT_HOST_RST_WARN BIT(8) -+#define ASPEED_ESPI_SYSEVT_OOB_RST_WARN BIT(6) -+#define ASPEED_ESPI_SYSEVT_PLTRSTN BIT(5) -+#define ASPEED_ESPI_SYSEVT1_INT_EN 0x100 -+#define ASPEED_ESPI_SYSEVT1 0x104 -+#define ASPEED_ESPI_SYSEVT1_SUS_ACK BIT(20) -+#define ASPEED_ESPI_SYSEVT1_INT_T0 0x120 -+#define ASPEED_ESPI_SYSEVT1_INT_T1 0x124 -+#define ASPEED_ESPI_SYSEVT1_INT_T2 0x128 -+#define ASPEED_ESPI_SYSEVT1_INT_STS 0x12C -+#define ASPEED_ESPI_SYSEVT1_SUS_WARN BIT(0) -+ -+#define ASPEED_ESPI_INT_MASK \ -+ (ASPEED_ESPI_HW_RESET | \ -+ ASPEED_ESPI_VW_SYSEVT1 | \ -+ ASPEED_ESPI_VW_SYSEVT) -+ -+/* -+ * Setup Interrupt Type / Enable of System Event from Master -+ * T2 T1 T0 -+ * 1) HOST_RST_WARN : Dual Edge 1 0 0 -+ * 2) OOB_RST_WARN : Dual Edge 1 0 0 -+ * 3) PLTRSTN : Dual Edge 1 0 0 -+ */ -+#define ASPEED_ESPI_SYSEVT_INT_T0_MASK 0 -+#define ASPEED_ESPI_SYSEVT_INT_T1_MASK 0 -+#define ASPEED_ESPI_SYSEVT_INT_T2_MASK \ -+ (ASPEED_ESPI_SYSEVT_HOST_RST_WARN | \ -+ ASPEED_ESPI_SYSEVT_OOB_RST_WARN | \ -+ ASPEED_ESPI_SYSEVT_PLTRSTN) -+#define ASPEED_ESPI_SYSEVT_INT_MASK \ -+ (ASPEED_ESPI_SYSEVT_INT_T0_MASK | \ -+ ASPEED_ESPI_SYSEVT_INT_T1_MASK | \ -+ ASPEED_ESPI_SYSEVT_INT_T2_MASK) -+ -+/* -+ * Setup Interrupt Type / Enable of System Event 1 from Master -+ * T2 T1 T0 -+ * 1) SUS_WARN : Rising Edge 0 0 1 -+ */ -+#define ASPEED_ESPI_SYSEVT1_INT_T0_MASK ASPEED_ESPI_SYSEVT1_SUS_WARN -+#define ASPEED_ESPI_SYSEVT1_INT_T1_MASK 0 -+#define ASPEED_ESPI_SYSEVT1_INT_T2_MASK 0 -+#define ASPEED_ESPI_SYSEVT1_INT_MASK \ -+ (ASPEED_ESPI_SYSEVT1_INT_T0_MASK | \ -+ ASPEED_ESPI_SYSEVT1_INT_T1_MASK | \ -+ ASPEED_ESPI_SYSEVT1_INT_T2_MASK) -+ -+struct aspeed_espi { -+ struct regmap *map; -+ struct clk *clk; -+ struct device *dev; -+ struct reset_control *reset; -+ int irq; -+ int rst_irq; -+ -+ /* for PLTRST_N signal monitoring interface */ -+ struct miscdevice pltrstn_miscdev; -+ spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */ -+ wait_queue_head_t pltrstn_waitq; -+ char pltrstn; -+}; -+ -+static void aspeed_espi_sys_event(struct aspeed_espi *priv) -+{ -+ u32 sts, evt; -+ -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, &sts); -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt); -+ -+ dev_dbg(priv->dev, "sys: sts = %08x, evt = %08x\n", sts, evt); -+ -+ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) { -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT, -+ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS | -+ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE); -+ dev_dbg(priv->dev, "Setting espi slave boot done\n"); -+ } -+ if (sts & ASPEED_ESPI_SYSEVT_HOST_RST_WARN && -+ evt & ASPEED_ESPI_SYSEVT_HOST_RST_WARN) { -+ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT, -+ ASPEED_ESPI_SYSEVT_HOST_RST_ACK, -+ ASPEED_ESPI_SYSEVT_HOST_RST_ACK); -+ dev_dbg(priv->dev, "SYSEVT_HOST_RST_WARN: acked\n"); -+ } -+ if (sts & ASPEED_ESPI_SYSEVT_OOB_RST_WARN && -+ evt & ASPEED_ESPI_SYSEVT_OOB_RST_WARN) { -+ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT, -+ ASPEED_ESPI_SYSEVT_OOB_RST_ACK, -+ ASPEED_ESPI_SYSEVT_OOB_RST_ACK); -+ dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n"); -+ } -+ if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') { -+ priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0'; -+ wake_up_interruptible(&priv->pltrstn_waitq); -+ dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn); -+ } -+ -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_STS, sts); -+} -+ -+static void aspeed_espi_sys_event1(struct aspeed_espi *priv) -+{ -+ u32 sts, evt; -+ -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, &sts); -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt); -+ -+ dev_dbg(priv->dev, "sys event1: sts = %08x, evt = %08x\n", sts, evt); -+ -+ if (sts & ASPEED_ESPI_SYSEVT1_SUS_WARN && -+ evt & ASPEED_ESPI_SYSEVT1_SUS_WARN) { -+ regmap_write_bits(priv->map, ASPEED_ESPI_SYSEVT1, -+ ASPEED_ESPI_SYSEVT1_SUS_ACK, -+ ASPEED_ESPI_SYSEVT1_SUS_ACK); -+ dev_dbg(priv->dev, "SYSEVT1_SUS_WARN: acked\n"); -+ } -+ -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_STS, sts); -+} -+ -+static void aspeed_espi_boot_ack(struct aspeed_espi *priv) -+{ -+ u32 evt; -+ -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT, &evt); -+ if (!(evt & ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS)) { -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT, -+ evt | ASPEED_ESPI_SYSEVT_SLAVE_BOOT_STATUS | -+ ASPEED_ESPI_SYSEVT_SLAVE_BOOT_DONE); -+ dev_dbg(priv->dev, "Setting espi slave boot done\n"); -+ } -+ -+ regmap_read(priv->map, ASPEED_ESPI_SYSEVT1, &evt); -+ if (evt & ASPEED_ESPI_SYSEVT1_SUS_WARN && -+ !(evt & ASPEED_ESPI_SYSEVT1_SUS_ACK)) { -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1, -+ evt | ASPEED_ESPI_SYSEVT1_SUS_ACK); -+ dev_dbg(priv->dev, "Boot SYSEVT1_SUS_WARN: acked\n"); -+ } -+} -+ -+static irqreturn_t aspeed_espi_irq(int irq, void *arg) -+{ -+ struct aspeed_espi *priv = arg; -+ u32 sts, sts_handled = 0; -+ -+ regmap_read(priv->map, ASPEED_ESPI_INT_STS, &sts); -+ -+ dev_dbg(priv->dev, "INT_STS: 0x%08x\n", sts); -+ -+ if (sts & ASPEED_ESPI_VW_SYSEVT) { -+ aspeed_espi_sys_event(priv); -+ sts_handled |= ASPEED_ESPI_VW_SYSEVT; -+ } -+ -+ if (sts & ASPEED_ESPI_VW_SYSEVT1) { -+ aspeed_espi_sys_event1(priv); -+ sts_handled |= ASPEED_ESPI_VW_SYSEVT1; -+ } -+ -+ if (sts & ASPEED_ESPI_HW_RESET) { -+ if (priv->rst_irq < 0) { -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_SW_RESET, 0); -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_SW_RESET, -+ ASPEED_ESPI_CTRL_SW_RESET); -+ } -+ -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_OOB_CHRDY, -+ ASPEED_ESPI_CTRL_OOB_CHRDY); -+ aspeed_espi_boot_ack(priv); -+ sts_handled |= ASPEED_ESPI_HW_RESET; -+ } -+ -+ regmap_write(priv->map, ASPEED_ESPI_INT_STS, sts); -+ -+ return sts != sts_handled ? IRQ_NONE : IRQ_HANDLED; -+} -+ -+static void aspeed_espi_config_irq(struct aspeed_espi *priv) -+{ -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T0, -+ ASPEED_ESPI_SYSEVT_INT_T0_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T1, -+ ASPEED_ESPI_SYSEVT_INT_T1_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_T2, -+ ASPEED_ESPI_SYSEVT_INT_T2_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT_INT_EN, -+ ASPEED_ESPI_SYSEVT_INT_MASK); -+ -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T0, -+ ASPEED_ESPI_SYSEVT1_INT_T0_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T1, -+ ASPEED_ESPI_SYSEVT1_INT_T1_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_T2, -+ ASPEED_ESPI_SYSEVT1_INT_T2_MASK); -+ regmap_write(priv->map, ASPEED_ESPI_SYSEVT1_INT_EN, -+ ASPEED_ESPI_SYSEVT1_INT_MASK); -+ -+ regmap_write(priv->map, ASPEED_ESPI_INT_EN, ASPEED_ESPI_INT_MASK); -+} -+ -+static irqreturn_t aspeed_espi_reset_isr(int irq, void *arg) -+{ -+ struct aspeed_espi *priv = arg; -+ -+ reset_control_assert(priv->reset); -+ reset_control_deassert(priv->reset); -+ -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_SW_RESET, 0); -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_SW_RESET, ASPEED_ESPI_CTRL_SW_RESET); -+ -+ regmap_write_bits(priv->map, ASPEED_ESPI_CTRL, -+ ASPEED_ESPI_CTRL_OOB_CHRDY, 0); -+ -+ aspeed_espi_config_irq(priv); -+ -+ return IRQ_HANDLED; -+} -+ -+static inline struct aspeed_espi *to_aspeed_espi(struct file *filp) -+{ -+ return container_of(filp->private_data, struct aspeed_espi, -+ pltrstn_miscdev); -+} -+ -+static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp) -+{ -+ if ((filp->f_flags & O_ACCMODE) != O_RDONLY) -+ return -EACCES; -+ -+ return 0; -+} -+ -+static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct aspeed_espi *priv = to_aspeed_espi(filp); -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long flags; -+ char old_sample; -+ int ret = 0; -+ -+ spin_lock_irqsave(&priv->pltrstn_lock, flags); -+ -+ add_wait_queue(&priv->pltrstn_waitq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ old_sample = priv->pltrstn; -+ -+ do { -+ char new_sample = priv->pltrstn; -+ -+ if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) { -+ ret = put_user(new_sample, (unsigned long __user *)buf); -+ if (!ret) -+ ret = sizeof(new_sample); -+ } else if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ } -+ -+ if (!ret) { -+ spin_unlock_irqrestore(&priv->pltrstn_lock, flags); -+ schedule(); -+ spin_lock_irqsave(&priv->pltrstn_lock, flags); -+ } -+ } while (!ret); -+ -+ remove_wait_queue(&priv->pltrstn_waitq, &wait); -+ set_current_state(TASK_RUNNING); -+ -+ spin_unlock_irqrestore(&priv->pltrstn_lock, flags); -+ -+ return ret; -+} -+ -+static const struct file_operations aspeed_espi_pltrstn_fops = { -+ .owner = THIS_MODULE, -+ .open = aspeed_espi_pltrstn_open, -+ .read = aspeed_espi_pltrstn_read, -+}; -+ -+static const struct regmap_config aspeed_espi_regmap_cfg = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = ASPEED_ESPI_SYSEVT1_INT_STS, -+}; -+ -+static int aspeed_espi_probe(struct platform_device *pdev) -+{ -+ struct aspeed_espi *priv; -+ struct resource *res; -+ void __iomem *regs; -+ u32 ctrl; -+ int ret; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(regs)) -+ return PTR_ERR(regs); -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&pdev->dev, priv); -+ priv->dev = &pdev->dev; -+ -+ priv->map = devm_regmap_init_mmio(&pdev->dev, regs, -+ &aspeed_espi_regmap_cfg); -+ if (IS_ERR(priv->map)) -+ return PTR_ERR(priv->map); -+ -+ spin_lock_init(&priv->pltrstn_lock); -+ init_waitqueue_head(&priv->pltrstn_waitq); -+ priv->pltrstn = 'U'; /* means it's not reported yet from master */ -+ -+ priv->irq = platform_get_irq(pdev, 0); -+ if (priv->irq < 0) -+ return priv->irq; -+ -+ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_espi_irq, 0, -+ "aspeed-espi-irq", priv); -+ if (ret) -+ return ret; -+ -+ if (of_device_is_compatible(pdev->dev.of_node, -+ "aspeed,ast2600-espi-slave")) { -+ priv->rst_irq = platform_get_irq(pdev, 1); -+ if (priv->rst_irq < 0) -+ return priv->rst_irq; -+ -+ ret = devm_request_irq(&pdev->dev, priv->rst_irq, -+ aspeed_espi_reset_isr, 0, -+ "aspeed-espi-rst-irq", priv); -+ if (ret) -+ return ret; -+ -+ priv->reset = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(priv->reset)) -+ return PTR_ERR(priv->reset); -+ } else { -+ priv->rst_irq = -ENOTSUPP; -+ } -+ -+ priv->clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(priv->clk)) { -+ ret = PTR_ERR(priv->clk); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "couldn't get clock\n"); -+ return ret; -+ } -+ ret = clk_prepare_enable(priv->clk); -+ if (ret) { -+ dev_err(&pdev->dev, "couldn't enable clock\n"); -+ return ret; -+ } -+ -+ /* -+ * We check that the regmap works on this very first access, but as this -+ * is an MMIO-backed regmap, subsequent regmap access is not going to -+ * fail and we skip error checks from this point. -+ */ -+ ret = regmap_read(priv->map, ASPEED_ESPI_CTRL, &ctrl); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to read ctrl register\n"); -+ goto err_clk_disable_out; -+ } -+ regmap_write(priv->map, ASPEED_ESPI_CTRL, -+ ctrl | ASPEED_ESPI_CTRL_OOB_CHRDY); -+ -+ priv->pltrstn_miscdev.minor = MISC_DYNAMIC_MINOR; -+ priv->pltrstn_miscdev.name = "espi-pltrstn"; -+ priv->pltrstn_miscdev.fops = &aspeed_espi_pltrstn_fops; -+ priv->pltrstn_miscdev.parent = &pdev->dev; -+ -+ ret = misc_register(&priv->pltrstn_miscdev); -+ if (ret) { -+ dev_err(&pdev->dev, "Unable to register device\n"); -+ goto err_clk_disable_out; -+ } -+ -+ aspeed_espi_config_irq(priv); -+ aspeed_espi_boot_ack(priv); -+ -+ dev_info(&pdev->dev, "eSPI registered, irq %d\n", priv->irq); -+ -+ return 0; -+ -+err_clk_disable_out: -+ clk_disable_unprepare(priv->clk); -+ -+ return ret; -+} -+ -+static int aspeed_espi_remove(struct platform_device *pdev) -+{ -+ struct aspeed_espi *priv = dev_get_drvdata(&pdev->dev); -+ -+ misc_deregister(&priv->pltrstn_miscdev); -+ clk_disable_unprepare(priv->clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id of_espi_match_table[] = { -+ { .compatible = "aspeed,ast2500-espi-slave" }, -+ { .compatible = "aspeed,ast2600-espi-slave" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, of_espi_match_table); -+ -+static struct platform_driver aspeed_espi_driver = { -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .of_match_table = of_match_ptr(of_espi_match_table), -+ }, -+ .probe = aspeed_espi_probe, -+ .remove = aspeed_espi_remove, -+}; -+module_platform_driver(aspeed_espi_driver); -+ -+MODULE_AUTHOR("Haiyue Wang "); -+MODULE_AUTHOR("Jae Hyun Yoo "); -+MODULE_DESCRIPTION("Aspeed eSPI driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h -index 3d90582a813f..1e18364de03d 100644 ---- a/include/dt-bindings/clock/ast2600-clock.h -+++ b/include/dt-bindings/clock/ast2600-clock.h -@@ -104,6 +104,7 @@ - #define ASPEED_RESET_PECI 36 - #define ASPEED_RESET_MII 35 - #define ASPEED_RESET_I2C 34 -+#define ASPEED_RESET_ESPI 32 - #define ASPEED_RESET_H2X 31 - #define ASPEED_RESET_GP_MCU 30 - #define ASPEED_RESET_DP_MCU 29 --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch deleted file mode 100644 index 45dec5b20..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch +++ /dev/null @@ -1,95 +0,0 @@ -From a4413fe3ba94906243b632e0b9e0e9a91620dd22 Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Fri, 1 Mar 2019 11:46:09 -0700 -Subject: [PATCH] Add AST2500 JTAG driver - -Update AST2500 JTAG driver. Remove Legacy driver but keep headers. - -Signed-off-by: Corona, Ernesto ---- - include/uapi/linux/jtag_drv.h | 73 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 73 insertions(+) - create mode 100644 include/uapi/linux/jtag_drv.h - -diff --git a/include/uapi/linux/jtag_drv.h b/include/uapi/linux/jtag_drv.h -new file mode 100644 -index 000000000000..4df638f8fa43 ---- /dev/null -+++ b/include/uapi/linux/jtag_drv.h -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (C) 2012-2017 ASPEED Technology Inc. */ -+/* Copyright (c) 2018 Intel Corporation */ -+ -+#ifndef __JTAG_DRV_H__ -+#define __JTAG_DRV_H__ -+ -+enum xfer_mode { -+ HW_MODE = 0, -+ SW_MODE -+} xfer_mode; -+ -+struct tck_bitbang { -+ __u8 tms; -+ __u8 tdi; -+ __u8 tdo; -+} __attribute__((__packed__)); -+ -+struct scan_xfer { -+ __u8 mode; -+ __u32 tap_state; -+ __u32 length; -+ __u8 *tdi; -+ __u32 tdi_bytes; -+ __u8 *tdo; -+ __u32 tdo_bytes; -+ __u32 end_tap_state; -+} __attribute__((__packed__)); -+ -+struct set_tck_param { -+ __u8 mode; -+ __u32 tck; -+} __attribute__((__packed__)); -+ -+struct get_tck_param { -+ __u8 mode; -+ __u32 tck; -+} __attribute__((__packed__)); -+ -+struct tap_state_param { -+ __u8 mode; -+ __u32 from_state; -+ __u32 to_state; -+} __attribute__((__packed__)); -+ -+enum jtag_states { -+ jtag_tlr, -+ jtag_rti, -+ jtag_sel_dr, -+ jtag_cap_dr, -+ jtag_shf_dr, -+ jtag_ex1_dr, -+ jtag_pau_dr, -+ jtag_ex2_dr, -+ jtag_upd_dr, -+ jtag_sel_ir, -+ jtag_cap_ir, -+ jtag_shf_ir, -+ jtag_ex1_ir, -+ jtag_pau_ir, -+ jtag_ex2_ir, -+ jtag_upd_ir -+} jtag_states; -+ -+#define JTAGIOC_BASE 'T' -+ -+#define AST_JTAG_SET_TCK _IOW(JTAGIOC_BASE, 3, struct set_tck_param) -+#define AST_JTAG_GET_TCK _IOR(JTAGIOC_BASE, 4, struct get_tck_param) -+#define AST_JTAG_BITBANG _IOWR(JTAGIOC_BASE, 5, struct tck_bitbang) -+#define AST_JTAG_SET_TAPSTATE _IOW(JTAGIOC_BASE, 6, struct tap_state_param) -+#define AST_JTAG_READWRITESCAN _IOWR(JTAGIOC_BASE, 7, struct scan_xfer) -+ -+#endif --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch deleted file mode 100644 index c9844e1bd..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0030-Add-dump-debug-code-into-I2C-drivers.patch +++ /dev/null @@ -1,145 +0,0 @@ -From a57f401058e452f9abb6f3233e7f2776af1e6b8d Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 29 Jun 2018 11:00:02 -0700 -Subject: [PATCH] Add dump debug code into I2C drivers - -This commit enables dump debug of master and slave I2C drivers. -This is only for downstream debug purpose so it shouldn't go to -the upstream. - -Usage (in case of bus 5 for an example): -echo 5 > /sys/module/i2c_aspeed/parameters/dump_debug_bus_id -echo 1 > /sys/module/i2c_aspeed/parameters/dump_debug -echo 5 > /sys/module/i2c_slave_mqueue/parameters/dump_debug_bus_id -echo 1 > /sys/module/i2c_slave_mqueue/parameters/dump_debug - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 26 ++++++++++++++++++++++++++ - drivers/i2c/i2c-slave-mqueue.c | 24 ++++++++++++++++++++++++ - 2 files changed, 50 insertions(+) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index a7be6f24450b..c113ffa8d5df 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -169,6 +169,21 @@ struct aspeed_i2c_bus { - #endif /* CONFIG_I2C_SLAVE */ - }; - -+static bool dump_debug __read_mostly; -+static int dump_debug_bus_id __read_mostly; -+ -+#define I2C_HEX_DUMP(bus, addr, flags, buf, len) \ -+ do { \ -+ if (dump_debug && (bus)->adap.nr == dump_debug_bus_id) { \ -+ char dump_info[100] = {0,}; \ -+ snprintf(dump_info, sizeof(dump_info), \ -+ "bus_id:%d, addr:0x%02x, flags:0x%02x: ", \ -+ (bus)->adap.nr, addr, flags); \ -+ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, \ -+ 16, 1, buf, len, true); \ -+ } \ -+ } while (0) -+ - static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus); - - static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) -@@ -657,6 +672,7 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, - { - struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap); - unsigned long time_left, flags; -+ int i; - - spin_lock_irqsave(&bus->lock, flags); - bus->cmd_err = 0; -@@ -708,6 +724,11 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, - return -ETIMEDOUT; - } - -+ for (i = 0; i < num; i++) { -+ I2C_HEX_DUMP(bus, msgs[i].addr, msgs[i].flags, -+ msgs[i].buf, msgs[i].len); -+ } -+ - return bus->master_xfer_result; - } - -@@ -1079,6 +1100,11 @@ static struct platform_driver aspeed_i2c_bus_driver = { - }; - module_platform_driver(aspeed_i2c_bus_driver); - -+module_param_named(dump_debug, dump_debug, bool, 0644); -+MODULE_PARM_DESC(dump_debug, "debug flag for dump printing"); -+module_param_named(dump_debug_bus_id, dump_debug_bus_id, int, 0644); -+MODULE_PARM_DESC(dump_debug_bus_id, "bus id for dump debug printing"); -+ - MODULE_AUTHOR("Brendan Higgins "); - MODULE_DESCRIPTION("Aspeed I2C Bus Driver"); - MODULE_LICENSE("GPL v2"); -diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c -index 6014bca0ff2a..2c7a6038409c 100644 ---- a/drivers/i2c/i2c-slave-mqueue.c -+++ b/drivers/i2c/i2c-slave-mqueue.c -@@ -21,6 +21,7 @@ struct mq_msg { - struct mq_queue { - struct bin_attribute bin; - struct kernfs_node *kn; -+ struct i2c_client *client; - - spinlock_t lock; /* spinlock for queue index handling */ - int in; -@@ -31,6 +32,21 @@ struct mq_queue { - struct mq_msg *queue; - }; - -+static bool dump_debug __read_mostly; -+static int dump_debug_bus_id __read_mostly; -+ -+#define I2C_HEX_DUMP(client, buf, len) \ -+ do { \ -+ if (dump_debug && \ -+ (client)->adapter->nr == dump_debug_bus_id) { \ -+ char dump_info[100] = {0,}; \ -+ snprintf(dump_info, sizeof(dump_info), \ -+ "bus_id:%d: ", (client)->adapter->nr); \ -+ print_hex_dump(KERN_ERR, dump_info, DUMP_PREFIX_NONE, \ -+ 16, 1, buf, len, true); \ -+ } \ -+ } while (0) -+ - static int i2c_slave_mqueue_callback(struct i2c_client *client, - enum i2c_slave_event event, u8 *val) - { -@@ -101,6 +117,7 @@ static ssize_t i2c_slave_mqueue_bin_read(struct file *filp, - if (msg->len <= count) { - ret = msg->len; - memcpy(buf, msg->buf, ret); -+ I2C_HEX_DUMP(mq->client, buf, ret); - } else { - ret = -EOVERFLOW; /* Drop this HUGE one. */ - } -@@ -131,6 +148,8 @@ static int i2c_slave_mqueue_probe(struct i2c_client *client, - - BUILD_BUG_ON(!is_power_of_2(MQ_QUEUE_SIZE)); - -+ mq->client = client; -+ - buf = devm_kmalloc_array(dev, MQ_QUEUE_SIZE, MQ_MSGBUF_SIZE, - GFP_KERNEL); - if (!buf) -@@ -212,6 +231,11 @@ static struct i2c_driver i2c_slave_mqueue_driver = { - }; - module_i2c_driver(i2c_slave_mqueue_driver); - -+module_param_named(dump_debug, dump_debug, bool, 0644); -+MODULE_PARM_DESC(dump_debug, "debug flag for dump printing"); -+module_param_named(dump_debug_bus_id, dump_debug_bus_id, int, 0644); -+MODULE_PARM_DESC(dump_debug_bus_id, "bus id for dump debug printing"); -+ - MODULE_LICENSE("GPL v2"); - MODULE_AUTHOR("Haiyue Wang "); - MODULE_DESCRIPTION("I2C slave mode for receiving and queuing messages"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch deleted file mode 100644 index 5240a05f5..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0031-Add-high-speed-baud-rate-support-for-UART.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0bc792097e73c07bc324e2c9b0172fb27b51a087 Mon Sep 17 00:00:00 2001 -From: Yong Li -Date: Wed, 2 Jan 2019 15:06:43 +0800 -Subject: [PATCH] Add high speed baud rate support for UART - -In order to support high speed baud rate(921600 bps), -the default UART clock(24MHz) needs to be switched -to 192MHz(from USB2.0 port1 PHY). - -Create a new 192M Hz clock and assign it to uart, -based on uart clock source configuration in SCU4C. - -bootloader(u-boot) will set SCU4C based on the environment configuration - -Signed-off-by: Yong Li ---- - drivers/clk/clk-aspeed.c | 44 +++++++++++++++++++++++++++----- - include/dt-bindings/clock/aspeed-clock.h | 2 ++ - 2 files changed, 39 insertions(+), 7 deletions(-) - -diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c -index 411ff5fb2c07..5e1c87bc8a99 100644 ---- a/drivers/clk/clk-aspeed.c -+++ b/drivers/clk/clk-aspeed.c -@@ -14,7 +14,9 @@ - - #include "clk-aspeed.h" - --#define ASPEED_NUM_CLKS 38 -+#define ASPEED_NUM_CLKS ASPEED_CLK_MAX -+#define UART_HIGH_SPEED_CLK 192000000 -+#define UART_LOW_SPEED_CLK 24000000 - - #define ASPEED_RESET2_OFFSET 32 - -@@ -29,6 +31,12 @@ - #define ASPEED_MISC_CTRL 0x2c - #define UART_DIV13_EN BIT(12) - #define ASPEED_MAC_CLK_DLY 0x48 -+#define ASPEED_MISC2_CTRL 0x4c -+#define UART1_HS_CLK_EN BIT(24) -+#define UART2_HS_CLK_EN BIT(25) -+#define UART3_HS_CLK_EN BIT(26) -+#define UART4_HS_CLK_EN BIT(27) -+#define UART5_HS_CLK_EN BIT(28) - #define ASPEED_STRAP 0x70 - #define CLKIN_25MHZ_EN BIT(23) - #define AST2400_CLK_SOURCE_SEL BIT(18) -@@ -386,7 +394,7 @@ static int aspeed_clk_probe(struct platform_device *pdev) - struct aspeed_reset *ar; - struct regmap *map; - struct clk_hw *hw; -- u32 val, rate; -+ u32 val, rate, rate_hi; - int i, ret; - - map = syscon_node_to_regmap(dev->of_node); -@@ -420,16 +428,25 @@ static int aspeed_clk_probe(struct platform_device *pdev) - - /* UART clock div13 setting */ - regmap_read(map, ASPEED_MISC_CTRL, &val); -- if (val & UART_DIV13_EN) -- rate = 24000000 / 13; -- else -- rate = 24000000; -+ if (val & UART_DIV13_EN) { -+ rate = UART_LOW_SPEED_CLK / 13; -+ rate_hi = UART_HIGH_SPEED_CLK / 13; -+ } else { -+ rate = UART_LOW_SPEED_CLK; -+ rate_hi = UART_HIGH_SPEED_CLK; -+ } - /* TODO: Find the parent data for the uart clock */ - hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate); - if (IS_ERR(hw)) - return PTR_ERR(hw); - aspeed_clk_data->hws[ASPEED_CLK_UART] = hw; - -+ hw = clk_hw_register_fixed_rate(dev, "uart-hs", "usb-port1-gate", 0, -+ rate_hi); -+ if (IS_ERR(hw)) -+ return PTR_ERR(hw); -+ aspeed_clk_data->hws[ASPEED_CLK_UART_HS] = hw; -+ - /* - * Memory controller (M-PLL) PLL. This clock is configured by the - * bootloader, and is exposed to Linux as a read-only clock rate. -@@ -539,9 +556,22 @@ static int aspeed_clk_probe(struct platform_device *pdev) - * UART[1..5] clock source mux - */ - -+ /* Get the uart clock source configuration from SCU4C*/ -+ regmap_read(map, ASPEED_MISC2_CTRL, &val); - for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) { - const struct aspeed_gate_data *gd = &aspeed_gates[i]; - u32 gate_flags; -+ char *parent_name; -+ -+ /* For uart, needs to adjust the clock based on SCU4C value */ -+ if ((i == ASPEED_CLK_GATE_UART1CLK && (val & UART1_HS_CLK_EN)) || -+ (i == ASPEED_CLK_GATE_UART2CLK && (val & UART2_HS_CLK_EN)) || -+ (i == ASPEED_CLK_GATE_UART5CLK && (val & UART5_HS_CLK_EN)) || -+ (i == ASPEED_CLK_GATE_UART3CLK && (val & UART3_HS_CLK_EN)) || -+ (i == ASPEED_CLK_GATE_UART4CLK && (val & UART4_HS_CLK_EN))) -+ parent_name = "uart-hs"; -+ else -+ parent_name = gd->parent_name; - - /* Special case: the USB port 1 clock (bit 14) is always - * working the opposite way from the other ones. -@@ -549,7 +579,7 @@ static int aspeed_clk_probe(struct platform_device *pdev) - gate_flags = (gd->clock_idx == 14) ? 0 : CLK_GATE_SET_TO_DISABLE; - hw = aspeed_clk_hw_register_gate(dev, - gd->name, -- gd->parent_name, -+ parent_name, - gd->flags, - map, - gd->clock_idx, -diff --git a/include/dt-bindings/clock/aspeed-clock.h b/include/dt-bindings/clock/aspeed-clock.h -index 9ff4f6e4558c..41d531dd0b48 100644 ---- a/include/dt-bindings/clock/aspeed-clock.h -+++ b/include/dt-bindings/clock/aspeed-clock.h -@@ -41,6 +41,8 @@ - #define ASPEED_CLK_24M 35 - #define ASPEED_CLK_MAC1RCLK 36 - #define ASPEED_CLK_MAC2RCLK 37 -+#define ASPEED_CLK_UART_HS 38 -+#define ASPEED_CLK_MAX 39 - - #define ASPEED_RESET_XDMA 0 - #define ASPEED_RESET_MCTP 1 --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch deleted file mode 100644 index 2ba9e5002..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch +++ /dev/null @@ -1,559 +0,0 @@ -From 09aa5d5af94823f100fb515d45b0a04fc8d7ee4f Mon Sep 17 00:00:00 2001 -From: Oskar Senft -Date: Wed, 8 Aug 2018 10:15:05 -0400 -Subject: [PATCH] misc: aspeed: Add Aspeed UART routing control driver. - -This driver adds sysfs files that allow the BMC userspace to configure -how UARTs and physical serial I/O ports are routed. - -Tested: Checked correct behavior (both read & write) on TYAN S7106 -board by manually changing routing settings and confirming that bits -flow as expected. Tested for UART1 and UART3 as this board doesn't have -the other UARTs wired up in a testable way. - -Signed-off-by: Oskar Senft -Signed-off-by: Yong Li -Signed-off-by: Vernon Mauery ---- - .../ABI/stable/sysfs-driver-aspeed-uart-routing | 14 + - Documentation/misc-devices/aspeed-uart-routing.txt | 49 +++ - arch/arm/boot/dts/aspeed-g5.dtsi | 6 + - arch/arm/boot/dts/aspeed-g6.dtsi | 6 + - drivers/misc/Kconfig | 6 + - drivers/misc/Makefile | 1 + - drivers/misc/aspeed-uart-routing.c | 383 +++++++++++++++++++++ - 7 files changed, 465 insertions(+) - create mode 100644 Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing - create mode 100644 Documentation/misc-devices/aspeed-uart-routing.txt - create mode 100644 drivers/misc/aspeed-uart-routing.c - -diff --git a/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing b/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing -new file mode 100644 -index 000000000000..5068737d9c12 ---- /dev/null -+++ b/Documentation/ABI/stable/sysfs-driver-aspeed-uart-routing -@@ -0,0 +1,14 @@ -+What: /sys/bus/platform/drivers/aspeed-uart-routing/*/io* -+Date: August 2018 -+Contact: Oskar Senft -+Description: Configures the input source for the specific physical -+ serial I/O port. -+Users: OpenBMC. Proposed changes should be mailed to -+ openbmc@lists.ozlabs.org -+ -+What: /sys/bus/platform/drivers/aspeed-uart-routing/*/uart* -+Date: August 2018 -+Contact: Oskar Senft -+Description: Configures the input source for the specific UART. -+Users: OpenBMC. Proposed changes should be mailed to -+ openbmc@lists.ozlabs.org -diff --git a/Documentation/misc-devices/aspeed-uart-routing.txt b/Documentation/misc-devices/aspeed-uart-routing.txt -new file mode 100644 -index 000000000000..cf1c2a466875 ---- /dev/null -+++ b/Documentation/misc-devices/aspeed-uart-routing.txt -@@ -0,0 +1,49 @@ -+Kernel driver aspeed-uart-routing -+================================= -+ -+Supported chips: -+ASPEED AST2500/AST2600 -+ -+Author: -+Google LLC -+ -+Description -+----------- -+ -+The Aspeed AST2500/AST2600 allows to dynamically route the inputs for the -+built-in UARTS and physical serial I/O ports. -+ -+This allows, for example, to connect the output of UART to another UART. -+This can be used to enable host<->BMC communication via UARTs, e.g. to allow -+access to the host's serial console. -+ -+This driver is for the BMC side. The sysfs files allow the BMC userspace -+which owns the system configuration policy, to configure how UARTs and -+physical serial I/O ports are routed. -+ -+The driver provides the following files in sysfs: -+uart1 Configure the input signal to UART1. -+uart2 Configure the input signal to UART2. -+uart3 Configure the input signal to UART3. -+uart4 Configure the input signal to UART4. -+uart5 Configure the input signal to UART5. -+io1 Configure the input signal to physical serial port 1. -+io2 Configure the input signal to physical serial port 2. -+io3 Configure the input signal to physical serial port 3. -+io4 Configure the input signal to physical serial port 4. -+io5 Configure the input signal to physical serial port 5. -+ -+When read, each file shows the list of available options with the currently -+selected option marked by square brackets "[]". The list of available options -+depends on the selected file. -+ -+Example: -+$ cat /sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1 -+[io1] io2 io3 io4 uart2 uart3 uart4 io6 -+ -+In this case, UART1 gets its input signal from IO1 (physical serial port 1). -+ -+$ echo -n "uart3" \ -+ >/sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1 -+$ cat /sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1 -+io1 io2 io3 io4 uart2 [uart3] uart4 io6 -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index bd2037e52a94..797013debaa7 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -523,6 +523,12 @@ - status = "disabled"; - }; - }; -+ -+ uart_routing: uart_routing@9c { -+ compatible = "aspeed,ast2500-uart-routing"; -+ reg = <0x9c 0x4>; -+ status = "disabled"; -+ }; - }; - - peci: bus@1e78b000 { -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index e4c1ab3d274e..8cc978058f16 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -291,6 +291,12 @@ - compatible = "aspeed,ast2600-pinctrl"; - }; - -+ uart_routing: uart_routing@9c { -+ compatible = "aspeed,ast2500-uart-routing"; -+ reg = <0x9c 0x4>; -+ status = "disabled"; -+ }; -+ - smp-memram@180 { - compatible = "aspeed,ast2600-smpmem"; - reg = <0x180 0x40>; -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 0f9b5a356c93..8af817694648 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -441,6 +441,12 @@ config ASPEED_ESPI_SLAVE - Control Aspeed ast2500 eSPI slave controller to handle event - which needs the firmware's processing. - -+config ASPEED_UART_ROUTING -+ tristate "Aspeed ast2500 UART routing control" -+ help -+ If you want to configure UART routing on Aspeed BMC platforms, enable -+ this option. -+ - config PCI_ENDPOINT_TEST - depends on PCI - select CRC32 -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 53864687e8fd..a4372208f4de 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_ECHO) += echo/ - obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o - obj-$(CONFIG_CXL_BASE) += cxl/ - obj-$(CONFIG_ASPEED_ESPI_SLAVE) += aspeed-espi-slave.o -+obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o - obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o - obj-$(CONFIG_OCXL) += ocxl/ - obj-y += cardreader/ -diff --git a/drivers/misc/aspeed-uart-routing.c b/drivers/misc/aspeed-uart-routing.c -new file mode 100644 -index 000000000000..21ef5d98c317 ---- /dev/null -+++ b/drivers/misc/aspeed-uart-routing.c -@@ -0,0 +1,383 @@ -+/* -+ * UART Routing driver for Aspeed AST2500 -+ * -+ * Copyright (c) 2018 Google LLC -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include -+#include -+#include -+#include -+ -+/* The Aspeed AST2500 allows to dynamically route the inputs for the built-in -+ * UARTS and physical serial I/O ports. -+ * -+ * This allows, for example, to connect the output of UART to another UART. -+ * This can be used to enable host<->BMC communication via UARTs, e.g. to allow -+ * access to the host's serial console. -+ * -+ * This driver is for the BMC side. The sysfs files allow the BMC userspace -+ * which owns the system configuration policy, to configure how UARTs and -+ * physical serial I/O ports are routed. -+ */ -+ -+#define ASPEED_HICRA_IO1 "io1" -+#define ASPEED_HICRA_IO2 "io2" -+#define ASPEED_HICRA_IO3 "io3" -+#define ASPEED_HICRA_IO4 "io4" -+#define ASPEED_HICRA_IO5 "io5" -+#define ASPEED_HICRA_IO6 "io6" -+#define ASPEED_HICRA_UART1 "uart1" -+#define ASPEED_HICRA_UART2 "uart2" -+#define ASPEED_HICRA_UART3 "uart3" -+#define ASPEED_HICRA_UART4 "uart4" -+#define ASPEED_HICRA_UART5 "uart5" -+ -+struct aspeed_uart_routing { -+ struct device *dev; -+ void __iomem *regs; -+ spinlock_t lock; -+}; -+ -+struct aspeed_uart_routing_selector { -+ struct device_attribute dev_attr; -+ int shift; -+ int mask; -+ const char * const options[]; -+}; -+ -+#define to_routing_selector(_dev_attr) \ -+ container_of(_dev_attr, struct aspeed_uart_routing_selector, dev_attr) -+ -+ -+static ssize_t aspeed_uart_routing_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf); -+ -+static ssize_t aspeed_uart_routing_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count); -+ -+#define ROUTING_ATTR(_name) { \ -+ .attr = {.name = _name, \ -+ .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \ -+ .show = aspeed_uart_routing_show, \ -+ .store = aspeed_uart_routing_store, \ -+} -+ -+static struct aspeed_uart_routing_selector uart5_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART5), -+ .shift = 28, -+ .mask = 0xf, -+ .options = { -+ ASPEED_HICRA_IO5, // 0 -+ ASPEED_HICRA_IO1, // 1 -+ ASPEED_HICRA_IO2, // 2 -+ ASPEED_HICRA_IO3, // 3 -+ ASPEED_HICRA_IO4, // 4 -+ ASPEED_HICRA_UART1, // 5 -+ ASPEED_HICRA_UART2, // 6 -+ ASPEED_HICRA_UART3, // 7 -+ ASPEED_HICRA_UART4, // 8 -+ ASPEED_HICRA_IO6, // 9 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector uart4_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART4), -+ .shift = 25, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_IO4, // 0 -+ ASPEED_HICRA_IO1, // 1 -+ ASPEED_HICRA_IO2, // 2 -+ ASPEED_HICRA_IO3, // 3 -+ ASPEED_HICRA_UART1, // 4 -+ ASPEED_HICRA_UART2, // 5 -+ ASPEED_HICRA_UART3, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector uart3_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART3), -+ .shift = 22, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_IO3, // 0 -+ ASPEED_HICRA_IO4, // 1 -+ ASPEED_HICRA_IO1, // 2 -+ ASPEED_HICRA_IO2, // 3 -+ ASPEED_HICRA_UART4, // 4 -+ ASPEED_HICRA_UART1, // 5 -+ ASPEED_HICRA_UART2, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector uart2_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART2), -+ .shift = 19, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_IO2, // 0 -+ ASPEED_HICRA_IO3, // 1 -+ ASPEED_HICRA_IO4, // 2 -+ ASPEED_HICRA_IO1, // 3 -+ ASPEED_HICRA_UART3, // 4 -+ ASPEED_HICRA_UART4, // 5 -+ ASPEED_HICRA_UART1, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector uart1_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_UART1), -+ .shift = 16, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_IO1, // 0 -+ ASPEED_HICRA_IO2, // 1 -+ ASPEED_HICRA_IO3, // 2 -+ ASPEED_HICRA_IO4, // 3 -+ ASPEED_HICRA_UART2, // 4 -+ ASPEED_HICRA_UART3, // 5 -+ ASPEED_HICRA_UART4, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector io5_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO5), -+ .shift = 12, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_UART5, // 0 -+ ASPEED_HICRA_UART1, // 1 -+ ASPEED_HICRA_UART2, // 2 -+ ASPEED_HICRA_UART3, // 3 -+ ASPEED_HICRA_UART4, // 4 -+ ASPEED_HICRA_IO1, // 5 -+ ASPEED_HICRA_IO3, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector io4_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO4), -+ .shift = 9, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_UART4, // 0 -+ ASPEED_HICRA_UART5, // 1 -+ ASPEED_HICRA_UART1, // 2 -+ ASPEED_HICRA_UART2, // 3 -+ ASPEED_HICRA_UART3, // 4 -+ ASPEED_HICRA_IO1, // 5 -+ ASPEED_HICRA_IO2, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector io3_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO3), -+ .shift = 6, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_UART3, // 0 -+ ASPEED_HICRA_UART4, // 1 -+ ASPEED_HICRA_UART5, // 2 -+ ASPEED_HICRA_UART1, // 3 -+ ASPEED_HICRA_UART2, // 4 -+ ASPEED_HICRA_IO1, // 5 -+ ASPEED_HICRA_IO2, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector io2_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO2), -+ .shift = 3, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_UART2, // 0 -+ ASPEED_HICRA_UART3, // 1 -+ ASPEED_HICRA_UART4, // 2 -+ ASPEED_HICRA_UART5, // 3 -+ ASPEED_HICRA_UART1, // 4 -+ ASPEED_HICRA_IO3, // 5 -+ ASPEED_HICRA_IO4, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+static struct aspeed_uart_routing_selector io1_sel = { -+ .dev_attr = ROUTING_ATTR(ASPEED_HICRA_IO1), -+ .shift = 0, -+ .mask = 0x7, -+ .options = { -+ ASPEED_HICRA_UART1, // 0 -+ ASPEED_HICRA_UART2, // 1 -+ ASPEED_HICRA_UART3, // 2 -+ ASPEED_HICRA_UART4, // 3 -+ ASPEED_HICRA_UART5, // 4 -+ ASPEED_HICRA_IO3, // 5 -+ ASPEED_HICRA_IO4, // 6 -+ ASPEED_HICRA_IO6, // 7 -+ NULL, // NULL termination -+ }, -+}; -+ -+ -+static struct attribute *aspeed_uart_routing_attrs[] = { -+ &uart1_sel.dev_attr.attr, -+ &uart2_sel.dev_attr.attr, -+ &uart3_sel.dev_attr.attr, -+ &uart4_sel.dev_attr.attr, -+ &uart5_sel.dev_attr.attr, -+ &io1_sel.dev_attr.attr, -+ &io2_sel.dev_attr.attr, -+ &io3_sel.dev_attr.attr, -+ &io4_sel.dev_attr.attr, -+ &io5_sel.dev_attr.attr, -+ NULL, -+}; -+ -+static const struct attribute_group aspeed_uart_routing_attr_group = { -+ .attrs = aspeed_uart_routing_attrs, -+}; -+ -+static ssize_t aspeed_uart_routing_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev); -+ struct aspeed_uart_routing_selector *sel = to_routing_selector(attr); -+ int val, pos, len; -+ -+ val = (readl(uart_routing->regs) >> sel->shift) & sel->mask; -+ -+ len = 0; -+ for (pos = 0; sel->options[pos] != NULL; ++pos) { -+ if (pos == val) { -+ len += snprintf(buf + len, PAGE_SIZE - 1 - len, -+ "[%s] ", sel->options[pos]); -+ } else { -+ len += snprintf(buf + len, PAGE_SIZE - 1 - len, -+ "%s ", sel->options[pos]); -+ } -+ } -+ -+ if (val >= pos) { -+ len += snprintf(buf + len, PAGE_SIZE - 1 - len, -+ "[unknown(%d)]", val); -+ } -+ -+ len += snprintf(buf + len, PAGE_SIZE - 1 - len, "\n"); -+ -+ return len; -+} -+ -+static ssize_t aspeed_uart_routing_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct aspeed_uart_routing *uart_routing = dev_get_drvdata(dev); -+ struct aspeed_uart_routing_selector *sel = to_routing_selector(attr); -+ int val; -+ u32 reg; -+ -+ val = match_string(sel->options, -1, buf); -+ if (val < 0) { -+ dev_err(dev, "invalid value \"%s\"\n", buf); -+ return -EINVAL; -+ } -+ -+ spin_lock(&uart_routing->lock); -+ reg = readl(uart_routing->regs); -+ // Zero out existing value in specified bits. -+ reg &= ~(sel->mask << sel->shift); -+ // Set new value in specified bits. -+ reg |= (val & sel->mask) << sel->shift; -+ writel(reg, uart_routing->regs); -+ spin_unlock(&uart_routing->lock); -+ -+ return count; -+} -+ -+static int aspeed_uart_routing_probe(struct platform_device *pdev) -+{ -+ struct aspeed_uart_routing *uart_routing; -+ struct resource *res; -+ int rc; -+ -+ uart_routing = devm_kzalloc(&pdev->dev, -+ sizeof(*uart_routing), -+ GFP_KERNEL); -+ if (!uart_routing) -+ return -ENOMEM; -+ -+ spin_lock_init(&uart_routing->lock); -+ uart_routing->dev = &pdev->dev; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ uart_routing->regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(uart_routing->regs)) -+ return PTR_ERR(uart_routing->regs); -+ -+ rc = sysfs_create_group(&uart_routing->dev->kobj, -+ &aspeed_uart_routing_attr_group); -+ if (rc < 0) -+ return rc; -+ -+ platform_set_drvdata(pdev, uart_routing); -+ -+ return 0; -+} -+ -+static int aspeed_uart_routing_remove(struct platform_device *pdev) -+{ -+ struct aspeed_uart_routing *uart_routing = platform_get_drvdata(pdev); -+ -+ sysfs_remove_group(&uart_routing->dev->kobj, -+ &aspeed_uart_routing_attr_group); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_uart_routing_table[] = { -+ { .compatible = "aspeed,ast2500-uart-routing" }, -+ { }, -+}; -+ -+static struct platform_driver aspeed_uart_routing_driver = { -+ .driver = { -+ .name = "aspeed-uart-routing", -+ .of_match_table = aspeed_uart_routing_table, -+ }, -+ .probe = aspeed_uart_routing_probe, -+ .remove = aspeed_uart_routing_remove, -+}; -+ -+module_platform_driver(aspeed_uart_routing_driver); -+ -+MODULE_AUTHOR("Oskar Senft "); -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("Driver to configure Aspeed UART routing"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch deleted file mode 100644 index 2f0fd3a31..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 65c8090f2b418892aee9f239729fa417bd508a00 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 3 Oct 2018 10:17:58 -0700 -Subject: [PATCH] arm: dts: aspeed: Swap the mac nodes numbering - -This patch swaps the numbering of mac0 and mac1 to make a dedicated -nic get assigned the first ethernet device number. - -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g4.dtsi | 16 ++++++++-------- - arch/arm/boot/dts/aspeed-g5.dtsi | 16 ++++++++-------- - 2 files changed, 16 insertions(+), 16 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index a70bee24d058..054d97229626 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -120,14 +120,6 @@ - reg = <0x1e6c2000 0x80>; - }; - -- mac0: ethernet@1e660000 { -- compatible = "aspeed,ast2400-mac", "faraday,ftgmac100"; -- reg = <0x1e660000 0x180>; -- interrupts = <2>; -- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>; -- status = "disabled"; -- }; -- - mac1: ethernet@1e680000 { - compatible = "aspeed,ast2400-mac", "faraday,ftgmac100"; - reg = <0x1e680000 0x180>; -@@ -136,6 +128,14 @@ - status = "disabled"; - }; - -+ mac0: ethernet@1e660000 { -+ compatible = "aspeed,ast2400-mac", "faraday,ftgmac100"; -+ reg = <0x1e660000 0x180>; -+ interrupts = <2>; -+ clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>; -+ status = "disabled"; -+ }; -+ - ehci0: usb@1e6a1000 { - compatible = "aspeed,ast2400-ehci", "generic-ehci"; - reg = <0x1e6a1000 0x100>; -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 797013debaa7..27ed188296a1 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -148,14 +148,6 @@ - reg = <0x1e6c2000 0x80>; - }; - -- mac0: ethernet@1e660000 { -- compatible = "aspeed,ast2500-mac", "faraday,ftgmac100"; -- reg = <0x1e660000 0x180>; -- interrupts = <2>; -- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>; -- status = "disabled"; -- }; -- - mac1: ethernet@1e680000 { - compatible = "aspeed,ast2500-mac", "faraday,ftgmac100"; - reg = <0x1e680000 0x180>; -@@ -164,6 +156,14 @@ - status = "disabled"; - }; - -+ mac0: ethernet@1e660000 { -+ compatible = "aspeed,ast2500-mac", "faraday,ftgmac100"; -+ reg = <0x1e660000 0x180>; -+ interrupts = <2>; -+ clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>; -+ status = "disabled"; -+ }; -+ - ehci0: usb@1e6a1000 { - compatible = "aspeed,ast2500-ehci", "generic-ehci"; - reg = <0x1e6a1000 0x100>; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch deleted file mode 100644 index 741b44462..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch +++ /dev/null @@ -1,245 +0,0 @@ -From 9be0e8ccde0e096cc494aad6f15e7d7d3de3e46f Mon Sep 17 00:00:00 2001 -From: Cheng C Yang -Date: Fri, 9 Nov 2018 10:24:37 +0800 -Subject: [PATCH] Implement a memory driver share memory - -Implement a memory driver for BMC to access VGA share memory. -The driver is used by MDRV2. In MDRV2 BIOS will send whole -SMBIOS table to VGA memory and BMC can get the table from VGA -memory through this driver. - -Signed-off-by: Cheng C Yang ---- - .../bindings/soc/aspeed/aspeed-vga-sharedmem.txt | 20 +++ - drivers/soc/aspeed/Kconfig | 9 ++ - drivers/soc/aspeed/Makefile | 1 + - drivers/soc/aspeed/aspeed-vga-sharedmem.c | 163 +++++++++++++++++++++ - 4 files changed, 193 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt - create mode 100644 drivers/soc/aspeed/aspeed-vga-sharedmem.c - -diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt -new file mode 100644 -index 000000000000..03f57c53e844 ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-vga-sharedmem.txt -@@ -0,0 +1,20 @@ -+* Aspeed VGA shared memory driver -+ -+Aspeed VGA shared memory driver allow user to read data from AST2500 -+VGA memory. This driver is required by ManagedDataRegionlV2 -+specification. In the spec, BIOS will transfer whole SMBIOS table to -+VGA memroy and BMC get the table from VGA memory. 0penBMC project do -+not allow to use /dev/mem for security concerns. To get the data in -+VGA shared memory in user space, implement this driver only allowed -+user to mmap limited memory area. -+ -+Required properties: -+- compatible: "aspeed,ast2500-vga-sharedmem" -+ - aspeed,ast2500-vga-sharedmem: Aspeed AST2500 family -+- reg: Should contain VGA shared memory start address and length -+ -+Example: -+vga-shared-memory { -+ compatible = "aspeed,ast2500-vga-sharedmem"; -+ reg = <0x9ff00000 0x100000>; -+}; -diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig -index cb85917b8c6f..13cd9fbabbf1 100644 ---- a/drivers/soc/aspeed/Kconfig -+++ b/drivers/soc/aspeed/Kconfig -@@ -59,4 +59,13 @@ config ASPEED_XDMA - SOCs. The XDMA engine can perform automatic PCI DMA operations - between the AST2XXX (acting as a BMC) and a host processor. - -+config ASPEED_VGA_SHAREDMEM -+ tristate "Aspeed VGA Shared memory" -+ depends on SOC_ASPEED -+ help -+ To access VGA shared memory on Aspeed BMC, enable this option. -+ This driver used by ManagedDataRegionlV2 specification. In the -+ specification, BIOS will transfer whole SMBIOS table to VGA memory, -+ and BMC can get the table from VGA memory through this driver. -+ - endmenu -diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile -index 56c5de5eeabe..875f0d9e7866 100644 ---- a/drivers/soc/aspeed/Makefile -+++ b/drivers/soc/aspeed/Makefile -@@ -6,3 +6,4 @@ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o - obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o - obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o - obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o -+obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o -diff --git a/drivers/soc/aspeed/aspeed-vga-sharedmem.c b/drivers/soc/aspeed/aspeed-vga-sharedmem.c -new file mode 100644 -index 000000000000..cd1f5431378c ---- /dev/null -+++ b/drivers/soc/aspeed/aspeed-vga-sharedmem.c -@@ -0,0 +1,163 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2018 Intel Corporation -+ * VGA Shared Memory driver for Aspeed AST2500 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define SHAREDMEM_NAME "vgasharedmem" -+ -+struct aspeed_vga_sharedmem { -+ struct miscdevice miscdev; -+ unsigned int addr; -+ unsigned int size; -+ bool mmap_enable; -+}; -+ -+static struct aspeed_vga_sharedmem *file_sharemem(struct file *file) -+{ -+ return container_of(file->private_data, -+ struct aspeed_vga_sharedmem, miscdev); -+} -+ -+static int vga_open(struct inode *inode, struct file *file) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file); -+ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ -+ if (!vga_sharedmem->mmap_enable) -+ return -EPERM; -+ -+ return 0; -+} -+ -+static int vga_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem = file_sharemem(file); -+ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ -+ vma->vm_flags = (vma->vm_flags & (~VM_WRITE)); -+ remap_pfn_range(vma, vma->vm_start, vga_sharedmem->addr >> PAGE_SHIFT, -+ vga_sharedmem->size, vma->vm_page_prot); -+ return 0; -+} -+ -+static ssize_t enable_mmap_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%u\n", vga_sharedmem->mmap_enable); -+} -+ -+static ssize_t enable_mmap_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem = -+ dev_get_drvdata(dev); -+ bool val; -+ -+ if (kstrtobool(buf, &val)) -+ return -EINVAL; -+ -+ vga_sharedmem->mmap_enable = val; -+ -+ return count; -+} -+static DEVICE_ATTR_RW(enable_mmap); -+ -+static struct attribute *sharedmem_attrs[] = { -+ &dev_attr_enable_mmap.attr, -+ NULL -+}; -+ -+static const struct attribute_group sharedmem_attr_group = { -+ .attrs = sharedmem_attrs, -+}; -+ -+static const struct attribute_group *sharedmem_attr_groups[] = { -+ &sharedmem_attr_group, -+ NULL -+}; -+ -+static const struct file_operations vga_sharedmem_fops = { -+ .owner = THIS_MODULE, -+ .open = vga_open, -+ .mmap = vga_mmap, -+}; -+ -+static struct miscdevice vga_sharedmem_miscdev = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = SHAREDMEM_NAME, -+ .fops = &vga_sharedmem_fops, -+ .groups = sharedmem_attr_groups, -+}; -+ -+static int vga_sharedmem_probe(struct platform_device *pdev) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem; -+ struct device *dev = &pdev->dev; -+ struct resource *rc; -+ -+ vga_sharedmem = devm_kzalloc(dev, sizeof(*vga_sharedmem), GFP_KERNEL); -+ if (!vga_sharedmem) -+ return -ENOMEM; -+ -+ dev_set_drvdata(&pdev->dev, vga_sharedmem); -+ -+ rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!rc) { -+ dev_err(dev, "Couldn't read size device-tree property\n"); -+ return -ENXIO; -+ } -+ -+ vga_sharedmem->addr = rc->start; -+ vga_sharedmem->size = resource_size(rc); -+ vga_sharedmem->mmap_enable = true; -+ -+ vga_sharedmem->miscdev = vga_sharedmem_miscdev; -+ -+ return misc_register(&vga_sharedmem->miscdev); -+} -+ -+static int vga_sharedmem_remove(struct platform_device *pdev) -+{ -+ struct aspeed_vga_sharedmem *vga_sharedmem = -+ dev_get_drvdata(&pdev->dev); -+ -+ misc_deregister(&vga_sharedmem->miscdev); -+ -+ return 0; -+} -+ -+static const struct of_device_id vga_sharedmem_match[] = { -+ { .compatible = "aspeed,ast2500-vga-sharedmem", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, vga_sharedmem_match); -+ -+static struct platform_driver vga_sharedmem_driver = { -+ .driver = { -+ .name = "VGA-SHAREDMEM", -+ .of_match_table = vga_sharedmem_match, -+ }, -+ .probe = vga_sharedmem_probe, -+ .remove = vga_sharedmem_remove, -+}; -+ -+module_platform_driver(vga_sharedmem_driver); -+ -+MODULE_AUTHOR("Yang Cheng "); -+MODULE_DESCRIPTION("Shared VGA memory"); -+MODULE_LICENSE("GPL v2"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch deleted file mode 100644 index 0fdd40d77..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch +++ /dev/null @@ -1,514 +0,0 @@ -From b20b1ce81f4451d9e906b84e7edcc22d4e70e7df Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Mon, 11 Feb 2019 17:02:35 -0800 -Subject: [PATCH] Add Aspeed PWM driver which uses FTTMR010 timer IP - -This commit adds Aspeed PWM driver which uses timer pulse output -feature in Aspeed SoCs. The timer IP is derived from Faraday -Technologies FTTMR010 IP but has some customized register -structure changes only for Aspeed SoCs. - -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g5.dtsi | 2 +- - drivers/pwm/Kconfig | 9 + - drivers/pwm/Makefile | 1 + - drivers/pwm/pwm-fttmr010.c | 441 +++++++++++++++++++++++++++++++++++++++ - 4 files changed, 452 insertions(+), 1 deletion(-) - create mode 100644 drivers/pwm/pwm-fttmr010.c - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 27ed188296a1..45202bc3d60c 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -341,7 +341,7 @@ - - timer: timer@1e782000 { - /* This timer is a Faraday FTTMR010 derivative */ -- compatible = "aspeed,ast2400-timer"; -+ compatible = "aspeed,ast2500-timer"; - reg = <0x1e782000 0x90>; - interrupts = <16 17 18 35 36 37 38 39>; - clocks = <&syscon ASPEED_CLK_APB>; -diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig -index e3a2518503ed..21def8cd5af6 100644 ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -171,6 +171,15 @@ config PWM_FSL_FTM - To compile this driver as a module, choose M here: the module - will be called pwm-fsl-ftm. - -+config PWM_FTTMR010 -+ tristate "Faraday Technology FTTMR010 timer PWM support" -+ help -+ Generic PWM framework driver for Faraday Technology FTTMR010 Timer -+ PWM output -+ -+ To compile this driver as a module, choose M here: the module -+ will be called pwm-fttmr010 -+ - config PWM_HIBVT - tristate "HiSilicon BVT PWM support" - depends on ARCH_HISI || COMPILE_TEST -diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile -index 26326adf71d7..3a9e9840b5ae 100644 ---- a/drivers/pwm/Makefile -+++ b/drivers/pwm/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_CRC) += pwm-crc.o - obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o - obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o - obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o -+obj-$(CONFIG_PWM_FTTMR010) += pwm-fttmr010.o - obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o - obj-$(CONFIG_PWM_IMG) += pwm-img.o - obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o -diff --git a/drivers/pwm/pwm-fttmr010.c b/drivers/pwm/pwm-fttmr010.c -new file mode 100644 -index 000000000000..283ded6906f1 ---- /dev/null -+++ b/drivers/pwm/pwm-fttmr010.c -@@ -0,0 +1,441 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2019 Intel Corporation -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TIMER_CR 0x30 -+ -+#define TIMER5_ASPEED_COUNT 0x50 -+#define TIMER5_ASPEED_LOAD 0x54 -+#define TIMER5_ASPEED_MATCH1 0x58 -+#define TIMER5_ASPEED_MATCH2 0x5c -+#define TIMER6_ASPEED_COUNT 0x60 -+#define TIMER6_ASPEED_LOAD 0x64 -+#define TIMER6_ASPEED_MATCH1 0x68 -+#define TIMER6_ASPEED_MATCH2 0x6c -+#define TIMER7_ASPEED_COUNT 0x70 -+#define TIMER7_ASPEED_LOAD 0x74 -+#define TIMER7_ASPEED_MATCH1 0x78 -+#define TIMER7_ASPEED_MATCH2 0x7c -+#define TIMER8_ASPEED_COUNT 0x80 -+#define TIMER8_ASPEED_LOAD 0x84 -+#define TIMER8_ASPEED_MATCH1 0x88 -+#define TIMER8_ASPEED_MATCH2 0x8c -+ -+#define TIMER_5_CR_ASPEED_ENABLE BIT(16) -+#define TIMER_5_CR_ASPEED_CLOCK BIT(17) -+#define TIMER_5_CR_ASPEED_INT BIT(18) -+#define TIMER_5_CR_ASPEED_PULSE_OUT BIT(19) -+#define TIMER_6_CR_ASPEED_ENABLE BIT(20) -+#define TIMER_6_CR_ASPEED_CLOCK BIT(21) -+#define TIMER_6_CR_ASPEED_INT BIT(22) -+#define TIMER_6_CR_ASPEED_PULSE_OUT BIT(23) -+#define TIMER_7_CR_ASPEED_ENABLE BIT(24) -+#define TIMER_7_CR_ASPEED_CLOCK BIT(25) -+#define TIMER_7_CR_ASPEED_INT BIT(26) -+#define TIMER_7_CR_ASPEED_PULSE_OUT BIT(27) -+#define TIMER_8_CR_ASPEED_ENABLE BIT(28) -+#define TIMER_8_CR_ASPEED_CLOCK BIT(29) -+#define TIMER_8_CR_ASPEED_INT BIT(30) -+#define TIMER_8_CR_ASPEED_PULSE_OUT BIT(31) -+ -+/** -+ * struct pwm_fttmr010_variant - variant data depends on SoC -+ * @bits: timer counter resolution -+ * @chan_min: lowest timer channel which has pwm pulse output -+ * @chan_max: highest timer channel which has pwm pulse output -+ * @output_mask: pwm pulse output mask which is defined in device tree -+ */ -+struct pwm_fttmr010_variant { -+ u8 bits; -+ u8 chan_min; -+ u8 chan_max; -+ u8 output_mask; -+}; -+ -+/** -+ * struct pwm_fttmr010_chan - private data of FTTMR010 PWM channel -+ * @period_ns: current period in nanoseconds programmed to the hardware -+ * @duty_ns: current duty time in nanoseconds programmed to the hardware -+ */ -+struct pwm_fttmr010_chan { -+ u32 period_ns; -+ u32 duty_ns; -+}; -+ -+/** -+ * struct pwm_fttmr010 - private data of FTTMR010 PWM -+ * @chip: generic PWM chip -+ * @variant: local copy of hardware variant data -+ * @disabled_mask: disabled status for all channels - one bit per channel -+ * @base: base address of mapped PWM registers -+ * @clk: clock used to drive the timers -+ */ -+struct pwm_fttmr010 { -+ struct pwm_chip chip; -+ struct pwm_fttmr010_variant variant; -+ u8 disabled_mask; -+ void __iomem *base; -+ struct clk *clk; -+ u32 clk_tick_ns; -+}; -+ -+static inline -+struct pwm_fttmr010 *to_pwm_fttmr010(struct pwm_chip *chip) -+{ -+ return container_of(chip, struct pwm_fttmr010, chip); -+} -+ -+static int pwm_fttmr010_request(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip); -+ struct pwm_fttmr010_chan *chan; -+ -+ if (!(priv->variant.output_mask & BIT(pwm->hwpwm))) { -+ dev_warn(chip->dev, -+ "tried to request PWM channel %d without output\n", -+ pwm->hwpwm); -+ return -EINVAL; -+ } -+ -+ chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL); -+ if (!chan) -+ return -ENOMEM; -+ -+ pwm_set_chip_data(pwm, chan); -+ -+ return 0; -+} -+ -+static void pwm_fttmr010_free(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ devm_kfree(chip->dev, pwm_get_chip_data(pwm)); -+ pwm_set_chip_data(pwm, NULL); -+} -+ -+static int pwm_fttmr010_enable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip); -+ u32 cr; -+ -+ cr = readl(priv->base + TIMER_CR); -+ -+ switch (pwm->hwpwm) { -+ case 5: -+ cr |= (TIMER_5_CR_ASPEED_ENABLE | TIMER_5_CR_ASPEED_PULSE_OUT); -+ break; -+ case 6: -+ cr |= (TIMER_6_CR_ASPEED_ENABLE | TIMER_6_CR_ASPEED_PULSE_OUT); -+ break; -+ case 7: -+ cr |= (TIMER_7_CR_ASPEED_ENABLE | TIMER_7_CR_ASPEED_PULSE_OUT); -+ break; -+ case 8: -+ cr |= (TIMER_8_CR_ASPEED_ENABLE | TIMER_8_CR_ASPEED_PULSE_OUT); -+ break; -+ default: -+ return -ERANGE; -+ } -+ -+ writel(cr, priv->base + TIMER_CR); -+ priv->disabled_mask &= ~BIT(pwm->hwpwm); -+ -+ return 0; -+} -+ -+static void pwm_fttmr010_disable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip); -+ u32 cr; -+ -+ cr = readl(priv->base + TIMER_CR); -+ -+ switch (pwm->hwpwm) { -+ case 5: -+ cr &= ~(TIMER_5_CR_ASPEED_ENABLE | TIMER_5_CR_ASPEED_PULSE_OUT); -+ break; -+ case 6: -+ cr &= ~(TIMER_6_CR_ASPEED_ENABLE | TIMER_6_CR_ASPEED_PULSE_OUT); -+ break; -+ case 7: -+ cr &= ~(TIMER_7_CR_ASPEED_ENABLE | TIMER_7_CR_ASPEED_PULSE_OUT); -+ break; -+ case 8: -+ cr &= ~(TIMER_8_CR_ASPEED_ENABLE | TIMER_8_CR_ASPEED_PULSE_OUT); -+ break; -+ default: -+ return; -+ } -+ -+ writel(cr, priv->base + TIMER_CR); -+ priv->disabled_mask |= BIT(pwm->hwpwm); -+} -+ -+static int pwm_fttmr010_config(struct pwm_chip *chip, struct pwm_device *pwm, -+ int duty_ns, int period_ns) -+{ -+ u32 tload, tmatch, creg_offset, lreg_offset, mreg_offset; -+ struct pwm_fttmr010_chan *chan = pwm_get_chip_data(pwm); -+ struct pwm_fttmr010 *priv = to_pwm_fttmr010(chip); -+ -+ /* -+ * We currently avoid using 64bit arithmetic by using the -+ * fact that anything faster than 1Hz is easily representable -+ * by 32bits. -+ */ -+ if (period_ns > NSEC_PER_SEC) -+ return -ERANGE; -+ -+ /* No need to update */ -+ if (chan->period_ns == period_ns || chan->duty_ns == duty_ns) -+ return 0; -+ -+ tload = period_ns / priv->clk_tick_ns; -+ -+ /* Period is too short */ -+ if (tload <= 1) -+ return -ERANGE; -+ -+ tmatch = duty_ns / priv->clk_tick_ns; -+ -+ /* 0% duty is not available */ -+ if (!tmatch) -+ ++tmatch; -+ -+ tmatch = tload - tmatch; -+ -+ /* Decrement to get tick numbers, instead of tick counts */ -+ --tload; -+ --tmatch; -+ -+ if (tload == 0 || tmatch == 0) -+ return -ERANGE; -+ -+ dev_dbg(priv->chip.dev, "clk_tick_ns:%u, tload:%u, tmatch:%u\n", -+ priv->clk_tick_ns, tload, tmatch); -+ -+ switch (pwm->hwpwm) { -+ case 5: -+ creg_offset = TIMER5_ASPEED_COUNT; -+ lreg_offset = TIMER5_ASPEED_LOAD; -+ mreg_offset = TIMER5_ASPEED_MATCH1; -+ break; -+ case 6: -+ creg_offset = TIMER6_ASPEED_COUNT; -+ lreg_offset = TIMER6_ASPEED_LOAD; -+ mreg_offset = TIMER6_ASPEED_MATCH1; -+ break; -+ case 7: -+ creg_offset = TIMER7_ASPEED_COUNT; -+ lreg_offset = TIMER7_ASPEED_LOAD; -+ mreg_offset = TIMER7_ASPEED_MATCH1; -+ break; -+ case 8: -+ creg_offset = TIMER8_ASPEED_COUNT; -+ lreg_offset = TIMER8_ASPEED_LOAD; -+ mreg_offset = TIMER8_ASPEED_MATCH1; -+ break; -+ default: -+ return -ERANGE; -+ } -+ -+ writel(tload, priv->base + creg_offset); -+ writel(tload, priv->base + lreg_offset); -+ writel(tmatch, priv->base + mreg_offset); -+ -+ chan->period_ns = period_ns; -+ chan->duty_ns = duty_ns; -+ -+ return 0; -+} -+ -+static const struct pwm_ops pwm_fttmr010_ops = { -+ .request = pwm_fttmr010_request, -+ .free = pwm_fttmr010_free, -+ .enable = pwm_fttmr010_enable, -+ .disable = pwm_fttmr010_disable, -+ .config = pwm_fttmr010_config, -+ .owner = THIS_MODULE, -+}; -+ -+#ifdef CONFIG_OF -+static const struct pwm_fttmr010_variant aspeed_variant = { -+ .bits = 32, -+ .chan_min = 5, -+ .chan_max = 8, -+}; -+ -+static const struct of_device_id pwm_fttmr010_matches[] = { -+ { .compatible = "aspeed,ast2400-timer", .data = &aspeed_variant }, -+ { .compatible = "aspeed,ast2500-timer", .data = &aspeed_variant }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, pwm_fttmr010_matches); -+ -+static int pwm_fttmr010_parse_dt(struct pwm_fttmr010 *priv) -+{ -+ struct device_node *np = priv->chip.dev->of_node; -+ const struct of_device_id *match; -+ struct property *prop; -+ const __be32 *cur; -+ u32 val; -+ -+ match = of_match_node(pwm_fttmr010_matches, np); -+ if (!match) -+ return -ENODEV; -+ -+ memcpy(&priv->variant, match->data, sizeof(priv->variant)); -+ -+ of_property_for_each_u32(np, "fttmr010,pwm-outputs", prop, cur, val) { -+ if (val < priv->variant.chan_min || -+ val > priv->variant.chan_max) { -+ dev_err(priv->chip.dev, -+ "invalid channel index in fttmr010,pwm-outputs property\n"); -+ continue; -+ } -+ priv->variant.output_mask |= BIT(val); -+ } -+ -+ return 0; -+} -+#else -+static int pwm_fttmr010_parse_dt(struct pwm_fttmr010 *priv) -+{ -+ return -ENODEV; -+} -+#endif -+ -+static int pwm_fttmr010_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct pwm_fttmr010 *priv; -+ struct resource *res; -+ ulong clk_rate; -+ int ret; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->chip.dev = &pdev->dev; -+ priv->chip.ops = &pwm_fttmr010_ops; -+ priv->chip.base = -1; -+ -+ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { -+ ret = pwm_fttmr010_parse_dt(priv); -+ if (ret) -+ return ret; -+ -+ priv->chip.of_xlate = of_pwm_xlate_with_flags; -+ priv->chip.of_pwm_n_cells = 3; -+ } else { -+ if (!pdev->dev.platform_data) { -+ dev_err(&pdev->dev, "no platform data specified\n"); -+ return -EINVAL; -+ } -+ -+ memcpy(&priv->variant, pdev->dev.platform_data, -+ sizeof(priv->variant)); -+ } -+ -+ priv->chip.npwm = priv->variant.chan_max + 1; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(priv->base)) -+ return PTR_ERR(priv->base); -+ -+ priv->clk = devm_clk_get(&pdev->dev, "PCLK"); -+ if (IS_ERR(priv->clk)) { -+ dev_err(dev, "failed to get timer base clk\n"); -+ return PTR_ERR(priv->clk); -+ } -+ -+ ret = clk_prepare_enable(priv->clk); -+ if (ret < 0) { -+ dev_err(dev, "failed to enable base clock\n"); -+ return ret; -+ } -+ -+ clk_rate = clk_get_rate(priv->clk); -+ priv->clk_tick_ns = NSEC_PER_SEC / clk_rate; -+ -+ platform_set_drvdata(pdev, priv); -+ -+ ret = pwmchip_add(&priv->chip); -+ if (ret < 0) { -+ dev_err(dev, "failed to register PWM chip\n"); -+ clk_disable_unprepare(priv->clk); -+ return ret; -+ } -+ -+ dev_dbg(dev, "clk at %lu\n", clk_rate); -+ -+ return 0; -+} -+ -+static int pwm_fttmr010_remove(struct platform_device *pdev) -+{ -+ struct pwm_fttmr010 *priv = platform_get_drvdata(pdev); -+ int ret; -+ -+ ret = pwmchip_remove(&priv->chip); -+ if (ret < 0) -+ return ret; -+ -+ clk_disable_unprepare(priv->clk); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int pwm_fttmr010_resume(struct device *dev) -+{ -+ struct pwm_fttmr010 *priv = dev_get_drvdata(dev); -+ struct pwm_chip *chip = &priv->chip; -+ unsigned int i; -+ -+ for (i = priv->variant.chan_min; i < priv->variant.chan_max; i++) { -+ struct pwm_device *pwm = &chip->pwms[i]; -+ struct pwm_fttmr010_chan *chan = pwm_get_chip_data(pwm); -+ -+ if (!chan) -+ continue; -+ -+ if (chan->period_ns) { -+ pwm_fttmr010_config(chip, pwm, chan->duty_ns, -+ chan->period_ns); -+ } -+ -+ if (priv->disabled_mask & BIT(i)) -+ pwm_fttmr010_disable(chip, pwm); -+ else -+ pwm_fttmr010_enable(chip, pwm); -+ } -+ -+ return 0; -+} -+#endif -+ -+static SIMPLE_DEV_PM_OPS(pwm_fttmr010_pm_ops, NULL, pwm_fttmr010_resume); -+ -+static struct platform_driver pwm_fttmr010_driver = { -+ .driver = { -+ .name = "fttmr010-timer-pwm", -+ .pm = &pwm_fttmr010_pm_ops, -+ .of_match_table = of_match_ptr(pwm_fttmr010_matches), -+ }, -+ .probe = pwm_fttmr010_probe, -+ .remove = pwm_fttmr010_remove, -+}; -+module_platform_driver(pwm_fttmr010_driver); -+ -+MODULE_AUTHOR("Jae Hyun Yoo "); -+MODULE_DESCRIPTION("FTTMR010 PWM Driver for timer pulse outputs"); -+MODULE_LICENSE("GPL v2"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch deleted file mode 100644 index 198beaa93..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch +++ /dev/null @@ -1,488 +0,0 @@ -From ee9cee93b96b791f52295d7763985fdb10903e2b Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 15 Feb 2019 16:05:09 -0800 -Subject: [PATCH] i2c: Add mux hold/unhold msg types - -This commit adds mux hold/unhold message types to support extended -mux control for IPMB and MCTP devices. A hold or an unhold message -can be added at the end of I2C message stream wrapped by -repeated-start, also can be used as a single message independantly. - -This mux hold/unhold message will be delivered throughout all mux -levels in the path. Means that if it goes to multi-level mux path, -all muxes will be held/unheld by this message. - -1. Hold message - struct i2c_msg msg; - uint16_t timeout = 5000; // timeout in ms. 5 secs in this example. - - msg.addr = 0x0; // any value can be used. addr will be ignored in this packet. - msg.flags = I2C_M_HOLD; // set this flag to indicate it's a hold message. - msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer. - msg.buf = (uint8_t *)&timeout; // set timeout value. - -2. Unhold message - struct i2c_msg msg; - uint16_t timeout = 0; // set 0 for an unhold message. - - msg.addr = 0x0; // any value can be used. addr will be ignored in this packet. - msg.flags = I2C_M_HOLD; // set this flag to indicate it's an unhold message. - msg.len = sizeof(uint16_t); // timeout value will be delivered using two bytes buffer. - msg.buf = (uint8_t *)&timeout; // set timeout value. - - This unhold message can be delivered to a mux adapter even when - a bus is locked so that any holding state can be unheld - immediately by invoking this unhold message. - -This patch would not be welcomed from upstream so it should be kept -in downstream only. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/i2c-core-base.c | 70 +++++++++++++++++++++++++-- - drivers/i2c/i2c-core-smbus.c | 22 +++++++-- - drivers/i2c/i2c-mux.c | 109 +++++++++++++++++++++++++++++++++++++++---- - include/linux/i2c-mux.h | 3 ++ - include/linux/i2c.h | 25 ++++++++++ - include/uapi/linux/i2c.h | 1 + - 6 files changed, 214 insertions(+), 16 deletions(-) - -diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c -index 5f6a4985f2bc..d1cd7afe4068 100644 ---- a/drivers/i2c/i2c-core-base.c -+++ b/drivers/i2c/i2c-core-base.c -@@ -1297,6 +1297,25 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr) - } - EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify); - -+static void i2c_adapter_hold(struct i2c_adapter *adapter, unsigned long timeout) -+{ -+ mutex_lock(&adapter->hold_lock); -+ mod_timer(&adapter->hold_timer, jiffies + timeout); -+} -+ -+static void i2c_adapter_unhold(struct i2c_adapter *adapter) -+{ -+ del_timer_sync(&adapter->hold_timer); -+ mutex_unlock(&adapter->hold_lock); -+} -+ -+static void i2c_adapter_hold_timer_callback(struct timer_list *t) -+{ -+ struct i2c_adapter *adapter = from_timer(adapter, t, hold_timer); -+ -+ i2c_adapter_unhold(adapter); -+} -+ - static int i2c_register_adapter(struct i2c_adapter *adap) - { - int res = -EINVAL; -@@ -1379,6 +1398,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap) - bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); - mutex_unlock(&core_lock); - -+ mutex_init(&adap->hold_lock); -+ timer_setup(&adap->hold_timer, i2c_adapter_hold_timer_callback, 0); -+ - return 0; - - out_reg: -@@ -1599,6 +1621,8 @@ void i2c_del_adapter(struct i2c_adapter *adap) - idr_remove(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - -+ i2c_adapter_unhold(adap); -+ - /* Clear the device structure in case this adapter is ever going to be - added again */ - memset(&adap->dev, 0, sizeof(adap->dev)); -@@ -1948,7 +1972,9 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, - */ - int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - { -+ enum i2c_hold_msg_type hold_msg = I2C_HOLD_MSG_NONE; - unsigned long orig_jiffies; -+ unsigned long timeout; - int ret, try; - - if (WARN_ON(!msgs || num < 1)) -@@ -1961,6 +1987,25 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) - return -EOPNOTSUPP; - -+ /* Do not deliver a mux hold msg to root bus adapter */ -+ if (!i2c_parent_is_i2c_adapter(adap)) { -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_adapter_hold(adap, timeout); -+ -+ if (--num == 0) -+ return 0; -+ } else if (hold_msg == I2C_HOLD_MSG_RESET) { -+ i2c_adapter_unhold(adap); -+ return 0; -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&adap->hold_lock); -+ } -+ } -+ - /* - * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets - * enabled. This is an efficient way of keeping the for-loop from -@@ -1997,6 +2042,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - trace_i2c_result(adap, num, ret); - } - -+ if (!i2c_parent_is_i2c_adapter(adap) && hold_msg == I2C_HOLD_MSG_NONE) -+ mutex_unlock(&adap->hold_lock); -+ - return ret; - } - EXPORT_SYMBOL(__i2c_transfer); -@@ -2015,6 +2063,7 @@ EXPORT_SYMBOL(__i2c_transfer); - */ - int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - { -+ bool do_bus_lock = true; - int ret; - - if (!adap->algo->master_xfer) { -@@ -2038,12 +2087,25 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) - * one (discarding status on the second message) or errno - * (discarding status on the first one). - */ -- ret = __i2c_lock_bus_helper(adap); -- if (ret) -- return ret; -+ /* -+ * Do not lock a bus for delivering an unhold msg to a mux -+ * adpater. This is just for a single length unhold msg case. -+ */ -+ if (num == 1 && i2c_parent_is_i2c_adapter(adap) && -+ i2c_check_hold_msg(msgs[0].flags, msgs[0].len, -+ (u16 *)msgs[0].buf) == -+ I2C_HOLD_MSG_RESET) -+ do_bus_lock = false; -+ -+ if (do_bus_lock) { -+ ret = __i2c_lock_bus_helper(adap); -+ if (ret) -+ return ret; -+ } - - ret = __i2c_transfer(adap, msgs, num); -- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); -+ if (do_bus_lock) -+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); - - return ret; - } -diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c -index 3ac426a8ab5a..f7bf95101e34 100644 ---- a/drivers/i2c/i2c-core-smbus.c -+++ b/drivers/i2c/i2c-core-smbus.c -@@ -526,15 +526,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, - u8 command, int protocol, union i2c_smbus_data *data) - { -+ bool do_bus_lock = true; - s32 res; - -- res = __i2c_lock_bus_helper(adapter); -- if (res) -- return res; -+ /* -+ * Do not lock a bus for delivering an unhold msg to a mux adpater. -+ * This is just for a single length unhold msg case. -+ */ -+ if (i2c_parent_is_i2c_adapter(adapter) && -+ i2c_check_hold_msg(flags, -+ protocol == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word) == I2C_HOLD_MSG_RESET) -+ do_bus_lock = false; -+ -+ if (do_bus_lock) { -+ res = __i2c_lock_bus_helper(adapter); -+ if (res) -+ return res; -+ } - - res = __i2c_smbus_xfer(adapter, addr, flags, read_write, - command, protocol, data); -- i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT); -+ if (do_bus_lock) -+ i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT); - - return res; - } -diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c -index 774507b54b57..c6e433238b22 100644 ---- a/drivers/i2c/i2c-mux.c -+++ b/drivers/i2c/i2c-mux.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - /* multiplexer per channel data */ - struct i2c_mux_priv { -@@ -36,21 +37,57 @@ struct i2c_mux_priv { - u32 chan_id; - }; - -+static void i2c_mux_hold(struct i2c_mux_core *muxc, unsigned long timeout) -+{ -+ mutex_lock(&muxc->hold_lock); -+ mod_timer(&muxc->hold_timer, jiffies + timeout); -+} -+ -+static void i2c_mux_unhold(struct i2c_mux_core *muxc) -+{ -+ del_timer_sync(&muxc->hold_timer); -+ mutex_unlock(&muxc->hold_lock); -+} -+ -+static void i2c_mux_hold_timer_callback(struct timer_list *t) -+{ -+ struct i2c_mux_core *muxc = from_timer(muxc, t, hold_timer); -+ -+ i2c_mux_unhold(muxc); -+} -+ - static int __i2c_mux_master_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) - { - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Switch to the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = __i2c_transfer(parent, msgs, num); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -61,15 +98,32 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Switch to the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(msgs[num - 1].flags, -+ msgs[num - 1].len, -+ (u16 *)msgs[num - 1].buf); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(*(u16 *)msgs[num - 1].buf); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = i2c_transfer(parent, msgs, num); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -82,16 +136,33 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Select the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(flags, -+ size == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(data->word); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = __i2c_smbus_xfer(parent, addr, flags, - read_write, command, size, data); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -104,16 +175,33 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_mux_core *muxc = priv->muxc; - struct i2c_adapter *parent = muxc->parent; -+ enum i2c_hold_msg_type hold_msg; -+ unsigned long timeout; - int ret; - - /* Select the right mux port and perform the transfer. */ - -+ hold_msg = i2c_check_hold_msg(flags, -+ size == I2C_SMBUS_WORD_DATA ? 2 : 0, -+ &data->word); -+ if (hold_msg == I2C_HOLD_MSG_SET) { -+ timeout = msecs_to_jiffies(data->word); -+ i2c_mux_hold(muxc, timeout); -+ } else if (hold_msg == I2C_HOLD_MSG_NONE) { -+ mutex_lock(&muxc->hold_lock); -+ } - ret = muxc->select(muxc, priv->chan_id); - if (ret >= 0) - ret = i2c_smbus_xfer(parent, addr, flags, - read_write, command, size, data); -- if (muxc->deselect) -- muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg != I2C_HOLD_MSG_SET) { -+ if (muxc->deselect) -+ muxc->deselect(muxc, priv->chan_id); -+ if (hold_msg == I2C_HOLD_MSG_RESET) -+ i2c_mux_unhold(muxc); -+ else -+ mutex_unlock(&muxc->hold_lock); -+ } - - return ret; - } -@@ -263,6 +351,9 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent, - muxc->deselect = deselect; - muxc->max_adapters = max_adapters; - -+ mutex_init(&muxc->hold_lock); -+ timer_setup(&muxc->hold_timer, i2c_mux_hold_timer_callback, 0); -+ - return muxc; - } - EXPORT_SYMBOL_GPL(i2c_mux_alloc); -@@ -441,6 +532,8 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc) - { - char symlink_name[20]; - -+ i2c_mux_unhold(muxc); -+ - while (muxc->num_adapters) { - struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters]; - struct i2c_mux_priv *priv = adap->algo_data; -diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h -index c5a977320f82..47f8763d6ed2 100644 ---- a/include/linux/i2c-mux.h -+++ b/include/linux/i2c-mux.h -@@ -27,6 +27,9 @@ struct i2c_mux_core { - int (*select)(struct i2c_mux_core *, u32 chan_id); - int (*deselect)(struct i2c_mux_core *, u32 chan_id); - -+ struct mutex hold_lock; /* mutex for channel holding */ -+ struct timer_list hold_timer; -+ - int num_adapters; - int max_adapters; - struct i2c_adapter *adapter[0]; -diff --git a/include/linux/i2c.h b/include/linux/i2c.h -index 1361637c369d..b4055d133338 100644 ---- a/include/linux/i2c.h -+++ b/include/linux/i2c.h -@@ -711,6 +711,13 @@ struct i2c_adapter { - const struct i2c_adapter_quirks *quirks; - - struct irq_domain *host_notify_domain; -+ -+ /* -+ * These will be used by root adpaters only. For muxes, each mux core -+ * has these individually. -+ */ -+ struct mutex hold_lock; /* mutex for bus holding */ -+ struct timer_list hold_timer; - }; - #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) - -@@ -1005,4 +1012,22 @@ static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle ha - } - #endif /* CONFIG_ACPI */ - -+enum i2c_hold_msg_type { -+ I2C_HOLD_MSG_NONE, -+ I2C_HOLD_MSG_SET, -+ I2C_HOLD_MSG_RESET -+}; -+ -+static inline enum i2c_hold_msg_type i2c_check_hold_msg(u16 flags, u16 len, u16 *buf) -+{ -+ if (flags & I2C_M_HOLD && len == sizeof(u16)) { -+ if (*buf) -+ return I2C_HOLD_MSG_SET; -+ -+ return I2C_HOLD_MSG_RESET; -+ } -+ -+ return I2C_HOLD_MSG_NONE; -+} -+ - #endif /* _LINUX_I2C_H */ -diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h -index f71a1751cacf..a1db9b17ed36 100644 ---- a/include/uapi/linux/i2c.h -+++ b/include/uapi/linux/i2c.h -@@ -72,6 +72,7 @@ struct i2c_msg { - #define I2C_M_RD 0x0001 /* read data, from slave to master */ - /* I2C_M_RD is guaranteed to be 0x0001! */ - #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ -+#define I2C_M_HOLD 0x0100 /* for holding a mux path */ - #define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */ - /* makes only sense in kernelspace */ - /* userspace buffers are copied anyway */ --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch deleted file mode 100644 index 5b9d4ef8b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 37e7896bf297edef4f2877998ca7a5c086015591 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 7 Mar 2019 15:17:40 -0800 -Subject: [PATCH] Add bus-timeout-ms and #retries device tree properties - -BMC uses I2C bus 7 as a PMBus channel to communicate with PSUs, -also ME uses this bus as SMLink to control PSUs so this bus is -managed by multi-masters. In this use case, some arbitration errors -are expected so we need to add retry logic. And PMBus subsystem -uses I2C bus in kernel internally so retry logic should be -supported in kernel level. - -To support the use case, this commit adds 'bus-timeout-ms' and -'#retries' device tree properties to set the bus specific -parameters at kernel boot time without using any additional ioctls -from user space. - -This patch would not be accepted by I2C maintainer in linux -upstream because he doesn't like adding these legacy properties -into device tree, so keep it only in downstream. - -Signed-off-by: Jae Hyun Yoo ---- - Documentation/devicetree/bindings/i2c/i2c-aspeed.txt | 3 +++ - Documentation/devicetree/bindings/i2c/i2c.txt | 6 ++++++ - drivers/i2c/busses/i2c-aspeed.c | 1 - - drivers/i2c/i2c-core-base.c | 12 ++++++++++-- - 4 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -index 8fbd8633a387..7da7e813b2b0 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -@@ -16,6 +16,9 @@ Optional Properties: - - bus-frequency : frequency of the bus clock in Hz defaults to 100 kHz when not - specified - - multi-master : states that there is another master active on this bus. -+- bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not -+ specified. -+- #retries : Number of retries for master transfer. - - Example: - -diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt -index 44efafdfd7f5..e382931cf3d6 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c.txt -@@ -80,6 +80,12 @@ wants to support one of the below features, it should adapt the bindings below. - Names of map programmable addresses. - It can contain any map needing another address than default one. - -+- bus-timeout-ms -+ Bus timeout in milliseconds. -+ -+- #retries -+ Number of retries for master transfer. -+ - Binding may contain optional "interrupts" property, describing interrupts - used by the device. I2C core will assign "irq" interrupt (or the very first - interrupt if not using interrupt names) as primary interrupt for the slave. -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index c113ffa8d5df..7becfcd67142 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -1032,7 +1032,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - spin_lock_init(&bus->lock); - init_completion(&bus->cmd_complete); - bus->adap.owner = THIS_MODULE; -- bus->adap.retries = 0; - bus->adap.algo = &aspeed_i2c_algo; - bus->adap.dev.parent = &pdev->dev; - bus->adap.dev.of_node = pdev->dev.of_node; -diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c -index d1cd7afe4068..1db991220fae 100644 ---- a/drivers/i2c/i2c-core-base.c -+++ b/drivers/i2c/i2c-core-base.c -@@ -1318,6 +1318,7 @@ static void i2c_adapter_hold_timer_callback(struct timer_list *t) - - static int i2c_register_adapter(struct i2c_adapter *adap) - { -+ u32 bus_timeout_ms = 0; - int res = -EINVAL; - - /* Can't register until after driver model init */ -@@ -1345,8 +1346,15 @@ static int i2c_register_adapter(struct i2c_adapter *adap) - INIT_LIST_HEAD(&adap->userspace_clients); - - /* Set default timeout to 1 second if not already set */ -- if (adap->timeout == 0) -- adap->timeout = HZ; -+ if (adap->timeout == 0) { -+ device_property_read_u32(&adap->dev, "bus-timeout-ms", -+ &bus_timeout_ms); -+ adap->timeout = bus_timeout_ms ? -+ msecs_to_jiffies(bus_timeout_ms) : HZ; -+ } -+ -+ /* Set retries count if it has the property setting */ -+ device_property_read_u32(&adap->dev, "#retries", &adap->retries); - - /* register soft irqs for Host Notify */ - res = i2c_setup_host_notify_irq_domain(adap); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch deleted file mode 100644 index 6cc7d1138..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 301c1aaba9e59eb593406d878451e3ea4fe355bb Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 13 Mar 2019 15:04:16 -0700 -Subject: [PATCH] char: ipmi: Add clock control logic into Aspeed LPC BT driver - -If LPC BT driver is registered ahead of lpc-ctrl module, LPC BT -block will be enabled without heart beating of LCLK until lpc-ctrl -enables the LCLK. This issue causes improper handling on host -interrupts when the host sends interrupt in that time frame. Then -kernel eventually forcibly disables the interrupt with dumping -stack and printing a 'nobody cared this irq' message out. - -To prevent this issue, all LPC sub-nodes should enable LCLK -individually so this patch adds clock control logic into the LPC -BT driver. - -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Vernon Mauery ---- - .../bindings/ipmi/aspeed,ast2400-ibt-bmc.txt | 3 +++ - arch/arm/boot/dts/aspeed-g4.dtsi | 1 + - arch/arm/boot/dts/aspeed-g5.dtsi | 1 + - arch/arm/boot/dts/aspeed-g6.dtsi | 1 + - drivers/char/ipmi/bt-bmc.c | 24 +++++++++++++++++++++- - 5 files changed, 29 insertions(+), 1 deletion(-) - -diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt -index 028268fd99ee..d13887d60f19 100644 ---- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt -+++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.txt -@@ -10,6 +10,8 @@ Required properties: - "aspeed,ast2400-ibt-bmc" - "aspeed,ast2500-ibt-bmc" - - reg: physical address and size of the registers -+- clocks: contains a phandle to the syscon node describing the clocks. -+ There should then be one cell representing the clock to use. - - Optional properties: - -@@ -22,4 +24,5 @@ Example: - compatible = "aspeed,ast2400-ibt-bmc"; - reg = <0x1e789140 0x18>; - interrupts = <8>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - }; -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index 054d97229626..db962ab435af 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -386,6 +386,7 @@ - ibt: ibt@c0 { - compatible = "aspeed,ast2400-ibt-bmc"; - reg = <0xc0 0x18>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - interrupts = <8>; - status = "disabled"; - }; -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 45202bc3d60c..c4724ec27041 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -499,6 +499,7 @@ - ibt: ibt@c0 { - compatible = "aspeed,ast2500-ibt-bmc"; - reg = <0xc0 0x18>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - interrupts = <8>; - status = "disabled"; - }; -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 8cc978058f16..a557a7e6fe8d 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -524,6 +524,7 @@ - ibt: ibt@c0 { - compatible = "aspeed,ast2600-ibt-bmc"; - reg = <0xc0 0x18>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - interrupts = ; - status = "disabled"; - }; -diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c -index 0e600449931b..87bf3ff28542 100644 ---- a/drivers/char/ipmi/bt-bmc.c -+++ b/drivers/char/ipmi/bt-bmc.c -@@ -5,6 +5,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -60,6 +61,7 @@ struct bt_bmc { - struct device dev; - struct miscdevice miscdev; - struct regmap *map; -+ struct clk *clk; - int offset; - int irq; - wait_queue_head_t queue; -@@ -467,6 +469,19 @@ static int bt_bmc_probe(struct platform_device *pdev) - mutex_init(&bt_bmc->mutex); - init_waitqueue_head(&bt_bmc->queue); - -+ bt_bmc->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(bt_bmc->clk)) { -+ rc = PTR_ERR(bt_bmc->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; -+ } -+ rc = clk_prepare_enable(bt_bmc->clk); -+ if (rc) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return rc; -+ } -+ - bt_bmc->miscdev.minor = MISC_DYNAMIC_MINOR, - bt_bmc->miscdev.name = DEVICE_NAME, - bt_bmc->miscdev.fops = &bt_bmc_fops, -@@ -474,7 +489,7 @@ static int bt_bmc_probe(struct platform_device *pdev) - rc = misc_register(&bt_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register misc device\n"); -- return rc; -+ goto err; - } - - bt_bmc_config_irq(bt_bmc, pdev); -@@ -498,6 +513,11 @@ static int bt_bmc_probe(struct platform_device *pdev) - clr_b_busy(bt_bmc); - - return 0; -+ -+err: -+ clk_disable_unprepare(bt_bmc->clk); -+ -+ return rc; - } - - static int bt_bmc_remove(struct platform_device *pdev) -@@ -507,6 +527,8 @@ static int bt_bmc_remove(struct platform_device *pdev) - misc_deregister(&bt_bmc->miscdev); - if (!bt_bmc->irq) - del_timer_sync(&bt_bmc->poll_timer); -+ clk_disable_unprepare(bt_bmc->clk); -+ - return 0; - } - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch deleted file mode 100644 index b3ace73f6..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 404f73827714e324a21250b1a855fdc10fcfaf51 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 13 Mar 2019 15:27:48 -0700 -Subject: [PATCH] misc: Add clock control logic into Aspeed LPC SNOOP driver - -If LPC SNOOP driver is registered ahead of lpc-ctrl module, LPC -SNOOP block will be enabled without heart beating of LCLK until -lpc-ctrl enables the LCLK. This issue causes improper handling on -host interrupts when the host sends interrupt in that time frame. -Then kernel eventually forcibly disables the interrupt with -dumping stack and printing a 'nobody cared this irq' message out. - -To prevent this issue, all LPC sub-nodes should enable LCLK -individually so this patch adds clock control logic into the LPC -SNOOP driver. - -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Vernon Mauery ---- - arch/arm/boot/dts/aspeed-g4.dtsi | 1 + - arch/arm/boot/dts/aspeed-g5.dtsi | 1 + - arch/arm/boot/dts/aspeed-g6.dtsi | 1 + - drivers/soc/aspeed/aspeed-lpc-snoop.c | 30 +++++++++++++++++++++++++++--- - 4 files changed, 30 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index db962ab435af..24a20384b5e8 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -369,6 +369,7 @@ - compatible = "aspeed,ast2400-lpc-snoop"; - reg = <0x0 0x80>; - interrupts = <8>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index c4724ec27041..18d2a465c0ed 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -482,6 +482,7 @@ - compatible = "aspeed,ast2500-lpc-snoop"; - reg = <0x0 0x80>; - interrupts = <8>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index a557a7e6fe8d..4035d7bd647e 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -507,6 +507,7 @@ - compatible = "aspeed,ast2600-lpc-snoop"; - reg = <0x0 0x80>; - interrupts = ; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - -diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c -index c7b4ac066b40..ed272677fc82 100644 ---- a/drivers/soc/aspeed/aspeed-lpc-snoop.c -+++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c -@@ -11,6 +11,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -67,6 +68,7 @@ struct aspeed_lpc_snoop_channel { - struct aspeed_lpc_snoop { - struct regmap *regmap; - int irq; -+ struct clk *clk; - struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; - }; - -@@ -282,22 +284,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) - return -ENODEV; - } - -+ lpc_snoop->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(lpc_snoop->clk)) { -+ rc = PTR_ERR(lpc_snoop->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; -+ } -+ rc = clk_prepare_enable(lpc_snoop->clk); -+ if (rc) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return rc; -+ } -+ - rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev); - if (rc) -- return rc; -+ goto err; - - rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); - if (rc) -- return rc; -+ goto err; - - /* Configuration of 2nd snoop channel port is optional */ - if (of_property_read_u32_index(dev->of_node, "snoop-ports", - 1, &port) == 0) { - rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); -- if (rc) -+ if (rc) { - aspeed_lpc_disable_snoop(lpc_snoop, 0); -+ goto err; -+ } - } - -+ return 0; -+ -+err: -+ clk_disable_unprepare(lpc_snoop->clk); -+ - return rc; - } - -@@ -309,6 +331,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) - aspeed_lpc_disable_snoop(lpc_snoop, 0); - aspeed_lpc_disable_snoop(lpc_snoop, 1); - -+ clk_disable_unprepare(lpc_snoop->clk); -+ - return 0; - } - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch deleted file mode 100644 index 1c0903d71..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch +++ /dev/null @@ -1,273 +0,0 @@ -From cd62ca008a771bd6b7aeb06526c37d8435f86648 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 13 Mar 2019 15:36:34 -0700 -Subject: [PATCH] char: ipmi: Add clock control logic into Aspeed LPC KCS - driver - -If LPC KCS driver is registered ahead of lpc-ctrl module, LPC KCS -block will be enabled without heart beating of LCLK until lpc-ctrl -enables the LCLK. This issue causes improper handling on host -interrupts when the host sends interrupt in that time frame. Then -kernel eventually forcibly disables the interrupt with dumping -stack and printing a 'nobody cared this irq' message out. - -To prevent this issue, all LPC sub-nodes should enable LCLK -individually so this patch adds clock control logic into the LPC -KCS driver. - -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Vernon Mauery ---- - .../devicetree/bindings/ipmi/aspeed-kcs-bmc.txt | 3 ++ - arch/arm/boot/dts/aspeed-g4.dtsi | 35 ++++++++++++++++++++ - arch/arm/boot/dts/aspeed-g5.dtsi | 6 +++- - arch/arm/boot/dts/aspeed-g6.dtsi | 6 ++++ - drivers/char/ipmi/kcs_bmc_aspeed.c | 37 ++++++++++++++++++---- - 5 files changed, 79 insertions(+), 8 deletions(-) - -diff --git a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt -index d98a9bf45d6c..3453eb0bf8f2 100644 ---- a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt -+++ b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt -@@ -9,6 +9,8 @@ Required properties: - "aspeed,ast2400-kcs-bmc" - "aspeed,ast2500-kcs-bmc" - - interrupts : interrupt generated by the controller -+- clocks: contains a phandle to the syscon node describing the clocks. -+ There should then be one cell representing the clock to use. - - kcs_chan : The LPC channel number in the controller - - kcs_addr : The host CPU IO map address - -@@ -19,6 +21,7 @@ Example: - compatible = "aspeed,ast2500-kcs-bmc"; - reg = <0x0 0x80>; - interrupts = <8>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - kcs_chan = <3>; - kcs_addr = <0xCA2>; - status = "okay"; -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index 24a20384b5e8..fc6f4e009db7 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -347,6 +347,33 @@ - lpc_bmc: lpc-bmc@0 { - compatible = "aspeed,ast2400-lpc-bmc"; - reg = <0x0 0x80>; -+ reg-io-width = <4>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x0 0x80>; -+ -+ kcs1: kcs1@0 { -+ compatible = "aspeed,ast2400-kcs-bmc"; -+ interrupts = <8>; -+ kcs_chan = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ kcs2: kcs2@0 { -+ compatible = "aspeed,ast2400-kcs-bmc"; -+ interrupts = <8>; -+ kcs_chan = <2>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ kcs3: kcs3@0 { -+ compatible = "aspeed,ast2400-kcs-bmc"; -+ interrupts = <8>; -+ kcs_chan = <3>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; - }; - - lpc_host: lpc-host@80 { -@@ -358,6 +385,14 @@ - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; - -+ kcs4: kcs4@0 { -+ compatible = "aspeed,ast2400-kcs-bmc"; -+ interrupts = <8>; -+ kcs_chan = <4>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; -+ status = "disabled"; -+ }; -+ - lpc_ctrl: lpc-ctrl@0 { - compatible = "aspeed,ast2400-lpc-ctrl"; - reg = <0x0 0x80>; -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index 18d2a465c0ed..751a8f0316d6 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -134,7 +134,7 @@ - }; - - vic: interrupt-controller@1e6c0080 { -- compatible = "aspeed,ast2400-vic"; -+ compatible = "aspeed,ast2500-vic"; - interrupt-controller; - #interrupt-cells = <1>; - valid-sources = <0xfefff7ff 0x0807ffff>; -@@ -439,18 +439,21 @@ - compatible = "aspeed,ast2500-kcs-bmc"; - interrupts = <8>; - kcs_chan = <1>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - kcs2: kcs2@0 { - compatible = "aspeed,ast2500-kcs-bmc"; - interrupts = <8>; - kcs_chan = <2>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - kcs3: kcs3@0 { - compatible = "aspeed,ast2500-kcs-bmc"; - interrupts = <8>; - kcs_chan = <3>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - }; -@@ -468,6 +471,7 @@ - compatible = "aspeed,ast2500-kcs-bmc"; - interrupts = <8>; - kcs_chan = <4>; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 4035d7bd647e..0e35c4598df5 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -463,18 +463,23 @@ - kcs1: kcs1@0 { - compatible = "aspeed,ast2600-kcs-bmc"; - interrupts = ; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - kcs_chan = <1>; - status = "disabled"; - }; -+ - kcs2: kcs2@0 { - compatible = "aspeed,ast2600-kcs-bmc"; - interrupts = ; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - kcs_chan = <2>; - status = "disabled"; - }; -+ - kcs3: kcs3@0 { - compatible = "aspeed,ast2600-kcs-bmc"; - interrupts = ; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - kcs_chan = <3>; - status = "disabled"; - }; -@@ -492,6 +497,7 @@ - kcs4: kcs4@0 { - compatible = "aspeed,ast2600-kcs-bmc"; - interrupts = ; -+ clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - kcs_chan = <4>; - status = "disabled"; - }; -diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c -index a0a8bb89c9b3..94cfb879f520 100644 ---- a/drivers/char/ipmi/kcs_bmc_aspeed.c -+++ b/drivers/char/ipmi/kcs_bmc_aspeed.c -@@ -1,11 +1,10 @@ - // SPDX-License-Identifier: GPL-2.0 --/* -- * Copyright (c) 2015-2018, Intel Corporation. -- */ -+// Copyright (c) 2015-2019, Intel Corporation. - - #define pr_fmt(fmt) "aspeed-kcs-bmc: " fmt - - #include -+#include - #include - #include - #include -@@ -63,6 +62,7 @@ - - struct aspeed_kcs_bmc { - struct regmap *map; -+ struct clk *clk; - }; - - -@@ -264,36 +264,59 @@ static int aspeed_kcs_probe(struct platform_device *pdev) - return -ENODEV; - } - -+ priv->clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(priv->clk)) { -+ rc = PTR_ERR(priv->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; -+ } -+ rc = clk_prepare_enable(priv->clk); -+ if (rc) { -+ dev_err(dev, "couldn't enable clock\n"); -+ return rc; -+ } -+ - kcs_bmc->ioreg = ast_kcs_bmc_ioregs[chan - 1]; - kcs_bmc->io_inputb = aspeed_kcs_inb; - kcs_bmc->io_outputb = aspeed_kcs_outb; - - dev_set_drvdata(dev, kcs_bmc); - -- aspeed_kcs_set_address(kcs_bmc, addr); -- aspeed_kcs_enable_channel(kcs_bmc, true); - rc = aspeed_kcs_config_irq(kcs_bmc, pdev); - if (rc) -- return rc; -+ goto err; - - rc = misc_register(&kcs_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register device\n"); -- return rc; -+ goto err; - } - -+ aspeed_kcs_set_address(kcs_bmc, addr); -+ aspeed_kcs_enable_channel(kcs_bmc, true); -+ - pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n", - chan, addr, - kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); - - return 0; -+ -+err: -+ aspeed_kcs_enable_channel(kcs_bmc, false); -+ clk_disable_unprepare(priv->clk); -+ -+ return rc; - } - - static int aspeed_kcs_remove(struct platform_device *pdev) - { - struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); -+ struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); - - misc_deregister(&kcs_bmc->miscdev); -+ aspeed_kcs_enable_channel(kcs_bmc, false); -+ clk_disable_unprepare(priv->clk); - - return 0; - } --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch deleted file mode 100644 index 8e9c793ba..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 5473931df3348b7284c16fac3e7d336c9d0c4294 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 13 Mar 2019 15:57:08 -0700 -Subject: [PATCH] misc: Block error printing on probe defer case in Aspeed LPC - ctrl - -This commit adds a checking code when it gets -EPROBE_DEFER while -getting a clock resource. In this case it doesn't need to print -out an error message because the probing will be re-visited. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/soc/aspeed/aspeed-lpc-ctrl.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c -index f4ac14c40518..432128b8db87 100644 ---- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c -+++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c -@@ -265,8 +265,10 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) - - lpc_ctrl->clk = devm_clk_get(dev, NULL); - if (IS_ERR(lpc_ctrl->clk)) { -- dev_err(dev, "couldn't get clock\n"); -- return PTR_ERR(lpc_ctrl->clk); -+ rc = PTR_ERR(lpc_ctrl->clk); -+ if (rc != -EPROBE_DEFER) -+ dev_err(dev, "couldn't get clock\n"); -+ return rc; - } - rc = clk_prepare_enable(lpc_ctrl->clk); - if (rc) { -@@ -288,6 +290,7 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) - - err: - clk_disable_unprepare(lpc_ctrl->clk); -+ - return rc; - } - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch deleted file mode 100644 index 4a87f2d76..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 5b9ec5081492b461710cb82e7ecc93fd3af8ad34 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Mon, 18 Mar 2019 14:06:36 -0700 -Subject: [PATCH] Suppress excessive HID gadget error logs - -HID events can be sent even when the host disconnects the HID -device according to the current graphic mode. For an example, if -KVM mouse events are sent when the host is in text mode, queueing -of end point messages will be dropped with this message: - -configfs-gadget gadget: usb_ep_queue error on int endpoint -108 - -This case is very usual case in BMC since BMC can control power -status of the host, so this commit suppress the error printing outs -with making HID gadget driver drop events quietly in the case. - -This should be a downstream only customization. Do not upstream it. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/usb/gadget/function/f_hid.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c -index f3816a5c861e..c96c0f6f1df0 100644 ---- a/drivers/usb/gadget/function/f_hid.c -+++ b/drivers/usb/gadget/function/f_hid.c -@@ -320,7 +320,7 @@ static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req) - struct f_hidg *hidg = (struct f_hidg *)ep->driver_data; - unsigned long flags; - -- if (req->status != 0) { -+ if (req->status != 0 && req->status != -ESHUTDOWN) { - ERROR(hidg->func.config->cdev, - "End Point Request ERROR: %d\n", req->status); - } -@@ -395,8 +395,10 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, - - status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC); - if (status < 0) { -- ERROR(hidg->func.config->cdev, -- "usb_ep_queue error on int endpoint %zd\n", status); -+ if (status != -ESHUTDOWN) -+ ERROR(hidg->func.config->cdev, -+ "usb_ep_queue error on int endpoint %zd\n", -+ status); - goto release_write_pending; - } else { - status = count; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch deleted file mode 100644 index db94b13fd..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0051-Add-AST2500-JTAG-device.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 79d407327558f27a7df9d04b1d66cbe63129b622 Mon Sep 17 00:00:00 2001 -From: "Hunt, Bryan" -Date: Mon, 6 May 2019 10:02:14 -0700 -Subject: [PATCH] Add AST2500 JTAG device - -Adding aspeed jtag device - -Signed-off-by: Hunt, Bryan ---- - arch/arm/boot/dts/aspeed-g5.dtsi | 9 +++++++++ - arch/arm/boot/dts/aspeed-g6.dtsi | 20 ++++++++++++++++++++ - 2 files changed, 29 insertions(+) - -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index f5c25dab5337..5999cd5e0f2e 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -438,6 +438,15 @@ - pinctrl-0 = <&pinctrl_espi_default>; - }; - -+ jtag: jtag@1e6e4000 { -+ compatible = "aspeed,ast2500-jtag"; -+ reg = <0x1e6e4000 0x1c>; -+ clocks = <&syscon ASPEED_CLK_APB>; -+ resets = <&syscon ASPEED_RESET_JTAG_MASTER>; -+ interrupts = <43>; -+ status = "disabled"; -+ }; -+ - lpc: lpc@1e789000 { - compatible = "aspeed,ast2500-lpc", "simple-mfd"; - reg = <0x1e789000 0x1000>; -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 09f50afea11b..4d8b561fe582 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -367,6 +367,26 @@ - status = "disabled"; - }; - -+ jtag0: jtag@1e6e4000 { -+ compatible = "aspeed,ast2600-jtag"; -+ reg = <0x1e6e4000 0x40>; -+ clocks = <&syscon ASPEED_CLK_APB1>; -+ resets = <&syscon ASPEED_RESET_JTAG_MASTER>; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ -+ jtag1: jtag@1e6e4100 { -+ compatible = "aspeed,ast2600-jtag"; -+ reg = <0x1e6e4100 0x40>; -+ clocks = <&syscon ASPEED_CLK_APB1>; -+ resets = <&syscon ASPEED_RESET_JTAG_MASTER2>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_jtagm_default>; -+ status = "disabled"; -+ }; -+ - adc: adc@1e6e9000 { - compatible = "aspeed,ast2500-adc"; - reg = <0x1e6e9000 0x100>; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch deleted file mode 100644 index 484c576b9..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0052-drivers-jtag-Add-JTAG-core-driver.patch +++ /dev/null @@ -1,920 +0,0 @@ -From ea6fa8fd6e36c776d560b4f69d1ede4a3bbe5f6b Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Fri, 7 Jun 2019 07:37:39 -0800 -Subject: [PATCH v29 1/6] drivers: jtag: Add JTAG core driver - -JTAG class driver provide infrastructure to support hardware/software -JTAG platform drivers. It provide user layer API interface for flashing -and debugging external devices which equipped with JTAG interface -using standard transactions. - -Driver exposes set of IOCTL to user space for: -- XFER: - SIR (Scan Instruction Register, IEEE 1149.1 Data Register scan); - SDR (Scan Data Register, IEEE 1149.1 Instruction Register scan); -- GIOCSTATUS read the current TAPC state of the JTAG controller -- SIOCSTATE Forces the JTAG TAPC to go into a particular state. -- SIOCFREQ/GIOCFREQ for setting and reading JTAG frequency. -- IOCBITBANG for low level control of JTAG signals. - -Driver core provides set of internal APIs for allocation and -registration: -- jtag_register; -- jtag_unregister; -- jtag_alloc; -- jtag_free; - -Platform driver on registration with jtag-core creates the next -entry in dev folder: -/dev/jtagX - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Jiri Pirko -Signed-off-by: Corona, Ernesto -Acked-by: Philippe Ombredanne -Cc: Vadim Pasternak -Cc: Masahiro Yamada -Cc: Paul Burton -Cc: Thomas Gleixner -Cc: Greg Kroah-Hartman -Cc: Arnd Bergmann -Cc: Boris Brezillon -Cc: Randy Dunlap -Cc: Johan Hovold -Cc: Jens Axboe -Cc: Joel Stanley -Cc: Palmer Dabbelt -Cc: Kees Cook -Cc: Steven A Filary -Cc: Bryan Hunt ---- -v28->v29 -Comments pointed by Steven Filary -- Expand bitbang function to accept multiples bitbang operations within a - single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS - values and it is expected that driver fills TDO fields with its - corresponding output value for every transaction. -- Always setup JTAG controller to master mode but disable JTAG output when - the driver is not in use to allow other HW to own the JTAG bus. Remove SCU - register accesses. This register controls the JTAG controller mode - (master/slave). -- Fix static analysis issues -- Add support for multichain. Set tap state and xfer operations now include - two tap state arguments: current state and end state. - -v27->v28 -Comments pointed by Steven Filary -- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC - end states in SW mode using a lookup table to navigate across states. -- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER). -- Support for switching JTAG controller mode between slave and master - mode. -- Setup JTAG controller mode to master only when the driver is opened, - letting - other HW to own the JTAG bus when it isn't in use. -- Include JTAG bit bang IOCTL for low level JTAG control usage - (JTAG_IOCBITBANG). - -v24->v25 -Comments pointed by Greg KH -- set values to enums in jtag.h - -v23->v24 -Notifications from kbuild test robot -- Add include types.h header to jtag.h -- remove unecessary jtag_release - -v22->v23 -Comments pointed by Greg KH -- remove restriction of allocated JTAG devs- -- add validation fo idle values -- remove unnecessary blank line -- change retcode for xfer -- remove unecessary jtag_release callback -- remove unecessary defined fron jtag.h -- align in one line define JTAG_IOCRUNTEST - -v21->v22 -Comments pointed by Andy Shevchenko -- Fix 0x0f -> 0x0F in ioctl-number.txt -- Add description to #define MAX_JTAG_NAME_LEN -- Remove unnecessary entry *dev from struct jtag -- Remove redundant parens -- Described mandatory callbacks and removed unnecessary -- Set JTAG_MAX_XFER_DATA_LEN to power of 2 -- rework driver alloc/register to devm_ variant -- increasing line length up to 84 in order to improve readability. - -Comments pointed by Randy Dunlap -- fix spell in ABI doccumentation - -v20->v21 - Comments pointed by Randy Dunlap - - Fix JTAG dirver help in Kconfig - -v19->v20 -Comments pointed by Randy Dunlap -- Fix JTAG dirver help in Kconfig - -Notifications from kbuild test robot -- fix incompatible type casts - -v18->v19 -Comments pointed by Julia Cartwright -- Fix memory leak on jtag_alloc exit - -v17->v18 -Comments pointed by Julia Cartwright -- Change to return -EOPNOTSUPP in case of error in JTAG_GIOCFREQ -- Add ops callbacks check to jtag_alloc -- Add err check for copy_to_user -- Move the kfree() above the if (err) in JTAG_IOCXFER -- remove unnecessary check for error after put_user -- add padding to struct jtag_xfer - -v16->v17 -Comments pointed by Julia Cartwright -- Fix memory allocation on jtag alloc -- Move out unnecessary form lock on jtag open -- Rework jtag register behavior - -v15->v16 -Comments pointed by Florian Fainelli -- move check jtag->ops->* in ioctl before get_user() -- change error type -EINVAL --> -EBUSY on open already opened jtag -- remove unnecessary ARCH_DMA_MINALIGN flag from kzalloc -- remove define ARCH_DMA_MINALIGN - -v14->v15 -v13->v14 -Comments pointed by Philippe Ombredanne -- Change style of head block comment from /**/ to // - -v12->v13 -Comments pointed by Philippe Ombredanne -- Change jtag.c licence type to - SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note - and reorder line with license in description - -v11->v12 -Comments pointed by Greg KH -- Change jtag.h licence type to - SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note - and reorder line with license in description - -Comments pointed by Chip Bilbrey -- Remove Apeed reference from uapi jtag.h header -- Remove access mode from xfer and idle transactions -- Add new ioctl JTAG_SIOCMODE for set hw mode -- Add single open per device blocking - -v10->v11 -Notifications from kbuild test robot -- Add include types.h header to jtag.h -- fix incompatible type of xfer callback -- remove rdundant class defination -- Fix return order in case of xfer error - -V9->v10 -Comments pointed by Greg KH -- remove unnecessary alignment for pirv data -- move jtag_copy_to_user and jtag_copy_from_user code just to ioctl -- move int jtag_run_test_idle_op and jtag_xfer_op code - just to ioctl -- change return error codes to more applicable -- add missing error checks -- fix error check order in ioctl -- remove unnecessary blank lines -- add param validation to ioctl -- remove compat_ioctl -- remove only one open per JTAG port blocking. - User will care about this. -- Fix idr memory leak on jtag_exit -- change cdev device type to misc - -V8->v9 -Comments pointed by Arnd Bergmann -- use get_user() instead of __get_user(). -- change jtag->open type from int to atomic_t -- remove spinlock on jtg_open -- remove mutex on jtag_register -- add unregister_chrdev_region on jtag_init err -- add unregister_chrdev_region on jtag_exit -- remove unnecessary pointer casts -- add *data parameter to xfer function prototype - -v7->v8 -Comments pointed by Moritz Fischer -- Fix misspelling s/friver/driver - -v6->v7 -Notifications from kbuild test robot -- Remove include asm/types.h from jtag.h -- Add include to jtag.c - -v5->v6 -v4->v5 - -v3->v4 -Comments pointed by Arnd Bergmann -- change transaction pointer tdio type to __u64 -- change internal status type from enum to __u32 -- reorder jtag_xfer members to avoid the implied padding -- add __packed attribute to jtag_xfer and jtag_run_test_idle - -v2->v3 -Notifications from kbuild test robot -- Change include path to in jtag.h - -v1->v2 -Comments pointed by Greg KH -- Change license type from GPLv2/BSD to GPLv2 -- Change type of variables which crossed user/kernel to __type -- Remove "default n" from Kconfig - -Comments pointed by Andrew Lunn -- Change list_add_tail in jtag_unregister to list_del - -Comments pointed by Neil Armstrong -- Add SPDX-License-Identifier instead of license text - -Comments pointed by Arnd Bergmann -- Change __copy_to_user to memdup_user -- Change __put_user to put_user -- Change type of variables to __type for compatible 32 and 64-bit systems -- Add check for maximum xfer data size -- Change lookup data mechanism to get jtag data from inode -- Add .compat_ioctl to file ops -- Add mem alignment for jtag priv data - -Comments pointed by Tobias Klauser -- Change function names to avoid match with variable types -- Fix description for jtag_ru_test_idle in uapi jtag.h -- Fix misprints IDEL/IDLE, trough/through ---- - drivers/Kconfig | 1 + - drivers/Makefile | 1 + - drivers/jtag/Kconfig | 17 +++ - drivers/jtag/Makefile | 1 + - drivers/jtag/jtag.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/jtag.h | 47 +++++++ - include/uapi/linux/jtag.h | 214 +++++++++++++++++++++++++++++++ - 7 files changed, 602 insertions(+) - create mode 100644 drivers/jtag/Kconfig - create mode 100644 drivers/jtag/Makefile - create mode 100644 drivers/jtag/jtag.c - create mode 100644 include/linux/jtag.h - create mode 100644 include/uapi/linux/jtag.h - -diff --git a/drivers/Kconfig b/drivers/Kconfig -index 4322efa37732..e5e4fe21b5d9 100644 ---- a/drivers/Kconfig -+++ b/drivers/Kconfig -@@ -230,4 +230,5 @@ source "drivers/counter/Kconfig" - - source "drivers/peci/Kconfig" - -+source "drivers/jtag/Kconfig" - endmenu -diff --git a/drivers/Makefile b/drivers/Makefile -index 82f78cfedf69..297047d4ed9b 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -187,3 +187,4 @@ obj-$(CONFIG_GNSS) += gnss/ - obj-$(CONFIG_INTERCONNECT) += interconnect/ - obj-$(CONFIG_COUNTER) += counter/ - obj-$(CONFIG_PECI) += peci/ -+obj-$(CONFIG_JTAG_ASPEED) += jtag/ -diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig -new file mode 100644 -index 000000000000..47771fcd3c5b ---- /dev/null -+++ b/drivers/jtag/Kconfig -@@ -0,0 +1,17 @@ -+menuconfig JTAG -+ tristate "JTAG support" -+ help -+ This provides basic core functionality support for JTAG class devices. -+ Hardware that is equipped with a JTAG microcontroller can be -+ supported by using this driver's interfaces. -+ This driver exposes a set of IOCTLs to the user space for -+ the following commands: -+ SDR: Performs an IEEE 1149.1 Data Register scan -+ SIR: Performs an IEEE 1149.1 Instruction Register scan. -+ RUNTEST: Forces the IEEE 1149.1 bus to a run state for a specified -+ number of clocks or a specified time period. -+ -+ If you want this support, you should say Y here. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called jtag. -diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile -new file mode 100644 -index 000000000000..af374939a9e6 ---- /dev/null -+++ b/drivers/jtag/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_JTAG) += jtag.o -diff --git a/drivers/jtag/jtag.c b/drivers/jtag/jtag.c -new file mode 100644 -index 000000000000..39a4d88a9c21 ---- /dev/null -+++ b/drivers/jtag/jtag.c -@@ -0,0 +1,321 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+// Copyright (c) 2018 Mellanox Technologies. All rights reserved. -+// Copyright (c) 2018 Oleksandr Shamray -+// Copyright (c) 2019 Intel Corporation -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct jtag { -+ struct miscdevice miscdev; -+ const struct jtag_ops *ops; -+ int id; -+ unsigned long priv[0]; -+}; -+ -+static DEFINE_IDA(jtag_ida); -+ -+void *jtag_priv(struct jtag *jtag) -+{ -+ return jtag->priv; -+} -+EXPORT_SYMBOL_GPL(jtag_priv); -+ -+static long jtag_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct jtag *jtag = file->private_data; -+ struct jtag_tap_state tapstate; -+ struct jtag_xfer xfer; -+ struct bitbang_packet bitbang; -+ struct tck_bitbang *bitbang_data; -+ struct jtag_mode mode; -+ u8 *xfer_data; -+ u32 data_size; -+ u32 value; -+ int err; -+ -+ if (!arg) -+ return -EINVAL; -+ -+ switch (cmd) { -+ case JTAG_GIOCFREQ: -+ if (!jtag->ops->freq_get) -+ return -EOPNOTSUPP; -+ -+ err = jtag->ops->freq_get(jtag, &value); -+ if (err) -+ break; -+ -+ if (put_user(value, (__u32 __user *)arg)) -+ err = -EFAULT; -+ break; -+ -+ case JTAG_SIOCFREQ: -+ if (!jtag->ops->freq_set) -+ return -EOPNOTSUPP; -+ -+ if (get_user(value, (__u32 __user *)arg)) -+ return -EFAULT; -+ if (value == 0) -+ return -EINVAL; -+ -+ err = jtag->ops->freq_set(jtag, value); -+ break; -+ -+ case JTAG_SIOCSTATE: -+ if (copy_from_user(&tapstate, (const void __user *)arg, -+ sizeof(struct jtag_tap_state))) -+ return -EFAULT; -+ -+ if (tapstate.from > JTAG_STATE_CURRENT) -+ return -EINVAL; -+ -+ if (tapstate.endstate > JTAG_STATE_CURRENT) -+ return -EINVAL; -+ -+ if (tapstate.reset > JTAG_FORCE_RESET) -+ return -EINVAL; -+ -+ err = jtag->ops->status_set(jtag, &tapstate); -+ break; -+ -+ case JTAG_IOCXFER: -+ if (copy_from_user(&xfer, (const void __user *)arg, -+ sizeof(struct jtag_xfer))) -+ return -EFAULT; -+ -+ if (xfer.length >= JTAG_MAX_XFER_DATA_LEN) -+ return -EINVAL; -+ -+ if (xfer.type > JTAG_SDR_XFER) -+ return -EINVAL; -+ -+ if (xfer.direction > JTAG_READ_WRITE_XFER) -+ return -EINVAL; -+ -+ if (xfer.from > JTAG_STATE_CURRENT) -+ return -EINVAL; -+ -+ if (xfer.endstate > JTAG_STATE_CURRENT) -+ return -EINVAL; -+ -+ data_size = DIV_ROUND_UP(xfer.length, BITS_PER_BYTE); -+ xfer_data = memdup_user(u64_to_user_ptr(xfer.tdio), data_size); -+ if (IS_ERR(xfer_data)) -+ return -EFAULT; -+ -+ err = jtag->ops->xfer(jtag, &xfer, xfer_data); -+ if (err) { -+ kfree(xfer_data); -+ return err; -+ } -+ -+ err = copy_to_user(u64_to_user_ptr(xfer.tdio), -+ (void *)xfer_data, data_size); -+ kfree(xfer_data); -+ if (err) -+ return -EFAULT; -+ -+ if (copy_to_user((void __user *)arg, (void *)&xfer, -+ sizeof(struct jtag_xfer))) -+ return -EFAULT; -+ break; -+ -+ case JTAG_GIOCSTATUS: -+ err = jtag->ops->status_get(jtag, &value); -+ if (err) -+ break; -+ -+ err = put_user(value, (__u32 __user *)arg); -+ break; -+ case JTAG_IOCBITBANG: -+ if (copy_from_user(&bitbang, (const void __user *)arg, -+ sizeof(struct bitbang_packet))) -+ return -EFAULT; -+ -+ if (bitbang.length >= JTAG_MAX_XFER_DATA_LEN) -+ return -EINVAL; -+ -+ data_size = bitbang.length * sizeof(struct tck_bitbang); -+ bitbang_data = memdup_user((void __user *)bitbang.data, -+ data_size); -+ if (IS_ERR(bitbang_data)) -+ return -EFAULT; -+ -+ err = jtag->ops->bitbang(jtag, &bitbang, bitbang_data); -+ if (err) { -+ kfree(bitbang_data); -+ return err; -+ } -+ err = copy_to_user((void __user *)bitbang.data, -+ (void *)bitbang_data, data_size); -+ kfree(bitbang_data); -+ if (err) -+ return -EFAULT; -+ break; -+ case JTAG_SIOCMODE: -+ if (!jtag->ops->mode_set) -+ return -EOPNOTSUPP; -+ -+ if (copy_from_user(&mode, (const void __user *)arg, -+ sizeof(struct jtag_mode))) -+ return -EFAULT; -+ -+ err = jtag->ops->mode_set(jtag, &mode); -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ return err; -+} -+ -+static int jtag_open(struct inode *inode, struct file *file) -+{ -+ struct jtag *jtag = container_of(file->private_data, -+ struct jtag, -+ miscdev); -+ -+ file->private_data = jtag; -+ if (jtag->ops->enable(jtag)) -+ return -EBUSY; -+ return nonseekable_open(inode, file); -+} -+ -+static int jtag_release(struct inode *inode, struct file *file) -+{ -+ struct jtag *jtag = file->private_data; -+ -+ if (jtag->ops->disable(jtag)) -+ return -EBUSY; -+ return 0; -+} -+ -+static const struct file_operations jtag_fops = { -+ .owner = THIS_MODULE, -+ .open = jtag_open, -+ .llseek = noop_llseek, -+ .unlocked_ioctl = jtag_ioctl, -+ .release = jtag_release, -+}; -+ -+struct jtag *jtag_alloc(struct device *host, size_t priv_size, -+ const struct jtag_ops *ops) -+{ -+ struct jtag *jtag; -+ -+ if (!host) -+ return NULL; -+ -+ if (!ops) -+ return NULL; -+ -+ if (!ops->status_set || !ops->status_get || !ops->xfer) -+ return NULL; -+ -+ jtag = kzalloc(sizeof(*jtag) + priv_size, GFP_KERNEL); -+ if (!jtag) -+ return NULL; -+ -+ jtag->ops = ops; -+ jtag->miscdev.parent = host; -+ -+ return jtag; -+} -+EXPORT_SYMBOL_GPL(jtag_alloc); -+ -+void jtag_free(struct jtag *jtag) -+{ -+ kfree(jtag); -+} -+EXPORT_SYMBOL_GPL(jtag_free); -+ -+static int jtag_register(struct jtag *jtag) -+{ -+ struct device *dev = jtag->miscdev.parent; -+ int err; -+ int id; -+ -+ if (!dev) -+ return -ENODEV; -+ -+ id = ida_simple_get(&jtag_ida, 0, 0, GFP_KERNEL); -+ if (id < 0) -+ return id; -+ -+ jtag->id = id; -+ -+ jtag->miscdev.fops = &jtag_fops; -+ jtag->miscdev.minor = MISC_DYNAMIC_MINOR; -+ jtag->miscdev.name = kasprintf(GFP_KERNEL, "jtag%d", id); -+ if (!jtag->miscdev.name) { -+ err = -ENOMEM; -+ goto err_jtag_alloc; -+ } -+ -+ err = misc_register(&jtag->miscdev); -+ if (err) { -+ dev_err(jtag->miscdev.parent, "Unable to register device\n"); -+ goto err_jtag_name; -+ } -+ return 0; -+ -+err_jtag_name: -+ kfree(jtag->miscdev.name); -+err_jtag_alloc: -+ ida_simple_remove(&jtag_ida, id); -+ return err; -+} -+ -+static void jtag_unregister(struct jtag *jtag) -+{ -+ misc_deregister(&jtag->miscdev); -+ kfree(jtag->miscdev.name); -+ ida_simple_remove(&jtag_ida, jtag->id); -+} -+ -+static void devm_jtag_unregister(struct device *dev, void *res) -+{ -+ jtag_unregister(*(struct jtag **)res); -+} -+ -+int devm_jtag_register(struct device *dev, struct jtag *jtag) -+{ -+ struct jtag **ptr; -+ int ret; -+ -+ ptr = devres_alloc(devm_jtag_unregister, sizeof(struct jtag *), -+ GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ ret = jtag_register(jtag); -+ if (!ret) { -+ *ptr = jtag; -+ devres_add(dev, ptr); -+ } else { -+ devres_free(ptr); -+ } -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_jtag_register); -+ -+static void __exit jtag_exit(void) -+{ -+ ida_destroy(&jtag_ida); -+} -+ -+module_exit(jtag_exit); -+ -+MODULE_AUTHOR("Oleksandr Shamray "); -+MODULE_DESCRIPTION("Generic jtag support"); -+MODULE_LICENSE("GPL v2"); -diff --git a/include/linux/jtag.h b/include/linux/jtag.h -new file mode 100644 -index 000000000000..fab12dc4fc5e ---- /dev/null -+++ b/include/linux/jtag.h -@@ -0,0 +1,47 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */ -+/* Copyright (c) 2018 Oleksandr Shamray */ -+/* Copyright (c) 2019 Intel Corporation */ -+ -+#ifndef __LINUX_JTAG_H -+#define __LINUX_JTAG_H -+ -+#include -+#include -+ -+#define JTAG_MAX_XFER_DATA_LEN 65535 -+ -+struct jtag; -+/** -+ * struct jtag_ops - callbacks for JTAG control functions: -+ * -+ * @freq_get: get frequency function. Filled by dev driver -+ * @freq_set: set frequency function. Filled by dev driver -+ * @status_get: get JTAG TAPC state function. Mandatory, Filled by dev driver -+ * @status_set: set JTAG TAPC state function. Mandatory, Filled by dev driver -+ * @xfer: send JTAG xfer function. Mandatory func. Filled by dev driver -+ * @mode_set: set specific work mode for JTAG. Filled by dev driver -+ * @bitbang: set low level bitbang operations. Filled by dev driver -+ * @enable: enables JTAG interface in master mode. Filled by dev driver -+ * @disable: disables JTAG interface master mode. Filled by dev driver -+ */ -+struct jtag_ops { -+ int (*freq_get)(struct jtag *jtag, u32 *freq); -+ int (*freq_set)(struct jtag *jtag, u32 freq); -+ int (*status_get)(struct jtag *jtag, u32 *state); -+ int (*status_set)(struct jtag *jtag, struct jtag_tap_state *endst); -+ int (*xfer)(struct jtag *jtag, struct jtag_xfer *xfer, u8 *xfer_data); -+ int (*mode_set)(struct jtag *jtag, struct jtag_mode *jtag_mode); -+ int (*bitbang)(struct jtag *jtag, struct bitbang_packet *bitbang, -+ struct tck_bitbang *bitbang_data); -+ int (*enable)(struct jtag *jtag); -+ int (*disable)(struct jtag *jtag); -+}; -+ -+void *jtag_priv(struct jtag *jtag); -+int devm_jtag_register(struct device *dev, struct jtag *jtag); -+struct jtag *jtag_alloc(struct device *host, size_t priv_size, -+ const struct jtag_ops *ops); -+void jtag_free(struct jtag *jtag); -+ -+#endif /* __LINUX_JTAG_H */ -diff --git a/include/uapi/linux/jtag.h b/include/uapi/linux/jtag.h -new file mode 100644 -index 000000000000..315e59577a17 ---- /dev/null -+++ b/include/uapi/linux/jtag.h -@@ -0,0 +1,214 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */ -+/* Copyright (c) 2018 Oleksandr Shamray */ -+/* Copyright (c) 2019 Intel Corporation */ -+ -+#ifndef __UAPI_LINUX_JTAG_H -+#define __UAPI_LINUX_JTAG_H -+ -+/* -+ * JTAG_XFER_MODE: JTAG transfer mode. Used to set JTAG controller transfer mode -+ * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_XFER_MODE 0 -+/* -+ * JTAG_CONTROL_MODE: JTAG controller mode. Used to set JTAG controller mode -+ * This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_CONTROL_MODE 1 -+/* -+ * JTAG_MASTER_OUTPUT_DISABLE: JTAG master mode output disable, it is used to -+ * enable other devices to own the JTAG bus. -+ * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_MASTER_OUTPUT_DISABLE 0 -+/* -+ * JTAG_MASTER_MODE: JTAG master mode. Used to set JTAG controller master mode -+ * This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_MASTER_MODE 1 -+/* -+ * JTAG_XFER_HW_MODE: JTAG hardware mode. Used to set HW drived or bitbang -+ * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_XFER_HW_MODE 1 -+/* -+ * JTAG_XFER_SW_MODE: JTAG software mode. Used to set SW drived or bitbang -+ * mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE -+ */ -+#define JTAG_XFER_SW_MODE 0 -+ -+/** -+ * enum jtag_tapstate: -+ * -+ * @JTAG_STATE_TLRESET: JTAG state machine Test Logic Reset state -+ * @JTAG_STATE_IDLE: JTAG state machine IDLE state -+ * @JTAG_STATE_SELECTDR: JTAG state machine SELECT_DR state -+ * @JTAG_STATE_CAPTUREDR: JTAG state machine CAPTURE_DR state -+ * @JTAG_STATE_SHIFTDR: JTAG state machine SHIFT_DR state -+ * @JTAG_STATE_EXIT1DR: JTAG state machine EXIT-1 DR state -+ * @JTAG_STATE_PAUSEDR: JTAG state machine PAUSE_DR state -+ * @JTAG_STATE_EXIT2DR: JTAG state machine EXIT-2 DR state -+ * @JTAG_STATE_UPDATEDR: JTAG state machine UPDATE DR state -+ * @JTAG_STATE_SELECTIR: JTAG state machine SELECT_IR state -+ * @JTAG_STATE_CAPTUREIR: JTAG state machine CAPTURE_IR state -+ * @JTAG_STATE_SHIFTIR: JTAG state machine SHIFT_IR state -+ * @JTAG_STATE_EXIT1IR: JTAG state machine EXIT-1 IR state -+ * @JTAG_STATE_PAUSEIR: JTAG state machine PAUSE_IR state -+ * @JTAG_STATE_EXIT2IR: JTAG state machine EXIT-2 IR state -+ * @JTAG_STATE_UPDATEIR: JTAG state machine UPDATE IR state -+ * @JTAG_STATE_CURRENT: JTAG current state, saved by driver -+ */ -+enum jtag_tapstate { -+ JTAG_STATE_TLRESET, -+ JTAG_STATE_IDLE, -+ JTAG_STATE_SELECTDR, -+ JTAG_STATE_CAPTUREDR, -+ JTAG_STATE_SHIFTDR, -+ JTAG_STATE_EXIT1DR, -+ JTAG_STATE_PAUSEDR, -+ JTAG_STATE_EXIT2DR, -+ JTAG_STATE_UPDATEDR, -+ JTAG_STATE_SELECTIR, -+ JTAG_STATE_CAPTUREIR, -+ JTAG_STATE_SHIFTIR, -+ JTAG_STATE_EXIT1IR, -+ JTAG_STATE_PAUSEIR, -+ JTAG_STATE_EXIT2IR, -+ JTAG_STATE_UPDATEIR, -+ JTAG_STATE_CURRENT -+}; -+ -+/** -+ * enum jtag_reset: -+ * -+ * @JTAG_NO_RESET: JTAG run TAP from current state -+ * @JTAG_FORCE_RESET: JTAG force TAP to reset state -+ */ -+enum jtag_reset { -+ JTAG_NO_RESET = 0, -+ JTAG_FORCE_RESET = 1, -+}; -+ -+/** -+ * enum jtag_xfer_type: -+ * -+ * @JTAG_SIR_XFER: SIR transfer -+ * @JTAG_SDR_XFER: SDR transfer -+ */ -+enum jtag_xfer_type { -+ JTAG_SIR_XFER = 0, -+ JTAG_SDR_XFER = 1, -+}; -+ -+/** -+ * enum jtag_xfer_direction: -+ * -+ * @JTAG_READ_XFER: read transfer -+ * @JTAG_WRITE_XFER: write transfer -+ * @JTAG_READ_WRITE_XFER: read & write transfer -+ */ -+enum jtag_xfer_direction { -+ JTAG_READ_XFER = 1, -+ JTAG_WRITE_XFER = 2, -+ JTAG_READ_WRITE_XFER = 3, -+}; -+ -+/** -+ * struct jtag_tap_state - forces JTAG state machine to go into a TAPC -+ * state -+ * -+ * @reset: 0 - run IDLE/PAUSE from current state -+ * 1 - go through TEST_LOGIC/RESET state before IDLE/PAUSE -+ * @end: completion flag -+ * @tck: clock counter -+ * -+ * Structure provide interface to JTAG device for JTAG set state execution. -+ */ -+struct jtag_tap_state { -+ __u8 reset; -+ __u8 from; -+ __u8 endstate; -+ __u8 tck; -+}; -+ -+/** -+ * struct jtag_xfer - jtag xfer: -+ * -+ * @type: transfer type -+ * @direction: xfer direction -+ * @from: xfer current state -+ * @endstate: xfer end state -+ * @padding: xfer padding -+ * @length: xfer bits length -+ * @tdio : xfer data array -+ * -+ * Structure provide interface to JTAG device for JTAG SDR/SIR xfer execution. -+ */ -+struct jtag_xfer { -+ __u8 type; -+ __u8 direction; -+ __u8 from; -+ __u8 endstate; -+ __u8 padding; -+ __u32 length; -+ __u64 tdio; -+}; -+ -+/** -+ * struct bitbang_packet - jtag bitbang array packet: -+ * -+ * @data: JTAG Bitbang struct array pointer(input/output) -+ * @length: array size (input) -+ * -+ * Structure provide interface to JTAG device for JTAG bitbang bundle execution -+ */ -+struct bitbang_packet { -+ struct tck_bitbang *data; -+ __u32 length; -+} __attribute__((__packed__)); -+ -+/** -+ * struct jtag_bitbang - jtag bitbang: -+ * -+ * @tms: JTAG TMS -+ * @tdi: JTAG TDI (input) -+ * @tdo: JTAG TDO (output) -+ * -+ * Structure provide interface to JTAG device for JTAG bitbang execution. -+ */ -+struct tck_bitbang { -+ __u8 tms; -+ __u8 tdi; -+ __u8 tdo; -+} __attribute__((__packed__)); -+ -+/** -+ * struct jtag_mode - jtag mode: -+ * -+ * @feature: 0 - JTAG feature setting selector for JTAG controller HW/SW -+ * 1 - JTAG feature setting selector for controller bus master -+ * mode output (enable / disable). -+ * @mode: (0 - SW / 1 - HW) for JTAG_XFER_MODE feature(0) -+ * (0 - output disable / 1 - output enable) for JTAG_CONTROL_MODE -+ * feature(1) -+ * -+ * Structure provide configuration modes to JTAG device. -+ */ -+struct jtag_mode { -+ __u32 feature; -+ __u32 mode; -+}; -+ -+/* ioctl interface */ -+#define __JTAG_IOCTL_MAGIC 0xb2 -+ -+#define JTAG_SIOCSTATE _IOW(__JTAG_IOCTL_MAGIC, 0, struct jtag_tap_state) -+#define JTAG_SIOCFREQ _IOW(__JTAG_IOCTL_MAGIC, 1, unsigned int) -+#define JTAG_GIOCFREQ _IOR(__JTAG_IOCTL_MAGIC, 2, unsigned int) -+#define JTAG_IOCXFER _IOWR(__JTAG_IOCTL_MAGIC, 3, struct jtag_xfer) -+#define JTAG_GIOCSTATUS _IOWR(__JTAG_IOCTL_MAGIC, 4, enum jtag_tapstate) -+#define JTAG_SIOCMODE _IOW(__JTAG_IOCTL_MAGIC, 5, unsigned int) -+#define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int) -+ -+#endif /* __UAPI_LINUX_JTAG_H */ --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch deleted file mode 100644 index d29098459..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch +++ /dev/null @@ -1,1780 +0,0 @@ -From e01c562db28797e3b6be9030f1f52507115c6765 Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Thu, 9 Jul 2020 12:03:34 -0700 -Subject: [PATCH] Add Aspeed SoC 24xx and 25xx families JTAG - -Driver adds support of Aspeed 2400-2600 series SOC JTAG master controller. - -Driver implements the following jtag ops: -- freq_get; -- freq_set; -- status_get; -- status_set -- xfer; -- mode_set; -- bitbang; -- enable; -- disable; - -It has been tested on Mellanox system with BMC equipped with -Aspeed 2520 SoC for programming CPLD devices. - -It has also been tested on Intel system using Aspeed 25xx SoC -for JTAG communication. - -Tested on Intel system using Aspeed 26xx SoC for JTAG communication. - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Jiri Pirko -Signed-off-by: Corona, Ernesto -Acked-by: Arnd Bergmann -Acked-by: Philippe Ombredanne -Acked-by: Joel Stanley -Cc: Vadim Pasternak -Cc: Andrew Jeffery -Cc: Steven A Filary -Cc: Bryan Hunt ---- -v29->v30 -Comments pointed by Steven Filary -- Add Suport for 26xx series - Software mode - Hardware mode 1 (disabled by default) - Hardware mode 2 (enabled by default) up to 160 bit lenght transfers -- clang jtag-aspeed.c - -v28->v29 -Comments pointed by Steven Filary -- Expand bitbang function to accept multiples bitbang operations within a - single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS - values and it is expected that driver fills TDO fields with its - corresponding output value for every transaction. -- Always setup JTAG controller to master mode but disable JTAG output when - the driver is not in use to allow other HW to own the JTAG bus. Remove SCU - register accesses. This register controls the JTAG controller mode - (master/slave). -- Encansulate dev_dgb message into DEBUG_JTAG macros to improve driver's JTAG - performace. -- Add support for multichain. Set tap state and xfer operations now include - two tap state arguments: current state and end state. - -v27->v28 -Comments pointed by Steven Filary -- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC - end states in SW mode using a lookup table to navigate across states. -- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER). -- Support for switching JTAG controller mode between slave and master - mode. -- Setup JTAG controller mode to master only when the driver is opened, - letting other HW to own the JTAG bus when it isn't in use. -- Include JTAG bit bang IOCTL for low level JTAG control usage - (JTAG_IOCBITBANG). -- Add debug traces. -- Add support for register polling (default) due it is 3 times faster than - interrupt mode. Define USE_INTERRUPTS macro to enable interrupt usage. -- Remove unnecessary delays for aspeed_jtag_status_set function. It makes - SW mode 4 times faster. -- Clean data buffer on aspeed_jtag_xfer_sw before tdo writes to avoid data - output corruption for read operations in SW mode. -- Correct register settings for HW mode transfer operations. -- Propagate ret codes all the way from low level functions up to - JTAG_IOCXFER call. -- Support for partitioned transfers. Single JTAG transfer through - multiples JTAG_IOCXFER calls. Now end transmission(scan_end) also - evaluates transfer end state. - -v26->v27 -Changes made by Oleksandr Shamray -- change aspeed_jtag_sw_delay to udelay function in bit-bang operation - -v25->v26 -v24->v25 -Comments pointed by Greg KH -- reduced debug printouts - -v23->v24 -v22->v23 -v21->v22 -Comments pointed by Andy Shevchenko -- rearrange ASPEED register defines -- simplified JTAG divider calculation formula -- change delay function in bit-bang operation -- add helper functions for TAP states switching -- remove unnecessary comments -- remove redundant debug messages -- make dines for repetative register bit sets -- fixed indentation -- change checks from negative to positive -- add error check for clk_prepare_enable -- rework driver alloc/register to devm_ variant -- Increasing line length up to 85 in order to improve readability - -v20->v21 -v19->v20 -Notifications from kbuild test robot -- add static declaration to 'aspeed_jtag_init' and - 'aspeed_jtag_deinit' functions - -v18->v19 -v17->v18 -v16->v17 -v15->v16 -Comments pointed by Joel Stanley -- Add reset_control on Jtag init/deinit - -v14->v15 -Comments pointed by Joel Stanley -- Add ARCH_ASPEED || COMPILE_TEST to Kconfig -- remove unused offset variable -- remove "aspeed_jtag" from dev_err and dev_dbg messages -- change clk_prepare_enable initialisation order - -v13->v14 -Comments pointed by Philippe Ombredanne -- Change style of head block comment from /**/ to // - -v12->v13 -Comments pointed by Philippe Ombredanne -- Change jtag-aspeed.c licence type to - SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note - and reorder line with license- add reset descriptions in bndings file - in description -Comments pointed by Kun Yi -- Changed capability check for aspeed,ast2400-jtag/ast200-jtag - -v11->v12 -Comments pointed by Chip Bilbrey -- Remove access mode from xfer and idle transactions -- Add new ioctl JTAG_SIOCMODE for set hw mode - -v10->v11 -v9->v10 -V8->v9 -Comments pointed by Arnd Bergmann -- add *data parameter to xfer function prototype - -v7->v8 -Comments pointed by Joel Stanley -- aspeed_jtag_init replace goto to return; -- change input variables type from __u32 to u32 - in functios freq_get, freq_set, status_get -- change sm_ variables type from char to u8 -- in jatg_init add disable clocks on error case -- remove release_mem_region on error case -- remove devm_free_irq on jtag_deinit -- Fix misspelling Disabe/Disable -- Change compatible string to ast2400 and ast2000 - -v6->v7 -Notifications from kbuild test robot -- Add include to jtag-asapeed.c - -v5->v6 -v4->v5 -Comments pointed by Arnd Bergmann -- Added HAS_IOMEM dependence in Kconfig to avoid - "undefined reference to `devm_ioremap_resource'" error, - because in some arch this not supported - -v3->v4 -Comments pointed by Arnd Bergmann -- change transaction pointer tdio type to __u64 -- change internal status type from enum to __u32 - -v2->v3 - -v1->v2 -Comments pointed by Greg KH -- change license type from GPLv2/BSD to GPLv2 - -Comments pointed by Neil Armstrong -- Add clk_prepare_enable/clk_disable_unprepare in clock init/deinit -- Change .compatible to soc-specific compatible names - aspeed,aspeed4000-jtag/aspeed5000-jtag -- Added dt-bindings - -Comments pointed by Arnd Bergmann -- Reorder functions and removed the forward declarations -- Add static const qualifier to state machine states transitions -- Change .compatible to soc-specific compatible names - aspeed,aspeed4000-jtag/aspeed5000-jtag -- Add dt-bindings - -Comments pointed by Randy Dunlap -- Change module name jtag-aspeed in description in Kconfig - -Comments pointed by kbuild test robot -- Remove invalid include -- add resource_size instead of calculation ---- - drivers/jtag/Kconfig | 14 + - drivers/jtag/Makefile | 1 + - drivers/jtag/jtag-aspeed.c | 1524 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 1539 insertions(+) - create mode 100644 drivers/jtag/jtag-aspeed.c - -diff --git a/drivers/jtag/Kconfig b/drivers/jtag/Kconfig -index 47771fc..0cc163f 100644 ---- a/drivers/jtag/Kconfig -+++ b/drivers/jtag/Kconfig -@@ -15,3 +15,17 @@ menuconfig JTAG - - To compile this driver as a module, choose M here: the module will - be called jtag. -+ -+menuconfig JTAG_ASPEED -+ tristate "Aspeed SoC JTAG controller support" -+ depends on JTAG && HAS_IOMEM -+ depends on ARCH_ASPEED || COMPILE_TEST -+ help -+ This provides a support for Aspeed JTAG device, equipped on -+ Aspeed SoC 24xx and 25xx families. Drivers allows programming -+ of hardware devices, connected to SoC through the JTAG interface. -+ -+ If you want this support, you should say Y here. -+ -+ To compile this driver as a module, choose M here: the module will -+ be called jtag-aspeed. -diff --git a/drivers/jtag/Makefile b/drivers/jtag/Makefile -index af37493..04a855e 100644 ---- a/drivers/jtag/Makefile -+++ b/drivers/jtag/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_JTAG) += jtag.o -+obj-$(CONFIG_JTAG_ASPEED) += jtag-aspeed.o -diff --git a/drivers/jtag/jtag-aspeed.c b/drivers/jtag/jtag-aspeed.c -new file mode 100644 -index 0000000..1e6ace6 ---- /dev/null -+++ b/drivers/jtag/jtag-aspeed.c -@@ -0,0 +1,1524 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2018 Mellanox Technologies. All rights reserved. -+// Copyright (c) 2018 Oleksandr Shamray -+// Copyright (c) 2019 Intel Corporation -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ASPEED_SCU_RESET_JTAG BIT(22) -+ -+#define ASPEED_JTAG_DATA 0x00 -+#define ASPEED_JTAG_INST 0x04 -+#define ASPEED_JTAG_CTRL 0x08 -+#define ASPEED_JTAG_ISR 0x0C -+#define ASPEED_JTAG_SW 0x10 -+#define ASPEED_JTAG_TCK 0x14 -+#define ASPEED_JTAG_EC 0x18 -+ -+#define ASPEED_JTAG_DATA_MSB 0x01 -+#define ASPEED_JTAG_DATA_CHUNK_SIZE 0x20 -+#define ASPEED_JTAG_HW2_DATA_CHUNK_SIZE 160 -+ -+/* ASPEED_JTAG_CTRL: Engine Control 24xx and 25xx series*/ -+#define ASPEED_JTAG_CTL_ENG_EN BIT(31) -+#define ASPEED_JTAG_CTL_ENG_OUT_EN BIT(30) -+#define ASPEED_JTAG_CTL_FORCE_TMS BIT(29) -+#define ASPEED_JTAG_CTL_IR_UPDATE BIT(26) -+#define ASPEED_JTAG_CTL_INST_LEN(x) ((x) << 20) -+#define ASPEED_JTAG_CTL_LASPEED_INST BIT(17) -+#define ASPEED_JTAG_CTL_INST_EN BIT(16) -+#define ASPEED_JTAG_CTL_DR_UPDATE BIT(10) -+#define ASPEED_JTAG_CTL_DATA_LEN(x) ((x) << 4) -+#define ASPEED_JTAG_CTL_LASPEED_DATA BIT(1) -+#define ASPEED_JTAG_CTL_DATA_EN BIT(0) -+ -+/* ASPEED_JTAG_CTRL: Engine Control 26xx series*/ -+#define ASPEED_JTAG_CTL_26XX_RESET_FIFO BIT(21) -+#define ASPEED_JTAG_CTL_26XX_FIFO_MODE_CTRL BIT(20) -+#define ASPEED_JTAG_CTL_26XX_TRANS_LEN(x) ((x) << 8) -+#define ASPEED_JTAG_CTL_26XX_TRANS_MASK GENMASK(17, 8) -+#define ASPEED_JTAG_CTL_26XX_MSB_FIRST BIT(6) -+#define ASPEED_JTAG_CTL_26XX_TERM_TRANS BIT(5) -+#define ASPEED_JTAG_CTL_26XX_LASPEED_TRANS BIT(4) -+#define ASPEED_JTAG_CTL_26XX_INST_EN BIT(1) -+ -+/* ASPEED_JTAG_ISR : Interrupt status and enable */ -+#define ASPEED_JTAG_ISR_INST_PAUSE BIT(19) -+#define ASPEED_JTAG_ISR_INST_COMPLETE BIT(18) -+#define ASPEED_JTAG_ISR_DATA_PAUSE BIT(17) -+#define ASPEED_JTAG_ISR_DATA_COMPLETE BIT(16) -+#define ASPEED_JTAG_ISR_INST_PAUSE_EN BIT(3) -+#define ASPEED_JTAG_ISR_INST_COMPLETE_EN BIT(2) -+#define ASPEED_JTAG_ISR_DATA_PAUSE_EN BIT(1) -+#define ASPEED_JTAG_ISR_DATA_COMPLETE_EN BIT(0) -+#define ASPEED_JTAG_ISR_INT_EN_MASK GENMASK(3, 0) -+#define ASPEED_JTAG_ISR_INT_MASK GENMASK(19, 16) -+ -+/* ASPEED_JTAG_SW : Software Mode and Status */ -+#define ASPEED_JTAG_SW_MODE_EN BIT(19) -+#define ASPEED_JTAG_SW_MODE_TCK BIT(18) -+#define ASPEED_JTAG_SW_MODE_TMS BIT(17) -+#define ASPEED_JTAG_SW_MODE_TDIO BIT(16) -+ -+/* ASPEED_JTAG_TCK : TCK Control */ -+#define ASPEED_JTAG_TCK_DIVISOR_MASK GENMASK(10, 0) -+#define ASPEED_JTAG_TCK_GET_DIV(x) ((x) & ASPEED_JTAG_TCK_DIVISOR_MASK) -+ -+/* ASPEED_JTAG_EC : Controller set for go to IDLE */ -+#define ASPEED_JTAG_EC_GO_IDLE BIT(0) -+ -+#define ASPEED_JTAG_IOUT_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_INST_LEN(len)) -+ -+#define ASPEED_JTAG_DOUT_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_DATA_LEN(len)) -+ -+#define ASPEED_JTAG_TRANS_LEN(len) \ -+ (ASPEED_JTAG_CTL_ENG_EN | \ -+ ASPEED_JTAG_CTL_ENG_OUT_EN | \ -+ ASPEED_JTAG_CTL_26XX_TRANS_LEN(len)) -+ -+#define ASPEED_JTAG_SW_TDIO (ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TDIO) -+ -+#define ASPEED_JTAG_GET_TDI(direction, byte) \ -+ (((direction) & JTAG_WRITE_XFER) ? byte : UINT_MAX) -+ -+#define ASPEED_JTAG_TCK_WAIT 10 -+#define ASPEED_JTAG_RESET_CNTR 10 -+#define WAIT_ITERATIONS 75 -+ -+/* Use this macro to switch between HW mode 1(comment out) and 2(defined) */ -+#define ASPEED_JTAG_HW_MODE_2_ENABLE 1 -+ -+/* ASPEED JTAG HW MODE 2 (Only supported in AST26xx series) */ -+#define ASPEED_JTAG_SHDATA 0x20 -+#define ASPEED_JTAG_SHINST 0x24 -+#define ASPEED_JTAG_PADCTRL0 0x28 -+#define ASPEED_JTAG_PADCTRL1 0x2C -+#define ASPEED_JTAG_SHCTRL 0x30 -+#define ASPEED_JTAG_GBLCTRL 0x34 -+#define ASPEED_JTAG_INTCTRL 0x38 -+#define ASPEED_JTAG_STAT 0x3C -+ -+/* ASPEED_JTAG_PADCTRLx : Padding control 0 and 1 */ -+#define ASPEED_JTAG_PADCTRL_PAD_DATA BIT(24) -+#define ASPEED_JTAG_PADCTRL_POSTPAD(x) (((x) & GENMASK(8, 0)) << 12) -+#define ASPEED_JTAG_PADCTRL_PREPAD(x) (((x) & GENMASK(8, 0)) << 0) -+ -+/* ASPEED_JTAG_SHCTRL: Shift Control */ -+#define ASPEED_JTAG_SHCTRL_FRUN_TCK_EN BIT(31) -+#define ASPEED_JTAG_SHCTRL_STSHIFT_EN BIT(30) -+#define ASPEED_JTAG_SHCTRL_TMS(x) (((x) & GENMASK(13, 0)) << 16) -+#define ASPEED_JTAG_SHCTRL_POST_TMS(x) (((x) & GENMASK(3, 0)) << 13) -+#define ASPEED_JTAG_SHCTRL_PRE_TMS(x) (((x) & GENMASK(3, 0)) << 10) -+#define ASPEED_JTAG_SHCTRL_PAD_SEL0 (0) -+#define ASPEED_JTAG_SHCTRL_PAD_SEL1 BIT(9) -+#define ASPEED_JTAG_SHCTRL_END_SHIFT BIT(8) -+#define ASPEED_JTAG_SHCTRL_START_SHIFT BIT(7) -+#define ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(x) ((x) & GENMASK(6, 0)) -+ -+#define ASPEED_JTAG_END_SHIFT_DISABLED 0 -+ -+/* ASPEED_JTAG_GBLCTRL : Global Control */ -+#define ASPEED_JTAG_GBLCTRL_ENG_MODE_EN BIT(31) -+#define ASPEED_JTAG_GBLCTRL_ENG_OUT_EN BIT(30) -+#define ASPEED_JTAG_GBLCTRL_FORCE_TMS BIT(29) -+#define ASPEED_JTAG_GBLCTRL_SHIFT_COMPLETE BIT(28) -+#define ASPEED_JTAG_GBLCTRL_RESET_FIFO BIT(25) -+#define ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE BIT(24) -+#define ASPEED_JTAG_GBLCTRL_UPDT_SHIFT(x) (((x) & GENMASK(9, 7)) << 13) -+#define ASPEED_JTAG_GBLCTRL_STSHIFT(x) (((x) & GENMASK(0, 0)) << 16) -+#define ASPEED_JTAG_GBLCTRL_TRST BIT(15) -+#define ASPEED_JTAG_CLK_DIVISOR_MASK GENMASK(11, 0) -+#define ASPEED_JTAG_CLK_GET_DIV(x) ((x) & ASPEED_JTAG_CLK_DIVISOR_MASK) -+ -+/* ASPEED_JTAG_INTCTRL: Interrupt Control */ -+#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN BIT(16) -+#define ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT BIT(0) -+ -+/* ASPEED_JTAG_STAT: JTAG HW mode 2 status */ -+#define ASPEED_JTAG_STAT_ENG_IDLE BIT(0) -+ -+/*#define USE_INTERRUPTS*/ -+#define DEBUG_JTAG -+ -+static const char * const regnames[] = { -+ [ASPEED_JTAG_DATA] = "ASPEED_JTAG_DATA", -+ [ASPEED_JTAG_INST] = "ASPEED_JTAG_INST", -+ [ASPEED_JTAG_CTRL] = "ASPEED_JTAG_CTRL", -+ [ASPEED_JTAG_ISR] = "ASPEED_JTAG_ISR", -+ [ASPEED_JTAG_SW] = "ASPEED_JTAG_SW", -+ [ASPEED_JTAG_TCK] = "ASPEED_JTAG_TCK", -+ [ASPEED_JTAG_EC] = "ASPEED_JTAG_EC", -+ [ASPEED_JTAG_SHDATA] = "ASPEED_JTAG_SHDATA", -+ [ASPEED_JTAG_SHINST] = "ASPEED_JTAG_SHINST", -+ [ASPEED_JTAG_PADCTRL0] = "ASPEED_JTAG_PADCTRL0", -+ [ASPEED_JTAG_PADCTRL1] = "ASPEED_JTAG_PADCTRL1", -+ [ASPEED_JTAG_SHCTRL] = "ASPEED_JTAG_SHCTRL", -+ [ASPEED_JTAG_GBLCTRL] = "ASPEED_JTAG_GBLCTRL", -+ [ASPEED_JTAG_INTCTRL] = "ASPEED_JTAG_INTCTRL", -+ [ASPEED_JTAG_STAT] = "ASPEED_JTAG_STAT", -+}; -+ -+#define ASPEED_JTAG_NAME "jtag-aspeed" -+ -+struct aspeed_jtag { -+ void __iomem *reg_base; -+ struct device *dev; -+ struct clk *pclk; -+ enum jtag_tapstate status; -+ int irq; -+ struct reset_control *rst; -+ u32 flag; -+ wait_queue_head_t jtag_wq; -+ u32 mode; -+ const struct jtag_low_level_functions *llops; -+}; -+ -+/* Multi generation support is enabled by fops and low level assped function -+ * mapping using asped_jtag_functions struct as config mechanism. -+ */ -+ -+struct jtag_low_level_functions { -+ void (*output_disable)(struct aspeed_jtag *aspeed_jtag); -+ void (*master_enable)(struct aspeed_jtag *aspeed_jtag); -+ int (*xfer_push_data)(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len); -+ int (*xfer_push_data_last)(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len); -+ void (*xfer_sw)(struct aspeed_jtag *aspeed_jtag, struct jtag_xfer *xfer, -+ u32 *data); -+ int (*xfer_hw)(struct aspeed_jtag *aspeed_jtag, struct jtag_xfer *xfer, -+ u32 *data); -+}; -+ -+struct aspeed_jtag_functions { -+ const struct jtag_ops *aspeed_jtag_ops; -+ const struct jtag_low_level_functions *aspeed_jtag_llops; -+}; -+ -+/* -+ * This structure represents a TMS cycle, as expressed in a set of bits and a -+ * count of bits (note: there are no start->end state transitions that require -+ * more than 1 byte of TMS cycles) -+ */ -+struct tms_cycle { -+ unsigned char tmsbits; -+ unsigned char count; -+}; -+ -+/* -+ * This is the complete set TMS cycles for going from any TAP state to any -+ * other TAP state, following a "shortest path" rule. -+ */ -+static const struct tms_cycle _tms_cycle_lookup[][16] = { -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* TLR */{{0x00, 0}, {0x00, 1}, {0x02, 2}, {0x02, 3}, {0x02, 4}, {0x0a, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0a, 5}, {0x2a, 6}, {0x1a, 5}, {0x06, 3}, {0x06, 4}, {0x06, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x16, 5}, {0x16, 6}, {0x56, 7}, {0x36, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* RTI */{{0x07, 3}, {0x00, 0}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SelDR*/{{0x03, 2}, {0x03, 3}, {0x00, 0}, {0x00, 1}, {0x00, 2}, {0x02, 2}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x02, 3}, {0x0a, 4}, {0x06, 3}, {0x01, 1}, {0x01, 2}, {0x01, 3}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x05, 3}, {0x05, 4}, {0x15, 5}, {0x0d, 4} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* CapDR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x00, 0}, {0x00, 1}, {0x01, 1}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x00, 0}, {0x01, 1}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x01, 2}, {0x05, 3}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex1DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x02, 3}, {0x00, 0}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x00, 1}, {0x02, 2}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* PDR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x01, 2}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x00, 0}, {0x01, 1}, {0x03, 2}, {0x0f, 4}, {0x0f, 5}, {0x0f, 6}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x2f, 6}, {0x2f, 7}, {0xaf, 8}, {0x6f, 7} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex2DR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x00, 1}, {0x02, 2}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x02, 3}, {0x00, 0}, {0x01, 1}, {0x07, 3}, {0x07, 4}, {0x07, 5}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x17, 5}, {0x17, 6}, {0x57, 7}, {0x37, 6} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* UpdDR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x00, 0}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x1b, 5} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SelIR*/{{0x01, 1}, {0x01, 2}, {0x05, 3}, {0x05, 4}, {0x05, 5}, {0x15, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x15, 6}, {0x55, 7}, {0x35, 6}, {0x00, 0}, {0x00, 1}, {0x00, 2}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x02, 2}, {0x02, 3}, {0x0a, 4}, {0x06, 3} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* CapIR*/{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x00, 0}, {0x00, 1}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* SIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x00, 0}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x01, 1}, {0x01, 2}, {0x05, 3}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex1IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x02, 3}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x00, 0}, {0x00, 1}, {0x02, 2}, {0x01, 1} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* PIR */{{0x1f, 5}, {0x03, 3}, {0x07, 3}, {0x07, 4}, {0x07, 5}, {0x17, 5}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x17, 6}, {0x57, 7}, {0x37, 6}, {0x0f, 4}, {0x0f, 5}, {0x01, 2}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x05, 3}, {0x00, 0}, {0x01, 1}, {0x03, 2} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* Ex2IR*/{{0x0f, 4}, {0x01, 2}, {0x03, 2}, {0x03, 3}, {0x03, 4}, {0x0b, 4}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x0b, 5}, {0x2b, 6}, {0x1b, 5}, {0x07, 3}, {0x07, 4}, {0x00, 1}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x02, 2}, {0x02, 3}, {0x00, 0}, {0x01, 1} }, -+ -+/* TLR RTI SelDR CapDR SDR Ex1DR*/ -+/* UpdIR*/{{0x07, 3}, {0x00, 1}, {0x01, 1}, {0x01, 2}, {0x01, 3}, {0x05, 3}, -+/* PDR Ex2DR UpdDR SelIR CapIR SIR*/ -+ {0x05, 4}, {0x15, 5}, {0x0d, 4}, {0x03, 2}, {0x03, 3}, {0x03, 4}, -+/* Ex1IR PIR Ex2IR UpdIR*/ -+ {0x0b, 4}, {0x0b, 5}, {0x2b, 6}, {0x00, 0} }, -+}; -+ -+#ifdef DEBUG_JTAG -+static char *end_status_str[] = { "tlr", "idle", "selDR", "capDR", -+ "sDR", "ex1DR", "pDR", "ex2DR", -+ "updDR", "selIR", "capIR", "sIR", -+ "ex1IR", "pIR", "ex2IR", "updIR" }; -+#endif -+ -+static u32 aspeed_jtag_read(struct aspeed_jtag *aspeed_jtag, u32 reg) -+{ -+ u32 val = readl(aspeed_jtag->reg_base + reg); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "read:%s val = 0x%08x\n", regnames[reg], val); -+#endif -+ return val; -+} -+ -+static void aspeed_jtag_write(struct aspeed_jtag *aspeed_jtag, u32 val, u32 reg) -+{ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "write:%s val = 0x%08x\n", regnames[reg], -+ val); -+#endif -+ writel(val, aspeed_jtag->reg_base + reg); -+} -+ -+static int aspeed_jtag_freq_set(struct jtag *jtag, u32 freq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ unsigned long apb_frq; -+ u32 tck_val; -+ u16 div; -+ -+ if (!freq) -+ return -EINVAL; -+ -+ apb_frq = clk_get_rate(aspeed_jtag->pclk); -+ if (!apb_frq) -+ return -ENOTSUPP; -+ -+ div = (apb_frq - 1) / freq; -+ tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK); -+ aspeed_jtag_write(aspeed_jtag, -+ (tck_val & ~ASPEED_JTAG_TCK_DIVISOR_MASK) | div, -+ ASPEED_JTAG_TCK); -+ return 0; -+} -+ -+static int aspeed_jtag_freq_set_26xx(struct jtag *jtag, u32 freq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ unsigned long apb_frq; -+ u32 tck_val; -+ u16 div; -+ -+ if (!freq) -+ return -EINVAL; -+ -+ apb_frq = clk_get_rate(aspeed_jtag->pclk); -+ if (!apb_frq) -+ return -ENOTSUPP; -+ -+ div = (apb_frq - 1) / freq; -+ tck_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ (tck_val & ~ASPEED_JTAG_CLK_DIVISOR_MASK) | div, -+ ASPEED_JTAG_GBLCTRL); -+ return 0; -+} -+ -+static int aspeed_jtag_freq_get(struct jtag *jtag, u32 *frq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ u32 pclk; -+ u32 tck; -+ -+ pclk = clk_get_rate(aspeed_jtag->pclk); -+ tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_TCK); -+ *frq = pclk / (ASPEED_JTAG_TCK_GET_DIV(tck) + 1); -+ -+ return 0; -+} -+ -+static int aspeed_jtag_freq_get_26xx(struct jtag *jtag, u32 *frq) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ u32 pclk; -+ u32 tck; -+ -+ pclk = clk_get_rate(aspeed_jtag->pclk); -+ tck = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ *frq = pclk / (ASPEED_JTAG_CLK_GET_DIV(tck) + 1); -+ -+ return 0; -+} -+ -+static inline void aspeed_jtag_output_disable(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+} -+ -+static inline void -+aspeed_jtag_output_disable_26xx(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_GBLCTRL); -+} -+ -+static inline void aspeed_jtag_master(struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, -+ (ASPEED_JTAG_CTL_ENG_EN | ASPEED_JTAG_CTL_ENG_OUT_EN), -+ ASPEED_JTAG_CTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE | -+ ASPEED_JTAG_ISR_INST_COMPLETE | -+ ASPEED_JTAG_ISR_DATA_PAUSE | -+ ASPEED_JTAG_ISR_DATA_COMPLETE | -+ ASPEED_JTAG_ISR_INST_PAUSE_EN | -+ ASPEED_JTAG_ISR_INST_COMPLETE_EN | -+ ASPEED_JTAG_ISR_DATA_PAUSE_EN | -+ ASPEED_JTAG_ISR_DATA_COMPLETE_EN, -+ ASPEED_JTAG_ISR); /* Enable Interrupt */ -+} -+ -+static inline void aspeed_jtag_master_26xx(struct aspeed_jtag *aspeed_jtag) -+{ -+ if (aspeed_jtag->mode & JTAG_XFER_HW_MODE) { -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL_ENG_MODE_EN | -+ ASPEED_JTAG_GBLCTRL_ENG_OUT_EN, -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN | -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT, -+ ASPEED_JTAG_INTCTRL); /* Enable Interrupt */ -+ } else { -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_CTL_ENG_EN | -+ ASPEED_JTAG_CTL_ENG_OUT_EN, -+ ASPEED_JTAG_CTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | -+ ASPEED_JTAG_SW_MODE_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE | -+ ASPEED_JTAG_ISR_INST_COMPLETE | -+ ASPEED_JTAG_ISR_DATA_PAUSE | -+ ASPEED_JTAG_ISR_DATA_COMPLETE | -+ ASPEED_JTAG_ISR_INST_PAUSE_EN | -+ ASPEED_JTAG_ISR_INST_COMPLETE_EN | -+ ASPEED_JTAG_ISR_DATA_PAUSE_EN | -+ ASPEED_JTAG_ISR_DATA_COMPLETE_EN, -+ ASPEED_JTAG_ISR); /* Enable Interrupt */ -+ } -+} -+ -+static int aspeed_jtag_mode_set(struct jtag *jtag, struct jtag_mode *jtag_mode) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ switch (jtag_mode->feature) { -+ case JTAG_XFER_MODE: -+ aspeed_jtag->mode = jtag_mode->mode; -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ break; -+ case JTAG_CONTROL_MODE: -+ if (jtag_mode->mode == JTAG_MASTER_OUTPUT_DISABLE) -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ else if (jtag_mode->mode == JTAG_MASTER_MODE) -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static char aspeed_jtag_tck_cycle(struct aspeed_jtag *aspeed_jtag, u8 tms, -+ u8 tdi) -+{ -+ char tdo = 0; -+ -+ /* TCK = 0 */ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | -+ (tms * ASPEED_JTAG_SW_MODE_TMS) | -+ (tdi * ASPEED_JTAG_SW_MODE_TDIO), -+ ASPEED_JTAG_SW); -+ -+ aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW); -+ -+ /* TCK = 1 */ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_SW_MODE_EN | ASPEED_JTAG_SW_MODE_TCK | -+ (tms * ASPEED_JTAG_SW_MODE_TMS) | -+ (tdi * ASPEED_JTAG_SW_MODE_TDIO), -+ ASPEED_JTAG_SW); -+ -+ if (aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_SW) & -+ ASPEED_JTAG_SW_MODE_TDIO) -+ tdo = 1; -+ -+ return tdo; -+} -+ -+static int aspeed_jtag_bitbang(struct jtag *jtag, -+ struct bitbang_packet *bitbang, -+ struct tck_bitbang *bitbang_data) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ int i = 0; -+ -+ for (i = 0; i < bitbang->length; i++) { -+ bitbang_data[i].tdo = -+ aspeed_jtag_tck_cycle(aspeed_jtag, bitbang_data[i].tms, -+ bitbang_data[i].tdi); -+ } -+ return 0; -+} -+ -+static int aspeed_jtag_isr_wait(struct aspeed_jtag *aspeed_jtag, u32 bit) -+{ -+ int res = 0; -+#ifdef USE_INTERRUPTS -+ res = wait_event_interruptible(aspeed_jtag->jtag_wq, -+ aspeed_jtag->flag & bit); -+ aspeed_jtag->flag &= ~bit; -+#else -+ u32 status = 0; -+ u32 iterations = 0; -+ -+ while ((status & bit) == 0) { -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR); -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status); -+#endif -+ iterations++; -+ if (iterations > WAIT_ITERATIONS) { -+ dev_err(aspeed_jtag->dev, "%s %d in ASPEED_JTAG_ISR\n", -+ "aspeed_jtag driver timed out waiting for bit", -+ bit); -+ res = -EFAULT; -+ break; -+ } -+ if ((status & ASPEED_JTAG_ISR_DATA_COMPLETE) == 0) { -+ if (iterations % 25 == 0) -+ usleep_range(1, 5); -+ else -+ udelay(1); -+ } -+ } -+ aspeed_jtag_write(aspeed_jtag, bit | (status & 0xf), ASPEED_JTAG_ISR); -+#endif -+ return res; -+} -+ -+static int aspeed_jtag_wait_shift_complete(struct aspeed_jtag *aspeed_jtag) -+{ -+ int res = 0; -+#ifdef USE_INTERRUPTS -+ res = wait_event_interruptible(aspeed_jtag->jtag_wq, -+ aspeed_jtag->flag & -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT); -+ aspeed_jtag->flag &= ~ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT; -+#else -+ u32 status = 0; -+ u32 iterations = 0; -+ -+ while ((status & ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT) == 0) { -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_INTCTRL); -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "%s = 0x%08x\n", __func__, status); -+#endif -+ iterations++; -+ if (iterations > WAIT_ITERATIONS) { -+ dev_err(aspeed_jtag->dev, -+ "aspeed_jtag driver timed out waiting for shift completed\n"); -+ res = -EFAULT; -+ break; -+ } -+ if (iterations % 25 == 0) -+ usleep_range(1, 5); -+ else -+ udelay(1); -+ } -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_STAT | -+ ASPEED_JTAG_INTCTRL_SHCPL_IRQ_EN, -+ ASPEED_JTAG_INTCTRL); -+#endif -+ return res; -+} -+ -+static void aspeed_jtag_set_tap_state(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_tapstate from_state, -+ enum jtag_tapstate end_state) -+{ -+ int i = 0; -+ enum jtag_tapstate from, to; -+ -+ from = from_state; -+ to = end_state; -+ -+ if (from == JTAG_STATE_CURRENT) -+ from = aspeed_jtag->status; -+ -+ for (i = 0; i < _tms_cycle_lookup[from][to].count; i++) -+ aspeed_jtag_tck_cycle(aspeed_jtag, -+ ((_tms_cycle_lookup[from][to].tmsbits -+ >> i) & 0x1), 0); -+ aspeed_jtag->status = end_state; -+} -+ -+static void aspeed_jtag_set_tap_state_sw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ /* SW mode from curent tap state -> to end_state */ -+ if (tapstate->reset) { -+ int i = 0; -+ -+ for (i = 0; i < ASPEED_JTAG_RESET_CNTR; i++) -+ aspeed_jtag_tck_cycle(aspeed_jtag, 1, 0); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ } -+ -+ aspeed_jtag_set_tap_state(aspeed_jtag, tapstate->from, -+ tapstate->endstate); -+} -+ -+static int aspeed_jtag_status_set(struct jtag *jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "Set TAP state: %s\n", -+ end_status_str[tapstate->endstate]); -+#endif -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ aspeed_jtag_set_tap_state_sw(aspeed_jtag, tapstate); -+ return 0; -+ } -+ -+ /* x TMS high + 1 TMS low */ -+ if (tapstate->reset) { -+ /* Disable sw mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ mdelay(1); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_CTL_ENG_EN | -+ ASPEED_JTAG_CTL_ENG_OUT_EN | -+ ASPEED_JTAG_CTL_FORCE_TMS, -+ ASPEED_JTAG_CTRL); -+ mdelay(1); -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_TDIO, -+ ASPEED_JTAG_SW); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ } -+ -+ return 0; -+} -+ -+static void aspeed_jtag_shctrl_tms_mask(enum jtag_tapstate from, -+ enum jtag_tapstate to, -+ enum jtag_tapstate there, -+ enum jtag_tapstate endstate, -+ u32 start_shift, u32 end_shift, -+ u32 *tms_mask) -+{ -+ u32 pre_tms = start_shift ? _tms_cycle_lookup[from][to].count : 0; -+ u32 post_tms = end_shift ? _tms_cycle_lookup[there][endstate].count : 0; -+ u32 tms_value = start_shift ? _tms_cycle_lookup[from][to].tmsbits : 0; -+ -+ tms_value |= end_shift ? _tms_cycle_lookup[there][endstate].tmsbits -+ << pre_tms : -+ 0; -+ *tms_mask = start_shift | ASPEED_JTAG_SHCTRL_PRE_TMS(pre_tms) | -+ end_shift | ASPEED_JTAG_SHCTRL_POST_TMS(post_tms) | -+ ASPEED_JTAG_SHCTRL_TMS(tms_value); -+} -+ -+static void aspeed_jtag_set_tap_state_hw2(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ u32 reg_val; -+ u32 start_shift = ASPEED_JTAG_SHCTRL_START_SHIFT; -+ u32 tms_mask = 0; -+ -+ /* x TMS high + 1 TMS low */ -+ if (tapstate->reset) { -+ /* Disable sw mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ mdelay(1); -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_ENG_MODE_EN | -+ ASPEED_JTAG_GBLCTRL_ENG_OUT_EN | -+ ASPEED_JTAG_GBLCTRL_RESET_FIFO | -+ ASPEED_JTAG_GBLCTRL_FORCE_TMS, -+ ASPEED_JTAG_GBLCTRL); -+ mdelay(1); -+ aspeed_jtag->status = JTAG_STATE_TLRESET; -+ return; -+ } -+ -+ if (tapstate->from != tapstate->endstate) { -+ aspeed_jtag_shctrl_tms_mask(tapstate->from, tapstate->endstate, -+ JTAG_STATE_TLRESET, -+ JTAG_STATE_TLRESET, start_shift, -+ ASPEED_JTAG_END_SHIFT_DISABLED, -+ &tms_mask); -+ -+ /* Trigger a 0 bit transfer to execute pre tms flow*/ -+ aspeed_jtag_write(aspeed_jtag, -+ tms_mask | ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(0), -+ ASPEED_JTAG_SHCTRL); -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_RESET_FIFO, -+ ASPEED_JTAG_GBLCTRL); -+ } -+ aspeed_jtag->status = tapstate->endstate; -+} -+ -+static int aspeed_jtag_status_set_26xx(struct jtag *jtag, -+ struct jtag_tap_state *tapstate) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "Set TAP state: %s\n", -+ end_status_str[tapstate->endstate]); -+#endif -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ aspeed_jtag_set_tap_state_sw(aspeed_jtag, tapstate); -+ return 0; -+ } -+ -+ aspeed_jtag_set_tap_state_hw2(aspeed_jtag, tapstate); -+ return 0; -+} -+ -+static void aspeed_jtag_xfer_sw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long shift_bits = 0; -+ unsigned long index = 0; -+ unsigned long tdi; -+ char tdo; -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "SW JTAG SHIFT %s, length = %d\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length); -+#endif -+ -+ if (xfer->type == JTAG_SIR_XFER) -+ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from, -+ JTAG_STATE_SHIFTIR); -+ else -+ aspeed_jtag_set_tap_state(aspeed_jtag, xfer->from, -+ JTAG_STATE_SHIFTDR); -+ -+ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]); -+ data[index] = 0; -+ while (remain_xfer > 1) { -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ tdi >>= 1; -+ shift_bits++; -+ remain_xfer--; -+ -+ if (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE == 0) { -+ tdo = 0; -+ index++; -+ tdi = ASPEED_JTAG_GET_TDI(xfer->direction, data[index]); -+ data[index] = 0; -+ } -+ } -+ -+ if ((xfer->endstate == (xfer->type == JTAG_SIR_XFER ? -+ JTAG_STATE_SHIFTIR : -+ JTAG_STATE_SHIFTDR))) { -+ /* Stay in Shift IR/DR*/ -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 0, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ } else { -+ /* Goto end state */ -+ tdo = aspeed_jtag_tck_cycle(aspeed_jtag, 1, -+ tdi & ASPEED_JTAG_DATA_MSB); -+ data[index] |= tdo -+ << (shift_bits % ASPEED_JTAG_DATA_CHUNK_SIZE); -+ aspeed_jtag->status = (xfer->type == JTAG_SIR_XFER) ? -+ JTAG_STATE_EXIT1IR : -+ JTAG_STATE_EXIT1DR; -+ aspeed_jtag_set_tap_state(aspeed_jtag, aspeed_jtag->status, -+ xfer->endstate); -+ } -+} -+ -+static int aspeed_jtag_xfer_push_data_26xx(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 bits_len) -+{ -+ int res = 0; -+ -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_TRANS_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(bits_len) | -+ ASPEED_JTAG_CTL_26XX_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(bits_len) | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_PAUSE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, u32 bits_len) -+{ -+ int res = 0; -+ -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_IOUT_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(bits_len) | -+ ASPEED_JTAG_CTL_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_PAUSE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_DOUT_LEN(bits_len), -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(bits_len) | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_PAUSE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data_last_26xx(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 shift_bits) -+{ -+ int res = 0; -+ -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS, -+ ASPEED_JTAG_CTRL); -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS | -+ ASPEED_JTAG_CTL_26XX_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_COMPLETE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_TRANS_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_26XX_LASPEED_TRANS | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_COMPLETE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_push_data_last(struct aspeed_jtag *aspeed_jtag, -+ enum jtag_xfer_type type, -+ u32 shift_bits) -+{ -+ int res = 0; -+ -+ if (type == JTAG_SIR_XFER) { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_INST, -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_IOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_INST | -+ ASPEED_JTAG_CTL_INST_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_INST_COMPLETE); -+ } else { -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_DATA, -+ ASPEED_JTAG_CTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ ASPEED_JTAG_DOUT_LEN(shift_bits) | -+ ASPEED_JTAG_CTL_LASPEED_DATA | -+ ASPEED_JTAG_CTL_DATA_EN, -+ ASPEED_JTAG_CTRL); -+ res = aspeed_jtag_isr_wait(aspeed_jtag, -+ ASPEED_JTAG_ISR_DATA_COMPLETE); -+ } -+ return res; -+} -+ -+static int aspeed_jtag_xfer_hw(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long index = 0; -+ char shift_bits; -+ u32 data_reg; -+ u32 scan_end; -+ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, "HW JTAG SHIFT %s, length = %d\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length); -+#endif -+ data_reg = xfer->type == JTAG_SIR_XFER ? ASPEED_JTAG_INST : -+ ASPEED_JTAG_DATA; -+ if (xfer->endstate == JTAG_STATE_SHIFTIR || -+ xfer->endstate == JTAG_STATE_SHIFTDR || -+ xfer->endstate == JTAG_STATE_PAUSEIR || -+ xfer->endstate == JTAG_STATE_PAUSEDR) { -+ scan_end = 0; -+ } else { -+ scan_end = 1; -+ } -+ -+ while (remain_xfer) { -+ if (xfer->direction & JTAG_WRITE_XFER) -+ aspeed_jtag_write(aspeed_jtag, data[index], data_reg); -+ else -+ aspeed_jtag_write(aspeed_jtag, 0, data_reg); -+ -+ if (remain_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) { -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Chunk len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE; -+ -+ /* -+ * Transmit bytes that were not equals to column length -+ * and after the transfer go to Pause IR/DR. -+ */ -+ if (aspeed_jtag->llops->xfer_push_data(aspeed_jtag, -+ xfer->type, -+ shift_bits) -+ != 0) { -+ return -EFAULT; -+ } -+ } else { -+ /* -+ * Read bytes equals to column length -+ */ -+ shift_bits = remain_xfer; -+ if (scan_end) { -+ /* -+ * If this data is the end of the transmission -+ * send remaining bits and go to endstate -+ */ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Last len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, -+ ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ if (aspeed_jtag->llops->xfer_push_data_last( -+ aspeed_jtag, xfer->type, -+ shift_bits) != 0) { -+ return -EFAULT; -+ } -+ } else { -+ /* -+ * If transmission is waiting for additional -+ * data send remaining bits and then go to -+ * Pause IR/DR. -+ */ -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "Tail len=%d chunk_size=%d remain_xfer=%lu\n", -+ xfer->length, -+ ASPEED_JTAG_DATA_CHUNK_SIZE, -+ remain_xfer); -+#endif -+ if (aspeed_jtag->llops->xfer_push_data( -+ aspeed_jtag, xfer->type, -+ shift_bits) != 0) { -+ return -EFAULT; -+ } -+ } -+ } -+ -+ if (xfer->direction & JTAG_READ_XFER) { -+ if (shift_bits < ASPEED_JTAG_DATA_CHUNK_SIZE) { -+ data[index] = -+ aspeed_jtag_read(aspeed_jtag, data_reg); -+ -+ data[index] >>= ASPEED_JTAG_DATA_CHUNK_SIZE - -+ shift_bits; -+ } else { -+ data[index] = -+ aspeed_jtag_read(aspeed_jtag, data_reg); -+ } -+ } -+ -+ remain_xfer = remain_xfer - shift_bits; -+ index++; -+ } -+ return 0; -+} -+ -+static int aspeed_jtag_xfer(struct jtag *jtag, struct jtag_xfer *xfer, -+ u8 *xfer_data) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ if (!(aspeed_jtag->mode & JTAG_XFER_HW_MODE)) { -+ /* SW mode */ -+ aspeed_jtag_write(aspeed_jtag, ASPEED_JTAG_SW_TDIO, -+ ASPEED_JTAG_SW); -+ -+ aspeed_jtag->llops->xfer_sw(aspeed_jtag, xfer, -+ (u32 *)xfer_data); -+ } else { -+ /* HW mode */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_SW); -+ if (aspeed_jtag->llops->xfer_hw(aspeed_jtag, xfer, -+ (u32 *)xfer_data) != 0) -+ return -EFAULT; -+ } -+ -+ aspeed_jtag->status = xfer->endstate; -+ return 0; -+} -+ -+static int aspeed_jtag_xfer_hw2(struct aspeed_jtag *aspeed_jtag, -+ struct jtag_xfer *xfer, u32 *data) -+{ -+ unsigned long remain_xfer = xfer->length; -+ unsigned long partial_xfer_size = 0; -+ unsigned long index = 0; -+ u32 shift_bits; -+ u32 data_reg; -+ u32 reg_val; -+ enum jtag_tapstate shift; -+ enum jtag_tapstate exit; -+ u32 start_shift; -+ u32 end_shift; -+ u32 tms_mask; -+ -+ if (xfer->type == JTAG_SIR_XFER) { -+ data_reg = ASPEED_JTAG_SHDATA; -+ shift = JTAG_STATE_SHIFTIR; -+ exit = JTAG_STATE_EXIT1IR; -+ } else { -+ data_reg = ASPEED_JTAG_SHDATA; -+ shift = JTAG_STATE_SHIFTDR; -+ exit = JTAG_STATE_EXIT1DR; -+ } -+#ifdef DEBUG_JTAG -+ dev_dbg(aspeed_jtag->dev, -+ "HW2 JTAG SHIFT %s, length %d from %s to %s then %s stat %s\n", -+ (xfer->type == JTAG_SIR_XFER) ? "IR" : "DR", xfer->length, -+ end_status_str[xfer->from], end_status_str[shift], -+ end_status_str[xfer->endstate], -+ end_status_str[aspeed_jtag->status]); -+#endif -+ -+ if (xfer->from == shift) { -+ start_shift = 0; -+ } else { -+ reg_val = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_GBLCTRL); -+ aspeed_jtag_write(aspeed_jtag, -+ reg_val | ASPEED_JTAG_GBLCTRL_RESET_FIFO, -+ ASPEED_JTAG_GBLCTRL); -+ start_shift = ASPEED_JTAG_SHCTRL_START_SHIFT; -+ } -+ -+ if (xfer->endstate == shift) -+ end_shift = 0; -+ else -+ end_shift = ASPEED_JTAG_SHCTRL_END_SHIFT; -+ -+ while (remain_xfer) { -+ unsigned long partial_xfer; -+ unsigned long partial_index; -+ -+ if (remain_xfer > ASPEED_JTAG_HW2_DATA_CHUNK_SIZE) -+ partial_xfer_size = ASPEED_JTAG_HW2_DATA_CHUNK_SIZE; -+ else -+ partial_xfer_size = remain_xfer; -+ -+ partial_index = index; -+ partial_xfer = partial_xfer_size; -+ while (partial_xfer) { -+ if (partial_xfer > ASPEED_JTAG_DATA_CHUNK_SIZE) -+ shift_bits = ASPEED_JTAG_DATA_CHUNK_SIZE; -+ else -+ shift_bits = partial_xfer; -+ -+ if (xfer->direction & JTAG_WRITE_XFER) -+ aspeed_jtag_write(aspeed_jtag, -+ data[partial_index++], -+ data_reg); -+ else -+ aspeed_jtag_write(aspeed_jtag, 0, data_reg); -+ partial_xfer = partial_xfer - shift_bits; -+ } -+ if (remain_xfer > ASPEED_JTAG_HW2_DATA_CHUNK_SIZE) { -+ shift_bits = ASPEED_JTAG_HW2_DATA_CHUNK_SIZE; -+ -+ /* -+ * Transmit bytes that were not equals to column length -+ * and after the transfer go to Pause IR/DR. -+ */ -+ -+ aspeed_jtag_shctrl_tms_mask(xfer->from, shift, exit, -+ xfer->endstate, start_shift, -+ 0, &tms_mask); -+ -+ reg_val = aspeed_jtag_read(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL); -+ reg_val = reg_val & ~(GENMASK(22, 20)); -+ aspeed_jtag_write(aspeed_jtag, reg_val | -+ ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE | -+ ASPEED_JTAG_GBLCTRL_UPDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, tms_mask | -+ ASPEED_JTAG_SHCTRL_LWRDT_SHIFT(shift_bits), -+ ASPEED_JTAG_SHCTRL); -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ } else { -+ /* -+ * Read bytes equals to column length -+ */ -+ shift_bits = remain_xfer; -+ aspeed_jtag_shctrl_tms_mask(xfer->from, shift, exit, -+ xfer->endstate, start_shift, -+ end_shift, &tms_mask); -+ -+ reg_val = aspeed_jtag_read(aspeed_jtag, -+ ASPEED_JTAG_GBLCTRL); -+ reg_val = reg_val & ~(GENMASK(22, 20)); -+ aspeed_jtag_write(aspeed_jtag, reg_val | -+ ASPEED_JTAG_GBLCTRL_FIFO_CTRL_MODE | -+ ASPEED_JTAG_GBLCTRL_UPDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_GBLCTRL); -+ -+ aspeed_jtag_write(aspeed_jtag, tms_mask | -+ ASPEED_JTAG_SHCTRL_LWRDT_SHIFT( -+ shift_bits), -+ ASPEED_JTAG_SHCTRL); -+ -+ aspeed_jtag_wait_shift_complete(aspeed_jtag); -+ } -+ -+ if (xfer->direction & JTAG_READ_XFER) { -+ partial_index = index; -+ partial_xfer = partial_xfer_size; -+ while (partial_xfer) { -+ if (partial_xfer > -+ ASPEED_JTAG_DATA_CHUNK_SIZE) { -+ shift_bits = -+ ASPEED_JTAG_DATA_CHUNK_SIZE; -+ data[partial_index++] = -+ aspeed_jtag_read(aspeed_jtag, -+ data_reg); -+ -+ } else { -+ shift_bits = partial_xfer; -+ data[partial_index++] = -+ aspeed_jtag_read(aspeed_jtag, -+ data_reg); -+ } -+ partial_xfer = partial_xfer - shift_bits; -+ } -+ } -+ -+ remain_xfer = remain_xfer - partial_xfer_size; -+ index = partial_index; -+ start_shift = 0; -+ } -+ aspeed_jtag->status = xfer->endstate; -+ return 0; -+} -+ -+static int aspeed_jtag_status_get(struct jtag *jtag, u32 *status) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ *status = aspeed_jtag->status; -+ return 0; -+} -+ -+#ifdef USE_INTERRUPTS -+static irqreturn_t aspeed_jtag_interrupt(s32 this_irq, void *dev_id) -+{ -+ struct aspeed_jtag *aspeed_jtag = dev_id; -+ irqreturn_t ret = IRQ_HANDLED; -+ u32 status; -+ -+ status = aspeed_jtag_read(aspeed_jtag, ASPEED_JTAG_ISR); -+ -+ if (status & ASPEED_JTAG_ISR_INT_MASK) { -+ aspeed_jtag_write(aspeed_jtag, -+ (status & ASPEED_JTAG_ISR_INT_MASK) | -+ (status & -+ ASPEED_JTAG_ISR_INT_EN_MASK), -+ ASPEED_JTAG_ISR); -+ aspeed_jtag->flag |= status & ASPEED_JTAG_ISR_INT_MASK; -+ } -+ -+ if (aspeed_jtag->flag) { -+ wake_up_interruptible(&aspeed_jtag->jtag_wq); -+ ret = IRQ_HANDLED; -+ } else { -+ dev_err(aspeed_jtag->dev, "irq status:%x\n", status); -+ ret = IRQ_NONE; -+ } -+ return ret; -+} -+#endif -+ -+static int aspeed_jtag_enable(struct jtag *jtag) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ aspeed_jtag->llops->master_enable(aspeed_jtag); -+ return 0; -+} -+ -+static int aspeed_jtag_disable(struct jtag *jtag) -+{ -+ struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag); -+ -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ return 0; -+} -+ -+static int aspeed_jtag_init(struct platform_device *pdev, -+ struct aspeed_jtag *aspeed_jtag) -+{ -+ struct resource *res; -+#ifdef USE_INTERRUPTS -+ int err; -+#endif -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ aspeed_jtag->reg_base = devm_ioremap_resource(aspeed_jtag->dev, res); -+ if (IS_ERR(aspeed_jtag->reg_base)) -+ return -ENOMEM; -+ -+ aspeed_jtag->pclk = devm_clk_get(aspeed_jtag->dev, NULL); -+ if (IS_ERR(aspeed_jtag->pclk)) { -+ dev_err(aspeed_jtag->dev, "devm_clk_get failed\n"); -+ return PTR_ERR(aspeed_jtag->pclk); -+ } -+ -+#ifdef USE_INTERRUPTS -+ aspeed_jtag->irq = platform_get_irq(pdev, 0); -+ if (aspeed_jtag->irq < 0) { -+ dev_err(aspeed_jtag->dev, "no irq specified\n"); -+ return -ENOENT; -+ } -+#endif -+ -+ if (clk_prepare_enable(aspeed_jtag->pclk)) { -+ dev_err(aspeed_jtag->dev, "no irq specified\n"); -+ return -ENOENT; -+ } -+ -+ aspeed_jtag->rst = devm_reset_control_get_shared(&pdev->dev, NULL); -+ if (IS_ERR(aspeed_jtag->rst)) { -+ dev_err(aspeed_jtag->dev, -+ "missing or invalid reset controller device tree entry"); -+ return PTR_ERR(aspeed_jtag->rst); -+ } -+ reset_control_deassert(aspeed_jtag->rst); -+ -+#ifdef USE_INTERRUPTS -+ err = devm_request_irq(aspeed_jtag->dev, aspeed_jtag->irq, -+ aspeed_jtag_interrupt, 0, "aspeed-jtag", -+ aspeed_jtag); -+ if (err) { -+ dev_err(aspeed_jtag->dev, "unable to get IRQ"); -+ clk_disable_unprepare(aspeed_jtag->pclk); -+ return err; -+ } -+#endif -+ -+ aspeed_jtag->llops->output_disable(aspeed_jtag); -+ -+ aspeed_jtag->flag = 0; -+ aspeed_jtag->mode = 0; -+ init_waitqueue_head(&aspeed_jtag->jtag_wq); -+ return 0; -+} -+ -+static int aspeed_jtag_deinit(struct platform_device *pdev, -+ struct aspeed_jtag *aspeed_jtag) -+{ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_ISR); -+ /* Disable clock */ -+ aspeed_jtag_write(aspeed_jtag, 0, ASPEED_JTAG_CTRL); -+ reset_control_assert(aspeed_jtag->rst); -+ clk_disable_unprepare(aspeed_jtag->pclk); -+ return 0; -+} -+ -+static const struct jtag_ops aspeed_jtag_ops = { -+ .freq_get = aspeed_jtag_freq_get, -+ .freq_set = aspeed_jtag_freq_set, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set, -+ .xfer = aspeed_jtag_xfer, -+ .mode_set = aspeed_jtag_mode_set, -+ .bitbang = aspeed_jtag_bitbang, -+ .enable = aspeed_jtag_enable, -+ .disable = aspeed_jtag_disable -+}; -+ -+static const struct jtag_ops aspeed_jtag_ops_26xx = { -+#ifdef ASPEED_JTAG_HW_MODE_2_ENABLE -+ .freq_get = aspeed_jtag_freq_get_26xx, -+ .freq_set = aspeed_jtag_freq_set_26xx, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set_26xx, -+#else -+ .freq_get = aspeed_jtag_freq_get, -+ .freq_set = aspeed_jtag_freq_set, -+ .status_get = aspeed_jtag_status_get, -+ .status_set = aspeed_jtag_status_set, -+#endif -+ .xfer = aspeed_jtag_xfer, -+ .mode_set = aspeed_jtag_mode_set, -+ .bitbang = aspeed_jtag_bitbang, -+ .enable = aspeed_jtag_enable, -+ .disable = aspeed_jtag_disable -+}; -+ -+static const struct jtag_low_level_functions ast25xx_llops = { -+ .master_enable = aspeed_jtag_master, -+ .output_disable = aspeed_jtag_output_disable, -+ .xfer_push_data = aspeed_jtag_xfer_push_data, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw -+}; -+ -+static const struct aspeed_jtag_functions ast25xx_functions = { -+ .aspeed_jtag_ops = &aspeed_jtag_ops, -+ .aspeed_jtag_llops = &ast25xx_llops -+}; -+ -+static const struct jtag_low_level_functions ast26xx_llops = { -+#ifdef ASPEED_JTAG_HW_MODE_2_ENABLE -+ .master_enable = aspeed_jtag_master_26xx, -+ .output_disable = aspeed_jtag_output_disable_26xx, -+ .xfer_push_data = aspeed_jtag_xfer_push_data_26xx, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last_26xx, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw2 -+#else -+ .master_enable = aspeed_jtag_master, -+ .output_disable = aspeed_jtag_output_disable, -+ .xfer_push_data = aspeed_jtag_xfer_push_data_26xx, -+ .xfer_push_data_last = aspeed_jtag_xfer_push_data_last_26xx, -+ .xfer_sw = aspeed_jtag_xfer_sw, -+ .xfer_hw = aspeed_jtag_xfer_hw -+#endif -+}; -+ -+static const struct aspeed_jtag_functions ast26xx_functions = { -+ .aspeed_jtag_ops = &aspeed_jtag_ops_26xx, -+ .aspeed_jtag_llops = &ast26xx_llops -+}; -+ -+static const struct of_device_id aspeed_jtag_of_match[] = { -+ { .compatible = "aspeed,ast2400-jtag", .data = &ast25xx_functions }, -+ { .compatible = "aspeed,ast2500-jtag", .data = &ast25xx_functions }, -+ { .compatible = "aspeed,ast2600-jtag", .data = &ast26xx_functions }, -+ {} -+}; -+ -+static int aspeed_jtag_probe(struct platform_device *pdev) -+{ -+ struct aspeed_jtag *aspeed_jtag; -+ struct jtag *jtag; -+ const struct of_device_id *match; -+ const struct aspeed_jtag_functions *jtag_functions; -+ int err; -+ -+ match = of_match_node(aspeed_jtag_of_match, pdev->dev.of_node); -+ if (!match) -+ return -ENODEV; -+ jtag_functions = match->data; -+ -+ jtag = jtag_alloc(&pdev->dev, sizeof(*aspeed_jtag), -+ jtag_functions->aspeed_jtag_ops); -+ if (!jtag) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, jtag); -+ aspeed_jtag = jtag_priv(jtag); -+ aspeed_jtag->dev = &pdev->dev; -+ -+ aspeed_jtag->llops = jtag_functions->aspeed_jtag_llops; -+ -+ /* Initialize device*/ -+ err = aspeed_jtag_init(pdev, aspeed_jtag); -+ if (err) -+ goto err_jtag_init; -+ -+ /* Initialize JTAG core structure*/ -+ err = devm_jtag_register(aspeed_jtag->dev, jtag); -+ if (err) -+ goto err_jtag_register; -+ -+ return 0; -+ -+err_jtag_register: -+ aspeed_jtag_deinit(pdev, aspeed_jtag); -+err_jtag_init: -+ jtag_free(jtag); -+ return err; -+} -+ -+static int aspeed_jtag_remove(struct platform_device *pdev) -+{ -+ struct jtag *jtag = platform_get_drvdata(pdev); -+ -+ aspeed_jtag_deinit(pdev, jtag_priv(jtag)); -+ return 0; -+} -+ -+static struct platform_driver aspeed_jtag_driver = { -+ .probe = aspeed_jtag_probe, -+ .remove = aspeed_jtag_remove, -+ .driver = { -+ .name = ASPEED_JTAG_NAME, -+ .of_match_table = aspeed_jtag_of_match, -+ }, -+}; -+module_platform_driver(aspeed_jtag_driver); -+ -+MODULE_AUTHOR("Oleksandr Shamray "); -+MODULE_DESCRIPTION("ASPEED JTAG driver"); -+MODULE_LICENSE("GPL v2"); --- -2.7.4 \ No newline at end of file diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch deleted file mode 100644 index 12073da02..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 2a22feac440070b7feaf0a6fe7e7e555d57ca19b Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Wed, 10 Mar 2019 11:45:04 -0800 -Subject: [PATCH] Documentation: jtag: Add bindings for Aspeed SoC - -It has been tested on Mellanox system with BMC equipped with -Aspeed 2520 SoC for programming CPLD devices. - -It also has been tested on Intel systems with BMC equipped with -Aspeed 25x0 SoC for JTAG board communication. - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Jiri Pirko -Signed-off-by: Corona, Ernesto -Acked-by: Rob Herring -Cc: Mark Rutland -Cc: Joel Stanley -Cc: Andrew Jeffery -Cc: Steven A Filary -Cc: Bryan Hunt ---- -v28->v29 -v27->v28 -v26->v27 -v25->v26 -v24->v25 -v23->v24 -v22->v23 -v21->v22 -v20->v21 -v19->v20 -v18->v19 - -v17->v18 -v16->v17 -v15->v16 -Comments pointed by Joel Stanley -- change clocks = <&clk_apb> to proper clocks = <&syscon ASPEED_CLK_APB> -- add reset descriptions in bindings file - -v14->v15 -v13->v14 -v12->v13 -v11->v12 -v10->v11 -v9->v10 -v8->v9 -v7->v8 -Comments pointed by pointed by Joel Stanley -- Change compatible string to ast2400 and ast2000 - -V6->v7 -Comments pointed by Tobias Klauser - - Fix spell "Doccumentation" -> "Documentation" - -v5->v6 -Comments pointed by Tobias Klauser -- Small nit: s/documentation/Documentation/ - -v4->v5 - -V3->v4 -Comments pointed by Rob Herring -- delete unnecessary "status" and "reg-shift" descriptions in - bindings file - -v2->v3 -Comments pointed by Rob Herring -- split Aspeed jtag driver and binding to separate patches -- delete unnecessary "status" and "reg-shift" descriptions in - bindings file ---- - .../devicetree/bindings/jtag/aspeed-jtag.txt | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - create mode 100644 Documentation/devicetree/bindings/jtag/aspeed-jtag.txt - -diff --git a/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt b/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt -new file mode 100644 -index 0000000..7c36eb6 ---- /dev/null -+++ b/Documentation/devicetree/bindings/jtag/aspeed-jtag.txt -@@ -0,0 +1,22 @@ -+Aspeed JTAG driver for ast2400 and ast2500 SoC -+ -+Required properties: -+- compatible: Should be one of -+ - "aspeed,ast2400-jtag" -+ - "aspeed,ast2500-jtag" -+- reg contains the offset and length of the JTAG memory -+ region -+- clocks root clock of bus, should reference the APB -+ clock in the second cell -+- resets phandle to reset controller with the reset number in -+ the second cell -+- interrupts should contain JTAG controller interrupt -+ -+Example: -+jtag: jtag@1e6e4000 { -+ compatible = "aspeed,ast2500-jtag"; -+ reg = <0x1e6e4000 0x1c>; -+ clocks = <&syscon ASPEED_CLK_APB>; -+ resets = <&syscon ASPEED_RESET_JTAG_MASTER>; -+ interrupts = <43>; -+}; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch deleted file mode 100644 index 1e4142035..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0055-Documentation-jtag-Add-ABI-documentation.patch +++ /dev/null @@ -1,310 +0,0 @@ -From d4c55bd4eeb6d9290025fa353d1787f18bca6ade Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Sun, 10 Mar 2019 11:47:40 -0800 -Subject: [PATCH v29 4/6] Documentation: jtag: Add ABI documentation - -Added document that describe the ABI for JTAG class driver - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Corona, Ernesto -Acked-by: Arnd Bergmann -Cc: Jonathan Corbet -Cc: Jiri Pirko -Cc: Vadim Pasternak -Cc: Steven A Filary -Cc: Bryan Hunt ---- -v28->v29 -Comments pointed by Steven Filary -- Expand bitbang function to accept multiples bitbang operations within a - single JTAG_IOCBITBANG call. It will receive a buffer with TDI and TMS - values and it is expected that driver fills TDO fields with its - corresponding output value for every transaction. - -v27->v28 -Comments pointed by Steven Filary -- Replace JTAG_IOCRUNTEST with JTAG_SIOCSTATE adding support for all TAPC - end states in SW mode using a lookup table to navigate across states. -- Add support for simultaneous READ/WRITE transfers(JTAG_READ_WRITE_XFER). -- Support for switching JTAG controller mode between slave and master - mode. -- Setup JTAG controller mode to master only when the driver is opened, - letting other HW to own the JTAG bus when it isn't in use. -- Include JTAG bit bang IOCTL for low level JTAG control usage - (JTAG_IOCBITBANG). - -v26->v27 -v25->v26 -Comments pointed by Randy Dunlap -- fix spell in ABI documentation - -v24->v25 -Comments pointed by Greg KH -- Fixed documentation according to new open() behavior - -v23->v24 -v22->v23 -Comments pointed by Randy Dunlap -- fix spell in ABI doccumentation - -v21->v22 -Comments pointed by Randy Dunlap -- fix spell in ABI doccumentation - -v20->v21 -Comments pointed by Randy Dunlap -- Fix JTAG dirver help in Kconfig - -v19->v20 -Comments pointed by Randy Dunlap -- Fix JTAG doccumentation - -v18->v19 -Pavel Machek -- Added JTAG doccumentation to Documentation/jtag - -v17->v18 -v16->v17 -v15->v16 -v14->v15 -v13->v14 -v12->v13 -v11->v12 Tobias Klauser -Comments pointed by -- rename /Documentation/ABI/testing/jatg-dev -> jtag-dev -- Typo: s/interfase/interface -v10->v11 -v9->v10 -Fixes added by Oleksandr: -- change jtag-cdev to jtag-dev in documentation -- update KernelVersion and Date in jtag-dev documentation; -v8->v9 -v7->v8 -v6->v7 -Comments pointed by Pavel Machek -- Added jtag-cdev documentation to Documentation/ABI/testing folder ---- - Documentation/ABI/testing/jtag-dev | 23 ++++++ - Documentation/jtag/overview | 27 +++++++ - Documentation/jtag/transactions | 145 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 195 insertions(+) - create mode 100644 Documentation/ABI/testing/jtag-dev - create mode 100644 Documentation/jtag/overview - create mode 100644 Documentation/jtag/transactions - -diff --git a/Documentation/ABI/testing/jtag-dev b/Documentation/ABI/testing/jtag-dev -new file mode 100644 -index 000000000000..423baab18761 ---- /dev/null -+++ b/Documentation/ABI/testing/jtag-dev -@@ -0,0 +1,23 @@ -+What: /dev/jtag[0-9]+ -+Date: July 2018 -+KernelVersion: 4.20 -+Contact: oleksandrs@mellanox.com -+Description: -+ The misc device files /dev/jtag* are the interface -+ between JTAG master interface and userspace. -+ -+ The ioctl(2)-based ABI is defined and documented in -+ [include/uapi]. -+ -+ The following file operations are supported: -+ -+ open(2) -+ Opens and allocates file descriptor. -+ -+ ioctl(2) -+ Initiate various actions. -+ See the inline documentation in [include/uapi] -+ for descriptions of all ioctls. -+ -+Users: -+ userspace tools which wants to access to JTAG bus -diff --git a/Documentation/jtag/overview b/Documentation/jtag/overview -new file mode 100644 -index 000000000000..6a5ec335e313 ---- /dev/null -+++ b/Documentation/jtag/overview -@@ -0,0 +1,27 @@ -+Linux kernel JTAG support -+========================= -+ -+JTAG is an industry standard for verifying hardware. JTAG provides access to -+many logic signals of a complex integrated circuit, including the device pins. -+ -+A JTAG interface is a special interface added to a chip. -+Depending on the version of JTAG, two, four, or five pins are added. -+ -+The connector pins are: -+ TDI (Test Data In) -+ TDO (Test Data Out) -+ TCK (Test Clock) -+ TMS (Test Mode Select) -+ TRST (Test Reset) optional -+ -+JTAG interface is designed to have two parts - basic core driver and -+hardware specific driver. The basic driver introduces a general interface -+which is not dependent of specific hardware. It provides communication -+between user space and hardware specific driver. -+Each JTAG device is represented as a char device from (jtag0, jtag1, ...). -+Access to a JTAG device is performed through IOCTL calls. -+ -+Call flow example: -+User: open -> /dev/jatgX -> JTAG core driver -> JTAG hardware specific driver -+User: ioctl -> /dev/jtagX -> JTAG core driver -> JTAG hardware specific driver -+User: close -> /dev/jatgX -> JTAG core driver -> JTAG hardware specific driver -diff --git a/Documentation/jtag/transactions b/Documentation/jtag/transactions -new file mode 100644 -index 000000000000..f5d4a1ded6cf ---- /dev/null -+++ b/Documentation/jtag/transactions -@@ -0,0 +1,145 @@ -+The JTAG API -+============= -+ -+JTAG master devices can be accessed through a character misc-device. -+Each JTAG master interface can be accessed by using /dev/jtagN. -+ -+JTAG system calls set: -+- SIR (Scan Instruction Register, IEEE 1149.1 Instruction Register scan); -+- SDR (Scan Data Register, IEEE 1149.1 Data Register scan); -+- RUNTEST (Forces the IEEE 1149.1 bus to a run state for a specified -+number of clocks. -+ -+open(), close() -+------- -+open() opens JTAG device. -+ -+Open/Close device: -+- jtag_fd = open("/dev/jtag0", O_RDWR); -+- close(jtag_fd); -+ -+ioctl() -+------- -+All access operations to JTAG devices are performed through ioctl interface. -+The IOCTL interface supports these requests: -+ JTAG_SIOCSTATE - Force JTAG state machine to go into a TAPC state -+ JTAG_SIOCFREQ - Set JTAG TCK frequency -+ JTAG_GIOCFREQ - Get JTAG TCK frequency -+ JTAG_IOCXFER - send/receive JTAG data Xfer -+ JTAG_GIOCSTATUS - get current JTAG TAP state -+ JTAG_SIOCMODE - set JTAG mode flags. -+ JTAG_IOCBITBANG - JTAG bitbang low level control. -+ -+JTAG_SIOCFREQ, JTAG_GIOCFREQ -+------ -+Set/Get JTAG clock speed: -+ -+ unsigned int jtag_fd; -+ ioctl(jtag_fd, JTAG_SIOCFREQ, &frq); -+ ioctl(jtag_fd, JTAG_GIOCFREQ, &frq); -+ -+JTAG_SIOCSTATE -+------ -+Force JTAG state machine to go into a TAPC state -+ -+struct jtag_tap_state { -+ __u8 reset; -+ __u8 from; -+ __u8 endstate; -+ __u8 tck; -+}; -+ -+reset: -+ JTAG_NO_RESET - go through selected endstate from current state -+ JTAG_FORCE_RESET - go through TEST_LOGIC/RESET state before selected endstate -+endstate: completion flag -+tck: clock counter -+ -+Example: -+ struct jtag_tap_state tap_state; -+ -+ tap_state.from = JTAG_STATE_TLRESET; -+ tap_state.endstate = JTAG_STATE_IDLE; -+ tap_state.reset = 0; -+ tap_state.tck = data_p->tck; -+ usleep(25 * 1000); -+ ioctl(jtag_fd, JTAG_SIOCSTATE, &tap_state); -+ -+JTAG_GIOCSTATUS -+------ -+Get JTAG TAPC machine state -+ -+ unsigned int jtag_fd; -+ jtag_tapstate tapstate; -+ ioctl(jtag_fd, JTAG_GIOCSTATUS, &tapstate); -+ -+JTAG_IOCXFER -+------ -+Send SDR/SIR transaction -+ -+struct jtag_xfer { -+ __u8 type; -+ __u8 direction; -+ __u8 from; -+ __u8 endstate; -+ __u8 padding; -+ __u32 length; -+ __u64 tdio; -+}; -+ -+type: transfer type - JTAG_SIR_XFER/JTAG_SDR_XFER -+direction: xfer direction - JTAG_READ_XFER/JTAG_WRITE_XFER/JTAG_READ_WRITE_XFER -+length: xfer data length in bits -+tdio : xfer data array -+from: xfer from state can be current JTAG tap state saved by the driver -+ JTAG_STATE_CURRENT or in a multichain environment any state listed in -+ jtag_tapstate struct saved by your multichain controller software. -+endstate: xfer end state after transaction finish -+ can be: any state listed in jtag_tapstate struct -+ -+Example: -+ struct jtag_xfer xfer; -+ static char buf[64]; -+ static unsigned int buf_len = 0; -+ [...] -+ xfer.type = JTAG_SDR_XFER; -+ xfer.tdio = (__u64)buf; -+ xfer.length = buf_len; -+ xfer.from = JTAG_STATE_TLRESET; -+ xfer.endstate = JTAG_STATE_IDLE; -+ -+ if (is_read) -+ xfer.direction = JTAG_READ_XFER; -+ else if (is_write) -+ xfer.direction = JTAG_WRITE_XFER; -+ else -+ xfer.direction = JTAG_READ_WRITE_XFER; -+ -+ ioctl(jtag_fd, JTAG_IOCXFER, &xfer); -+ -+JTAG_SIOCMODE -+------ -+If hardware driver can support different running modes you can change it. -+ -+Example: -+ struct jtag_mode mode; -+ mode.feature = JTAG_XFER_MODE; -+ mode.mode = JTAG_XFER_HW_MODE; -+ ioctl(jtag_fd, JTAG_SIOCMODE, &mode); -+ -+JTAG_IOCBITBANG -+------ -+JTAG Bitbang low level operation. -+ -+Example: -+ struct bitbang_packet bitbang; -+ struct tck_bitbang bitbang_data[2]; -+ bitbang_data[0].tms = 0; -+ bitbang_data[0].tdi = 1; -+ bitbang_data[1].tms = 0; -+ bitbang_data[1].tdi = 1; -+ bitbang.data = bitbang_data; -+ bitbang.length = 2; -+ ioctl(jtag_fd, JTAG_IOCBITBANG, &bitbang); -+ tdo0 = bitbang_data[0].tdo; -+ tdo1 = bitbang_data[1].tdo; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch deleted file mode 100644 index 99cc318ab..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 8618c2cd920d10681859bacf8af56c71f168b5a2 Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Sun, 10 Mar 2019 11:48:18 -0800 -Subject: [PATCH] Documentation jtag: Add JTAG core driver ioctl number - -JTAG class driver provide infrastructure to support hardware/software -JTAG platform drivers. It provide user layer API interface for flashing -and debugging external devices which equipped with JTAG interface -using standard transactions. - -Driver exposes set of IOCTL to user space for: -- XFER: - SIR (Scan Instruction Register, IEEE 1149.1 Data Register scan); - SDR (Scan Data Register, IEEE 1149.1 Instruction Register scan); -- GIOCSTATUS read the current TAPC state of the JTAG controller -- SIOCSTATE Forces the JTAG TAPC to go into a particular state. -- SIOCFREQ/GIOCFREQ for setting and reading JTAG frequency. -- IOCBITBANG for low level control of JTAG signals. - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Corona, Ernesto -Acked-by: Philippe Ombredanne -Cc: Jiri Pirko -Cc: Vadim Pasternak -Cc: Jonathan Corbet -Cc: Greg Kroah-Hartman -Cc: Gustavo Pimentel -Cc: Lorenzo Pieralisi -Cc: Kishon Vijay Abraham I -Cc: Darrick J. Wong -Cc: Bryant G. Ly -Cc: Eric Sandeen -Cc: Randy Dunlap -Cc: Tomohiro Kusumi -Cc: Arnd Bergmann -Cc: Steven A Filary -Cc: Bryan Hunt ---- - Documentation/ioctl/ioctl-number.rst | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/Documentation/ioctl/ioctl-number.rst b/Documentation/ioctl/ioctl-number.rst -index de23fc0f0fce..339d198c5adf 100644 ---- a/Documentation/ioctl/ioctl-number.rst -+++ b/Documentation/ioctl/ioctl-number.rst -@@ -333,6 +333,8 @@ Code Seq# Include File Comments - - 0xB1 00-1F PPPoX - -+0xB2 00-0F linux/jtag.h JTAG driver -+ - 0xB3 00 linux/mmc/ioctl.h - 0xB4 00-0F linux/gpio.h - 0xB5 00-0F uapi/linux/rpmsg.h --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch deleted file mode 100644 index 9ff92d8ec..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch +++ /dev/null @@ -1,50 +0,0 @@ -From fcf8f7fd3cb4e0b08cb1540f9ff9e5988cd285d1 Mon Sep 17 00:00:00 2001 -From: "Corona, Ernesto" -Date: Sun, 10 Mar 2019 11:49:37 -0800 -Subject: [PATCH] drivers: jtag: Add JTAG core driver Maintainers - -JTAG class driver provide infrastructure to support hardware/software -JTAG platform drivers. It provide user layer API interface for flashing -and debugging external devices which equipped with JTAG interface -using standard transactions. - -Signed-off-by: Oleksandr Shamray -Signed-off-by: Corona, Ernesto -Acked-by: Arnd Bergmann -Cc: Jiri Pirko -Cc: Vadim Pasternak -Cc: Mauro Carvalho Chehab -Cc: Greg Kroah-Hartman -Cc: David S. Miller -Cc: Nicolas Ferre -Cc: Steven A Filary -Cc: Bryan Hunt ---- - MAINTAINERS | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/MAINTAINERS b/MAINTAINERS -index 3bbdae50eb7e..34ab3522801c 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -8819,6 +8819,17 @@ L: linux-serial@vger.kernel.org - S: Orphan - F: drivers/tty/serial/jsm/ - -+JTAG SUBSYSTEM -+M: Oleksandr Shamray -+M: Vadim Pasternak -+M Ernesto Corona -+S: Maintained -+F: include/linux/jtag.h -+F: include/uapi/linux/jtag.h -+F: drivers/jtag/ -+F: Documentation/devicetree/bindings/jtag/ -+F: Documentation/ABI/testing/jtag-dev -+ - K10TEMP HARDWARE MONITORING DRIVER - M: Clemens Ladisch - L: linux-hwmon@vger.kernel.org --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch deleted file mode 100644 index fbf422a35..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0061-i2c-aspeed-add-buffer-mode-transfer-support.patch +++ /dev/null @@ -1,1148 +0,0 @@ -From b8d7d0f3513abdf014345b240a79d23c63409c4c Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 11 Jun 2019 15:07:08 -0700 -Subject: [PATCH] i2c: aspeed: add buffer mode transfer support - -Byte mode currently this driver uses makes lots of interrupt call -which isn't good for performance and it makes the driver very -timing sensitive. To improve performance of the driver, this commit -adds buffer mode transfer support which uses I2C SRAM buffer -instead of using a single byte buffer. - -AST2400: -It has 2 KBytes (256 Bytes x 8 pages) of I2C SRAM buffer pool from -0x1e78a800 to 0x1e78afff that can be used for all busses with -buffer pool manipulation. To simplify implementation for supporting -both AST2400 and AST2500, it assigns each 128 Bytes per bus without -using buffer pool manipulation so total 1792 Bytes of I2C SRAM -buffer will be used. - -AST2500: -It has 16 Bytes of individual I2C SRAM buffer per each bus and its -range is from 0x1e78a200 to 0x1e78a2df, so it doesn't have 'buffer -page selection' bit field in the Function control register, and -neither 'base address pointer' bit field in the Pool buffer control -register it has. To simplify implementation for supporting both -AST2400 and AST2500, it writes zeros on those register bit fields -but it's okay because it does nothing in AST2500. - -It provides buffer based master and slave data transfer. - -Signed-off-by: Jae Hyun Yoo ---- - .../devicetree/bindings/i2c/i2c-aspeed.txt | 40 ++- - arch/arm/boot/dts/aspeed-g4.dtsi | 47 +-- - arch/arm/boot/dts/aspeed-g5.dtsi | 47 +-- - arch/arm/boot/dts/aspeed-g6.dtsi | 32 +- - drivers/i2c/busses/i2c-aspeed.c | 376 +++++++++++++++++++-- - 5 files changed, 451 insertions(+), 91 deletions(-) - -diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -index 7da7e813b2b0..0ff3539cee95 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -@@ -3,7 +3,10 @@ Device tree configuration for the I2C busses on the AST24XX and AST25XX SoCs. - Required Properties: - - #address-cells : should be 1 - - #size-cells : should be 0 --- reg : address offset and range of bus -+- reg : Address offset and range of bus registers. -+ An additional SRAM buffer address offset and range is -+ optional in case of enabling I2C dedicated SRAM for -+ buffer mode transfer support. - - compatible : should be "aspeed,ast2400-i2c-bus" - or "aspeed,ast2500-i2c-bus" - - clocks : root clock of bus, should reference the APB -@@ -28,12 +31,21 @@ i2c { - #size-cells = <1>; - ranges = <0 0x1e78a000 0x1000>; - -- i2c_ic: interrupt-controller@0 { -- #interrupt-cells = <1>; -- compatible = "aspeed,ast2400-i2c-ic"; -+ i2c_gr: i2c-global-regs@0 { -+ compatible = "aspeed,ast2500-i2c-gr", "syscon"; - reg = <0x0 0x40>; -- interrupts = <12>; -- interrupt-controller; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x0 0x40>; -+ -+ i2c_ic: interrupt-controller@0 { -+ #interrupt-cells = <1>; -+ compatible = "aspeed,ast2500-i2c-ic"; -+ reg = <0x0 0x4>; -+ interrupts = <12>; -+ interrupt-controller; -+ }; - }; - - i2c0: i2c-bus@40 { -@@ -41,11 +53,25 @@ i2c { - #size-cells = <0>; - #interrupt-cells = <1>; - reg = <0x40 0x40>; -- compatible = "aspeed,ast2400-i2c-bus"; -+ compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; - bus-frequency = <100000>; - interrupts = <0>; - interrupt-parent = <&i2c_ic>; - }; -+ -+ /* buffer mode transfer enabled */ -+ i2c1: i2c-bus@80 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0x80 0x40>, <0x210 0x10>; -+ compatible = "aspeed,ast2500-i2c-bus"; -+ clocks = <&syscon ASPEED_CLK_APB>; -+ resets = <&syscon ASPEED_RESET_I2C>; -+ bus-frequency = <100000>; -+ interrupts = <1>; -+ interrupt-parent = <&i2c_ic>; -+ }; - }; -diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi -index fc6f4e009db7..0b30c8546e64 100644 ---- a/arch/arm/boot/dts/aspeed-g4.dtsi -+++ b/arch/arm/boot/dts/aspeed-g4.dtsi -@@ -518,12 +518,21 @@ - }; - - &i2c { -- i2c_ic: interrupt-controller@0 { -- #interrupt-cells = <1>; -- compatible = "aspeed,ast2400-i2c-ic"; -+ i2c_gr: i2c-global-regs@0 { -+ compatible = "aspeed,ast2400-i2c-gr", "syscon"; - reg = <0x0 0x40>; -- interrupts = <12>; -- interrupt-controller; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x0 0x40>; -+ -+ i2c_ic: interrupt-controller@0 { -+ #interrupt-cells = <1>; -+ compatible = "aspeed,ast2400-i2c-ic"; -+ reg = <0x0 0x4>; -+ interrupts = <12>; -+ interrupt-controller; -+ }; - }; - - i2c0: i2c-bus@40 { -@@ -531,7 +540,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x40 0x40>; -+ reg = <0x40 0x40>, <0x800 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -547,7 +556,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x80 0x40>; -+ reg = <0x80 0x40>, <0x880 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -563,7 +572,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0xc0 0x40>; -+ reg = <0xc0 0x40>, <0x900 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -580,7 +589,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x100 0x40>; -+ reg = <0x100 0x40>, <0x980 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -597,7 +606,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x140 0x40>; -+ reg = <0x140 0x40>, <0xa00 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -614,7 +623,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x180 0x40>; -+ reg = <0x180 0x40>, <0xa80 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -631,7 +640,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x1c0 0x40>; -+ reg = <0x1c0 0x40>, <0xb00 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -648,7 +657,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x300 0x40>; -+ reg = <0x300 0x40>, <0xb80 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -665,7 +674,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x340 0x40>; -+ reg = <0x340 0x40>, <0xc00 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -682,7 +691,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x380 0x40>; -+ reg = <0x380 0x40>, <0xc80 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -699,7 +708,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x3c0 0x40>; -+ reg = <0x3c0 0x40>, <0xd00 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -716,7 +725,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x400 0x40>; -+ reg = <0x400 0x40>, <0xd80 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -733,7 +742,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x440 0x40>; -+ reg = <0x440 0x40>, <0xe00 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -750,7 +759,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x480 0x40>; -+ reg = <0x480 0x40>, <0xe80 0x80>; - compatible = "aspeed,ast2400-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi -index eb1f9c9d9cca..51593a0a8a23 100644 ---- a/arch/arm/boot/dts/aspeed-g5.dtsi -+++ b/arch/arm/boot/dts/aspeed-g5.dtsi -@@ -615,12 +615,21 @@ - }; - - &i2c { -- i2c_ic: interrupt-controller@0 { -- #interrupt-cells = <1>; -- compatible = "aspeed,ast2500-i2c-ic"; -+ i2c_gr: i2c-global-regs@0 { -+ compatible = "aspeed,ast2500-i2c-gr", "syscon"; - reg = <0x0 0x40>; -- interrupts = <12>; -- interrupt-controller; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0x0 0x0 0x40>; -+ -+ i2c_ic: interrupt-controller@0 { -+ #interrupt-cells = <1>; -+ compatible = "aspeed,ast2500-i2c-ic"; -+ reg = <0x0 0x4>; -+ interrupts = <12>; -+ interrupt-controller; -+ }; - }; - - i2c0: i2c-bus@40 { -@@ -628,7 +637,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x40 0x40>; -+ reg = <0x40 0x40>, <0x200 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -644,7 +653,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x80 0x40>; -+ reg = <0x80 0x40>, <0x210 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -660,7 +669,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0xc0 0x40>; -+ reg = <0xc0 0x40>, <0x220 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -677,7 +686,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x100 0x40>; -+ reg = <0x100 0x40>, <0x230 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -694,7 +703,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x140 0x40>; -+ reg = <0x140 0x40>, <0x240 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -711,7 +720,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x180 0x40>; -+ reg = <0x180 0x40>, <0x250 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -728,7 +737,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x1c0 0x40>; -+ reg = <0x1c0 0x40>, <0x260 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -745,7 +754,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x300 0x40>; -+ reg = <0x300 0x40>, <0x270 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -762,7 +771,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x340 0x40>; -+ reg = <0x340 0x40>, <0x280 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -779,7 +788,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x380 0x40>; -+ reg = <0x380 0x40>, <0x290 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -796,7 +805,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x3c0 0x40>; -+ reg = <0x3c0 0x40>, <0x2a0 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -813,7 +822,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x400 0x40>; -+ reg = <0x400 0x40>, <0x2b0 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -830,7 +839,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x440 0x40>; -+ reg = <0x440 0x40>, <0x2c0 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -847,7 +856,7 @@ - #size-cells = <0>; - #interrupt-cells = <1>; - -- reg = <0x480 0x40>; -+ reg = <0x480 0x40>, <0x2d0 0x10>; - compatible = "aspeed,ast2500-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB>; - resets = <&syscon ASPEED_RESET_I2C>; -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index f92a2aa999d1..3ef312543269 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -712,7 +712,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x80 0x80>; -+ reg = <0x80 0x80>, <0xc00 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -727,7 +727,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x100 0x80>; -+ reg = <0x100 0x80>, <0xc20 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -742,7 +742,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x180 0x80>; -+ reg = <0x180 0x80>, <0xc40 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -757,7 +757,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x200 0x80>; -+ reg = <0x200 0x80>, <0xc60 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -772,7 +772,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x280 0x80>; -+ reg = <0x280 0x80>, <0xc80 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -787,7 +787,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x300 0x80>; -+ reg = <0x300 0x80>, <0xca0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -802,7 +802,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x380 0x80>; -+ reg = <0x380 0x80>, <0xcc0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -817,7 +817,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x400 0x80>; -+ reg = <0x400 0x80>, <0xce0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -832,7 +832,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x480 0x80>; -+ reg = <0x480 0x80>, <0xd00 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -847,7 +847,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x500 0x80>; -+ reg = <0x500 0x80>, <0xd20 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -862,7 +862,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x580 0x80>; -+ reg = <0x580 0x80>, <0xd40 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -877,7 +877,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x600 0x80>; -+ reg = <0x600 0x80>, <0xd60 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -892,7 +892,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x680 0x80>; -+ reg = <0x680 0x80>, <0xd80 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -907,7 +907,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x700 0x80>; -+ reg = <0x700 0x80>, <0xda0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -922,7 +922,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x780 0x80>; -+ reg = <0x780 0x80>, <0xdc0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -@@ -937,7 +937,7 @@ - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; -- reg = <0x800 0x80>; -+ reg = <0x800 0x80>, <0xde0 0x20>; - compatible = "aspeed,ast2600-i2c-bus"; - clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_I2C>; -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 7becfcd67142..bf72e151d11f 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -7,6 +7,7 @@ - * Copyright 2017 Google, Inc. - */ - -+#include - #include - #include - #include -@@ -19,15 +20,24 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include -+#include - #include - #include - --/* I2C Register */ -+/* I2C Global Registers */ -+/* 0x00 : I2CG Interrupt Status Register */ -+/* 0x08 : I2CG Interrupt Target Assignment */ -+/* 0x0c : I2CG Global Control Register (AST2500) */ -+#define ASPEED_I2CG_GLOBAL_CTRL_REG 0x0c -+#define ASPEED_I2CG_SRAM_BUFFER_EN BIT(0) -+ -+/* I2C Bus Registers */ - #define ASPEED_I2C_FUN_CTRL_REG 0x00 - #define ASPEED_I2C_AC_TIMING_REG1 0x04 - #define ASPEED_I2C_AC_TIMING_REG2 0x08 -@@ -35,14 +45,12 @@ - #define ASPEED_I2C_INTR_STS_REG 0x10 - #define ASPEED_I2C_CMD_REG 0x14 - #define ASPEED_I2C_DEV_ADDR_REG 0x18 -+#define ASPEED_I2C_BUF_CTRL_REG 0x1c - #define ASPEED_I2C_BYTE_BUF_REG 0x20 - --/* Global Register Definition */ --/* 0x00 : I2C Interrupt Status Register */ --/* 0x08 : I2C Interrupt Target Assignment */ -- - /* Device Register Definition */ - /* 0x00 : I2CD Function Control Register */ -+#define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20) - #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15) - #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8) - #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7) -@@ -102,6 +110,8 @@ - #define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11) - - /* Command Bit */ -+#define ASPEED_I2CD_RX_BUFF_ENABLE BIT(7) -+#define ASPEED_I2CD_TX_BUFF_ENABLE BIT(6) - #define ASPEED_I2CD_M_STOP_CMD BIT(5) - #define ASPEED_I2CD_M_S_RX_CMD_LAST BIT(4) - #define ASPEED_I2CD_M_RX_CMD BIT(3) -@@ -118,6 +128,13 @@ - /* 0x18 : I2CD Slave Device Address Register */ - #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) - -+/* 0x1c : I2CD Buffer Control Register */ -+/* Use 8-bits or 6-bits wide bit fileds to support both AST2400 and AST2500 */ -+#define ASPEED_I2CD_BUF_RX_COUNT_MASK GENMASK(31, 24) -+#define ASPEED_I2CD_BUF_RX_SIZE_MASK GENMASK(23, 16) -+#define ASPEED_I2CD_BUF_TX_COUNT_MASK GENMASK(15, 8) -+#define ASPEED_I2CD_BUF_OFFSET_MASK GENMASK(5, 0) -+ - enum aspeed_i2c_master_state { - ASPEED_I2C_MASTER_INACTIVE, - ASPEED_I2C_MASTER_PENDING, -@@ -163,6 +180,11 @@ struct aspeed_i2c_bus { - int master_xfer_result; - /* Multi-master */ - bool multi_master; -+ /* Buffer mode */ -+ void __iomem *buf_base; -+ u8 buf_offset; -+ u8 buf_page; -+ size_t buf_size; - #if IS_ENABLED(CONFIG_I2C_SLAVE) - struct i2c_client *slave; - enum aspeed_i2c_slave_state slave_state; -@@ -255,6 +277,77 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) - } - - #if IS_ENABLED(CONFIG_I2C_SLAVE) -+static inline void -+aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status, -+ u8 *value) -+{ -+ if (bus->buf_base && -+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && -+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) -+ *value = readb(bus->buf_base); -+ else -+ *value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; -+} -+ -+static inline void -+aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, -+ u8 *value) -+{ -+ int i, len; -+ -+ if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && -+ irq_status & ASPEED_I2CD_INTR_RX_DONE) { -+ if (bus->buf_base) { -+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, -+ readl(bus->base + -+ ASPEED_I2C_BUF_CTRL_REG)); -+ for (i = 0; i < len; i++) { -+ *value = readb(bus->buf_base + i); -+ i2c_slave_event(bus->slave, -+ I2C_SLAVE_WRITE_RECEIVED, -+ value); -+ } -+ } -+ } -+} -+ -+static inline void -+aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value) -+{ -+ if (bus->buf_base) { -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, -+ bus->buf_size - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -+ bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ writel(ASPEED_I2CD_RX_BUFF_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); -+ } -+} -+ -+static inline void -+aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value) -+{ -+ int i, len; -+ -+ if (bus->buf_base) { -+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, -+ readl(bus->base + -+ ASPEED_I2C_BUF_CTRL_REG)); -+ for (i = 1; i < len; i++) { -+ *value = readb(bus->buf_base + i); -+ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED, -+ value); -+ } -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, -+ bus->buf_size - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ writel(ASPEED_I2CD_RX_BUFF_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); -+ } -+} -+ - static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - { - u32 command, irq_handled = 0; -@@ -281,7 +374,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - - /* Slave was sent something. */ - if (irq_status & ASPEED_I2CD_INTR_RX_DONE) { -- value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; -+ aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value); - /* Handle address frame. */ - if (bus->slave_state == ASPEED_I2C_SLAVE_START) { - if (value & 0x1) -@@ -296,9 +389,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - - /* Slave was asked to stop. */ - if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { -+ aspeed_i2c_slave_handle_normal_stop(bus, irq_status, &value); - irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; - bus->slave_state = ASPEED_I2C_SLAVE_STOP; - } -+ - if (irq_status & ASPEED_I2CD_INTR_TX_NAK && - bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) { - irq_handled |= ASPEED_I2CD_INTR_TX_NAK; -@@ -328,9 +423,11 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - case ASPEED_I2C_SLAVE_WRITE_REQUESTED: - bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED; - i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); -+ aspeed_i2c_slave_handle_write_requested(bus, &value); - break; - case ASPEED_I2C_SLAVE_WRITE_RECEIVED: - i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); -+ aspeed_i2c_slave_handle_write_received(bus, &value); - break; - case ASPEED_I2C_SLAVE_STOP: - i2c_slave_event(slave, I2C_SLAVE_STOP, &value); -@@ -350,12 +447,76 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - } - #endif /* CONFIG_I2C_SLAVE */ - -+static inline u32 -+aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) -+{ -+ u32 command = 0; -+ int len; -+ -+ if (msg->len > bus->buf_size) { -+ len = bus->buf_size; -+ } else { -+ len = msg->len; -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } -+ -+ if (bus->buf_base) { -+ command |= ASPEED_I2CD_RX_BUFF_ENABLE; -+ -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ } -+ -+ return command; -+} -+ -+static inline u32 -+aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) -+{ -+ u8 slave_addr = i2c_8bit_addr_from_msg(msg); -+ u32 command = 0; -+ int len; -+ -+ if (msg->len + 1 > bus->buf_size) -+ len = bus->buf_size; -+ else -+ len = msg->len + 1; -+ -+ if (bus->buf_base) { -+ u8 wbuf[4]; -+ int i; -+ -+ command |= ASPEED_I2CD_TX_BUFF_ENABLE; -+ -+ /* -+ * Yeah, it looks bad but byte writing on remapped I2C SRAM -+ * causes corruption so use this way to make dword writings. -+ */ -+ wbuf[0] = slave_addr; -+ for (i = 1; i < len; i++) { -+ wbuf[i % 4] = msg->buf[i - 1]; -+ if (i % 4 == 3) -+ writel(*(u32 *)wbuf, bus->buf_base + i - 3); -+ } -+ if (--i % 4 != 3) -+ writel(*(u32 *)wbuf, bus->buf_base + i - (i % 4)); -+ -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ } -+ -+ bus->buf_index = len - 1; -+ -+ return command; -+} -+ - /* precondition: bus.lock has been acquired. */ - static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) - { - u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD; - struct i2c_msg *msg = &bus->msgs[bus->msgs_index]; -- u8 slave_addr = i2c_8bit_addr_from_msg(msg); - - #if IS_ENABLED(CONFIG_I2C_SLAVE) - /* -@@ -374,12 +535,21 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) - - if (msg->flags & I2C_M_RD) { - command |= ASPEED_I2CD_M_RX_CMD; -- /* Need to let the hardware know to NACK after RX. */ -- if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN)) -- command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ if (!(msg->flags & I2C_M_RECV_LEN)) { -+ if (msg->len && bus->buf_base) -+ command |= aspeed_i2c_prepare_rx_buf(bus, msg); -+ -+ /* Need to let the hardware know to NACK after RX. */ -+ if (msg->len <= 1) -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } -+ } else if (msg->len && bus->buf_base) { -+ command |= aspeed_i2c_prepare_tx_buf(bus, msg); - } - -- writel(slave_addr, bus->base + ASPEED_I2C_BYTE_BUF_REG); -+ if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE)) -+ writel(i2c_8bit_addr_from_msg(msg), -+ bus->base + ASPEED_I2C_BYTE_BUF_REG); - writel(command, bus->base + ASPEED_I2C_CMD_REG); - } - -@@ -414,6 +584,104 @@ static int aspeed_i2c_is_irq_error(u32 irq_status) - return 0; - } - -+static inline u32 -+aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus, -+ struct i2c_msg *msg) -+{ -+ u32 command = 0; -+ -+ if (bus->buf_base) { -+ u8 wbuf[4]; -+ int len; -+ int i; -+ -+ if (msg->len - bus->buf_index > bus->buf_size) -+ len = bus->buf_size; -+ else -+ len = msg->len - bus->buf_index; -+ -+ -+ command |= ASPEED_I2CD_TX_BUFF_ENABLE; -+ -+ if (msg->len - bus->buf_index > bus->buf_size) -+ len = bus->buf_size; -+ else -+ len = msg->len - bus->buf_index; -+ -+ for (i = 0; i < len; i++) { -+ wbuf[i % 4] = msg->buf[bus->buf_index + i]; -+ if (i % 4 == 3) -+ writel(*(u32 *)wbuf, -+ bus->buf_base + i - 3); -+ } -+ if (--i % 4 != 3) -+ writel(*(u32 *)wbuf, -+ bus->buf_base + i - (i % 4)); -+ -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, -+ len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -+ bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ -+ bus->buf_index += len; -+ } else { -+ writel(msg->buf[bus->buf_index++], -+ bus->base + ASPEED_I2C_BYTE_BUF_REG); -+ } -+ -+ return command; -+} -+ -+static inline void -+aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) -+{ -+ u8 recv_byte; -+ int len; -+ -+ if (bus->buf_base) { -+ len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, -+ readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)); -+ memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len); -+ bus->buf_index += len; -+ } else { -+ recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; -+ msg->buf[bus->buf_index++] = recv_byte; -+ } -+} -+ -+static inline u32 -+aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, -+ struct i2c_msg *msg) -+{ -+ u32 command = 0; -+ -+ if (bus->buf_base) { -+ int len; -+ -+ if (msg->len - bus->buf_index > bus->buf_size) { -+ len = bus->buf_size; -+ } else { -+ len = msg->len - bus->buf_index; -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } -+ -+ command |= ASPEED_I2CD_RX_BUFF_ENABLE; -+ -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, -+ len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -+ bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ } else { -+ if (bus->buf_index + 1 == msg->len) -+ command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ } -+ -+ return command; -+} -+ - static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - { - u32 irq_handled = 0, command = 0; -@@ -522,11 +790,10 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - /* fall through */ - case ASPEED_I2C_MASTER_TX_FIRST: - if (bus->buf_index < msg->len) { -+ command = ASPEED_I2CD_M_TX_CMD; -+ command |= aspeed_i2c_master_handle_tx_first(bus, msg); -+ writel(command, bus->base + ASPEED_I2C_CMD_REG); - bus->master_state = ASPEED_I2C_MASTER_TX; -- writel(msg->buf[bus->buf_index++], -- bus->base + ASPEED_I2C_BYTE_BUF_REG); -- writel(ASPEED_I2CD_M_TX_CMD, -- bus->base + ASPEED_I2C_CMD_REG); - } else { - aspeed_i2c_next_msg_or_stop(bus); - } -@@ -543,26 +810,26 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - } - irq_handled |= ASPEED_I2CD_INTR_RX_DONE; - -- recv_byte = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8; -- msg->buf[bus->buf_index++] = recv_byte; -- - if (msg->flags & I2C_M_RECV_LEN) { -+ recv_byte = readl(bus->base + -+ ASPEED_I2C_BYTE_BUF_REG) >> 8; - if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) { - bus->cmd_err = -EPROTO; - aspeed_i2c_do_stop(bus); - goto out_no_complete; - } -- msg->len = recv_byte + -- ((msg->flags & I2C_CLIENT_PEC) ? 2 : 1); -+ msg->len = recv_byte + ((msg->flags & I2C_CLIENT_PEC) ? -+ 2 : 1); - msg->flags &= ~I2C_M_RECV_LEN; -+ } else if (msg->len) { -+ aspeed_i2c_master_handle_rx(bus, msg); - } - - if (bus->buf_index < msg->len) { -- bus->master_state = ASPEED_I2C_MASTER_RX; - command = ASPEED_I2CD_M_RX_CMD; -- if (bus->buf_index + 1 == msg->len) -- command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -+ command |= aspeed_i2c_master_handle_rx_next(bus, msg); - writel(command, bus->base + ASPEED_I2C_CMD_REG); -+ bus->master_state = ASPEED_I2C_MASTER_RX; - } else { - aspeed_i2c_next_msg_or_stop(bus); - } -@@ -924,6 +1191,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus, - if (ret < 0) - return ret; - -+ fun_ctrl_reg |= FIELD_PREP(ASPEED_I2CD_BUFFER_PAGE_SEL_MASK, -+ bus->buf_page); -+ - if (of_property_read_bool(pdev->dev.of_node, "multi-master")) - bus->multi_master = true; - else -@@ -964,6 +1234,52 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus) - return ret; - } - -+static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus) -+{ -+ struct platform_device *pdev = to_platform_device(bus->dev); -+ bool sram_enabled = true; -+ int ret; -+ -+ /* -+ * Enable I2C SRAM in case of AST2500. -+ * SRAM is enabled by default in AST2400 and AST2600. -+ */ -+ if (of_device_is_compatible(pdev->dev.of_node, -+ "aspeed,ast2500-i2c-bus")) { -+ struct regmap *gr_regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2500-i2c-gr"); -+ -+ if (IS_ERR(gr_regmap)) -+ ret = PTR_ERR(gr_regmap); -+ else -+ ret = regmap_update_bits(gr_regmap, -+ ASPEED_I2CG_GLOBAL_CTRL_REG, -+ ASPEED_I2CG_SRAM_BUFFER_EN, -+ ASPEED_I2CG_SRAM_BUFFER_EN); -+ -+ if (ret) -+ sram_enabled = false; -+ } -+ -+ if (sram_enabled) { -+ struct resource *res = platform_get_resource(pdev, -+ IORESOURCE_MEM, 1); -+ -+ if (res && resource_size(res) >= 2) -+ bus->buf_base = devm_ioremap_resource(&pdev->dev, res); -+ -+ if (!IS_ERR_OR_NULL(bus->buf_base)) { -+ bus->buf_size = resource_size(res); -+ if (of_device_is_compatible(pdev->dev.of_node, -+ "aspeed,ast2400-i2c-bus")) { -+ bus->buf_page = ((res->start >> 8) & -+ GENMASK(3, 0)) - 8; -+ bus->buf_offset = (res->start >> 2) & -+ ASPEED_I2CD_BUF_OFFSET_MASK; -+ } -+ } -+ } -+} -+ - static const struct of_device_id aspeed_i2c_bus_of_table[] = { - { - .compatible = "aspeed,ast2400-i2c-bus", -@@ -986,18 +1302,18 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - const struct of_device_id *match; - struct aspeed_i2c_bus *bus; - struct clk *parent_clk; -- struct resource *res; - int irq, ret; - - bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL); - if (!bus) - return -ENOMEM; - -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- bus->base = devm_ioremap_resource(&pdev->dev, res); -+ bus->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(bus->base)) - return PTR_ERR(bus->base); - -+ bus->dev = &pdev->dev; -+ - parent_clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(parent_clk)) - return PTR_ERR(parent_clk); -@@ -1028,6 +1344,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - bus->get_clk_reg_val = (u32 (*)(struct device *, u32)) - match->data; - -+ aspeed_i2c_set_xfer_mode(bus); -+ - /* Initialize the I2C adapter */ - spin_lock_init(&bus->lock); - init_completion(&bus->cmd_complete); -@@ -1038,8 +1356,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name)); - i2c_set_adapdata(&bus->adap, bus); - -- bus->dev = &pdev->dev; -- - /* Clean up any left over interrupt state. */ - writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG); - writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG); -@@ -1063,8 +1379,8 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - - platform_set_drvdata(pdev, bus); - -- dev_info(bus->dev, "i2c bus %d registered, irq %d\n", -- bus->adap.nr, irq); -+ dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n", -+ bus->adap.nr, bus->buf_base ? "buffer" : "byte", irq); - - return 0; - } --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch deleted file mode 100644 index 994c20b18..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0062-i2c-aspeed-add-DMA-mode-transfer-support.patch +++ /dev/null @@ -1,491 +0,0 @@ -From 5bf7a202eb0af455675a85a4f1bdad863fd8805d Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 18 Jun 2019 08:47:50 -0700 -Subject: [PATCH] i2c: aspeed: add DMA mode transfer support - -This commit adds DMA mode transfer support. - -Only AST2500 supports DMA mode under some limitations: -I2C is sharing the DMA H/W with UHCI host controller and MCTP -controller. Since those controllers operate with DMA mode only, I2C -has to use buffer mode or byte mode instead if one of those -controllers is enabled. Also make sure that if SD/eMMC or Port80 -snoop uses DMA mode instead of PIO or FIFO respectively, I2C can't -use DMA mode. - -Signed-off-by: Jae Hyun Yoo ---- - .../devicetree/bindings/i2c/i2c-aspeed.txt | 25 ++ - drivers/i2c/busses/i2c-aspeed.c | 253 +++++++++++++++++---- - 2 files changed, 234 insertions(+), 44 deletions(-) - -diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -index 0ff3539cee95..d3f4a39f7ba6 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -@@ -22,6 +22,16 @@ Optional Properties: - - bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not - specified. - - #retries : Number of retries for master transfer. -+- aspeed,dma-buf-size : size of DMA buffer (from 2 to 4095 in case of AST2500) -+ Only AST2500 supports DMA mode under some limitations: -+ I2C is sharing the DMA H/W with UHCI host controller -+ and MCTP controller. Since those controllers operate -+ with DMA mode only, I2C has to use buffer mode or byte -+ mode instead if one of those controllers is enabled. -+ Also make sure that if SD/eMMC or Port80 snoop uses -+ DMA mode instead of PIO or FIFO respectively, I2C -+ can't use DMA mode. IF both DMA and buffer modes are -+ enabled, DMA mode will be selected. - - Example: - -@@ -74,4 +84,19 @@ i2c { - interrupts = <1>; - interrupt-parent = <&i2c_ic>; - }; -+ -+ /* DMA mode transfer enabled */ -+ i2c2: i2c-bus@c0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #interrupt-cells = <1>; -+ reg = <0xc0 0x40>; -+ aspeed,dma-buf-size = <4095>; -+ compatible = "aspeed,ast2500-i2c-bus"; -+ clocks = <&syscon ASPEED_CLK_APB>; -+ resets = <&syscon ASPEED_RESET_I2C>; -+ bus-frequency = <100000>; -+ interrupts = <2>; -+ interrupt-parent = <&i2c_ic>; -+ }; - }; -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index bf72e151d11f..3c9e491cbe4e 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -10,6 +10,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -47,6 +49,8 @@ - #define ASPEED_I2C_DEV_ADDR_REG 0x18 - #define ASPEED_I2C_BUF_CTRL_REG 0x1c - #define ASPEED_I2C_BYTE_BUF_REG 0x20 -+#define ASPEED_I2C_DMA_ADDR_REG 0x24 -+#define ASPEED_I2C_DMA_LEN_REG 0x28 - - /* Device Register Definition */ - /* 0x00 : I2CD Function Control Register */ -@@ -110,6 +114,8 @@ - #define ASPEED_I2CD_BUS_RECOVER_CMD BIT(11) - - /* Command Bit */ -+#define ASPEED_I2CD_RX_DMA_ENABLE BIT(9) -+#define ASPEED_I2CD_TX_DMA_ENABLE BIT(8) - #define ASPEED_I2CD_RX_BUFF_ENABLE BIT(7) - #define ASPEED_I2CD_TX_BUFF_ENABLE BIT(6) - #define ASPEED_I2CD_M_STOP_CMD BIT(5) -@@ -135,6 +141,14 @@ - #define ASPEED_I2CD_BUF_TX_COUNT_MASK GENMASK(15, 8) - #define ASPEED_I2CD_BUF_OFFSET_MASK GENMASK(5, 0) - -+/* 0x24 : I2CD DMA Mode Buffer Address Register */ -+#define ASPEED_I2CD_DMA_ADDR_MASK GENMASK(31, 2) -+#define ASPEED_I2CD_DMA_ALIGN 4 -+ -+/* 0x28 : I2CD DMA Transfer Length Register */ -+#define ASPEED_I2CD_DMA_LEN_SHIFT 0 -+#define ASPEED_I2CD_DMA_LEN_MASK GENMASK(11, 0) -+ - enum aspeed_i2c_master_state { - ASPEED_I2C_MASTER_INACTIVE, - ASPEED_I2C_MASTER_PENDING, -@@ -184,6 +198,12 @@ struct aspeed_i2c_bus { - void __iomem *buf_base; - u8 buf_offset; - u8 buf_page; -+ /* DMA mode */ -+ struct dma_pool *dma_pool; -+ dma_addr_t dma_handle; -+ u8 *dma_buf; -+ size_t dma_len; -+ /* Buffer/DMA mode */ - size_t buf_size; - #if IS_ENABLED(CONFIG_I2C_SLAVE) - struct i2c_client *slave; -@@ -281,7 +301,11 @@ static inline void - aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status, - u8 *value) - { -- if (bus->buf_base && -+ if (bus->dma_buf && -+ bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && -+ !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) -+ *value = bus->dma_buf[0]; -+ else if (bus->buf_base && - bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && - !(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP)) - *value = readb(bus->buf_base); -@@ -297,7 +321,18 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, - - if (bus->slave_state == ASPEED_I2C_SLAVE_WRITE_RECEIVED && - irq_status & ASPEED_I2CD_INTR_RX_DONE) { -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ len = bus->buf_size - -+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, -+ readl(bus->base + -+ ASPEED_I2C_DMA_LEN_REG)); -+ for (i = 0; i < len; i++) { -+ *value = bus->dma_buf[i]; -+ i2c_slave_event(bus->slave, -+ I2C_SLAVE_WRITE_RECEIVED, -+ value); -+ } -+ } else if (bus->buf_base) { - len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, - readl(bus->base + - ASPEED_I2C_BUF_CTRL_REG)); -@@ -314,7 +349,14 @@ aspeed_i2c_slave_handle_normal_stop(struct aspeed_i2c_bus *bus, u32 irq_status, - static inline void - aspeed_i2c_slave_handle_write_requested(struct aspeed_i2c_bus *bus, u8 *value) - { -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ writel(ASPEED_I2CD_RX_DMA_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); -+ } else if (bus->buf_base) { - writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, - bus->buf_size - 1) | - FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -@@ -330,7 +372,23 @@ aspeed_i2c_slave_handle_write_received(struct aspeed_i2c_bus *bus, u8 *value) - { - int i, len; - -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ len = bus->buf_size - -+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, -+ readl(bus->base + -+ ASPEED_I2C_DMA_LEN_REG)); -+ for (i = 1; i < len; i++) { -+ *value = bus->dma_buf[i]; -+ i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED, -+ value); -+ } -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, bus->buf_size), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ writel(ASPEED_I2CD_RX_DMA_ENABLE, -+ bus->base + ASPEED_I2C_CMD_REG); -+ } else if (bus->buf_base) { - len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, - readl(bus->base + - ASPEED_I2C_BUF_CTRL_REG)); -@@ -460,7 +518,15 @@ aspeed_i2c_prepare_rx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) - command |= ASPEED_I2CD_M_S_RX_CMD_LAST; - } - -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_RX_DMA_ENABLE; -+ -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else { - command |= ASPEED_I2CD_RX_BUFF_ENABLE; - - writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, len - 1) | -@@ -483,7 +549,18 @@ aspeed_i2c_prepare_tx_buf(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) - else - len = msg->len + 1; - -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_TX_DMA_ENABLE; -+ -+ bus->dma_buf[0] = slave_addr; -+ memcpy(bus->dma_buf + 1, msg->buf, len); -+ -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else { - u8 wbuf[4]; - int i; - -@@ -536,18 +613,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) - if (msg->flags & I2C_M_RD) { - command |= ASPEED_I2CD_M_RX_CMD; - if (!(msg->flags & I2C_M_RECV_LEN)) { -- if (msg->len && bus->buf_base) -+ if (msg->len && (bus->dma_buf || bus->buf_base)) - command |= aspeed_i2c_prepare_rx_buf(bus, msg); - - /* Need to let the hardware know to NACK after RX. */ - if (msg->len <= 1) - command |= ASPEED_I2CD_M_S_RX_CMD_LAST; - } -- } else if (msg->len && bus->buf_base) { -+ } else if (msg->len && (bus->dma_buf || bus->buf_base)) { - command |= aspeed_i2c_prepare_tx_buf(bus, msg); - } - -- if (!(command & ASPEED_I2CD_TX_BUFF_ENABLE)) -+ if (!(command & (ASPEED_I2CD_TX_BUFF_ENABLE | -+ ASPEED_I2CD_TX_DMA_ENABLE))) - writel(i2c_8bit_addr_from_msg(msg), - bus->base + ASPEED_I2C_BYTE_BUF_REG); - writel(command, bus->base + ASPEED_I2C_CMD_REG); -@@ -590,39 +668,52 @@ aspeed_i2c_master_handle_tx_first(struct aspeed_i2c_bus *bus, - { - u32 command = 0; - -- if (bus->buf_base) { -- u8 wbuf[4]; -+ if (bus->dma_buf || bus->buf_base) { - int len; -- int i; - - if (msg->len - bus->buf_index > bus->buf_size) - len = bus->buf_size; - else - len = msg->len - bus->buf_index; - -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_TX_DMA_ENABLE; - -- command |= ASPEED_I2CD_TX_BUFF_ENABLE; -+ memcpy(bus->dma_buf, msg->buf + bus->buf_index, len); - -- if (msg->len - bus->buf_index > bus->buf_size) -- len = bus->buf_size; -- else -- len = msg->len - bus->buf_index; - -- for (i = 0; i < len; i++) { -- wbuf[i % 4] = msg->buf[bus->buf_index + i]; -- if (i % 4 == 3) -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else { -+ u8 wbuf[4]; -+ int i; -+ -+ command |= ASPEED_I2CD_TX_BUFF_ENABLE; -+ -+ if (msg->len - bus->buf_index > bus->buf_size) -+ len = bus->buf_size; -+ else -+ len = msg->len - bus->buf_index; -+ -+ for (i = 0; i < len; i++) { -+ wbuf[i % 4] = msg->buf[bus->buf_index + i]; -+ if (i % 4 == 3) -+ writel(*(u32 *)wbuf, -+ bus->buf_base + i - 3); -+ } -+ if (--i % 4 != 3) - writel(*(u32 *)wbuf, -- bus->buf_base + i - 3); -- } -- if (--i % 4 != 3) -- writel(*(u32 *)wbuf, -- bus->buf_base + i - (i % 4)); -+ bus->buf_base + i - (i % 4)); - -- writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, -- len - 1) | -- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -- bus->buf_offset), -- bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, -+ len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -+ bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ } - - bus->buf_index += len; - } else { -@@ -639,7 +730,14 @@ aspeed_i2c_master_handle_rx(struct aspeed_i2c_bus *bus, struct i2c_msg *msg) - u8 recv_byte; - int len; - -- if (bus->buf_base) { -+ if (bus->dma_buf) { -+ len = bus->dma_len - -+ FIELD_GET(ASPEED_I2CD_DMA_LEN_MASK, -+ readl(bus->base + ASPEED_I2C_DMA_LEN_REG)); -+ -+ memcpy(msg->buf + bus->buf_index, bus->dma_buf, len); -+ bus->buf_index += len; -+ } else if (bus->buf_base) { - len = FIELD_GET(ASPEED_I2CD_BUF_RX_COUNT_MASK, - readl(bus->base + ASPEED_I2C_BUF_CTRL_REG)); - memcpy_fromio(msg->buf + bus->buf_index, bus->buf_base, len); -@@ -656,7 +754,7 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, - { - u32 command = 0; - -- if (bus->buf_base) { -+ if (bus->dma_buf || bus->buf_base) { - int len; - - if (msg->len - bus->buf_index > bus->buf_size) { -@@ -666,14 +764,24 @@ aspeed_i2c_master_handle_rx_next(struct aspeed_i2c_bus *bus, - command |= ASPEED_I2CD_M_S_RX_CMD_LAST; - } - -- command |= ASPEED_I2CD_RX_BUFF_ENABLE; -+ if (bus->dma_buf) { -+ command |= ASPEED_I2CD_RX_DMA_ENABLE; - -- writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, -- len - 1) | -- FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | -- FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -- bus->buf_offset), -- bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ writel(bus->dma_handle & ASPEED_I2CD_DMA_ADDR_MASK, -+ bus->base + ASPEED_I2C_DMA_ADDR_REG); -+ writel(FIELD_PREP(ASPEED_I2CD_DMA_LEN_MASK, len), -+ bus->base + ASPEED_I2C_DMA_LEN_REG); -+ bus->dma_len = len; -+ } else { -+ command |= ASPEED_I2CD_RX_BUFF_ENABLE; -+ -+ writel(FIELD_PREP(ASPEED_I2CD_BUF_RX_SIZE_MASK, -+ len - 1) | -+ FIELD_PREP(ASPEED_I2CD_BUF_TX_COUNT_MASK, 0) | -+ FIELD_PREP(ASPEED_I2CD_BUF_OFFSET_MASK, -+ bus->buf_offset), -+ bus->base + ASPEED_I2C_BUF_CTRL_REG); -+ } - } else { - if (bus->buf_index + 1 == msg->len) - command |= ASPEED_I2CD_M_S_RX_CMD_LAST; -@@ -1260,7 +1368,51 @@ static void aspeed_i2c_set_xfer_mode(struct aspeed_i2c_bus *bus) - sram_enabled = false; - } - -- if (sram_enabled) { -+ /* -+ * Only AST2500 and AST2600 support DMA mode under some limitations: -+ * I2C is sharing the DMA H/W with UHCI host controller and MCTP -+ * controller. Since those controllers operate with DMA mode only, I2C -+ * has to use buffer mode or byte mode instead if one of those -+ * controllers is enabled. Also make sure that if SD/eMMC or Port80 -+ * snoop uses DMA mode instead of PIO or FIFO respectively, I2C can't -+ * use DMA mode. -+ */ -+ if (sram_enabled && !IS_ENABLED(CONFIG_USB_UHCI_ASPEED) && -+ !of_device_is_compatible(pdev->dev.of_node, -+ "aspeed,ast2400-i2c-bus")) { -+ u32 dma_len_max = ASPEED_I2CD_DMA_LEN_MASK >> -+ ASPEED_I2CD_DMA_LEN_SHIFT; -+ -+ ret = device_property_read_u32(&pdev->dev, -+ "aspeed,dma-buf-size", -+ &bus->buf_size); -+ if (!ret && bus->buf_size > dma_len_max) -+ bus->buf_size = dma_len_max; -+ } -+ -+ if (bus->buf_size) { -+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { -+ dev_warn(&pdev->dev, "No suitable DMA available\n"); -+ } else { -+ bus->dma_pool = dma_pool_create("i2c-aspeed", -+ &pdev->dev, -+ bus->buf_size, -+ ASPEED_I2CD_DMA_ALIGN, -+ 0); -+ if (bus->dma_pool) -+ bus->dma_buf = dma_pool_alloc(bus->dma_pool, -+ GFP_KERNEL, -+ &bus->dma_handle); -+ -+ if (!bus->dma_buf) { -+ dev_warn(&pdev->dev, -+ "Cannot allocate DMA buffer\n"); -+ dma_pool_destroy(bus->dma_pool); -+ } -+ } -+ } -+ -+ if (!bus->dma_buf && sram_enabled) { - struct resource *res = platform_get_resource(pdev, - IORESOURCE_MEM, 1); - -@@ -1365,24 +1517,33 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - */ - ret = aspeed_i2c_init(bus, pdev); - if (ret < 0) -- return ret; -+ goto out_free_dma_buf; - - irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq, - 0, dev_name(&pdev->dev), bus); - if (ret < 0) -- return ret; -+ goto out_free_dma_buf; - - ret = i2c_add_adapter(&bus->adap); - if (ret < 0) -- return ret; -+ goto out_free_dma_buf; - - platform_set_drvdata(pdev, bus); - - dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n", -- bus->adap.nr, bus->buf_base ? "buffer" : "byte", irq); -+ bus->adap.nr, bus->dma_buf ? "dma" : -+ bus->buf_base ? "buffer" : "byte", -+ irq); - - return 0; -+ -+out_free_dma_buf: -+ if (bus->dma_buf) -+ dma_pool_free(bus->dma_pool, bus->dma_buf, bus->dma_handle); -+ dma_pool_destroy(bus->dma_pool); -+ -+ return ret; - } - - static int aspeed_i2c_remove_bus(struct platform_device *pdev) -@@ -1400,6 +1561,10 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) - - reset_control_assert(bus->rst); - -+ if (bus->dma_buf) -+ dma_pool_free(bus->dma_pool, bus->dma_buf, bus->dma_handle); -+ dma_pool_destroy(bus->dma_pool); -+ - i2c_del_adapter(&bus->adap); - - return 0; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch deleted file mode 100644 index 899924f61..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0063-i2c-aspeed-add-general-call-support.patch +++ /dev/null @@ -1,180 +0,0 @@ -From d731b53de05b8d69ea739f02275416126cf5fe4e Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 1 May 2019 13:27:34 -0700 -Subject: [PATCH] i2c: aspeed: add general call support - -This commit adds general call support into Aspeed I2C driver. -This is downstream only customization so it should not go into -upstream. - -Signed-off-by: Jae Hyun Yoo ---- - .../devicetree/bindings/i2c/i2c-aspeed.txt | 1 + - drivers/i2c/busses/i2c-aspeed.c | 39 ++++++++++++++++++++++ - drivers/i2c/i2c-slave-mqueue.c | 4 ++- - include/linux/i2c.h | 1 + - 4 files changed, 44 insertions(+), 1 deletion(-) - -diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -index d3f4a39f7ba6..c1ee99398517 100644 ---- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt -@@ -19,6 +19,7 @@ Optional Properties: - - bus-frequency : frequency of the bus clock in Hz defaults to 100 kHz when not - specified - - multi-master : states that there is another master active on this bus. -+- general-call : enables general call receiving. - - bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not - specified. - - #retries : Number of retries for master transfer. -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 3c9e491cbe4e..4420899e2c2d 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -59,6 +59,7 @@ - #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8) - #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7) - #define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6) -+#define ASPEED_I2CD_GCALL_EN BIT(2) - #define ASPEED_I2CD_SLAVE_EN BIT(1) - #define ASPEED_I2CD_MASTER_EN BIT(0) - -@@ -83,6 +84,7 @@ - */ - #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) - #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) -+#define ASPEED_I2CD_INTR_GCALL_ADDR BIT(8) - #define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7) - #define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6) - #define ASPEED_I2CD_INTR_ABNORMAL BIT(5) -@@ -167,6 +169,8 @@ enum aspeed_i2c_slave_state { - ASPEED_I2C_SLAVE_READ_PROCESSED, - ASPEED_I2C_SLAVE_WRITE_REQUESTED, - ASPEED_I2C_SLAVE_WRITE_RECEIVED, -+ ASPEED_I2C_SLAVE_GCALL_START, -+ ASPEED_I2C_SLAVE_GCALL_REQUESTED, - ASPEED_I2C_SLAVE_STOP, - }; - -@@ -208,6 +212,8 @@ struct aspeed_i2c_bus { - #if IS_ENABLED(CONFIG_I2C_SLAVE) - struct i2c_client *slave; - enum aspeed_i2c_slave_state slave_state; -+ /* General call */ -+ bool general_call; - #endif /* CONFIG_I2C_SLAVE */ - }; - -@@ -423,6 +429,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - bus->slave_state = ASPEED_I2C_SLAVE_START; - } - -+ /* General call was requested, restart state machine. */ -+ if (irq_status & ASPEED_I2CD_INTR_GCALL_ADDR) { -+ irq_handled |= ASPEED_I2CD_INTR_GCALL_ADDR; -+ bus->slave_state = ASPEED_I2C_SLAVE_GCALL_START; -+ } -+ - /* Slave is not currently active, irq was for someone else. */ - if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) - return irq_handled; -@@ -441,6 +453,21 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - else - bus->slave_state = - ASPEED_I2C_SLAVE_WRITE_REQUESTED; -+ } else if (bus->slave_state == ASPEED_I2C_SLAVE_GCALL_START) { -+ /* -+ * I2C spec defines the second byte meaning like below. -+ * 0x06 : Reset and write programmable part of slave -+ * address by hardware. -+ * 0x04 : Write programmable part of slave address by -+ * hardware. -+ * 0x00 : No allowed. -+ * -+ * But in OpenBMC, we are going to use this -+ * 'General call' feature for IPMB message broadcasting -+ * so it delivers all data as is without any specific -+ * handling of the second byte. -+ */ -+ bus->slave_state = ASPEED_I2C_SLAVE_GCALL_REQUESTED; - } - irq_handled |= ASPEED_I2CD_INTR_RX_DONE; - } -@@ -487,11 +514,16 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); - aspeed_i2c_slave_handle_write_received(bus, &value); - break; -+ case ASPEED_I2C_SLAVE_GCALL_REQUESTED: -+ bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED; -+ i2c_slave_event(slave, I2C_SLAVE_GCALL_REQUESTED, &value); -+ break; - case ASPEED_I2C_SLAVE_STOP: - i2c_slave_event(slave, I2C_SLAVE_STOP, &value); - bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; - break; - case ASPEED_I2C_SLAVE_START: -+ case ASPEED_I2C_SLAVE_GCALL_START: - /* Slave was just started. Waiting for the next event. */; - break; - default: -@@ -1127,6 +1159,8 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr) - /* Turn on slave mode. */ - func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG); - func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN; -+ if (bus->general_call) -+ func_ctrl_reg_val |= ASPEED_I2CD_GCALL_EN; - writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG); - } - -@@ -1165,6 +1199,8 @@ static int aspeed_i2c_unreg_slave(struct i2c_client *client) - /* Turn off slave mode. */ - func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG); - func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN; -+ if (bus->general_call) -+ func_ctrl_reg_val &= ~ASPEED_I2CD_GCALL_EN; - writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG); - - bus->slave = NULL; -@@ -1312,6 +1348,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus, - bus->base + ASPEED_I2C_FUN_CTRL_REG); - - #if IS_ENABLED(CONFIG_I2C_SLAVE) -+ if (of_property_read_bool(pdev->dev.of_node, "general-call")) -+ bus->general_call = true; -+ - /* If slave has already been registered, re-enable it. */ - if (bus->slave) - __aspeed_i2c_reg_slave(bus, bus->slave->addr); -diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c -index 2c7a6038409c..1d4db584b393 100644 ---- a/drivers/i2c/i2c-slave-mqueue.c -+++ b/drivers/i2c/i2c-slave-mqueue.c -@@ -56,10 +56,12 @@ static int i2c_slave_mqueue_callback(struct i2c_client *client, - - switch (event) { - case I2C_SLAVE_WRITE_REQUESTED: -+ case I2C_SLAVE_GCALL_REQUESTED: - mq->truncated = 0; - - msg->len = 1; -- msg->buf[0] = client->addr << 1; -+ msg->buf[0] = event == I2C_SLAVE_GCALL_REQUESTED ? -+ 0 : client->addr << 1; - break; - - case I2C_SLAVE_WRITE_RECEIVED: -diff --git a/include/linux/i2c.h b/include/linux/i2c.h -index b4055d133338..52369ea150b4 100644 ---- a/include/linux/i2c.h -+++ b/include/linux/i2c.h -@@ -365,6 +365,7 @@ enum i2c_slave_event { - I2C_SLAVE_WRITE_REQUESTED, - I2C_SLAVE_READ_PROCESSED, - I2C_SLAVE_WRITE_RECEIVED, -+ I2C_SLAVE_GCALL_REQUESTED, - I2C_SLAVE_STOP, - }; - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch deleted file mode 100644 index 925880eff..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0064-set-idle-disconnect-to-true-in-all-cases.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 7854a5e094ac49bebf9b2bfdd44db2f8cdd37543 Mon Sep 17 00:00:00 2001 -From: James Feist -Date: Fri, 31 May 2019 15:05:13 -0700 -Subject: [PATCH] set idle-disconnect to true in all cases - -From sysfs this parameter can't be set. We want the -muxes to clean themselves up if possible. Set this to -true. - -Signed-off-by: James Feist ---- - drivers/i2c/muxes/i2c-mux-pca954x.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c -index 923aa3a5a3dc..084c10951890 100644 ---- a/drivers/i2c/muxes/i2c-mux-pca954x.c -+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c -@@ -474,8 +474,12 @@ static int pca954x_probe(struct i2c_client *client, - data->last_chan = 0; /* force the first selection */ - data->idle_state = MUX_IDLE_AS_IS; - -+#if 1 /* Forcibly set the self-disconnect flag */ -+ idle_disconnect_dt = true; -+#else - idle_disconnect_dt = np && - of_property_read_bool(np, "i2c-mux-idle-disconnect"); -+#endif - if (idle_disconnect_dt) - data->idle_state = MUX_IDLE_DISCONNECT; - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch deleted file mode 100644 index 0e8a2b101..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch +++ /dev/null @@ -1,191 +0,0 @@ -From b429cf11ecb2f6009dd9e062ea5e053718802d93 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 11 Jul 2019 13:53:34 -0700 -Subject: [PATCH] i2c: aspeed: add H/W timeout support - -This commit adds I2C H/W timeout support. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 82 ++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 76 insertions(+), 6 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 4420899e2c2d..830b3d2cabad 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -55,6 +55,7 @@ - /* Device Register Definition */ - /* 0x00 : I2CD Function Control Register */ - #define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20) -+#define ASPEED_I2CD_BUS_AUTO_RECOVERY_EN BIT(17) - #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15) - #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8) - #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7) -@@ -71,10 +72,14 @@ - #define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16) - #define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12 - #define ASPEED_I2CD_TIME_SCL_LOW_MASK GENMASK(15, 12) -+#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT 8 -+#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK GENMASK(9, 8) - #define ASPEED_I2CD_TIME_BASE_DIVISOR_MASK GENMASK(3, 0) - #define ASPEED_I2CD_TIME_SCL_REG_MAX GENMASK(3, 0) -+ - /* 0x08 : I2CD Clock and AC Timing Control Register #2 */ --#define ASPEED_NO_TIMEOUT_CTRL 0 -+#define ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT 0 -+#define ASPEED_I2CD_TIMEOUT_CYCLES_MASK GENMASK(4, 0) - - /* 0x0c : I2CD Interrupt Control Register & - * 0x10 : I2CD Interrupt Status Register -@@ -82,6 +87,7 @@ - * These share bit definitions, so use the same values for the enable & - * status bits. - */ -+#define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15) - #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) - #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) - #define ASPEED_I2CD_INTR_GCALL_ADDR BIT(8) -@@ -98,8 +104,11 @@ - ASPEED_I2CD_INTR_SCL_TIMEOUT | \ - ASPEED_I2CD_INTR_ABNORMAL | \ - ASPEED_I2CD_INTR_ARBIT_LOSS) -+#define ASPEED_I2CD_INTR_SLAVE_ERRORS \ -+ ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT - #define ASPEED_I2CD_INTR_ALL \ -- (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \ -+ (ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT | \ -+ ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \ - ASPEED_I2CD_INTR_BUS_RECOVER_DONE | \ - ASPEED_I2CD_INTR_SCL_TIMEOUT | \ - ASPEED_I2CD_INTR_ABNORMAL | \ -@@ -186,6 +195,7 @@ struct aspeed_i2c_bus { - u32 divisor); - unsigned long parent_clk_frequency; - u32 bus_frequency; -+ u32 hw_timeout_ms; - /* Transaction state. */ - enum aspeed_i2c_master_state master_state; - struct i2c_msg *msgs; -@@ -303,6 +313,14 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) - } - - #if IS_ENABLED(CONFIG_I2C_SLAVE) -+static int aspeed_i2c_check_slave_error(u32 irq_status) -+{ -+ if (irq_status & ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT) -+ return -EIO; -+ -+ return 0; -+} -+ - static inline void - aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status, - u8 *value) -@@ -421,6 +439,14 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - if (!slave) - return 0; - -+ if (aspeed_i2c_check_slave_error(irq_status)) { -+ dev_dbg(bus->dev, "received slave error interrupt: 0x%08x\n", -+ irq_status); -+ irq_handled |= (irq_status & ASPEED_I2CD_INTR_SLAVE_ERRORS); -+ bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; -+ return irq_handled; -+ } -+ - command = readl(bus->base + ASPEED_I2C_CMD_REG); - - /* Slave was requested, restart state machine. */ -@@ -681,7 +707,7 @@ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus) - } - } - --static int aspeed_i2c_is_irq_error(u32 irq_status) -+static int aspeed_i2c_check_master_error(u32 irq_status) - { - if (irq_status & ASPEED_I2CD_INTR_ARBIT_LOSS) - return -EAGAIN; -@@ -840,9 +866,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - * should clear the command queue effectively taking us back to the - * INACTIVE state. - */ -- ret = aspeed_i2c_is_irq_error(irq_status); -+ ret = aspeed_i2c_check_master_error(irq_status); - if (ret) { -- dev_dbg(bus->dev, "received error interrupt: 0x%08x\n", -+ dev_dbg(bus->dev, "received master error interrupt: 0x%08x\n", - irq_status); - irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS); - if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) { -@@ -1307,6 +1333,7 @@ static u32 aspeed_i2c_25xx_get_clk_reg_val(struct device *dev, u32 divisor) - /* precondition: bus.lock has been acquired. */ - static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus) - { -+ u32 timeout_base_divisor, timeout_tick_us, timeout_cycles; - u32 divisor, clk_reg_val; - - divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency); -@@ -1315,8 +1342,46 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus) - ASPEED_I2CD_TIME_THDSTA_MASK | - ASPEED_I2CD_TIME_TACST_MASK); - clk_reg_val |= bus->get_clk_reg_val(bus->dev, divisor); -+ -+ if (bus->hw_timeout_ms) { -+ u8 div_max = ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK >> -+ ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT; -+ u8 cycles_max = ASPEED_I2CD_TIMEOUT_CYCLES_MASK >> -+ ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT; -+ -+ timeout_base_divisor = 0; -+ -+ do { -+ timeout_tick_us = 1000 * (16384 << -+ (timeout_base_divisor << 1)) / -+ (bus->parent_clk_frequency / 1000); -+ -+ if (timeout_base_divisor == div_max || -+ timeout_tick_us * ASPEED_I2CD_TIMEOUT_CYCLES_MASK >= -+ bus->hw_timeout_ms * 1000) -+ break; -+ } while (timeout_base_divisor++ < div_max); -+ -+ if (timeout_tick_us) { -+ timeout_cycles = DIV_ROUND_UP(bus->hw_timeout_ms * 1000, -+ timeout_tick_us); -+ if (timeout_cycles == 0) -+ timeout_cycles = 1; -+ else if (timeout_cycles > cycles_max) -+ timeout_cycles = cycles_max; -+ } else { -+ timeout_cycles = 0; -+ } -+ } else { -+ timeout_base_divisor = 0; -+ timeout_cycles = 0; -+ } -+ -+ clk_reg_val |= FIELD_PREP(ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK, -+ timeout_base_divisor); -+ - writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1); -- writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2); -+ writel(timeout_cycles, bus->base + ASPEED_I2C_AC_TIMING_REG2); - - return 0; - } -@@ -1331,6 +1396,11 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus, - /* Disable everything. */ - writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG); - -+ device_property_read_u32(&pdev->dev, "aspeed,hw-timeout-ms", -+ &bus->hw_timeout_ms); -+ if (bus->hw_timeout_ms) -+ fun_ctrl_reg |= ASPEED_I2CD_BUS_AUTO_RECOVERY_EN; -+ - ret = aspeed_i2c_init_clk(bus); - if (ret < 0) - return ret; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch deleted file mode 100644 index 104279ace..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch +++ /dev/null @@ -1,50 +0,0 @@ -From b43bdeb5f3aa297549655e67f0e6a5db5f592e34 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 11 Jul 2019 14:04:39 -0700 -Subject: [PATCH] i2c: aspeed: add SLAVE_ADDR_RECEIVED_PENDING interrupt - handling - -If a peer master sends messages too quickly before it processes -previous slave DMA data handling, this indicator will be set. It's -just a indicator and driver can't recover this case so just ignore -it. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 830b3d2cabad..a308d5896632 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -87,6 +87,7 @@ - * These share bit definitions, so use the same values for the enable & - * status bits. - */ -+#define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(30) - #define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15) - #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) - #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) -@@ -468,6 +469,18 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n", - irq_status, command); - -+ /* -+ * If a peer master sends messages too quickly before it processes -+ * previous slave DMA data handling, this indicator will be set. It's -+ * just a indicator and driver can't recover this case so just ignore -+ * it. -+ */ -+ if (unlikely(irq_status & -+ ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING)) { -+ dev_dbg(bus->dev, "A slave addr match interrupt is pending.\n"); -+ irq_handled |= ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING; -+ } -+ - /* Slave was sent something. */ - if (irq_status & ASPEED_I2CD_INTR_RX_DONE) { - aspeed_i2c_slave_handle_rx_done(bus, irq_status, &value); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch deleted file mode 100644 index 5c3e35016..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0bda96c5fe3064c71f190bc484e2ce59c51d5585 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 19 Jul 2019 12:54:38 -0700 -Subject: [PATCH] gpio: aspeed: temporary fix for gpiochip range setting - -Since we are still using fixed indices for gpio line numbers for sysfs -interface, this commit set the gpiochip range as fixed temporariliy -til we replace all index based gpio uses with name based uses. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/gpio/gpio-aspeed.c | 2 +- - drivers/gpio/sgpio-aspeed.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c -index 39c50c53dae3..05945470bd89 100644 ---- a/drivers/gpio/gpio-aspeed.c -+++ b/drivers/gpio/gpio-aspeed.c -@@ -1181,7 +1181,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) - gpio->chip.set = aspeed_gpio_set; - gpio->chip.set_config = aspeed_gpio_set_config; - gpio->chip.label = dev_name(&pdev->dev); -- gpio->chip.base = -1; -+ gpio->chip.base = 0; - - /* Allocate a cache of the output registers */ - banks = DIV_ROUND_UP(gpio->chip.ngpio, 32); -diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c -index 5028e9144a75..850539da43f5 100644 ---- a/drivers/gpio/sgpio-aspeed.c -+++ b/drivers/gpio/sgpio-aspeed.c -@@ -681,7 +681,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) - gpio->chip.set = aspeed_sgpio_set; - gpio->chip.set_config = aspeed_sgpio_set_config; - gpio->chip.label = dev_name(&pdev->dev); -- gpio->chip.base = -1; -+ gpio->chip.base = gpio->config->nr_pgpios; - - rc = aspeed_sgpio_setup_irqs(gpio, pdev); - if (rc < 0) --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch deleted file mode 100644 index 40a9272e0..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0072-pmbus-add-fault-and-beep-attributes.patch +++ /dev/null @@ -1,88 +0,0 @@ -From e360a6c2a3f15bfc8900c7262c56f9bcd5e0f16e Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 8 Aug 2019 10:38:00 -0700 -Subject: [PATCH] pmbus: add 'fault' and 'beep' attributes - -This commit adds two more attirbutes to reflect MFR_SPECIFIC bit in -the STATUS_WORD and 'Unit Off For Insufficient Input Voltage' bit in -the STATUS_INPUT into 'fault' and 'beep' attributes respectively. - -The attributes will be enumerated as 'inX_fault' and 'inX_beep' in -a 'vin' group. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/hwmon/pmbus/pmbus.h | 1 + - drivers/hwmon/pmbus/pmbus_core.c | 30 ++++++++++++++++++++++++++++++ - 2 files changed, 31 insertions(+) - -diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h -index d198af3a92b6..09e6fe01c304 100644 ---- a/drivers/hwmon/pmbus/pmbus.h -+++ b/drivers/hwmon/pmbus/pmbus.h -@@ -303,6 +303,7 @@ enum pmbus_fan_mode { percent = 0, rpm }; - #define PB_PIN_OP_WARNING BIT(0) - #define PB_IIN_OC_WARNING BIT(1) - #define PB_IIN_OC_FAULT BIT(2) -+#define PB_UNIT_OFF_FOR_INSUF_VIN BIT(3) - - /* - * STATUS_TEMPERATURE -diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c -index 898d7378f4f8..85295a45c3ba 100644 ---- a/drivers/hwmon/pmbus/pmbus_core.c -+++ b/drivers/hwmon/pmbus/pmbus_core.c -@@ -1163,6 +1163,8 @@ struct pmbus_limit_attr { - struct pmbus_sensor_attr { - u16 reg; /* sensor register */ - u16 gbit; /* generic status bit */ -+ u16 gfbit; /* generic fault status bit */ -+ u16 sbbit; /* beep status bit */ - u8 nlimit; /* # of limit registers */ - enum pmbus_sensor_classes class;/* sensor class */ - const char *label; /* sensor label */ -@@ -1264,6 +1266,32 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, - return ret; - } - } -+ /* -+ * Add fault attribute if there is a generic fault bit, and if -+ * the generic status register (word or byte, depending on which global -+ * bit is set) for this page is accessible. -+ */ -+ if (attr->gfbit) { -+ upper = !!(attr->gfbit & 0xff00); /* need to check STATUS_WORD */ -+ if ((!upper || (upper && data->has_status_word)) && -+ pmbus_check_status_register(client, page)) { -+ ret = pmbus_add_boolean(data, name, "fault", index, -+ NULL, NULL, -+ PB_STATUS_BASE + page, -+ attr->gfbit); -+ if (ret) -+ return ret; -+ } -+ } -+ /* Add beep attribute if there is a beep status bit. */ -+ if (attr->sbbit) { -+ ret = pmbus_add_boolean(data, name, "beep", index, -+ NULL, NULL, -+ attr->sbase + page, -+ attr->sbbit); -+ if (ret) -+ return ret; -+ } - return 0; - } - -@@ -1435,6 +1463,8 @@ static const struct pmbus_sensor_attr voltage_attributes[] = { - .gbit = PB_STATUS_VIN_UV, - .limit = vin_limit_attrs, - .nlimit = ARRAY_SIZE(vin_limit_attrs), -+ .gfbit = PB_STATUS_WORD_MFR, -+ .sbbit = PB_UNIT_OFF_FOR_INSUF_VIN, - }, { - .reg = PMBUS_VIRT_READ_VMON, - .class = PSC_VOLTAGE_IN, --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch deleted file mode 100644 index 1056b3beb..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 5c82e0b33f2a373d5e19569635f108cfa096f53e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Adrian=20Ambro=C5=BCewicz?= -Date: Mon, 29 Jul 2019 10:19:00 +0200 -Subject: [PATCH] Add IO statistics to USB Mass storage gadget -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Introduces new attribute to Mass Storage Gadget ConfigFS : stats. -It's read-only attribute which contains statistics of read/write operations -based on LUN transaction counters (IO number and bytes transferred). - -Goal is to provide a way to observe whether simulated device is actually -used by host. Statistics on hosted file / nbd level are not always viable -due to page cache having severe impact on actual IO statistics. -This attribute should provide information about host IO on USB Gadget as -close to endpoint as possible. - -Attribute is tied completely to configFS implementation and it's lifecycle -is managed by Kernel and user. Driver implements a handler which populates -output buffer on read. - -Tests performed: -- mounted USB Mass Storage gadget, new attribute showed up in gadget tree -- attribute was monitored for changes during IO performed on host machine -- removed device, attribute (along with other device attributes) was gone - -Signed-off-by: Adrian Ambrożewicz ---- - drivers/usb/gadget/function/f_mass_storage.c | 12 ++++++++++++ - drivers/usb/gadget/function/storage_common.c | 9 +++++++++ - drivers/usb/gadget/function/storage_common.h | 29 ++++++++++++++++++++++++++++ - 3 files changed, 50 insertions(+) - -diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c -index 7c96c4665178..ecc3c68a7882 100644 ---- a/drivers/usb/gadget/function/f_mass_storage.c -+++ b/drivers/usb/gadget/function/f_mass_storage.c -@@ -710,6 +710,8 @@ static int do_read(struct fsg_common *common) - amount_left -= nread; - common->residue -= nread; - -+ fsg_stats_rd_attempt(&curlun->stats, nread); -+ - /* - * Except at the end of the transfer, nread will be - * equal to the buffer size, which is divisible by the -@@ -907,6 +909,8 @@ static int do_write(struct fsg_common *common) - amount_left_to_write -= nwritten; - common->residue -= nwritten; - -+ fsg_stats_wr_attempt(&curlun->stats, nwritten); -+ - /* If an error occurred, report it and its position */ - if (nwritten < amount) { - curlun->sense_data = SS_WRITE_ERROR; -@@ -3122,6 +3126,13 @@ static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item, - - CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string); - -+static ssize_t fsg_lun_opts_stats_show(struct config_item *item, char *page) -+{ -+ return fsg_show_stats(to_fsg_lun_opts(item)->lun, page); -+} -+ -+CONFIGFS_ATTR_RO(fsg_lun_opts_, stats); -+ - static struct configfs_attribute *fsg_lun_attrs[] = { - &fsg_lun_opts_attr_file, - &fsg_lun_opts_attr_ro, -@@ -3129,6 +3140,7 @@ static struct configfs_attribute *fsg_lun_attrs[] = { - &fsg_lun_opts_attr_cdrom, - &fsg_lun_opts_attr_nofua, - &fsg_lun_opts_attr_inquiry_string, -+ &fsg_lun_opts_attr_stats, - NULL, - }; - -diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c -index f7e6c42558eb..2325b97961df 100644 ---- a/drivers/usb/gadget/function/storage_common.c -+++ b/drivers/usb/gadget/function/storage_common.c -@@ -371,6 +371,15 @@ ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf) - } - EXPORT_SYMBOL_GPL(fsg_show_inquiry_string); - -+ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf) -+{ -+ return sprintf(buf, "read cnt: %u\n" "read sum: %llu\n" -+ "write cnt: %u\n" "write sum: %llu\n", -+ curlun->stats.read.count, curlun->stats.read.bytes, -+ curlun->stats.write.count, curlun->stats.write.bytes); -+} -+EXPORT_SYMBOL_GPL(fsg_show_stats); -+ - /* - * The caller must hold fsg->filesem for reading when calling this function. - */ -diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h -index e5e3a2553aaa..447021ba821a 100644 ---- a/drivers/usb/gadget/function/storage_common.h -+++ b/drivers/usb/gadget/function/storage_common.h -@@ -95,6 +95,32 @@ do { \ - */ - #define INQUIRY_STRING_LEN ((size_t) (8 + 16 + 4 + 1)) - -+struct fsg_stats_cnt { -+ u64 bytes; -+ u32 count; -+}; -+ -+struct fsg_stats { -+ struct fsg_stats_cnt read; -+ struct fsg_stats_cnt write; -+}; -+ -+static inline void fsg_stats_update(struct fsg_stats_cnt *cnt, u64 diff) -+{ -+ cnt->count++; -+ cnt->bytes += diff; -+} -+ -+static inline void fsg_stats_wr_attempt(struct fsg_stats *stats, u64 b_written) -+{ -+ fsg_stats_update(&stats->write, b_written); -+} -+ -+static inline void fsg_stats_rd_attempt(struct fsg_stats *stats, u64 b_read) -+{ -+ fsg_stats_update(&stats->read, b_read); -+} -+ - struct fsg_lun { - struct file *filp; - loff_t file_length; -@@ -120,6 +146,8 @@ struct fsg_lun { - const char *name; /* "lun.name" */ - const char **name_pfx; /* "function.name" */ - char inquiry_string[INQUIRY_STRING_LEN]; -+ -+ struct fsg_stats stats; - }; - - static inline bool fsg_lun_is_open(struct fsg_lun *curlun) -@@ -213,6 +241,7 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, - ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf); - ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf); - ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf); -+ssize_t fsg_show_stats(struct fsg_lun *curlun, char *buf); - ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, - const char *buf, size_t count); - ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch deleted file mode 100644 index 52c3617d6..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0075-Refine-initialization-flow-in-I2C-driver.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 93ba2aeb9ad3899e2b72877daa47376a6bf192b6 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Mon, 23 Sep 2019 13:48:49 -0700 -Subject: [PATCH] Refine initialization flow in I2C driver - -Since we enabled I2C busses in u-boot, we need to disable the I2C -bus and clear all garbage interrupts when kernel probes the bus. -This commit refines the initialization flow by adding a bus reset -at the beginning of probe function and by moving bus init function -after interrupt handling setup. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 20 +++++++++----------- - 1 file changed, 9 insertions(+), 11 deletions(-) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index a308d5896632..b32611088c82 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -1588,6 +1588,11 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - - bus->dev = &pdev->dev; - -+ /* Disable bus and clean up any left over interrupt state. */ -+ writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG); -+ writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG); -+ writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG); -+ - parent_clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(parent_clk)) - return PTR_ERR(parent_clk); -@@ -1630,17 +1635,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name)); - i2c_set_adapdata(&bus->adap, bus); - -- /* Clean up any left over interrupt state. */ -- writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG); -- writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG); -- /* -- * bus.lock does not need to be held because the interrupt handler has -- * not been enabled yet. -- */ -- ret = aspeed_i2c_init(bus, pdev); -- if (ret < 0) -- goto out_free_dma_buf; -- - irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq, - 0, dev_name(&pdev->dev), bus); -@@ -1653,6 +1647,10 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) - - platform_set_drvdata(pdev, bus); - -+ ret = aspeed_i2c_init(bus, pdev); -+ if (ret < 0) -+ goto out_free_dma_buf; -+ - dev_info(bus->dev, "i2c bus %d registered (%s mode), irq %d\n", - bus->adap.nr, bus->dma_buf ? "dma" : - bus->buf_base ? "buffer" : "byte", --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch deleted file mode 100644 index 9515a1a89..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch +++ /dev/null @@ -1,1107 +0,0 @@ -From a17a084c4889dcc7cb43ef5f93032997cfcee4f0 Mon Sep 17 00:00:00 2001 -From: Vernon Mauery -Date: Fri, 27 Sep 2019 13:09:48 -0700 -Subject: [PATCH] arm: ast2600: add pwm_tacho driver from aspeed - -Add the pwm_tacho driver from Aspeed to get pwm working until an -upstream PWM/Tacho driver is available. This was copied from the v5.02 -BSP from Aspeed. - -Signed-off-by: Vernon Mauery ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 10 + - drivers/hwmon/Kconfig | 11 + - drivers/hwmon/Makefile | 1 + - drivers/hwmon/aspeed-g6-pwm-tacho.c | 1025 +++++++++++++++++++++++++++++++++++ - 4 files changed, 1047 insertions(+) - create mode 100644 drivers/hwmon/aspeed-g6-pwm-tacho.c - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index eeace4b7b725..33fcd89db6b8 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -278,6 +278,16 @@ - #size-cells = <1>; - ranges; - -+ pwm_tacho: pwm-tacho-controller@1e610000 { -+ compatible = "aspeed,ast2600-pwm-tacho"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1e610000 0x100>; -+ clocks = <&syscon ASPEED_CLK_AHB>; -+ resets = <&syscon ASPEED_RESET_PWM>; -+ status = "disabled"; -+ }; -+ - syscon: syscon@1e6e2000 { - compatible = "aspeed,ast2600-scu", "syscon", "simple-mfd"; - reg = <0x1e6e2000 0x1000>; -diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index e244a7901392..8312b3798b82 100644 ---- a/drivers/hwmon/Kconfig -+++ b/drivers/hwmon/Kconfig -@@ -371,6 +371,17 @@ config SENSORS_ASPEED - This driver can also be built as a module. If so, the module - will be called aspeed_pwm_tacho. - -+config SENSORS_ASPEED_G6 -+ tristate "ASPEED AST2600 PWM and Fan tach driver" -+ depends on THERMAL || THERMAL=n -+ select REGMAP -+ help -+ This driver provides support for ASPEED AST2600 PWM -+ and Fan Tacho controllers. -+ -+ This driver can also be built as a module. If so, the module -+ will be called aspeed_g6_pwm_tacho. -+ - config SENSORS_ATXP1 - tristate "Attansic ATXP1 VID controller" - depends on I2C -diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 1c7ab361adc7..e74ea925fb56 100644 ---- a/drivers/hwmon/Makefile -+++ b/drivers/hwmon/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o - obj-$(CONFIG_SENSORS_AS370) += as370-hwmon.o - obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o - obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o -+obj-$(CONFIG_SENSORS_ASPEED_G6) += aspeed-g6-pwm-tacho.o - obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o - obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o - obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o -diff --git a/drivers/hwmon/aspeed-g6-pwm-tacho.c b/drivers/hwmon/aspeed-g6-pwm-tacho.c -new file mode 100644 -index 000000000000..1894f6ad5edb ---- /dev/null -+++ b/drivers/hwmon/aspeed-g6-pwm-tacho.c -@@ -0,0 +1,1025 @@ -+/* -+ * Copyright (C) ASPEED Technology Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 or later as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ASPEED_PWM_CTRL 0x00 //PWM0 General Register -+#define ASPEED_PWM_CTRL_CH(x) ((x * 0x10) + 0x00) -+#define PWM_LOAD_AS_WDT BIT(19) //load selection as WDT -+#define PWM_DUTY_LOAD_AS_WDT_EN BIT(18) //enable PWM duty load as WDT -+#define PWM_DUTY_SYNC_DIS BIT(17) //disable PWM duty sync -+#define PWM_CLK_ENABLE BIT(16) //enable PWM clock -+#define PWM_LEVEL_OUTPUT BIT(15) //output PWM level -+#define PWM_INVERSE BIT(14) //inverse PWM pin -+#define PWM_OPEN_DRAIN_EN BIT(13) //enable open-drain -+#define PWM_PIN_EN BIT(12) //enable PWM pin -+#define PWM_CLK_DIV_H_MASK (0xf << 8) //PWM clock division H bit [3:0] -+#define PWM_CLK_DIV_L_MASK (0xff) //PWM clock division H bit [3:0] -+ -+/* -+\xregmid {11:8 }{RW}{PWM clock division H bit [3:0]}{ -+ 0: divide 1 \n -+ 1: divide 2 \n -+ 2: divide 4 \n -+ 3: divide 8 \n -+ ... \n -+ F: divide 32768} -+\xregmid {7 :0 }{RW}{PWM clock division L bit [7:0]}{ -+ 00: divide 1 \n -+ 01: divide 2 \n -+ 02: divide 3 \n -+ 03: divide 4 \n -+ ... \n -+ FF: divide 256} -+*/ -+ -+#define ASPEED_PWM_DUTY_CYCLE 0x04 //PWM0 Duty Cycle Register -+#define ASPEED_PWM_DUTY_CYCLE_CH(x) ((x * 0x10) + 0x04) -+#define PWM_LOOP_BIT_MASK (0xf << 24) //loop bit [7:0] -+#define PWM_PERIOD_BIT (24) //pwm period bit [7:0] -+#define PWM_PERIOD_BIT_MASK (0xff << 24) //pwm period bit [7:0] -+#define PWM_RISING_FALLING_AS_WDT_BIT (16) -+#define PWM_RISING_FALLING_AS_WDT_MASK (0xff << 16) //pwm rising/falling point bit [7:0] as WDT -+#define PWM_RISING_FALLING_MASK (0xffff) -+#define PWM_RISING_FALLING_BIT (8) //pwm falling point bit [7:0] -+#define PWM_RISING_RISING_BIT (0) //pwm rising point bit [7:0] -+ -+#define ASPEED_TACHO_CTRL 0x08 //TACH0 General Register -+#define ASPEED_TACHO_CTRL_CH(x) ((x * 0x10) + 0x08) -+#define TACHO_IER BIT(31) //enable tacho interrupt -+#define TACHO_INVERS_LIMIT BIT(30) //inverse tacho limit comparison -+#define TACHO_LOOPBACK BIT(29) //tacho loopback -+#define TACHO_ENABLE BIT(28) //{enable tacho} -+#define TACHO_DEBOUNCE_BIT (26) //{tacho de-bounce} -+#define TACHO_DEBOUNCE_MASK (0x3 << 26) //{tacho de-bounce} -+#define TECHIO_EDGE_MASK (0x3 << 24) //tacho edge} -+#define TECHIO_EDGE_BIT (24) //tacho edge} -+#define TACHO_CLK_DIV_T_MASK (0xf << 20) -+#define TACHO_CLK_DIV_BIT (20) -+#define TACHO_THRESHOLD_MASK (0xfffff) //tacho threshold bit -+/* -+\xregmid {23:20}{RW}{tacho clock division T bit [3:0]}{ -+ 0: divide 1 \n -+ 1: divide 4 \n -+ 2: divide 16 \n -+ 3: divide 64 \n -+ ... \n -+ B: divide 4194304 \n -+ others: reserved} -+\xregmidb{19 :0 }{RW}{tacho threshold bit [19:0]} -+*/ -+ -+#define ASPEED_TACHO_STS 0x0C //TACH0 Status Register -+#define ASPEED_TACHO_STS_CH(x) ((x * 0x10) + 0x0C) -+#define TACHO_ISR BIT(31) //interrupt status and clear -+#define PWM_OUT BIT(25) //{pwm_out} -+#define PWM_OEN BIT(24) //{pwm_oeN} -+#define TACHO_DEB_INPUT BIT(23) //tacho deB input -+#define TACHO_RAW_INPUT BIT(22) //tacho raw input} -+#define TACHO_VALUE_UPDATE BIT(21) //tacho value updated since the last read -+#define TACHO_FULL_MEASUREMENT BIT(20) //{tacho full measurement} -+#define TACHO_VALUE_MASK 0xfffff //tacho value bit [19:0]} -+ -+#define MAX_CDEV_NAME_LEN 16 -+ -+struct aspeed_pwm_channel_params { -+ int load_wdt_rising_falling_pt; -+ int load_wdt_selection; //0: rising , 1: falling -+ int load_wdt_enable; -+ int duty_sync_enable; -+ int invert_pin; -+ u8 divide_h; -+ u8 divide_l; -+ u8 period; -+ u8 rising; -+ u8 falling; -+}; -+ -+static struct aspeed_pwm_channel_params default_pwm_params[] = { -+ [0] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 1, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [1] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [2] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [3] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [4] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [5] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [6] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [7] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [8] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [9] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [10] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [11] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [12] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [13] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [14] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+ [15] = { -+ .load_wdt_rising_falling_pt = 0x10, -+ .load_wdt_selection = 0, -+ .load_wdt_enable = 0, -+ .duty_sync_enable = 0, -+ .invert_pin = 0, -+ .divide_h = 0x5, -+ .divide_l = 0x6, -+ .period = 0x13, //5% ~~ -+ .rising = 0x00, -+ .falling = 0x0a, -+ }, -+}; -+ -+/* -+ * 5:4 fan tach edge mode selection bit: -+ * 00: falling -+ * 01: rising -+ * 10: both -+ * 11: reserved. -+ */ -+ -+struct aspeed_tacho_channel_params { -+ int limited_inverse; -+ u16 threshold; -+ u8 tacho_edge; -+ u8 tacho_debounce; -+ u8 divide; -+}; -+ -+ -+static struct aspeed_tacho_channel_params default_tacho_params[] = { -+ [0] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [1] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [2] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [3] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [4] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [5] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [6] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [7] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [8] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [9] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [10] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [11] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [12] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [13] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [14] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+ [15] = { -+ .limited_inverse = 0, -+ .threshold = 0, -+ .tacho_edge = 0, -+ .tacho_debounce = 0, -+ .divide = 8, -+ }, -+}; -+ -+struct aspeed_pwm_tachometer_data { -+ struct regmap *regmap; -+ unsigned long clk_freq; -+ struct reset_control *reset; -+ bool pwm_present[16]; -+ bool fan_tach_present[16]; -+ struct aspeed_pwm_channel_params *pwm_channel; -+ struct aspeed_tacho_channel_params *tacho_channel; -+ struct aspeed_cooling_device *cdev[8]; -+ const struct attribute_group *groups[3]; -+}; -+ -+struct aspeed_cooling_device { -+ char name[16]; -+ struct aspeed_pwm_tachometer_data *priv; -+ struct thermal_cooling_device *tcdev; -+ int pwm_channel; -+ u8 *cooling_levels; -+ u8 max_state; -+ u8 cur_state; -+}; -+ -+static int regmap_aspeed_pwm_tachometer_reg_write(void *context, unsigned int reg, -+ unsigned int val) -+{ -+ void __iomem *regs = (void __iomem *)context; -+ -+ writel(val, regs + reg); -+ return 0; -+} -+ -+static int regmap_aspeed_pwm_tachometer_reg_read(void *context, unsigned int reg, -+ unsigned int *val) -+{ -+ void __iomem *regs = (void __iomem *)context; -+ -+ *val = readl(regs + reg); -+ return 0; -+} -+ -+static const struct regmap_config aspeed_pwm_tachometer_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = 0x100, -+ .reg_write = regmap_aspeed_pwm_tachometer_reg_write, -+ .reg_read = regmap_aspeed_pwm_tachometer_reg_read, -+ .fast_io = true, -+}; -+ -+static void aspeed_set_pwm_channel_enable(struct regmap *regmap, u8 pwm_channel, -+ bool enable) -+{ -+ regmap_update_bits(regmap, ASPEED_PWM_CTRL_CH(pwm_channel), (PWM_CLK_ENABLE | PWM_PIN_EN), enable ? (PWM_CLK_ENABLE | PWM_PIN_EN) : 0); -+} -+ -+static void aspeed_set_fan_tach_ch_enable(struct aspeed_pwm_tachometer_data *priv, u8 fan_tach_ch, -+ bool enable) -+{ -+ u32 i = 0, j; -+ u32 divide_val = 0; -+ u32 reg_value = 0; -+ -+ if(enable) { -+ //4 ^ n -+ //check pwm clk and to change tacho devide 25KZ -+ for(i = 0; i < 12; i++) { -+ divide_val = 1; -+ for (j = 1; j <= i; j++) -+ divide_val *= 4; -+// printk("i : %d , priv->clk_freq/divide_val %d ",i, priv->clk_freq/divide_val); -+ if((priv->clk_freq/divide_val) < 250000) -+ break; -+ } -+ i--; -+ divide_val = ((1 << i) * (1 << i)); -+// printk("tacho divide_val %d , i %x max tacho clk %d \n", divide_val, i, priv->clk_freq / divide_val); -+ priv->tacho_channel[fan_tach_ch].divide = i; -+ -+ reg_value = TACHO_ENABLE | -+ (priv->tacho_channel[fan_tach_ch].tacho_edge << TECHIO_EDGE_BIT) | -+ (priv->tacho_channel[fan_tach_ch].divide << TACHO_CLK_DIV_BIT) | -+ (priv->tacho_channel[fan_tach_ch].tacho_debounce << TACHO_DEBOUNCE_BIT); -+ -+ if(priv->tacho_channel[fan_tach_ch].limited_inverse) -+ reg_value |= TACHO_INVERS_LIMIT; -+ -+ if(priv->tacho_channel[fan_tach_ch].threshold) -+ reg_value |= (TACHO_IER | priv->tacho_channel[fan_tach_ch].threshold); -+ -+ regmap_write(priv->regmap, ASPEED_TACHO_CTRL_CH(fan_tach_ch), reg_value); -+ } else -+ regmap_update_bits(priv->regmap, ASPEED_TACHO_CTRL_CH(fan_tach_ch), TACHO_ENABLE, 0); -+} -+ -+static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *priv, -+ u8 index, u8 fan_ctrl) -+{ -+ u32 duty_value, ctrl_value; -+ -+ if (fan_ctrl == 0) { -+ aspeed_set_pwm_channel_enable(priv->regmap, index, false); -+ } else { -+ duty_value = (priv->pwm_channel[index].period << PWM_PERIOD_BIT) | -+ (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT); -+ -+ ctrl_value = (priv->pwm_channel[index].divide_h << 8) | priv->pwm_channel[index].divide_l; -+ -+ if (priv->pwm_channel[index].load_wdt_enable) { -+ ctrl_value |= PWM_DUTY_LOAD_AS_WDT_EN; -+ if(priv->pwm_channel[index].load_wdt_selection) { -+ ctrl_value |= PWM_LOAD_AS_WDT; -+ duty_value |= (priv->pwm_channel[index].load_wdt_rising_falling_pt << PWM_RISING_FALLING_AS_WDT_BIT); -+ } else { -+ duty_value |= (priv->pwm_channel[index].load_wdt_rising_falling_pt << PWM_RISING_FALLING_AS_WDT_BIT); -+ } -+ } -+ -+ regmap_write(priv->regmap, ASPEED_PWM_DUTY_CYCLE_CH(index), duty_value); -+ -+ regmap_write(priv->regmap, ASPEED_PWM_CTRL_CH(index), ctrl_value); -+// printk("pwm clk is %d \n", priv->clk_freq / (priv->pwm_channel[index].period + 1)); -+ aspeed_set_pwm_channel_enable(priv->regmap, index, true); -+ } -+} -+ -+#define BOTH_EDGES 0x02 /* 10b */ -+ -+static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv, -+ u8 fan_tach_ch) -+{ -+ u32 raw_data, tach_div, clk_source, val; -+ u8 mode, both; -+ int i, retries = 3; -+ -+ for(i = 0; i < retries; i++) { -+ regmap_read(priv->regmap, ASPEED_TACHO_STS_CH(fan_tach_ch), &val); -+ if (TACHO_FULL_MEASUREMENT & val) -+ break; -+ } -+ -+ raw_data = val & TACHO_VALUE_MASK; -+ if(raw_data == 0xfffff) -+ return 0; -+ -+ tach_div = priv->tacho_channel[fan_tach_ch].divide; -+ /* -+ * We need the mode to determine if the raw_data is double (from -+ * counting both edges). -+ */ -+ mode = priv->tacho_channel[fan_tach_ch].tacho_edge; -+ both = (mode & BOTH_EDGES) ? 1 : 0; -+// printk("clk %ld, raw_data %x , tach_div %x both %x \n", priv->clk_freq, raw_data, tach_div, both); -+ -+ tach_div = (tach_div * 2) * (0x1 << both); -+ clk_source = priv->clk_freq; -+ -+ if (raw_data == 0) -+ return 0; -+ -+ return (clk_source * 60) / (2 * raw_data * tach_div); -+ -+} -+ -+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int index = sensor_attr->index; -+ int ret; -+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); -+ long fan_ctrl; -+ -+ ret = kstrtol(buf, 10, &fan_ctrl); -+ if (ret != 0) -+ return ret; -+ -+ if (fan_ctrl < 0 || fan_ctrl > priv->pwm_channel[index].period) -+ return -EINVAL; -+ -+ if (priv->pwm_channel[index].falling == fan_ctrl) -+ return count; -+ -+ priv->pwm_channel[index].falling = fan_ctrl; -+ aspeed_set_pwm_channel_fan_ctrl(priv, index, fan_ctrl); -+ -+ return count; -+} -+ -+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int index = sensor_attr->index; -+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%u\n", priv->pwm_channel[index].falling); -+} -+ -+static ssize_t show_rpm(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int index = sensor_attr->index; -+ int rpm; -+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); -+ -+ rpm = aspeed_get_fan_tach_ch_rpm(priv, index); -+ if (rpm < 0) -+ return rpm; -+ -+ return sprintf(buf, "%d\n", rpm); -+} -+ -+static umode_t pwm_is_visible(struct kobject *kobj, -+ struct attribute *a, int index) -+{ -+ struct device *dev = container_of(kobj, struct device, kobj); -+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); -+ -+ if (!priv->pwm_present[index]) -+ return 0; -+ return a->mode; -+} -+ -+static umode_t fan_dev_is_visible(struct kobject *kobj, -+ struct attribute *a, int index) -+{ -+ struct device *dev = container_of(kobj, struct device, kobj); -+ struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); -+ -+ if (!priv->fan_tach_present[index]) -+ return 0; -+ return a->mode; -+} -+ -+static SENSOR_DEVICE_ATTR(pwm0, 0644, -+ show_pwm, set_pwm, 0); -+static SENSOR_DEVICE_ATTR(pwm1, 0644, -+ show_pwm, set_pwm, 1); -+static SENSOR_DEVICE_ATTR(pwm2, 0644, -+ show_pwm, set_pwm, 2); -+static SENSOR_DEVICE_ATTR(pwm3, 0644, -+ show_pwm, set_pwm, 3); -+static SENSOR_DEVICE_ATTR(pwm4, 0644, -+ show_pwm, set_pwm, 4); -+static SENSOR_DEVICE_ATTR(pwm5, 0644, -+ show_pwm, set_pwm, 5); -+static SENSOR_DEVICE_ATTR(pwm6, 0644, -+ show_pwm, set_pwm, 6); -+static SENSOR_DEVICE_ATTR(pwm7, 0644, -+ show_pwm, set_pwm, 7); -+static SENSOR_DEVICE_ATTR(pwm8, 0644, -+ show_pwm, set_pwm, 8); -+static SENSOR_DEVICE_ATTR(pwm9, 0644, -+ show_pwm, set_pwm, 9); -+static SENSOR_DEVICE_ATTR(pwm10, 0644, -+ show_pwm, set_pwm, 10); -+static SENSOR_DEVICE_ATTR(pwm11, 0644, -+ show_pwm, set_pwm, 11); -+static SENSOR_DEVICE_ATTR(pwm12, 0644, -+ show_pwm, set_pwm, 12); -+static SENSOR_DEVICE_ATTR(pwm13, 0644, -+ show_pwm, set_pwm, 13); -+static SENSOR_DEVICE_ATTR(pwm14, 0644, -+ show_pwm, set_pwm, 14); -+static SENSOR_DEVICE_ATTR(pwm15, 0644, -+ show_pwm, set_pwm, 15); -+static struct attribute *pwm_dev_attrs[] = { -+ &sensor_dev_attr_pwm0.dev_attr.attr, -+ &sensor_dev_attr_pwm1.dev_attr.attr, -+ &sensor_dev_attr_pwm2.dev_attr.attr, -+ &sensor_dev_attr_pwm3.dev_attr.attr, -+ &sensor_dev_attr_pwm4.dev_attr.attr, -+ &sensor_dev_attr_pwm5.dev_attr.attr, -+ &sensor_dev_attr_pwm6.dev_attr.attr, -+ &sensor_dev_attr_pwm7.dev_attr.attr, -+ &sensor_dev_attr_pwm8.dev_attr.attr, -+ &sensor_dev_attr_pwm9.dev_attr.attr, -+ &sensor_dev_attr_pwm10.dev_attr.attr, -+ &sensor_dev_attr_pwm11.dev_attr.attr, -+ &sensor_dev_attr_pwm12.dev_attr.attr, -+ &sensor_dev_attr_pwm13.dev_attr.attr, -+ &sensor_dev_attr_pwm14.dev_attr.attr, -+ &sensor_dev_attr_pwm15.dev_attr.attr, -+ NULL, -+}; -+ -+static const struct attribute_group pwm_dev_group = { -+ .attrs = pwm_dev_attrs, -+ .is_visible = pwm_is_visible, -+}; -+ -+static SENSOR_DEVICE_ATTR(fan0_input, 0444, -+ show_rpm, NULL, 0); -+static SENSOR_DEVICE_ATTR(fan1_input, 0444, -+ show_rpm, NULL, 1); -+static SENSOR_DEVICE_ATTR(fan2_input, 0444, -+ show_rpm, NULL, 2); -+static SENSOR_DEVICE_ATTR(fan3_input, 0444, -+ show_rpm, NULL, 3); -+static SENSOR_DEVICE_ATTR(fan4_input, 0444, -+ show_rpm, NULL, 4); -+static SENSOR_DEVICE_ATTR(fan5_input, 0444, -+ show_rpm, NULL, 5); -+static SENSOR_DEVICE_ATTR(fan6_input, 0444, -+ show_rpm, NULL, 6); -+static SENSOR_DEVICE_ATTR(fan7_input, 0444, -+ show_rpm, NULL, 7); -+static SENSOR_DEVICE_ATTR(fan8_input, 0444, -+ show_rpm, NULL, 8); -+static SENSOR_DEVICE_ATTR(fan9_input, 0444, -+ show_rpm, NULL, 9); -+static SENSOR_DEVICE_ATTR(fan10_input, 0444, -+ show_rpm, NULL, 10); -+static SENSOR_DEVICE_ATTR(fan11_input, 0444, -+ show_rpm, NULL, 11); -+static SENSOR_DEVICE_ATTR(fan12_input, 0444, -+ show_rpm, NULL, 12); -+static SENSOR_DEVICE_ATTR(fan13_input, 0444, -+ show_rpm, NULL, 13); -+static SENSOR_DEVICE_ATTR(fan14_input, 0444, -+ show_rpm, NULL, 14); -+static SENSOR_DEVICE_ATTR(fan15_input, 0444, -+ show_rpm, NULL, 15); -+static struct attribute *fan_dev_attrs[] = { -+ &sensor_dev_attr_fan0_input.dev_attr.attr, -+ &sensor_dev_attr_fan1_input.dev_attr.attr, -+ &sensor_dev_attr_fan2_input.dev_attr.attr, -+ &sensor_dev_attr_fan3_input.dev_attr.attr, -+ &sensor_dev_attr_fan4_input.dev_attr.attr, -+ &sensor_dev_attr_fan5_input.dev_attr.attr, -+ &sensor_dev_attr_fan6_input.dev_attr.attr, -+ &sensor_dev_attr_fan7_input.dev_attr.attr, -+ &sensor_dev_attr_fan8_input.dev_attr.attr, -+ &sensor_dev_attr_fan9_input.dev_attr.attr, -+ &sensor_dev_attr_fan10_input.dev_attr.attr, -+ &sensor_dev_attr_fan11_input.dev_attr.attr, -+ &sensor_dev_attr_fan12_input.dev_attr.attr, -+ &sensor_dev_attr_fan13_input.dev_attr.attr, -+ &sensor_dev_attr_fan14_input.dev_attr.attr, -+ &sensor_dev_attr_fan15_input.dev_attr.attr, -+ NULL -+}; -+ -+static const struct attribute_group fan_dev_group = { -+ .attrs = fan_dev_attrs, -+ .is_visible = fan_dev_is_visible, -+}; -+ -+static void aspeed_create_pwm_channel(struct aspeed_pwm_tachometer_data *priv, -+ u8 pwm_channel) -+{ -+ priv->pwm_present[pwm_channel] = true; -+ -+ //use default -+ aspeed_set_pwm_channel_fan_ctrl(priv, pwm_channel, priv->pwm_channel[pwm_channel].falling); -+} -+ -+static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tachometer_data *priv, -+ u8 *fan_tach_ch, -+ int count) -+{ -+ u8 val, index; -+ -+ for (val = 0; val < count; val++) { -+ index = fan_tach_ch[val]; -+ priv->fan_tach_present[index] = true; -+ aspeed_set_fan_tach_ch_enable(priv, index, true); -+ } -+} -+ -+static int -+aspeed_pwm_cz_get_max_state(struct thermal_cooling_device *tcdev, -+ unsigned long *state) -+{ -+ struct aspeed_cooling_device *cdev = tcdev->devdata; -+ -+ *state = cdev->max_state; -+ -+ return 0; -+} -+ -+static int -+aspeed_pwm_cz_get_cur_state(struct thermal_cooling_device *tcdev, -+ unsigned long *state) -+{ -+ struct aspeed_cooling_device *cdev = tcdev->devdata; -+ -+ *state = cdev->cur_state; -+ -+ return 0; -+} -+ -+static int -+aspeed_pwm_cz_set_cur_state(struct thermal_cooling_device *tcdev, -+ unsigned long state) -+{ -+ struct aspeed_cooling_device *cdev = tcdev->devdata; -+ -+ if (state > cdev->max_state) -+ return -EINVAL; -+ -+ cdev->cur_state = state; -+ cdev->priv->pwm_channel[cdev->pwm_channel].falling = -+ cdev->cooling_levels[cdev->cur_state]; -+ aspeed_set_pwm_channel_fan_ctrl(cdev->priv, cdev->pwm_channel, -+ cdev->cooling_levels[cdev->cur_state]); -+ -+ return 0; -+} -+ -+static const struct thermal_cooling_device_ops aspeed_pwm_cool_ops = { -+ .get_max_state = aspeed_pwm_cz_get_max_state, -+ .get_cur_state = aspeed_pwm_cz_get_cur_state, -+ .set_cur_state = aspeed_pwm_cz_set_cur_state, -+}; -+ -+static int aspeed_create_pwm_cooling(struct device *dev, -+ struct device_node *child, -+ struct aspeed_pwm_tachometer_data *priv, -+ u32 pwm_channel, u8 num_levels) -+{ -+ int ret; -+ struct aspeed_cooling_device *cdev; -+ -+ cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); -+ if (!cdev) -+ return -ENOMEM; -+ -+ cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL); -+ if (!cdev->cooling_levels) -+ return -ENOMEM; -+ -+ cdev->max_state = num_levels - 1; -+ ret = of_property_read_u8_array(child, "cooling-levels", -+ cdev->cooling_levels, -+ num_levels); -+ if (ret) { -+ dev_err(dev, "Property 'cooling-levels' cannot be read.\n"); -+ return ret; -+ } -+ snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_channel); -+ -+ cdev->tcdev = thermal_of_cooling_device_register(child, -+ cdev->name, -+ cdev, -+ &aspeed_pwm_cool_ops); -+ if (IS_ERR(cdev->tcdev)) -+ return PTR_ERR(cdev->tcdev); -+ -+ cdev->priv = priv; -+ cdev->pwm_channel = pwm_channel; -+ -+ priv->cdev[pwm_channel] = cdev; -+ -+ return 0; -+} -+ -+static int aspeed_pwm_create_fan(struct device *dev, -+ struct device_node *child, -+ struct aspeed_pwm_tachometer_data *priv) -+{ -+ u8 *fan_tach_ch; -+ u32 pwm_channel; -+ int ret, count; -+ -+ ret = of_property_read_u32(child, "reg", &pwm_channel); -+ if (ret) -+ return ret; -+ -+ aspeed_create_pwm_channel(priv, (u8)pwm_channel); -+ -+ ret = of_property_count_u8_elems(child, "cooling-levels"); -+ if (ret > 0) { -+ ret = aspeed_create_pwm_cooling(dev, child, priv, pwm_channel, -+ ret); -+ if (ret) -+ return ret; -+ } -+ -+ count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); -+ if (count < 1) -+ return -EINVAL; -+ -+ fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count, -+ GFP_KERNEL); -+ if (!fan_tach_ch) -+ return -ENOMEM; -+ ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch", -+ fan_tach_ch, count); -+ if (ret) -+ return ret; -+ -+ aspeed_create_fan_tach_channel(priv, fan_tach_ch, count); -+ -+ return 0; -+} -+ -+static int aspeed_pwm_tachometer_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np, *child; -+ struct aspeed_pwm_tachometer_data *priv; -+ void __iomem *regs; -+ struct resource *res; -+ struct device *hwmon; -+ struct clk *clk; -+ int ret; -+ -+ np = dev->of_node; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -ENOENT; -+ regs = devm_ioremap_resource(dev, res); -+ if (IS_ERR(regs)) -+ return PTR_ERR(regs); -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->pwm_channel = default_pwm_params; -+ priv->tacho_channel = default_tacho_params; -+ priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, -+ &aspeed_pwm_tachometer_regmap_config); -+ if (IS_ERR(priv->regmap)) -+ return PTR_ERR(priv->regmap); -+ -+ clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(clk)) -+ return -ENODEV; -+ priv->clk_freq = clk_get_rate(clk); -+ -+ priv->reset = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(priv->reset)) { -+ dev_err(&pdev->dev, "can't get aspeed_pwm_tacho reset\n"); -+ return PTR_ERR(priv->reset); -+ } -+ -+ //scu init -+ reset_control_assert(priv->reset); -+ reset_control_deassert(priv->reset); -+ -+ for_each_child_of_node(np, child) { -+ ret = aspeed_pwm_create_fan(dev, child, priv); -+ if (ret) { -+ of_node_put(child); -+ return ret; -+ } -+ } -+ -+ priv->groups[0] = &pwm_dev_group; -+ priv->groups[1] = &fan_dev_group; -+ priv->groups[2] = NULL; -+ hwmon = devm_hwmon_device_register_with_groups(dev, -+ "aspeed_g6_pwm_tacho", -+ priv, priv->groups); -+ -+ return PTR_ERR_OR_ZERO(hwmon); -+} -+ -+static const struct of_device_id of_pwm_tachometer_match_table[] = { -+ { .compatible = "aspeed,ast2600-pwm-tacho", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, of_pwm_tachometer_match_table); -+ -+static struct platform_driver aspeed_pwm_tachometer_driver = { -+ .probe = aspeed_pwm_tachometer_probe, -+ .driver = { -+ .name = "aspeed_g6_pwm_tacho", -+ .of_match_table = of_pwm_tachometer_match_table, -+ }, -+}; -+ -+module_platform_driver(aspeed_pwm_tachometer_driver); -+ -+MODULE_AUTHOR("Ryan Chen "); -+MODULE_DESCRIPTION("ASPEED PWM and Fan Tachometer device driver"); -+MODULE_LICENSE("GPL"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch deleted file mode 100644 index 7ea00a4a2..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0077-soc-aspeed-Add-read-only-property-support.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f2d62c90f2ea05b1abf9a1887502122eefb5906d Mon Sep 17 00:00:00 2001 -From: Yong Li -Date: Wed, 16 Oct 2019 15:11:06 +0800 -Subject: [PATCH] soc: aspeed: Add read-only property support - -Add a read-only property, to support export register bits as read-only. - -Signed-off-by: Yong Li ---- - drivers/soc/aspeed/aspeed-bmc-misc.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/soc/aspeed/aspeed-bmc-misc.c b/drivers/soc/aspeed/aspeed-bmc-misc.c -index 314007b..bf88376 100644 ---- a/drivers/soc/aspeed/aspeed-bmc-misc.c -+++ b/drivers/soc/aspeed/aspeed-bmc-misc.c -@@ -15,6 +15,7 @@ struct aspeed_bmc_ctrl { - u32 offset; - u32 mask; - u32 shift; -+ bool read_only; - struct regmap *map; - struct kobj_attribute attr; - }; -@@ -55,6 +56,8 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child, - if (rc < 0) - return rc; - -+ ctrl->read_only = of_property_read_bool(child, "read-only"); -+ - ctrl->mask <<= ctrl->shift; - - return 0; -@@ -116,6 +119,10 @@ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj, - return rc; - - ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr); -+ -+ if (ctrl->read_only) -+ return -EROFS; -+ - val <<= ctrl->shift; - rc = regmap_update_bits(ctrl->map, ctrl->offset, ctrl->mask, val); - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch deleted file mode 100644 index 09a957860..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 3eaf814c51f85aaad0d181d27ff686ce35b31d6a Mon Sep 17 00:00:00 2001 -From: Kuiying Wang -Date: Tue, 29 Oct 2019 11:28:29 +0800 -Subject: [PATCH] Fix NCSI driver issue caused by host shutdown due to - overheated. - -NCSI device cannot be recovered when host shutdown due to overheated. - -Tested: -Heat host till shutdown due to overheated and then -run the ipmi command like power status - -Signed-off-by: Kuiying Wang ---- - net/ncsi/ncsi-manage.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c -index 70fe02697544..4e16a0015f26 100644 ---- a/net/ncsi/ncsi-manage.c -+++ b/net/ncsi/ncsi-manage.c -@@ -132,18 +132,15 @@ static void ncsi_channel_monitor(struct timer_list *t) - netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n", - nc->id); - ncsi_report_link(ndp, true); -- ndp->flags |= NCSI_DEV_RESHUFFLE; - - ncsi_stop_channel_monitor(nc); - -- ncm = &nc->modes[NCSI_MODE_LINK]; - spin_lock_irqsave(&nc->lock, flags); -- nc->state = NCSI_CHANNEL_INVISIBLE; -- ncm->data[2] &= ~0x1; -+ nc->state = NCSI_CHANNEL_INACTIVE; - spin_unlock_irqrestore(&nc->lock, flags); - - spin_lock_irqsave(&ndp->lock, flags); -- nc->state = NCSI_CHANNEL_ACTIVE; -+ ndp->flags |= NCSI_DEV_RESHUFFLE | NCSI_DEV_RESET; - list_add_tail_rcu(&nc->link, &ndp->channel_queue); - spin_unlock_irqrestore(&ndp->lock, flags); - ncsi_process_next_channel(ndp); -@@ -424,6 +421,7 @@ static void ncsi_request_timeout(struct timer_list *t) - { - struct ncsi_request *nr = from_timer(nr, t, timer); - struct ncsi_dev_priv *ndp = nr->ndp; -+ struct ncsi_dev *nd = &ndp->ndev; - struct ncsi_cmd_pkt *cmd; - struct ncsi_package *np; - struct ncsi_channel *nc; -@@ -438,6 +436,16 @@ static void ncsi_request_timeout(struct timer_list *t) - spin_unlock_irqrestore(&ndp->lock, flags); - return; - } -+ if (nd->state == ncsi_dev_state_suspend || -+ nd->state == ncsi_dev_state_suspend_select || -+ nd->state == ncsi_dev_state_suspend_gls || -+ nd->state == ncsi_dev_state_suspend_dcnt || -+ nd->state == ncsi_dev_state_suspend_dc || -+ nd->state == ncsi_dev_state_suspend_deselect || -+ nd->state == ncsi_dev_state_suspend_done) { -+ ndp->flags |= NCSI_DEV_RESET; -+ nd->state = ncsi_dev_state_suspend_done; -+ } - spin_unlock_irqrestore(&ndp->lock, flags); - - if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) { --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch deleted file mode 100644 index d8e911a54..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0080-i2c-aspeed-filter-garbage-interrupts-out.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 063957ca24903e7cbebcaa11bde4cc1cc3cbb6a1 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 8 Nov 2019 15:57:27 -0800 -Subject: [PATCH] i2c: aspeed: filter garbage interrupts out - -AST2600 makes a garbage interrupt which is decribed as 'reserved' -in datasheet so filter them out. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index 24850fb78ee1..d5a8da4a9009 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -87,7 +87,11 @@ - * These share bit definitions, so use the same values for the enable & - * status bits. - */ -+#if defined(CONFIG_MACH_ASPEED_G6) -+#define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(29) -+#else - #define ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING BIT(30) -+#endif - #define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15) - #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) - #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) -@@ -118,6 +122,11 @@ - ASPEED_I2CD_INTR_RX_DONE | \ - ASPEED_I2CD_INTR_TX_NAK | \ - ASPEED_I2CD_INTR_TX_ACK) -+#define ASPEED_I2CD_INTR_STATUS_MASK \ -+ (ASPEED_I2CD_INTR_SLAVE_ADDR_RECEIVED_PENDING | \ -+ ASPEED_I2CD_INTR_GCALL_ADDR | \ -+ ASPEED_I2CD_INTR_SLAVE_MATCH | \ -+ ASPEED_I2CD_INTR_ALL) - - /* 0x14 : I2CD Command/Status Register */ - #define ASPEED_I2CD_SCL_LINE_STS BIT(18) -@@ -1065,6 +1074,11 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) - writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE, - bus->base + ASPEED_I2C_INTR_STS_REG); - readl(bus->base + ASPEED_I2C_INTR_STS_REG); -+ /* -+ * AST2600 makes a garbage interrupt which is decribed as 'reserved' -+ * in datasheet so filter them out. -+ */ -+ irq_received &= ASPEED_I2CD_INTR_STATUS_MASK; - irq_remaining = irq_received; - - #if IS_ENABLED(CONFIG_I2C_SLAVE) --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch deleted file mode 100644 index f578d0f04..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0084-ARM-dts-aspeed-g6-add-GFX-node.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 523bbaaf9f9d064c9cf1f627d64dd7ba169d175d Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 20 Nov 2019 15:01:06 -0800 -Subject: [PATCH] ARM: dts: aspeed-g6: add GFX node - -This commit adds GFX node for AST2600 SoC. - -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index b880e8e8f999..3e2153416e11 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -330,6 +330,15 @@ - quality = <100>; - }; - -+ gfx: display@1e6e6000 { -+ compatible = "aspeed,ast2600-gfx", "syscon"; -+ reg = <0x1e6e6000 0x1000>; -+ reg-io-width = <4>; -+ clocks = <&syscon ASPEED_CLK_GATE_D1CLK>; -+ status = "disabled"; -+ interrupts = ; -+ }; -+ - adc: adc@1e6e9000 { - compatible = "aspeed,ast2500-adc"; - reg = <0x1e6e9000 0x100>; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch deleted file mode 100644 index 259720e87..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0085-drm-add-AST2600-GFX-support.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 195cd60ff2fe38b18ebdea90245b908548f4e985 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 20 Nov 2019 14:58:24 -0800 -Subject: [PATCH] drm: add AST2600 GFX support - -This commit adds support for AST2600 GFX. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/gpu/drm/aspeed/aspeed_gfx.h | 4 ++++ - drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c | 6 +++--- - drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 18 +++++++++++------- - 3 files changed, 18 insertions(+), 10 deletions(-) - -diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h -index a10358bb61ec..eebd72eb1220 100644 ---- a/drivers/gpu/drm/aspeed/aspeed_gfx.h -+++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h -@@ -13,11 +13,15 @@ struct aspeed_gfx { - struct drm_simple_display_pipe pipe; - struct drm_connector connector; - struct drm_fbdev_cma *fbdev; -+ u32 scu_misc_offset; - }; - - int aspeed_gfx_create_pipe(struct drm_device *drm); - int aspeed_gfx_create_output(struct drm_device *drm); - -+#define SCU_MISC_AST2500 0x2c /* SCU Misc of AST2500 */ -+#define SCU_MISC_AST2600 0xc0 /* SCU Misc1 of AST2600 */ -+ - #define CRT_CTRL1 0x60 /* CRT Control I */ - #define CRT_CTRL2 0x64 /* CRT Control II */ - #define CRT_STATUS 0x68 /* CRT Status */ -diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c -index 2184b8be6fd4..86359a0fe05f 100644 ---- a/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c -+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c -@@ -59,8 +59,8 @@ static void aspeed_gfx_enable_controller(struct aspeed_gfx *priv) - u32 ctrl1 = readl(priv->base + CRT_CTRL1); - u32 ctrl2 = readl(priv->base + CRT_CTRL2); - -- /* SCU2C: set DAC source for display output to Graphics CRT (GFX) */ -- regmap_update_bits(priv->scu, 0x2c, BIT(16), BIT(16)); -+ /* Set DAC source for display output to Graphics CRT (GFX) */ -+ regmap_update_bits(priv->scu, priv->scu_misc_offset, BIT(16), BIT(16)); - - writel(ctrl1 | CRT_CTRL_EN, priv->base + CRT_CTRL1); - writel(ctrl2 | CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2); -@@ -74,7 +74,7 @@ static void aspeed_gfx_disable_controller(struct aspeed_gfx *priv) - writel(ctrl1 & ~CRT_CTRL_EN, priv->base + CRT_CTRL1); - writel(ctrl2 & ~CRT_CTRL_DAC_EN, priv->base + CRT_CTRL2); - -- regmap_update_bits(priv->scu, 0x2c, BIT(16), 0); -+ regmap_update_bits(priv->scu, priv->scu_misc_offset, BIT(16), 0); - } - - static void aspeed_gfx_crtc_mode_set_nofb(struct aspeed_gfx *priv) -diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -index ada2f6aca906..92bc9b475e0f 100644 ---- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -@@ -112,8 +112,14 @@ static int aspeed_gfx_load(struct drm_device *drm) - - priv->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2500-scu"); - if (IS_ERR(priv->scu)) { -- dev_err(&pdev->dev, "failed to find SCU regmap\n"); -- return PTR_ERR(priv->scu); -+ priv->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2600-scu"); -+ if (IS_ERR(priv->scu)) { -+ dev_err(&pdev->dev, "failed to find SCU regmap\n"); -+ return PTR_ERR(priv->scu); -+ } -+ priv->scu_misc_offset = SCU_MISC_AST2600; -+ } else { -+ priv->scu_misc_offset = SCU_MISC_AST2500; - } - - ret = of_reserved_mem_device_init(drm->dev); -@@ -130,12 +136,9 @@ static int aspeed_gfx_load(struct drm_device *drm) - } - - priv->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -- if (IS_ERR(priv->rst)) { -- dev_err(&pdev->dev, -- "missing or invalid reset controller device tree entry"); -- return PTR_ERR(priv->rst); -+ if (!IS_ERR_OR_NULL(priv->rst)) { -+ reset_control_deassert(priv->rst); - } -- reset_control_deassert(priv->rst); - - priv->clk = devm_clk_get(drm->dev, NULL); - if (IS_ERR(priv->clk)) { -@@ -211,6 +214,7 @@ static struct drm_driver aspeed_gfx_driver = { - - static const struct of_device_id aspeed_gfx_match[] = { - { .compatible = "aspeed,ast2500-gfx" }, -+ { .compatible = "aspeed,ast2600-gfx" }, - { } - }; - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch deleted file mode 100644 index 4dde9fb06..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ADC-linux-driver-for-AST2600.patch +++ /dev/null @@ -1,271 +0,0 @@ -From 278db13a36f128b84f76fc0f0f13860b5bf62588 Mon Sep 17 00:00:00 2001 -From: Chen Yugang -Date: Tue, 3 Dec 2019 13:41:37 +0800 -Subject: [PATCH] ADC linux driver for AST2600 - -Tested: -it's tested with DC input. - -Signed-off-by: Chen Yugang ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 14 +++++- - drivers/iio/adc/aspeed_adc.c | 99 +++++++++++++++++++++++++++++++++++----- - 2 files changed, 99 insertions(+), 14 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 3e2153416e11..5acc1085526d 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -339,12 +339,22 @@ - interrupts = ; - }; - -- adc: adc@1e6e9000 { -- compatible = "aspeed,ast2500-adc"; -+ adc0: adc@1e6e9000 { -+ compatible = "aspeed,ast2600-adc"; - reg = <0x1e6e9000 0x100>; - clocks = <&syscon ASPEED_CLK_APB2>; -+ resets = <&syscon ASPEED_RESET_ADC>; - interrupts = ; -+ #io-channel-cells = <1>; -+ status = "disabled"; -+ }; -+ -+ adc1: adc@1e6e9100 { -+ compatible = "aspeed,ast2600-adc"; -+ reg = <0x1e6e9100 0x100>; -+ clocks = <&syscon ASPEED_CLK_APB2>; - resets = <&syscon ASPEED_RESET_ADC>; -+ interrupts = ; - #io-channel-cells = <1>; - status = "disabled"; - }; -diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c -index d3fc39df535d..1dd5a97a16bc 100644 ---- a/drivers/iio/adc/aspeed_adc.c -+++ b/drivers/iio/adc/aspeed_adc.c -@@ -1,8 +1,12 @@ --// SPDX-License-Identifier: GPL-2.0-only - /* -- * Aspeed AST2400/2500 ADC -+ * Aspeed AST2400/2500/2600 ADC - * - * Copyright (C) 2017 Google, Inc. -+ * Copyright (C) ASPEED Technology Inc. -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * - */ - - #include -@@ -30,6 +34,14 @@ - #define ASPEED_REG_CLOCK_CONTROL 0x0C - #define ASPEED_REG_MAX 0xC0 - -+/* ast2600 */ -+#define REF_VLOTAGE_2500mV 0 -+#define REF_VLOTAGE_1200mV GENMASK(6, 6) -+#define REF_VLOTAGE_1550mV GENMASK(7, 7) -+#define REF_VLOTAGE_900mV GENMASK(7, 6) -+ -+#define ASPEED_AUTOPENSATING BIT(5) -+ - #define ASPEED_OPERATION_MODE_POWER_DOWN (0x0 << 1) - #define ASPEED_OPERATION_MODE_STANDBY (0x1 << 1) - #define ASPEED_OPERATION_MODE_NORMAL (0x7 << 1) -@@ -45,8 +57,10 @@ struct aspeed_adc_model_data { - const char *model_name; - unsigned int min_sampling_rate; // Hz - unsigned int max_sampling_rate; // Hz -- unsigned int vref_voltage; // mV -+ u32 vref_voltage; // mV - bool wait_init_sequence; -+ struct iio_chan_spec const *channels; -+ int num_channels; - }; - - struct aspeed_adc_data { -@@ -56,6 +70,7 @@ struct aspeed_adc_data { - struct clk_hw *clk_prescaler; - struct clk_hw *clk_scaler; - struct reset_control *rst; -+ int cv; - }; - - #define ASPEED_CHAN(_idx, _data_reg_addr) { \ -@@ -87,6 +102,17 @@ static const struct iio_chan_spec aspeed_adc_iio_channels[] = { - ASPEED_CHAN(15, 0x2E), - }; - -+static const struct iio_chan_spec ast2600_adc_iio_channels[] = { -+ ASPEED_CHAN(0, 0x10), -+ ASPEED_CHAN(1, 0x12), -+ ASPEED_CHAN(2, 0x14), -+ ASPEED_CHAN(3, 0x16), -+ ASPEED_CHAN(4, 0x18), -+ ASPEED_CHAN(5, 0x1A), -+ ASPEED_CHAN(6, 0x1C), -+ ASPEED_CHAN(7, 0x1E), -+}; -+ - static int aspeed_adc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -@@ -175,7 +201,10 @@ static int aspeed_adc_probe(struct platform_device *pdev) - const struct aspeed_adc_model_data *model_data; - struct resource *res; - const char *clk_parent_name; -+ char prescaler_clk_name[32]; -+ char scaler_clk_name[32]; - int ret; -+ u32 eng_ctrl = 0; - u32 adc_engine_control_reg_val; - - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data)); -@@ -194,19 +223,21 @@ static int aspeed_adc_probe(struct platform_device *pdev) - spin_lock_init(&data->clk_lock); - clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); - -+ snprintf(prescaler_clk_name, sizeof(prescaler_clk_name), "prescaler-%s", pdev->name); - data->clk_prescaler = clk_hw_register_divider( -- &pdev->dev, "prescaler", clk_parent_name, 0, -+ &pdev->dev, prescaler_clk_name, clk_parent_name, 0, - data->base + ASPEED_REG_CLOCK_CONTROL, - 17, 15, 0, &data->clk_lock); - if (IS_ERR(data->clk_prescaler)) - return PTR_ERR(data->clk_prescaler); - -+ snprintf(scaler_clk_name, sizeof(scaler_clk_name), "scaler-%s", pdev->name); - /* - * Register ADC clock scaler downstream from the prescaler. Allow rate - * setting to adjust the prescaler as well. - */ - data->clk_scaler = clk_hw_register_divider( -- &pdev->dev, "scaler", "prescaler", -+ &pdev->dev, scaler_clk_name, prescaler_clk_name, - CLK_SET_RATE_PARENT, - data->base + ASPEED_REG_CLOCK_CONTROL, - 0, 10, 0, &data->clk_lock); -@@ -215,7 +246,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) - goto scaler_error; - } - -- data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -+ data->rst = devm_reset_control_get_shared(&pdev->dev, NULL); - if (IS_ERR(data->rst)) { - dev_err(&pdev->dev, - "invalid or missing reset controller device tree entry"); -@@ -225,11 +256,26 @@ static int aspeed_adc_probe(struct platform_device *pdev) - reset_control_deassert(data->rst); - - model_data = of_device_get_match_data(&pdev->dev); -+ if (!of_property_read_u32(pdev->dev.of_node, "ref_voltage", (u32 *)&model_data->vref_voltage)) { -+ if (model_data->vref_voltage == 2500) -+ eng_ctrl = REF_VLOTAGE_2500mV; -+ else if (model_data->vref_voltage == 1200) -+ eng_ctrl = REF_VLOTAGE_1200mV; -+ else if ((model_data->vref_voltage >= 1550) && (model_data->vref_voltage <= 2700)) -+ eng_ctrl = REF_VLOTAGE_1550mV; -+ else if ((model_data->vref_voltage >= 900) && (model_data->vref_voltage <= 1650)) -+ eng_ctrl = REF_VLOTAGE_900mV; -+ else { -+ printk("error ref voltage %d \n", model_data->vref_voltage); -+ eng_ctrl = 0; -+ } -+ } else -+ eng_ctrl = 0; - - if (model_data->wait_init_sequence) { - /* Enable engine in normal mode. */ -- writel(ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE, -- data->base + ASPEED_REG_ENGINE_CONTROL); -+ eng_ctrl |= ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE; -+ writel(eng_ctrl, data->base + ASPEED_REG_ENGINE_CONTROL); - - /* Wait for initial sequence complete. */ - ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL, -@@ -242,12 +288,26 @@ static int aspeed_adc_probe(struct platform_device *pdev) - goto poll_timeout_error; - } - -+ /* do compensating calculation use ch 0 */ -+ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL | -+ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL); -+ -+ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL | BIT(16) | -+ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL); -+ mdelay(1); -+ -+ data->cv = 0x200 - (readl(data->base + 0x10) & GENMASK(9, 0)); -+ -+ writel(eng_ctrl | ASPEED_OPERATION_MODE_NORMAL | -+ ASPEED_ENGINE_ENABLE | ASPEED_AUTOPENSATING, data->base + ASPEED_REG_ENGINE_CONTROL); -+ printk(KERN_INFO "aspeed_adc: cv %d \n", data->cv); -+ - /* Start all channels in normal mode. */ - ret = clk_prepare_enable(data->clk_scaler->clk); - if (ret) - goto clk_enable_error; - -- adc_engine_control_reg_val = GENMASK(31, 16) | -+ adc_engine_control_reg_val = eng_ctrl | GENMASK(31, 16) | - ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE; - writel(adc_engine_control_reg_val, - data->base + ASPEED_REG_ENGINE_CONTROL); -@@ -257,8 +317,8 @@ static int aspeed_adc_probe(struct platform_device *pdev) - indio_dev->dev.parent = &pdev->dev; - indio_dev->info = &aspeed_adc_iio_info; - indio_dev->modes = INDIO_DIRECT_MODE; -- indio_dev->channels = aspeed_adc_iio_channels; -- indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels); -+ indio_dev->channels = model_data->channels; -+ indio_dev->num_channels = model_data->num_channels; - - ret = iio_device_register(indio_dev); - if (ret) -@@ -301,6 +361,8 @@ static const struct aspeed_adc_model_data ast2400_model_data = { - .vref_voltage = 2500, // mV - .min_sampling_rate = 10000, - .max_sampling_rate = 500000, -+ .channels = aspeed_adc_iio_channels, -+ .num_channels = 16, - }; - - static const struct aspeed_adc_model_data ast2500_model_data = { -@@ -309,11 +371,24 @@ static const struct aspeed_adc_model_data ast2500_model_data = { - .min_sampling_rate = 1, - .max_sampling_rate = 1000000, - .wait_init_sequence = true, -+ .channels = aspeed_adc_iio_channels, -+ .num_channels = 16, -+}; -+ -+static const struct aspeed_adc_model_data ast2600_model_data = { -+ .model_name = "ast2500-adc", -+ .vref_voltage = 1800, /* mV --> can be 1.2v or 2.5 or ext 1.55~2.7v, 0.9v ~1.65v */ -+ .min_sampling_rate = 1, -+ .max_sampling_rate = 1000000, -+ .wait_init_sequence = true, -+ .channels = ast2600_adc_iio_channels, -+ .num_channels = 8, - }; - - static const struct of_device_id aspeed_adc_matches[] = { - { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data }, - { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data }, -+ { .compatible = "aspeed,ast2600-adc", .data = &ast2600_model_data }, - {}, - }; - MODULE_DEVICE_TABLE(of, aspeed_adc_matches); -@@ -330,5 +405,5 @@ static struct platform_driver aspeed_adc_driver = { - module_platform_driver(aspeed_adc_driver); - - MODULE_AUTHOR("Rick Altherr "); --MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver"); -+MODULE_DESCRIPTION("Aspeed AST2400/2500/2600 ADC Driver"); - MODULE_LICENSE("GPL"); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch deleted file mode 100644 index 221800720..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0086-ARM-dts-aspeed-g6-add-video-node.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 90c72bbe5f1ac2c8d62736c44492bd8bbc4fcab0 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 26 Nov 2019 16:37:36 -0800 -Subject: [PATCH] ARM: dts: aspeed-g6: add video node - -This commit adds video node. - -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 5acc1085526d..b0283e03e9ff 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -359,6 +359,16 @@ - status = "disabled"; - }; - -+ video: video@1e700000 { -+ compatible = "aspeed,ast2600-video-engine"; -+ reg = <0x1e700000 0x1000>; -+ clocks = <&syscon ASPEED_CLK_GATE_VCLK>, -+ <&syscon ASPEED_CLK_GATE_ECLK>; -+ clock-names = "vclk", "eclk"; -+ interrupts = ; -+ status = "disabled"; -+ }; -+ - gpio0: gpio@1e780000 { - #gpio-cells = <2>; - gpio-controller; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch deleted file mode 100644 index 1d8b722de..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 1765cb18bacff9d1f48b833f44da198a09f7d5cb Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 26 Nov 2019 16:39:16 -0800 -Subject: [PATCH] media: aspeed: add aspeed,ast2600-video-engine compatible - string - -This commit adds "aspeed,ast2600-video-engine" compatible string -to support AST2600 video engine H/W. Also. it adds G6 specific -register handling flow. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/media/platform/aspeed-video.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c -index db45502774b1..fe70ad408375 100644 ---- a/drivers/media/platform/aspeed-video.c -+++ b/drivers/media/platform/aspeed-video.c -@@ -72,8 +72,8 @@ - #define VE_SEQ_CTRL_CAP_BUSY BIT(16) - #define VE_SEQ_CTRL_COMP_BUSY BIT(18) - --#ifdef CONFIG_MACH_ASPEED_G5 --#define VE_SEQ_CTRL_JPEG_MODE BIT(13) /* AST2500 */ -+#if defined(CONFIG_MACH_ASPEED_G5) || defined(CONFIG_MACH_ASPEED_G6) -+#define VE_SEQ_CTRL_JPEG_MODE BIT(13) /* AST2500/2600 */ - #else - #define VE_SEQ_CTRL_JPEG_MODE BIT(8) /* AST2400 */ - #endif /* CONFIG_MACH_ASPEED_G5 */ -@@ -135,6 +135,12 @@ - - #define VE_OFFSET_COMP_STREAM 0x078 - -+#ifdef CONFIG_MACH_ASPEED_G6 -+#define VE_JPEG_COMP_SIZE_READ_BACK 0x084 /* AST2600 */ -+#else -+#define VE_JPEG_COMP_SIZE_READ_BACK VE_OFFSET_COMP_STREAM -+#endif -+ - #define VE_SRC_LR_EDGE_DET 0x090 - #define VE_SRC_LR_EDGE_DET_LEFT GENMASK(11, 0) - #define VE_SRC_LR_EDGE_DET_NO_V BIT(12) -@@ -572,7 +578,7 @@ static irqreturn_t aspeed_video_irq(int irq, void *arg) - if (sts & VE_INTERRUPT_COMP_COMPLETE) { - struct aspeed_video_buffer *buf; - u32 frame_size = aspeed_video_read(video, -- VE_OFFSET_COMP_STREAM); -+ VE_JPEG_COMP_SIZE_READ_BACK); - - spin_lock(&video->lock); - clear_bit(VIDEO_FRAME_INPRG, &video->flags); -@@ -1718,6 +1724,7 @@ static int aspeed_video_remove(struct platform_device *pdev) - static const struct of_device_id aspeed_video_of_match[] = { - { .compatible = "aspeed,ast2400-video-engine" }, - { .compatible = "aspeed,ast2500-video-engine" }, -+ { .compatible = "aspeed,ast2600-video-engine" }, - {} - }; - MODULE_DEVICE_TABLE(of, aspeed_video_of_match); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch deleted file mode 100644 index 34df0882b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0088-clk-ast2600-enable-ESPICLK-always.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 37efef00064a228c3e723b0eece22d72f2632705 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 6 Dec 2019 13:51:37 -0800 -Subject: [PATCH] clk: ast2600: enable ESPICLK always - -To support continous eSPI H/W handshaking, this patch enables -ESPICLK always so that there discontinuity of eSPI handshaking while -boot BMC. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/clk/clk-ast2600.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c -index 8201d65..21967bc 100644 ---- a/drivers/clk/clk-ast2600.c -+++ b/drivers/clk/clk-ast2600.c -@@ -87,7 +87,7 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = { - [ASPEED_CLK_GATE_EMMCCLK] = { 27, 16, "emmcclk-gate", NULL, 0 }, /* For card clk */ - /* Reserved 28/29/30 */ - [ASPEED_CLK_GATE_LCLK] = { 32, 32, "lclk-gate", NULL, 0 }, /* LPC */ -- [ASPEED_CLK_GATE_ESPICLK] = { 33, -1, "espiclk-gate", NULL, 0 }, /* eSPI */ -+ [ASPEED_CLK_GATE_ESPICLK] = { 33, -1, "espiclk-gate", NULL, CLK_IS_CRITICAL }, /* eSPI */ - [ASPEED_CLK_GATE_REF1CLK] = { 34, -1, "ref1clk-gate", "clkin", CLK_IS_CRITICAL }, - /* Reserved 35 */ - [ASPEED_CLK_GATE_SDCLK] = { 36, 56, "sdclk-gate", NULL, 0 }, /* SDIO/SD */ --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch deleted file mode 100644 index 962d42e6f..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0089-ast2600-enable-high-speed-uart-in-kernel.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 054391014d04e5b97ae62e1bf5e6aed005f3c67a Mon Sep 17 00:00:00 2001 -From: Kuiying Wang -Date: Fri, 13 Dec 2019 16:15:16 +0800 -Subject: [PATCH] ast2600: enable high speed uart in kernel. - -Tested: -1. Config baud rate to 921600 in BIOS setup page -2. BMC could change env variable "hostserialcfg" to 1. -3. BMC is force to reboot and SPA baud rate is changed to 921600 successfully. -4. It is same for back to 115200. - -Signed-off-by: Kuiying Wang ---- - drivers/clk/clk-ast2600.c | 26 +++++++++++++++++++------- - include/dt-bindings/clock/ast2600-clock.h | 2 ++ - 2 files changed, 21 insertions(+), 7 deletions(-) - -diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c -index c7236e39ef85..af908b2dbeb6 100644 ---- a/drivers/clk/clk-ast2600.c -+++ b/drivers/clk/clk-ast2600.c -@@ -15,7 +15,7 @@ - - #include "clk-aspeed.h" - --#define ASPEED_G6_NUM_CLKS 71 -+#define ASPEED_G6_NUM_CLKS ASPEED_CLK_MAX - - #define ASPEED_G6_SILICON_REV 0x004 - -@@ -43,6 +43,9 @@ - #define ASPEED_MAC12_CLK_DLY 0x340 - #define ASPEED_MAC34_CLK_DLY 0x350 - -+#define ASPEED_G6_GEN_UART_REF 0x338 -+#define UART_192MHZ_R_N_VALUE 0x3c38e -+ - /* Globally visible clocks */ - static DEFINE_SPINLOCK(aspeed_g6_clk_lock); - -@@ -76,7 +79,7 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = { - /* Reserved 11/12 */ - [ASPEED_CLK_GATE_YCLK] = { 13, 4, "yclk-gate", NULL, 0 }, /* HAC */ - [ASPEED_CLK_GATE_USBPORT1CLK] = { 14, 14, "usb-port1-gate", NULL, 0 }, /* USB2 hub/USB2 host port 1/USB1.1 dev */ -- [ASPEED_CLK_GATE_UART5CLK] = { 15, -1, "uart5clk-gate", "uart", 0 }, /* UART5 */ -+ [ASPEED_CLK_GATE_UART5CLK] = { 15, -1, "uart5clk-gate", "uart5", 0 }, /* UART5 */ - /* Reserved 16/19 */ - [ASPEED_CLK_GATE_MAC1CLK] = { 20, 11, "mac1clk-gate", "mac12", 0 }, /* MAC1 */ - [ASPEED_CLK_GATE_MAC2CLK] = { 21, 12, "mac2clk-gate", "mac12", 0 }, /* MAC2 */ -@@ -437,17 +440,26 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) - return ret; - } - -- /* UART clock div13 setting */ -- regmap_read(map, ASPEED_G6_MISC_CTRL, &val); -- if (val & UART_DIV13_EN) -- rate = 24000000 / 13; -+ /* UART clock setting */ -+ regmap_read(map, ASPEED_G6_GEN_UART_REF, &val); -+ if (val == UART_192MHZ_R_N_VALUE){ -+ rate = 192000000 / 13; -+ dev_err(dev, "192Mhz baud rate 921600\n"); -+ } - else -- rate = 24000000; -+ rate = 24000000 / 13; - hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate); - if (IS_ERR(hw)) - return PTR_ERR(hw); - aspeed_g6_clk_data->hws[ASPEED_CLK_UART] = hw; - -+ /* UART5 clock setting */ -+ rate = 24000000 / 13; -+ hw = clk_hw_register_fixed_rate(dev, "uart5", NULL, 0, rate); -+ if (IS_ERR(hw)) -+ return PTR_ERR(hw); -+ aspeed_g6_clk_data->hws[ASPEED_CLK_UART5] = hw; -+ - /* UART6~13 clock div13 setting */ - regmap_read(map, 0x80, &val); - if (val & BIT(31)) -diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h -index 3d90582a813f..4952f7683be7 100644 ---- a/include/dt-bindings/clock/ast2600-clock.h -+++ b/include/dt-bindings/clock/ast2600-clock.h -@@ -87,6 +87,8 @@ - #define ASPEED_CLK_MAC2RCLK 68 - #define ASPEED_CLK_MAC3RCLK 69 - #define ASPEED_CLK_MAC4RCLK 70 -+#define ASPEED_CLK_UART5 71 -+#define ASPEED_CLK_MAX 72 - - /* Only list resets here that are not part of a gate */ - #define ASPEED_RESET_ADC 55 --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch deleted file mode 100644 index 475e9611f..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0090-peci-cpupower-driver-1.patch +++ /dev/null @@ -1,405 +0,0 @@ -From e40f7d10d5306c075e2fc7e538ce1efc70eeb448 Mon Sep 17 00:00:00 2001 -From: ZhikuiRen -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 ---- - 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 -+ -+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 -+#include -+#include -+#include -+#include -+#include -+#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 "); -+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 deleted file mode 100644 index f8a05fd7c..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0092-SPI-Quad-IO-driver-support-AST2600.patch +++ /dev/null @@ -1,136 +0,0 @@ -From f231c8d6babe5ac1b74ab4eb09901b864020a83f Mon Sep 17 00:00:00 2001 -From: arun-pm -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 ---- - drivers/mtd/spi-nor/aspeed-smc.c | 49 ++++++++++++++++++++++++++++++++++------ - drivers/mtd/spi-nor/spi-nor.c | 7 +++++- - 2 files changed, 48 insertions(+), 8 deletions(-) - -diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c -index 0805dcab8cb1..6e2f3802d162 100644 ---- a/drivers/mtd/spi-nor/aspeed-smc.c -+++ b/drivers/mtd/spi-nor/aspeed-smc.c -@@ -21,6 +21,11 @@ - #include - - #define DEVICE_NAME "aspeed-smc" -+#define AST2600A0 0x05000303 -+#define AST2600A0_MAX_FREQ 50000000 -+#define AST2600A0_SAFE_FREQ 40000000 -+#define AST_MAX_FREQ 100000000 -+#define AST2600_REVISION_ID_SCU 0x1e6e2004 - - /* - * The driver only support SPI flash -@@ -542,6 +547,10 @@ static int aspeed_smc_get_io_mode(struct aspeed_smc_chip *chip) - return CONTROL_IO_DUAL_DATA; - case SNOR_PROTO_1_2_2: - return CONTROL_IO_DUAL_ADDR_DATA; -+ case SNOR_PROTO_1_1_4: -+ return CONTROL_IO_QUAD_DATA; -+ case SNOR_PROTO_1_4_4: -+ return CONTROL_IO_QUAD_ADDR_DATA; - default: - dev_err(chip->nor.dev, "unsupported SPI read mode\n"); - return -EINVAL; -@@ -573,7 +582,7 @@ static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, - aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); - - /* Set IO mode only for data */ -- if (io_mode == CONTROL_IO_DUAL_DATA) -+ if (io_mode == CONTROL_IO_DUAL_DATA || io_mode == CONTROL_IO_QUAD_DATA) - aspeed_smc_set_io_mode(chip, io_mode); - - aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len); -@@ -1222,20 +1231,35 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) - return 0; - } - -+static void aspeed_allowed_max_freq(struct aspeed_smc_chip *chip) -+{ -+ void __iomem *scu_ast_revision_id = ioremap(AST2600_REVISION_ID_SCU, 4); -+ u32 rev_id = readl(scu_ast_revision_id); -+ -+ /*Limit max spi frequency less than 50MHz on AST2600-A0 due -+ * to FWSPICLK signal quality issue. -+ */ -+ if(rev_id == AST2600A0 && chip->clk_rate > AST2600A0_MAX_FREQ) -+ chip->clk_rate = AST2600A0_MAX_FREQ; -+} -+ -+static u32 get_hwcaps(unsigned int tx_width){ -+ if(tx_width == 4) -+ return SNOR_HWCAPS_READ_1_1_4; -+ else -+ return SNOR_HWCAPS_READ_1_1_2; -+} -+ - static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller, - struct device_node *np, struct resource *r) - { -- const struct spi_nor_hwcaps hwcaps = { -- .mask = SNOR_HWCAPS_READ | -- SNOR_HWCAPS_READ_FAST | -- SNOR_HWCAPS_READ_1_1_2 | -- SNOR_HWCAPS_PP, -- }; -+ struct spi_nor_hwcaps hwcaps; - const struct aspeed_smc_info *info = controller->info; - struct device *dev = controller->dev; - struct device_node *child; - unsigned int cs; - int ret = -ENODEV; -+ unsigned int spi_tx_width; - - for_each_available_child_of_node(np, child) { - struct aspeed_smc_chip *chip; -@@ -1276,9 +1300,20 @@ static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller, - &chip->clk_rate)) { - chip->clk_rate = ASPEED_SPI_DEFAULT_FREQ; - } -+ aspeed_allowed_max_freq(chip); - dev_info(dev, "Using %d MHz SPI frequency\n", - chip->clk_rate / 1000000); - -+ if (of_property_read_u32(child, "spi-tx-bus-width", -+ &spi_tx_width)) { -+ spi_tx_width = 2; -+ } -+ dev_info(dev, "tx width: %ld\n", spi_tx_width); -+ -+ hwcaps.mask = SNOR_HWCAPS_READ | -+ SNOR_HWCAPS_READ_FAST | -+ get_hwcaps(spi_tx_width) | -+ SNOR_HWCAPS_PP; - chip->controller = controller; - chip->ctl = controller->regs + info->ctl0 + cs * 4; - chip->cs = cs; -diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c -index 3668a862d37d..50904876cb09 100644 ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2315,7 +2315,12 @@ static const struct flash_info spi_nor_ids[] = { - SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, - { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | - SPI_NOR_QUAD_READ) }, -- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, -+ /* Removed n25q00 Quad I/O support for the time being due to clock issue with chip 'Micron 8UA15 - rw182 (128MB)' -+ * while enabling Quad I/O mode. As this chip is default shipped in platforms, marking it -+ * as Not supported for the time being. Once all chips are replaced with the new model, this can be enabled -+ * back(Note:- Certain other chips having same name(n25q00) but different part number has no issues). -+ */ -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | NO_CHIP_ERASE) }, - { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, - { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096, - SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch deleted file mode 100644 index 4b3b6b838..000000000 --- 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 +++ /dev/null @@ -1,37 +0,0 @@ -From 8be7c34e78bd09fa95ce9972332c8c2bb950ec03 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -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 ---- - drivers/char/ipmi/ipmb_dev_int.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c -index 382e4a1df510..c5db37266724 100644 ---- a/drivers/char/ipmi/ipmb_dev_int.c -+++ b/drivers/char/ipmi/ipmb_dev_int.c -@@ -328,8 +328,12 @@ static int ipmb_probe(struct i2c_client *client, - if (ret) - return ret; - -+#if 1 /* FIXME: Quick fix. Need to add parsing code for ipmb_id instead */ -+ ipmb_dev->is_i2c_protocol = true; -+#else - ipmb_dev->is_i2c_protocol - = device_property_read_bool(&client->dev, "i2c-protocol"); -+#endif - - ipmb_dev->client = client; - i2c_set_clientdata(client, ipmb_dev); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch deleted file mode 100644 index 3e426edcd..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f280c15c79e7d13e4a59d413a3091eb21b56dd92 Mon Sep 17 00:00:00 2001 -From: Johnathan Mantey -Date: Mon, 27 Jan 2020 09:03:56 -0800 -Subject: [PATCH] Return link speed and duplex settings for the NCSI channel - -The ftgmac100_open function initializes state for the NCSI -channel. The get link settings function does not return this -data. This caused the link speed, and the duplex value to be returned -incorrectly by the PHY driver (0 Mbps, and duplex off). - -Update the driver to return either the PHY settings when not using -NCSI, or the NCSI values that were assigned when the driver is opened. - -Signed-off-by: Johnathan Mantey ---- - drivers/net/ethernet/faraday/ftgmac100.c | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c -index 8ed85037f021..a53878eecfc8 100644 ---- a/drivers/net/ethernet/faraday/ftgmac100.c -+++ b/drivers/net/ethernet/faraday/ftgmac100.c -@@ -1218,10 +1218,30 @@ static int ftgmac100_set_pauseparam(struct net_device *netdev, - return 0; - } - -+int ftgmac100_ethtool_get_link_ksettings(struct net_device *netdev, -+ struct ethtool_link_ksettings *cmd) -+{ -+ struct phy_device *phydev = netdev->phydev; -+ struct ftgmac100 *priv = netdev_priv(netdev); -+ int retval = 0; -+ -+ if (phydev) { -+ phy_ethtool_ksettings_get(phydev, cmd); -+ } else if (priv->use_ncsi) { -+ cmd->base.speed = priv->cur_speed; -+ cmd->base.duplex = priv->cur_duplex; -+ cmd->base.autoneg = 0; -+ } else { -+ retval = -ENODEV; -+ } -+ -+ return retval; -+} -+ - static const struct ethtool_ops ftgmac100_ethtool_ops = { - .get_drvinfo = ftgmac100_get_drvinfo, - .get_link = ethtool_op_get_link, -- .get_link_ksettings = phy_ethtool_get_link_ksettings, -+ .get_link_ksettings = ftgmac100_ethtool_get_link_ksettings, - .set_link_ksettings = phy_ethtool_set_link_ksettings, - .nway_reset = phy_ethtool_nway_reset, - .get_ringparam = ftgmac100_get_ringparam, --- -2.24.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch deleted file mode 100644 index badda2d60..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0095-pwm-and-tach-driver-changes-for-ast2600.patch +++ /dev/null @@ -1,783 +0,0 @@ -From ffa6dd9617c65d6387bea50827a2843925aedde9 Mon Sep 17 00:00:00 2001 -From: Ayushi Smriti -Date: Mon, 2 Mar 2020 22:51:46 +0530 -Subject: [PATCH] pwm and tach driver changes for ast2600 - -This commit includes additions/changes in driver code -to support 9 PWM outputs and 9 fan tachometer inputs for -ast2600 - -Signed-off-by: Ayushi Smriti ---- - drivers/hwmon/aspeed-g6-pwm-tacho.c | 328 +++++++++++++++++++----------------- - 1 file changed, 171 insertions(+), 157 deletions(-) - -diff --git a/drivers/hwmon/aspeed-g6-pwm-tacho.c b/drivers/hwmon/aspeed-g6-pwm-tacho.c -index 1894f6ad5edb..9551a17e7f55 100644 ---- a/drivers/hwmon/aspeed-g6-pwm-tacho.c -+++ b/drivers/hwmon/aspeed-g6-pwm-tacho.c -@@ -64,6 +64,9 @@ - #define PWM_RISING_FALLING_BIT (8) //pwm falling point bit [7:0] - #define PWM_RISING_RISING_BIT (0) //pwm rising point bit [7:0] - -+#define PWM_PERIOD_MAX 255 -+#define PWM_FALLING_DEFAULT 255 /* 100% */ -+ - #define ASPEED_TACHO_CTRL 0x08 //TACH0 General Register - #define ASPEED_TACHO_CTRL_CH(x) ((x * 0x10) + 0x08) - #define TACHO_IER BIT(31) //enable tacho interrupt -@@ -72,8 +75,7 @@ - #define TACHO_ENABLE BIT(28) //{enable tacho} - #define TACHO_DEBOUNCE_BIT (26) //{tacho de-bounce} - #define TACHO_DEBOUNCE_MASK (0x3 << 26) //{tacho de-bounce} --#define TECHIO_EDGE_MASK (0x3 << 24) //tacho edge} --#define TECHIO_EDGE_BIT (24) //tacho edge} -+#define TACHIO_EDGE_BIT (24) /*tacho edge}*/ - #define TACHO_CLK_DIV_T_MASK (0xf << 20) - #define TACHO_CLK_DIV_BIT (20) - #define TACHO_THRESHOLD_MASK (0xfffff) //tacho threshold bit -@@ -102,211 +104,181 @@ - - #define MAX_CDEV_NAME_LEN 16 - -+#define DEFAULT_TARGET_PWM_FREQ 25000 -+#define DEFAULT_MIN_RPM 2900 -+ - struct aspeed_pwm_channel_params { -+ int target_freq; -+ int pwm_freq; - int load_wdt_rising_falling_pt; - int load_wdt_selection; //0: rising , 1: falling - int load_wdt_enable; - int duty_sync_enable; - int invert_pin; -- u8 divide_h; -- u8 divide_l; -- u8 period; - u8 rising; - u8 falling; - }; - - static struct aspeed_pwm_channel_params default_pwm_params[] = { - [0] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 1, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [1] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [2] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [3] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [4] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [5] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [6] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [7] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [8] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [9] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [10] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [11] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [12] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [13] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [14] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - [15] = { -+ .target_freq = 25000, - .load_wdt_rising_falling_pt = 0x10, - .load_wdt_selection = 0, - .load_wdt_enable = 0, - .duty_sync_enable = 0, - .invert_pin = 0, -- .divide_h = 0x5, -- .divide_l = 0x6, -- .period = 0x13, //5% ~~ - .rising = 0x00, -- .falling = 0x0a, -+ .falling = PWM_FALLING_DEFAULT, - }, - }; - -@@ -318,125 +290,146 @@ static struct aspeed_pwm_channel_params default_pwm_params[] = { - * 11: reserved. - */ - -+#define F2F_EDGES 0x00 -+#define R2R_EDGES 0x01 -+#define BOTH_EDGES 0x02 -+ - struct aspeed_tacho_channel_params { -+ u32 min_rpm; - int limited_inverse; - u16 threshold; - u8 tacho_edge; - u8 tacho_debounce; -- u8 divide; -+ u32 divide; - }; - - - static struct aspeed_tacho_channel_params default_tacho_params[] = { - [0] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [1] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [2] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [3] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [4] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [5] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [6] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [7] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [8] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [9] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [10] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [11] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [12] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [13] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [14] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, - [15] = { -+ .min_rpm = 2900, - .limited_inverse = 0, - .threshold = 0, -- .tacho_edge = 0, -+ .tacho_edge = F2F_EDGES, - .tacho_debounce = 0, - .divide = 8, - }, -@@ -501,29 +494,29 @@ static void aspeed_set_pwm_channel_enable(struct regmap *regmap, u8 pwm_channel, - static void aspeed_set_fan_tach_ch_enable(struct aspeed_pwm_tachometer_data *priv, u8 fan_tach_ch, - bool enable) - { -- u32 i = 0, j; -+ u32 i; - u32 divide_val = 0; -+ u32 target_div; - u32 reg_value = 0; - - if(enable) { -- //4 ^ n -- //check pwm clk and to change tacho devide 25KZ -- for(i = 0; i < 12; i++) { -+ /*RPM calculation as per ast2600 datasheet*/ -+ target_div = (priv->clk_freq * 60 / priv->tacho_channel[fan_tach_ch].min_rpm * 2) / (0xfffff + 1); -+ if (target_div) { -+ for (i = 0; i < 12; i++) { -+ divide_val = BIT(i) * BIT(i); -+ if (divide_val > target_div) -+ break; -+ } -+ } else { -+ i = 0; - divide_val = 1; -- for (j = 1; j <= i; j++) -- divide_val *= 4; --// printk("i : %d , priv->clk_freq/divide_val %d ",i, priv->clk_freq/divide_val); -- if((priv->clk_freq/divide_val) < 250000) -- break; - } -- i--; -- divide_val = ((1 << i) * (1 << i)); --// printk("tacho divide_val %d , i %x max tacho clk %d \n", divide_val, i, priv->clk_freq / divide_val); -- priv->tacho_channel[fan_tach_ch].divide = i; -+ priv->tacho_channel[fan_tach_ch].divide = divide_val; - - reg_value = TACHO_ENABLE | -- (priv->tacho_channel[fan_tach_ch].tacho_edge << TECHIO_EDGE_BIT) | -- (priv->tacho_channel[fan_tach_ch].divide << TACHO_CLK_DIV_BIT) | -+ (priv->tacho_channel[fan_tach_ch].tacho_edge << TACHIO_EDGE_BIT) | -+ (i << TACHO_CLK_DIV_BIT) | - (priv->tacho_channel[fan_tach_ch].tacho_debounce << TACHO_DEBOUNCE_BIT); - - if(priv->tacho_channel[fan_tach_ch].limited_inverse) -@@ -541,14 +534,28 @@ static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *p - u8 index, u8 fan_ctrl) - { - u32 duty_value, ctrl_value; -+ u32 div_h, div_l, cal_freq; - - if (fan_ctrl == 0) { - aspeed_set_pwm_channel_enable(priv->regmap, index, false); - } else { -- duty_value = (priv->pwm_channel[index].period << PWM_PERIOD_BIT) | -- (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT); -+ cal_freq = priv->clk_freq / (PWM_PERIOD_MAX + 1); -+ /*calculate for target frequence*/ -+ for (div_l = 0; div_l < 0x100; div_l++) { -+ for (div_h = 0; div_h < 0x10; div_h++) { -+ if ((cal_freq / (BIT(div_h) * (div_l + 1))) < priv->pwm_channel[index].target_freq) -+ break; -+ } -+ if ((cal_freq / (BIT(div_h) * (div_l + 1))) < priv->pwm_channel[index].target_freq) -+ break; -+ } - -- ctrl_value = (priv->pwm_channel[index].divide_h << 8) | priv->pwm_channel[index].divide_l; -+ priv->pwm_channel[index].pwm_freq = cal_freq / (BIT(div_h) * (div_l + 1)); -+ -+ ctrl_value = (div_h << 8) | div_l; -+ -+ duty_value = (PWM_PERIOD_MAX << PWM_PERIOD_BIT) | -+ (0 << PWM_RISING_RISING_BIT) | (fan_ctrl << PWM_RISING_FALLING_BIT); - - if (priv->pwm_channel[index].load_wdt_enable) { - ctrl_value |= PWM_DUTY_LOAD_AS_WDT_EN; -@@ -568,13 +575,11 @@ static void aspeed_set_pwm_channel_fan_ctrl(struct aspeed_pwm_tachometer_data *p - } - } - --#define BOTH_EDGES 0x02 /* 10b */ -- - static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv, - u8 fan_tach_ch) - { - u32 raw_data, tach_div, clk_source, val; -- u8 mode, both; -+ u8 multiplier = 2; - int i, retries = 3; - - for(i = 0; i < retries; i++) { -@@ -587,22 +592,15 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tachometer_data *priv, - if(raw_data == 0xfffff) - return 0; - -- tach_div = priv->tacho_channel[fan_tach_ch].divide; -- /* -- * We need the mode to determine if the raw_data is double (from -- * counting both edges). -- */ -- mode = priv->tacho_channel[fan_tach_ch].tacho_edge; -- both = (mode & BOTH_EDGES) ? 1 : 0; --// printk("clk %ld, raw_data %x , tach_div %x both %x \n", priv->clk_freq, raw_data, tach_div, both); -+ raw_data += 1; -+ tach_div = raw_data * (priv->tacho_channel[fan_tach_ch].divide) * (multiplier); - -- tach_div = (tach_div * 2) * (0x1 << both); - clk_source = priv->clk_freq; - - if (raw_data == 0) - return 0; - -- return (clk_source * 60) / (2 * raw_data * tach_div); -+ return (clk_source / tach_div * 60); - - } - -@@ -614,19 +612,27 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - int ret; - struct aspeed_pwm_tachometer_data *priv = dev_get_drvdata(dev); - long fan_ctrl; -+ u8 org_falling = priv->pwm_channel[index].falling; - - ret = kstrtol(buf, 10, &fan_ctrl); - if (ret != 0) - return ret; - -- if (fan_ctrl < 0 || fan_ctrl > priv->pwm_channel[index].period) -+ if (fan_ctrl < 0 || fan_ctrl > PWM_PERIOD_MAX) - return -EINVAL; - - if (priv->pwm_channel[index].falling == fan_ctrl) - return count; - - priv->pwm_channel[index].falling = fan_ctrl; -- aspeed_set_pwm_channel_fan_ctrl(priv, index, fan_ctrl); -+ -+ if (fan_ctrl == 0) -+ aspeed_set_pwm_channel_enable(priv->regmap, index, false); -+ else -+ regmap_update_bits(priv->regmap, ASPEED_PWM_DUTY_CYCLE_CH(index), GENMASK(15, 8), (fan_ctrl << PWM_RISING_FALLING_BIT)); -+ -+ if (org_falling == 0) -+ aspeed_set_pwm_channel_enable(priv->regmap, index, true); - - return count; - } -@@ -678,40 +684,39 @@ static umode_t fan_dev_is_visible(struct kobject *kobj, - return a->mode; - } - --static SENSOR_DEVICE_ATTR(pwm0, 0644, -- show_pwm, set_pwm, 0); - static SENSOR_DEVICE_ATTR(pwm1, 0644, -- show_pwm, set_pwm, 1); -+ show_pwm, set_pwm, 0); - static SENSOR_DEVICE_ATTR(pwm2, 0644, -- show_pwm, set_pwm, 2); -+ show_pwm, set_pwm, 1); - static SENSOR_DEVICE_ATTR(pwm3, 0644, -- show_pwm, set_pwm, 3); -+ show_pwm, set_pwm, 2); - static SENSOR_DEVICE_ATTR(pwm4, 0644, -- show_pwm, set_pwm, 4); -+ show_pwm, set_pwm, 3); - static SENSOR_DEVICE_ATTR(pwm5, 0644, -- show_pwm, set_pwm, 5); -+ show_pwm, set_pwm, 4); - static SENSOR_DEVICE_ATTR(pwm6, 0644, -- show_pwm, set_pwm, 6); -+ show_pwm, set_pwm, 5); - static SENSOR_DEVICE_ATTR(pwm7, 0644, -- show_pwm, set_pwm, 7); -+ show_pwm, set_pwm, 6); - static SENSOR_DEVICE_ATTR(pwm8, 0644, -- show_pwm, set_pwm, 8); -+ show_pwm, set_pwm, 7); - static SENSOR_DEVICE_ATTR(pwm9, 0644, -- show_pwm, set_pwm, 9); -+ show_pwm, set_pwm, 8); - static SENSOR_DEVICE_ATTR(pwm10, 0644, -- show_pwm, set_pwm, 10); -+ show_pwm, set_pwm, 9); - static SENSOR_DEVICE_ATTR(pwm11, 0644, -- show_pwm, set_pwm, 11); -+ show_pwm, set_pwm, 10); - static SENSOR_DEVICE_ATTR(pwm12, 0644, -- show_pwm, set_pwm, 12); -+ show_pwm, set_pwm, 11); - static SENSOR_DEVICE_ATTR(pwm13, 0644, -- show_pwm, set_pwm, 13); -+ show_pwm, set_pwm, 12); - static SENSOR_DEVICE_ATTR(pwm14, 0644, -- show_pwm, set_pwm, 14); -+ show_pwm, set_pwm, 13); - static SENSOR_DEVICE_ATTR(pwm15, 0644, -+ show_pwm, set_pwm, 14); -+static SENSOR_DEVICE_ATTR(pwm16, 0644, - show_pwm, set_pwm, 15); - static struct attribute *pwm_dev_attrs[] = { -- &sensor_dev_attr_pwm0.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, -@@ -727,6 +732,7 @@ static struct attribute *pwm_dev_attrs[] = { - &sensor_dev_attr_pwm13.dev_attr.attr, - &sensor_dev_attr_pwm14.dev_attr.attr, - &sensor_dev_attr_pwm15.dev_attr.attr, -+ &sensor_dev_attr_pwm16.dev_attr.attr, - NULL, - }; - -@@ -735,40 +741,39 @@ static const struct attribute_group pwm_dev_group = { - .is_visible = pwm_is_visible, - }; - --static SENSOR_DEVICE_ATTR(fan0_input, 0444, -- show_rpm, NULL, 0); - static SENSOR_DEVICE_ATTR(fan1_input, 0444, -- show_rpm, NULL, 1); -+ show_rpm, NULL, 0); - static SENSOR_DEVICE_ATTR(fan2_input, 0444, -- show_rpm, NULL, 2); -+ show_rpm, NULL, 1); - static SENSOR_DEVICE_ATTR(fan3_input, 0444, -- show_rpm, NULL, 3); -+ show_rpm, NULL, 2); - static SENSOR_DEVICE_ATTR(fan4_input, 0444, -- show_rpm, NULL, 4); -+ show_rpm, NULL, 3); - static SENSOR_DEVICE_ATTR(fan5_input, 0444, -- show_rpm, NULL, 5); -+ show_rpm, NULL, 4); - static SENSOR_DEVICE_ATTR(fan6_input, 0444, -- show_rpm, NULL, 6); -+ show_rpm, NULL, 5); - static SENSOR_DEVICE_ATTR(fan7_input, 0444, -- show_rpm, NULL, 7); -+ show_rpm, NULL, 6); - static SENSOR_DEVICE_ATTR(fan8_input, 0444, -- show_rpm, NULL, 8); -+ show_rpm, NULL, 7); - static SENSOR_DEVICE_ATTR(fan9_input, 0444, -- show_rpm, NULL, 9); -+ show_rpm, NULL, 8); - static SENSOR_DEVICE_ATTR(fan10_input, 0444, -- show_rpm, NULL, 10); -+ show_rpm, NULL, 9); - static SENSOR_DEVICE_ATTR(fan11_input, 0444, -- show_rpm, NULL, 11); -+ show_rpm, NULL, 10); - static SENSOR_DEVICE_ATTR(fan12_input, 0444, -- show_rpm, NULL, 12); -+ show_rpm, NULL, 11); - static SENSOR_DEVICE_ATTR(fan13_input, 0444, -- show_rpm, NULL, 13); -+ show_rpm, NULL, 12); - static SENSOR_DEVICE_ATTR(fan14_input, 0444, -- show_rpm, NULL, 14); -+ show_rpm, NULL, 13); - static SENSOR_DEVICE_ATTR(fan15_input, 0444, -+ show_rpm, NULL, 14); -+static SENSOR_DEVICE_ATTR(fan16_input, 0444, - show_rpm, NULL, 15); - static struct attribute *fan_dev_attrs[] = { -- &sensor_dev_attr_fan0_input.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, -@@ -784,6 +789,7 @@ static struct attribute *fan_dev_attrs[] = { - &sensor_dev_attr_fan13_input.dev_attr.attr, - &sensor_dev_attr_fan14_input.dev_attr.attr, - &sensor_dev_attr_fan15_input.dev_attr.attr, -+ &sensor_dev_attr_fan16_input.dev_attr.attr, - NULL - }; - -@@ -802,14 +808,14 @@ static void aspeed_create_pwm_channel(struct aspeed_pwm_tachometer_data *priv, - } - - static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tachometer_data *priv, -- u8 *fan_tach_ch, -- int count) -+ u8 *fan_tach_ch, int count, u32 min_rpm) - { - u8 val, index; - - for (val = 0; val < count; val++) { - index = fan_tach_ch[val]; - priv->fan_tach_present[index] = true; -+ priv->tacho_channel[index].min_rpm = min_rpm; - aspeed_set_fan_tach_ch_enable(priv, index, true); - } - } -@@ -906,13 +912,19 @@ static int aspeed_pwm_create_fan(struct device *dev, - struct aspeed_pwm_tachometer_data *priv) - { - u8 *fan_tach_ch; -+ u32 fan_min_rpm; - u32 pwm_channel; -+ u32 target_pwm_freq; - int ret, count; - - ret = of_property_read_u32(child, "reg", &pwm_channel); - if (ret) - return ret; - -+ ret = of_property_read_u32(child, "aspeed,target_pwm", &target_pwm_freq); -+ if (ret) -+ target_pwm_freq = DEFAULT_TARGET_PWM_FREQ; -+ - aspeed_create_pwm_channel(priv, (u8)pwm_channel); - - ret = of_property_count_u8_elems(child, "cooling-levels"); -@@ -935,9 +947,11 @@ static int aspeed_pwm_create_fan(struct device *dev, - fan_tach_ch, count); - if (ret) - return ret; -+ ret = of_property_read_u32(child, "aspeed,min_rpm", &fan_min_rpm); -+ if (ret) -+ fan_min_rpm = DEFAULT_MIN_RPM; - -- aspeed_create_fan_tach_channel(priv, fan_tach_ch, count); -- -+ aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, fan_min_rpm); - return 0; - } - --- -2.7.4 - 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 deleted file mode 100644 index e2196c629..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 7555448ab0676ea974ef67ef0c8ebe5d68b73d25 Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -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 ---- - drivers/peci/peci-core.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index 9aedb74..efb73b0 100644 ---- a/drivers/peci/peci-core.c -+++ b/drivers/peci/peci-core.c -@@ -1040,7 +1040,6 @@ static int peci_cmd_wr_end_pt_cfg(struct peci_adapter *adapter, void *vmsg) - >> 24); /* MSB - DWORD Register Offset */ - if (umsg->params.mmio.addr_type == - PECI_ENDPTCFG_ADDR_TYPE_MMIO_Q) { -- msg->tx_len = PECI_WRENDPTCFG_MMIO_Q_WRITE_LEN_BASE; - msg->tx_buf[14] = (u8)(umsg->params.mmio.offset - >> 32); /* Register Offset */ - msg->tx_buf[15] = (u8)(umsg->params.mmio.offset --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch deleted file mode 100644 index cb06f9def..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0100-Mailbox-Enabling-interrupt-based-mailbox.patch +++ /dev/null @@ -1,237 +0,0 @@ -From d5bc758cee51d92c48f2835ca2b4ebb146f0f0b4 Mon Sep 17 00:00:00 2001 -From: "Arun P. Mohanan" -Date: Wed, 11 Mar 2020 17:23:49 +0530 -Subject: [PATCH] [Mailbox] Enabling interrupt based mailbox - -Modifying the mailbox driver to use FIFO queue while using interrupt. - -Signed-off-by: Arun P. Mohanan ---- - drivers/soc/aspeed/aspeed-lpc-mbox.c | 102 ++++++++++++++++++--------- - 1 file changed, 69 insertions(+), 33 deletions(-) - -diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c -index 795107206022..1ca68bb3534c 100644 ---- a/drivers/soc/aspeed/aspeed-lpc-mbox.c -+++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c -@@ -12,10 +12,11 @@ - #include - #include - #include -+#include - - #define DEVICE_NAME "aspeed-mbox" - --#define MBX_USE_INTERRUPT 0 -+#define MBX_USE_INTERRUPT 1 - - #define ASPEED_MBOX_NUM_REGS 16 - -@@ -29,6 +30,7 @@ - #define ASPEED_MBOX_HOST_CTRL 0x4c - #define ASPEED_MBOX_INTERRUPT_0 0x50 - #define ASPEED_MBOX_INTERRUPT_1 0x54 -+#define MBOX_FIFO_SIZE 64 - - struct aspeed_mbox { - struct miscdevice miscdev; -@@ -38,6 +40,8 @@ struct aspeed_mbox { - int irq; - wait_queue_head_t queue; - struct mutex mutex; -+ struct kfifo fifo; -+ spinlock_t lock; - }; - - static atomic_t aspeed_mbox_open_count = ATOMIC_INIT(0); -@@ -74,20 +78,37 @@ static struct aspeed_mbox *file_mbox(struct file *file) - return container_of(file->private_data, struct aspeed_mbox, miscdev); - } - -+/* Save a byte to a FIFO and discard the oldest byte if FIFO is full */ -+static void put_fifo_with_discard(struct aspeed_mbox *mbox, u8 val) -+{ -+ if (!kfifo_initialized(&mbox->fifo)) -+ return; -+ if (kfifo_is_full(&mbox->fifo)) -+ kfifo_skip(&mbox->fifo); -+ kfifo_put(&mbox->fifo, val); -+} -+ - static int aspeed_mbox_open(struct inode *inode, struct file *file) - { - #if MBX_USE_INTERRUPT - struct aspeed_mbox *mbox = file_mbox(file); -+ int i; - #endif - - if (atomic_inc_return(&aspeed_mbox_open_count) == 1) { - #if MBX_USE_INTERRUPT - /* -- * Clear the interrupt status bit if it was left on and unmask -- * interrupts. -- * ASPEED_MBOX_CTRL_RECV bit is W1C, this also unmasks in 1 step -+ * Reset the FIFO while opening to clear the old cached data -+ * and load the FIFO with latest mailbox register values. - */ -- aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); -+ kfifo_reset(&mbox->fifo); -+ spin_lock_irq(&mbox->lock); -+ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) { -+ put_fifo_with_discard(mbox, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4))); -+ } -+ spin_unlock_irq(&mbox->lock); -+ - #endif - return 0; - } -@@ -102,6 +123,8 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, - struct aspeed_mbox *mbox = file_mbox(file); - char __user *p = buf; - ssize_t ret; -+ unsigned int copied; -+ unsigned long flags; - int i; - - if (!access_ok(buf, count)) -@@ -111,17 +134,32 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, - return -EINVAL; - - #if MBX_USE_INTERRUPT -- if (file->f_flags & O_NONBLOCK) { -- if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -- ASPEED_MBOX_CTRL_RECV)) -+ /* -+ * Restrict count as per the number of mailbox registers -+ * to use kfifo. -+ */ -+ if (count != ASPEED_MBOX_NUM_REGS) -+ goto reg_read; -+ -+ if (kfifo_is_empty(&mbox->fifo)) { -+ if (file->f_flags & O_NONBLOCK){ - return -EAGAIN; -- } else if (wait_event_interruptible(mbox->queue, -- aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & -- ASPEED_MBOX_CTRL_RECV)) { -- return -ERESTARTSYS; -+ } -+ ret = wait_event_interruptible(mbox->queue, -+ !kfifo_is_empty(&mbox->fifo)); -+ if (ret == -ERESTARTSYS){ -+ return -EINTR; -+ } - } -+ -+ spin_lock_irqsave(&mbox->lock, flags); -+ ret = kfifo_to_user(&mbox->fifo, buf, count, &copied); -+ spin_unlock_irqrestore(&mbox->lock, flags); -+ return ret ? ret : copied; -+ - #endif - -+reg_read: - mutex_lock(&mbox->mutex); - - for (i = *ppos; count > 0 && i < ASPEED_MBOX_NUM_REGS; i++) { -@@ -134,11 +172,6 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, - p++; - count--; - } -- --#if MBX_USE_INTERRUPT -- /* ASPEED_MBOX_CTRL_RECV bit is write to clear, this also unmasks in 1 step */ -- aspeed_mbox_outb(mbox, ASPEED_MBOX_CTRL_RECV, ASPEED_MBOX_BMC_CTRL); --#endif - ret = p - buf; - - out_unlock: -@@ -186,16 +219,9 @@ static ssize_t aspeed_mbox_write(struct file *file, const char __user *buf, - static unsigned int aspeed_mbox_poll(struct file *file, poll_table *wait) - { - struct aspeed_mbox *mbox = file_mbox(file); -- unsigned int mask = 0; - - poll_wait(file, &mbox->queue, wait); -- --#if MBX_USE_INTERRUPT -- if (aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV) --#endif -- mask |= POLLIN; -- -- return mask; -+ return !kfifo_is_empty(&mbox->fifo) ? POLLIN : 0; - } - - static int aspeed_mbox_release(struct inode *inode, struct file *file) -@@ -220,19 +246,23 @@ static irqreturn_t aspeed_mbox_irq(int irq, void *arg) - #if MBX_USE_INTERRUPT - int i; - --// if (!(aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL) & ASPEED_MBOX_CTRL_RECV)) --// return IRQ_NONE; -- -- printk(KERN_ERR "BMC_CTRL: 0x%02x\n", -+ dev_dbg(mbox->miscdev.parent, "BMC_CTRL11: 0x%02x\n", - aspeed_mbox_inb(mbox, ASPEED_MBOX_BMC_CTRL)); -- printk(KERN_ERR "STATUS_0: 0x%02x\n", -+ dev_dbg(mbox->miscdev.parent, "STATUS_0: 0x%02x\n", - aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_0)); -- printk(KERN_ERR "STATUS_1: 0x%02x\n", -+ dev_dbg(mbox->miscdev.parent, "STATUS_1: 0x%02x\n", - aspeed_mbox_inb(mbox, ASPEED_MBOX_STATUS_1)); - for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) { -- printk(KERN_ERR "DATA_%d: 0x%02x\n", i, -+ dev_dbg(mbox->miscdev.parent, "DATA_%d: 0x%02x\n", i, - aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4))); - } -+ -+ spin_lock(&mbox->lock); -+ for (i = 0; i < ASPEED_MBOX_NUM_REGS; i++) { -+ put_fifo_with_discard(mbox, -+ aspeed_mbox_inb(mbox, ASPEED_MBOX_DATA_0 + (i * 4))); -+ } -+ spin_unlock(&mbox->lock); - #endif - - /* Clear interrupt status */ -@@ -249,7 +279,6 @@ static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox, - { - struct device *dev = &pdev->dev; - int rc; -- - mbox->irq = platform_get_irq(pdev, 0); - if (!mbox->irq) - return -ENODEV; -@@ -300,6 +329,7 @@ static int aspeed_mbox_probe(struct platform_device *pdev) - return -ENODEV; - } - -+ spin_lock_init(&mbox->lock); - mutex_init(&mbox->mutex); - init_waitqueue_head(&mbox->queue); - -@@ -316,6 +346,11 @@ static int aspeed_mbox_probe(struct platform_device *pdev) - return rc; - } - -+ /* Create FIFO data structure */ -+ rc = kfifo_alloc(&mbox->fifo, MBOX_FIFO_SIZE, GFP_KERNEL); -+ if (rc) -+ return rc; -+ - mbox->miscdev.minor = MISC_DYNAMIC_MINOR; - mbox->miscdev.name = DEVICE_NAME; - mbox->miscdev.fops = &aspeed_mbox_fops; -@@ -349,6 +384,7 @@ static int aspeed_mbox_remove(struct platform_device *pdev) - - misc_deregister(&mbox->miscdev); - clk_disable_unprepare(mbox->clk); -+ kfifo_free(&mbox->fifo); - - return 0; - } --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch deleted file mode 100644 index b4118e169..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0101-Add-poll-fops-in-eSPI-driver.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 9479d8f12efc845faca4bb1aef9b6e63799a7e5c Mon Sep 17 00:00:00 2001 -From: "Arun P. Mohanan" -Date: Wed, 18 Mar 2020 08:34:43 +0530 -Subject: [PATCH] Add poll fops in eSPI driver - -Modify eSPI driver to support poll fops. - -Signed-off-by: Arun P. Mohanan ---- - drivers/misc/aspeed-espi-slave.c | 85 +++++++++++++++++++++++--------- - 1 file changed, 61 insertions(+), 24 deletions(-) - -diff --git a/drivers/misc/aspeed-espi-slave.c b/drivers/misc/aspeed-espi-slave.c -index 87bc81948694..cb8ed585c69f 100644 ---- a/drivers/misc/aspeed-espi-slave.c -+++ b/drivers/misc/aspeed-espi-slave.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -95,6 +96,7 @@ struct aspeed_espi { - spinlock_t pltrstn_lock; /* for PLTRST_N signal sampling */ - wait_queue_head_t pltrstn_waitq; - char pltrstn; -+ bool pltrstn_in_avail; - }; - - static void aspeed_espi_sys_event(struct aspeed_espi *priv) -@@ -127,7 +129,10 @@ static void aspeed_espi_sys_event(struct aspeed_espi *priv) - dev_dbg(priv->dev, "SYSEVT_OOB_RST_WARN: acked\n"); - } - if (sts & ASPEED_ESPI_SYSEVT_PLTRSTN || priv->pltrstn == 'U') { -+ spin_lock(&priv->pltrstn_lock); - priv->pltrstn = (evt & ASPEED_ESPI_SYSEVT_PLTRSTN) ? '1' : '0'; -+ priv->pltrstn_in_avail = true; -+ spin_unlock(&priv->pltrstn_lock); - wake_up_interruptible(&priv->pltrstn_waitq); - dev_dbg(priv->dev, "SYSEVT_PLTRSTN: %c\n", priv->pltrstn); - } -@@ -269,6 +274,8 @@ static int aspeed_espi_pltrstn_open(struct inode *inode, struct file *filp) - { - if ((filp->f_flags & O_ACCMODE) != O_RDONLY) - return -EACCES; -+ struct aspeed_espi *priv = to_aspeed_espi(filp); -+ priv->pltrstn_in_avail = true ; /*Setting true returns first data after file open*/ - - return 0; - } -@@ -284,41 +291,71 @@ static ssize_t aspeed_espi_pltrstn_read(struct file *filp, char __user *buf, - - spin_lock_irqsave(&priv->pltrstn_lock, flags); - -- add_wait_queue(&priv->pltrstn_waitq, &wait); -- set_current_state(TASK_INTERRUPTIBLE); -- -- old_sample = priv->pltrstn; -- -- do { -- char new_sample = priv->pltrstn; -- -- if (filp->f_flags & O_NONBLOCK || old_sample != new_sample) { -- ret = put_user(new_sample, (unsigned long __user *)buf); -- if (!ret) -- ret = sizeof(new_sample); -- } else if (signal_pending(current)) { -- ret = -ERESTARTSYS; -+ if (filp->f_flags & O_NONBLOCK) { -+ if (!priv->pltrstn_in_avail) { -+ ret = -EAGAIN; -+ goto out_unlock; - } -- -- if (!ret) { -- spin_unlock_irqrestore(&priv->pltrstn_lock, flags); -- schedule(); -- spin_lock_irqsave(&priv->pltrstn_lock, flags); -+ char data = priv->pltrstn; -+ ret = put_user(data, (unsigned long __user *)buf); -+ if (!ret){ -+ ret = sizeof(data); -+ } else{ -+ ret = -EAGAIN; - } -- } while (!ret); -- -- remove_wait_queue(&priv->pltrstn_waitq, &wait); -- set_current_state(TASK_RUNNING); -- -+ priv->pltrstn_in_avail = false; -+ } else { -+ add_wait_queue(&priv->pltrstn_waitq, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ old_sample = priv->pltrstn; -+ -+ do { -+ char new_sample = priv->pltrstn; -+ -+ if (old_sample != new_sample) { -+ ret = put_user(new_sample, -+ (unsigned long __user *)buf); -+ if (!ret) -+ ret = sizeof(new_sample); -+ } else if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ } -+ -+ if (!ret) { -+ spin_unlock_irqrestore(&priv->pltrstn_lock, -+ flags); -+ schedule(); -+ spin_lock_irqsave(&priv->pltrstn_lock, flags); -+ } -+ } while (!ret); -+ -+ remove_wait_queue(&priv->pltrstn_waitq, &wait); -+ set_current_state(TASK_RUNNING); -+ } -+out_unlock: - spin_unlock_irqrestore(&priv->pltrstn_lock, flags); - - return ret; - } - -+static unsigned int aspeed_espi_pltrstn_poll(struct file *file, -+ poll_table *wait) -+{ -+ struct aspeed_espi *priv = to_aspeed_espi(file); -+ unsigned int mask = 0; -+ poll_wait(file, &priv->pltrstn_waitq, wait); -+ -+ if (priv->pltrstn_in_avail) -+ mask |= POLLIN; -+ return mask; -+} -+ - static const struct file_operations aspeed_espi_pltrstn_fops = { - .owner = THIS_MODULE, - .open = aspeed_espi_pltrstn_open, - .read = aspeed_espi_pltrstn_read, -+ .poll = aspeed_espi_pltrstn_poll, - }; - - static const struct regmap_config aspeed_espi_regmap_cfg = { --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch deleted file mode 100644 index f3bb26a8a..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 9d4191d2702ad5a368ca79eb253de26ce94b91c7 Mon Sep 17 00:00:00 2001 -From: AppaRao Puli -Date: Mon, 30 Mar 2020 11:00:16 +0530 -Subject: [PATCH] From: Thomas Betker - -jffs2_flash_direct_writev() always invokes jffs2_sum_add_kvec(), even -if mtd_writev() fails. Usually, this results in an extra summary entry -pointing to dirty node space, which should be ignored -- it is a bit of -a waste, but harmless. - -When mtd_writev() returns *retlen == 0, though, the node space is not -reserved as dirty, but re-used; the extra summary entry then points -into the space of the next node. After the erase block has been closed, -we get the following messages on remount: - - jffs2: error: (79) jffs2_link_node_ref: - Adding new ref c3048d18 at (0x00ec5b88-0x00ec6bcc) - not immediately after previous (0x00ec5b88-0x00ec5b88) - ... - jffs2: Checked all inodes but still 0x2088 bytes of unchecked space? - jffs2: No space for garbage collection. Aborting GC thread - -The extra summary entries amount to "unchecked space", so that -jffs2_garbage_collect_pass() returns -ENOSPC. And without garbage -collection, the filesystem becomes unuseable over time as the erase -blocks fill up. - -Fix this by skipping jffs2_sum_add_kvec() when the MTD write fails. We -don't need the summary entry anyway, and the behaviour matches that of -jffs2_flash_writev() in wbuf.c (with write buffering enabled). - -Signed-off-by: Thomas Betker ---- - fs/jffs2/writev.c | 16 +++++++++++++++- - 1 file changed, 15 insertions(+), 1 deletion(-) - -diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c -index a1bda9d..eec4197 100644 ---- a/fs/jffs2/writev.c -+++ b/fs/jffs2/writev.c -@@ -16,9 +16,18 @@ - int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen) - { -+ int ret; -+ -+ ret = mtd_writev(c->mtd, vecs, count, to, retlen); -+ - if (!jffs2_is_writebuffered(c)) { - if (jffs2_sum_active()) { - int res; -+ -+ if (ret || -+ *retlen != iov_length((struct iovec *) vecs, count)) -+ return ret; -+ - res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to); - if (res) { - return res; -@@ -26,19 +35,23 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, - } - } - -- return mtd_writev(c->mtd, vecs, count, to, retlen); -+ return ret; - } - - int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf) - { - int ret; -+ - ret = mtd_write(c->mtd, ofs, len, retlen, buf); - - if (jffs2_sum_active()) { - struct kvec vecs[1]; - int res; - -+ if (ret || *retlen != len) -+ return ret; -+ - vecs[0].iov_base = (unsigned char *) buf; - vecs[0].iov_len = len; - -@@ -47,5 +60,6 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, - return res; - } - } -+ - return ret; - } --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch deleted file mode 100644 index ef234fffe..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0103-Refine-clock-settings.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 9fc2343bac42db2432f96db1bbfc6979822a7154 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 26 Mar 2020 14:20:19 -0700 -Subject: [PATCH] Refine clock settings - -This commit refines clock settings with cherry picking the latest -code from Aspeed SDK v00.05.05 - -Signed-off-by: Jae Hyun Yoo ---- - drivers/clk/clk-ast2600.c | 60 +++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 53 insertions(+), 7 deletions(-) - -diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c -index fb6b11440b97..e07326544fdc 100644 ---- a/drivers/clk/clk-ast2600.c -+++ b/drivers/clk/clk-ast2600.c -@@ -31,6 +31,24 @@ - #define ASPEED_G6_CLK_SELECTION1 0x300 - #define ASPEED_G6_CLK_SELECTION2 0x304 - #define ASPEED_G6_CLK_SELECTION4 0x310 -+#define ASPEED_G6_CLK_SELECTION5 0x314 -+ -+#define ASPEED_G6_MAC12_CLK_CTRL0 0x340 -+#define ASPEED_G6_MAC12_CLK_CTRL1 0x348 -+#define ASPEED_G6_MAC12_CLK_CTRL2 0x34C -+ -+#define ASPEED_G6_MAC34_CLK_CTRL0 0x350 -+#define ASPEED_G6_MAC34_CLK_CTRL1 0x358 -+#define ASPEED_G6_MAC34_CLK_CTRL2 0x35C -+ -+#define ASPEED_G6_MAC34_DRIVING_CTRL 0x458 -+ -+#define ASPEED_G6_DEF_MAC12_DELAY_1G 0x0041b410 -+#define ASPEED_G6_DEF_MAC12_DELAY_100M 0x00417410 -+#define ASPEED_G6_DEF_MAC12_DELAY_10M 0x00417410 -+#define ASPEED_G6_DEF_MAC34_DELAY_1G 0x00104208 -+#define ASPEED_G6_DEF_MAC34_DELAY_100M 0x00104208 -+#define ASPEED_G6_DEF_MAC34_DELAY_10M 0x00104208 - - #define ASPEED_HPLL_PARAM 0x200 - #define ASPEED_APLL_PARAM 0x210 -@@ -40,9 +58,6 @@ - - #define ASPEED_G6_STRAP1 0x500 - --#define ASPEED_MAC12_CLK_DLY 0x340 --#define ASPEED_MAC34_CLK_DLY 0x350 -- - #define ASPEED_G6_GEN_UART_REF 0x338 - #define UART_192MHZ_R_N_VALUE 0x3c38e - -@@ -515,7 +530,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) - - /* RMII1 50MHz (RCLK) output enable */ - hw = clk_hw_register_gate(dev, "mac1rclk", "mac12rclk", 0, -- scu_g6_base + ASPEED_MAC12_CLK_DLY, 29, 0, -+ scu_g6_base + ASPEED_G6_MAC12_CLK_CTRL0, 29, 0, - &aspeed_g6_clk_lock); - if (IS_ERR(hw)) - return PTR_ERR(hw); -@@ -523,7 +538,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) - - /* RMII2 50MHz (RCLK) output enable */ - hw = clk_hw_register_gate(dev, "mac2rclk", "mac12rclk", 0, -- scu_g6_base + ASPEED_MAC12_CLK_DLY, 30, 0, -+ scu_g6_base + ASPEED_G6_MAC12_CLK_CTRL0, 30, 0, - &aspeed_g6_clk_lock); - if (IS_ERR(hw)) - return PTR_ERR(hw); -@@ -545,7 +560,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) - - /* RMII3 50MHz (RCLK) output enable */ - hw = clk_hw_register_gate(dev, "mac3rclk", "mac34rclk", 0, -- scu_g6_base + ASPEED_MAC34_CLK_DLY, 29, 0, -+ scu_g6_base + ASPEED_G6_MAC34_CLK_CTRL0, 29, 0, - &aspeed_g6_clk_lock); - if (IS_ERR(hw)) - return PTR_ERR(hw); -@@ -553,7 +568,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) - - /* RMII4 50MHz (RCLK) output enable */ - hw = clk_hw_register_gate(dev, "mac4rclk", "mac34rclk", 0, -- scu_g6_base + ASPEED_MAC34_CLK_DLY, 30, 0, -+ scu_g6_base + ASPEED_G6_MAC34_CLK_CTRL0, 30, 0, - &aspeed_g6_clk_lock); - if (IS_ERR(hw)) - return PTR_ERR(hw); -@@ -770,6 +785,37 @@ static void __init aspeed_g6_cc_init(struct device_node *np) - return; - } - -+ /* fixed settings for RGMII/RMII clock generator */ -+ /* MAC1/2 RGMII 125MHz = EPLL / 8 */ -+ regmap_update_bits(map, ASPEED_G6_CLK_SELECTION2, GENMASK(23, 20), -+ (0x7 << 20)); -+ -+ /* MAC3/4 RMII 50MHz = HCLK / 4 */ -+ regmap_update_bits(map, ASPEED_G6_CLK_SELECTION4, GENMASK(18, 16), -+ (0x3 << 16)); -+ -+ /* -+ * BIT[31]: MAC1/2 RGMII 125M source = internal PLL -+ * BIT[28]: RGMIICK pad direction = output -+ */ -+ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL0, -+ BIT(31) | BIT(28) | ASPEED_G6_DEF_MAC12_DELAY_1G); -+ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL1, -+ ASPEED_G6_DEF_MAC12_DELAY_100M); -+ regmap_write(map, ASPEED_G6_MAC12_CLK_CTRL2, -+ ASPEED_G6_DEF_MAC12_DELAY_10M); -+ -+ /* MAC3/4 RGMII 125M source = RGMIICK pad */ -+ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL0, -+ ASPEED_G6_DEF_MAC34_DELAY_1G); -+ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL1, -+ ASPEED_G6_DEF_MAC34_DELAY_100M); -+ regmap_write(map, ASPEED_G6_MAC34_CLK_CTRL2, -+ ASPEED_G6_DEF_MAC34_DELAY_10M); -+ -+ /* MAC3/4 default pad driving strength */ -+ regmap_write(map, ASPEED_G6_MAC34_DRIVING_CTRL, 0x0000000a); -+ - aspeed_g6_cc(map); - aspeed_g6_clk_data->num = ASPEED_G6_NUM_CLKS; - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_g6_clk_data); --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch deleted file mode 100644 index ec215d07a..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 766f7e504cc2a0508c887c7625332c88f93c5729 Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Fri, 27 Mar 2020 14:42:05 -0700 -Subject: [PATCH] Add chip unique id reading interface - -This commit adds an interface for reading chip unique id value. -Optionally, the id can be encrypted using a dts-supplied hash data. - -Signed-off-by: Jae Hyun Yoo -Signed-off-by: Vernon Mauery -Signed-off-by: Arun P. Mohanan ---- - drivers/soc/aspeed/aspeed-bmc-misc.c | 118 ++++++++++++++++++++++++--- - 1 file changed, 105 insertions(+), 13 deletions(-) - -diff --git a/drivers/soc/aspeed/aspeed-bmc-misc.c b/drivers/soc/aspeed/aspeed-bmc-misc.c -index 04d97ab17274..4aad3129f793 100644 ---- a/drivers/soc/aspeed/aspeed-bmc-misc.c -+++ b/drivers/soc/aspeed/aspeed-bmc-misc.c -@@ -7,15 +7,18 @@ - #include - #include - #include -+#include - - #define DEVICE_NAME "aspeed-bmc-misc" - - struct aspeed_bmc_ctrl { - const char *name; - u32 offset; -- u32 mask; -+ u64 mask; - u32 shift; - bool read_only; -+ u32 reg_width; -+ const char *hash_data; - struct regmap *map; - struct kobj_attribute attr; - }; -@@ -31,6 +34,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child, - struct aspeed_bmc_ctrl *ctrl) - { - int rc; -+ u32 mask; - - /* Example child: - * -@@ -38,6 +42,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child, - * offset = <0x80>; - * bit-mask = <0x1>; - * bit-shift = <6>; -+ * reg-width = <64>; - * label = "foo"; - * } - */ -@@ -48,9 +53,21 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child, - if (rc < 0) - return rc; - -- rc = of_property_read_u32(child, "bit-mask", &ctrl->mask); -- if (rc < 0) -- return rc; -+ /* optional reg-width, default to 32 */ -+ rc = of_property_read_u32(child, "reg-width", &ctrl->reg_width); -+ if (rc < 0 || ctrl->reg_width != 64) -+ ctrl->reg_width = 32; -+ -+ if (ctrl->reg_width == 32) { -+ rc = of_property_read_u32(child, "bit-mask", &mask); -+ if (rc < 0) -+ return rc; -+ ctrl->mask = mask; -+ } else { -+ rc = of_property_read_u64(child, "bit-mask", &ctrl->mask); -+ if (rc < 0) -+ return rc; -+ } - - rc = of_property_read_u32(child, "bit-shift", &ctrl->shift); - if (rc < 0) -@@ -59,6 +76,9 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child, - ctrl->read_only = of_property_read_bool(child, "read-only"); - - ctrl->mask <<= ctrl->shift; -+ /* optional hash_data for obfuscating reads */ -+ if (of_property_read_string(child, "hash-data", &ctrl->hash_data)) -+ ctrl->hash_data = NULL; - - return 0; - } -@@ -88,22 +108,94 @@ static int aspeed_bmc_misc_parse_dt(struct aspeed_bmc_misc *bmc, - return 0; - } - -+#define SHA256_DIGEST_LEN 32 -+static int hmac_sha256(u8 *key, u8 ksize, const char *plaintext, u8 psize, -+ u8 *output) -+{ -+ struct crypto_shash *tfm; -+ struct shash_desc *shash; -+ int ret; -+ -+ if (!ksize) -+ return -EINVAL; -+ -+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); -+ if (IS_ERR(tfm)) { -+ return -ENOMEM; -+ } -+ -+ ret = crypto_shash_setkey(tfm, key, ksize); -+ if (ret) -+ goto failed; -+ -+ shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), GFP_KERNEL); -+ if (!shash) { -+ ret = -ENOMEM; -+ goto failed; -+ } -+ -+ shash->tfm = tfm; -+ ret = crypto_shash_digest(shash, plaintext, psize, output); -+ -+ kfree(shash); -+ -+failed: -+ crypto_free_shash(tfm); -+ return ret; -+} -+ - static ssize_t aspeed_bmc_misc_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) - { - struct aspeed_bmc_ctrl *ctrl; -- unsigned int val; -+ u32 val; -+ u64 val64; - int rc; -+ u8 *binbuf; -+ size_t buf_len; -+ u8 hashbuf[SHA256_DIGEST_LEN]; - - ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr); -+ -+ if (ctrl->reg_width == 32) { -+ rc = regmap_read(ctrl->map, ctrl->offset, &val); -+ if (rc) -+ return rc; -+ val &= (u32)ctrl->mask; -+ val >>= ctrl->shift; -+ -+ return sprintf(buf, "%u\n", val); -+ } - rc = regmap_read(ctrl->map, ctrl->offset, &val); - if (rc) - return rc; -+ val64 = val; -+ rc = regmap_read(ctrl->map, ctrl->offset + sizeof(u32), &val); -+ if (rc) -+ return rc; -+ /* aspeed puts 64-bit regs as L, H in address space */ -+ val64 |= (u64)val << 32; -+ val64 &= ctrl->mask; -+ val64 >>= ctrl->shift; -+ buf_len = sizeof(val64); -+ -+ if (ctrl->hash_data) { -+ rc = hmac_sha256((u8*)&val64, buf_len, ctrl->hash_data, -+ strlen(ctrl->hash_data), hashbuf); -+ if (rc) -+ return rc; -+ buf_len = SHA256_DIGEST_LEN; -+ binbuf = hashbuf; -+ } else { -+ binbuf = (u8*)&val64; -+ buf_len = sizeof(val64); -+ } -+ bin2hex(buf, binbuf, buf_len); -+ buf[buf_len * 2] = '\n'; -+ rc = buf_len * 2 + 1; - -- val &= ctrl->mask; -- val >>= ctrl->shift; -+ return rc; - -- return sprintf(buf, "%u\n", val); - } - - static ssize_t aspeed_bmc_misc_store(struct kobject *kobj, -@@ -114,17 +206,17 @@ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj, - long val; - int rc; - -- rc = kstrtol(buf, 0, &val); -- if (rc) -- return rc; -- - ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr); - - if (ctrl->read_only) - return -EROFS; - -+ rc = kstrtol(buf, 0, &val); -+ if (rc) -+ return rc; -+ - val <<= ctrl->shift; -- rc = regmap_update_bits(ctrl->map, ctrl->offset, ctrl->mask, val); -+ rc = regmap_write_bits(ctrl->map, ctrl->offset, ctrl->mask, val); - - return rc < 0 ? rc : count; - } --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch deleted file mode 100644 index f5c0a6ec8..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 2cf0bee18a390a90cd1e5736ba79909a8feef94e Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Tue, 28 Apr 2020 12:08:14 -0700 -Subject: [PATCH] i2c: aspeed: fix arbitration loss handling logic - -When an arbitration loss happens in a multi-master bus, driver -drops the packet induce I2C subsystem to retry the transaction -by returning -EAGAIN. During this handling, tx_ack comes along -sometimes and it causes this this garbage printing -out: - -aspeed-i2c-bus 1e78a400.i2c-bus: irq handled != irq. expected 0x00000009, but was 0x00000008 - -To fix this issue, this commit adds the tx_ack flag clearing into -the arbitration loss handling logic. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/i2c/busses/i2c-aspeed.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c -index b56e60508914..8625c0da440b 100644 ---- a/drivers/i2c/busses/i2c-aspeed.c -+++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -896,6 +896,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) - if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) { - bus->cmd_err = ret; - bus->master_state = ASPEED_I2C_MASTER_INACTIVE; -+ if (ret == -EAGAIN) -+ irq_handled |= (irq_status & -+ ASPEED_I2CD_INTR_TX_ACK); - goto out_complete; - } - } --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch deleted file mode 100644 index 4cc88cbeb..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0106-enable-AST2600-I3C.patch +++ /dev/null @@ -1,910 +0,0 @@ -From c3be31a18ef1755c86c169b9d0e54bdbbea99d8a Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Wed, 6 May 2020 18:11:29 -0700 -Subject: [PATCH] enable AST2600 I3C - -This commit ports I3C related changes from Aspeed SDK v00.05.05. -It also includes Vitor's I3C cdev implementation which isn't -upstreamed yet so it should be refined later. - -Signed-off-by: Ryan Chen -Signed-off-by: Vitor Soares -Signed-off-by: Jae Hyun Yoo ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 19 +- - drivers/clk/clk-ast2600.c | 30 ++- - drivers/i3c/Kconfig | 15 ++ - drivers/i3c/Makefile | 1 + - drivers/i3c/i3cdev.c | 428 ++++++++++++++++++++++++++++++ - drivers/i3c/internals.h | 2 + - drivers/i3c/master.c | 39 ++- - drivers/i3c/master/Kconfig | 5 + - drivers/i3c/master/Makefile | 1 + - drivers/i3c/master/aspeed-i3c-global.c | 77 ++++++ - include/dt-bindings/clock/ast2600-clock.h | 3 +- - include/uapi/linux/i3c/i3cdev.h | 38 +++ - 12 files changed, 634 insertions(+), 24 deletions(-) - create mode 100644 drivers/i3c/i3cdev.c - create mode 100644 drivers/i3c/master/aspeed-i3c-global.c - create mode 100644 include/uapi/linux/i3c/i3cdev.h - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 91f431e419d9..33e1b0ef24f0 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -1091,13 +1091,20 @@ - }; - - &i3c { -+ i3cglobal: i3cg@0 { -+ reg = <0x0 0x1000>; -+ compatible = "aspeed,ast2600-i3c-global"; -+ resets = <&syscon ASPEED_RESET_I3C_DMA>; -+ status = "disabled"; -+ }; -+ - i3c0: i3c0@2000 { - #address-cells = <1>; - #size-cells = <0>; - #interrupt-cells = <1>; - reg = <0x2000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C0CLK>; - resets = <&syscon ASPEED_RESET_I3C0>; - bus-frequency = <100000>; - interrupts = ; -@@ -1110,7 +1117,7 @@ - #interrupt-cells = <1>; - reg = <0x3000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C1CLK>; - resets = <&syscon ASPEED_RESET_I3C1>; - bus-frequency = <100000>; - interrupts = ; -@@ -1123,7 +1130,7 @@ - #interrupt-cells = <1>; - reg = <0x4000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C2CLK>; - resets = <&syscon ASPEED_RESET_I3C2>; - bus-frequency = <100000>; - interrupts = ; -@@ -1138,7 +1145,7 @@ - #interrupt-cells = <1>; - reg = <0x5000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C3CLK>; - resets = <&syscon ASPEED_RESET_I3C3>; - bus-frequency = <100000>; - interrupts = ; -@@ -1153,7 +1160,7 @@ - #interrupt-cells = <1>; - reg = <0x6000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C4CLK>; - resets = <&syscon ASPEED_RESET_I3C4>; - bus-frequency = <100000>; - interrupts = ; -@@ -1168,7 +1175,7 @@ - #interrupt-cells = <1>; - reg = <0x7000 0x1000>; - compatible = "snps,dw-i3c-master-1.00a"; -- clocks = <&syscon ASPEED_CLK_APB2>; -+ clocks = <&syscon ASPEED_CLK_GATE_I3C5CLK>; - resets = <&syscon ASPEED_RESET_I3C5>; - bus-frequency = <100000>; - interrupts = ; -diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c -index e07326544fdc..a30dcbb1a3fd 100644 ---- a/drivers/clk/clk-ast2600.c -+++ b/drivers/clk/clk-ast2600.c -@@ -112,14 +112,14 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = { - [ASPEED_CLK_GATE_LHCCLK] = { 37, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */ - /* Reserved 38 RSA: no longer used */ - /* Reserved 39 */ -- [ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", NULL, 0 }, /* I3C0 */ -- [ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", NULL, 0 }, /* I3C1 */ -- [ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", NULL, 0 }, /* I3C2 */ -- [ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", NULL, 0 }, /* I3C3 */ -- [ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", NULL, 0 }, /* I3C4 */ -- [ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", NULL, 0 }, /* I3C5 */ -- [ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", NULL, 0 }, /* I3C6 */ -- [ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", NULL, 0 }, /* I3C7 */ -+ [ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", "i3cclk", 0 }, /* I3C0 */ -+ [ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", "i3cclk", 0 }, /* I3C1 */ -+ [ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", "i3cclk", 0 }, /* I3C2 */ -+ [ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", "i3cclk", 0 }, /* I3C3 */ -+ [ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", "i3cclk", 0 }, /* I3C4 */ -+ [ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", "i3cclk", 0 }, /* I3C5 */ -+ [ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", "i3cclk", 0 }, /* I3C6 */ -+ [ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", "i3cclk", 0 }, /* I3C7 */ - [ASPEED_CLK_GATE_UART1CLK] = { 48, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */ - [ASPEED_CLK_GATE_UART2CLK] = { 49, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */ - [ASPEED_CLK_GATE_UART3CLK] = { 50, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */ -@@ -749,6 +749,20 @@ static void __init aspeed_g6_cc(struct regmap *map) - /* USB 2.0 port1 phy 40MHz clock */ - hw = clk_hw_register_fixed_rate(NULL, "usb-phy-40m", NULL, 0, 40000000); - aspeed_g6_clk_data->hws[ASPEED_CLK_USBPHY_40M] = hw; -+ -+ /* i3c clock source */ -+ regmap_read(map, ASPEED_G6_CLK_SELECTION5, &val); -+ if(val & BIT(31)) { -+ val = (val >> 28) & 0x7; -+ if(val) -+ div = val + 1; -+ else -+ div = val + 2; -+ hw = clk_hw_register_fixed_factor(NULL, "i3cclk", "apll", 0, 1, div); -+ } else { -+ hw = clk_hw_register_fixed_factor(NULL, "i3cclk", "ahb", 0, 1, 1); -+ } -+ aspeed_g6_clk_data->hws[ASPEED_CLK_I3C] = hw; - }; - - static void __init aspeed_g6_cc_init(struct device_node *np) -diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig -index 30a441506f61..01642768ab5f 100644 ---- a/drivers/i3c/Kconfig -+++ b/drivers/i3c/Kconfig -@@ -20,5 +20,20 @@ menuconfig I3C - will be called i3c. - - if I3C -+ -+config I3CDEV -+ tristate "I3C device interface" -+ depends on I3C -+ help -+ Say Y here to use i3c-* device files, usually found in the /dev -+ directory on your system. They make it possible to have user-space -+ programs use the I3C devices. -+ -+ This support is also available as a module. If so, the module -+ will be called i3cdev. -+ -+ Note that this application programming interface is EXPERIMENTAL -+ and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes. -+ - source "drivers/i3c/master/Kconfig" - endif # I3C -diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile -index 11982efbc6d9..606d422841b2 100644 ---- a/drivers/i3c/Makefile -+++ b/drivers/i3c/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 - i3c-y := device.o master.o - obj-$(CONFIG_I3C) += i3c.o -+obj-$(CONFIG_I3CDEV) += i3cdev.o - obj-$(CONFIG_I3C) += master/ -diff --git a/drivers/i3c/i3cdev.c b/drivers/i3c/i3cdev.c -new file mode 100644 -index 000000000000..07f5641a902d ---- /dev/null -+++ b/drivers/i3c/i3cdev.c -@@ -0,0 +1,428 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates. -+ * -+ * Author: Vitor Soares -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "internals.h" -+ -+struct i3cdev_data { -+ struct list_head list; -+ struct i3c_device *i3c; -+ struct cdev cdev; -+ struct device *dev; -+ int id; -+}; -+ -+static DEFINE_IDA(i3cdev_ida); -+static dev_t i3cdev_number; -+#define I3C_MINORS 16 /* 16 I3C devices supported for now */ -+ -+static LIST_HEAD(i3cdev_list); -+static DEFINE_SPINLOCK(i3cdev_list_lock); -+ -+static struct i3cdev_data *i3cdev_get_by_i3c(struct i3c_device *i3c) -+{ -+ struct i3cdev_data *i3cdev; -+ -+ spin_lock(&i3cdev_list_lock); -+ list_for_each_entry(i3cdev, &i3cdev_list, list) { -+ if (i3cdev->i3c == i3c) -+ goto found; -+ } -+ -+ i3cdev = NULL; -+ -+found: -+ spin_unlock(&i3cdev_list_lock); -+ return i3cdev; -+} -+ -+static struct i3cdev_data *get_free_i3cdev(struct i3c_device *i3c) -+{ -+ struct i3cdev_data *i3cdev; -+ int id; -+ -+ id = ida_simple_get(&i3cdev_ida, 0, I3C_MINORS, GFP_KERNEL); -+ if (id < 0) { -+ pr_err("i3cdev: no minor number available!\n"); -+ return ERR_PTR(id); -+ } -+ -+ i3cdev = kzalloc(sizeof(*i3cdev), GFP_KERNEL); -+ if (!i3cdev) { -+ ida_simple_remove(&i3cdev_ida, id); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ i3cdev->i3c = i3c; -+ i3cdev->id = id; -+ -+ spin_lock(&i3cdev_list_lock); -+ list_add_tail(&i3cdev->list, &i3cdev_list); -+ spin_unlock(&i3cdev_list_lock); -+ -+ return i3cdev; -+} -+ -+static void put_i3cdev(struct i3cdev_data *i3cdev) -+{ -+ spin_lock(&i3cdev_list_lock); -+ list_del(&i3cdev->list); -+ spin_unlock(&i3cdev_list_lock); -+ kfree(i3cdev); -+} -+ -+static ssize_t -+i3cdev_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) -+{ -+ struct i3c_device *i3c = file->private_data; -+ struct i3c_priv_xfer xfers = { -+ .rnw = true, -+ .len = count, -+ }; -+ char *tmp; -+ int ret; -+ -+ tmp = kzalloc(count, GFP_KERNEL); -+ if (!tmp) -+ return -ENOMEM; -+ -+ xfers.data.in = tmp; -+ -+ dev_dbg(&i3c->dev, "Reading %zu bytes.\n", count); -+ -+ ret = i3c_device_do_priv_xfers(i3c, &xfers, 1); -+ if (!ret) -+ ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; -+ -+ kfree(tmp); -+ return ret; -+} -+ -+static ssize_t -+i3cdev_write(struct file *file, const char __user *buf, size_t count, -+ loff_t *f_pos) -+{ -+ struct i3c_device *i3c = file->private_data; -+ struct i3c_priv_xfer xfers = { -+ .rnw = false, -+ .len = count, -+ }; -+ char *tmp; -+ int ret; -+ -+ tmp = memdup_user(buf, count); -+ if (IS_ERR(tmp)) -+ return PTR_ERR(tmp); -+ -+ xfers.data.out = tmp; -+ -+ dev_dbg(&i3c->dev, "Writing %zu bytes.\n", count); -+ -+ ret = i3c_device_do_priv_xfers(i3c, &xfers, 1); -+ kfree(tmp); -+ return (!ret) ? count : ret; -+} -+ -+static int -+i3cdev_do_priv_xfer(struct i3c_device *dev, struct i3c_ioc_priv_xfer *xfers, -+ unsigned int nxfers) -+{ -+ struct i3c_priv_xfer *k_xfers; -+ u8 **data_ptrs; -+ int i, ret = 0; -+ -+ k_xfers = kcalloc(nxfers, sizeof(*k_xfers), GFP_KERNEL); -+ if (!k_xfers) -+ return -ENOMEM; -+ -+ data_ptrs = kcalloc(nxfers, sizeof(*data_ptrs), GFP_KERNEL); -+ if (!data_ptrs) { -+ ret = -ENOMEM; -+ goto err_free_k_xfer; -+ } -+ -+ for (i = 0; i < nxfers; i++) { -+ data_ptrs[i] = memdup_user((const u8 __user *) -+ (uintptr_t)xfers[i].data, -+ xfers[i].len); -+ if (IS_ERR(data_ptrs[i])) { -+ ret = PTR_ERR(data_ptrs[i]); -+ break; -+ } -+ -+ k_xfers[i].len = xfers[i].len; -+ if (xfers[i].rnw) { -+ k_xfers[i].rnw = true; -+ k_xfers[i].data.in = data_ptrs[i]; -+ } else { -+ k_xfers[i].rnw = false; -+ k_xfers[i].data.out = data_ptrs[i]; -+ } -+ } -+ -+ if (ret < 0) { -+ i--; -+ goto err_free_mem; -+ } -+ -+ ret = i3c_device_do_priv_xfers(dev, k_xfers, nxfers); -+ if (ret) -+ goto err_free_mem; -+ -+ for (i = 0; i < nxfers; i++) { -+ if (xfers[i].rnw) { -+ if (copy_to_user((void __user *)(uintptr_t)xfers[i].data, -+ data_ptrs[i], xfers[i].len)) -+ ret = -EFAULT; -+ } -+ } -+ -+err_free_mem: -+ for (; i >= 0; i--) -+ kfree(data_ptrs[i]); -+ kfree(data_ptrs); -+err_free_k_xfer: -+ kfree(k_xfers); -+ return ret; -+} -+ -+static struct i3c_ioc_priv_xfer * -+i3cdev_get_ioc_priv_xfer(unsigned int cmd, struct i3c_ioc_priv_xfer *u_xfers, -+ unsigned int *nxfers) -+{ -+ u32 tmp = _IOC_SIZE(cmd); -+ -+ if ((tmp % sizeof(struct i3c_ioc_priv_xfer)) != 0) -+ return ERR_PTR(-EINVAL); -+ -+ *nxfers = tmp / sizeof(struct i3c_ioc_priv_xfer); -+ if (*nxfers == 0) -+ return NULL; -+ -+ return memdup_user(u_xfers, tmp); -+} -+ -+static int -+i3cdev_ioc_priv_xfer(struct i3c_device *i3c, unsigned int cmd, -+ struct i3c_ioc_priv_xfer *u_xfers) -+{ -+ struct i3c_ioc_priv_xfer *k_xfers; -+ unsigned int nxfers; -+ int ret; -+ -+ k_xfers = i3cdev_get_ioc_priv_xfer(cmd, u_xfers, &nxfers); -+ if (IS_ERR_OR_NULL(k_xfers)) -+ return PTR_ERR(k_xfers); -+ -+ ret = i3cdev_do_priv_xfer(i3c, k_xfers, nxfers); -+ -+ kfree(k_xfers); -+ -+ return ret; -+} -+ -+static long -+i3cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct i3c_device *i3c = file->private_data; -+ -+ dev_dbg(&i3c->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", cmd, arg); -+ -+ if (_IOC_TYPE(cmd) != I3C_DEV_IOC_MAGIC) -+ return -ENOTTY; -+ -+ /* Check command number and direction */ -+ if (_IOC_NR(cmd) == _IOC_NR(I3C_IOC_PRIV_XFER(0)) && -+ _IOC_DIR(cmd) == (_IOC_READ | _IOC_WRITE)) -+ return i3cdev_ioc_priv_xfer(i3c, cmd, -+ (struct i3c_ioc_priv_xfer __user *)arg); -+ -+ return 0; -+} -+ -+static int i3cdev_open(struct inode *inode, struct file *file) -+{ -+ struct i3cdev_data *i3cdev = container_of(inode->i_cdev, -+ struct i3cdev_data, -+ cdev); -+ -+ file->private_data = i3cdev->i3c; -+ -+ return 0; -+} -+ -+static int i3cdev_release(struct inode *inode, struct file *file) -+{ -+ file->private_data = NULL; -+ -+ return 0; -+} -+ -+static const struct file_operations i3cdev_fops = { -+ .owner = THIS_MODULE, -+ .read = i3cdev_read, -+ .write = i3cdev_write, -+ .unlocked_ioctl = i3cdev_ioctl, -+ .open = i3cdev_open, -+ .release = i3cdev_release, -+}; -+ -+/* ------------------------------------------------------------------------- */ -+ -+static struct class *i3cdev_class; -+ -+static int i3cdev_attach(struct device *dev, void *dummy) -+{ -+ struct i3cdev_data *i3cdev; -+ struct i3c_device *i3c; -+ int res; -+ -+ if (dev->type == &i3c_masterdev_type || dev->driver) -+ return 0; -+ -+ i3c = dev_to_i3cdev(dev); -+ -+ /* Get a device */ -+ i3cdev = get_free_i3cdev(i3c); -+ if (IS_ERR(i3cdev)) -+ return PTR_ERR(i3cdev); -+ -+ cdev_init(&i3cdev->cdev, &i3cdev_fops); -+ i3cdev->cdev.owner = THIS_MODULE; -+ res = cdev_add(&i3cdev->cdev, -+ MKDEV(MAJOR(i3cdev_number), i3cdev->id), 1); -+ if (res) -+ goto error_cdev; -+ -+ /* register this i3c device with the driver core */ -+ i3cdev->dev = device_create(i3cdev_class, &i3c->dev, -+ MKDEV(MAJOR(i3cdev_number), i3cdev->id), -+ NULL, "i3c-%s", dev_name(&i3c->dev)); -+ if (IS_ERR(i3cdev->dev)) { -+ res = PTR_ERR(i3cdev->dev); -+ goto error; -+ } -+ pr_debug("i3cdev: I3C device [%s] registered as minor %d\n", -+ dev_name(&i3c->dev), i3cdev->id); -+ return 0; -+ -+error: -+ cdev_del(&i3cdev->cdev); -+error_cdev: -+ put_i3cdev(i3cdev); -+ return res; -+} -+ -+static int i3cdev_detach(struct device *dev, void *dummy) -+{ -+ struct i3cdev_data *i3cdev; -+ struct i3c_device *i3c; -+ -+ if (dev->type == &i3c_masterdev_type) -+ return 0; -+ -+ i3c = dev_to_i3cdev(dev); -+ -+ i3cdev = i3cdev_get_by_i3c(i3c); -+ if (!i3cdev) -+ return 0; -+ -+ cdev_del(&i3cdev->cdev); -+ device_destroy(i3cdev_class, MKDEV(MAJOR(i3cdev_number), i3cdev->id)); -+ ida_simple_remove(&i3cdev_ida, i3cdev->id); -+ put_i3cdev(i3cdev); -+ -+ pr_debug("i3cdev: device [%s] unregistered\n", dev_name(&i3c->dev)); -+ -+ return 0; -+} -+ -+static int i3cdev_notifier_call(struct notifier_block *nb, -+ unsigned long action, -+ void *data) -+{ -+ struct device *dev = data; -+ -+ switch (action) { -+ case BUS_NOTIFY_ADD_DEVICE: -+ case BUS_NOTIFY_UNBOUND_DRIVER: -+ return i3cdev_attach(dev, NULL); -+ case BUS_NOTIFY_DEL_DEVICE: -+ case BUS_NOTIFY_BOUND_DRIVER: -+ return i3cdev_detach(dev, NULL); -+ } -+ -+ return 0; -+} -+ -+static struct notifier_block i3c_notifier = { -+ .notifier_call = i3cdev_notifier_call, -+}; -+ -+static int __init i3cdev_init(void) -+{ -+ int res; -+ -+ /* Dynamically request unused major number */ -+ res = alloc_chrdev_region(&i3cdev_number, 0, I3C_MINORS, "i3c"); -+ if (res) -+ goto out; -+ -+ /* Create a classe to populate sysfs entries*/ -+ i3cdev_class = class_create(THIS_MODULE, "i3cdev"); -+ if (IS_ERR(i3cdev_class)) { -+ res = PTR_ERR(i3cdev_class); -+ goto out_unreg_chrdev; -+ } -+ -+ /* Keep track of busses which have devices to add or remove later */ -+ res = bus_register_notifier(&i3c_bus_type, &i3c_notifier); -+ if (res) -+ goto out_unreg_class; -+ -+ /* Bind to already existing device without driver right away */ -+ i3c_for_each_dev(NULL, i3cdev_attach); -+ -+ return 0; -+ -+out_unreg_class: -+ class_destroy(i3cdev_class); -+out_unreg_chrdev: -+ unregister_chrdev_region(i3cdev_number, I3C_MINORS); -+out: -+ pr_err("%s: Driver Initialisation failed\n", __FILE__); -+ return res; -+} -+ -+static void __exit i3cdev_exit(void) -+{ -+ bus_unregister_notifier(&i3c_bus_type, &i3c_notifier); -+ i3c_for_each_dev(NULL, i3cdev_detach); -+ class_destroy(i3cdev_class); -+ unregister_chrdev_region(i3cdev_number, I3C_MINORS); -+} -+ -+MODULE_AUTHOR("Vitor Soares "); -+MODULE_DESCRIPTION("I3C /dev entries driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(i3cdev_init); -+module_exit(i3cdev_exit); -diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h -index 86b7b44cfca2..a6deedf5ce06 100644 ---- a/drivers/i3c/internals.h -+++ b/drivers/i3c/internals.h -@@ -11,6 +11,7 @@ - #include - - extern struct bus_type i3c_bus_type; -+extern const struct device_type i3c_masterdev_type; - - void i3c_bus_normaluse_lock(struct i3c_bus *bus); - void i3c_bus_normaluse_unlock(struct i3c_bus *bus); -@@ -23,4 +24,5 @@ int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev); - int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev, - const struct i3c_ibi_setup *req); - void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev); -+int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *)); - #endif /* I3C_INTERNAL_H */ -diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c -index 5c051dba32a5..53910fb6702e 100644 ---- a/drivers/i3c/master.c -+++ b/drivers/i3c/master.c -@@ -321,6 +321,7 @@ struct bus_type i3c_bus_type = { - .probe = i3c_device_probe, - .remove = i3c_device_remove, - }; -+EXPORT_SYMBOL_GPL(i3c_bus_type); - - static enum i3c_addr_slot_status - i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr) -@@ -523,11 +524,12 @@ static void i3c_masterdev_release(struct device *dev) - of_node_put(dev->of_node); - } - --static const struct device_type i3c_masterdev_type = { -+const struct device_type i3c_masterdev_type = { - .groups = i3c_masterdev_groups, - }; -+EXPORT_SYMBOL_GPL(i3c_masterdev_type); - --int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode, -+static int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode, - unsigned long max_i2c_scl_rate) - { - struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus); -@@ -1410,19 +1412,19 @@ static void i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) - master->ops->detach_i2c_dev(dev); - } - --static void i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev) -+static int i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev) - { - struct i3c_master_controller *master = i3c_dev_get_master(dev); - int ret; - - if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr || - !dev->boardinfo->static_addr) -- return; -+ return -1; - - ret = i3c_master_setdasa_locked(master, dev->info.static_addr, - dev->boardinfo->init_dyn_addr); - if (ret) -- return; -+ return ret; - - dev->info.dyn_addr = dev->boardinfo->init_dyn_addr; - ret = i3c_master_reattach_i3c_dev(dev, 0); -@@ -1433,10 +1435,11 @@ static void i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev) - if (ret) - goto err_rstdaa; - -- return; -+ return 0; - - err_rstdaa: - i3c_master_rstdaa_locked(master, dev->boardinfo->init_dyn_addr); -+ return ret; - } - - static void -@@ -1631,7 +1634,7 @@ static int i3c_master_bus_init(struct i3c_master_controller *master) - enum i3c_addr_slot_status status; - struct i2c_dev_boardinfo *i2cboardinfo; - struct i3c_dev_boardinfo *i3cboardinfo; -- struct i3c_dev_desc *i3cdev; -+ struct i3c_dev_desc *i3cdev, *i3ctmp; - struct i2c_dev_desc *i2cdev; - int ret; - -@@ -1730,8 +1733,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master) - * Pre-assign dynamic address and retrieve device information if - * needed. - */ -- i3c_bus_for_each_i3cdev(&master->bus, i3cdev) -- i3c_master_pre_assign_dyn_addr(i3cdev); -+ list_for_each_entry_safe(i3cdev, i3ctmp, &master->bus.devs.i3c, -+ common.node) { -+ ret = i3c_master_pre_assign_dyn_addr(i3cdev); -+ if (ret) { -+ i3c_master_detach_i3c_dev(i3cdev); -+ i3c_master_free_i3c_dev(i3cdev); -+ } -+ } - - ret = i3c_master_do_daa(master); - if (ret) -@@ -2638,6 +2647,18 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev) - dev->ibi = NULL; - } - -+int i3c_for_each_dev(void *data, int (*fn)(struct device *, void *)) -+{ -+ int res; -+ -+ mutex_lock(&i3c_core_lock); -+ res = bus_for_each_dev(&i3c_bus_type, NULL, data, fn); -+ mutex_unlock(&i3c_core_lock); -+ -+ return res; -+} -+EXPORT_SYMBOL_GPL(i3c_for_each_dev); -+ - static int __init i3c_init(void) - { - return bus_register(&i3c_bus_type); -diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig -index 4e80a1fcbf91..693f9aba2b17 100644 ---- a/drivers/i3c/master/Kconfig -+++ b/drivers/i3c/master/Kconfig -@@ -21,3 +21,8 @@ config DW_I3C_MASTER - - This driver can also be built as a module. If so, the module - will be called dw-i3c-master. -+ -+config ASPEED_I3C_GLOBAL -+ tristate "ASPEED I3C global driver" -+ depends on I3C -+ depends on MACH_ASPEED_G6 -diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile -index 7eea9e086144..b5ec8e8dd622 100644 ---- a/drivers/i3c/master/Makefile -+++ b/drivers/i3c/master/Makefile -@@ -1,3 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0-only -+obj-$(CONFIG_ASPEED_I3C_GLOBAL) += aspeed-i3c-global.o - obj-$(CONFIG_CDNS_I3C_MASTER) += i3c-master-cdns.o - obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o -diff --git a/drivers/i3c/master/aspeed-i3c-global.c b/drivers/i3c/master/aspeed-i3c-global.c -new file mode 100644 -index 000000000000..8db6c1397a6c ---- /dev/null -+++ b/drivers/i3c/master/aspeed-i3c-global.c -@@ -0,0 +1,77 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (C) 2019 ASPEED Technology Inc. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ASPEED_I3CG_CTRL(x) (0x10 + (x*0x10)) -+#define ASPEED_I3CG_SET(x) (0x14 + (x*0x10)) -+ -+struct aspeed_i3c_global { -+ void __iomem *base; -+ struct reset_control *rst; -+}; -+ -+static int aspeed_i3c_global_probe(struct platform_device *pdev) -+{ -+ struct aspeed_i3c_global *i3c_global; -+ struct device_node *node = pdev->dev.of_node; -+ int i = 0; -+ -+ i3c_global = kzalloc(sizeof(*i3c_global), GFP_KERNEL); -+ if (!i3c_global) -+ return -ENOMEM; -+ -+ i3c_global->base = of_iomap(node, 0); -+ if (!i3c_global->base) { -+ return -ENOMEM; -+ } -+ -+ i3c_global->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -+ -+ if (IS_ERR(i3c_global->rst)) { -+ if (PTR_ERR(i3c_global->rst) != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "missing or invalid reset controller device tree entry\n"); -+ return PTR_ERR(i3c_global->rst); -+ } -+ -+ reset_control_assert(i3c_global->rst); -+ udelay(3); -+ reset_control_deassert(i3c_global->rst); -+ -+ /* init */ -+ for(i = 0; i < 5; i++) -+ writel(0x000474c4, i3c_global->base + ASPEED_I3CG_SET(i)); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_i3c_of_match[] = { -+ { .compatible = "aspeed,ast2600-i3c-global", }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, aspeed_i3c_of_match); -+ -+static struct platform_driver aspeed_i3c_driver = { -+ .probe = aspeed_i3c_global_probe, -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .of_match_table = aspeed_i3c_of_match, -+ }, -+}; -+module_platform_driver(aspeed_i3c_driver); -+ -+MODULE_AUTHOR("Ryan Chen"); -+MODULE_DESCRIPTION("ASPEED I3C Global Driver"); -+MODULE_LICENSE("GPL v2"); -diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h -index 26f84584a821..6cc47373cc97 100644 ---- a/include/dt-bindings/clock/ast2600-clock.h -+++ b/include/dt-bindings/clock/ast2600-clock.h -@@ -88,7 +88,8 @@ - #define ASPEED_CLK_MAC3RCLK 69 - #define ASPEED_CLK_MAC4RCLK 70 - #define ASPEED_CLK_UART5 71 --#define ASPEED_CLK_MAX 72 -+#define ASPEED_CLK_I3C 72 -+#define ASPEED_CLK_MAX 73 - - /* Only list resets here that are not part of a gate */ - #define ASPEED_RESET_ADC 55 -diff --git a/include/uapi/linux/i3c/i3cdev.h b/include/uapi/linux/i3c/i3cdev.h -new file mode 100644 -index 000000000000..0897313f5516 ---- /dev/null -+++ b/include/uapi/linux/i3c/i3cdev.h -@@ -0,0 +1,38 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates. -+ * -+ * Author: Vitor Soares -+ */ -+ -+#ifndef _UAPI_I3C_DEV_H_ -+#define _UAPI_I3C_DEV_H_ -+ -+#include -+#include -+ -+/* IOCTL commands */ -+#define I3C_DEV_IOC_MAGIC 0x07 -+ -+/** -+ * struct i3c_ioc_priv_xfer - I3C SDR ioctl private transfer -+ * @data: Holds pointer to userspace buffer with transmit data. -+ * @len: Length of data buffer buffers, in bytes. -+ * @rnw: encodes the transfer direction. true for a read, false for a write -+ */ -+struct i3c_ioc_priv_xfer { -+ __u64 data; -+ __u16 len; -+ __u8 rnw; -+ __u8 pad[5]; -+}; -+ -+ -+#define I3C_PRIV_XFER_SIZE(N) \ -+ ((((sizeof(struct i3c_ioc_priv_xfer)) * (N)) < (1 << _IOC_SIZEBITS)) \ -+ ? ((sizeof(struct i3c_ioc_priv_xfer)) * (N)) : 0) -+ -+#define I3C_IOC_PRIV_XFER(N) \ -+ _IOC(_IOC_READ|_IOC_WRITE, I3C_DEV_IOC_MAGIC, 30, I3C_PRIV_XFER_SIZE(N)) -+ -+#endif --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch deleted file mode 100644 index fc72c7537..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 7f4dc6aee65d9badf841099806ae6b85a86320ce Mon Sep 17 00:00:00 2001 -From: Iwona Winiarska -Date: Thu, 27 Feb 2020 00:53:38 +0100 -Subject: [PATCH 107/108] arm: dts: aspeed-g6: Add ast2600-mctp node - -AST2600 provides MCTP over PCIe controller allowing BMC to communicate -with devices on host PCIe bus. - -We are also adding syscon node describing PCIe Host controller device -which can be used to gather information on PCIe enumeration (and -assigned address). - -Signed-off-by: Iwona Winiarska ---- - .../bindings/soc/aspeed/aspeed-mctp.txt | 25 +++++++++++++++++++ - arch/arm/boot/dts/aspeed-g6.dtsi | 15 +++++++++++ - 2 files changed, 40 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt - -diff --git a/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt b/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt -new file mode 100644 -index 000000000000..5dc30fdfc53a ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/aspeed/aspeed-mctp.txt -@@ -0,0 +1,25 @@ -+* Aspeed AST2600 MCTP PCIe VDM Controller -+ -+Required properties: -+- compatible : must be "aspeed,ast2600-mctp" -+- reg : contains the address and size of the memory region -+ associated with the MCTP controller -+- resets : reset specifier for the syscon reset associated with -+ the MCTP controller -+- interrupts-extended : two interrupt cells; the first specifies the global -+ interrupt for MCTP controller and the second -+ specifies the PCIe reset or PERST interrupt -+- aspeed,pcieh : a phandle to the PCIe Host Controller node to be -+ used in conjunction with the PCIe reset or PERST -+ interrupt -+Example: -+ -+mctp: mctp@1e6e8000 { -+ compatible = "aspeed,ast2600-mctp"; -+ reg = <0x1e6e8000 0x1000>; -+ interrupts-extended = <&gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, -+ <&scu_ic0 ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>; -+ resets = <&syscon ASPEED_RESET_DEV_MCTP>; -+ aspeed,pcieh = <&pcieh>; -+ status = "disabled"; -+}; -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 33e1b0ef24f0..90a060db20c7 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -407,6 +407,21 @@ - interrupts = ; - }; - -+ pcieh: pcieh@1e6ed000 { -+ compatible = "aspeed,ast2600-pcieh", "syscon"; -+ reg = <0x1e6ed000 0x100>; -+ }; -+ -+ mctp: mctp@1e6e8000 { -+ compatible = "aspeed,ast2600-mctp"; -+ reg = <0x1e6e8000 0x1000>; -+ interrupts-extended = <&gic GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, -+ <&scu_ic0 ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>; -+ resets = <&syscon ASPEED_RESET_DEV_MCTP>; -+ aspeed,pcieh = <&pcieh>; -+ status = "disabled"; -+ }; -+ - adc0: adc@1e6e9000 { - compatible = "aspeed,ast2600-adc"; - reg = <0x1e6e9000 0x100>; --- -2.21.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch deleted file mode 100644 index bff271bfe..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch +++ /dev/null @@ -1,1265 +0,0 @@ -From cafc578414a664ecde96598838a3907a5d915416 Mon Sep 17 00:00:00 2001 -From: Iwona Winiarska -Date: Mon, 6 Apr 2020 22:00:46 +0200 -Subject: [PATCH 108/108] soc: aspeed: mctp: Add initial driver for - ast2600-mctp - -Currently, there is no proper MCTP networking subsystem in Linux. -Until we are able to work out the details of that, we are going to -expose HW to userspace using raw read/write interface. -Because of that, this driver is not intended to be submitted upstream. - -Here we are providing a simple device driver for AST2600 MCTP -controller. - -Signed-off-by: Iwona Winiarska ---- - drivers/soc/aspeed/Kconfig | 8 + - drivers/soc/aspeed/Makefile | 1 + - drivers/soc/aspeed/aspeed-mctp.c | 1126 ++++++++++++++++++++++++++++++ - include/uapi/linux/aspeed-mctp.h | 72 ++ - 4 files changed, 1207 insertions(+) - create mode 100644 drivers/soc/aspeed/aspeed-mctp.c - create mode 100644 include/uapi/linux/aspeed-mctp.h - -diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig -index 13cd9fbabbf1..78d9140d822b 100644 ---- a/drivers/soc/aspeed/Kconfig -+++ b/drivers/soc/aspeed/Kconfig -@@ -43,6 +43,14 @@ config ASPEED_LPC_SNOOP - allows the BMC to listen on and save the data written by - the host to an arbitrary LPC I/O port. - -+config ASPEED_MCTP -+ tristate "Aspeed ast2600 MCTP Controller support" -+ depends on SOC_ASPEED && REGMAP && MFD_SYSCON -+ help -+ Enable support for ast2600 MCTP Controller. -+ The MCTP controller allows the BMC to communicate with devices on -+ the host PCIe network. -+ - config ASPEED_P2A_CTRL - depends on SOC_ASPEED && REGMAP && MFD_SYSCON - tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control" -diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile -index 875f0d9e7866..b3c143f9e24c 100644 ---- a/drivers/soc/aspeed/Makefile -+++ b/drivers/soc/aspeed/Makefile -@@ -7,3 +7,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o - obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o - obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o - obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o -+obj-$(CONFIG_ASPEED_MCTP) += aspeed-mctp.o -diff --git a/drivers/soc/aspeed/aspeed-mctp.c b/drivers/soc/aspeed/aspeed-mctp.c -new file mode 100644 -index 000000000000..addf96133abf ---- /dev/null -+++ b/drivers/soc/aspeed/aspeed-mctp.c -@@ -0,0 +1,1126 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2020, Intel Corporation. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* AST2600 MCTP Controller registers */ -+#define ASPEED_MCTP_CTRL 0x000 -+#define TX_CMD_TRIGGER BIT(0) -+#define RX_CMD_READY BIT(4) -+#define MATCHING_EID BIT(9) -+ -+#define ASPEED_MCTP_TX_CMD 0x004 -+#define ASPEED_MCTP_RX_CMD 0x008 -+ -+#define ASPEED_MCTP_INT_STS 0x00c -+#define ASPEED_MCTP_INT_EN 0x010 -+#define TX_CMD_SENT_INT BIT(0) -+#define TX_CMD_LAST_INT BIT(1) -+#define TX_CMD_WRONG_INT BIT(2) -+#define RX_CMD_RECEIVE_INT BIT(8) -+#define RX_CMD_NO_MORE_INT BIT(9) -+ -+#define ASPEED_MCTP_EID 0x014 -+#define ASPEED_MCTP_OBFF_CTRL 0x018 -+ -+#define ASPEED_MCTP_ENGINE_CTRL 0x01c -+#define TX_MAX_PAYLOAD_SIZE_SHIFT 0 -+#define TX_MAX_PAYLOAD_SIZE_MASK GENMASK(1, TX_MAX_PAYLOAD_SIZE_SHIFT) -+#define TX_MAX_PAYLOAD_SIZE(x) \ -+ (((x) << TX_MAX_PAYLOAD_SIZE_SHIFT) & TX_MAX_PAYLOAD_SIZE_MASK) -+#define RX_MAX_PAYLOAD_SIZE_SHIFT 4 -+#define RX_MAX_PAYLOAD_SIZE_MASK GENMASK(5, RX_MAX_PAYLOAD_SIZE_SHIFT) -+#define RX_MAX_PAYLOAD_SIZE(x) \ -+ (((x) << RX_MAX_PAYLOAD_SIZE_SHIFT) & RX_MAX_PAYLOAD_SIZE_MASK) -+#define FIFO_LAYOUT_SHIFT 8 -+#define FIFO_LAYOUT_MASK GENMASK(9, FIFO_LAYOUT_SHIFT) -+#define FIFO_LAYOUT(x) \ -+ (((x) << FIFO_LAYOUT_SHIFT) & FIFO_LAYOUT_MASK) -+ -+#define ASPEED_MCTP_RX_BUF_ADDR 0x020 -+#define ASPEED_MCTP_RX_BUF_SIZE 0x024 -+#define ASPEED_MCTP_RX_BUF_RD_PTR 0x028 -+#define UPDATE_RX_RD_PTR BIT(31) -+#define RX_BUFFER_RD_PTR GENMASK(11, 0) -+#define ASPEED_MCTP_RX_BUF_WR_PTR 0x02c -+#define RX_BUFFER_WR_PTR GENMASK(11, 0) -+ -+#define ASPEED_MCTP_TX_BUF_ADDR 0x004 -+#define ASPEED_MCTP_TX_BUF_SIZE 0x034 -+#define ASPEED_MCTP_TX_BUF_RD_PTR 0x038 -+#define UPDATE_TX_RD_PTR BIT(31) -+#define TX_BUFFER_RD_PTR GENMASK(11, 0) -+#define ASPEED_MCTP_TX_BUF_WR_PTR 0x03c -+#define TX_BUFFER_WR_PTR GENMASK(11, 0) -+ -+#define ADDR_LEN (BIT(26) - 1) -+#define DATA_ADDR(x) (((x) >> 4) & ADDR_LEN) -+ -+/* TX command */ -+#define TX_LAST_CMD BIT(31) -+#define TX_DATA_ADDR_SHIFT 4 -+#define TX_DATA_ADDR_MASK GENMASK(30, TX_DATA_ADDR_SHIFT) -+#define TX_DATA_ADDR(x) \ -+ ((DATA_ADDR(x) << TX_DATA_ADDR_SHIFT) & TX_DATA_ADDR_MASK) -+#define TX_RESERVED_1_MASK GENMASK(1, 0) /* must be 1 */ -+#define TX_RESERVED_1 1 -+#define TX_STOP_AFTER_CMD BIT(16) -+#define TX_INTERRUPT_AFTER_CMD BIT(15) -+#define TX_PACKET_SIZE_SHIFT 2 -+#define TX_PACKET_SIZE_MASK GENMASK(12, TX_PACKET_SIZE_SHIFT) -+#define TX_PACKET_SIZE(x) \ -+ (((x) << TX_PACKET_SIZE_SHIFT) & TX_PACKET_SIZE_MASK) -+#define TX_RESERVED_0_MASK GENMASK(1, 0) /* MBZ */ -+#define TX_RESERVED_0 0 -+ -+/* RX command */ -+#define RX_INTERRUPT_AFTER_CMD BIT(2) -+#define RX_DATA_ADDR_SHIFT 4 -+#define RX_DATA_ADDR_MASK GENMASK(30, RX_DATA_ADDR_SHIFT) -+#define RX_DATA_ADDR(x) \ -+ ((DATA_ADDR(x) << RX_DATA_ADDR_SHIFT) & RX_DATA_ADDR_MASK) -+ -+/* Buffer sizes */ -+#define TX_CMD_COUNT 4 -+#define RX_CMD_COUNT 4 -+#define TX_MAX_CMD_COUNT SZ_4K -+#define RX_MAX_CMD_COUNT SZ_4K -+ -+/* PCIe Host Controller registers */ -+#define ASPEED_PCIE_MISC_STS_1 0x0c4 -+ -+/* PCI address definitions */ -+#define PCI_DEV_NUM_MASK GENMASK(4, 0) -+#define PCI_BUS_NUM_SHIFT 5 -+#define PCI_BUS_NUM_MASK GENMASK(12, PCI_BUS_NUM_SHIFT) -+#define GET_PCI_DEV_NUM(x) ((x) & PCI_DEV_NUM_MASK) -+#define GET_PCI_BUS_NUM(x) (((x) & PCI_BUS_NUM_MASK) >> PCI_BUS_NUM_SHIFT) -+ -+/* FIXME: ast2600 supports variable max transmission unit */ -+#define ASPEED_MCTP_MTU 64 -+ -+struct mctp_pcie_packet { -+ struct { -+ u32 hdr[4]; -+ u32 payload[16]; -+ } data; -+ u32 size; -+}; -+ -+struct aspeed_mctp_tx_cmd { -+ u32 tx_lo; -+ u32 tx_hi; -+}; -+ -+struct mctp_buffer { -+ void *vaddr; -+ dma_addr_t dma_handle; -+}; -+ -+struct mctp_channel { -+ struct mctp_buffer data; -+ struct mctp_buffer cmd; -+ struct tasklet_struct tasklet; -+ u32 rd_ptr; -+ u32 wr_ptr; -+}; -+ -+struct aspeed_mctp { -+ struct device *dev; -+ struct regmap *map; -+ struct reset_control *reset; -+ struct mctp_channel tx; -+ struct mctp_channel rx; -+ struct list_head clients; -+ spinlock_t clients_lock; /* to protect clients list operations */ -+ wait_queue_head_t wait_queue; -+ struct { -+ struct regmap *map; -+ struct delayed_work rst_dwork; -+ bool need_uevent; -+ u16 bdf; -+ } pcie; -+}; -+ -+struct mctp_client { -+ struct kref ref; -+ struct aspeed_mctp *priv; -+ struct ptr_ring tx_queue; -+ struct ptr_ring rx_queue; -+ struct list_head link; -+ bool disconnected; -+}; -+ -+#define TX_CMD_BUF_SIZE \ -+ PAGE_ALIGN(TX_CMD_COUNT * sizeof(struct aspeed_mctp_tx_cmd)) -+#define TX_DATA_BUF_SIZE \ -+ PAGE_ALIGN(TX_CMD_COUNT * sizeof(struct mctp_pcie_packet)) -+#define RX_CMD_BUF_SIZE PAGE_ALIGN(RX_CMD_COUNT * sizeof(u32)) -+#define RX_DATA_BUF_SIZE \ -+ PAGE_ALIGN(RX_CMD_COUNT * sizeof(struct mctp_pcie_packet)) -+ -+struct kmem_cache *packet_cache; -+ -+static void *packet_alloc(gfp_t flags) -+{ -+ return kmem_cache_alloc(packet_cache, flags); -+} -+ -+static void packet_free(void *packet) -+{ -+ kmem_cache_free(packet_cache, packet); -+} -+ -+static void aspeed_mctp_rx_trigger(struct mctp_channel *rx) -+{ -+ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx); -+ -+ /* -+ * Even though rx_buf_addr doesn't change, if we don't do the write -+ * here, the HW doesn't trigger RX. -+ * Also, note that we're writing 0 as wr_ptr. If we're writing other -+ * value, the HW behaves in a bizzare way that's hard to explain... -+ */ -+ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_ADDR, rx->cmd.dma_handle); -+ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_WR_PTR, 0); -+ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, RX_CMD_READY, -+ RX_CMD_READY); -+} -+ -+static void aspeed_mctp_tx_trigger(struct mctp_channel *tx) -+{ -+ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx); -+ -+ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_ADDR, -+ tx->cmd.dma_handle); -+ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_WR_PTR, tx->wr_ptr); -+ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, TX_CMD_TRIGGER, -+ TX_CMD_TRIGGER); -+} -+ -+static void aspeed_mctp_emit_tx_cmd(struct mctp_channel *tx, -+ struct mctp_pcie_packet *packet, bool last) -+{ -+ struct aspeed_mctp_tx_cmd *tx_cmd = -+ (struct aspeed_mctp_tx_cmd *)tx->cmd.vaddr + tx->wr_ptr; -+ u32 packet_sz_dw = packet->size / sizeof(u32) - -+ sizeof(packet->data.hdr) / sizeof(u32); -+ u32 offset = tx->wr_ptr * sizeof(packet->data); -+ -+ memcpy(tx->data.vaddr + offset, &packet->data, -+ sizeof(packet->data)); -+ -+ tx_cmd->tx_lo |= TX_PACKET_SIZE(packet_sz_dw); -+ tx_cmd->tx_lo |= TX_STOP_AFTER_CMD; -+ tx_cmd->tx_lo |= TX_INTERRUPT_AFTER_CMD; -+ tx_cmd->tx_hi |= TX_RESERVED_1; -+ tx_cmd->tx_hi |= TX_DATA_ADDR(tx->data.dma_handle + offset); -+ if (last) -+ tx_cmd->tx_hi |= TX_LAST_CMD; -+ -+ tx->wr_ptr++; -+} -+ -+static struct mctp_client *aspeed_mctp_client_alloc(struct aspeed_mctp *priv) -+{ -+ struct mctp_client *client; -+ -+ client = kzalloc(sizeof(*client), GFP_KERNEL); -+ if (!client) -+ goto out; -+ -+ kref_init(&client->ref); -+ client->priv = priv; -+ ptr_ring_init(&client->tx_queue, TX_CMD_COUNT, GFP_KERNEL); -+ ptr_ring_init(&client->rx_queue, RX_CMD_COUNT, GFP_ATOMIC); -+ -+out: -+ return client; -+} -+ -+static void aspeed_mctp_client_free(struct kref *ref) -+{ -+ struct mctp_client *client = container_of(ref, typeof(*client), ref); -+ -+ ptr_ring_cleanup(&client->rx_queue, &packet_free); -+ ptr_ring_cleanup(&client->tx_queue, &packet_free); -+ -+ kfree(client); -+} -+ -+static void aspeed_mctp_client_get(struct mctp_client *client) -+{ -+ lockdep_assert_held(&client->priv->clients_lock); -+ -+ kref_get(&client->ref); -+} -+ -+static void aspeed_mctp_client_put(struct mctp_client *client) -+{ -+ kref_put(&client->ref, &aspeed_mctp_client_free); -+} -+ -+static void aspeed_mctp_tx_tasklet(unsigned long data) -+{ -+ struct mctp_channel *tx = (struct mctp_channel *)data; -+ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx); -+ u32 rd_ptr = READ_ONCE(tx->rd_ptr); -+ struct mctp_pcie_packet *packet; -+ struct mctp_client *client; -+ bool last, trigger = false; -+ -+ /* we're called while there's still TX in progress */ -+ if (rd_ptr == 0 && tx->wr_ptr != 0) -+ return; -+ -+ spin_lock(&priv->clients_lock); -+ client = list_first_entry_or_null(&priv->clients, typeof(*client), -+ link); -+ if (!client) { -+ spin_unlock(&priv->clients_lock); -+ return; -+ } -+ aspeed_mctp_client_get(client); -+ spin_unlock(&priv->clients_lock); -+ -+ /* last tx ended up with buffer size, meaning we now restart from 0 */ -+ if (rd_ptr == TX_CMD_COUNT) { -+ WRITE_ONCE(tx->rd_ptr, 0); -+ tx->wr_ptr = 0; -+ } -+ -+ while (tx->wr_ptr < TX_CMD_COUNT) { -+ packet = ptr_ring_consume(&client->tx_queue); -+ if (!packet) -+ break; -+ -+ last = !__ptr_ring_peek(&client->tx_queue); -+ -+ aspeed_mctp_emit_tx_cmd(tx, packet, last); -+ packet_free(packet); -+ -+ trigger = true; -+ -+ if (last) -+ break; -+ } -+ -+ aspeed_mctp_client_put(client); -+ -+ if (trigger) -+ aspeed_mctp_tx_trigger(tx); -+} -+ -+static void aspeed_mctp_rx_tasklet(unsigned long data) -+{ -+ struct mctp_channel *rx = (struct mctp_channel *)data; -+ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx); -+ u32 rd_ptr = READ_ONCE(priv->rx.rd_ptr); -+ struct mctp_pcie_packet *rx_packet; -+ struct mctp_client *client; -+ int ret; -+ -+ spin_lock(&priv->clients_lock); -+ client = list_first_entry_or_null(&priv->clients, typeof(*client), -+ link); -+ if (!client) { -+ rx->wr_ptr = rd_ptr; -+ spin_unlock(&priv->clients_lock); -+ goto out_skip; -+ } -+ aspeed_mctp_client_get(client); -+ spin_unlock(&priv->clients_lock); -+ -+ while (rx->wr_ptr < rd_ptr) { -+ rx_packet = packet_alloc(GFP_ATOMIC); -+ if (!rx_packet) { -+ dev_err(priv->dev, "Failed to allocate RX packet\n"); -+ goto out_put; -+ } -+ -+ memcpy(&rx_packet->data, -+ rx->data.vaddr + rx->wr_ptr * sizeof(rx_packet->data), -+ sizeof(rx_packet->data)); -+ rx->wr_ptr++; -+ -+ ret = ptr_ring_produce(&client->rx_queue, rx_packet); -+ if (ret) { -+ dev_warn(priv->dev, "Failed to produce RX packet: %d\n", -+ ret); -+ packet_free(rx_packet); -+ continue; -+ } -+ } -+out_skip: -+ if (rx->wr_ptr == RX_CMD_COUNT || (rx->wr_ptr == 0 && rd_ptr == 0)) { -+ rx->wr_ptr = 0; -+ if (client) -+ aspeed_mctp_rx_trigger(rx); -+ else -+ WRITE_ONCE(rx->rd_ptr, 0); -+ } -+ wake_up_all(&priv->wait_queue); -+ -+out_put: -+ if (client) -+ aspeed_mctp_client_put(client); -+} -+ -+static void aspeed_mctp_rx_chan_init(struct mctp_channel *rx) -+{ -+ struct aspeed_mctp *priv = container_of(rx, typeof(*priv), rx); -+ u32 *rx_cmd = (u32 *)rx->cmd.vaddr; -+ u32 rx_data_addr = rx->data.dma_handle; -+ struct mctp_pcie_packet packet; -+ u32 data_size = sizeof(packet.data); -+ u32 i; -+ -+ for (i = 0; i < RX_CMD_COUNT; i++) { -+ *rx_cmd |= RX_DATA_ADDR(rx_data_addr); -+ *rx_cmd |= RX_INTERRUPT_AFTER_CMD; -+ rx_data_addr += data_size; -+ rx_cmd++; -+ } -+ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_SIZE, RX_CMD_COUNT); -+} -+ -+static void aspeed_mctp_tx_chan_init(struct mctp_channel *tx) -+{ -+ struct aspeed_mctp *priv = container_of(tx, typeof(*priv), tx); -+ -+ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_SIZE, TX_CMD_COUNT); -+ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_WR_PTR, 0); -+} -+ -+static int aspeed_mctp_open(struct inode *inode, struct file *file) -+{ -+ struct miscdevice *misc = file->private_data; -+ struct platform_device *pdev = to_platform_device(misc->parent); -+ struct aspeed_mctp *priv = platform_get_drvdata(pdev); -+ struct mctp_client *client; -+ int ret; -+ -+ if (priv->pcie.bdf == 0) { -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ client = aspeed_mctp_client_alloc(priv); -+ if (!client) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ spin_lock_bh(&priv->clients_lock); -+ /* TODO: Add support for multiple clients */ -+ if (!list_empty(&priv->clients)) { -+ ret = -EBUSY; -+ goto out_unlock; -+ } -+ list_add_tail(&client->link, &priv->clients); -+ spin_unlock_bh(&priv->clients_lock); -+ -+ /* -+ * kick the tasklet to trigger rx -+ * bh_disable/enable is just to make sure that the tasklet gets -+ * scheduled immediately in process context without any unnecessary -+ * delay -+ */ -+ local_bh_disable(); -+ tasklet_hi_schedule(&priv->rx.tasklet); -+ local_bh_enable(); -+ -+ file->private_data = client; -+ -+ return 0; -+out_unlock: -+ spin_unlock_bh(&priv->clients_lock); -+ aspeed_mctp_client_put(client); -+out: -+ return ret; -+} -+ -+static int aspeed_mctp_release(struct inode *inode, struct file *file) -+{ -+ struct mctp_client *client = file->private_data; -+ struct aspeed_mctp *priv = client->priv; -+ -+ spin_lock_bh(&priv->clients_lock); -+ list_del(&client->link); -+ spin_unlock_bh(&priv->clients_lock); -+ -+ /* Disable the tasklet to appease lockdep */ -+ local_bh_disable(); -+ aspeed_mctp_client_put(client); -+ local_bh_enable(); -+ -+ return 0; -+} -+ -+static ssize_t aspeed_mctp_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct mctp_client *client = file->private_data; -+ struct aspeed_mctp *priv = client->priv; -+ struct mctp_pcie_packet *rx_packet; -+ size_t packet_sz = sizeof(rx_packet->data); -+ -+ if (READ_ONCE(client->disconnected)) -+ return -EIO; -+ -+ if (buf && count > 0) { -+ if (count > packet_sz) -+ count = packet_sz; -+ -+ rx_packet = ptr_ring_consume_bh(&client->rx_queue); -+ if (!rx_packet) -+ return -EAGAIN; -+ -+ if (copy_to_user(buf, &rx_packet->data, count)) { -+ dev_err(priv->dev, "copy to user failed\n"); -+ packet_free(rx_packet); -+ return -EFAULT; -+ } -+ -+ packet_free(rx_packet); -+ } -+ -+ return count; -+} -+ -+static ssize_t aspeed_mctp_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct mctp_client *client = file->private_data; -+ struct aspeed_mctp *priv = client->priv; -+ struct mctp_pcie_packet *tx_packet; -+ int ret; -+ -+ if (READ_ONCE(client->disconnected)) -+ return -EIO; -+ -+ tx_packet = packet_alloc(GFP_KERNEL); -+ if (!tx_packet) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ if (buf && count > 0) { -+ if (count > sizeof(tx_packet->data)) { -+ ret = -ENOSPC; -+ goto out_packet; -+ } -+ -+ if (copy_from_user(&tx_packet->data, buf, count)) { -+ dev_err(priv->dev, "copy from user failed\n"); -+ ret = -EFAULT; -+ goto out_packet; -+ } -+ tx_packet->size = count; -+ -+ ret = ptr_ring_produce_bh(&client->tx_queue, tx_packet); -+ if (ret) -+ goto out_packet; -+ -+ tasklet_hi_schedule(&priv->tx.tasklet); -+ } -+ -+ return count; -+ -+out_packet: -+ packet_free(tx_packet); -+out: -+ return ret; -+} -+ -+static int -+aspeed_mctp_filter_eid(struct aspeed_mctp *priv, void __user *userbuf) -+{ -+ struct aspeed_mctp_filter_eid eid; -+ -+ if (copy_from_user(&eid, userbuf, sizeof(eid))) { -+ dev_err(priv->dev, "copy from user failed\n"); -+ return -EFAULT; -+ } -+ -+ if (eid.enable) { -+ regmap_write(priv->map, ASPEED_MCTP_EID, eid.eid); -+ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, -+ MATCHING_EID, MATCHING_EID); -+ } else { -+ regmap_update_bits(priv->map, ASPEED_MCTP_CTRL, -+ MATCHING_EID, 0); -+ } -+ return 0; -+} -+ -+static int aspeed_mctp_get_bdf(struct aspeed_mctp *priv, void __user *userbuf) -+{ -+ struct aspeed_mctp_get_bdf bdf = { priv->pcie.bdf }; -+ -+ if (copy_to_user(userbuf, &bdf, sizeof(bdf))) { -+ dev_err(priv->dev, "copy to user failed\n"); -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+static int -+aspeed_mctp_get_medium_id(struct aspeed_mctp *priv, void __user *userbuf) -+{ -+ struct aspeed_mctp_get_medium_id id = { 0x09 }; /* PCIe revision 2.0 */ -+ -+ if (copy_to_user(userbuf, &id, sizeof(id))) { -+ dev_err(priv->dev, "copy to user failed\n"); -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+static int -+aspeed_mctp_get_mtu(struct aspeed_mctp *priv, void __user *userbuf) -+{ -+ struct aspeed_mctp_get_mtu id = { ASPEED_MCTP_MTU }; -+ -+ if (copy_to_user(userbuf, &id, sizeof(id))) { -+ dev_err(priv->dev, "copy to user failed\n"); -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+static long -+aspeed_mctp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct mctp_client *client = file->private_data; -+ struct aspeed_mctp *priv = client->priv; -+ void __user *userbuf = (void __user *)arg; -+ int ret; -+ -+ switch (cmd) { -+ case ASPEED_MCTP_IOCTL_FILTER_EID: -+ ret = aspeed_mctp_filter_eid(priv, userbuf); -+ break; -+ -+ case ASPEED_MCTP_IOCTL_GET_BDF: -+ ret = aspeed_mctp_get_bdf(priv, userbuf); -+ break; -+ -+ case ASPEED_MCTP_IOCTL_GET_MEDIUM_ID: -+ ret = aspeed_mctp_get_medium_id(priv, userbuf); -+ break; -+ -+ case ASPEED_MCTP_IOCTL_GET_MTU: -+ ret = aspeed_mctp_get_mtu(priv, userbuf); -+ break; -+ -+ default: -+ dev_err(priv->dev, "Command not found\n"); -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static __poll_t aspeed_mctp_poll(struct file *file, -+ struct poll_table_struct *pt) -+{ -+ struct mctp_client *client = file->private_data; -+ struct aspeed_mctp *priv = client->priv; -+ __poll_t ret = 0; -+ -+ poll_wait(file, &priv->wait_queue, pt); -+ -+ if (!ptr_ring_full_bh(&client->tx_queue)) -+ ret |= EPOLLOUT; -+ -+ if (__ptr_ring_peek(&client->rx_queue)) -+ ret |= EPOLLIN; -+ -+ return ret; -+} -+ -+static const struct file_operations aspeed_mctp_fops = { -+ .owner = THIS_MODULE, -+ .open = aspeed_mctp_open, -+ .release = aspeed_mctp_release, -+ .read = aspeed_mctp_read, -+ .write = aspeed_mctp_write, -+ .unlocked_ioctl = aspeed_mctp_ioctl, -+ .poll = aspeed_mctp_poll, -+}; -+ -+static const struct regmap_config aspeed_mctp_regmap_cfg = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = ASPEED_MCTP_TX_BUF_WR_PTR, -+}; -+ -+struct device_type aspeed_mctp_type = { -+ .name = "aspeed-mctp", -+}; -+ -+static struct miscdevice aspeed_mctp_miscdev = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = "aspeed-mctp", -+ .fops = &aspeed_mctp_fops, -+}; -+ -+static void aspeed_mctp_send_pcie_uevent(struct kobject *kobj, bool ready) -+{ -+ char *pcie_not_ready_event[] = { ASPEED_MCTP_READY "=0", NULL }; -+ char *pcie_ready_event[] = { ASPEED_MCTP_READY "=1", NULL }; -+ -+ kobject_uevent_env(kobj, KOBJ_CHANGE, -+ ready ? pcie_ready_event : pcie_not_ready_event); -+} -+ -+static void aspeed_mctp_pcie_setup(struct aspeed_mctp *priv) -+{ -+ u32 reg; -+ -+ regmap_read(priv->pcie.map, ASPEED_PCIE_MISC_STS_1, ®); -+ -+ priv->pcie.bdf = PCI_DEVID(GET_PCI_BUS_NUM(reg), GET_PCI_DEV_NUM(reg)); -+ if (priv->pcie.bdf != 0) -+ cancel_delayed_work(&priv->pcie.rst_dwork); -+ else -+ schedule_delayed_work(&priv->pcie.rst_dwork, -+ msecs_to_jiffies(1000)); -+} -+ -+static void aspeed_mctp_irq_enable(struct aspeed_mctp *priv) -+{ -+ u32 enable = TX_CMD_LAST_INT | TX_CMD_WRONG_INT | -+ RX_CMD_RECEIVE_INT; -+ -+ regmap_write(priv->map, ASPEED_MCTP_INT_EN, enable); -+} -+ -+static void aspeed_mctp_irq_disable(struct aspeed_mctp *priv) -+{ -+ regmap_write(priv->map, ASPEED_MCTP_INT_EN, 0); -+} -+ -+static void aspeed_mctp_reset_work(struct work_struct *work) -+{ -+ struct aspeed_mctp *priv = container_of(work, typeof(*priv), -+ pcie.rst_dwork.work); -+ -+ /* -+ * Client "disconnection" is permanent to avoid forcing the user to use -+ * uevents in order to monitor for reset. Even if no reads/writes are -+ * issued during pci reset, userspace will still get -EIO afterwards, -+ * forcing it to reopen and check the BDF (which may have potentially -+ * changed after reset). Uevents can be used to avoid looping in open() -+ */ -+ if (priv->pcie.need_uevent) { -+ struct kobject *kobj = &aspeed_mctp_miscdev.this_device->kobj; -+ struct mctp_client *client; -+ -+ spin_lock_bh(&priv->clients_lock); -+ client = list_first_entry_or_null(&priv->clients, -+ typeof(*client), link); -+ /* -+ * Here, we're only updating the "disconnected" flag under -+ * spinlock, meaning that we can skip taking the refcount -+ */ -+ if (client) -+ WRITE_ONCE(client->disconnected, true); -+ spin_unlock_bh(&priv->clients_lock); -+ -+ aspeed_mctp_send_pcie_uevent(kobj, false); -+ priv->pcie.need_uevent = false; -+ } -+ -+ aspeed_mctp_pcie_setup(priv); -+ -+ if (priv->pcie.bdf) { -+ aspeed_mctp_send_pcie_uevent(&priv->dev->kobj, true); -+ aspeed_mctp_irq_enable(priv); -+ } -+} -+ -+static void aspeed_mctp_channels_init(struct aspeed_mctp *priv) -+{ -+ aspeed_mctp_rx_chan_init(&priv->rx); -+ aspeed_mctp_tx_chan_init(&priv->tx); -+} -+ -+static irqreturn_t aspeed_mctp_irq_handler(int irq, void *arg) -+{ -+ struct aspeed_mctp *priv = arg; -+ u32 handled = 0; -+ u32 status; -+ -+ regmap_read(priv->map, ASPEED_MCTP_INT_STS, &status); -+ regmap_write(priv->map, ASPEED_MCTP_INT_STS, status); -+ -+ if (status & TX_CMD_LAST_INT) { -+ u32 rd_ptr; -+ -+ regmap_write(priv->map, ASPEED_MCTP_TX_BUF_RD_PTR, -+ UPDATE_RX_RD_PTR); -+ regmap_read(priv->map, ASPEED_MCTP_TX_BUF_RD_PTR, &rd_ptr); -+ rd_ptr &= TX_BUFFER_RD_PTR; -+ -+ /* -+ * rd_ptr on TX side seems to be busted... -+ * Since we're always reading zeroes, let's trust that when -+ * we're getting LAST_CMD irq, everything we previously -+ * submitted was transmitted and start from 0 -+ */ -+ WRITE_ONCE(priv->tx.rd_ptr, TX_CMD_COUNT); -+ -+ tasklet_hi_schedule(&priv->tx.tasklet); -+ -+ wake_up_all(&priv->wait_queue); -+ -+ handled |= TX_CMD_LAST_INT; -+ } -+ -+ if (status & TX_CMD_WRONG_INT) { -+ /* TODO: print the actual command */ -+ dev_warn(priv->dev, "TX wrong"); -+ -+ handled |= TX_CMD_WRONG_INT; -+ } -+ -+ if (status & RX_CMD_RECEIVE_INT) { -+ u32 rd_ptr; -+ -+ regmap_write(priv->map, ASPEED_MCTP_RX_BUF_RD_PTR, -+ UPDATE_RX_RD_PTR); -+ regmap_read(priv->map, ASPEED_MCTP_RX_BUF_RD_PTR, &rd_ptr); -+ rd_ptr &= RX_BUFFER_RD_PTR; -+ -+ WRITE_ONCE(priv->rx.rd_ptr, rd_ptr > 0 ? rd_ptr : RX_CMD_COUNT); -+ -+ tasklet_hi_schedule(&priv->rx.tasklet); -+ -+ handled |= RX_CMD_RECEIVE_INT; -+ } -+ -+ if (!handled) -+ return IRQ_NONE; -+ -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t aspeed_mctp_pcie_rst_irq_handler(int irq, void *arg) -+{ -+ struct aspeed_mctp *priv = arg; -+ -+ aspeed_mctp_channels_init(priv); -+ -+ priv->pcie.need_uevent = true; -+ priv->pcie.bdf = 0; -+ -+ schedule_delayed_work(&priv->pcie.rst_dwork, 0); -+ -+ return IRQ_HANDLED; -+} -+ -+static void aspeed_mctp_drv_init(struct aspeed_mctp *priv) -+{ -+ init_waitqueue_head(&priv->wait_queue); -+ INIT_LIST_HEAD(&priv->clients); -+ -+ spin_lock_init(&priv->clients_lock); -+ -+ INIT_DELAYED_WORK(&priv->pcie.rst_dwork, aspeed_mctp_reset_work); -+ -+ tasklet_init(&priv->tx.tasklet, aspeed_mctp_tx_tasklet, -+ (unsigned long)&priv->tx); -+ tasklet_init(&priv->rx.tasklet, aspeed_mctp_rx_tasklet, -+ (unsigned long)&priv->rx); -+} -+ -+static void aspeed_mctp_drv_fini(struct aspeed_mctp *priv) -+{ -+ tasklet_disable(&priv->tx.tasklet); -+ tasklet_kill(&priv->tx.tasklet); -+ tasklet_disable(&priv->rx.tasklet); -+ tasklet_kill(&priv->rx.tasklet); -+ -+ cancel_delayed_work_sync(&priv->pcie.rst_dwork); -+} -+ -+static int aspeed_mctp_resources_init(struct aspeed_mctp *priv) -+{ -+ struct platform_device *pdev = to_platform_device(priv->dev); -+ void __iomem *regs; -+ -+ regs = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(regs)) { -+ dev_err(priv->dev, "Failed to get regmap!\n"); -+ return PTR_ERR(regs); -+ } -+ -+ priv->map = devm_regmap_init_mmio(priv->dev, regs, -+ &aspeed_mctp_regmap_cfg); -+ if (IS_ERR(priv->map)) -+ return PTR_ERR(priv->map); -+ -+ priv->reset = devm_reset_control_get(priv->dev, 0); -+ if (IS_ERR(priv->reset)) { -+ dev_err(priv->dev, "Failed to get reset!\n"); -+ return PTR_ERR(priv->reset); -+ } -+ -+ priv->pcie.map = -+ syscon_regmap_lookup_by_phandle(priv->dev->of_node, -+ "aspeed,pcieh"); -+ if (IS_ERR(priv->pcie.map)) { -+ dev_err(priv->dev, "Failed to find PCIe Host regmap!\n"); -+ return PTR_ERR(priv->pcie.map); -+ } -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static int aspeed_mctp_dma_init(struct aspeed_mctp *priv) -+{ -+ struct mctp_channel *tx = &priv->tx; -+ struct mctp_channel *rx = &priv->rx; -+ int ret = -ENOMEM; -+ -+ BUILD_BUG_ON(TX_CMD_COUNT >= TX_MAX_CMD_COUNT); -+ BUILD_BUG_ON(RX_CMD_COUNT >= RX_MAX_CMD_COUNT); -+ -+ tx->cmd.vaddr = dma_alloc_coherent(priv->dev, TX_CMD_BUF_SIZE, -+ &tx->cmd.dma_handle, GFP_KERNEL); -+ -+ if (!tx->cmd.vaddr) -+ return ret; -+ -+ tx->data.vaddr = dma_alloc_coherent(priv->dev, TX_DATA_BUF_SIZE, -+ &tx->data.dma_handle, GFP_KERNEL); -+ -+ if (!tx->data.vaddr) -+ goto out_tx_data; -+ -+ rx->cmd.vaddr = dma_alloc_coherent(priv->dev, RX_CMD_BUF_SIZE, -+ &rx->cmd.dma_handle, GFP_KERNEL); -+ -+ if (!rx->cmd.vaddr) -+ goto out_tx_cmd; -+ -+ rx->data.vaddr = dma_alloc_coherent(priv->dev, RX_DATA_BUF_SIZE, -+ &rx->data.dma_handle, GFP_KERNEL); -+ -+ if (!rx->data.vaddr) -+ goto out_rx_data; -+ -+ return 0; -+out_rx_data: -+ dma_free_coherent(priv->dev, RX_CMD_BUF_SIZE, rx->cmd.vaddr, -+ rx->cmd.dma_handle); -+ -+out_tx_cmd: -+ dma_free_coherent(priv->dev, TX_DATA_BUF_SIZE, tx->data.vaddr, -+ tx->data.dma_handle); -+ -+out_tx_data: -+ dma_free_coherent(priv->dev, TX_CMD_BUF_SIZE, tx->cmd.vaddr, -+ tx->cmd.dma_handle); -+ return ret; -+} -+ -+static void aspeed_mctp_dma_fini(struct aspeed_mctp *priv) -+{ -+ struct mctp_channel *tx = &priv->tx; -+ struct mctp_channel *rx = &priv->rx; -+ -+ dma_free_coherent(priv->dev, TX_CMD_BUF_SIZE, tx->cmd.vaddr, -+ tx->cmd.dma_handle); -+ -+ dma_free_coherent(priv->dev, RX_CMD_BUF_SIZE, rx->cmd.vaddr, -+ rx->cmd.dma_handle); -+ -+ dma_free_coherent(priv->dev, TX_DATA_BUF_SIZE, tx->data.vaddr, -+ tx->data.dma_handle); -+ -+ dma_free_coherent(priv->dev, RX_DATA_BUF_SIZE, rx->data.vaddr, -+ rx->data.dma_handle); -+} -+ -+static int aspeed_mctp_irq_init(struct aspeed_mctp *priv) -+{ -+ struct platform_device *pdev = to_platform_device(priv->dev); -+ int irq, ret; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (!irq) -+ return -ENODEV; -+ -+ ret = devm_request_irq(priv->dev, irq, aspeed_mctp_irq_handler, -+ IRQF_SHARED, "aspeed-mctp", priv); -+ if (ret) -+ return ret; -+ -+ irq = platform_get_irq(pdev, 1); -+ if (!irq) -+ return -ENODEV; -+ -+ ret = devm_request_irq(priv->dev, irq, -+ aspeed_mctp_pcie_rst_irq_handler, -+ IRQF_SHARED, "aspeed-mctp", priv); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static void aspeed_mctp_hw_reset(struct aspeed_mctp *priv) -+{ -+ if (reset_control_assert(priv->reset) != 0) -+ dev_warn(priv->dev, "Failed to assert reset\n"); -+ -+ if (reset_control_deassert(priv->reset) != 0) -+ dev_warn(priv->dev, "Failed to deassert reset\n"); -+} -+ -+static int aspeed_mctp_probe(struct platform_device *pdev) -+{ -+ struct aspeed_mctp *priv; -+ int ret; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ priv->dev = &pdev->dev; -+ -+ aspeed_mctp_drv_init(priv); -+ -+ ret = aspeed_mctp_resources_init(priv); -+ if (ret) { -+ dev_err(priv->dev, "Failed to init resources\n"); -+ goto out_drv; -+ } -+ -+ ret = aspeed_mctp_dma_init(priv); -+ if (ret) { -+ dev_err(priv->dev, "Failed to init DMA\n"); -+ goto out_drv; -+ } -+ -+ /* -+ * FIXME: We need to verify how to make the reset work when we probe -+ * multiple times. Currently calling reset more than once seems to make -+ * the HW upset, however, we do need to reset after boot before we're -+ * able to use the HW. -+ */ -+ aspeed_mctp_hw_reset(priv); -+ -+ aspeed_mctp_channels_init(priv); -+ -+ aspeed_mctp_miscdev.parent = priv->dev; -+ ret = misc_register(&aspeed_mctp_miscdev); -+ if (ret) { -+ dev_err(priv->dev, "Failed to register miscdev\n"); -+ goto out_dma; -+ } -+ aspeed_mctp_miscdev.this_device->type = &aspeed_mctp_type; -+ -+ ret = aspeed_mctp_irq_init(priv); -+ if (ret) { -+ dev_err(priv->dev, "Failed to init IRQ!\n"); -+ goto out_dma; -+ } -+ -+ aspeed_mctp_irq_enable(priv); -+ -+ aspeed_mctp_pcie_setup(priv); -+ -+ return 0; -+ -+out_dma: -+ aspeed_mctp_dma_fini(priv); -+out_drv: -+ aspeed_mctp_drv_fini(priv); -+out: -+ dev_err(priv->dev, "Failed to probe Aspeed MCTP: %d\n", ret); -+ return ret; -+} -+ -+static int aspeed_mctp_remove(struct platform_device *pdev) -+{ -+ struct aspeed_mctp *priv = platform_get_drvdata(pdev); -+ -+ misc_deregister(&aspeed_mctp_miscdev); -+ -+ aspeed_mctp_irq_disable(priv); -+ -+ aspeed_mctp_dma_fini(priv); -+ -+ aspeed_mctp_drv_fini(priv); -+ -+ return 0; -+} -+ -+static const struct of_device_id aspeed_mctp_match_table[] = { -+ { .compatible = "aspeed,ast2600-mctp" }, -+ { } -+}; -+ -+static struct platform_driver aspeed_mctp_driver = { -+ .driver = { -+ .name = "aspeed-mctp", -+ .of_match_table = of_match_ptr(aspeed_mctp_match_table), -+ }, -+ .probe = aspeed_mctp_probe, -+ .remove = aspeed_mctp_remove, -+}; -+ -+static int __init aspeed_mctp_init(void) -+{ -+ packet_cache = -+ kmem_cache_create_usercopy("mctp-packet", -+ sizeof(struct mctp_pcie_packet), -+ 0, 0, 0, -+ sizeof(struct mctp_pcie_packet), -+ NULL); -+ if (!packet_cache) -+ return -ENOMEM; -+ -+ return platform_driver_register(&aspeed_mctp_driver); -+} -+ -+static void __exit aspeed_mctp_exit(void) -+{ -+ platform_driver_unregister(&aspeed_mctp_driver); -+ kmem_cache_destroy(packet_cache); -+} -+ -+module_init(aspeed_mctp_init) -+module_exit(aspeed_mctp_exit) -+ -+MODULE_DEVICE_TABLE(of, aspeed_mctp_match_table); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Iwona Winiarska "); -+MODULE_DESCRIPTION("Aspeed AST2600 MCTP driver"); -diff --git a/include/uapi/linux/aspeed-mctp.h b/include/uapi/linux/aspeed-mctp.h -new file mode 100644 -index 000000000000..e37fa3afde9d ---- /dev/null -+++ b/include/uapi/linux/aspeed-mctp.h -@@ -0,0 +1,72 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* Copyright (c) 2020 Intel Corporation */ -+ -+#ifndef _UAPI_LINUX_ASPEED_MCTP_H -+#define _UAPI_LINUX_ASPEED_MCTP_H -+ -+#include -+#include -+ -+/* -+ * aspeed-mctp is a simple device driver exposing a read/write interface: -+ * +----------------------+ -+ * | PCIe VDM Header | 16 bytes (Big Endian) -+ * +----------------------+ -+ * | MCTP Message Payload | 64/128/256/512 bytes (Little Endian) -+ * +----------------------+ -+ * -+ * MCTP packet description can be found in DMTF DSP0238, -+ * MCTP PCIe VDM Transport Specification. -+ * -+ * Note: AST2600 hardware follows MCTP Message Payload rules from earlier -+ * hardware and we've decided to copy the packets directly, without swapping. -+ * This means that it's userspace responsibility to provide the data in -+ * a format that the hardware expects. -+ */ -+ -+#define ASPEED_MCTP_PCIE_VDM_HDR_SIZE 16 -+ -+/* -+ * uevents generated by aspeed-mctp driver -+ */ -+#define ASPEED_MCTP_READY "PCIE_READY" -+ -+/* -+ * MCTP operations -+ * @ASPEED_MCTP_IOCTL_FILTER_EID: enable/disable filter incoming packets based -+ * on Endpoint ID (BROKEN) -+ * @ASPEED_MCTP_IOCTL_GET_BDF: read PCI bus/device/function of MCTP Controller -+ * @ASPEED_MCTP_IOCTL_GET_MEDIUM_ID: read MCTP physical medium identifier -+ * related to PCIe revision -+ * @ASPEED_MCTP_IOCTL_GET_MTU: read max transmission unit (in bytes) -+ */ -+ -+struct aspeed_mctp_filter_eid { -+ __u8 eid; -+ bool enable; -+}; -+ -+struct aspeed_mctp_get_bdf { -+ __u16 bdf; -+}; -+ -+struct aspeed_mctp_get_medium_id { -+ __u8 medium_id; -+}; -+ -+struct aspeed_mctp_get_mtu { -+ __u8 mtu; -+}; -+ -+#define ASPEED_MCTP_IOCTL_BASE 0x4d -+ -+#define ASPEED_MCTP_IOCTL_FILTER_EID \ -+ _IOW(ASPEED_MCTP_IOCTL_BASE, 0, struct aspeed_mctp_filter_eid) -+#define ASPEED_MCTP_IOCTL_GET_BDF \ -+ _IOR(ASPEED_MCTP_IOCTL_BASE, 1, struct aspeed_mctp_get_bdf) -+#define ASPEED_MCTP_IOCTL_GET_MEDIUM_ID \ -+ _IOR(ASPEED_MCTP_IOCTL_BASE, 2, struct aspeed_mctp_get_medium_id) -+#define ASPEED_MCTP_IOCTL_GET_MTU \ -+ _IOR(ASPEED_MCTP_IOCTL_BASE, 3, struct aspeed_mctp_get_mtu) -+ -+#endif /* _UAPI_LINUX_ASPEED_MCTP_H */ --- -2.21.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch deleted file mode 100644 index 542d80e16..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 15753588bcd4bbffae1cca33c8ced5722477fe1f Mon Sep 17 00:00:00 2001 -From: Kyungtae Kim -Date: Sun, 10 May 2020 05:43:34 +0000 -Subject: [PATCH] USB: gadget: fix illegal array access in binding with UDC - -FuzzUSB (a variant of syzkaller) found an illegal array access -using an incorrect index while binding a gadget with UDC. - -Reference: https://www.spinics.net/lists/linux-usb/msg194331.html - -This bug occurs when a size variable used for a buffer -is misused to access its strcpy-ed buffer. -Given a buffer along with its size variable (taken from user input), -from which, a new buffer is created using kstrdup(). -Due to the original buffer containing 0 value in the middle, -the size of the kstrdup-ed buffer becomes smaller than that of the original. -So accessing the kstrdup-ed buffer with the same size variable -triggers memory access violation. - -The fix makes sure no zero value in the buffer, -by comparing the strlen() of the orignal buffer with the size variable, -so that the access to the kstrdup-ed buffer is safe. - -BUG: KASAN: slab-out-of-bounds in gadget_dev_desc_UDC_store+0x1ba/0x200 -drivers/usb/gadget/configfs.c:266 -Read of size 1 at addr ffff88806a55dd7e by task syz-executor.0/17208 - -CPU: 2 PID: 17208 Comm: syz-executor.0 Not tainted 5.6.8 #1 -Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 -Call Trace: - __dump_stack lib/dump_stack.c:77 [inline] - dump_stack+0xce/0x128 lib/dump_stack.c:118 - print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374 - __kasan_report+0x131/0x1b0 mm/kasan/report.c:506 - kasan_report+0x12/0x20 mm/kasan/common.c:641 - __asan_report_load1_noabort+0x14/0x20 mm/kasan/generic_report.c:132 - gadget_dev_desc_UDC_store+0x1ba/0x200 drivers/usb/gadget/configfs.c:266 - flush_write_buffer fs/configfs/file.c:251 [inline] - configfs_write_file+0x2f1/0x4c0 fs/configfs/file.c:283 - __vfs_write+0x85/0x110 fs/read_write.c:494 - vfs_write+0x1cd/0x510 fs/read_write.c:558 - ksys_write+0x18a/0x220 fs/read_write.c:611 - __do_sys_write fs/read_write.c:623 [inline] - __se_sys_write fs/read_write.c:620 [inline] - __x64_sys_write+0x73/0xb0 fs/read_write.c:620 - do_syscall_64+0x9e/0x510 arch/x86/entry/common.c:294 - entry_SYSCALL_64_after_hwframe+0x49/0xbe - -Signed-off-by: Kyungtae Kim -Reported-and-tested-by: Kyungtae Kim -Cc: Felipe Balbi -Cc: stable -Link: https://lore.kernel.org/r/20200510054326.GA19198@pizza01 -Signed-off-by: Greg Kroah-Hartman ---- - drivers/usb/gadget/configfs.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c -index 32b637e3e1fa..6a9aa4413d64 100644 ---- a/drivers/usb/gadget/configfs.c -+++ b/drivers/usb/gadget/configfs.c -@@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, - char *name; - int ret; - -+ if (strlen(page) < len) -+ return -EOVERFLOW; -+ - name = kstrdup(page, GFP_KERNEL); - if (!name) - return -ENOMEM; --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0111-Unconditionally-calculate-the-PECI-AW-FCS.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0111-Unconditionally-calculate-the-PECI-AW-FCS.patch deleted file mode 100644 index 9b68f8036..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0111-Unconditionally-calculate-the-PECI-AW-FCS.patch +++ /dev/null @@ -1,73 +0,0 @@ -From e985c1cbb4cf6971c82afacb16737749a2d25452 Mon Sep 17 00:00:00 2001 -From: Johnathan Mantey -Date: Tue, 19 May 2020 11:39:00 -0700 -Subject: [PATCH] Unconditionally calculate the PECI AW FCS - -The PECI write commands that include the AW FCS byte were failing due -to the way AW FCS bytes were being managed. The current paradigm -permitted in the Redfish interface was to allow the AW FCS byte to be -omitted. The peci-core logic attempted to create the AW FCS byte. The -algorithm being used left the possibility of a bad FCS byte being -appended to the PECI command. - -This change manages the issue by always overwriting the AW FCS byte -with a value freshly calculated from the write payload. The user -supplying the AW FCS byte no longer matters. - -Tested: -Submitted this PECI sequence: -48 10 1 165 0 26 0 0 223 134 21 0 - -The sequence was sent from Redfish, and a return code of 0x40 -resulted. -Prior to this the sequence would report 0x90. - -Supplied the same sequence to "peci_cmds raw" in the console. -It failed because the number of bytes did not include the AW FCS -byte. Adding any additional byte allows the command to succeed. - -Change-Id: I217a8f136b48282634a7c8fdde7b440720c010c6 -Signed-off-by: Johnathan Mantey ---- - drivers/peci/peci-core.c | 21 ++++++--------------- - 1 file changed, 6 insertions(+), 15 deletions(-) - -diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index efb73b09a9c0..426ee2be3271 100644 ---- a/drivers/peci/peci-core.c -+++ b/drivers/peci/peci-core.c -@@ -397,25 +397,16 @@ static int peci_cmd_xfer(struct peci_adapter *adapter, void *vmsg) - case PECI_WRPCICFG_CMD: - case PECI_WRPCICFGLOCAL_CMD: - case PECI_WRENDPTCFG_CMD: -- /* Check if the AW FCS byte is already provided */ -+ /* -+ * The sender may not have supplied the AW FCS byte. -+ * Unconditionally add an Assured Write Frame Check -+ * Sequence byte -+ */ - ret = peci_aw_fcs(msg, 2 + msg->tx_len, &aw_fcs); - if (ret) - break; - -- if (msg->tx_buf[msg->tx_len - 1] != (0x80 ^ aw_fcs)) { -- /* -- * Add an Assured Write Frame Check Sequence -- * byte and increment the tx_len to include -- * the new byte. -- */ -- msg->tx_len++; -- ret = peci_aw_fcs(msg, 2 + msg->tx_len, -- &aw_fcs); -- if (ret) -- break; -- -- msg->tx_buf[msg->tx_len - 1] = 0x80 ^ aw_fcs; -- } -+ msg->tx_buf[msg->tx_len - 1] = 0x80 ^ aw_fcs; - - ret = peci_xfer_with_retries(adapter, msg, true); - break; --- -2.26.2 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0112-AST2600-enable-UART-routing.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0112-AST2600-enable-UART-routing.patch deleted file mode 100644 index 7d14f9e91..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0112-AST2600-enable-UART-routing.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 47bb1475893aab85067b286fee7f6b126ea2b633 Mon Sep 17 00:00:00 2001 -From: Kuiying Wang -Date: Wed, 10 Jun 2020 13:07:59 +0800 -Subject: [PATCH] AST2600: enable UART routing. - -Enable UART routing. - -Signed-off-by: Kuiying Wang ---- - arch/arm/boot/dts/aspeed-g6.dtsi | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi -index 90a060db20c7..0361a7ee6e14 100644 ---- a/arch/arm/boot/dts/aspeed-g6.dtsi -+++ b/arch/arm/boot/dts/aspeed-g6.dtsi -@@ -331,12 +331,6 @@ - compatible = "aspeed,ast2600-pinctrl"; - }; - -- uart_routing: uart_routing@9c { -- compatible = "aspeed,ast2500-uart-routing"; -- reg = <0x9c 0x4>; -- status = "disabled"; -- }; -- - smp-memram@180 { - compatible = "aspeed,ast2600-smpmem"; - reg = <0x180 0x40>; -@@ -688,6 +682,12 @@ - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - }; - }; -+ -+ uart_routing: uart_routing@9c { -+ compatible = "aspeed,ast2500-uart-routing"; -+ reg = <0x9c 0x4>; -+ status = "disabled"; -+ }; - }; - - sdc: sdc@1e740000 { --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch deleted file mode 100644 index 33e142c30..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0116-watchdog-aspeed-fix-AST2600-support.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 02acccc7dd2ade8cf48aff2312ebb8752c8c98eb Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo -Date: Thu, 25 Jun 2020 23:56:15 -0700 -Subject: [PATCH] watchdog: aspeed: fix AST2600 support - -AST2600 provides different function of WDT0C[4] and it doesn't -provides WDT10[1] so this commit fixes driver to make it available -on AST2600. - -Signed-off-by: Jae Hyun Yoo ---- - drivers/watchdog/aspeed_wdt.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c -index 7e00960651fa..b0afeb939686 100644 ---- a/drivers/watchdog/aspeed_wdt.c -+++ b/drivers/watchdog/aspeed_wdt.c -@@ -47,7 +47,8 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table); - #define WDT_CTRL_RESET_MODE_SOC (0x00 << 5) - #define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5) - #define WDT_CTRL_RESET_MODE_ARM_CPU (0x10 << 5) --#define WDT_CTRL_1MHZ_CLK BIT(4) -+#define WDT_CTRL_1MHZ_CLK BIT(4) /* ast2400/2500 */ -+#define WDT_CTRL_WDT_RST_BY_SOC_RST BIT(4) /* ast2600 */ - #define WDT_CTRL_WDT_EXT BIT(3) - #define WDT_CTRL_WDT_INTR BIT(2) - #define WDT_CTRL_RESET_SYSTEM BIT(1) -@@ -277,12 +278,15 @@ static int aspeed_wdt_probe(struct platform_device *pdev) - * On clock rates: - * - ast2400 wdt can run at PCLK, or 1MHz - * - ast2500 only runs at 1MHz, hard coding bit 4 to 1 -- * - ast2600 always runs at 1MHz -+ * - ast2600 uses WDT0C[4] as 'Enable WDT to be reset by SOC reset' - * - * Set the ast2400 to run at 1MHz as it simplifies the driver. - */ -- if (of_device_is_compatible(np, "aspeed,ast2400-wdt")) -+ if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || -+ of_device_is_compatible(np, "aspeed,ast2500-wdt")) - wdt->ctrl = WDT_CTRL_1MHZ_CLK; -+ else if (of_device_is_compatible(np, "aspeed,ast2600-wdt")) -+ wdt->ctrl = WDT_CTRL_WDT_RST_BY_SOC_RST; - - /* - * Control reset on a per-device basis to ensure the -@@ -367,13 +371,12 @@ static int aspeed_wdt_probe(struct platform_device *pdev) - writel(duration - 1, wdt->base + WDT_RESET_WIDTH); - } - -- status = readl(wdt->base + WDT_TIMEOUT_STATUS); -- if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { -- wdt->wdd.bootstatus = WDIOF_CARDRESET; -- -- if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || -- of_device_is_compatible(np, "aspeed,ast2500-wdt")) -+ if (!of_device_is_compatible(np, "aspeed,ast2600-wdt")) { -+ status = readl(wdt->base + WDT_TIMEOUT_STATUS); -+ if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { -+ wdt->wdd.bootstatus = WDIOF_CARDRESET; - wdt->wdd.groups = bswitch_groups; -+ } - } - - dev_set_drvdata(dev, wdt); --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch deleted file mode 100644 index f019b43ab..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch +++ /dev/null @@ -1,54 +0,0 @@ -From c63c2466e3e8f61dd61fd98f4265af2e13ac9bac Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -Date: Mon, 6 Jul 2020 13:59:52 -0700 -Subject: [PATCH] Copy raw PECI response to user-space on timeout - -When a raw PECI command times out, the response is not copied -to user-space, so the timeout completion code is lost. - -This follows the default flow and also copies the response to -user-space on timeout to give the user a valid completion code. - -Tested: -Forced PECI timeout and confirmed that the raw PECI command -returns a valid completion code to the user. - -Signed-off-by: Jason M. Bills ---- - drivers/peci/peci-dev.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/drivers/peci/peci-dev.c b/drivers/peci/peci-dev.c -index e0fe09467a80..c574d13213af 100644 ---- a/drivers/peci/peci-dev.c -+++ b/drivers/peci/peci-dev.c -@@ -138,8 +138,13 @@ static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg) - xmsg->tx_len = uxmsg.tx_len; - xmsg->rx_len = uxmsg.rx_len; - -+ /* -+ * Send the command and copy the results back to user space on -+ * either success or timeout to provide the completion code to -+ * the caller. -+ */ - ret = peci_command(peci_dev->adapter, cmd, xmsg); -- if (!ret && xmsg->rx_len && -+ if ((!ret || ret == -ETIMEDOUT) && xmsg->rx_len && - copy_to_user((__u8 __user *)uxmsg.rx_buf, xmsg->rx_buf, - xmsg->rx_len)) - ret = -EFAULT; -@@ -153,6 +158,11 @@ static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg) - break; - } - -+ /* -+ * Send the command and copy the results back to user space on -+ * either success or timeout to provide the completion code to -+ * the caller. -+ */ - ret = peci_command(peci_dev->adapter, cmd, msg); - if ((!ret || ret == -ETIMEDOUT) && - copy_to_user(umsg, msg, msg_len)) --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch deleted file mode 100644 index af173e71d..000000000 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 2453c89ead650ab8e21f13c1b0a1b4054e0e7067 Mon Sep 17 00:00:00 2001 -From: "Jason M. Bills" -Date: Mon, 27 Jul 2020 11:27:47 -0700 -Subject: [PATCH] Recalculate AW FCS on WrEndPointConfig command - -The WrEndPointConfig command requires recalculating the AW FCS -on retry, so set the has_aw_fcs parameter to true. - -Tested: -Ran a WrEndPointConfig command with C-states enabled to confirm -that it correctly retries the command: -peci_cmds WrEndpointConfigPCILocal 0 13 12 0 0x2d4 0x601e0 - -Signed-off-by: Jason M. Bills ---- - drivers/peci/peci-core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index 426ee2be3271..ba561bf810f9 100644 ---- a/drivers/peci/peci-core.c -+++ b/drivers/peci/peci-core.c -@@ -1059,7 +1059,7 @@ static int peci_cmd_wr_end_pt_cfg(struct peci_adapter *adapter, void *vmsg) - return -EINVAL; - } - -- ret = peci_xfer_with_retries(adapter, msg, false); -+ ret = peci_xfer_with_retries(adapter, msg, true); - - out: - umsg->cc = msg->rx_buf[0]; --- -2.17.1 - 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 077b83bac..5b2e178b2 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 @@ -14,6 +14,7 @@ CONFIG_SENSORS_PECI_CPUTEMP=y CONFIG_SENSORS_PECI_DIMMTEMP=y CONFIG_SENSORS_PECI_CPUPOWER=y CONFIG_SENSORS_PECI_DIMMPOWER=y +CONFIG_SENSORS_PECI_PLATFORMPOWER=y CONFIG_CONFIGFS_FS=y CONFIG_BLK_DEV_RAM_SIZE=49152 CONFIG_MAGIC_SYSRQ=y @@ -88,3 +89,4 @@ CONFIG_USB_EHCI_HCD=n CONFIG_USB_EHCI_ROOT_HUB_TT=n CONFIG_USB_EHCI_HCD_PLATFORM=n CONFIG_IPMB_DEVICE_INTERFACE=y +CONFIG_BPF_SYSCALL=n diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend index 8250ec919..4875050a9 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -1,5 +1,11 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +KBRANCH = "dev-5.8-intel" +KSRC = "git://github.com/Intel-BMC/linux;protocol=ssh;branch=${KBRANCH}" +# Include this as a comment only for downstream auto-bump +# SRC_URI = "git://github.com/Intel-BMC/linux;protocol=ssh;branch=dev-5.8-intel" +SRCREV="9f71530c30ebbec6fc5267475b5517add7ad40ce" + do_compile_prepend(){ # device tree compiler flags export DTC_FLAGS=-@ @@ -7,85 +13,6 @@ do_compile_prepend(){ SRC_URI += " \ file://intel.cfg \ - file://0001-arm-dts-add-DTS-for-Intel-ast2500-platforms.patch \ - file://0001-arm-dts-intel-s2600wf-dts-fixups.patch \ - file://0001-arm-dts-add-DTS-for-Intel-ast2600-platforms.patch \ - file://0001-arm-dts-base-aspeed-g6-dtsi-fixups.patch \ - file://0002-Enable-pass-through-on-GPIOE1-and-GPIOE3-free.patch \ - file://0003-Enable-GPIOE0-and-GPIOE2-pass-through-by-default.patch \ - file://0006-Allow-monitoring-of-power-control-input-GPIOs.patch \ - file://0007-aspeed-pwm-tacho-change-default-fan-speed.patch \ - file://0014-arm-dts-aspeed-g5-add-espi.patch \ - file://0015-New-flash-map-for-intel.patch \ - file://0016-Add-ASPEED-SGPIO-driver.patch \ - file://0017-SGPIO-DT-and-pinctrl-fixup.patch \ - file://0019-Add-I2C-IPMB-support.patch \ - file://0020-misc-aspeed-add-lpc-mbox-driver.patch \ - file://0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch \ - file://0022-Add-AST2500-eSPI-driver.patch \ - file://0028-Add-AST2500-JTAG-driver.patch \ - file://0030-Add-dump-debug-code-into-I2C-drivers.patch \ - file://0031-Add-high-speed-baud-rate-support-for-UART.patch \ - file://0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch \ - file://0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch \ - file://0035-Implement-a-memory-driver-share-memory.patch \ - file://0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch \ - file://0040-i2c-Add-mux-hold-unhold-msg-types.patch \ - file://0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch \ - file://0043-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-BT.patch \ - file://0044-misc-Add-clock-control-logic-into-Aspeed-LPC-SNOOP-d.patch \ - file://0045-char-ipmi-Add-clock-control-logic-into-Aspeed-LPC-KC.patch \ - file://0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch \ - file://0049-Suppress-excessive-HID-gadget-error-logs.patch \ - file://0051-Add-AST2500-JTAG-device.patch \ - file://0052-drivers-jtag-Add-JTAG-core-driver.patch \ - file://0053-Add-Aspeed-SoC-24xx-and-25xx-families-JTAG.patch \ - file://0054-Documentation-jtag-Add-bindings-for-Aspeed-SoC.patch \ - file://0055-Documentation-jtag-Add-ABI-documentation.patch \ - file://0056-Documentation-jtag-Add-JTAG-core-driver-ioctl-number.patch \ - file://0057-drivers-jtag-Add-JTAG-core-driver-Maintainers.patch \ - file://0061-i2c-aspeed-add-buffer-mode-transfer-support.patch \ - file://0062-i2c-aspeed-add-DMA-mode-transfer-support.patch \ - file://0063-i2c-aspeed-add-general-call-support.patch \ - file://0064-set-idle-disconnect-to-true-in-all-cases.patch \ - file://0068-i2c-aspeed-add-H-W-timeout-support.patch \ - file://0069-i2c-aspeed-add-SLAVE_ADDR_RECEIVED_PENDING-interrupt.patch \ - file://0070-gpio-aspeed-temporary-fix-for-gpiochip-range-setting.patch \ - file://0072-pmbus-add-fault-and-beep-attributes.patch \ - file://0073-Add-IO-statistics-to-USB-Mass-storage-gadget.patch \ - file://0075-Refine-initialization-flow-in-I2C-driver.patch \ - file://0076-arm-ast2600-add-pwm_tacho-driver-from-aspeed.patch \ - file://0077-soc-aspeed-Add-read-only-property-support.patch \ - file://0078-Fix-NCSI-driver-issue-caused-by-host-shutdown.patch \ - file://0080-i2c-aspeed-filter-garbage-interrupts-out.patch \ - file://0084-ARM-dts-aspeed-g6-add-GFX-node.patch \ - file://0085-drm-add-AST2600-GFX-support.patch \ - file://0086-ADC-linux-driver-for-AST2600.patch \ - file://0086-ARM-dts-aspeed-g6-add-video-node.patch \ - file://0087-media-aspeed-add-aspeed-ast2600-video-engine-compati.patch \ - file://0088-clk-ast2600-enable-ESPICLK-always.patch \ - file://0089-ast2600-enable-high-speed-uart-in-kernel.patch \ - file://0090-peci-cpupower-driver-1.patch \ - file://0092-SPI-Quad-IO-driver-support-AST2600.patch \ - file://0093-ipmi-ipmb_dev_int-add-quick-fix-for-raw-I2C-type-reg.patch \ - file://0094-Return-link-speed-and-duplex-settings-for-the-NCSI-c.patch \ - file://0095-pwm-and-tach-driver-changes-for-ast2600.patch \ - file://0096-Fix-truncated-WrEndPointConfig-MMIO-command.patch \ - file://0100-Mailbox-Enabling-interrupt-based-mailbox.patch \ - file://0101-Add-poll-fops-in-eSPI-driver.patch \ - file://0102-Fix-for-dirty-node-in-jffs2-summary-entry.patch \ - file://0103-Refine-clock-settings.patch \ - file://0104-Add-chip-unique-id-reading-interface.patch \ - file://0105-i2c-aspeed-fix-arbitration-loss-handling-logic.patch \ - file://0106-enable-AST2600-I3C.patch \ - file://0107-arm-dts-aspeed-g6-Add-ast2600-mctp-node.patch \ - file://0108-soc-aspeed-mctp-Add-initial-driver-for-ast2600-mctp.patch \ - file://0110-USB-gadget-fix-illegal-array-access-in-binding-with-.patch \ - file://0111-Unconditionally-calculate-the-PECI-AW-FCS.patch \ - file://0112-AST2600-enable-UART-routing.patch \ - file://0116-watchdog-aspeed-fix-AST2600-support.patch \ - file://0117-Copy-raw-PECI-response-to-user-space-on-timeout.patch \ - file://0118-Recalculate-AW-FCS-on-WrEndPointConfig-command.patch \ " SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}" -- cgit v1.2.3