From 4c6b7217ed91713b4a88e2bbedceeaf3261ec57d Mon Sep 17 00:00:00 2001 From: aasboddu_amdeng Date: Thu, 12 Mar 2026 00:02:11 -0500 Subject: [PATCH] drivers:dts: Aspeed specific driver porting for AST2700 A2 - AMD specific AST2700 drivers are ported from Aspeed SDK 6.10 - Drivers are proted from: - URL : https://github.com/AspeedTech-BMC/linux/tree/aspeed-master-v6.6, Tag:v00.06.09 - Commint ID: 0364b2fdf854b9f3c23752d2d499747f342f42e4 - Latest base DTS 'aspeed-g7.dtsi' pulled from above repo. - dts files modified to accomodate latest base DTS and driver changes. Signed-off-by: aasboddu_amdeng --- .../boot/dts/aspeed/aspeed-bmc-amd-congo.dts | 59 +- .../boot/dts/aspeed/aspeed-bmc-amd-eagle.dts | 60 +- .../boot/dts/aspeed/aspeed-bmc-amd-falcon.dts | 60 +- .../boot/dts/aspeed/aspeed-bmc-amd-ghana.dts | 66 +- .../dts/aspeed/aspeed-bmc-amd-hornbill.dts | 66 +- .../boot/dts/aspeed/aspeed-bmc-amd-kenya.dts | 60 +- .../boot/dts/aspeed/aspeed-bmc-amd-marley.dts | 26 +- .../dts/aspeed/aspeed-bmc-amd-morocco.dts | 86 +- .../dts/aspeed/aspeed-bmc-amd-nigeria.dts | 66 +- .../dts/aspeed/aspeed-bmc-amd-nigerias3.dts | 51 +- .../dts/aspeed/aspeed-bmc-amd-seagull.dts | 67 +- arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi | 1146 +++++++------ .../boot/dts/aspeed/ast2700-reserved-mem.dtsi | 128 ++ drivers/clk/clk-ast2700.c | 1362 +++++++--------- drivers/edac/Kconfig | 9 + drivers/edac/Makefile | 1 + drivers/edac/edac_ast2700.c | 356 ++++ drivers/i3c/master/Kconfig | 7 + drivers/i3c/master/Makefile | 1 + drivers/i3c/master/amd-i3c-master.c | 1175 ++++++++++++++ drivers/i3c/master/ast2600-i3c-master.c | 34 +- drivers/irqchip/irq-aspeed-intc.c | 92 +- drivers/pci/controller/Kconfig | 9 + drivers/pci/controller/Makefile | 1 + drivers/pci/controller/pcie-aspeed.c | 1222 ++++++++++++++ drivers/soc/aspeed/Kconfig | 92 +- drivers/soc/aspeed/Makefile | 11 +- drivers/soc/aspeed/aspeed-bmc-dev.c | 112 +- drivers/soc/aspeed/aspeed-espi-comm.h | 14 +- drivers/soc/aspeed/aspeed-host-bmc-dev.c | 1434 +++++++++++++++++ drivers/soc/aspeed/aspeed-lpc-ctrl.c | 6 +- drivers/soc/aspeed/aspeed-lpc-mbox.c | 439 +++++ drivers/soc/aspeed/aspeed-lpc-pcc.c | 302 ++-- drivers/soc/aspeed/aspeed-lpc-snoop.c | 21 +- drivers/soc/aspeed/aspeed-p2a-ctrl.c | 6 +- drivers/soc/aspeed/aspeed-socinfo.c | 12 +- drivers/soc/aspeed/aspeed-uart-routing.c | 6 +- drivers/soc/aspeed/aspeed-udma.c | 23 +- drivers/soc/aspeed/aspeed-usb-hp.c | 6 +- drivers/soc/aspeed/aspeed-usb-phy.c | 1 - drivers/soc/aspeed/aspeed-xdma.c | 488 +++++- drivers/soc/aspeed/ast2700-espi.c | 142 +- drivers/soc/aspeed/ast2700-espi.h | 8 +- drivers/spi/Kconfig | 16 +- drivers/spi/Makefile | 2 +- drivers/spi/spi-aspeed-txrx.c | 44 +- drivers/tty/serial/8250/8250_aspeed.c | 195 +-- drivers/usb/gadget/udc/aspeed-vhub/core.c | 57 + drivers/usb/gadget/udc/aspeed-vhub/vhub.h | 10 + .../dt-bindings/clock/aspeed,ast2700-scu.h | 101 +- include/dt-bindings/clock/ast2600-clock.h | 18 +- include/dt-bindings/gpio/aspeed-gpio.h | 2 - .../dt-bindings/reset/aspeed,ast2700-scu.h | 1 + include/linux/clk-provider.h | 18 + include/linux/soc/aspeed/aspeed-udma.h | 8 +- 55 files changed, 7236 insertions(+), 2569 deletions(-) create mode 100644 arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi create mode 100644 drivers/edac/edac_ast2700.c create mode 100644 drivers/i3c/master/amd-i3c-master.c create mode 100644 drivers/pci/controller/pcie-aspeed.c create mode 100644 drivers/soc/aspeed/aspeed-host-bmc-dev.c create mode 100644 drivers/soc/aspeed/aspeed-lpc-mbox.c diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-congo.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-congo.dts index 122479c9859cf8..461ff9a4aea55d 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-congo.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-congo.dts @@ -10,6 +10,8 @@ #include //#define VERONA 1 +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD Congo VRB"; @@ -37,35 +39,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; @@ -73,29 +47,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -161,7 +112,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -173,6 +124,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -1026,7 +978,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-eagle.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-eagle.dts index 3a89c7f078c63b..03f641e5c9fe2c 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-eagle.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-eagle.dts @@ -9,6 +9,9 @@ #include #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC + / { model = "AMD Eagle VRB"; compatible = "amd,eagle-bmc", "aspeed,ast2700"; @@ -35,35 +38,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; @@ -71,29 +46,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -159,7 +111,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -171,6 +123,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -1002,7 +955,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-falcon.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-falcon.dts index fc831ade635b3f..b4f509c67402ae 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-falcon.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-falcon.dts @@ -9,6 +9,9 @@ #include #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC + / { model = "AMD Falcon PRB"; compatible = "amd,falcon-bmc", "aspeed,ast2700"; @@ -35,35 +38,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; @@ -71,29 +46,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -130,7 +82,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -142,6 +94,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -565,7 +518,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-ghana.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-ghana.dts index c9effe9c6a1b25..4b6425e73b5db0 100755 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-ghana.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-ghana.dts @@ -10,6 +10,9 @@ #include #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC + / { model = "AMD Ghana PRB"; compatible = "amd,ghana-bmc", "aspeed,ast2700"; @@ -36,35 +39,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; /* 64M */ @@ -79,35 +54,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; - - mctp1_reserved: mctp1_reserved@431090000 { - reg = <0x4 0x31090000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -147,7 +93,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -159,6 +105,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -758,7 +705,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-hornbill.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-hornbill.dts index 74d95935cd86eb..f1687d5b68f9fe 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-hornbill.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-hornbill.dts @@ -9,6 +9,8 @@ #include #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD Hornbill VRB"; @@ -36,35 +38,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; @@ -79,35 +53,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; - - mctp1_reserved: mctp1_reserved@431090000 { - reg = <0x4 0x31090000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { i2c100 = &NC_1; @@ -182,7 +127,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -194,6 +139,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -1020,7 +966,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; @@ -1033,7 +978,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-kenya.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-kenya.dts index 9854fe741976de..08a5fe2bf4c396 100755 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-kenya.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-kenya.dts @@ -11,6 +11,8 @@ #include //#define VERONA 1 +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD Kenya PRB"; @@ -38,65 +40,14 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { - size = <0x0 0x04000000>; /* 64M */ + size = <0x0 0x02000000>; alignment = <0x0 0x00010000>; compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -155,7 +106,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -167,6 +118,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-marley.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-marley.dts index 781fca88fe7028..2f86fd84c15f77 100755 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-marley.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-marley.dts @@ -8,6 +8,9 @@ #include "dt-bindings/gpio/aspeed-gpio.h" #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC + / { model = "AMD Marley BMC"; compatible = "amd,marley-bmc", "aspeed,ast2700"; @@ -34,20 +37,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee_core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory: jpegbuffer { size = <0x02000000>; /* 32M */ @@ -55,11 +45,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0xE0000000 0x00001000>; /* 4K */ - no-map; - }; }; }; @@ -84,7 +69,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -448,7 +433,6 @@ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-morocco.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-morocco.dts index c1814ff77b9e71..5f535d878b606f 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-morocco.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-morocco.dts @@ -10,6 +10,8 @@ #include //#define VERONA 1 +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD Morocco VRB"; @@ -37,77 +39,20 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; - - video_engine_memory0: video0 { - size = <0x0 0x04000000>; - alignment = <0x0 0x00010000>; - compatible = "shared-dma-pool"; - reusable; - }; - - video_engine_memory1: video1{ - size = <0x0 0x04000000>; - alignment = <0x0 0x00010000>; - compatible = "shared-dma-pool"; - reusable; - }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; + video_engine_memory0: video0 { + size = <0x0 0x02000000>; + alignment = <0x0 0x00010000>; + compatible = "shared-dma-pool"; + reusable; }; - mctp1_reserved: mctp1_reserved@431090000 { - reg = <0x4 0x31090000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; + video_engine_memory1: video1{ + size = <0x0 0x02000000>; + alignment = <0x0 0x00010000>; + compatible = "shared-dma-pool"; + reusable; }; }; aliases { @@ -182,7 +127,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -194,6 +139,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -1186,7 +1132,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; @@ -1199,7 +1144,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigeria.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigeria.dts index 7d5599729f3f00..ce10dc3a0950ca 100755 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigeria.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigeria.dts @@ -11,6 +11,9 @@ #include //#define VERONA 1 +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC + / { model = "AMD Nigeria PRB"; compatible = "amd,nigeria-bmc", "aspeed,ast2700"; @@ -37,35 +40,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; /* 64M */ @@ -80,35 +55,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; - - mctp1_reserved: mctp1_reserved@431090000 { - reg = <0x4 0x31090000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { @@ -174,7 +120,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -186,6 +132,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -976,7 +923,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigerias3.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigerias3.dts index 55b16d6679bf0e..ed68433585cdc8 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigerias3.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-nigerias3.dts @@ -10,6 +10,8 @@ #include #include +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD NigeriaS3 PRB"; compatible = "amd,nigerias3-bmc", "aspeed,ast2700"; @@ -36,35 +38,8 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; /* 64M */ @@ -72,23 +47,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; }; aliases { @@ -118,7 +76,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -130,6 +88,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { diff --git a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-seagull.dts b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-seagull.dts index 945e186cf41f1b..92e7ddcac9e34c 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-seagull.dts +++ b/arch/arm64/boot/dts/aspeed/aspeed-bmc-amd-seagull.dts @@ -9,7 +9,8 @@ #include #include - +#define PCIE0_EP 1 // 1: EP, 0: RC +#define PCIE1_EP 1 // 1: EP, 0: RC / { model = "AMD Seagull PRB"; compatible = "amd,seagull-bmc", "aspeed,ast2700"; @@ -36,35 +37,7 @@ #size-cells = <2>; ranges; - mcu_fw: mcu-firmware@42fe00000 { - reg = <0x4 0x2fe00000 0x0 0x200000>; - no-map; - }; - - atf: trusted-firmware-a@430000000 { - reg = <0x4 0x30000000 0x0 0x80000>; - no-map; - }; - - optee_core: optee-core@430080000 { - reg = <0x4 0x30080000 0x0 0x1000000>; - no-map; - }; - - bmc_dev0_memory: bmc_dev0_memory@423800000 { - reg = <0x4 0x23800000 0x0 0x100000>; - no-map; - }; - - vbios_base0: vbios-base0@431bb0000 { - reg = <0x4 0x31bb0000 0x0 0x10000>; - no-map; - }; - - vbios_base1: vbios-base1@431bc0000 { - reg = <0x4 0x31bc0000 0x0 0x10000>; - no-map; - }; + #include "ast2700-reserved-mem.dtsi" video_engine_memory0: video0 { size = <0x0 0x04000000>; @@ -79,35 +52,6 @@ compatible = "shared-dma-pool"; reusable; }; - - pcc_memory: pccbuffer { - reg = <0x4 0xE0000000 0x00001000>; /* 4K */ - no-map; - }; - - xdma_memory0: xdma0 { - size = <0x0 0x01000000>; - alignment = <0x0 0x01000000>; - compatible = "shared-dma-pool"; - no-map; - }; - - espi0_mmbi_memory: espi0-mmbi-memory@424000000 { - reg = <0x4 0x24000000 0x0 0x4000000>; - no-map; - }; - - mctp0_reserved: mctp0_reserved@431080000 { - reg = <0x4 0x31080000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; - - mctp1_reserved: mctp1_reserved@431090000 { - reg = <0x4 0x31090000 0x0 0x10000>; - compatible = "shared-dma-pool"; - no-map; - }; }; aliases { i2c116 = &P0_id; @@ -151,7 +95,7 @@ &mac0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <ðphy0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; @@ -163,6 +107,7 @@ pinctrl-0 = <&pinctrl_rmii1_default>; clock-names = "MACCLK", "RCLK"; use-ncsi; + phy-mode = "rmii"; }; &fmc { @@ -746,7 +691,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; @@ -759,7 +703,6 @@ spd_ ## bus ## _ ## index: spd@addr,4cc5118 ## index ## 000 { \ port-addr = <0x80>; dma-mode; A2600-15; - memory-region = <&pcc_memory>; rec-mode = <0x1>; port-addr-hbits-select = <0x1>; port-addr-xbits = <0x3>; diff --git a/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi b/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi index d217f1529ab5c4..ed2f0c71a6c20c 100644 --- a/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi +++ b/arch/arm64/boot/dts/aspeed/aspeed-g7.dtsi @@ -80,111 +80,135 @@ rvas1 = &rvas1; xdma0 = &xdma0; xdma1 = &xdma1; + xdma2 = &xdma2; + bmcdev0 = &bmc_dev0; + bmcdev1 = &bmc_dev1; + edac = &edac; }; cpus { - #address-cells = <1>; + #address-cells = <2>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { + device_type = "cpu"; compatible = "arm,cortex-a35"; + reg = <0x0 0x0>; enable-method = "psci"; - device_type = "cpu"; - reg = <0>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; next-level-cache = <&l2>; }; - cpu@1 { + cpu1: cpu@1 { + device_type = "cpu"; compatible = "arm,cortex-a35"; + reg = <0x0 0x1>; enable-method = "psci"; - device_type = "cpu"; - reg = <1>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; next-level-cache = <&l2>; }; - cpu@2 { + cpu2: cpu@2 { + device_type = "cpu"; compatible = "arm,cortex-a35"; + reg = <0x0 0x2>; enable-method = "psci"; - device_type = "cpu"; - reg = <2>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; next-level-cache = <&l2>; }; - cpu@3 { + cpu3: cpu@3 { + device_type = "cpu"; compatible = "arm,cortex-a35"; + reg = <0x0 0x3>; enable-method = "psci"; - device_type = "cpu"; - reg = <3>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - d-cache-sets = <128>; i-cache-size = <0x8000>; i-cache-line-size = <64>; i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; next-level-cache = <&l2>; }; l2: l2-cache0 { compatible = "cache"; + cache-level = <2>; + cache-unified; cache-size = <0x80000>; cache-line-size = <64>; cache-sets = <1024>; - cache-level = <2>; }; }; - pmu { - compatible = "arm,cortex-a35-pmu"; - interrupt-parent = <&gic>; - interrupts = ; + firmware { + optee: optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; }; - psci { - compatible = "arm,psci-1.0"; - method = "smc"; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + atf: trusted-firmware-a@430000000 { + reg = <0x4 0x30000000 0x0 0x80000>; + no-map; + }; + + optee_core: optee-core@430080000 { + reg = <0x4 0x30080000 0x0 0x1000000>; + no-map; + }; }; - gic: interrupt-controller@12200000 { - compatible = "arm,gic-v3"; - interrupts = ; - #interrupt-cells = <3>; - interrupt-controller; - interrupt-parent = <&gic>; - #redistributor-regions = <1>; - reg = <0 0x12200000 0 0x10000>, //GICD - <0 0x12280000 0 0x80000>, //GICR - <0 0x40440000 0 0x1000>; //GICC + arm-pmu { + compatible = "arm,cortex-a35-pmu"; + interrupts = ; }; timer { compatible = "arm,armv8-timer"; - interrupt-parent = <&gic>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; arm,cpu-registers-not-fw-configured; always-on; }; + gic: interrupt-controller@12200000 { + compatible = "arm,gic-v3"; + reg = <0 0x12200000 0 0x10000>, /* GICD */ + <0 0x12280000 0 0x80000>, /* GICR */ + <0 0x40440000 0 0x1000>; /* GICC */ + interrupts = ; + #interrupt-cells = <3>; + interrupt-controller; + }; + soc0: soc@10000000 { compatible = "simple-bus"; #address-cells = <2>; @@ -225,7 +249,7 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2axhpd1_default>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -258,7 +282,7 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2bxhpd1_default>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -294,7 +318,7 @@ resets = <&syscon0 SCU0_RESET_PORTA_XHCI>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb3axhp_default>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; phys = <&uphy3a>; phy-names = "usb3-phy"; status = "disabled"; @@ -333,7 +357,7 @@ resets = <&syscon0 SCU0_RESET_PORTB_XHCI>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb3bxhp_default>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; phys = <&uphy3b>; phy-names = "usb3-phy"; status = "disabled"; @@ -349,7 +373,7 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2ad0_default>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -372,7 +396,7 @@ resets = <&syscon0 SCU0_RESET_PORTA_VHUB_EHCI>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2ahp_default>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; status = "disabled"; }; @@ -386,7 +410,7 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2bd0_default>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -409,7 +433,16 @@ resets = <&syscon0 SCU0_RESET_PORTB_VHUB_EHCI>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2bhp_default>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; + status = "disabled"; + }; + + hace: crypto@12070000 { + compatible = "aspeed,ast2700-hace"; + reg = <0x0 0x12070000 0x0 0x200>; + interrupts = ; + clocks = <&syscon0 SCU0_CLK_GATE_HACCLK>; + resets = <&syscon0 SCU0_RESET_HACE>; status = "disabled"; }; @@ -447,59 +480,183 @@ }; }; - ufs_controller: cnr@12c08000 { - compatible = "aspeed,ast2700-ufscnr"; - reg = <0 0x12c08000 0 0x100>; - #address-cells = <2>; + video0: video@120a0000 { + compatible = "aspeed,ast2700-video-engine", "syscon"; + reg = <0x0 0x120a0000 0x0 0x400>, <0x0 0x14c3a800 0x0 0x400>; + clocks = <&syscon0 SCU0_CLK_GATE_VCLK>, + <&syscon0 SCU0_CLK_GATE_ECLK>, + <&syscon0 SCU0_CLK_GATE_CRT1CLK>; + clock-names = "vclk", "eclk", "crt2clk"; + interrupts-extended = <&gic GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, <&intc1_5 22>; + resets = <&syscon0 SCU0_RESET_VIDEO>; + aspeed,scu = <&syscon0>; + status = "disabled"; + }; + + video1: video@120a1000 { + compatible = "aspeed,ast2700-video-engine"; + reg = <0x0 0x120a1000 0x0 0x400>; + clocks = <&syscon0 SCU0_CLK_GATE_VCLK>, + <&syscon0 SCU0_CLK_GATE_ECLK>, + <&syscon0 SCU0_CLK_GATE_CRT1CLK>; + clock-names = "vclk", "eclk", "crt2clk"; + interrupts = ; + resets = <&syscon0 SCU0_RESET_VIDEO>; + aspeed,scu = <&syscon0>; + status = "disabled"; + }; + + rvas0: rvas@120b8000 { + compatible = "aspeed,ast2700-rvas"; + reg = <0x0 0x120b8000 0x0 0x800>, + <0x0 0x12c14000 0x0 0x800>, + <0x0 0x120a0000 0x0 0x1000>; + clocks = <&syscon0 SCU0_CLK_GATE_RVAS0CLK>, + <&syscon0 SCU0_CLK_GATE_VCLK>, + <&syscon0 SCU0_CLK_GATE_ECLK>; + clock-names = "rvasclk", "vclk", "eclk"; + interrupts = , , ; + resets = <&syscon0 SCU0_RESET_RVAS0>, <&syscon0 SCU0_RESET_VIDEO>; + status = "disabled"; + }; + + rvas1: rvas@120bc000 { + compatible = "aspeed,ast2700-rvas"; + reg = <0x0 0x120bc000 0x0 0x800>, + <0x0 0x12c14800 0x0 0x800>, + <0x0 0x120a1000 0x0 0x1000>; + clocks = <&syscon0 SCU0_CLK_GATE_RVAS1CLK>, + <&syscon0 SCU0_CLK_GATE_VCLK>, + <&syscon0 SCU0_CLK_GATE_ECLK>; + clock-names = "rvas2clk", "vclk", "eclk"; + interrupts = , , ; + resets = <&syscon0 SCU0_RESET_RVAS1>, <&syscon0 SCU0_RESET_VIDEO>; + status = "disabled"; + }; + + pcie0: pcie@120e0000 { + compatible = "aspeed,ast2700-pcie"; + device_type = "pci"; + reg = <0x0 0x120e0000 0x0 0x100>; + linux,pci-domain = <0>; + #address-cells = <3>; #size-cells = <2>; - ranges = <0 0 0 0x12c08000 0 0x300>; - clocks = <&syscon0 SCU0_CLK_GATE_UFSCLK>; - resets = <&syscon0 SCU0_RESET_UFS>; + bus-range = <0x00 0xff>; + ranges = <0x02000000 0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>; + interrupts = ; + resets = <&syscon0 SCU0_RESET_H2X0>, + <&syscon0 SCU0_RESET_PCIE0RST>; + reset-names = "h2x", "perst"; status = "disabled"; - ufs: ufshc@12c08200 { - compatible = "aspeed,ast2700-ufshc"; - reg = <0 0x200 0 0x100>; - interrupts = ; - clocks = <&syscon0 SCU0_CLK_AXI1>; - clock-names = "core_clk"; - freq-table-hz = <0 0>; - status = "disabled"; + clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; + pinctrl-0 = <&pinctrl_pcierc0_perst_default>; + pinctrl-names = "default"; + + #interrupt-cells = <1>; + msi-controller; + + aspeed,pciephy = <&pcie_phy0>; + aspeed,pciecfg = <&pcie_cfg0>; + + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc0 0>, + <0 0 0 2 &pcie_intc0 1>, + <0 0 0 3 &pcie_intc0 2>, + <0 0 0 4 &pcie_intc0 3>; + pcie_intc0: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; }; }; - intc0: interrupt-controller@12100000 { - compatible = "simple-mfd"; - reg = <0 0x12100000 0 0x4000>; - #address-cells = <2>; + pcie1: pcie@120f0000 { + compatible = "aspeed,ast2700-pcie"; + device_type = "pci"; + reg = <0x0 0x120f0000 0x0 0x100>; + linux,pci-domain = <1>; + #address-cells = <3>; #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x12100000 0x0 0x4000>; + bus-range = <0x00 0xff>; + ranges = <0x02000000 0 0x80000000 0x0 0x80000000 0x0 0x20000000>; + interrupts = ; + resets = <&syscon0 SCU0_RESET_H2X1>, + <&syscon0 SCU0_RESET_PCIE1RST>; + reset-names = "h2x", "perst"; + status = "disabled"; - intc0_11: interrupt-controller@1b00 { - #interrupt-cells = <1>; + clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; + pinctrl-0 = <&pinctrl_pcierc1_perst_default>; + pinctrl-names = "default"; + + #interrupt-cells = <1>; + msi-controller; + + aspeed,pciephy = <&pcie_phy1>; + aspeed,pciecfg = <&pcie_cfg1>; + + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc1 0>, + <0 0 0 2 &pcie_intc1 1>, + <0 0 0 3 &pcie_intc1 2>, + <0 0 0 4 &pcie_intc1 3>; + pcie_intc1: interrupt-controller { interrupt-controller; - compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x1b00 0x0 0x10>; - interrupts = , - , - , - , - , - , - , - , - , - ; + #address-cells = <0>; + #interrupt-cells = <1>; }; }; + xdma0: xdma@12c04000 { + compatible = "aspeed,ast2700-xdma0"; + reg = <0x0 0x12c04000 0x0 0x100>; + clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; + resets = <&syscon0 SCU0_RESET_XDMA0>; + reset-names = "device"; + interrupts-extended = <&gic GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, + <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>; + aspeed,pcie-device = "bmc"; + aspeed,scu = <&syscon0>; + status = "disabled"; + }; + + xdma1: xdma@12c05000 { + compatible = "aspeed,ast2700-xdma1"; + reg = <0x0 0x12c05000 0x0 0x100>; + clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; + resets = <&syscon0 SCU0_RESET_XDMA1>; + reset-names = "device"; + interrupts-extended = <&gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, + <&scu_ic1 ASPEED_AST2700_SCU_IC1_PCIE_RCRST_LO_TO_HI>; + aspeed,pcie-device = "bmc"; + aspeed,scu = <&syscon0>; + status = "disabled"; + }; + + intc0_11: interrupt-controller@12101b00 { + compatible = "aspeed,ast2700-intc-ic"; + reg = <0x0 0x12101b00 0x0 0x10>; + #interrupt-cells = <1>; + interrupt-controller; + interrupts = , + , + , + , + , + , + , + , + , + ; + }; + bmc_dev0: bmc-dev@12110000 { compatible = "aspeed,ast2700-bmc-device"; reg = <0x0 0x12110000 0x0 0xb000>; interrupts-extended = <&gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>; - aspeed,config = <&pcie_config0>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; aspeed,e2m = <&e2m_config0>; aspeed,scu = <&syscon0>; pcie2lpc; @@ -511,67 +668,62 @@ reg = <0x0 0x12120000 0x0 0xb000>; interrupts-extended = <&gic GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, <&scu_ic1 ASPEED_AST2700_SCU_IC1_PCIE_RCRST_LO_TO_HI>; - aspeed,config = <&pcie_config1>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; aspeed,e2m = <&e2m_config1>; aspeed,scu = <&syscon0>; pcie2lpc; status = "disabled"; }; + edac: sdram@12c00000 { + compatible = "aspeed,ast2700-sdram-edac", "syscon"; + reg = <0 0x12c00000 0 0x1000>; + interrupts = ; + }; + syscon0: syscon@12c02000 { compatible = "aspeed,ast2700-scu0", "syscon", "simple-mfd"; reg = <0x0 0x12c02000 0x0 0x1000>; - ranges = <0x0 0x0 0 0x12c02000 0 0x1000>; - #address-cells = <2>; - #size-cells = <2>; + ranges = <0x0 0x0 0x12c02000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; silicon-id@0 { compatible = "aspeed,ast2700-silicon-id", "aspeed,silicon-id"; - reg = <0 0x0 0 0x4>; + reg = <0x0 0x4>; }; scu_ic0: interrupt-controller@1D0 { - #interrupt-cells = <1>; compatible = "aspeed,ast2700-scu-ic0"; - reg = <0 0x1d0 0 0xc>; + reg = <0x1d0 0xc>; interrupts = ; + #interrupt-cells = <1>; interrupt-controller; }; scu_ic1: interrupt-controller@1E0 { - #interrupt-cells = <1>; compatible = "aspeed,ast2700-scu-ic1"; - reg = <0 0x1e0 0 0xc>; + reg = <0x1e0 0xc>; interrupts = ; + #interrupt-cells = <1>; interrupt-controller; }; pinctrl0: pinctrl@400 { compatible = "aspeed,ast2700-soc0-pinctrl"; - reg = <0 0x400 0 0x600>; + reg = <0x400 0x600>; }; }; - pcie_config0: pcie-config@12c02960 { - compatible = "syscon", "simple-mfd"; - reg = <0 0x12c02960 0 0x40>; - }; - - pcie_config1: pcie-config@12c029a0 { - compatible = "syscon", "simple-mfd"; - reg = <0 0x12c029a0 0 0x40>; - }; - - pcie_device0: pcie-device@12c02a00 { - compatible = "syscon", "simple-mfd"; + pcie_cfg0: syscon@12c02a00 { + compatible = "syscon"; reg = <0 0x12c02a00 0 0x80>; }; - pcie_device1: pcie-device@12c02a80 { - compatible = "syscon", "simple-mfd"; + pcie_cfg1: syscon@12c02a80 { + compatible = "syscon"; reg = <0 0x12c02a80 0 0x80>; }; @@ -597,6 +749,27 @@ status = "disabled"; }; + ufs_controller: cnr@12c08000 { + compatible = "aspeed,ast2700-ufscnr"; + reg = <0 0x12c08000 0 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0 0 0 0x12c08000 0 0x300>; + clocks = <&syscon0 SCU0_CLK_GATE_UFSCLK>; + resets = <&syscon0 SCU0_RESET_UFS>; + status = "disabled"; + + ufs: ufshc@12c08200 { + compatible = "aspeed,ast2700-ufshc"; + reg = <0 0x200 0 0x100>; + interrupts = ; + clocks = <&syscon0 SCU0_CLK_AXI1>; + clock-names = "core_clk"; + freq-table-hz = <0 0>; + status = "disabled"; + }; + }; + display_port: dp@12c0a000 { compatible = "aspeed,ast2700-displayport", "syscon"; reg = <0x0 0x12c0a000 0x0 0x200>; @@ -617,7 +790,9 @@ resets = <&syscon0 SCU0_RESET_CRT0>; syscon = <&syscon0>; status = "disabled"; - interrupts = ; + interrupts-extended = <&gic GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>, + <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>, + <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_HI_TO_LO>; }; disp_intf: disp-intf { @@ -634,7 +809,7 @@ status = "disabled"; }; - gpio1: gpio@12c11000 { + gpio0: gpio@12c11000 { #gpio-cells = <2>; gpio-controller; compatible = "aspeed,ast2700-gpio"; @@ -647,19 +822,21 @@ #interrupt-cells = <2>; }; - pcie_phy0: pcie-phy@12c15000 { + pcie_phy0: phy@12c15000 { compatible = "aspeed,ast2700-pcie-phy", "syscon"; reg = <0x0 0x12c15000 0x0 0x800>; }; - pcie_phy1: rc-bridge@12c15800 { + pcie_phy1: phy@12c15800 { compatible = "aspeed,ast2700-pcie-phy", "syscon"; reg = <0x0 0x12c15800 0x0 0x800>; }; pcie_vuart0: serial@12c18000 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x12c18000 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts = ; clocks = <&syscon0 SCU0_CLK_APB>; virtual; @@ -667,8 +844,10 @@ }; pcie_vuart1: serial@12c18100 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x12c18100 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts = ; clocks = <&syscon0 SCU0_CLK_APB>; virtual; @@ -676,8 +855,10 @@ }; pcie_vuart2: serial@12c18200 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x12c18200 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts = ; clocks = <&syscon0 SCU0_CLK_APB>; virtual; @@ -685,8 +866,10 @@ }; pcie_vuart3: serial@12c18300 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x12c18300 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts = ; clocks = <&syscon0 SCU0_CLK_APB>; virtual; @@ -811,78 +994,6 @@ }; - pcie0: pcie@120e0000 { - compatible = "aspeed,ast2700-pcie"; - device_type = "pci"; - reg = <0x0 0x120e0000 0x0 0x100>; - linux,pci-domain = <0>; - #address-cells = <3>; - #size-cells = <2>; - bus-range = <0x00 0xff>; - ranges = <0x01000000 0 0x00000000 0x0 0x00000000 0x0 0x00008000>, /* I/O */ - <0x02000000 0 0x60000000 0x0 0x60000000 0x0 0x10000000>; /* memory */ - interrupts = ; - resets = <&syscon0 SCU0_RESET_H2X0>, - <&syscon0 SCU0_RESET_PCIE0RST>; - reset-names = "h2x", "perst"; - status = "disabled"; - - pinctrl-0 = <&pinctrl_pcierc0_perst_default>; - pinctrl-names = "default"; - - #interrupt-cells = <1>; - msi-parent = <&pcie0>; - msi_address = <0x000000F0>; - pciephy = <&pcie_phy0>; - aspeed,device = <&pcie_device0>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc0 0>, - <0 0 0 2 &pcie_intc0 1>, - <0 0 0 3 &pcie_intc0 2>, - <0 0 0 4 &pcie_intc0 3>; - pcie_intc0: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; - - pcie1: pcie@120f0000 { - compatible = "aspeed,ast2700-pcie"; - device_type = "pci"; - reg = <0x0 0x120f0000 0x0 0x100>; - linux,pci-domain = <1>; - #address-cells = <3>; - #size-cells = <2>; - bus-range = <0x00 0xff>; - ranges = <0x01000000 0 0x00000000 0x0 0x00000000 0x0 0x00008000>, - <0x02000000 0 0x80000000 0x0 0x80000000 0x0 0x10000000>; /* memory */ - interrupts = ; - resets = <&syscon0 SCU0_RESET_H2X1>, - <&syscon0 SCU0_RESET_PCIE1RST>; - reset-names = "h2x", "perst"; - status = "disabled"; - - pinctrl-0 = <&pinctrl_pcierc1_perst_default>; - pinctrl-names = "default"; - - #interrupt-cells = <1>; - msi-parent = <&pcie1>; - msi_address = <0x000000F0>; - pciephy = <&pcie_phy1>; - aspeed,device = <&pcie_device1>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc1 0>, - <0 0 0 2 &pcie_intc1 1>, - <0 0 0 3 &pcie_intc1 2>, - <0 0 0 4 &pcie_intc1 3>; - pcie_intc1: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; - }; - uart4: serial@12c1a000 { compatible = "aspeed,ast2700-uart"; reg = <0x0 0x12c1a000 0x0 0x1000>; @@ -894,12 +1005,30 @@ status = "disabled"; }; + mbox0: mbox@12c1c200 { + compatible = "aspeed,ast2700-mailbox"; + reg = <0x0 0x12c1c200 0x0 0x100>, <0x0 0x12c1c300 0x0 0x100>; + reg-names = "tx", "rx"; + interrupts = ; + #mbox-cells = <1>; + mbox-name = "ssp"; + }; + + mbox1: mbox@12c1c600 { + compatible = "aspeed,ast2700-mailbox"; + reg = <0x0 0x12c1c600 0x0 0x100>, <0x0 0x12c1c700 0x0 0x100>; + reg-names = "tx", "rx"; + interrupts = ; + #mbox-cells = <1>; + mbox-name = "tsp"; + }; + ecdsa: crypto@12c1e000 { compatible = "aspeed,ast2700-ecdsa"; reg = <0x0 0x12c1e000 0x0 0x1000>; interrupts = ; clocks = <&syscon0 SCU0_CLK_GATE_ECDSACLK>; - resets = <&syscon0 SCU0_RESET_HACE>; + resets = <&syscon0 SCU0_RESET_ECC>; status = "disabled"; }; @@ -907,8 +1036,10 @@ compatible = "aspeed,ast2700-jtag"; reg= <0x0 0x12c20000 0x0 0x40>; interrupts = ; - clocks = <&syscon0 SCU0_CLK_APB>; + clocks = <&syscon0 SCU0_CLK_AHB>; resets = <&syscon0 SCU0_RESET_JTAG>; + pinctrl-0 = <&pinctrl_jtagm0_default>; + pinctrl-names = "default"; status = "disabled"; }; @@ -918,7 +1049,7 @@ ranges = <0 0 0 0x12c21000 0 0x300>; #address-cells = <2>; #size-cells = <2>; - aspeed,device = <&pcie_device0>; + aspeed,device = <&pcie_cfg0>; e2m_ic0: interrupt-controller@14 { #interrupt-cells = <1>; @@ -935,6 +1066,7 @@ index = <0>; pid = <3>; bar = <0x3c>; + msi = <28>; status = "disabled"; }; @@ -944,6 +1076,7 @@ index = <1>; pid = <4>; bar = <0x4c>; + msi = <29>; status = "disabled"; }; @@ -953,6 +1086,7 @@ index = <2>; pid = <5>; bar = <0x5c>; + msi = <30>; status = "disabled"; }; @@ -962,6 +1096,7 @@ index = <3>; pid = <6>; bar = <0x6c>; + msi = <31>; status = "disabled"; }; }; @@ -972,7 +1107,7 @@ ranges = <0x0 0x0 0 0x12c22000 0 0x300>; #address-cells = <2>; #size-cells = <2>; - aspeed,device = <&pcie_device1>; + aspeed,device = <&pcie_cfg1>; e2m_ic1: interrupt-controller@14 { #interrupt-cells = <1>; @@ -988,6 +1123,7 @@ index = <4>; pid = <11>; bar = <0x3c>; + msi = <28>; status = "disabled"; }; @@ -997,6 +1133,7 @@ index = <5>; pid = <12>; bar = <0x4c>; + msi = <29>; status = "disabled"; }; @@ -1006,6 +1143,7 @@ index = <6>; pid = <13>; bar = <0x5c>; + msi = <30>; status = "disabled"; }; @@ -1015,98 +1153,10 @@ index = <7>; pid = <14>; bar = <0x6c>; + msi = <31>; status = "disabled"; }; }; - - hace: crypto@12070000 { - compatible = "aspeed,ast2700-hace"; - reg = <0x0 0x12070000 0x0 0x200>; - interrupts = ; - clocks = <&syscon0 SCU0_CLK_GATE_HACCLK>; - resets = <&syscon0 SCU0_RESET_HACE>; - status = "disabled"; - }; - - video0: video@120a0000 { - compatible = "aspeed,ast2700-video-engine", "syscon"; - reg = <0x0 0x120a0000 0x0 0x400>; - clocks = <&syscon0 SCU0_CLK_GATE_VCLK>, - <&syscon0 SCU0_CLK_GATE_ECLK>, - <&syscon0 SCU0_CLK_GATE_CRT1CLK>; - clock-names = "vclk", "eclk", "crt2clk"; - interrupts = ; - resets = <&syscon0 SCU0_RESET_VIDEO>; - aspeed,scu = <&syscon0>; - status = "disabled"; - }; - - video1: video@120a1000 { - compatible = "aspeed,ast2700-video-engine"; - reg = <0x0 0x120a1000 0x0 0x400>; - clocks = <&syscon0 SCU0_CLK_GATE_VCLK>, - <&syscon0 SCU0_CLK_GATE_ECLK>, - <&syscon0 SCU0_CLK_GATE_CRT1CLK>; - clock-names = "vclk", "eclk", "crt2clk"; - interrupts = ; - resets = <&syscon0 SCU0_RESET_VIDEO>; - aspeed,scu = <&syscon0>; - status = "disabled"; - }; - - rvas0: rvas@120b8000 { - compatible = "aspeed,ast2700-rvas"; - reg = <0x0 0x120b8000 0x0 0x800>, - <0x0 0x12c14000 0x0 0x800>, - <0x0 0x120a0000 0x0 0x1000>; - clocks = <&syscon0 SCU0_CLK_GATE_RVAS0CLK>, - <&syscon0 SCU0_CLK_GATE_VCLK>, - <&syscon0 SCU0_CLK_GATE_ECLK>; - clock-names = "rvasclk", "vclk", "eclk"; - interrupts = , , ; - resets = <&syscon0 SCU0_RESET_RVAS0>, <&syscon0 SCU0_RESET_VIDEO>; - status = "disabled"; - }; - - rvas1: rvas@120bc000 { - compatible = "aspeed,ast2700-rvas"; - reg = <0x0 0x120bc000 0x0 0x800>, - <0x0 0x12c14800 0x0 0x800>, - <0x0 0x120a1000 0x0 0x1000>; - clocks = <&syscon0 SCU0_CLK_GATE_RVAS1CLK>, - <&syscon0 SCU0_CLK_GATE_VCLK>, - <&syscon0 SCU0_CLK_GATE_ECLK>; - clock-names = "rvas2clk", "vclk", "eclk"; - interrupts = , , ; - resets = <&syscon0 SCU0_RESET_RVAS1>, <&syscon0 SCU0_RESET_VIDEO>; - status = "disabled"; - }; - - xdma0: xdma@12c04000 { - compatible = "aspeed,ast2700-xdma0"; - reg = <0x0 0x12c04000 0x0 0x100>; - clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; - resets = <&syscon0 SCU0_RESET_XDMA0>; - reset-names = "device"; - interrupts-extended = <&gic GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, - <&scu_ic0 ASPEED_AST2700_SCU_IC0_PCIE_PERST_LO_TO_HI>; - aspeed,pcie-device = "bmc"; - aspeed,scu = <&syscon0>; - status = "disabled"; - }; - - xdma1: xdma@12c05000 { - compatible = "aspeed,ast2700-xdma1"; - reg = <0x0 0x12c05000 0x0 0x100>; - clocks = <&syscon0 SCU0_CLK_GATE_BCLK>; - resets = <&syscon0 SCU0_RESET_XDMA1>; - reset-names = "device"; - interrupts-extended = <&gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, - <&scu_ic1 ASPEED_AST2700_SCU_IC1_PCIE_RCRST_LO_TO_HI>; - aspeed,pcie-device = "bmc"; - aspeed,scu = <&syscon0>; - status = "disabled"; - }; }; soc1: soc@14000000 { @@ -1122,6 +1172,7 @@ compatible = "aspeed,ast2700-fmc"; status = "disabled"; clocks = <&syscon1 SCU1_CLK_AHB>; + interrupts-extended = <&intc1_3 25>; num-cs = <3>; flash@0 { @@ -1155,6 +1206,7 @@ #size-cells = <0>; compatible = "aspeed,ast2700-spi"; clocks = <&syscon1 SCU1_CLK_AHB>; + interrupts-extended = <&intc1_3 26>; status = "disabled"; num-cs = <2>; @@ -1181,6 +1233,7 @@ #size-cells = <0>; compatible = "aspeed,ast2700-spi"; clocks = <&syscon1 SCU1_CLK_AHB>; + interrupts-extended = <&intc1_3 27>; status = "disabled"; num-cs = <2>; @@ -1207,6 +1260,7 @@ #size-cells = <0>; clocks = <&syscon1 SCU1_CLK_AHB>; resets = <&syscon1 SCU1_RESET_SPI2>; + interrupts-extended = <&intc1_3 28>; num-cs = <2>; status = "disabled"; }; @@ -1222,58 +1276,34 @@ pinctrl-names = "default"; }; - mdio: bus@14040000 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0 0 0 0x14040000 0 0x100>; - - mdio0: mdio@0 { - compatible = "aspeed,ast2600-mdio"; - reg = <0 0 0 0x8>; - resets = <&syscon1 SCU1_RESET_MII>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mdio0_default>; - status = "disabled"; - }; - - mdio1: mdio@8 { - compatible = "aspeed,ast2600-mdio"; - reg = <0 0x8 0 0x8>; - resets = <&syscon1 SCU1_RESET_MII>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mdio1_default>; - status = "disabled"; - }; - - mdio2: mdio@10 { - compatible = "aspeed,ast2600-mdio"; - reg = <0 0x10 0 0x8>; - resets = <&syscon1 SCU1_RESET_MII>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mdio2_default>; - status = "disabled"; - }; + mdio0: mdio@14040000 { + compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio"; + reg = <0 0x14040000 0 0x8>; + resets = <&syscon1 SCU1_RESET_MII>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio0_default>; + status = "disabled"; }; - plda: plda@14C1C200 { - compatible = "aspeed,plda", "syscon", "simple-mfd"; - reg = <0x0 0x14c1c000 0x0 0x400>; + mdio1: mdio@14040008 { + compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio"; + reg = <0 0x14040008 0 0x8>; + resets = <&syscon1 SCU1_RESET_MII>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio1_default>; + status = "disabled"; }; - sgmii: phy@14C01000 { - compatible = "aspeed,ast2700-sgmii"; - reg = <0x0 0x14c01000 0x0 0x40>; - - aspeed,plda = <&plda>; - + mdio2: mdio@14040010 { + compatible = "aspeed,ast2700-mdio", "aspeed,ast2600-mdio"; + reg = <0 0x14040010 0 0x8>; + resets = <&syscon1 SCU1_RESET_MII>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sgmii_default>; - #phy-cells = <0>; + pinctrl-0 = <&pinctrl_mdio2_default>; status = "disabled"; }; - mac0: ftgmac@14050000 { + mac0: ethernet@14050000 { compatible = "aspeed,ast2700-mac", "faraday,ftgmac100"; reg = <0x0 0x14050000 0x0 0x200>; interrupts-extended = <&intc1_4 0>; @@ -1283,7 +1313,7 @@ status = "disabled"; }; - mac1: ftgmac@14060000 { + mac1: ethernet@14060000 { compatible = "aspeed,ast2700-mac", "faraday,ftgmac100"; reg = <0x0 0x14060000 0x0 0x200>; interrupts-extended = <&intc1_4 1>; @@ -1293,7 +1323,7 @@ status = "disabled"; }; - mac2: ftgmac@14070000 { + mac2: ethernet@14070000 { compatible = "aspeed,ast2700-mac", "faraday,ftgmac100"; reg = <0x0 0x14070000 0x0 0x200>; interrupts-extended = <&intc1_4 2>; @@ -1337,6 +1367,43 @@ status = "disabled"; }; + pcie2: pcie@140d0000 { + compatible = "aspeed,ast2700-pcie"; + device_type = "pci"; + reg = <0x0 0x140d0000 0x0 0x100>; + linux,pci-domain = <2>; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; + ranges = <0x02000000 0 0xa0000000 0x0 0xa0000000 0x0 0x20000000>; + interrupts-extended = <&intc1_4 31>; + resets = <&syscon1 SCU1_RESET_H2X>, + <&syscon1 SCU1_RESET_PCIE2RST>; + reset-names = "h2x", "perst"; + status = "disabled"; + + clocks = <&syscon1 SCU1_CLK_GATE_PCICLK>; + pinctrl-0 = <&pinctrl_pcierc2_perst_default>; + pinctrl-names = "default"; + + #interrupt-cells = <1>; + msi-controller; + + aspeed,pciephy = <&pcie_phy2>; + aspeed,pciecfg = <&pcie_cfg2>; + + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc2 0>, + <0 0 0 2 &pcie_intc2 1>, + <0 0 0 3 &pcie_intc2 2>, + <0 0 0 4 &pcie_intc2 3>; + pcie_intc2: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + uhci1: usb@14110000 { compatible = "aspeed,ast2700-uhci", "generic-uhci"; reg = <0x0 0x14110000 0x0 0x100>; @@ -1357,7 +1424,6 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2cd_default>; - aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -1382,7 +1448,6 @@ aspeed,vhub-generic-endpoints = <21>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb2dd_default>; - aspeed,scu = <&syscon0>; status = "disabled"; }; @@ -1397,6 +1462,20 @@ status = "disabled"; }; + sram1: sram@14b80000 { + compatible = "mmio-sram"; + reg = <0x0 0x14b80000 0x0 0x40000>; + ranges = <0x0 0x0 0x0 0x14b80000 0x0 0x40000>; + #address-cells = <2>; + #size-cells = <2>; + no-memory-wc; + + exported@0 { + reg = <0 0x0 0 0x40000>; + export; + }; + }; + adc0: adc@14c00000 { compatible = "aspeed,ast2700-adc0"; reg = <0x0 0x14c00000 0 0x100>; @@ -1419,48 +1498,51 @@ status = "disabled"; }; - sram1: sram@14b80000 { - compatible = "mmio-sram"; - reg = <0x0 0x14b80000 0x0 0x40000>; - ranges = <0x0 0x0 0x0 0x14b80000 0x0 0x40000>; - #address-cells = <2>; - #size-cells = <2>; - no-memory-wc; + sgmii: phy@14c01000 { + compatible = "aspeed,ast2700-sgmii"; + reg = <0x0 0x14c01000 0x0 0x40>; - exported@0 { - reg = <0 0x0 0 0x40000>; - export; - }; + phys = <&pcie_phy2>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sgmii_default>; + #phy-cells = <0>; + status = "disabled"; }; syscon1: syscon@14c02000 { compatible = "aspeed,ast2700-scu1", "syscon", "simple-mfd"; reg = <0x0 0x14c02000 0x0 0x1000>; - ranges = <0x0 0x0 0x0 0x14c02000 0x0 0x1000>; - #address-cells = <2>; - #size-cells = <2>; + ranges = <0x0 0x0 0x14c02000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; + assigned-clocks = <&syscon1 SCU1_CLK_MACHCLK>, + <&syscon1 SCU1_CLK_RGMII>, + <&syscon1 SCU1_CLK_RMII>; + assigned-clock-rates = <200000000>, <125000000>, <50000000>; + scu_ic2: interrupt-controller@100 { - #interrupt-cells = <1>; compatible = "aspeed,ast2700-scu-ic2"; - reg = <0 0x100 0 0x8>; + reg = <0x100 0x8>; interrupts-extended = <&intc1_5 0>; + #interrupt-cells = <1>; interrupt-controller; }; scu_ic3: interrupt-controller@108 { - #interrupt-cells = <1>; compatible = "aspeed,ast2700-scu-ic3"; - reg = <0 0x108 0 0x8>; + reg = <0x108 0x8>; interrupts-extended = <&intc1_5 26>; + #interrupt-cells = <1>; interrupt-controller; }; pinctrl1: pinctrl@400 { compatible = "aspeed,ast2700-soc1-pinctrl"; - reg = <0x0 0x400 0x0 0x100>; + reg = <0x400 0x100>; }; }; @@ -1470,6 +1552,11 @@ status = "disabled"; }; + pcie_cfg2: syscon@14c02a80 { + compatible = "syscon"; + reg = <0 0x14c02a80 0 0x80>; + }; + chassis: chassis@14c04010 { compatible = "aspeed,ast2600-chassis"; reg = <0 0x14c04010 0 0x4>; @@ -1525,6 +1612,7 @@ interrupts-extended = <&intc1_0 10>, <&intc1_0 16>; clocks = <&syscon1 SCU1_CLK_GATE_ESPI0CLK>; resets = <&syscon1 SCU1_RESET_ESPI0>; + syscon = <&syscon1>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_espi0_default>; status = "disabled"; @@ -1536,6 +1624,7 @@ interrupts-extended = <&intc1_1 10>, <&intc1_1 16>; clocks = <&syscon1 SCU1_CLK_GATE_ESPI1CLK>; resets = <&syscon1 SCU1_RESET_ESPI1>; + syscon = <&syscon1>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_espi1_default>; status = "disabled"; @@ -1561,7 +1650,7 @@ status = "disabled"; }; - gpio0: gpio@14c0b000 { + gpio1: gpio@14c0b000 { #gpio-cells = <2>; gpio-controller; compatible = "aspeed,ast2700-gpio"; @@ -1620,17 +1709,17 @@ }; intc1: interrupt-controller@14c18000 { - compatible = "simple-mfd"; + compatible = "aspeed,ast2700-intc1"; reg = <0 0x14c18000 0 0x400>; - #address-cells = <2>; - #size-cells = <2>; - ranges = <0x0 0x0 0x0 0x14c18000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x14c18000 0x400>; intc1_0: interrupt-controller@100 { #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x100 0x0 0x10>; + reg = <0x100 0x10>; interrupts-extended = <&intc0_11 0>; }; @@ -1638,7 +1727,7 @@ #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x110 0x0 0x10>; + reg = <0x110 0x10>; interrupts-extended = <&intc0_11 1>; }; @@ -1646,7 +1735,7 @@ #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x120 0x0 0x10>; + reg = <0x120 0x10>; interrupts-extended = <&intc0_11 2>; }; @@ -1654,7 +1743,7 @@ #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x130 0x0 0x10>; + reg = <0x130 0x10>; interrupts-extended = <&intc0_11 3>; }; @@ -1662,7 +1751,7 @@ #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x140 0x0 0x10>; + reg = <0x140 0x10>; interrupts-extended = <&intc0_11 4>; }; @@ -1670,11 +1759,120 @@ #interrupt-cells = <1>; interrupt-controller; compatible = "aspeed,ast2700-intc-ic"; - reg = <0x0 0x150 0x0 0x10>; + reg = <0x150 0x10>; interrupts-extended = <&intc0_11 5>; }; }; + xdma2: xdma@14c19000 { + compatible = "aspeed,ast2700-xdma1"; + reg = <0x0 0x14c19000 0x0 0x100>; + clocks = <&syscon1 SCU1_CLK_GATE_PCICLK>; + resets = <&syscon1 SCU1_RESET_XDMA>; + reset-names = "device"; + interrupts-extended = <&intc1_4 21>, <&scu_ic2 ASPEED_AST2700_SCU_IC2_PCIE_PERST_LO_TO_HI>; + aspeed,pcie-device = "bmc"; + aspeed,scu = <&syscon1>; + status = "disabled"; + }; + + mctp2: mctp2@14c1a000 { + compatible = "aspeed,ast2700-mctp1"; + reg = <0x0 0x14c1a000 0x0 0x40>; + interrupts-extended = <&intc1_4 3>, <&scu_ic2 ASPEED_AST2700_SCU_IC2_PCIE_PERST_LO_TO_HI>; + interrupt-names = "mctp", "pcie"; + resets = <&syscon1 SCU1_RESET_MCTP>; + aspeed,scu = <&syscon1>; + aspeed,pcieh = <&pcie_phy2>; + status = "disabled"; + }; + + pcie_phy2: phy@14c1c000 { + compatible = "aspeed,ast2700-pcie-phy", "syscon"; + reg = <0x0 0x14c1c000 0x0 0x800>; + #phy-cells = <0>; + }; + + e2m_config2: e2m-config@14c1d000 { + compatible = "syscon", "simple-mfd"; + reg = <0 0x14c1d000 0 0x300>; + ranges = <0x0 0x0 0 0x14c1d000 0 0x300>; + #address-cells = <2>; + #size-cells = <2>; + aspeed,device = <&pcie_cfg2>; + + pinctrl-0 = <&pinctrl_pcierc2_perst_default>; + pinctrl-names = "default"; + + e2m_ic2: interrupt-controller@14 { + #interrupt-cells = <1>; + compatible = "aspeed,ast2700-e2m-ic"; + reg = <0 0x14 0 0x8>; + interrupts-extended = <&intc1_4 20>; + interrupt-controller; + }; + + pcie2_mmbi0: pcie2-mmbi@0 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT0>; + index = <0>; + pid = <2>; + bar = <0x1c>; + msi = <1>; + status = "disabled"; + }; + + pcie2_mmbi1: pcie2-mmbi@1 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT1>; + index = <1>; + pid = <3>; + bar = <0x50>; + msi = <2>; + status = "disabled"; + }; + + pcie2_mmbi2: pcie2-mmbi@2 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT2>; + index = <2>; + pid = <4>; + bar = <0x3c>; + msi = <3>; + status = "disabled"; + }; + + pcie2_mmbi3: pcie2-mmbi@3 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT3>; + index = <3>; + pid = <5>; + bar = <0x4c>; + msi = <4>; + status = "disabled"; + }; + + pcie2_mmbi4: pcie2-mmbi@4 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT4>; + index = <4>; + pid = <6>; + bar = <0x5c>; + msi = <5>; + status = "disabled"; + }; + + pcie2_mmbi5: pcie2-mmbi@5 { + compatible = "aspeed,ast2700-pcie-mmbi"; + interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT5>; + index = <5>; + pid = <7>; + bar = <0x6c>; + msi = <6>; + status = "disabled"; + }; + }; + peci0: peci-controller@14c1f000 { compatible = "aspeed,ast2600-peci"; reg = <0x0 0x14c1f000 0x0 0x100>; @@ -1895,38 +2093,50 @@ }; vuart0: serial@14c30000 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c30000 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts-extended = <&intc1_0 17>; clocks = <&syscon0 SCU0_CLK_APB>; virtual; + dma-channel = <12>; status = "disabled"; }; vuart1: serial@14c30100 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c30100 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts-extended = <&intc1_0 18>; clocks = <&syscon0 SCU0_CLK_APB>; virtual; + dma-channel = <13>; status = "disabled"; }; vuart2: serial@14c30200 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c30200 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts-extended = <&intc1_1 17>; clocks = <&syscon0 SCU0_CLK_APB>; virtual; + dma-channel = <14>; status = "disabled"; }; vuart3: serial@14c30300 { - compatible = "aspeed,ast2600-uart"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c30300 0x0 0x40>; + reg-shift = <2>; + reg-io-width = <4>; interrupts-extended = <&intc1_1 18>; clocks = <&syscon0 SCU0_CLK_APB>; virtual; + dma-channel = <15>; status = "disabled"; }; @@ -2097,6 +2307,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd0_default &pinctrl_rxd0_default>; + dma-channel = <0>; status = "disabled"; }; @@ -2111,6 +2322,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd1_default &pinctrl_rxd1_default>; + dma-channel = <1>; status = "disabled"; }; @@ -2125,6 +2337,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd2_default &pinctrl_rxd2_default>; + dma-channel = <2>; status = "disabled"; }; @@ -2139,6 +2352,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd3_default &pinctrl_rxd3_default>; + dma-channel = <3>; status = "disabled"; }; @@ -2153,6 +2367,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd5_default &pinctrl_rxd5_default>; + dma-channel = <4>; status = "disabled"; }; @@ -2167,6 +2382,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd6_default &pinctrl_rxd6_default>; + dma-channel = <5>; status = "disabled"; }; @@ -2181,6 +2397,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd7_default &pinctrl_rxd7_default>; + dma-channel = <6>; status = "disabled"; }; @@ -2195,6 +2412,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd8_default &pinctrl_rxd8_default>; + dma-channel = <7>; status = "disabled"; }; @@ -2208,6 +2426,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd9_default &pinctrl_rxd9_default>; + dma-channel = <8>; status = "disabled"; }; @@ -2221,6 +2440,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd10_default &pinctrl_rxd10_default>; + dma-channel = <9>; status = "disabled"; }; @@ -2234,6 +2454,7 @@ no-loopback-test; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_txd11_default &pinctrl_rxd11_default>; + dma-channel = <10>; status = "disabled"; }; @@ -2246,27 +2467,29 @@ interrupts-extended = <&intc1_4 18>; no-loopback-test; pinctrl-names = "default"; + dma-channel = <11>; + status = "disabled"; }; uart13: serial@14c33c00 { - compatible = "ns16550a"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c33c00 0x0 0x100>; reg-shift = <2>; reg-io-width = <4>; + clocks = <&syscon1 SCU1_CLK_UART13>; interrupts-extended = <&intc1_0 23>; - clock-frequency = <59076923>; no-loopback-test; pinctrl-names = "default"; status = "disabled"; }; uart14: serial@14c33d00 { - compatible = "ns16550a"; + compatible = "aspeed,ast2700-uart"; reg = <0x0 0x14c33d00 0x0 0x100>; reg-shift = <2>; reg-io-width = <4>; + clocks = <&syscon1 SCU1_CLK_UART14>; interrupts-extended = <&intc1_1 23>; - clock-frequency = <59076923>; no-loopback-test; pinctrl-names = "default"; status = "disabled"; @@ -2274,10 +2497,14 @@ ltpi0: ltpi@14c34000 { compatible = "aspeed-ltpi"; - reg = <0x0 0x14c34000 0x0 0x100>; + reg = <0x0 0x14c34000 0x0 0x100>, + <0x0 0x14c34200 0x0 0x100>, + <0x0 0x14c34800 0x0 0x100>; + reg-names = "base", "phy", "top"; clocks = <&syscon1 SCU1_CLK_GATE_LTPICLK>, <&syscon1 SCU1_CLK_GATE_LTPIPHYCLK>; clock-names = "ahb", "phy"; + aspeed,scu = <&syscon1>; resets = <&syscon1 SCU1_RESET_LTPI0>; interrupts-extended = <&intc1_5 12>; status = "disabled"; @@ -2297,10 +2524,14 @@ ltpi1: ltpi@14c35000 { compatible = "aspeed-ltpi"; - reg = <0x0 0x14c35000 0x0 0x100>; + reg = <0x0 0x14c35000 0x0 0x100>, + <0x0 0x14c35200 0x0 0x100>, + <0x0 0x14c35800 0x0 0x100>; + reg-names = "base", "phy", "top"; clocks = <&syscon1 SCU1_CLK_GATE_LTPICLK>, <&syscon1 SCU1_CLK_GATE_LTPI1TXCLK>; clock-names = "ahb", "phy"; + aspeed,scu = <&syscon1>; resets = <&syscon1 SCU1_RESET_LTPI1>; interrupts-extended = <&intc1_5 13>; status = "disabled"; @@ -2340,6 +2571,15 @@ status = "disabled"; }; + mbox2: mbox@14c39200 { + compatible = "aspeed,ast2700-mailbox"; + reg = <0x0 0x14c39200 0x0 0x100>, <0x0 0x14c39300 0x0 0x100>; + reg-names = "tx", "rx"; + interrupts-extended = <&intc1_5 17>; + #mbox-cells = <1>; + mbox-name = "bootmcu"; + }; + sgpios: sgpios@14c3c000 { #gpio-cells = <2>; gpio-controller; @@ -2349,7 +2589,7 @@ clocks = <&syscon1 SCU1_CLK_APB>; interrupt-controller; #interrupt-cells = <2>; - ngpios = <136>; + ngpios = <72>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sgps_default>; status = "disabled"; @@ -2377,136 +2617,20 @@ status = "disabled"; }; - pcie_device2: pcie-device@14c02a80 { - compatible = "syscon", "simple-mfd"; - reg = <0 0x14c02a80 0 0x80>; - }; - - mctp2: mctp2@14c1a000 { - compatible = "aspeed,ast2700-mctp1"; - reg = <0x0 0x14c1a000 0x0 0x40>; - interrupts-extended = <&intc1_4 3>, <&scu_ic2 ASPEED_AST2700_SCU_IC2_PCIE_PERST_LO_TO_HI>; - interrupt-names = "mctp", "pcie"; - resets = <&syscon1 SCU1_RESET_MCTP>; - aspeed,scu = <&syscon1>; - aspeed,pcieh = <&pcie_phy2>; + rtc_over_espi0: rtc-over_espi@14c3d000 { + compatible = "aspeed,ast2700-rtc-over-espi"; + reg = <0x0 0x14c3d000 0x0 0x100>; + interval-ms = <1000>; status = "disabled"; }; - pcie_phy2: rc-bridge@14c1c000 { - compatible = "aspeed,ast2700-pcie-phy", "syscon"; - reg = <0x0 0x14c1c000 0x0 0x800>; - }; - - pcie2: pcie@140d0000 { - compatible = "aspeed,ast2700-pcie"; - device_type = "pci"; - reg = <0x0 0x140d0000 0x0 0x100>; - linux,pci-domain = <2>; - #address-cells = <3>; - #size-cells = <2>; - bus-range = <0x00 0xff>; - ranges = <0x01000000 0 0x00000000 0x0 0x00000000 0x0 0x00008000>, - <0x02000000 0 0xa0000000 0x0 0xa0000000 0x0 0x10000000>; /* memory */ - interrupts-extended = <&intc1_4 31>; - resets = <&syscon1 SCU1_RESET_H2X>, - <&syscon1 SCU1_RESET_PCIE2RST>; - reset-names = "h2x", "perst"; + rtc_over_espi1: rtc-over_espi@14c3d100 { + compatible = "aspeed,ast2700-rtc-over-espi"; + reg = <0x0 0x14c3d100 0x0 0x100>; + interval-ms = <1000>; status = "disabled"; - - pinctrl-0 = <&pinctrl_pcierc2_perst_default>; - pinctrl-names = "default"; - - #interrupt-cells = <1>; - msi-parent = <&pcie2>; - msi_address = <0x000000F0>; - pciephy = <&pcie_phy2>; - aspeed,device = <&pcie_device2>; - interrupt-map-mask = <0 0 0 7>; - interrupt-map = <0 0 0 1 &pcie_intc2 0>, - <0 0 0 2 &pcie_intc2 1>, - <0 0 0 3 &pcie_intc2 2>, - <0 0 0 4 &pcie_intc2 3>; - pcie_intc2: interrupt-controller { - interrupt-controller; - #address-cells = <0>; - #interrupt-cells = <1>; - }; }; - e2m_config2: e2m-config@14c1d000 { - compatible = "syscon", "simple-mfd"; - reg = <0 0x14c1d000 0 0x300>; - ranges = <0x0 0x0 0 0x14c1d000 0 0x300>; - #address-cells = <2>; - #size-cells = <2>; - aspeed,device = <&pcie_device2>; - - pinctrl-0 = <&pinctrl_pcierc2_perst_default>; - pinctrl-names = "default"; - - e2m_ic2: interrupt-controller@14 { - #interrupt-cells = <1>; - compatible = "aspeed,ast2700-e2m-ic"; - reg = <0 0x14 0 0x8>; - interrupts-extended = <&intc1_4 20>; - interrupt-controller; - }; - - pcie2_mmbi0: pcie2-mmbi@0 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT0>; - index = <0>; - pid = <2>; - bar = <0x1c>; - status = "disabled"; - }; - - pcie2_mmbi1: pcie2-mmbi@1 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT1>; - index = <1>; - pid = <3>; - bar = <0x50>; - status = "disabled"; - }; - - pcie2_mmbi2: pcie2-mmbi@2 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT2>; - index = <2>; - pid = <4>; - bar = <0x3c>; - status = "disabled"; - }; - - pcie2_mmbi3: pcie2-mmbi@3 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT3>; - index = <3>; - pid = <5>; - bar = <0x4c>; - status = "disabled"; - }; - - pcie2_mmbi4: pcie2-mmbi@4 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT4>; - index = <4>; - pid = <6>; - bar = <0x5c>; - status = "disabled"; - }; - - pcie2_mmbi5: pcie2-mmbi@5 { - compatible = "aspeed,ast2700-pcie-mmbi"; - interrupts-extended = <&e2m_ic2 ASPEED_AST2700_E2M_MMBI_H2B_INT5>; - index = <5>; - pid = <7>; - bar = <0x6c>; - status = "disabled"; - }; - }; }; }; @@ -2521,7 +2645,6 @@ i2c0: i2c-bus@100 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x100 0x80>, <0x1A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2539,7 +2662,6 @@ i2c1: i2c-bus@200 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x200 0x80>, <0x2A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2557,7 +2679,6 @@ i2c2: i2c-bus@300 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x300 0x80>, <0x3A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2575,7 +2696,6 @@ i2c3: i2c-bus@400 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x400 0x80>, <0x4A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2592,7 +2712,6 @@ i2c4: i2c-bus@500 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x500 0x80>, <0x5A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2610,7 +2729,6 @@ i2c5: i2c-bus@600 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x600 0x80>, <0x6A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2628,7 +2746,6 @@ i2c6: i2c-bus@700 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x700 0x80>, <0x7A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2646,7 +2763,6 @@ i2c7: i2c-bus@800 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x800 0x80>, <0x8A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2664,7 +2780,6 @@ i2c8: i2c-bus@900 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x900 0x80>, <0x9A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2682,7 +2797,6 @@ i2c9: i2c-bus@a00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xA00 0x80>, <0xAA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2700,7 +2814,6 @@ i2c10: i2c-bus@b00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xB00 0x80>, <0xBA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2718,7 +2831,6 @@ i2c11: i2c-bus@c00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xC00 0x80>, <0xCA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2736,7 +2848,6 @@ i2c12: i2c-bus@d00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xD00 0x80>, <0xDA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2754,7 +2865,6 @@ i2c13: i2c-bus@e00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xE00 0x80>, <0xEA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2772,7 +2882,6 @@ i2c14: i2c-bus@f00 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0xF00 0x80>, <0xFA0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; @@ -2790,7 +2899,6 @@ i2c15: i2c-bus@1000 { #address-cells = <1>; #size-cells = <0>; - #interrupt-cells = <1>; reg = <0x1000 0x80>, <0x10A0 0x20>; compatible = "aspeed,ast2700-i2c"; aspeed,global-regs = <&i2c_global>; diff --git a/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi b/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi new file mode 100644 index 00000000000000..c09e51b0c64f2f --- /dev/null +++ b/arch/arm64/boot/dts/aspeed/ast2700-reserved-mem.dtsi @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* AST2700 reserved memories with no-map property */ + +#if DUAL_NODE +espi1_mmbi_memory: espi1-mmbi-memory@418000000 { + reg = <0x4 0x18000000 0x0 0x4000000>; + no-map; +}; + +edaf1: edaf1-memory@41c000000 { + reg = <0x4 0x1c000000 0x0 0x4000000>; + no-map; +}; +#endif + +edaf0: eadf0-memory@428000000 { + reg = <0x4 0x28000000 0x0 0x4000000>; + no-map; +}; + +espi0_mmbi_memory: espi0-mmbi-memory@424000000 { + reg = <0x4 0x24000000 0x0 0x4000000>; + no-map; +}; + +#if PCIE0_EP +bmc_dev0_memory: bmc-dev0-memory@423800000 { + compatible = "shared-dma-pool"; + reg = <0x4 0x23800000 0x0 0x100000>; + no-map; +}; + +xdma_memory0: xdma0 { + size = <0x0 0x00100000>; + compatible = "shared-dma-pool"; + no-map; +}; + +pcie0_mmbi0_memory: pcie0-mmbi0-memory@423a00000 { + reg = <0x4 0x23a00000 0x0 0x200000>; + no-map; +}; +#endif + +#if PCIE1_EP +bmc_dev1_memory: bmc-dev1-memory@423900000 { + compatible = "shared-dma-pool"; + reg = <0x4 0x23900000 0x0 0x100000>; + no-map; +}; + +xdma_memory1: xdma1 { + size = <0x0 0x00100000>; + compatible = "shared-dma-pool"; + no-map; +}; + +pcie1_mmbi4_memory: pcie1-mmbi4-memory@423c00000 { + reg = <0x4 0x23c00000 0x0 0x200000>; + no-map; +}; +#endif + +pcie2_mmbi0_memory: pcie2-mmbi0-memory@423e00000 { + reg = <0x4 0x23e00000 0x0 0x200000>; + no-map; +}; + +ssp_memory: ssp-memory@42c000000 { + reg = <0x4 0x2c000000 0x0 0x2000000>; + no-map; +}; + +tsp_memory: tsp-memory@42e000000 { + reg = <0x4 0x2e000000 0x0 0x2000000>; + no-map; +}; + +ipc_ssp_share: ipc-ssp-share@431080000 { + reg = <0x4 0x31080000 0x0 0x800000>; + no-map; +}; + +ipc_bootmcu_share: ipc-bootmcu-share@431880000 { + reg = <0x4 0x31880000 0x0 0x2b0000>; + no-map; +}; + +uhci0_reserved: uhci0-reserved@431b30000 { + reg = <0x4 0x31b30000 0x0 0x40000>; + compatible = "shared-dma-pool"; + no-map; +}; + +uhci1_reserved: uhci1-reserved@431b70000 { + reg = <0x4 0x31b70000 0x0 0x40000>; + compatible = "shared-dma-pool"; + no-map; +}; + +vbios_base0: vbios-base0@431bb0000 { + reg = <0x4 0x31bb0000 0x0 0x10000>; + no-map; +}; + +vbios_base1: vbios-base1@431bc0000 { + reg = <0x4 0x31bc0000 0x0 0x10000>; + no-map; +}; + +mctp0_reserved: mctp0-reserved@431bd0000 { + reg = <0x4 0x31bd0000 0x0 0x10000>; + compatible = "shared-dma-pool"; + no-map; +}; + +mctp1_reserved: mctp1-reserved@431be0000 { + reg = <0x4 0x31be0000 0x0 0x10000>; + compatible = "shared-dma-pool"; + no-map; +}; + +mctp2_reserved: mctp2-reserved@431bf0000 { + reg = <0x4 0x31bf0000 0x0 0x10000>; + compatible = "shared-dma-pool"; + no-map; +}; diff --git a/drivers/clk/clk-ast2700.c b/drivers/clk/clk-ast2700.c index 83a4d6a7918bd2..f585dd3de5e2c8 100644 --- a/drivers/clk/clk-ast2700.c +++ b/drivers/clk/clk-ast2700.c @@ -10,14 +10,11 @@ #include #include #include -#include +#include #include -#define SCU_CLK_12MHZ (12 * HZ_PER_MHZ) -#define SCU_CLK_24MHZ (24 * HZ_PER_MHZ) -#define SCU_CLK_25MHZ (25 * HZ_PER_MHZ) -#define SCU_CLK_192MHZ (192 * HZ_PER_MHZ) +#define REVISION_ID GENMASK(23, 16) /* SOC0 */ #define SCU0_HWSTRAP1 0x010 @@ -36,9 +33,8 @@ #define SCU0_MPHYCLK_PARAM 0x360 /* SOC1 */ -#define SCU1_REVISION_ID 0x0 -#define REVISION_ID GENMASK(23, 16) #define SCU1_CLK_STOP 0x240 +#define AST2755_SCU1_CLK_STOP 0x248 #define SCU1_CLK_STOP2 0x260 #define SCU1_CLK_SEL1 0x280 #define SCU1_CLK_SEL2 0x284 @@ -81,7 +77,8 @@ #define MAC_CLK_100M_10M_OUTPUT_DELAY_2 GENMASK(11, 6) #define MAC_CLK_100M_10M_OUTPUT_DELAY_1 GENMASK(5, 0) -#define AST2700_DEF_MAC12_DELAY_1G 0x00C70C73 +#define AST2700_DEF_MAC12_DELAY_1G_A0 0x00CF4D75 +#define AST2700_DEF_MAC12_DELAY_1G_A1 0x005D6618 #define AST2700_DEF_MAC12_DELAY_100M 0x00410410 #define AST2700_DEF_MAC12_DELAY_10M 0x00410410 @@ -101,7 +98,7 @@ enum ast2700_clk_type { CLK_GATE, CLK_MISC, CLK_FIXED, - DCLK_FIXED, + CLK_FIXED_DISPLAY, CLK_DIVIDER, CLK_UART_PLL, CLK_FIXED_FACTOR, @@ -109,20 +106,21 @@ enum ast2700_clk_type { }; struct ast2700_clk_fixed_factor_data { - const struct clk_parent_data *parent; unsigned int mult; unsigned int div; + int parent_id; }; struct ast2700_clk_gate_data { - const struct clk_parent_data *parent; + int parent_id; u32 flags; u32 reg; u8 bit; }; struct ast2700_clk_mux_data { - const struct clk_parent_data *parents; + const struct clk_hw **parent_hws; + const unsigned int *parent_ids; unsigned int num_parents; u8 bit_shift; u8 bit_width; @@ -131,14 +129,14 @@ struct ast2700_clk_mux_data { struct ast2700_clk_div_data { const struct clk_div_table *div_table; - const struct clk_parent_data *parent; + unsigned int parent_id; u8 bit_shift; u8 bit_width; u32 reg; }; struct ast2700_clk_pll_data { - const struct clk_parent_data *parent; + unsigned int parent_id; u32 reg; }; @@ -146,14 +144,19 @@ struct ast2700_clk_fixed_rate_data { unsigned long fixed_rate; }; +struct ast2700_clk_display_fixed_data { + u32 reg; +}; + struct ast2700_clk_info { + u32 id; const char *name; - u8 clk_idx; u32 reg; u32 type; union { struct ast2700_clk_fixed_factor_data factor; struct ast2700_clk_fixed_rate_data rate; + struct ast2700_clk_display_fixed_data display_rate; struct ast2700_clk_gate_data gate; struct ast2700_clk_div_data div; struct ast2700_clk_pll_data pll; @@ -162,7 +165,7 @@ struct ast2700_clk_info { }; struct ast2700_clk_data { - struct ast2700_clk_info const *clk_info; + const struct ast2700_clk_info *clk_info; unsigned int nr_clks; const int scu; }; @@ -230,284 +233,139 @@ static const struct clk_div_table ast2700_hclk_div_table[] = { { 0 } }; -static const struct clk_div_table ast2700a0_hclk_div_table[] = { - { 0x0, 4 }, - { 0x1, 4 }, - { 0x2, 6 }, - { 0x3, 8 }, - { 0 } -}; - static const struct clk_div_table ast2700_clk_uart_div_table[] = { { 0x0, 1 }, { 0x1, 13 }, { 0 } }; -static const struct clk_parent_data soc0_clkin[] = { - { .fw_name = "soc0-clkin", .name = "soc0-clkin" }, -}; - -static const struct clk_parent_data pspclk[] = { - { .fw_name = "pspclk", .name = "pspclk" }, -}; - -static const struct clk_parent_data soc0_mpll_div8[] = { - { .fw_name = "soc0-mpll_div8", .name = "soc0-mpll_div8" }, -}; - -static const struct clk_parent_data mphysrc[] = { - { .fw_name = "mphysrc", .name = "mphysrc" }, -}; - -static const struct clk_parent_data u2phy_refclksrc[] = { - { .fw_name = "u2phy_refclksrc", .name = "u2phy_refclksrc" }, -}; - -static const struct clk_parent_data soc0_hpll[] = { - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, -}; - -static const struct clk_parent_data soc0_mpll[] = { - { .fw_name = "soc0-mpll", .name = "soc0-mpll" }, -}; - -static const struct clk_parent_data axi0clk[] = { - { .fw_name = "axi0clk", .name = "axi0clk" }, -}; - -static const struct clk_parent_data soc0_ahbmux[] = { - { .fw_name = "soc0-ahbmux", .name = "soc0-ahbmux" }, -}; - -static const struct clk_parent_data soc0_ahb[] = { - { .fw_name = "soc0-ahb", .name = "soc0-ahb" }, -}; - -static const struct clk_parent_data soc0_uartclk[] = { - { .fw_name = "soc0-uartclk", .name = "soc0-uartclk" }, -}; - -static const struct clk_parent_data emmcclk[] = { - { .fw_name = "emmcclk", .name = "emmcclk" }, -}; - -static const struct clk_parent_data emmcsrc_mux[] = { - { .fw_name = "emmcsrc-mux", .name = "emmcsrc-mux" }, -}; - -static const struct clk_parent_data soc1_clkin[] = { - { .fw_name = "soc1-clkin", .name = "soc1-clkin" }, -}; - -static const struct clk_parent_data soc1_hpll[] = { - { .fw_name = "soc1-hpll", .name = "soc1-hpll" }, -}; - -static const struct clk_parent_data soc1_apll[] = { - { .fw_name = "soc1-apll", .name = "soc1-apll" }, -}; - -static const struct clk_parent_data sdclk[] = { - { .fw_name = "sdclk", .name = "sdclk" }, -}; - -static const struct clk_parent_data sdclk_mux[] = { - { .fw_name = "sdclk-mux", .name = "sdclk-mux" }, -}; - -static const struct clk_parent_data huartxclk[] = { - { .fw_name = "huartxclk", .name = "huartxclk" }, -}; - -static const struct clk_parent_data uxclk[] = { - { .fw_name = "uxclk", .name = "uxclk" }, -}; - -static const struct clk_parent_data huxclk[] = { - { .fw_name = "huxclk", .name = "huxclk" }, -}; - -static const struct clk_parent_data uart0clk[] = { - { .fw_name = "uart0clk", .name = "uart0clk" }, -}; - -static const struct clk_parent_data uart1clk[] = { - { .fw_name = "uart1clk", .name = "uart1clk" }, -}; - -static const struct clk_parent_data uart2clk[] = { - { .fw_name = "uart2clk", .name = "uart2clk" }, -}; - -static const struct clk_parent_data uart3clk[] = { - { .fw_name = "uart3clk", .name = "uart3clk" }, +/* soc 0 */ +static const unsigned int psp_parent_ids[] = { + SCU0_CLK_MPLL, + SCU0_CLK_HPLL, + SCU0_CLK_HPLL, + SCU0_CLK_HPLL, + SCU0_CLK_MPLL_DIV2, + SCU0_CLK_HPLL_DIV2, + SCU0_CLK_HPLL, + SCU0_CLK_HPLL }; -static const struct clk_parent_data uart5clk[] = { - { .fw_name = "uart5clk", .name = "uart5clk" }, -}; - -static const struct clk_parent_data uart4clk[] = { - { .fw_name = "uart4clk", .name = "uart4clk" }, -}; - -static const struct clk_parent_data uart6clk[] = { - { .fw_name = "uart6clk", .name = "uart6clk" }, -}; - -static const struct clk_parent_data uart7clk[] = { - { .fw_name = "uart7clk", .name = "uart7clk" }, -}; +static const struct clk_hw *psp_parent_hws[ARRAY_SIZE(psp_parent_ids)]; -static const struct clk_parent_data uart8clk[] = { - { .fw_name = "uart8clk", .name = "uart8clk" }, +static const unsigned int hclk_parent_ids[] = { + SCU0_CLK_HPLL, + SCU0_CLK_MPLL }; -static const struct clk_parent_data uart9clk[] = { - { .fw_name = "uart9clk", .name = "uart9clk" }, -}; +static const struct clk_hw *hclk_parent_hws[ARRAY_SIZE(hclk_parent_ids)]; -static const struct clk_parent_data uart10clk[] = { - { .fw_name = "uart10clk", .name = "uart10clk" }, +static const unsigned int emmc_parent_ids[] = { + SCU0_CLK_MPLL_DIV4, + SCU0_CLK_HPLL_DIV4 }; -static const struct clk_parent_data uart11clk[] = { - { .fw_name = "uart11clk", .name = "uart11clk" }, -}; +static const struct clk_hw *emmc_parent_hws[ARRAY_SIZE(emmc_parent_ids)]; -static const struct clk_parent_data uart12clk[] = { - { .fw_name = "uart12clk", .name = "uart12clk" }, +static const unsigned int mphy_parent_ids[] = { + SCU0_CLK_MPLL, + SCU0_CLK_HPLL, + SCU0_CLK_DPLL, + SCU0_CLK_192M }; -static const struct clk_parent_data uart13clk[] = { - { .fw_name = "uart13clk", .name = "uart13clk" }, -}; +static const struct clk_hw *mphy_parent_hws[ARRAY_SIZE(mphy_parent_ids)]; -static const struct clk_parent_data uart14clk[] = { - { .fw_name = "uart14clk", .name = "uart14clk" }, +static const unsigned int u2phy_parent_ids[] = { + SCU0_CLK_MPLL, + SCU0_CLK_HPLL }; -static const struct clk_parent_data uart15clk[] = { - { .fw_name = "uart15clk", .name = "uart15clk" }, -}; +static const struct clk_hw *u2phy_parent_hws[ARRAY_SIZE(u2phy_parent_ids)]; -static const struct clk_parent_data uart16clk[] = { - { .fw_name = "uart16clk", .name = "uart16clk" }, +static const unsigned int uart_parent_ids[] = { + SCU0_CLK_24M, + SCU0_CLK_192M }; -static const struct clk_parent_data soc1_ahb[] = { - { .fw_name = "soc1-ahb", .name = "soc1-ahb" }, -}; +static const struct clk_hw *uart_parent_hws[ARRAY_SIZE(uart_parent_ids)]; -static const struct clk_parent_data soc1_i3c[] = { - { .fw_name = "soc1-i3c", .name = "soc1-i3c" }, +/* soc 1 */ +static const unsigned int uartx_parent_ids[] = { + SCU1_CLK_UARTX, + SCU1_CLK_HUARTX }; -static const struct clk_parent_data canclk[] = { - { .fw_name = "canclk", .name = "canclk" }, -}; +static const struct clk_hw *uartx_parent_hws[ARRAY_SIZE(uartx_parent_ids)]; -static const struct clk_parent_data rmii[] = { - { .fw_name = "rmii", .name = "rmii" }, +static const unsigned int uxclk_parent_ids[] = { + SCU1_CLK_APLL_DIV4, + SCU1_CLK_APLL_DIV2, + SCU1_CLK_APLL, + SCU1_CLK_HPLL }; -static const struct clk_parent_data d_clk_sels[] = { - { .fw_name = "soc0-hpll_div2", .name = "soc0-hpll_div2" }, - { .fw_name = "soc0-mpll_div2", .name = "soc0-mpll_div2" }, -}; +static const struct clk_hw *uxclk_parent_hws[ARRAY_SIZE(uxclk_parent_ids)]; -static const struct clk_parent_data hclk_clk_sels[] = { - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-mpll", .name = "soc0-mpll" }, +static const unsigned int sdclk_parent_ids[] = { + SCU1_CLK_HPLL, + SCU1_CLK_APLL }; -static const struct clk_parent_data mhpll_clk_sels[] = { - { .fw_name = "soc0-mpll", .name = "soc0-mpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, -}; - -static const struct clk_parent_data mphy_clk_sels[] = { - { .fw_name = "soc0-mpll", .name = "soc0-mpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-dpll", .name = "soc0-dpll" }, - { .fw_name = "soc0-clk192Mhz", .name = "soc0-clk192Mhz" }, -}; - -static const struct clk_parent_data psp_clk_sels[] = { - { .fw_name = "soc0-mpll", .name = "soc0-mpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-mpll_div2", .name = "soc0-mpll_div2" }, - { .fw_name = "soc0-hpll_div2", .name = "soc0-hpll_div2" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, - { .fw_name = "soc0-hpll", .name = "soc0-hpll" }, -}; - -static const struct clk_parent_data uart_clk_sels[] = { - { .fw_name = "soc0-clk24Mhz", .name = "soc0-clk24Mhz" }, - { .fw_name = "soc0-clk192Mhz", .name = "soc0-clk192Mhz" }, -}; - -static const struct clk_parent_data emmc_clk_sels[] = { - { .fw_name = "soc0-mpll_div4", .name = "soc0-mpll_div4" }, - { .fw_name = "soc0-hpll_div4", .name = "soc0-hpll_div4" }, -}; - -static const struct clk_parent_data sdio_clk_sels[] = { - { .fw_name = "soc1-hpll", .name = "soc1-hpll" }, - { .fw_name = "soc1-apll", .name = "soc1-apll" }, -}; - -static const struct clk_parent_data ux_clk_sels[] = { - { .fw_name = "soc1-apll_div4", .name = "soc1-apll_div4" }, - { .fw_name = "soc1-apll_div2", .name = "soc1-apll_div2" }, - { .fw_name = "soc1-apll", .name = "soc1-apll" }, - { .fw_name = "soc1-hpll", .name = "soc1-hpll" }, -}; - -static const struct clk_parent_data uartx_clk_sels[] = { - { .fw_name = "uartxclk", .name = "uartxclk" }, - { .fw_name = "huartxclk", .name = "huartxclk" }, -}; +static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)]; #define FIXED_CLK(_id, _name, _rate) \ - [_id] = { \ + { \ + .id = _id, \ .type = CLK_FIXED, \ .name = _name, \ .data = { .rate = { .fixed_rate = _rate, } }, \ } -#define PLL_CLK(_id, _type, _name, _parent, _reg) \ - [_id] = { \ +#define FIXED_DISPLAY_CLK(_id, _name, _reg) \ + { \ + .id = _id, \ + .type = CLK_FIXED_DISPLAY, \ + .name = _name, \ + .data = { .display_rate = { .reg = _reg } }, \ + } + +#define PLL_CLK(_id, _type, _name, _parent_id, _reg) \ + { \ + .id = _id, \ .type = _type, \ .name = _name, \ - .data = { .pll = { .parent = _parent, .reg = _reg, } }, \ + .data = { .pll = { \ + .parent_id = _parent_id, \ + .reg = _reg, \ + } }, \ } -#define MUX_CLK(_id, _name, _parents, _num_parents, _reg, _shift, _width) \ - [_id] = { \ - .type = CLK_MUX, \ - .name = _name, \ - .data = { \ - .mux = { \ - .parents = _parents, \ - .num_parents = _num_parents, \ - .reg = _reg, \ - .bit_shift = _shift, \ - .bit_width = _width, \ +#define MUX_CLK(_id, _name, _parent_ids, _num_parents, _parent_hws, _reg, _shift, _width) \ + { \ + .id = _id, \ + .type = CLK_MUX, \ + .name = _name, \ + .data = { \ + .mux = { \ + .parent_ids = _parent_ids, \ + .parent_hws = _parent_hws, \ + .num_parents = _num_parents, \ + .reg = (_reg), \ + .bit_shift = _shift, \ + .bit_width = _width, \ + }, \ }, \ - }, \ - } + } -#define DIVIDER_CLK(_id, _name, _parent, _reg, _shift, _width, _div_table) \ - [_id] = { \ +#define DIVIDER_CLK(_id, _name, _parent_id, _reg, _shift, _width, _div_table) \ + { \ + .id = _id, \ .type = CLK_DIVIDER, \ .name = _name, \ .data = { \ .div = { \ - .parent = _parent, \ + .parent_id = _parent_id, \ .reg = _reg, \ .bit_shift = _shift, \ .bit_width = _width, \ @@ -516,20 +374,22 @@ static const struct clk_parent_data uartx_clk_sels[] = { }, \ } -#define FIXED_FACTOR_CLK(_id, _name, _parent, _mult, _div) \ - [_id] = { \ +#define FIXED_FACTOR_CLK(_id, _name, _parent_id, _mult, _div) \ + { \ + .id = _id, \ .type = CLK_FIXED_FACTOR, \ .name = _name, \ - .data = { .factor = { .parent = _parent, .mult = _mult, .div = _div, } }, \ + .data = { .factor = { .parent_id = _parent_id, .mult = _mult, .div = _div, } }, \ } -#define GATE_CLK(_id, _type, _name, _parent, _reg, _bit, _flags) \ - [_id] = { \ +#define GATE_CLK(_id, _type, _name, _parent_id, _reg, _bit, _flags) \ + { \ + .id = _id, \ .type = _type, \ .name = _name, \ .data = { \ .gate = { \ - .parent = _parent, \ + .parent_id = _parent_id, \ .reg = _reg, \ .bit = _bit, \ .flags = _flags, \ @@ -538,513 +398,458 @@ static const struct clk_parent_data uartx_clk_sels[] = { } static const struct ast2700_clk_info ast2700_scu0_clk_info[] __initconst = { - FIXED_CLK(SCU0_CLKIN, "soc0-clkin", SCU_CLK_25MHZ), - FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", SCU_CLK_24MHZ), - FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", SCU_CLK_192MHZ), - FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", SCU_CLK_12MHZ), - PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", soc0_clkin, SCU0_HPLL_PARAM), - PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", soc0_clkin, SCU0_DPLL_PARAM), - PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", soc0_clkin, SCU0_MPLL_PARAM), - PLL_CLK(SCU0_CLK_D0, DCLK_FIXED, "d0clk", NULL, SCU0_D0CLK_PARAM), - PLL_CLK(SCU0_CLK_D1, DCLK_FIXED, "d1clk", NULL, SCU0_D1CLK_PARAM), - PLL_CLK(SCU0_CLK_CRT0, DCLK_FIXED, "crt0clk", NULL, SCU0_CRT0CLK_PARAM), - PLL_CLK(SCU0_CLK_CRT1, DCLK_FIXED, "crt1clk", NULL, SCU0_CRT1CLK_PARAM), - PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", mphysrc, SCU0_MPHYCLK_PARAM), - PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", u2phy_refclksrc, SCU0_CLK_SEL2), - FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", soc0_hpll, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", soc0_hpll, 1, 4), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", soc0_mpll, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", soc0_mpll, 1, 4), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", soc0_mpll, 1, 8), - FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", pspclk, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", soc0_mpll, 1, 4), - DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", soc0_ahbmux, + FIXED_CLK(SCU0_CLKIN, "soc0-clkin", 25 * HZ_PER_MHZ), + FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", 24 * HZ_PER_MHZ), + FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", 192 * HZ_PER_MHZ), + FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", 12 * HZ_PER_MHZ), + FIXED_DISPLAY_CLK(SCU0_CLK_D0, "d0clk", SCU0_D0CLK_PARAM), + FIXED_DISPLAY_CLK(SCU0_CLK_D1, "d1clk", SCU0_D1CLK_PARAM), + FIXED_DISPLAY_CLK(SCU0_CLK_CRT0, "crt0clk", SCU0_CRT0CLK_PARAM), + FIXED_DISPLAY_CLK(SCU0_CLK_CRT1, "crt1clk", SCU0_CRT1CLK_PARAM), + PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", SCU0_CLKIN, SCU0_HPLL_PARAM), + PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", SCU0_CLKIN, SCU0_DPLL_PARAM), + PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", SCU0_CLKIN, SCU0_MPLL_PARAM), + FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", SCU0_CLK_HPLL, 1, 2), + FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", SCU0_CLK_HPLL, 1, 4), + FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", SCU0_CLK_MPLL, 1, 2), + FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", SCU0_CLK_MPLL, 1, 4), + FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", SCU0_CLK_MPLL, 1, 8), + FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", SCU0_CLK_MPLL, 1, 4), + MUX_CLK(SCU0_CLK_PSP, "pspclk", psp_parent_ids, ARRAY_SIZE(psp_parent_ids), + psp_parent_hws, SCU0_HWSTRAP1, 2, 3), + FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", SCU0_CLK_PSP, 1, 2), + MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", hclk_parent_ids, ARRAY_SIZE(hclk_parent_ids), + hclk_parent_hws, SCU0_HWSTRAP1, 7, 1), + MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_parent_ids, ARRAY_SIZE(emmc_parent_ids), + emmc_parent_hws, SCU0_CLK_SEL1, 11, 1), + MUX_CLK(SCU0_CLK_MPHYSRC, "mphysrc", mphy_parent_ids, ARRAY_SIZE(mphy_parent_ids), + mphy_parent_hws, SCU0_CLK_SEL2, 18, 2), + MUX_CLK(SCU0_CLK_U2PHY_REFCLKSRC, "u2phy_refclksrc", u2phy_parent_ids, + ARRAY_SIZE(u2phy_parent_ids), u2phy_parent_hws, SCU0_CLK_SEL2, 23, 1), + MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_parent_ids, ARRAY_SIZE(uart_parent_ids), + uart_parent_hws, SCU0_CLK_SEL2, 14, 1), + PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", SCU0_CLK_MPHYSRC, SCU0_MPHYCLK_PARAM), + PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", SCU0_CLK_U2PHY_REFCLKSRC, + SCU0_CLK_SEL2), + DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", SCU0_CLK_AHBMUX, SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), - DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", emmcsrc_mux, + DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", SCU0_CLK_EMMCMUX, SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2), - DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", axi0clk, + DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", SCU0_CLK_AXI0, SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2), - DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", soc0_uartclk, - SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table), - MUX_CLK(SCU0_CLK_PSP, "pspclk", psp_clk_sels, ARRAY_SIZE(psp_clk_sels), - SCU0_HWSTRAP1, 2, 3), - MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", hclk_clk_sels, ARRAY_SIZE(hclk_clk_sels), - SCU0_HWSTRAP1, 7, 1), - MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_clk_sels, ARRAY_SIZE(emmc_clk_sels), - SCU0_CLK_SEL1, 11, 1), - MUX_CLK(SCU0_CLK_MPHYSRC, "mphysrc", mphy_clk_sels, ARRAY_SIZE(mphy_clk_sels), - SCU0_CLK_SEL2, 18, 2), - MUX_CLK(SCU0_CLK_U2PHY_REFCLKSRC, "u2phy_refclksrc", mhpll_clk_sels, - ARRAY_SIZE(mhpll_clk_sels), SCU0_CLK_SEL2, 23, 1), - MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_clk_sels, ARRAY_SIZE(uart_clk_sels), - SCU0_CLK_SEL2, 14, 1), - GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", soc0_mpll, - SCU0_CLK_STOP, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", NULL, SCU0_CLK_STOP, 1, 0), - GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", NULL, SCU0_CLK_STOP, 2, 0), - GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", NULL, SCU0_CLK_STOP, 3, 0), - GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", NULL, - SCU0_CLK_STOP, 4, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", NULL, - SCU0_CLK_STOP, 5, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", soc0_clkin, - SCU0_CLK_STOP, 6, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", NULL, - SCU0_CLK_STOP, 7, 0), - GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", NULL, SCU0_CLK_STOP, 9, 0), - GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", NULL, - SCU0_CLK_STOP, 10, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", NULL, - SCU0_CLK_STOP, 11, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", NULL, - SCU0_CLK_STOP, 12, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", NULL, SCU0_CLK_STOP, 13, 0), - GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", NULL, - SCU0_CLK_STOP, 14, 0), - GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", uart4clk, - SCU0_CLK_STOP, 15, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", NULL, - SCU0_CLK_STOP, 16, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", NULL, - SCU0_CLK_STOP, 17, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", NULL, - SCU0_CLK_STOP, 18, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", NULL, - SCU0_CLK_STOP, 19, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", NULL, - SCU0_CLK_STOP, 20, 0), - GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", NULL, - SCU0_CLK_STOP, 21, 0), - GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", NULL, - SCU0_CLK_STOP, 23, 0), - GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", NULL, - SCU0_CLK_STOP, 24, 0), - GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", NULL, - SCU0_CLK_STOP, 25, 0), - GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", NULL, - SCU0_CLK_STOP, 26, 0), - GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", emmcclk, - SCU0_CLK_STOP, 27, 0), - GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", NULL, - SCU0_CLK_STOP, 28, 0), -}; - -static const struct ast2700_clk_info ast2700a0_scu0_clk_info[] __initconst = { - FIXED_CLK(SCU0_CLKIN, "soc0-clkin", SCU_CLK_25MHZ), - FIXED_CLK(SCU0_CLK_24M, "soc0-clk24Mhz", SCU_CLK_24MHZ), - FIXED_CLK(SCU0_CLK_192M, "soc0-clk192Mhz", SCU_CLK_192MHZ), - FIXED_CLK(SCU0_CLK_U2PHY_CLK12M, "u2phy_clk12m", SCU_CLK_12MHZ), - PLL_CLK(SCU0_CLK_HPLL, CLK_HPLL, "soc0-hpll", soc0_clkin, SCU0_HPLL_PARAM), - PLL_CLK(SCU0_CLK_DPLL, CLK_PLL, "soc0-dpll", soc0_clkin, SCU0_DPLL_PARAM), - PLL_CLK(SCU0_CLK_MPLL, CLK_PLL, "soc0-mpll", soc0_clkin, SCU0_MPLL_PARAM), - PLL_CLK(SCU0_CLK_D0, DCLK_FIXED, "d0clk", NULL, SCU0_D0CLK_PARAM), - PLL_CLK(SCU0_CLK_D1, DCLK_FIXED, "d1clk", NULL, SCU0_D1CLK_PARAM), - PLL_CLK(SCU0_CLK_CRT0, DCLK_FIXED, "crt0clk", NULL, SCU0_CRT0CLK_PARAM), - PLL_CLK(SCU0_CLK_CRT1, DCLK_FIXED, "crt1clk", NULL, SCU0_CRT1CLK_PARAM), - PLL_CLK(SCU0_CLK_MPHY, CLK_MISC, "mphyclk", soc0_hpll, SCU0_MPHYCLK_PARAM), - PLL_CLK(SCU0_CLK_U2PHY_REFCLK, CLK_MISC, "u2phy_refclk", soc0_mpll_div8, SCU0_CLK_SEL2), - FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV2, "soc0-hpll_div2", soc0_hpll, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_HPLL_DIV4, "soc0-hpll_div4", soc0_hpll, 1, 4), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV2, "soc0-mpll_div2", soc0_mpll, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV4, "soc0-mpll_div4", soc0_mpll, 1, 4), - FIXED_FACTOR_CLK(SCU0_CLK_MPLL_DIV8, "soc0-mpll_div8", soc0_mpll, 1, 8), - FIXED_FACTOR_CLK(SCU0_CLK_AXI0, "axi0clk", pspclk, 1, 2), - FIXED_FACTOR_CLK(SCU0_CLK_AXI1, "axi1clk", soc0_ahb, 1, 1), - DIVIDER_CLK(SCU0_CLK_AHB, "soc0-ahb", soc0_ahbmux, - SCU0_HWSTRAP1, 5, 2, ast2700a0_hclk_div_table), - DIVIDER_CLK(SCU0_CLK_APB, "soc0-apb", axi0clk, - SCU0_CLK_SEL1, 23, 3, ast2700_clk_div_table2), - DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", soc0_uartclk, + DIVIDER_CLK(SCU0_CLK_HPLL_DIV_AHB, "soc0-hpll-ahb", SCU0_CLK_HPLL, + SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), + DIVIDER_CLK(SCU0_CLK_MPLL_DIV_AHB, "soc0-mpll-ahb", SCU0_CLK_MPLL, + SCU0_HWSTRAP1, 5, 2, ast2700_hclk_div_table), + DIVIDER_CLK(SCU0_CLK_UART4, "uart4clk", SCU0_CLK_UART, SCU0_CLK_SEL2, 30, 1, ast2700_clk_uart_div_table), - DIVIDER_CLK(SCU0_CLK_EMMC, "emmcclk", emmcsrc_mux, - SCU0_CLK_SEL1, 12, 3, ast2700_clk_div_table2), - MUX_CLK(SCU0_CLK_PSP, "pspclk", mhpll_clk_sels, ARRAY_SIZE(mhpll_clk_sels), - SCU0_HWSTRAP1, 4, 1), - MUX_CLK(SCU0_CLK_AHBMUX, "soc0-ahbmux", mhpll_clk_sels, ARRAY_SIZE(mhpll_clk_sels), - SCU0_HWSTRAP1, 7, 1), - MUX_CLK(SCU0_CLK_UART, "soc0-uartclk", uart_clk_sels, ARRAY_SIZE(uart_clk_sels), - SCU0_CLK_SEL2, 14, 1), - MUX_CLK(SCU0_CLK_EMMCMUX, "emmcsrc-mux", emmc_clk_sels, ARRAY_SIZE(emmc_clk_sels), - SCU0_CLK_SEL1, 11, 1), - GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", soc0_mpll, + GATE_CLK(SCU0_CLK_GATE_MCLK, CLK_GATE_ASPEED, "mclk-gate", SCU0_CLK_MPLL, SCU0_CLK_STOP, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", NULL, SCU0_CLK_STOP, 1, 0), - GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", NULL, SCU0_CLK_STOP, 2, 0), - GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", NULL, SCU0_CLK_STOP, 3, 0), - GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_ECLK, CLK_GATE_ASPEED, "eclk-gate", -1, SCU0_CLK_STOP, 1, 0), + GATE_CLK(SCU0_CLK_GATE_2DCLK, CLK_GATE_ASPEED, "gclk-gate", -1, SCU0_CLK_STOP, 2, 0), + GATE_CLK(SCU0_CLK_GATE_VCLK, CLK_GATE_ASPEED, "vclk-gate", -1, SCU0_CLK_STOP, 3, 0), + GATE_CLK(SCU0_CLK_GATE_BCLK, CLK_GATE_ASPEED, "bclk-gate", -1, SCU0_CLK_STOP, 4, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_VGA0CLK, CLK_GATE_ASPEED, "vga0clk-gate", -1, SCU0_CLK_STOP, 5, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", soc0_clkin, + GATE_CLK(SCU0_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc0-refclk-gate", SCU0_CLKIN, SCU0_CLK_STOP, 6, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_PORTBUSB2CLK, CLK_GATE_ASPEED, "portb-usb2clk-gate", -1, SCU0_CLK_STOP, 7, 0), - GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", NULL, SCU0_CLK_STOP, 9, 0), - GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "uhciclk-gate", -1, SCU0_CLK_STOP, 9, 0), + GATE_CLK(SCU0_CLK_GATE_VGA1CLK, CLK_GATE_ASPEED, "vga1clk-gate", -1, SCU0_CLK_STOP, 10, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_DDRPHYCLK, CLK_GATE_ASPEED, "ddrphy-gate", -1, SCU0_CLK_STOP, 11, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_E2M0CLK, CLK_GATE_ASPEED, "e2m0clk-gate", -1, SCU0_CLK_STOP, 12, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", NULL, SCU0_CLK_STOP, 13, 0), - GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_HACCLK, CLK_GATE_ASPEED, "hacclk-gate", -1, SCU0_CLK_STOP, 13, 0), + GATE_CLK(SCU0_CLK_GATE_PORTAUSB2CLK, CLK_GATE_ASPEED, "porta-usb2clk-gate", -1, SCU0_CLK_STOP, 14, 0), - GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", uart4clk, + GATE_CLK(SCU0_CLK_GATE_UART4CLK, CLK_GATE_ASPEED, "uart4clk-gate", SCU0_CLK_UART4, SCU0_CLK_STOP, 15, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc0-sliclk-gate", -1, SCU0_CLK_STOP, 16, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_DACCLK, CLK_GATE_ASPEED, "dacclk-gate", -1, SCU0_CLK_STOP, 17, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_DP, CLK_GATE_ASPEED, "dpclk-gate", -1, SCU0_CLK_STOP, 18, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_E2M1CLK, CLK_GATE_ASPEED, "e2m1clk-gate", -1, SCU0_CLK_STOP, 19, CLK_IS_CRITICAL), - GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_CRT0CLK, CLK_GATE_ASPEED, "crt0clk-gate", -1, SCU0_CLK_STOP, 20, 0), - GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_CRT1CLK, CLK_GATE_ASPEED, "crt1clk-gate", -1, SCU0_CLK_STOP, 21, 0), - GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_ECDSACLK, CLK_GATE_ASPEED, "eccclk-gate", -1, SCU0_CLK_STOP, 23, 0), - GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_RSACLK, CLK_GATE_ASPEED, "rsaclk-gate", -1, SCU0_CLK_STOP, 24, 0), - GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_RVAS0CLK, CLK_GATE_ASPEED, "rvas0clk-gate", -1, SCU0_CLK_STOP, 25, 0), - GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_UFSCLK, CLK_GATE_ASPEED, "ufsclk-gate", -1, SCU0_CLK_STOP, 26, 0), - GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", emmcclk, + GATE_CLK(SCU0_CLK_GATE_EMMCCLK, CLK_GATE_ASPEED, "emmcclk-gate", SCU0_CLK_EMMC, SCU0_CLK_STOP, 27, 0), - GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", NULL, + GATE_CLK(SCU0_CLK_GATE_RVAS1CLK, CLK_GATE_ASPEED, "rvas1clk-gate", -1, SCU0_CLK_STOP, 28, 0), }; static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = { - FIXED_CLK(SCU1_CLKIN, "soc1-clkin", SCU_CLK_25MHZ), - PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", soc1_clkin, SCU1_HPLL_PARAM), - PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", soc1_clkin, SCU1_APLL_PARAM), - PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", soc1_clkin, SCU1_DPLL_PARAM), - PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", uxclk, SCU1_UXCLK_CTRL), - PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", huxclk, SCU1_HUXCLK_CTRL), - FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", soc1_apll, 1, 2), - FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", soc1_apll, 1, 4), - FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", huartxclk, 1, 1), - FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", huartxclk, 1, 1), - FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", soc1_apll, 1, 10), - DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", sdclk_mux, - SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", soc1_hpll, + FIXED_CLK(SCU1_CLKIN, "soc1-clkin", 25 * HZ_PER_MHZ), + PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM), + PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM), + PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM), + FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2), + FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4), + FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10), + DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2), - DIVIDER_CLK(SCU1_CLK_RMII, "rmii", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_RMII, "rmii", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table), - DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table), - DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", soc1_apll, - SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", + SCU1_CLK_APLL, SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table), + DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", SCU1_CLK_HPLL, SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", SCU1_CLK_HPLL, SCU1_CLK_SEL2, 23, 3, ast2700_clk_div_table), - MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 0, 1), - MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 1, 1), - MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 2, 1), - MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 3, 1), - MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 5, 1), - MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 6, 1), - MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 7, 1), - MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 8, 1), - MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 9, 1), - MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 10, 1), - MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 11, 1), - MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 12, 1), - MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdio_clk_sels, ARRAY_SIZE(sdio_clk_sels), - SCU1_CLK_SEL1, 13, 1), - MUX_CLK(SCU1_CLK_UXCLK, "uxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels), - SCU1_CLK_SEL2, 0, 2), - MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels), - SCU1_CLK_SEL2, 3, 2), - GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 29, 0), - GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 30, 0), - GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", NULL, + MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdclk_parent_ids, ARRAY_SIZE(sdclk_parent_ids), + sdclk_parent_hws, SCU1_CLK_SEL1, 13, 1), + MUX_CLK(SCU1_CLK_UXCLK, "uxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), + uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2), + MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), + uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2), + DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX, + SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), + PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL), + PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", SCU1_CLK_HUXCLK, SCU1_HUXCLK_CTRL), + MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 0, 1), + MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 1, 1), + MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 2, 1), + MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 3, 1), + MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 5, 1), + MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 6, 1), + MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 7, 1), + MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 8, 1), + MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 9, 1), + MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 10, 1), + MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 11, 1), + MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 12, 1), + FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", SCU1_CLK_HUARTX, 1, 1), + FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", SCU1_CLK_HUARTX, 1, 1), + GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", SCU1_CLK_RMII, + SCU1_MAC12_CLK_DLY, 29, 0), + GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", SCU1_CLK_RMII, + SCU1_MAC12_CLK_DLY, 30, 0), + GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", -1, SCU1_CLK_STOP, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", -1, SCU1_CLK_STOP, 1, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", -1, SCU1_CLK_STOP, 2, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", -1, SCU1_CLK_STOP, 3, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", sdclk, + GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", SCU1_CLK_SDCLK, SCU1_CLK_STOP, 4, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", -1, SCU1_CLK_STOP, 5, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", -1, SCU1_CLK_STOP, 6, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", -1, SCU1_CLK_STOP, 7, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", -1, SCU1_CLK_STOP, 8, 0), - GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", -1, SCU1_CLK_STOP, 9, 0), - GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", -1, SCU1_CLK_STOP, 10, 0), - GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", uart0clk, - SCU1_CLK_STOP, 11, 0), - GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", uart1clk, - SCU1_CLK_STOP, 12, 0), - GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", uart2clk, - SCU1_CLK_STOP, 13, 0), - GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", uart3clk, - SCU1_CLK_STOP, 14, 0), - GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", NULL, SCU1_CLK_STOP, 15, 0), - GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", SCU1_CLK_UART0, + SCU1_CLK_STOP, 11, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", SCU1_CLK_UART1, + SCU1_CLK_STOP, 12, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", SCU1_CLK_UART2, + SCU1_CLK_STOP, 13, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", SCU1_CLK_UART3, + SCU1_CLK_STOP, 14, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", -1, SCU1_CLK_STOP, 15, 0), + GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 16, 0), - GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 17, 0), - GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 18, 0), - GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 19, 0), - GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 20, 0), - GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 21, 0), - GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 22, 0), - GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 23, 0), - GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 24, 0), - GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 25, 0), - GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 26, 0), - GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 27, 0), - GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 28, 0), - GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 29, 0), - GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 30, 0), - GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", soc1_i3c, + GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", SCU1_CLK_I3C, SCU1_CLK_STOP, 31, 0), - GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", uart5clk, + GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", SCU1_CLK_UART5, SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", uart6clk, + GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", SCU1_CLK_UART6, SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", uart7clk, + GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", SCU1_CLK_UART7, SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", uart8clk, + GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", SCU1_CLK_UART8, SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", uart9clk, + GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", SCU1_CLK_UART9, SCU1_CLK_STOP2, 4, 0), - GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", uart10clk, + GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", SCU1_CLK_UART10, SCU1_CLK_STOP2, 5, 0), - GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", uart11clk, + GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", SCU1_CLK_UART11, SCU1_CLK_STOP2, 6, 0), - GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", uart12clk, + GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", SCU1_CLK_UART12, SCU1_CLK_STOP2, 7, 0), - GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", NULL, SCU1_CLK_STOP2, 8, 0), - GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", -1, SCU1_CLK_STOP2, 8, 0), + GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", -1, SCU1_CLK_STOP2, 9, 0), - GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", -1, SCU1_CLK_STOP2, 10, 0), - GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", -1, SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", -1, SCU1_CLK_STOP2, 12, 0), - GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", canclk, + GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", SCU1_CLK_CAN, SCU1_CLK_STOP2, 13, 0), - GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", -1, SCU1_CLK_STOP2, 14, 0), - GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", -1, SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", -1, SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", -1, SCU1_CLK_STOP2, 17, 0), - GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", -1, SCU1_CLK_STOP2, 18, 0), - GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", NULL, + GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", -1, SCU1_CLK_STOP2, 19, 0), }; -static const struct ast2700_clk_info ast2700a0_scu1_clk_info[] __initconst = { - FIXED_CLK(SCU1_CLKIN, "soc1-clkin", SCU_CLK_25MHZ), - PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", soc1_clkin, SCU1_HPLL_PARAM), - PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", soc1_clkin, SCU1_APLL_PARAM), - PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", soc1_clkin, SCU1_DPLL_PARAM), - PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", uxclk, SCU1_UXCLK_CTRL), - PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", huxclk, SCU1_HUXCLK_CTRL), - FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", soc1_apll, 1, 2), - FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", soc1_apll, 1, 4), - FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", huartxclk, 1, 1), - FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", huartxclk, 1, 1), - FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", soc1_apll, 1, 10), - DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", sdclk_mux, - SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", soc1_hpll, +static const struct ast2700_clk_info ast2755_scu1_clk_info[] __initconst = { + FIXED_CLK(SCU1_CLKIN, "soc1-clkin", 25 * HZ_PER_MHZ), + PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM), + PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM), + PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM), + FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2), + FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4), + FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10), + DIVIDER_CLK(SCU1_CLK_APB, "soc1-apb", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 18, 3, ast2700_clk_div_table2), - DIVIDER_CLK(SCU1_CLK_RMII, "rmii", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_RMII, "rmii", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 21, 3, ast2700_rmii_div_table), - DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_RGMII, "rgmii", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 25, 3, ast2700_rgmii_div_table), - DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_MACHCLK, "machclk", SCU1_CLK_HPLL, SCU1_CLK_SEL1, 29, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", soc1_apll, - SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table), - DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", soc1_hpll, + DIVIDER_CLK(SCU1_CLK_APLL_DIVN, "soc1-apll_divn", + SCU1_CLK_APLL, SCU1_CLK_SEL2, 8, 3, ast2700_clk_div_table), + DIVIDER_CLK(SCU1_CLK_AHB, "soc1-ahb", SCU1_CLK_HPLL, SCU1_CLK_SEL2, 20, 3, ast2700_clk_div_table), - MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 0, 1), - MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 1, 1), - MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 2, 1), - MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 3, 1), - MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 5, 1), - MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 6, 1), - MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 7, 1), - MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 8, 1), - MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 9, 1), - MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 10, 1), - MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 11, 1), - MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_clk_sels, ARRAY_SIZE(uartx_clk_sels), - SCU1_CLK_SEL1, 12, 1), - MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdio_clk_sels, ARRAY_SIZE(sdio_clk_sels), - SCU1_CLK_SEL1, 13, 1), - MUX_CLK(SCU1_CLK_UXCLK, "uxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels), - SCU1_CLK_SEL2, 0, 2), - MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", ux_clk_sels, ARRAY_SIZE(ux_clk_sels), - SCU1_CLK_SEL2, 3, 2), - GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 29, 0), - GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", rmii, SCU1_MAC12_CLK_DLY, 30, 0), - GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", NULL, + DIVIDER_CLK(SCU1_CLK_I3C, "soc1-i3c", SCU1_CLK_HPLL, + SCU1_CLK_SEL2, 23, 3, ast2700_clk_div_table), + MUX_CLK(SCU1_CLK_SDMUX, "sdclk-mux", sdclk_parent_ids, ARRAY_SIZE(sdclk_parent_ids), + sdclk_parent_hws, SCU1_CLK_SEL1, 13, 1), + MUX_CLK(SCU1_CLK_UXCLK, "uxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), + uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2), + MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), + uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2), + DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX, + SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), + PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL), + PLL_CLK(SCU1_CLK_HUARTX, CLK_UART_PLL, "huartxclk", SCU1_CLK_HUXCLK, SCU1_HUXCLK_CTRL), + MUX_CLK(SCU1_CLK_UART0, "uart0clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 0, 1), + MUX_CLK(SCU1_CLK_UART1, "uart1clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 1, 1), + MUX_CLK(SCU1_CLK_UART2, "uart2clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 2, 1), + MUX_CLK(SCU1_CLK_UART3, "uart3clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 3, 1), + MUX_CLK(SCU1_CLK_UART5, "uart5clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 5, 1), + MUX_CLK(SCU1_CLK_UART6, "uart6clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 6, 1), + MUX_CLK(SCU1_CLK_UART7, "uart7clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 7, 1), + MUX_CLK(SCU1_CLK_UART8, "uart8clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 8, 1), + MUX_CLK(SCU1_CLK_UART9, "uart9clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 9, 1), + MUX_CLK(SCU1_CLK_UART10, "uart10clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 10, 1), + MUX_CLK(SCU1_CLK_UART11, "uart11clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 11, 1), + MUX_CLK(SCU1_CLK_UART12, "uart12clk", uartx_parent_ids, ARRAY_SIZE(uartx_parent_ids), + uartx_parent_hws, SCU1_CLK_SEL1, 12, 1), + FIXED_FACTOR_CLK(SCU1_CLK_UART13, "uart13clk", SCU1_CLK_HUARTX, 1, 1), + FIXED_FACTOR_CLK(SCU1_CLK_UART14, "uart14clk", SCU1_CLK_HUARTX, 1, 1), + GATE_CLK(SCU1_CLK_MAC0RCLK, CLK_GATE, "mac0rclk-gate", SCU1_CLK_RMII, + SCU1_MAC12_CLK_DLY, 29, 0), + GATE_CLK(SCU1_CLK_MAC1RCLK, CLK_GATE, "mac1rclk-gate", SCU1_CLK_RMII, + SCU1_MAC12_CLK_DLY, 30, 0), + GATE_CLK(SCU1_CLK_GATE_LCLK0, CLK_GATE_ASPEED, "lclk0-gate", -1, SCU1_CLK_STOP, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", NULL, - SCU1_CLK_STOP, 1, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", NULL, - SCU1_CLK_STOP, 2, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", NULL, - SCU1_CLK_STOP, 3, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", sdclk, - SCU1_CLK_STOP, 4, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", NULL, - SCU1_CLK_STOP, 5, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", NULL, - SCU1_CLK_STOP, 6, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", NULL, - SCU1_CLK_STOP, 7, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", NULL, - SCU1_CLK_STOP, 8, 0), - GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", NULL, - SCU1_CLK_STOP, 9, 0), - GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", NULL, - SCU1_CLK_STOP, 10, 0), - GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", uart0clk, - SCU1_CLK_STOP, 11, 0), - GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", uart1clk, - SCU1_CLK_STOP, 12, 0), - GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", uart2clk, - SCU1_CLK_STOP, 13, 0), - GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", uart3clk, - SCU1_CLK_STOP, 14, 0), - GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", NULL, SCU1_CLK_STOP, 15, 0), - GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", soc1_ahb, - SCU1_CLK_STOP, 16, 0), - GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", soc1_ahb, - SCU1_CLK_STOP, 17, 0), - GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", soc1_ahb, - SCU1_CLK_STOP, 18, 0), - GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", soc1_ahb, - SCU1_CLK_STOP, 19, 0), - GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", soc1_ahb, - SCU1_CLK_STOP, 20, 0), - GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", soc1_ahb, - SCU1_CLK_STOP, 21, 0), - GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", soc1_ahb, - SCU1_CLK_STOP, 22, 0), - GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", soc1_ahb, - SCU1_CLK_STOP, 23, 0), - GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", soc1_ahb, - SCU1_CLK_STOP, 24, 0), - GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", soc1_ahb, - SCU1_CLK_STOP, 25, 0), - GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", soc1_ahb, - SCU1_CLK_STOP, 26, 0), - GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", soc1_ahb, - SCU1_CLK_STOP, 27, 0), - GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", soc1_ahb, - SCU1_CLK_STOP, 28, 0), - GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", soc1_ahb, - SCU1_CLK_STOP, 29, 0), - GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", soc1_ahb, - SCU1_CLK_STOP, 30, 0), - GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", soc1_ahb, - SCU1_CLK_STOP, 31, 0), - GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", uart5clk, - SCU1_CLK_STOP2, 0, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", uart6clk, - SCU1_CLK_STOP2, 1, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", uart7clk, - SCU1_CLK_STOP2, 2, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", uart8clk, - SCU1_CLK_STOP2, 3, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", uart9clk, - SCU1_CLK_STOP2, 4, 0), - GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", uart10clk, - SCU1_CLK_STOP2, 5, 0), - GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", uart11clk, - SCU1_CLK_STOP2, 6, 0), - GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", uart12clk, - SCU1_CLK_STOP2, 7, 0), - GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", NULL, SCU1_CLK_STOP2, 8, 0), - GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", NULL, - SCU1_CLK_STOP2, 9, 0), - GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", NULL, - SCU1_CLK_STOP2, 10, 0), - GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", NULL, - SCU1_CLK_STOP2, 11, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", NULL, - SCU1_CLK_STOP2, 12, 0), - GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", canclk, - SCU1_CLK_STOP2, 13, 0), - GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", canclk, - SCU1_CLK_STOP2, 14, 0), - GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", canclk, - SCU1_CLK_STOP2, 15, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", NULL, - SCU1_CLK_STOP2, 16, CLK_IS_CRITICAL), - GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", NULL, - SCU1_CLK_STOP2, 17, 0), - GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", NULL, - SCU1_CLK_STOP2, 18, 0), - GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", NULL, - SCU1_CLK_STOP2, 19, 0), -}; + GATE_CLK(SCU1_CLK_GATE_LCLK1, CLK_GATE_ASPEED, "lclk1-gate", -1, + AST2755_SCU1_CLK_STOP, 1, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_ESPI0CLK, CLK_GATE_ASPEED, "espi0clk-gate", -1, + AST2755_SCU1_CLK_STOP, 2, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_ESPI1CLK, CLK_GATE_ASPEED, "espi1clk-gate", -1, + AST2755_SCU1_CLK_STOP, 3, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_SDCLK, CLK_GATE_ASPEED, "sdclk-gate", SCU1_CLK_SDCLK, + AST2755_SCU1_CLK_STOP, 4, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_IPEREFCLK, CLK_GATE_ASPEED, "soc1-iperefclk-gate", -1, + AST2755_SCU1_CLK_STOP, 5, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_REFCLK, CLK_GATE_ASPEED, "soc1-refclk-gate", -1, + AST2755_SCU1_CLK_STOP, 6, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_LPCHCLK, CLK_GATE_ASPEED, "lpchclk-gate", -1, + AST2755_SCU1_CLK_STOP, 7, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_MAC0CLK, CLK_GATE_ASPEED, "mac0clk-gate", -1, + AST2755_SCU1_CLK_STOP, 8, 0), + GATE_CLK(SCU1_CLK_GATE_MAC1CLK, CLK_GATE_ASPEED, "mac1clk-gate", -1, + AST2755_SCU1_CLK_STOP, 9, 0), + GATE_CLK(SCU1_CLK_GATE_MAC2CLK, CLK_GATE_ASPEED, "mac2clk-gate", -1, + AST2755_SCU1_CLK_STOP, 10, 0), + GATE_CLK(SCU1_CLK_GATE_UART0CLK, CLK_GATE_ASPEED, "uart0clk-gate", SCU1_CLK_UART0, + AST2755_SCU1_CLK_STOP, 11, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART1CLK, CLK_GATE_ASPEED, "uart1clk-gate", SCU1_CLK_UART1, + AST2755_SCU1_CLK_STOP, 12, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART2CLK, CLK_GATE_ASPEED, "uart2clk-gate", SCU1_CLK_UART2, + AST2755_SCU1_CLK_STOP, 13, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART3CLK, CLK_GATE_ASPEED, "uart3clk-gate", SCU1_CLK_UART3, + AST2755_SCU1_CLK_STOP, 14, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_I2CCLK, CLK_GATE_ASPEED, "i2cclk-gate", -1, SCU1_CLK_STOP, 15, 0), + GATE_CLK(SCU1_CLK_GATE_I3C0CLK, CLK_GATE_ASPEED, "i3c0clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 16, 0), + GATE_CLK(SCU1_CLK_GATE_I3C1CLK, CLK_GATE_ASPEED, "i3c1clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 17, 0), + GATE_CLK(SCU1_CLK_GATE_I3C2CLK, CLK_GATE_ASPEED, "i3c2clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 18, 0), + GATE_CLK(SCU1_CLK_GATE_I3C3CLK, CLK_GATE_ASPEED, "i3c3clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 19, 0), + GATE_CLK(SCU1_CLK_GATE_I3C4CLK, CLK_GATE_ASPEED, "i3c4clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 20, 0), + GATE_CLK(SCU1_CLK_GATE_I3C5CLK, CLK_GATE_ASPEED, "i3c5clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 21, 0), + GATE_CLK(SCU1_CLK_GATE_I3C6CLK, CLK_GATE_ASPEED, "i3c6clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 22, 0), + GATE_CLK(SCU1_CLK_GATE_I3C7CLK, CLK_GATE_ASPEED, "i3c7clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 23, 0), + GATE_CLK(SCU1_CLK_GATE_I3C8CLK, CLK_GATE_ASPEED, "i3c8clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 24, 0), + GATE_CLK(SCU1_CLK_GATE_I3C9CLK, CLK_GATE_ASPEED, "i3c9clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 25, 0), + GATE_CLK(SCU1_CLK_GATE_I3C10CLK, CLK_GATE_ASPEED, "i3c10clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 26, 0), + GATE_CLK(SCU1_CLK_GATE_I3C11CLK, CLK_GATE_ASPEED, "i3c11clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 27, 0), + GATE_CLK(SCU1_CLK_GATE_I3C12CLK, CLK_GATE_ASPEED, "i3c12clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 28, 0), + GATE_CLK(SCU1_CLK_GATE_I3C13CLK, CLK_GATE_ASPEED, "i3c13clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 29, 0), + GATE_CLK(SCU1_CLK_GATE_I3C14CLK, CLK_GATE_ASPEED, "i3c14clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 30, 0), + GATE_CLK(SCU1_CLK_GATE_I3C15CLK, CLK_GATE_ASPEED, "i3c15clk-gate", SCU1_CLK_I3C, + AST2755_SCU1_CLK_STOP, 31, 0), + GATE_CLK(SCU1_CLK_GATE_UART5CLK, CLK_GATE_ASPEED, "uart5clk-gate", SCU1_CLK_UART5, + AST2755_SCU1_CLK_STOP, 0, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART6CLK, CLK_GATE_ASPEED, "uart6clk-gate", SCU1_CLK_UART6, + AST2755_SCU1_CLK_STOP, 1, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART7CLK, CLK_GATE_ASPEED, "uart7clk-gate", SCU1_CLK_UART7, + AST2755_SCU1_CLK_STOP, 2, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART8CLK, CLK_GATE_ASPEED, "uart8clk-gate", SCU1_CLK_UART8, + AST2755_SCU1_CLK_STOP, 3, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UART9CLK, CLK_GATE_ASPEED, "uart9clk-gate", SCU1_CLK_UART9, + AST2755_SCU1_CLK_STOP, 4, 0), + GATE_CLK(SCU1_CLK_GATE_UART10CLK, CLK_GATE_ASPEED, "uart10clk-gate", SCU1_CLK_UART10, + AST2755_SCU1_CLK_STOP, 5, 0), + GATE_CLK(SCU1_CLK_GATE_UART11CLK, CLK_GATE_ASPEED, "uart11clk-gate", SCU1_CLK_UART11, + AST2755_SCU1_CLK_STOP, 6, 0), + GATE_CLK(SCU1_CLK_GATE_UART12CLK, CLK_GATE_ASPEED, "uart12clk-gate", SCU1_CLK_UART12, + AST2755_SCU1_CLK_STOP, 7, 0), + GATE_CLK(SCU1_CLK_GATE_FSICLK, CLK_GATE_ASPEED, "fsiclk-gate", -1, SCU1_CLK_STOP2, 8, 0), + GATE_CLK(SCU1_CLK_GATE_LTPIPHYCLK, CLK_GATE_ASPEED, "ltpiphyclk-gate", -1, + AST2755_SCU1_CLK_STOP, 9, 0), + GATE_CLK(SCU1_CLK_GATE_LTPICLK, CLK_GATE_ASPEED, "ltpiclk-gate", -1, + AST2755_SCU1_CLK_STOP, 10, 0), + GATE_CLK(SCU1_CLK_GATE_VGALCLK, CLK_GATE_ASPEED, "vgalclk-gate", -1, + AST2755_SCU1_CLK_STOP, 11, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_UHCICLK, CLK_GATE_ASPEED, "usbuartclk-gate", -1, + AST2755_SCU1_CLK_STOP, 12, 0), + GATE_CLK(SCU1_CLK_GATE_CANCLK, CLK_GATE_ASPEED, "canclk-gate", SCU1_CLK_CAN, + AST2755_SCU1_CLK_STOP, 13, 0), + GATE_CLK(SCU1_CLK_GATE_PCICLK, CLK_GATE_ASPEED, "pciclk-gate", -1, + AST2755_SCU1_CLK_STOP, 14, 0), + GATE_CLK(SCU1_CLK_GATE_SLICLK, CLK_GATE_ASPEED, "soc1-sliclk-gate", -1, + AST2755_SCU1_CLK_STOP, 15, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_E2MCLK, CLK_GATE_ASPEED, "soc1-e2m-gate", -1, + AST2755_SCU1_CLK_STOP, 16, CLK_IS_CRITICAL), + GATE_CLK(SCU1_CLK_GATE_PORTCUSB2CLK, CLK_GATE_ASPEED, "portcusb2-gate", -1, + AST2755_SCU1_CLK_STOP, 17, 0), + GATE_CLK(SCU1_CLK_GATE_PORTDUSB2CLK, CLK_GATE_ASPEED, "portdusb2-gate", -1, + AST2755_SCU1_CLK_STOP, 18, 0), + GATE_CLK(SCU1_CLK_GATE_LTPI1TXCLK, CLK_GATE_ASPEED, "ltp1tx-gate", -1, + AST2755_SCU1_CLK_STOP, 19, 0), +}; + +static struct clk_hw *ast2700_clk_hw_register_fixed_display(void __iomem *reg, const char *name, + struct ast2700_clk_ctrl *clk_ctrl) +{ + unsigned int mult, div, r, n; + u32 xdclk; + u32 val; + + val = readl(clk_ctrl->base + SCU0_CLK_SEL2); + if (val & BIT(29)) + xdclk = 800 * HZ_PER_MHZ; + else + xdclk = 1000 * HZ_PER_MHZ; + + val = readl(reg); + r = val & GENMASK(15, 0); + n = (val >> 16) & GENMASK(15, 0); + mult = r; + div = 2 * n; + + return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div); +} static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg, - const char *name, const char *parent_name, + const char *name, const struct clk_hw *parent_hw, struct ast2700_clk_ctrl *clk_ctrl) { unsigned int mult, div; @@ -1095,15 +900,16 @@ static struct clk_hw *ast2700_clk_hw_register_hpll(void __iomem *reg, u32 p = (val >> 19) & 0xf; mult = (m + 1) / (2 * (n + 1)); - div = (p + 1); + div = p + 1; } } - return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, parent_name, 0, mult, div); + return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, + parent_hw, 0, mult, div); } static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg, - const char *name, const char *parent_name, + const char *name, const struct clk_hw *parent_hw, struct ast2700_clk_ctrl *clk_ctrl) { int scu = clk_ctrl->clk_data->scu; @@ -1121,45 +927,24 @@ static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem *reg if (scu) { mult = (m + 1) / (n + 1); - div = (p + 1); + div = p + 1; } else { if (clk_idx == SCU0_CLK_MPLL) { mult = m / (n + 1); - div = (p + 1); + div = p + 1; } else { mult = (m + 1) / (2 * (n + 1)); - div = (p + 1); + div = p + 1; } } } - return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, parent_name, 0, mult, div); + return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, + parent_hw, 0, mult, div); } -static struct clk_hw *ast2700_clk_hw_register_dclk(void __iomem *reg, const char *name, - struct ast2700_clk_ctrl *clk_ctrl) -{ - unsigned int mult, div, r, n; - u32 xdclk; - u32 val; - - val = readl(clk_ctrl->base + 0x284); - if (val & BIT(29)) - xdclk = 800 * HZ_PER_MHZ; - else - xdclk = 1000 * HZ_PER_MHZ; - - val = readl(reg); - r = val & GENMASK(15, 0); - n = (val >> 16) & GENMASK(15, 0); - mult = r; - div = 2 * n; - - return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, name, NULL, 0, (xdclk * mult) / div); -} - -static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, - const char *name, const char *parent_name, +static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, const char *name, + const struct clk_hw *parent_hw, struct ast2700_clk_ctrl *clk_ctrl) { unsigned int mult, div; @@ -1170,12 +955,12 @@ static struct clk_hw *ast2700_clk_hw_register_uartpll(void __iomem *reg, mult = r; div = n * 2; - return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, - parent_name, 0, mult, div); + return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, + parent_hw, 0, mult, div); } static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *reg, - const char *name, const char *parent_name, + const char *name, const struct clk_hw *parent_hw, struct ast2700_clk_ctrl *clk_ctrl) { u32 div = 0; @@ -1191,8 +976,8 @@ static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void __iomem *re return ERR_PTR(-EINVAL); } - return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, name, - parent_name, 0, 1, div); + return devm_clk_hw_register_fixed_factor_parent_hw(clk_ctrl->dev, name, + parent_hw, 0, 1, div); } static int ast2700_clk_is_enabled(struct clk_hw *hw) @@ -1233,13 +1018,13 @@ static const struct clk_ops ast2700_clk_gate_ops = { }; static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const char *name, - const struct clk_parent_data *parent, + const struct clk_hw *parent_hw, void __iomem *reg, u8 clock_idx, - unsigned long clk_gate_flags, spinlock_t *lock) + unsigned long flags, spinlock_t *lock) { + struct clk_init_data init; struct clk_gate *gate; struct clk_hw *hw; - struct clk_init_data init; int ret = -EINVAL; gate = kzalloc(sizeof(*gate), GFP_KERNEL); @@ -1248,9 +1033,11 @@ static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const cha init.name = name; init.ops = &ast2700_clk_gate_ops; - init.flags = clk_gate_flags; - init.parent_names = parent ? &parent->name : NULL; - init.num_parents = parent ? 1 : 0; + init.flags = flags; + init.parent_names = NULL; + init.parent_hws = parent_hw ? &parent_hw : NULL; + init.parent_data = NULL; + init.num_parents = parent_hw ? 1 : 0; gate->reg = reg; gate->bit_idx = clock_idx; @@ -1275,7 +1062,14 @@ static void ast2700_soc1_configure_mac01_clk(struct ast2700_clk_ctrl *clk_ctrl) u32 reg[3]; int ret; - reg[0] = AST2700_DEF_MAC12_DELAY_1G; + if (readl(clk_ctrl->base) & REVISION_ID) { + if ((readl(clk_ctrl->base + SCU1_MAC12_CLK_DLY) & GENMASK(25, 0)) == 0) + reg[0] = AST2700_DEF_MAC12_DELAY_1G_A1; + else + reg[0] = readl(clk_ctrl->base + SCU1_MAC12_CLK_DLY); + } else { + reg[0] = AST2700_DEF_MAC12_DELAY_1G_A0; + } reg[1] = AST2700_DEF_MAC12_DELAY_100M; reg[2] = AST2700_DEF_MAC12_DELAY_10M; @@ -1319,20 +1113,29 @@ static void ast2700_soc1_configure_mac01_clk(struct ast2700_clk_ctrl *clk_ctrl) static void ast2700_soc1_configure_i3c_clk(struct ast2700_clk_ctrl *clk_ctrl) { - if (readl(clk_ctrl->base + SCU1_REVISION_ID) & REVISION_ID) + if (readl(clk_ctrl->base) & REVISION_ID) { + u32 val; + /* I3C 250MHz = HPLL/4 */ - writel((readl(clk_ctrl->base + SCU1_CLK_SEL2) & - ~SCU1_CLK_I3C_DIV_MASK) | - FIELD_PREP(SCU1_CLK_I3C_DIV_MASK, - SCU1_CLK_I3C_DIV(4)), - clk_ctrl->base + SCU1_CLK_SEL2); + val = readl(clk_ctrl->base + SCU1_CLK_SEL2) & ~SCU1_CLK_I3C_DIV_MASK; + val |= FIELD_PREP(SCU1_CLK_I3C_DIV_MASK, SCU1_CLK_I3C_DIV(4)); + writel(val, clk_ctrl->base + SCU1_CLK_SEL2); + } +} + +static inline const struct clk_hw *get_parent_hw_or_null(struct clk_hw **hws, int idx) +{ + if (idx < 0) + return NULL; + else + return hws[idx]; } static int ast2700_soc_clk_probe(struct platform_device *pdev) { - struct ast2700_clk_data *clk_data; - struct ast2700_clk_ctrl *clk_ctrl; + const struct ast2700_clk_data *clk_data; struct clk_hw_onecell_data *clk_hw_data; + struct ast2700_clk_ctrl *clk_ctrl; struct device *dev = &pdev->dev; u32 uart_clk_source = 0; void __iomem *clk_base; @@ -1385,86 +1188,102 @@ static int ast2700_soc_clk_probe(struct platform_device *pdev) for (i = 0; i < clk_data->nr_clks; i++) { const struct ast2700_clk_info *clk = &clk_data->clk_info[i]; - void __iomem *reg = clk_ctrl->base + clk->reg; + const struct clk_hw *phw = NULL; + unsigned int id = clk->id; + void __iomem *reg = NULL; + + if (id >= clk_hw_data->num || hws[id]) { + dev_err(dev, "clk id %u invalid for %s\n", id, clk->name); + return -EINVAL; + } if (clk->type == CLK_FIXED) { const struct ast2700_clk_fixed_rate_data *fixed_rate = &clk->data.rate; - hws[i] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0, - fixed_rate->fixed_rate); + hws[id] = devm_clk_hw_register_fixed_rate(dev, clk->name, NULL, 0, + fixed_rate->fixed_rate); } else if (clk->type == CLK_FIXED_FACTOR) { const struct ast2700_clk_fixed_factor_data *factor = &clk->data.factor; - hws[i] = devm_clk_hw_register_fixed_factor(dev, clk->name, - factor->parent->name, - 0, factor->mult, factor->div); - } else if (clk->type == DCLK_FIXED) { - const struct ast2700_clk_pll_data *pll = &clk->data.pll; + phw = hws[factor->parent_id]; + hws[id] = devm_clk_hw_register_fixed_factor_parent_hw(dev, clk->name, + phw, 0, factor->mult, + factor->div); + } else if (clk->type == CLK_FIXED_DISPLAY) { + reg = clk_ctrl->base + clk->data.display_rate.reg; - reg = clk_ctrl->base + pll->reg; - hws[i] = ast2700_clk_hw_register_dclk(reg, clk->name, clk_ctrl); + hws[id] = ast2700_clk_hw_register_fixed_display(reg, clk->name, clk_ctrl); } else if (clk->type == CLK_HPLL) { const struct ast2700_clk_pll_data *pll = &clk->data.pll; reg = clk_ctrl->base + pll->reg; - hws[i] = ast2700_clk_hw_register_hpll(reg, clk->name, - pll->parent->name, clk_ctrl); + phw = hws[pll->parent_id]; + hws[id] = ast2700_clk_hw_register_hpll(reg, clk->name, phw, clk_ctrl); } else if (clk->type == CLK_PLL) { const struct ast2700_clk_pll_data *pll = &clk->data.pll; reg = clk_ctrl->base + pll->reg; - hws[i] = ast2700_clk_hw_register_pll(i, reg, clk->name, - pll->parent->name, clk_ctrl); + phw = hws[pll->parent_id]; + hws[id] = ast2700_clk_hw_register_pll(id, reg, clk->name, phw, clk_ctrl); } else if (clk->type == CLK_UART_PLL) { const struct ast2700_clk_pll_data *pll = &clk->data.pll; reg = clk_ctrl->base + pll->reg; - hws[i] = ast2700_clk_hw_register_uartpll(reg, clk->name, - pll->parent->name, clk_ctrl); + phw = hws[pll->parent_id]; + hws[id] = ast2700_clk_hw_register_uartpll(reg, clk->name, phw, clk_ctrl); } else if (clk->type == CLK_MUX) { const struct ast2700_clk_mux_data *mux = &clk->data.mux; reg = clk_ctrl->base + mux->reg; - hws[i] = devm_clk_hw_register_mux_parent_data_table(dev, clk->name, - mux->parents, - mux->num_parents, 0, - reg, mux->bit_shift, - mux->bit_width, 0, - NULL, &clk_ctrl->lock); + for (int j = 0; j < mux->num_parents; j++) { + unsigned int pid = mux->parent_ids[j]; + + mux->parent_hws[j] = hws[pid]; + } + + hws[id] = devm_clk_hw_register_mux_parent_hws(dev, clk->name, + mux->parent_hws, + mux->num_parents, 0, + reg, mux->bit_shift, + mux->bit_width, 0, + &clk_ctrl->lock); } else if (clk->type == CLK_MISC) { - const struct ast2700_clk_pll_data *misc = &clk->data.pll; + const struct ast2700_clk_pll_data *pll = &clk->data.pll; - reg = clk_ctrl->base + misc->reg; - hws[i] = ast2700_clk_hw_register_misc(i, reg, clk->name, - misc->parent->name, clk_ctrl); + reg = clk_ctrl->base + pll->reg; + phw = hws[pll->parent_id]; + hws[id] = ast2700_clk_hw_register_misc(id, reg, clk->name, phw, clk_ctrl); } else if (clk->type == CLK_DIVIDER) { - const struct ast2700_clk_div_data *div = &clk->data.div; - - reg = clk_ctrl->base + div->reg; - hws[i] = devm_clk_hw_register_divider_table(dev, clk->name, - div->parent->name, 0, - reg, div->bit_shift, - div->bit_width, 0, - div->div_table, - &clk_ctrl->lock); + const struct ast2700_clk_div_data *divider = &clk->data.div; + + reg = clk_ctrl->base + divider->reg; + phw = hws[divider->parent_id]; + hws[id] = clk_hw_register_divider_table_parent_hw(dev, clk->name, + phw, + 0, reg, + divider->bit_shift, + divider->bit_width, 0, + divider->div_table, + &clk_ctrl->lock); } else if (clk->type == CLK_GATE_ASPEED) { const struct ast2700_clk_gate_data *gate = &clk->data.gate; + phw = get_parent_hw_or_null(hws, gate->parent_id); reg = clk_ctrl->base + gate->reg; - hws[i] = ast2700_clk_hw_register_gate(dev, clk->name, gate->parent, - reg, gate->bit, gate->flags, 0); - + hws[id] = ast2700_clk_hw_register_gate(dev, clk->name, phw, reg, gate->bit, + gate->flags, &clk_ctrl->lock); } else { const struct ast2700_clk_gate_data *gate = &clk->data.gate; + phw = get_parent_hw_or_null(hws, gate->parent_id); reg = clk_ctrl->base + gate->reg; - hws[i] = devm_clk_hw_register_gate_parent_data(dev, clk->name, gate->parent, - 0, reg, clk->clk_idx, 0, - &clk_ctrl->lock); + hws[id] = devm_clk_hw_register_gate_parent_hw(dev, clk->name, phw, + gate->flags, reg, gate->bit, + 0, &clk_ctrl->lock); } - if (IS_ERR(hws[i])) - return PTR_ERR(hws[i]); + if (IS_ERR(hws[id])) + return PTR_ERR(hws[id]); } ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data); @@ -1476,33 +1295,26 @@ static int ast2700_soc_clk_probe(struct platform_device *pdev) static const struct ast2700_clk_data ast2700_clk0_data = { .scu = 0, - .nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info), .clk_info = ast2700_scu0_clk_info, -}; - -static const struct ast2700_clk_data ast2700a0_clk0_data = { - .scu = 0, - .nr_clks = ARRAY_SIZE(ast2700a0_scu0_clk_info), - .clk_info = ast2700a0_scu0_clk_info, + .nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info), }; static const struct ast2700_clk_data ast2700_clk1_data = { .scu = 1, - .nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info), .clk_info = ast2700_scu1_clk_info, + .nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info), }; -static const struct ast2700_clk_data ast2700a0_clk1_data = { - .scu = 1, - .nr_clks = ARRAY_SIZE(ast2700a0_scu1_clk_info), - .clk_info = ast2700a0_scu1_clk_info, +static const struct ast2700_clk_data ast2755_clk1_data = { + .scu = 2, + .clk_info = ast2755_scu1_clk_info, + .nr_clks = ARRAY_SIZE(ast2755_scu1_clk_info), }; static const struct of_device_id ast2700_scu_match[] = { { .compatible = "aspeed,ast2700-scu0", .data = &ast2700_clk0_data }, - { .compatible = "aspeed,ast2700a0-scu0", .data = &ast2700a0_clk0_data }, { .compatible = "aspeed,ast2700-scu1", .data = &ast2700_clk1_data }, - { .compatible = "aspeed,ast2700a0-scu1", .data = &ast2700a0_clk1_data }, + { .compatible = "aspeed,ast2755-scu1", .data = &ast2755_clk1_data }, { /* sentinel */ } }; diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 110e99b86a66a3..918af2430cd743 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -528,6 +528,15 @@ config EDAC_ASPEED First, ECC must be configured in the bootloader. Then, this driver will expose error counters via the EDAC kernel framework. +config EDAC_AST2700 + tristate "Aspeed AST2700 BMC SoC" + depends on ARCH_ASPEED + help + Support for error detection and correction on the Aspeed AST2700 + + First, ECC must be configured in the bootloader. Then, this driver + will expose error counters via the EDAC kernel framework. + config EDAC_BLUEFIELD tristate "Mellanox BlueField Memory ECC" depends on ARM64 && ((MELLANOX_PLATFORM && ACPI) || COMPILE_TEST) diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 446364264e2b18..1224da0e8e54d8 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o +obj-$(CONFIG_EDAC_AST2700) += edac_ast2700.o obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o obj-$(CONFIG_EDAC_NPCM) += npcm_edac.o diff --git a/drivers/edac/edac_ast2700.c b/drivers/edac/edac_ast2700.c new file mode 100644 index 00000000000000..26f45bb60f0098 --- /dev/null +++ b/drivers/edac/edac_ast2700.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018, 2019 Cisco Systems + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "edac_module.h" + +#define DRV_NAME "aspeed-edac" + +#define DRAMC_PROT 0x00 /* protection key register */ +#define DRAMC_INT_STS 0x04 /* interrupt status register */ +#define INT_STS_ECC_REC BIT(5) /* ECC recoverable error interrupt */ +#define INT_STS_ECC_ERR BIT(4) /* ECC error interrupt */ +#define DRAMC_INT_CLR 0x08 /* interrupt clear register */ +#define DRAMC_INT_MASK 0x0c /* interrupt mask register */ +#define DRAMC_MCFG 0x10 /* main configuration register */ +#define MCFG_ECC_ENABLE BIT(6) +#define MCFG_DRAM_SIZE_MASK GENMASK(5, 4) /* 2=1GB, 3=2GB, 4=4GB, 5=8GB */ +#define MCFG_DRAM_SIZE_SHIFT (2) +#define MCFG_DRAM_TYPE BIT(0) /* 0=DDR4, 1=DDR5 */ + +#define DRAMC_ECC_STS 0x78 /* ECC status register */ +#define ECC_STS_REC_CNT_MASK GENMASK(15, 8) /* recoverable error count */ +#define ECC_STS_REC_CNT_SHIFT (8) +#define ECC_STS_UNREC_CNT_MASK GENMASK(7, 0) /* unrecoverable error count */ +#define ECC_STS_UNREC_CNT_SHIFT (0) +#define DRAMC_ECC_FAIL_ADDR 0x7c /* ECC fail address register */ + +static struct regmap *aspeed_regmap; + +static int regmap_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_reg_read(void *context, unsigned int reg, unsigned int *val) +{ + void __iomem *regs = (void __iomem *)context; + + *val = readl(regs + reg); + + return 0; +} + +static bool regmap_is_volatile(struct device *dev, unsigned int reg) +{ + return 1; +} + +static const struct regmap_config aspeed_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = DRAMC_ECC_FAIL_ADDR, + .reg_write = regmap_reg_write, + .reg_read = regmap_reg_read, + .volatile_reg = regmap_is_volatile, + .fast_io = true, +}; + +static void count_rec(struct mem_ctl_info *mci, u8 rec_cnt, u32 rec_addr) +{ + struct csrow_info *csrow = mci->csrows[0]; + u32 page, offset, syndrome; + + if (!rec_cnt) + return; + + /* report first few errors (if there are) */ + /* note: no addresses are recorded */ + if (rec_cnt > 1) { + /* page, offset and syndrome are not available */ + page = 0; + offset = 0; + syndrome = 0; + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, rec_cnt - 1, + page, offset, syndrome, 0, 0, -1, + "address(es) not available", ""); + } + + /* report last error */ + /* note: rec_addr is the last recoverable error addr */ + page = rec_addr >> PAGE_SHIFT; + offset = rec_addr & ~PAGE_MASK; + /* syndrome is not available */ + syndrome = 0; + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + csrow->first_page + page, offset, syndrome, + 0, 0, -1, "", ""); +} + +static void count_un_rec(struct mem_ctl_info *mci, u8 un_rec_cnt, + u32 un_rec_addr) +{ + struct csrow_info *csrow = mci->csrows[0]; + u32 page, offset, syndrome; + + if (!un_rec_cnt) + return; + + /* report 1. error */ + /* note: un_rec_addr is the first unrecoverable error addr */ + page = un_rec_addr >> PAGE_SHIFT; + offset = un_rec_addr & ~PAGE_MASK; + /* syndrome is not available */ + syndrome = 0; + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + csrow->first_page + page, offset, syndrome, + 0, 0, -1, "", ""); + + /* report further errors (if there are) */ + /* note: no addresses are recorded */ + if (un_rec_cnt > 1) { + /* page, offset and syndrome are not available */ + page = 0; + offset = 0; + syndrome = 0; + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, un_rec_cnt - 1, + page, offset, syndrome, 0, 0, -1, + "address(es) not available", ""); + } +} + +static irqreturn_t mcr_isr(int irq, void *arg) +{ + struct mem_ctl_info *mci = arg; + u32 reg, ecc_sts, ecc_fail_addr; + u16 rec_cnt, un_rec_cnt; + + regmap_read(aspeed_regmap, DRAMC_INT_STS, ®); + + regmap_read(aspeed_regmap, DRAMC_ECC_STS, &ecc_sts); + + /* collect data about recoverable and unrecoverable errors */ + rec_cnt = (ecc_sts & ECC_STS_REC_CNT_MASK) >> ECC_STS_REC_CNT_SHIFT; + un_rec_cnt = (ecc_sts & ECC_STS_UNREC_CNT_MASK) >> ECC_STS_UNREC_CNT_SHIFT; + + regmap_read(aspeed_regmap, DRAMC_ECC_FAIL_ADDR, &ecc_fail_addr); + + /* clear interrupt flags */ + regmap_update_bits(aspeed_regmap, DRAMC_INT_CLR, + reg, reg); + + /* process recoverable and unrecoverable errors */ + count_rec(mci, rec_cnt, ecc_fail_addr); + count_un_rec(mci, un_rec_cnt, ecc_fail_addr); + + return IRQ_HANDLED; +} + +static int config_irq(void *ctx, struct platform_device *pdev) +{ + int irq; + int rc; + + /* register interrupt handler */ + irq = platform_get_irq(pdev, 0); + dev_dbg(&pdev->dev, "got irq %d\n", irq); + if (irq < 0) + return irq; + + rc = devm_request_irq(&pdev->dev, irq, mcr_isr, IRQF_TRIGGER_HIGH, + DRV_NAME, ctx); + if (rc) { + dev_err(&pdev->dev, "unable to request irq %d\n", irq); + return rc; + } + + /* enable interrupts */ + regmap_clear_bits(aspeed_regmap, DRAMC_INT_MASK, + INT_STS_ECC_REC | INT_STS_ECC_ERR); + + return 0; +} + +static int init_csrows(struct mem_ctl_info *mci) +{ + struct csrow_info *csrow = mci->csrows[0]; + u32 nr_pages, dram_type; + struct dimm_info *dimm; + struct device_node *np; + struct resource r; + u32 reg04; + int rc; + + pr_info("%s: initializing csrows\n", DRV_NAME); + + /* retrieve info about physical memory from device tree */ + np = of_find_node_by_name(NULL, "memory"); + if (!np) { + dev_err(mci->pdev, "dt: missing /memory node\n"); + return -ENODEV; + } + + rc = of_address_to_resource(np, 0, &r); + + of_node_put(np); + + if (rc) { + dev_err(mci->pdev, "dt: failed requesting resource for /memory node\n"); + return rc; + } + + dev_dbg(mci->pdev, "dt: /memory node resources: first page %pR, PAGE_SHIFT macro=0x%x\n", + &r, PAGE_SHIFT); + + csrow->first_page = r.start >> PAGE_SHIFT; + nr_pages = resource_size(&r) >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + nr_pages - 1; + + regmap_read(aspeed_regmap, DRAMC_MCFG, ®04); + dram_type = (reg04 & MCFG_DRAM_TYPE) ? MEM_DDR5 : MEM_DDR4; + + dimm = csrow->channels[0]->dimm; + dimm->mtype = dram_type; + dimm->edac_mode = EDAC_SECDED; + dimm->nr_pages = nr_pages / csrow->nr_channels; + + dev_dbg(mci->pdev, "initialized dimm with first_page=0x%lx and nr_pages=0x%x\n", + csrow->first_page, nr_pages); + + return 0; +} + +static int aspeed_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct edac_mc_layer layers[2]; + struct mem_ctl_info *mci; + void __iomem *regs; + //u32 reg04; + u32 reg; + int rc; + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + aspeed_regmap = devm_regmap_init(dev, NULL, (__force void *)regs, + &aspeed_regmap_config); + if (IS_ERR(aspeed_regmap)) + return PTR_ERR(aspeed_regmap); + + /* bail out if ECC mode is not configured */ + regmap_read(aspeed_regmap, DRAMC_MCFG, ®); + if (!(reg & MCFG_ECC_ENABLE)) { + dev_err(&pdev->dev, "ECC mode is not configured in u-boot\n"); + return -EPERM; + } + + edac_op_state = EDAC_OPSTATE_INT; + + /* allocate & init EDAC MC data structure */ + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = 1; + layers[0].is_virt_csrow = true; + layers[1].type = EDAC_MC_LAYER_CHANNEL; + layers[1].size = 1; + layers[1].is_virt_csrow = false; + + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); + if (!mci) + return -ENOMEM; + + mci->pdev = &pdev->dev; + mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_DDR5; + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->scrub_cap = SCRUB_FLAG_HW_SRC; + mci->scrub_mode = SCRUB_HW_SRC; + mci->mod_name = DRV_NAME; + mci->ctl_name = "MIC"; + mci->dev_name = dev_name(&pdev->dev); + + rc = init_csrows(mci); + if (rc) { + dev_err(&pdev->dev, "failed to init csrows\n"); + goto probe_exit02; + } + + platform_set_drvdata(pdev, mci); + + /* register with edac core */ + rc = edac_mc_add_mc(mci); + if (rc) { + dev_err(&pdev->dev, "failed to register with EDAC core\n"); + goto probe_exit02; + } + + /* register interrupt handler and enable interrupts */ + rc = config_irq(mci, pdev); + if (rc) { + dev_err(&pdev->dev, "failed setting up irq\n"); + goto probe_exit01; + } + + return 0; + +probe_exit01: + edac_mc_del_mc(&pdev->dev); +probe_exit02: + edac_mc_free(mci); + return rc; +} + +static int aspeed_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci; + + /* disable interrupts */ + regmap_update_bits(aspeed_regmap, DRAMC_INT_MASK, + INT_STS_ECC_REC | INT_STS_ECC_ERR, + INT_STS_ECC_REC | INT_STS_ECC_ERR); + + /* free resources */ + mci = edac_mc_del_mc(&pdev->dev); + if (mci) + edac_mc_free(mci); + + return 0; +} + +static const struct of_device_id aspeed_of_match[] = { + { .compatible = "aspeed,ast2700-sdram-edac" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, aspeed_of_match); + +static struct platform_driver aspeed_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = aspeed_of_match + }, + .probe = aspeed_probe, + .remove = aspeed_remove +}; +module_platform_driver(aspeed_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stefan Schaeckeler "); +MODULE_DESCRIPTION("Aspeed BMC SoC EDAC driver"); +MODULE_VERSION("1.0"); diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig index 90dee3ec552097..f72bb1065d1457 100644 --- a/drivers/i3c/master/Kconfig +++ b/drivers/i3c/master/Kconfig @@ -44,6 +44,13 @@ config SVC_I3C_MASTER help Support for Silvaco I3C Dual-Role Master Controller. +config AMD_I3C_MASTER + tristate "AMD I3C Master driver" + depends on I3C + depends on HAS_IOMEM + help + Support for AMD I3C Master Controller. + config MIPI_I3C_HCI tristate "MIPI I3C Host Controller Interface driver (EXPERIMENTAL)" depends on I3C diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile index 3e97960160bc85..972896764c64e0 100644 --- a/drivers/i3c/master/Makefile +++ b/drivers/i3c/master/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_CDNS_I3C_MASTER) += i3c-master-cdns.o obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o obj-$(CONFIG_AST2600_I3C_MASTER) += ast2600-i3c-master.o obj-$(CONFIG_SVC_I3C_MASTER) += svc-i3c-master.o +obj-$(CONFIG_AMD_I3C_MASTER) += amd-i3c-master.o obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci/ diff --git a/drivers/i3c/master/amd-i3c-master.c b/drivers/i3c/master/amd-i3c-master.c new file mode 100644 index 00000000000000..c5af4bf64f2596 --- /dev/null +++ b/drivers/i3c/master/amd-i3c-master.c @@ -0,0 +1,1175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * I3C master driver for the AMD I3C controller. + * + * Copyright (C) 2025, Advanced Micro Devices, Inc. + */ + +#include // override iowrite32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCIE_INTERFACE_SUPPORT 1 +// #define DYNAMIC_ADDRESS_WORKAROUND 1 +// #define RESPONSE_LENGTH_WORKAROUND 1 +// Enable debug messages during initial BU +#define XI3C_DEBUG_ENABLE 1 + +#define XI3C_RESET_OFFSET 0x04 /* Soft Reset Register */ +#define XI3C_CR_OFFSET 0x08 /* Control Register */ +#define XI3C_ADDRESS_OFFSET 0x0C /* Target Address Register */ +#define XI3C_SR_OFFSET 0x10 /* Status Register */ +#define XI3C_CMD_FIFO_OFFSET 0x20 /* I3C Command FIFO Register */ +#define XI3C_WR_FIFO_OFFSET 0x24 /* I3C Write Data FIFO Register */ +#define XI3C_RD_FIFO_OFFSET 0x28 /* I3C Read Data FIFO Register */ +#define XI3C_RESP_STATUS_FIFO_OFFSET 0x2C /* I3C Response status FIFO Register */ +#define XI3C_FIFO_LVL_STATUS_OFFSET 0x30 /* I3C CMD & WR FIFO LVL Register */ +#define XI3C_FIFO_LVL_STATUS_1_OFFSET 0x34 /* I3C RESP & RD FIFO LVL Register */ + +#define XI3C_SCL_HIGH_TIME_OFFSET 0x38 /**< I3C SCL HIGH Register */ +#define XI3C_SCL_LOW_TIME_OFFSET 0x3C /**< I3C SCL LOW Register */ +#define XI3C_SDA_HOLD_TIME_OFFSET 0x40 /**< I3C SDA HOLD Register */ +#define XI3C_BUS_IDLE_OFFSET 0x44 /**< I3C CONTROLLER BUS IDLE Register */ +#define XI3C_TSU_START_OFFSET 0x48 /**< I3C START SETUP Register */ +#define XI3C_THD_START_OFFSET 0x4C /**< I3C START HOLD Register */ +#define XI3C_TSU_STOP_OFFSET 0x50 /**< I3C STOP Setup Register */ +#define XI3C_OD_SCL_HIGH_TIME_OFFSET 0x54 /**< I3C OD SCL HIGH Register */ +#define XI3C_OD_SCL_LOW_TIME_OFFSET 0x58 /**< I3C OD SCL LOW Register */ +#define XI3C_PID0_OFFSET 0x6C /* LSB 4 bytes of the PID */ +#define XI3C_PID1_BCR_DCR 0x70 /* MSB 2 bytes of the PID, BCR and DCR */ + + #define XI3C_CR_EN_MASK BIT(0) /* Core Enable */ + #define XI3C_SR_RESP_NOT_EMPTY_MASK BIT(4) /* Resp Fifo not empty status */ + + #define XI3C_RESP_CODE_SHIFT 5 + + #define XI3C_MAXDATA_LENGTH 4095 + #define XI3C_MAX_DEVS 32 + #define XI3C_DAA_SLAVEINFO_READ_BYTECOUNT 8 + + #define XI3C_I2C_MODE 0 + #define XI3C_I2C_TID 0 + #define XI3C_SDR_MODE 1 + #define XI3C_SDR_TID 1 + +#ifdef RESPONSE_LENGTH_WORKAROUND + #define I3C_CCC_DIRECT_GETMXDS 0x94 +#endif + +#ifndef PCIE_INTERFACE_SUPPORT + #define XI3C_PM_TIMEOUT_MS 1000 +#endif + + /* timeout waiting for the controller finish transfers */ + #define XI3C_XFER_TIMEOUT (msecs_to_jiffies(1000)) + + #define xi3c_wrfifolevel(master) \ + ((u16)(ioread32((master)->membase + XI3C_FIFO_LVL_STATUS_OFFSET) & GENMASK(15, 0))) + + #define xi3c_rdfifolevel(master) \ + ((u16)(ioread32((master)->membase + XI3C_FIFO_LVL_STATUS_1_OFFSET) & GENMASK(15, 0))) + +#define ioread32_poll_timeout(addr, val, cond, delay_us, timeout_us) \ +({ \ + unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \ + for (;;) { \ + (val) = ioread32(addr); \ + if (cond) \ + break; \ + if (timeout_us && time_after(jiffies, timeout)) { \ + (val) = ioread32(addr); /* Get the last value before timeout */ \ + break; \ + } \ + if (delay_us) \ + udelay(delay_us); \ + else \ + cpu_relax(); \ + } \ + (cond) ? 0 : -ETIMEDOUT; \ +}) + + struct xi3c_cmd { + u16 tx_len; + u16 rx_len; + void *tx_buf; + void *rx_buf; + u8 addr; + u8 type; + u8 tid; + bool rnw; + bool is_daa; + bool continued; + }; + + struct xi3c_xfer { + struct list_head node; + struct completion comp; + int ret; + unsigned int ncmds; + struct xi3c_cmd cmds[] __counted_by(ncmds); + }; + + + /** + * struct xi3c_master - I3C Master structure + * @base: I3C master controller + * @dev: Pointer to device structure + * @xferqueue: Transfer queue structure + * @xferqueue.list: List member + * @xferqueue.cur: Current ongoing transfer + * @xferqueue.lock: Queue lock + * @membase: Memory base of the HW registers + * @pclk: Input clock + * @lock: Transfer lock + * @pid_bcr_dcr: Poniter to PID, BCR and DCR value + * @num_targets: Number of i3c target devices + * @addrs: Slave addresses array + */ + struct xi3c_master { + struct i3c_master_controller base; + struct device *dev; + struct { + struct list_head list; + struct xi3c_xfer *cur; + /* Queue lock */ + struct mutex lock; + } xferqueue; + void __iomem *membase; + struct clk *pclk; + /* Transfer lock */ + struct mutex lock; + u64 *pid_bcr_dcr; + u32 num_targets; + u32 axi_clk_freq; + u32 scl_clk_freq; + u32 od_scl_high_time; + u32 od_scl_low_time; + u8 addrs[] __counted_by(num_targets); + }; + + static inline struct xi3c_master * + to_xi3c_master(struct i3c_master_controller *master) + { + return container_of(master, struct xi3c_master, base); + } + + static int xi3c_get_response(struct xi3c_master *master) + { + int ret; + u32 resp_reg, response_data; + + ret = ioread32_poll_timeout(master->membase + XI3C_SR_OFFSET, + resp_reg, + resp_reg & XI3C_SR_RESP_NOT_EMPTY_MASK, + 0, 1000); + if (ret) { + dev_err(master->dev, "AXI I3C response timeout\n"); + return ret; + } + + response_data = ioread32(master->membase + XI3C_RESP_STATUS_FIFO_OFFSET); + + /* Return response code */ + return (response_data & GENMASK(8, 5)) >> XI3C_RESP_CODE_SHIFT; + } + + static void xi3c_master_wr_to_tx_fifo(struct xi3c_master *master, struct xi3c_cmd *cmd) + { + u32 data = 0; + u8 *tx_buf = (u8 *)cmd->tx_buf; + + if (cmd->tx_len > 3) { + memcpy(&data, tx_buf, 4); + tx_buf += 4; + cmd->tx_len -= 4; + } else { + if (cmd->tx_len > 0) { + memcpy(&data, tx_buf, cmd->tx_len); + tx_buf += cmd->tx_len; + cmd->tx_len = 0; + } + } + cmd->tx_buf = tx_buf; + + /* Write the 32-bit value to the Tx FIFO */ + iowrite32be(data, master->membase + XI3C_WR_FIFO_OFFSET); + } + + static void xi3c_master_rd_from_rx_fifo(struct xi3c_master *master, struct xi3c_cmd *cmd) + { + u32 data; + u8 *rx_buf = (u8 *)cmd->rx_buf; + + /* Read from Rx FIFO */ + data = ioread32be(master->membase + XI3C_RD_FIFO_OFFSET); + + /* Data extraction to rx_buf */ + if (cmd->rx_len > 3) { + memcpy(rx_buf, &data, 4); + rx_buf += 4; + cmd->rx_len -= 4; + } else { + if (cmd->rx_len > 0) { + memcpy(rx_buf, &data, cmd->rx_len); + rx_buf += cmd->rx_len; + cmd->rx_len = 0; + } + } + cmd->rx_buf = rx_buf; + } + + static void xi3c_master_write_to_cmdfifo(struct xi3c_master *master, struct xi3c_cmd *cmd, u16 len) + { + u32 transfer_cmd = 0; + u8 addr; + + addr = ((cmd->addr & GENMASK(6, 0)) << 1) | (cmd->rnw & BIT(0)); + + transfer_cmd = cmd->type & GENMASK(3, 0); + transfer_cmd |= (u32)(!cmd->continued) << 4; + transfer_cmd |= (u32)(addr) << 8; + transfer_cmd |= (u32)(cmd->tid & GENMASK(3, 0)) << 28; + + /* For dynamic addressing, an additional 1-byte length must be added + * to the command FIFO to account for the address present in the TX FIFO. + */ + if(cmd->is_daa) { + xi3c_master_wr_to_tx_fifo(master, cmd); + len = len + 1; + cmd->is_daa = false; + } + + transfer_cmd |= (u32)(len & GENMASK(11, 0)) << 16; + iowrite32(transfer_cmd, master->membase + XI3C_CMD_FIFO_OFFSET); + } + + static void xi3c_master_enable(struct xi3c_master *master) + { + iowrite32(ioread32(master->membase + XI3C_CR_OFFSET) | XI3C_CR_EN_MASK, + master->membase + XI3C_CR_OFFSET); + } + + static void xi3c_master_disable(struct xi3c_master *master) + { + iowrite32(ioread32(master->membase + XI3C_CR_OFFSET) & (~XI3C_CR_EN_MASK), + master->membase + XI3C_CR_OFFSET); + } + + static void xi3c_master_init(struct xi3c_master *master) + { + u32 data; + + /* Reset fifos */ + data = ioread32(master->membase + XI3C_RESET_OFFSET); + data |= GENMASK(4, 1); + iowrite32(data, master->membase + XI3C_RESET_OFFSET); + usleep_range(1, 2); + data &= ~GENMASK(4, 1); + iowrite32(data, master->membase + XI3C_RESET_OFFSET); + usleep_range(1, 2); + +#ifdef PCIE_INTERFACE_SUPPORT + // Reset controller + data = ioread32(master->membase + XI3C_RESET_OFFSET); + data |= 0x01; + iowrite32(data, master->membase + XI3C_RESET_OFFSET); + usleep_range(1, 2); + data = ioread32(master->membase + XI3C_RESET_OFFSET); + data &= ~0x1; + iowrite32(data, master->membase + XI3C_RESET_OFFSET); + usleep_range(1, 2); +#endif + + /* Enable controller */ + xi3c_master_enable(master); + } + + static struct xi3c_xfer * + xi3c_master_alloc_xfer(struct xi3c_master *master, unsigned int ncmds) + { + struct xi3c_xfer *xfer; + + xfer = kzalloc(struct_size(xfer, cmds, ncmds), GFP_KERNEL); + if (!xfer) + return NULL; + + INIT_LIST_HEAD(&xfer->node); + xfer->ncmds = ncmds; + xfer->ret = -ETIMEDOUT; + + return xfer; + } + + static void xi3c_master_free_xfer(struct xi3c_xfer *xfer) + { + kfree(xfer); + } + + static u8 xi3c_even_parity(u8 p) + { + p ^= p >> 4; + p &= 0xf; + + return (0x9669 >> p) & 1; + } + + static int xi3c_master_read(struct xi3c_master *master, struct xi3c_cmd *cmd) + { + u16 rx_data_available; + u16 data_index; + unsigned long timeout; + u16 len; + + if (!cmd->rx_buf || cmd->rx_len > XI3C_MAXDATA_LENGTH) { + return -EINVAL; + } + + /* Fill command fifo */ + xi3c_master_write_to_cmdfifo(master, cmd, cmd->rx_len); + + timeout = jiffies + XI3C_XFER_TIMEOUT; + len = cmd->rx_len; + /* Read data from rx fifo */ + while (cmd->rx_len > 0){ + if (time_after(jiffies, timeout)) { + dev_err(master->dev, "XI3C read timeout\n"); + goto err_read; + } + + rx_data_available = xi3c_rdfifolevel(master); + for (data_index = 0; + data_index < rx_data_available && cmd->rx_len > 0; + data_index++) { + xi3c_master_rd_from_rx_fifo(master, cmd); + } + } + return 0; + + err_read: + return -EIO; + } + + static int xi3c_master_write(struct xi3c_master *master, struct xi3c_cmd *cmd) + { + u16 wrfifo_space; + u16 space_index; + u16 len; + unsigned long timeout; + + if (!cmd->tx_buf || cmd->tx_len > XI3C_MAXDATA_LENGTH) { + return -EINVAL; + } + len = cmd->tx_len; + + /* Fill Tx fifo */ + wrfifo_space = xi3c_wrfifolevel(master); + for (space_index = 0; space_index < wrfifo_space && cmd->tx_len > 0; space_index++) + xi3c_master_wr_to_tx_fifo(master, cmd); + + /* Write to command fifo */ + xi3c_master_write_to_cmdfifo(master, cmd, len); + + timeout = jiffies + XI3C_XFER_TIMEOUT; + /* Fill if any remaining data to tx fifo */ + while (cmd->tx_len > 0){ + if (time_after(jiffies, timeout)) { + dev_err(master->dev, "XI3C write timeout\n"); + goto err_write; + } + + wrfifo_space = xi3c_wrfifolevel(master); + for (space_index = 0; space_index < wrfifo_space && cmd->tx_len > 0; space_index++) + xi3c_master_wr_to_tx_fifo(master, cmd); + } + + return 0; + + err_write: + return -EIO; + } + + static int xi3c_master_xfer(struct xi3c_master *master, struct xi3c_cmd *cmd) + { + int ret; + + if (cmd->rnw) { + ret = xi3c_master_read(master, cmd); + } + else { + ret = xi3c_master_write(master, cmd); + } + + if (ret < 0) { + goto err_xfer_out; + } + + if (xi3c_get_response(master)) { + goto err_xfer_out; + } + + return 0; + + err_xfer_out: + xi3c_master_init(master); + return -EIO; + } + + static void xi3c_master_dequeue_xfer_locked(struct xi3c_master *master, + struct xi3c_xfer *xfer) + { + if (master->xferqueue.cur == xfer) + master->xferqueue.cur = NULL; + else + list_del_init(&xfer->node); + } + + static void xi3c_master_dequeue_xfer(struct xi3c_master *master, + struct xi3c_xfer *xfer) + { + mutex_lock(&master->xferqueue.lock); + xi3c_master_dequeue_xfer_locked(master, xfer); + mutex_unlock(&master->xferqueue.lock); + } + + static void xi3c_master_start_xfer_locked(struct xi3c_master *master) + { + struct xi3c_xfer *xfer = master->xferqueue.cur; + int ret, i; + + if (!xfer) { + return; + } + + for (i = 0; i < xfer->ncmds; i++) { + struct xi3c_cmd *cmd = &xfer->cmds[i]; + + ret = xi3c_master_xfer(master, cmd); + if (ret) + break; + } + + xfer->ret = ret; + complete(&xfer->comp); + + xfer = list_first_entry_or_null(&master->xferqueue.list, + struct xi3c_xfer, + node); + if (xfer) + list_del_init(&xfer->node); + + master->xferqueue.cur = xfer; + xi3c_master_start_xfer_locked(master); + } + + static void xi3c_master_enqueue_xfer(struct xi3c_master *master, + struct xi3c_xfer *xfer) + { +#ifndef PCIE_INTERFACE_SUPPORT + int ret; + + ret = pm_runtime_resume_and_get(master->dev); + + if (ret < 0) { + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); + return; + } +#endif + init_completion(&xfer->comp); + mutex_lock(&master->xferqueue.lock); + if (master->xferqueue.cur) { + list_add_tail(&xfer->node, &master->xferqueue.list); + } else { + master->xferqueue.cur = xfer; + xi3c_master_start_xfer_locked(master); + } + mutex_unlock(&master->xferqueue.lock); + +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_mark_last_busy(master->dev); + pm_runtime_put_autosuspend(master->dev); +#endif + } + +#ifndef DYNAMIC_ADDRESS_WORKAROUND + static u64 xi3c_swap_pid_bytes(const u8 *pid_buf) + { + u64 pid = 0; + int i; + + for (i = 0; i < 6; i++) { + pid <<= 8; + pid |= pid_buf[i]; + } + + return pid; + } +#endif + + static int xi3c_master_do_daa(struct i3c_master_controller *m) + { + struct xi3c_master *master = to_xi3c_master(m); + struct xi3c_xfer *xfer; + struct xi3c_cmd *daa_cmd; + int ret, i, timeout; + u8 pid_bufs[XI3C_MAX_DEVS][XI3C_DAA_SLAVEINFO_READ_BYTECOUNT]; + u8 *pid_buf; + u8 addr, data, last_addr = 0; +#ifdef DYNAMIC_ADDRESS_WORKAROUND + bool masterinit = 0; +#endif + +#ifdef XI3C_DEBUG_ENABLE + dev_info(master->dev, "xi3c_master_do_daa: Start"); +#endif + + if (master->num_targets == 0 || master->num_targets > XI3C_MAX_DEVS) { + dev_err(master->dev, "Invalid / No target devices connected\n"); + return -EIO; + } + + master->pid_bcr_dcr = kcalloc(master->num_targets, sizeof(u64), GFP_KERNEL); + if (!master->pid_bcr_dcr) { + return -ENOMEM; + } + + xfer = xi3c_master_alloc_xfer(master, master->num_targets + 1); + if (!xfer) { + ret = -ENOMEM; + goto err_daa_mem; + } + + /* Fill ENTDAA CCC */ + data = I3C_CCC_ENTDAA; + daa_cmd = &xfer->cmds[0]; + daa_cmd->addr = I3C_BROADCAST_ADDR; + daa_cmd->rnw = 0; + daa_cmd->tx_buf = &data; + daa_cmd->tx_len = 1; + daa_cmd->type = XI3C_SDR_MODE; + daa_cmd->tid = XI3C_SDR_TID; + daa_cmd->continued = true; + + for (i = 1; i < master->num_targets + 1; i++) { + struct xi3c_cmd *cmd = &xfer->cmds[i]; + + pid_buf = pid_bufs[i - 1]; + + addr = i3c_master_get_free_addr(m, last_addr + 1); + if (addr < 0) { + ret = -ENOSPC; + goto err_daa; + } + last_addr = addr; + master->addrs[i - 1] = addr; + addr = (addr << 1) | xi3c_even_parity(addr); + + cmd->tx_buf = &addr; + cmd->tx_len = 1; + cmd->addr = I3C_BROADCAST_ADDR; + cmd->rnw = 1; + cmd->rx_buf = pid_buf; + cmd->rx_len = XI3C_DAA_SLAVEINFO_READ_BYTECOUNT; + cmd->is_daa = true; + cmd->type = XI3C_SDR_MODE; + cmd->tid = XI3C_SDR_TID; + cmd->continued = i < master->num_targets; + } + + + mutex_lock(&master->lock); + + xi3c_master_enqueue_xfer(master, xfer); + + timeout = wait_for_completion_timeout(&xfer->comp, + msecs_to_jiffies(1000 * master->num_targets)); + if (!timeout) { + ret = -ETIMEDOUT; + } + else { + ret = xfer->ret; + } + + if (ret) + xi3c_master_dequeue_xfer(master, xfer); + + + mutex_unlock(&master->lock); +#ifdef DYNAMIC_ADDRESS_WORKAROUND + if (ret) + masterinit = 1; +#endif + +#ifndef DYNAMIC_ADDRESS_WORKAROUND + if (ret) + goto err_daa; + + + for (i = 0; i < master->num_targets; i++) { + ret = i3c_master_add_i3c_dev_locked(m, master->addrs[i]); + + if (ret) { + goto err_daa; + } + + master->pid_bcr_dcr[i] = xi3c_swap_pid_bytes(pid_bufs[i]); + dev_info(master->dev, "Client %d: PID: 0x%llx\n", i, master->pid_bcr_dcr[i]); + } +#endif + + kfree(master->pid_bcr_dcr); + if(ret) { +#ifdef DYNAMIC_ADDRESS_WORKAROUND + if (masterinit == 1) +#endif + xi3c_master_init(master); + } + xi3c_master_free_xfer(xfer); +#ifdef XI3C_DEBUG_ENABLE + dev_info(master->dev, "xi3c_master_do_daa: Success"); +#endif + return 0; + + err_daa: + xi3c_master_init(master); + xi3c_master_free_xfer(xfer); + err_daa_mem: + kfree(master->pid_bcr_dcr); +#ifdef XI3C_DEBUG_ENABLE + dev_err(master->dev, "xi3c_master_do_daa: Error %x", ret); +#endif + return -EIO; + } + + static bool + xi3c_master_supports_ccc_cmd(struct i3c_master_controller *master, + const struct i3c_ccc_cmd *cmd) + { + if (cmd->ndests > 1) + return false; + + switch (cmd->id) { + case I3C_CCC_ENEC(true): + case I3C_CCC_ENEC(false): + case I3C_CCC_DISEC(true): + case I3C_CCC_DISEC(false): + case I3C_CCC_ENTAS(0, true): + case I3C_CCC_ENTAS(0, false): + case I3C_CCC_RSTDAA(true): + case I3C_CCC_RSTDAA(false): + case I3C_CCC_ENTDAA: + case I3C_CCC_SETMWL(true): + case I3C_CCC_SETMWL(false): + case I3C_CCC_SETMRL(true): + case I3C_CCC_SETMRL(false): + case I3C_CCC_ENTHDR(0): + case I3C_CCC_SETDASA: + case I3C_CCC_SETNEWDA: + case I3C_CCC_GETMWL: + case I3C_CCC_GETMRL: + case I3C_CCC_GETPID: + case I3C_CCC_GETBCR: + case I3C_CCC_GETDCR: + case I3C_CCC_GETSTATUS: + case I3C_CCC_GETMXDS: + return true; + default: + return false; + } + } + + static int xi3c_master_send_bdcast_ccc_cmd(struct xi3c_master *master, + struct i3c_ccc_cmd *ccc) + { + u16 xfer_len = ccc->dests[0].payload.len + 1; + struct xi3c_xfer *xfer; + struct xi3c_cmd *cmd; + int ret, timeout; + u8 *buf; + + xfer = xi3c_master_alloc_xfer(master, 1); + if (!xfer) { + return -ENOMEM; + } + + buf = kmalloc(xfer_len, GFP_KERNEL); + if (!buf) { + xi3c_master_free_xfer(xfer); + return -ENOMEM; + } + + buf[0] = ccc->id; + memcpy(&buf[1], ccc->dests[0].payload.data, ccc->dests[0].payload.len); + + cmd = &xfer->cmds[0]; + cmd->addr = ccc->dests[0].addr; + cmd->rnw = ccc->rnw; + cmd->tx_buf = buf; + cmd->tx_len = xfer_len; + cmd->type = XI3C_SDR_MODE; + cmd->tid = XI3C_SDR_TID; + cmd->continued = false; + + mutex_lock(&master->lock); + xi3c_master_enqueue_xfer(master, xfer); + timeout = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)); + if (!timeout) + ret = -ETIMEDOUT; + else + ret = xfer->ret; + + + if (ret) + xi3c_master_dequeue_xfer(master, xfer); + mutex_unlock(&master->lock); + kfree(buf); + + xi3c_master_free_xfer(xfer); + + return ret; + } + + static int xi3c_master_send_direct_ccc_cmd(struct xi3c_master *master, + struct i3c_ccc_cmd *ccc) + { + struct xi3c_xfer *xfer; + struct xi3c_cmd *cmd; + int ret, timeout; + + xfer = xi3c_master_alloc_xfer(master, 2); + if (!xfer) { + return -ENOMEM; + } + + /* Broadcasted message */ + cmd = &xfer->cmds[0]; + cmd->addr = I3C_BROADCAST_ADDR; + cmd->rnw = 0; + cmd->tx_buf = &ccc->id; + cmd->tx_len = 1; + cmd->type = XI3C_SDR_MODE; + cmd->tid = XI3C_SDR_TID; + cmd->continued = true; + + /* Directed message */ + cmd = &xfer->cmds[1]; + cmd->addr = ccc->dests[0].addr; + cmd->rnw = ccc->rnw; + if (cmd->rnw) { + cmd->rx_buf = ccc->dests[0].payload.data; + cmd->rx_len = ccc->dests[0].payload.len; +#ifdef RESPONSE_LENGTH_WORKAROUND + if(ccc->id == I3C_CCC_DIRECT_GETMXDS) + cmd->rx_len = 2; +#endif + } else { + cmd->tx_buf = ccc->dests[0].payload.data; + cmd->tx_len = ccc->dests[0].payload.len; + } + cmd->type = XI3C_SDR_MODE; + cmd->tid = XI3C_SDR_TID; + cmd->continued = false; + + mutex_lock(&master->lock); + xi3c_master_enqueue_xfer(master, xfer); + timeout = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)); + if (!timeout) + ret = -ETIMEDOUT; + else + ret = xfer->ret; + + if (ret) + xi3c_master_dequeue_xfer(master, xfer); + mutex_unlock(&master->lock); + + xi3c_master_free_xfer(xfer); + + return ret; + } + + static int xi3c_master_send_ccc_cmd(struct i3c_master_controller *m, + struct i3c_ccc_cmd *cmd) + { + struct xi3c_master *master = to_xi3c_master(m); + bool broadcast = cmd->id < 0x80; + int ret; + + if (broadcast) { + ret = xi3c_master_send_bdcast_ccc_cmd(master, cmd); + } + else { + ret = xi3c_master_send_direct_ccc_cmd(master, cmd); + } +#ifdef XI3C_DEBUG_ENABLE + dev_info(master->dev, "xi3c_master_send_ccc_cmd: cmd %x status %x", cmd->id, ret); +#endif + + return ret; + } + + static int xi3c_master_priv_xfers(struct i3c_dev_desc *dev, + struct i3c_priv_xfer *xfers, + int nxfers) + { + struct i3c_master_controller *m = i3c_dev_get_master(dev); + struct xi3c_master *master = to_xi3c_master(m); + struct xi3c_xfer *xfer; + int ret, i, timeout; + + if (!nxfers) + return 0; + + xfer = xi3c_master_alloc_xfer(master, nxfers); + if (!xfer) + return -ENOMEM; + + for (i = 0; i < nxfers; i++) { + struct xi3c_cmd *cmd = &xfer->cmds[i]; + + cmd->addr = dev->info.dyn_addr; + cmd->rnw = xfers[i].rnw; + + if (cmd->rnw) { + cmd->rx_buf = xfers[i].data.in; + cmd->rx_len = xfers[i].len; + } else { + cmd->tx_buf = (void *)xfers[i].data.out; + cmd->tx_len = xfers[i].len; + } + + cmd->type = XI3C_SDR_MODE; + cmd->tid = XI3C_SDR_TID; + cmd->continued = (i + 1) < nxfers; + } + + mutex_lock(&master->lock); + xi3c_master_enqueue_xfer(master, xfer); + + timeout = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000 * nxfers)); + if (!timeout) + ret = -ETIMEDOUT; + else + ret = xfer->ret; + + if (ret) + xi3c_master_dequeue_xfer(master, xfer); + mutex_unlock(&master->lock); + + xi3c_master_free_xfer(xfer); + + return ret; + } + + static int xi3c_master_i2c_xfers(struct i2c_dev_desc *dev, + const struct i2c_msg *xfers, + int nxfers) + { + struct i3c_master_controller *m = i2c_dev_get_master(dev); + struct xi3c_master *master = to_xi3c_master(m); + struct xi3c_xfer *xfer; + int ret, i, timeout; + + if (!nxfers) + return 0; + + xfer = xi3c_master_alloc_xfer(master, nxfers); + if (!xfer) + return -ENOMEM; + + for (i = 0; i < nxfers; i++) { + struct xi3c_cmd *cmd = &xfer->cmds[i]; + + cmd->addr = xfers[i].addr & GENMASK(6, 0); + cmd->rnw = xfers[i].flags & I2C_M_RD; + + if (cmd->rnw) { + cmd->rx_buf = xfers[i].buf; + cmd->rx_len = xfers[i].len; + } else { + cmd->tx_buf = (void *)xfers[i].buf; + cmd->tx_len = xfers[i].len; + } + + cmd->type = XI3C_I2C_MODE; + cmd->tid = XI3C_I2C_TID; + cmd->continued = (i + 1) < nxfers; + } + + mutex_lock(&master->lock); + xi3c_master_enqueue_xfer(master, xfer); + + timeout = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000 * nxfers)); + if (!timeout) + ret = -ETIMEDOUT; + else + ret = xfer->ret; + + if (ret) + xi3c_master_dequeue_xfer(master, xfer); + mutex_unlock(&master->lock); + + xi3c_master_free_xfer(xfer); + + return ret; + } + + static int xi3c_master_bus_init(struct i3c_master_controller *m) + { + struct xi3c_master *master = to_xi3c_master(m); + struct i3c_bus *bus = i3c_master_get_bus(m); + struct i3c_device_info info = { }; + int ret; + u64 pid1_bcr_dcr; + +#ifndef PCIE_INTERFACE_SUPPORT + ret = pm_runtime_resume_and_get(master->dev); + if (ret < 0) { + dev_err(master->dev, + "<%s> cannot resume i3c bus master, err: %d\n", __func__, ret); + return ret; + } +#endif + + if (bus->mode != I3C_BUS_MODE_PURE) { + ret = -EINVAL; + goto rpm_out; + } + + /* Get an address for the master. */ + ret = i3c_master_get_free_addr(m, 0); + if (ret < 0) { + goto rpm_out; + } + + info.dyn_addr = (u8)ret; + + /* + * Write the dynamic address value to the address register + */ + iowrite32(info.dyn_addr, master->membase + XI3C_ADDRESS_OFFSET); +#ifdef PCIE_INTERFACE_SUPPORT + // Open Drain timings + if(master->od_scl_high_time) + iowrite32(master->od_scl_high_time, master->membase + XI3C_OD_SCL_HIGH_TIME_OFFSET); + if(master->od_scl_low_time) + iowrite32(master->od_scl_low_time, master->membase + XI3C_OD_SCL_LOW_TIME_OFFSET); +#endif + + /* + * Read PID, BCR and DCR values, and assign to i3c device info + */ + pid1_bcr_dcr = ioread32(master->membase + XI3C_PID1_BCR_DCR); + + info.pid = (((pid1_bcr_dcr & GENMASK(15, 0)) << 32) | + ioread32(master->membase + XI3C_PID0_OFFSET)); + info.bcr = (u8)((pid1_bcr_dcr & GENMASK(23, 16)) >> 16); + info.dcr = (u8)((pid1_bcr_dcr & GENMASK(31, 24)) >> 24); + + ret = i3c_master_set_info(&master->base, &info); + + if (ret) { + goto rpm_out; + } + xi3c_master_init(master); + + + rpm_out: +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_mark_last_busy(master->dev); + pm_runtime_put_autosuspend(master->dev); +#endif + + return ret; + } + + static void xi3c_master_bus_cleanup(struct i3c_master_controller *m) + { + struct xi3c_master *master = to_xi3c_master(m); +#ifndef PCIE_INTERFACE_SUPPORT + int ret; + + ret = pm_runtime_resume_and_get(master->dev); + if (ret < 0) { + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); + return; + } +#endif + + xi3c_master_disable(master); +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_mark_last_busy(master->dev); + pm_runtime_put_autosuspend(master->dev); +#endif + } + + static const struct i3c_master_controller_ops xi3c_master_ops = { + .bus_init = xi3c_master_bus_init, + .bus_cleanup = xi3c_master_bus_cleanup, + .do_daa = xi3c_master_do_daa, + .supports_ccc_cmd = xi3c_master_supports_ccc_cmd, + .send_ccc_cmd = xi3c_master_send_ccc_cmd, + .priv_xfers = xi3c_master_priv_xfers, + .i2c_xfers = xi3c_master_i2c_xfers, + }; + + static const struct of_device_id xi3c_master_of_ids[] = { + { .compatible = "xlnx,axi-i3c-1.0" }, + { }, + }; + + static int xi3c_master_probe(struct platform_device *pdev) + { + struct xi3c_master *master; + int ret; + + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); + if (!master) { + return -ENOMEM; + } + + master->membase = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(master->membase)) { + return PTR_ERR(master->membase); + } + + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,num-targets", &master->num_targets); + if (ret) { + dev_err(&pdev->dev, "Failed to read xlnx,num-targets\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,axi-clk-freq", &master->axi_clk_freq); + if (ret) { + dev_info(&pdev->dev, "Failed to read xlnx,axi_clk_freq\n"); + } + + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,scl-clk-freq", &master->scl_clk_freq); + if (ret) { + dev_info(&pdev->dev, "Failed to read xlnx,scl-clk-freq\n"); + } + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,od-scl-high-time", &master->od_scl_high_time); + if (ret) { + dev_info(&pdev->dev, "Failed to read xlnx,od-scl-high-time\n"); + master->od_scl_high_time = 0; + } + ret = of_property_read_u32(pdev->dev.of_node, "xlnx,od-scl-low-time", &master->od_scl_low_time); + if (ret) { + dev_info(&pdev->dev, "Failed to read xlnx,od-scl-low-time\n"); + master->od_scl_low_time = 0; + } + +#ifndef PCIE_INTERFACE_SUPPORT + master->pclk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); + if (IS_ERR(master->pclk)) { + ret = PTR_ERR(master->pclk); + dev_err(&pdev->dev, "Failed to get and enable clock: %d\n", ret); + return ret; + } +#endif + + master->dev = &pdev->dev; + + mutex_init(&master->lock); + mutex_init(&master->xferqueue.lock); + INIT_LIST_HEAD(&master->xferqueue.list); + + platform_set_drvdata(pdev, master); +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_set_autosuspend_delay(&pdev->dev, XI3C_PM_TIMEOUT_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); +#endif + ret = i3c_master_register(&master->base, &pdev->dev, + &xi3c_master_ops, false); + if (ret) { + goto err_rpm_disable; + } +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); +#endif + return 0; + + err_rpm_disable: +#ifndef PCIE_INTERFACE_SUPPORT + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); +#endif + return ret; + } + + static void xi3c_master_remove(struct platform_device *pdev) + { + struct xi3c_master *master = platform_get_drvdata(pdev); + + i3c_master_unregister(&master->base); +#ifndef PCIE_INTERFACE_SUPPORT + clk_disable_unprepare(master->pclk); +#endif + } + + #ifndef PCIE_INTERFACE_SUPPORT + static int __maybe_unused xi3c_master_runtime_suspend(struct device *dev) + { + struct xi3c_master *master = dev_get_drvdata(dev); + xi3c_master_disable(master); + + clk_disable_unprepare(master->pclk); + return 0; + } + +static int __maybe_unused xi3c_master_runtime_resume(struct device *dev) + { + struct xi3c_master *master = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(master->pclk); + if (ret) + return ret; + + xi3c_master_enable(master); + return 0; + } +#endif + + #ifndef PCIE_INTERFACE_SUPPORT + static const struct dev_pm_ops xi3c_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(xi3c_master_runtime_suspend, xi3c_master_runtime_resume, NULL) + }; +#endif + + static struct platform_driver xi3c_master_driver = { + .probe = xi3c_master_probe, + .remove_new = xi3c_master_remove, + .driver = { + .name = "axi-i3c-master", + .of_match_table = xi3c_master_of_ids, +#ifndef PCIE_INTERFACE_SUPPORT + .pm = &xi3c_pm_ops, +#endif + }, + }; + module_platform_driver(xi3c_master_driver); + + MODULE_AUTHOR("Manikanta Guntupalli "); + MODULE_DESCRIPTION("AXI I3C master driver"); + MODULE_LICENSE("GPL v2"); + diff --git a/drivers/i3c/master/ast2600-i3c-master.c b/drivers/i3c/master/ast2600-i3c-master.c index b832aaba3b65bc..7b0fbb191d54a2 100644 --- a/drivers/i3c/master/ast2600-i3c-master.c +++ b/drivers/i3c/master/ast2600-i3c-master.c @@ -77,12 +77,16 @@ #define ADDR_HID(x) ((x) & ADDR_HID_MASK) #define IBI_QUEUE_STATUS 0x18 +#define IBI_QUEUE_STATUS_DATA_LEN(x) ((x) & GENMASK(7, 0)) #define IBI_SIR_REQ_REJECT 0x30 #define INTR_STATUS_EN 0x40 #define INTR_SIGNAL_EN 0x44 #define INTR_IBI_THLD_STAT BIT(2) +#define QUEUE_STATUS_LEVEL 0x4c +#define QUEUE_STATUS_IBI_STATUS_CNT(x) (((x) & GENMASK(28, 24)) >> 24) + #define PRESENT_STATE 0x54 #define CM_TFR_STS GENMASK(13, 8) #define CM_TFR_STS_MASTER_SERV_IBI 0xe @@ -340,6 +344,20 @@ static void ast2600_i3c_gen_target_reset_pattern(struct dw_i3c_master *dw) SDA_IN_SW_MODE_EN | SCL_IN_SW_MODE_EN, 0); } +static void aspeed_i3c_drain_ibi_queue(struct dw_i3c_master *dw) +{ + /* + * Clear the IBI queue to avoid any stale IBI data when + * re-enabling the controller. + */ + u32 ibi_status = readl(dw->regs + IBI_QUEUE_STATUS); + u8 length = IBI_QUEUE_STATUS_DATA_LEN(ibi_status); + int i, nwords = (length + 3) >> 2; + + for (i = 0; i < nwords; i++) + readl(dw->regs + IBI_QUEUE_STATUS); +} + static bool ast2600_i3c_fsm_exit_serv_ibi(struct dw_i3c_master *dw) { u32 state; @@ -348,7 +366,7 @@ static bool ast2600_i3c_fsm_exit_serv_ibi(struct dw_i3c_master *dw) * Clear the IBI queue to enable the hardware to generate SCL and * begin detecting the T-bit low to stop reading IBI data. */ - readl(dw->regs + IBI_QUEUE_STATUS); + aspeed_i3c_drain_ibi_queue(dw); state = FIELD_GET(CM_TFR_STS, readl(dw->regs + PRESENT_STATE)); if (state == CM_TFR_STS_MASTER_SERV_IBI) return false; @@ -359,7 +377,8 @@ static bool ast2600_i3c_fsm_exit_serv_ibi(struct dw_i3c_master *dw) static void ast2600_i3c_gen_tbits_in(struct dw_i3c_master *dw) { struct ast2600_i3c *i3c = to_ast2600_i3c(dw); - bool is_idle; + bool is_halted; + u32 nibi, i; int ret; regmap_write_bits(i3c->global_regs, AST2600_I3CG_REG1(i3c->global_idx), @@ -370,14 +389,21 @@ static void ast2600_i3c_gen_tbits_in(struct dw_i3c_master *dw) regmap_write_bits(i3c->global_regs, AST2600_I3CG_REG1(i3c->global_idx), SDA_IN_SW_MODE_VAL, 0); ret = readx_poll_timeout_atomic(ast2600_i3c_fsm_exit_serv_ibi, dw, - is_idle, is_idle, 0, 2000000); + is_halted, is_halted, 0, 2000000); regmap_write_bits(i3c->global_regs, AST2600_I3CG_REG1(i3c->global_idx), SDA_IN_SW_MODE_EN, 0); - if (ret) + if (ret) { dev_err(&dw->base.dev, "Failed to exit the I3C fsm from %lx(MASTER_SERV_IBI): %d", FIELD_GET(CM_TFR_STS, readl(dw->regs + PRESENT_STATE)), ret); + } else { + /* Clear the dummy data generated in this recovery process */ + nibi = readl(dw->regs + QUEUE_STATUS_LEVEL); + nibi = QUEUE_STATUS_IBI_STATUS_CNT(nibi); + for (i = 0; i < nibi; i++) + aspeed_i3c_drain_ibi_queue(dw); + } } static void ast2600_i3c_set_ibi_mdb(struct dw_i3c_master *dw, u8 mdb) diff --git a/drivers/irqchip/irq-aspeed-intc.c b/drivers/irqchip/irq-aspeed-intc.c index faf18a6753950a..8fa6b583f8b43c 100644 --- a/drivers/irqchip/irq-aspeed-intc.c +++ b/drivers/irqchip/irq-aspeed-intc.c @@ -18,29 +18,65 @@ #define INTC_INT_ENABLE_REG 0x00 #define INTC_INT_STATUS_REG 0x04 #define INTC_IRQS_PER_WORD 32 +#define INTC_IRQ_BASE 192 struct aspeed_intc_ic { void __iomem *base; - raw_spinlock_t gic_lock; raw_spinlock_t intc_lock; struct irq_domain *irq_domain; }; -static void aspeed_intc_ic_irq_handler(struct irq_desc *desc) +static void aspeed_intc0_ic_irq_handler(struct irq_desc *desc) { struct aspeed_intc_ic *intc_ic = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); + struct irq_data *irq_data = irq_desc_get_irq_data(desc); + unsigned long hwirq; + + if (!irq_data || !intc_ic) { + pr_err("Invalid irq_data or intc_ic\n"); + return; + } + + if (irq_data->hwirq < INTC_IRQ_BASE + 32) { + pr_err("Invalid hwirq: %lu\n", irq_data->hwirq); + return; + } + hwirq = irq_data->hwirq - INTC_IRQ_BASE - 32; /* 32 is SPI offset */ chained_irq_enter(chip, desc); - scoped_guard(raw_spinlock, &intc_ic->gic_lock) { - unsigned long bit, status; + generic_handle_domain_irq(intc_ic->irq_domain, hwirq); - status = readl(intc_ic->base + INTC_INT_STATUS_REG); - for_each_set_bit(bit, &status, INTC_IRQS_PER_WORD) { - generic_handle_domain_irq(intc_ic->irq_domain, bit); - writel(BIT(bit), intc_ic->base + INTC_INT_STATUS_REG); - } + /* + * TODO: This a WA to prevnet potential race conditions when + * multiple interrupts are processed in multi-core environment. + */ + raw_spin_lock(&intc_ic->intc_lock); + writel(BIT(hwirq), intc_ic->base + INTC_INT_STATUS_REG); + raw_spin_unlock(&intc_ic->intc_lock); + + chained_irq_exit(chip, desc); +} + +static void aspeed_intc1_ic_irq_handler(struct irq_desc *desc) +{ + struct aspeed_intc_ic *intc_ic = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long bit, status; + + if (!intc_ic) { + pr_err("Invalid intc_ic\n"); + return; + } + + chained_irq_enter(chip, desc); + + status = readl(intc_ic->base + INTC_INT_STATUS_REG); + + for_each_set_bit(bit, &status, INTC_IRQS_PER_WORD) { + generic_handle_domain_irq(intc_ic->irq_domain, bit); + writel(BIT(bit), intc_ic->base + INTC_INT_STATUS_REG); } chained_irq_exit(chip, desc); @@ -49,18 +85,20 @@ static void aspeed_intc_ic_irq_handler(struct irq_desc *desc) static void aspeed_intc_irq_mask(struct irq_data *data) { struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data); - unsigned int mask = readl(intc_ic->base + INTC_INT_ENABLE_REG) & ~BIT(data->hwirq); + unsigned int mask; - guard(raw_spinlock)(&intc_ic->intc_lock); + guard(raw_spinlock_irqsave)(&intc_ic->intc_lock); + mask = readl(intc_ic->base + INTC_INT_ENABLE_REG) & ~BIT(data->hwirq); writel(mask, intc_ic->base + INTC_INT_ENABLE_REG); } static void aspeed_intc_irq_unmask(struct irq_data *data) { struct aspeed_intc_ic *intc_ic = irq_data_get_irq_chip_data(data); - unsigned int unmask = readl(intc_ic->base + INTC_INT_ENABLE_REG) | BIT(data->hwirq); + unsigned int unmask; - guard(raw_spinlock)(&intc_ic->intc_lock); + guard(raw_spinlock_irqsave)(&intc_ic->intc_lock); + unmask = readl(intc_ic->base + INTC_INT_ENABLE_REG) | BIT(data->hwirq); writel(unmask, intc_ic->base + INTC_INT_ENABLE_REG); } @@ -88,7 +126,7 @@ static int __init aspeed_intc_ic_of_init(struct device_node *node, { struct aspeed_intc_ic *intc_ic; int ret = 0; - int irq, i; + int irq, irq_count, i; intc_ic = kzalloc(sizeof(*intc_ic), GFP_KERNEL); if (!intc_ic) @@ -110,27 +148,37 @@ static int __init aspeed_intc_ic_of_init(struct device_node *node, goto err_iounmap; } - raw_spin_lock_init(&intc_ic->gic_lock); raw_spin_lock_init(&intc_ic->intc_lock); - /* Check all the irq numbers valid. If not, unmaps all the base and frees the data. */ - for (i = 0; i < of_irq_count(node); i++) { + irq_count = of_irq_count(node); + if (irq_count == 0) { + pr_err("Failed to get irq count\n"); + ret = -EINVAL; + goto err_iounmap; + } + + for (i = 0; i < irq_count; i++) { irq = irq_of_parse_and_map(node, i); if (!irq) { pr_err("Failed to get irq number\n"); ret = -EINVAL; goto err_iounmap; + } else { + if (irq_count > 1) + irq_set_chained_handler_and_data(irq, aspeed_intc0_ic_irq_handler, intc_ic); + else + irq_set_chained_handler_and_data(irq, aspeed_intc1_ic_irq_handler, intc_ic); } } - for (i = 0; i < of_irq_count(node); i++) { - irq = irq_of_parse_and_map(node, i); - irq_set_chained_handler_and_data(irq, aspeed_intc_ic_irq_handler, intc_ic); - } - return 0; err_iounmap: + for (i = 0; i < irq_count; i++) { + irq = irq_of_parse_and_map(node, i); + if (irq) + irq_dispose_mapping(irq); + } iounmap(intc_ic->base); err_free_ic: kfree(intc_ic); diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index c0c3f282499074..6970f7cc745f63 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -47,6 +47,15 @@ config PCIE_APPLE If unsure, say Y if you have an Apple Silicon system. +config PCIE_ASPEED + bool "ASPEED PCIe controller" + depends on PCI + depends on OF || COMPILE_TEST + select PCI_MSI_ARCH_FALLBACKS + help + Say Y here if you want PCIe controller support on + ASPEED SoCs. + config PCI_VERSATILE bool "ARM Versatile PB PCI controller" depends on ARCH_VERSATILE || COMPILE_TEST diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index 37c8663de7fe1f..cede8534782903 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o +obj-$(CONFIG_PCIE_ASPEED) += pcie-aspeed.o obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o diff --git a/drivers/pci/controller/pcie-aspeed.c b/drivers/pci/controller/pcie-aspeed.c new file mode 100644 index 00000000000000..49d1c3fa876b7b --- /dev/null +++ b/drivers/pci/controller/pcie-aspeed.c @@ -0,0 +1,1222 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PCIe host controller driver for ASPEED PCIe Bridge + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pci.h" + +#define MAX_MSI_HOST_IRQS 64 + +/* AST2600 AHBC Registers */ +#define AHBC_KEY 0x00 +#define AHBC_UNLOCK 0xAEED1A03 +#define AHBC_ADDR_MAPPING 0x8C +#define PCIE_RC_MEMORY_EN BIT(5) + +/* AST2600 PCIe Host Controller Registers */ +#define PEHR_MISC_10 0x10 +#define DATALINK_REPORT_CAPABLE BIT(4) +#define PEHR_MISC_14 0x14 +#define HOTPLUG_CAPABLE_ENABLE BIT(6) +#define HOTPLUG_SURPRISE_ENABLE BIT(5) +#define ATTENTION_BUTTON_ENABLE BIT(0) +#define PEHR_GLOBAL 0x30 +#define RC_SYNC_RESET_DISABLE BIT(20) +#define PCIE_RC_SLOT_ENABLE BIT(1) +#define ROOT_COMPLEX_ID(x) ((x) << 4) +#define PEHR_LOCK 0x7C +#define PCIE_UNLOCK 0xa8 +#define PEHR_LINK 0xC0 +#define PCIE_LINK_STS BIT(5) + +/* AST2600 H2X Controller Registers */ +/* Common Registers*/ +#define H2X_INT_STS 0x08 +#define PCIE_TX_IDLE_CLEAR BIT(0) +#define H2X_TX_DESC0 0x10 +#define H2X_TX_DESC1 0x14 +#define H2X_TX_DESC2 0x18 +#define H2X_TX_DESC3 0x1C +#define H2X_TX_DESC_DATA 0x20 +#define H2X_STS 0x24 +#define PCIE_TX_IDLE BIT(31) +#define PCIE_STATUS_OF_TX GENMASK(25, 24) +#define PCIE_RC_L_TX_COMPLETE BIT(24) +#define PCIE_RC_H_TX_COMPLETE BIT(25) +#define PCIE_TRIGGER_TX BIT(0) +#define H2X_AHB_ADDR_CONFIG0 0x60 +#define H2X_AHB_ADDR_CONFIG1 0x64 +#define H2X_AHB_ADDR_CONFIG2 0x68 +/* Device Registers */ +#define H2X_DEV_CTRL 0x00 +#define PCIE_RX_DMA_EN BIT(9) +#define PCIE_RX_LINEAR BIT(8) +#define PCIE_RX_MSI_SEL BIT(7) +#define PCIE_RX_MSI_EN BIT(6) +#define PCIE_UNLOCK_RX_BUFF BIT(4) +#define PCIE_Wait_RX_TLP_CLR BIT(2) +#define PCIE_RC_RX_ENABLE BIT(1) +#define PCIE_RC_ENABLE BIT(0) +#define H2X_DEV_STS 0x08 +#define PCIE_RC_RX_DONE_ISR BIT(4) +#define H2X_DEV_RX_DESC_DATA 0x0C +#define H2X_DEV_RX_DESC1 0x14 +#define H2X_DEV_TX_TAG 0x3C + +/* AST2700 H2X */ +#define H2X_CTRL 0x00 +#define H2X_BRIDGE_EN BIT(0) +#define H2X_BRIDGE_DIRECT_EN BIT(1) +#define H2X_CFGE_INT_STS 0x08 +#define CFGE_TX_IDLE BIT(0) +#define CFGE_RX_BUSY BIT(1) +#define H2X_CFGI_TLP 0x20 +#define H2X_CFGI_WR_DATA 0x24 +#define H2X_CFGI_CTRL 0x28 +#define CFGI_TLP_FIRE BIT(0) +#define H2X_CFGI_RET_DATA 0x2C +#define H2X_CFGE_TLP_1ST 0x30 +#define H2X_CFGE_TLP_NEXT 0x34 +#define H2X_CFGE_CTRL 0x38 +#define CFGE_TLP_FIRE BIT(0) +#define H2X_CFGE_RET_DATA 0x3C +#define H2X_REMAP_PREF_ADDR 0x70 +#define H2X_REMAP_DIRECT_ADDR 0x78 + +/* AST2700 PEHR */ +#define PEHR_VID_DID 0x00 +#define PEHR_MISC_44 0x44 +#define ENABLE_SLOT_CAP BIT(12) +#define PEHR_MISC_38 0x38 +#define DATALINK_REPORT_CAP BIT(20) +#define PEHR_MISC_3C 0x3C +#define PEHR_MISC_58 0x58 +#define LOCAL_SCALE_SUP BIT(0) +#define PEHR_MISC_5C 0x5C +#define PEHR_MISC_60 0x60 +#define PORT_TPYE GENMASK(7, 4) +#define PORT_TYPE_ROOT BIT(2) +#define PEHR_MISC_70 0x70 +#define PEHR_MISC_78 0x78 +#define PEHR_MISC_1B8 0x1B8 +#define SW_ATT_BTN BIT(0) +#define PEHR_MISC_344 0x344 +#define LINK_STATUS_GEN2 BIT(18) +#define PEHR_MISC_358 0x358 +#define LINK_STATUS_GEN4 BIT(8) + +/* AST2700 SCU */ +#define SCU_60 0x60 +#define RC_E2M_PATH_EN BIT(0) +#define RC_H2XS_PATH_EN BIT(16) +#define RC_H2XD_PATH_EN BIT(17) +#define RC_H2XX_PATH_EN BIT(18) +#define RC_UPSTREAM_MEM_EN BIT(19) +#define SCU_64 0x64 +#define SCU_70 0x70 +#define SCU_78 0x78 + +/* TLP configuration type 0 and type 1 */ +#define CRG_READ_FMTTYPE(type) (0x04000000 | (type << 24)) +#define CRG_WRITE_FMTTYPE(type) (0x44000000 | (type << 24)) +#define CRG_PAYLOAD_SIZE 0x01 /* 1 DWORD */ +#define TLP_COMP_STATUS(s) (((s) >> 13) & 7) + +struct aspeed_pcie_rc_platform { + int (*setup)(struct platform_device *pdev); + /* Interrupt Register Offset */ + int reg_intx_en; + int reg_intx_sts; + int reg_msi_en; + int reg_msi_sts; + int msi_address; +}; + +struct aspeed_pcie { + struct pci_host_bridge *host; + struct device *dev; + void __iomem *reg; + struct regmap *ahbc; + struct regmap *cfg; + struct regmap *pciephy; + struct clk *clock; + const struct aspeed_pcie_rc_platform *platform; + + int domain; + u8 tx_tag; + int host_bus_num; + + struct reset_control *h2xrst; + struct reset_control *perst; + + struct irq_domain *irq_domain; + struct irq_domain *dev_domain; + struct irq_domain *msi_domain; + struct mutex lock; + + int hotplug_event; + struct gpio_desc *perst_ep_in; + struct gpio_desc *perst_rc_out; + struct gpio_desc *perst_owner; + struct delayed_work rst_dwork; + DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_HOST_IRQS); +}; + +static void aspeed_pcie_intx_ack_irq(struct irq_data *d) +{ + struct aspeed_pcie *pcie = irq_data_get_irq_chip_data(d); + int intx_en = pcie->platform->reg_intx_en; + + writel(readl(pcie->reg + intx_en) | BIT(d->hwirq), pcie->reg + intx_en); +} + +static void aspeed_pcie_intx_mask_irq(struct irq_data *d) +{ + struct aspeed_pcie *pcie = irq_data_get_irq_chip_data(d); + int intx_en = pcie->platform->reg_intx_en; + + writel(readl(pcie->reg + intx_en) & ~BIT(d->hwirq), pcie->reg + intx_en); +} + +static void aspeed_pcie_intx_unmask_irq(struct irq_data *d) +{ + struct aspeed_pcie *pcie = irq_data_get_irq_chip_data(d); + int intx_en = pcie->platform->reg_intx_en; + + writel(readl(pcie->reg + intx_en) | BIT(d->hwirq), pcie->reg + intx_en); +} + +static struct irq_chip aspeed_intx_irq_chip = { + .name = "ASPEED:IntX", + .irq_ack = aspeed_pcie_intx_ack_irq, + .irq_mask = aspeed_pcie_intx_mask_irq, + .irq_unmask = aspeed_pcie_intx_unmask_irq, +}; + +static int aspeed_pcie_intx_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_set_chip_and_handler(irq, &aspeed_intx_irq_chip, handle_level_irq); + irq_set_chip_data(irq, domain->host_data); + irq_set_status_flags(irq, IRQ_LEVEL); + + return 0; +} + +static const struct irq_domain_ops aspeed_intx_domain_ops = { + .map = aspeed_pcie_intx_map, +}; + +static irqreturn_t aspeed_pcie_intr_handler(int irq, void *dev_id) +{ + struct aspeed_pcie *pcie = dev_id; + const struct aspeed_pcie_rc_platform *platform = pcie->platform; + unsigned long status; + unsigned long intx; + u32 bit; + int i; + + intx = readl(pcie->reg + platform->reg_intx_sts) & 0xf; + if (intx) { + for_each_set_bit(bit, &intx, PCI_NUM_INTX) + generic_handle_domain_irq(pcie->irq_domain, bit); + } + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + for (i = 0; i < 2; i++) { + status = readl(pcie->reg + platform->reg_msi_sts + (i * 4)); + writel(status, pcie->reg + platform->reg_msi_sts + (i * 4)); + /* Workaround: AST2700 MSI needs to cleat status twice */ + if (of_device_is_compatible(pcie->dev->of_node, "aspeed,ast2700-pcie")) + writel(status, pcie->reg + platform->reg_msi_sts + (i * 4)); + if (!status) + continue; + + for_each_set_bit(bit, &status, 32) { + if (i) + bit += 32; + generic_handle_domain_irq(pcie->dev_domain, bit); + } + } + } + + return IRQ_HANDLED; +} + +void aspeed_pcie_set_slot_power_limit(struct aspeed_pcie *pcie) +{ + u32 cfg_val, isr; + int ret; + + writel(BIT(4) | readl(pcie->reg), pcie->reg); + + pcie->tx_tag %= 0x7; + regmap_write(pcie->cfg, H2X_TX_DESC0, 0x74000001); + regmap_write(pcie->cfg, H2X_TX_DESC1, 0x00200050 | (pcie->tx_tag << 8)); + regmap_write(pcie->cfg, H2X_TX_DESC2, 0); + regmap_write(pcie->cfg, H2X_TX_DESC3, 0); + regmap_write(pcie->cfg, H2X_TX_DESC_DATA, 0x1a); + + regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX); + + ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val, + (cfg_val & PCIE_TX_IDLE), 0, 50); + if (ret) + goto out; + + regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR, + PCIE_TX_IDLE_CLEAR); + + regmap_read(pcie->cfg, H2X_STS, &cfg_val); + switch (cfg_val & PCIE_STATUS_OF_TX) { + case PCIE_RC_L_TX_COMPLETE: + case PCIE_RC_H_TX_COMPLETE: + ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr, + (isr & PCIE_RC_RX_DONE_ISR), 0, 50); + if (ret) + dev_err(pcie->dev, "[%d] : tx timeout [%x]\n", + pcie->domain, isr); + + writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS); + break; + } +out: + pcie->tx_tag++; +} + +static int aspeed_ast2600_rd_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct aspeed_pcie *pcie = bus->sysdata; + u32 bdf_offset; + int rx_done_fail = 0, slot = PCI_SLOT(devfn); + u32 cfg_val, isr, type = 0; + u32 link_sts = 0; + int ret; + + /* Driver may set unlock RX buffere before triggering next TX config */ + writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL), + pcie->reg + H2X_DEV_CTRL); + + if (bus->number == pcie->host_bus_num && slot != 0 && slot != 8) + return PCIBIOS_DEVICE_NOT_FOUND; + type = (bus->number > pcie->host_bus_num); + + if (type) { + regmap_read(pcie->pciephy, PEHR_LINK, &link_sts); + if (!(link_sts & PCIE_LINK_STS)) + return PCIBIOS_DEVICE_NOT_FOUND; + } + + bdf_offset = ((bus->number) << 24) | (PCI_SLOT(devfn) << 19) | + (PCI_FUNC(devfn) << 16) | (where & ~3); + + pcie->tx_tag %= 0x7; + + regmap_write(pcie->cfg, H2X_TX_DESC0, 0x04000001 | (type << 24)); + regmap_write(pcie->cfg, H2X_TX_DESC1, 0x0000200f | (pcie->tx_tag << 8)); + regmap_write(pcie->cfg, H2X_TX_DESC2, bdf_offset); + regmap_write(pcie->cfg, H2X_TX_DESC3, 0x00000000); + + regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX); + + ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val, + (cfg_val & PCIE_TX_IDLE), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CR tx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), cfg_val); + goto out; + } + + regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR, + PCIE_TX_IDLE_CLEAR); + + regmap_read(pcie->cfg, H2X_STS, &cfg_val); + switch (cfg_val & PCIE_STATUS_OF_TX) { + case PCIE_RC_L_TX_COMPLETE: + case PCIE_RC_H_TX_COMPLETE: + ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr, + (isr & PCIE_RC_RX_DONE_ISR), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CR rx timeoutsts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), isr); + rx_done_fail = 1; + *val = ~0; + } + if (!rx_done_fail) { + if (readl(pcie->reg + H2X_DEV_RX_DESC1) & BIT(13)) + *val = ~0; + else + *val = readl(pcie->reg + H2X_DEV_RX_DESC_DATA); + } + + writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL), + pcie->reg + H2X_DEV_CTRL); + break; + case PCIE_STATUS_OF_TX: + *val = ~0; + break; + default: + regmap_read(pcie->cfg, H2X_DEV_RX_DESC_DATA, &cfg_val); + *val = cfg_val; + break; + } + + switch (size) { + case 1: + *val = (*val >> ((where & 3) * 8)) & 0xff; + break; + case 2: + *val = (*val >> ((where & 2) * 8)) & 0xffff; + break; + } + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) { + if (where == (0x80 + PCI_EXP_SLTSTA) && + bus->number == pcie->host_bus_num && + PCI_SLOT(devfn) == 0x8 && + PCI_FUNC(devfn) == 0x0 && + pcie->hotplug_event) + *val |= PCI_EXP_SLTSTA_ABP; + } + + ret = PCIBIOS_SUCCESSFUL; +out: + writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS); + pcie->tx_tag++; + return ret; +} + +static int aspeed_ast2600_wr_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 type = 0; + u32 shift = 8 * (where & 3); + u32 bdf_offset; + u8 byte_en = 0; + struct aspeed_pcie *pcie = bus->sysdata; + u32 isr, cfg_val; + int ret; + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) { + if (where == (0x80 + PCI_EXP_SLTSTA) && + bus->number == pcie->host_bus_num && + PCI_SLOT(devfn) == 0x8 && + PCI_FUNC(devfn) == 0x0 && + pcie->hotplug_event && + (val & PCI_EXP_SLTSTA_ABP)) { + pcie->hotplug_event = 0; + return PCIBIOS_SUCCESSFUL; + } + } + + /* Driver may set unlock RX buffere before triggering next TX config */ + writel(PCIE_UNLOCK_RX_BUFF | readl(pcie->reg + H2X_DEV_CTRL), + pcie->reg + H2X_DEV_CTRL); + + switch (size) { + case 1: + byte_en = 1 << (where % 4); + val = (val & 0xff) << shift; + break; + case 2: + byte_en = 0x3 << (2 * ((where >> 1) % 2)); + val = (val & 0xffff) << shift; + break; + default: + byte_en = 0xf; + break; + } + + type = (bus->number > pcie->host_bus_num); + + bdf_offset = (bus->number << 24) | (PCI_SLOT(devfn) << 19) | + (PCI_FUNC(devfn) << 16) | (where & ~3); + pcie->tx_tag %= 0x7; + + regmap_write(pcie->cfg, H2X_TX_DESC0, 0x44000001 | (type << 24)); + regmap_write(pcie->cfg, H2X_TX_DESC1, + 0x00002000 | (pcie->tx_tag << 8) | byte_en); + regmap_write(pcie->cfg, H2X_TX_DESC2, bdf_offset); + regmap_write(pcie->cfg, H2X_TX_DESC3, 0x00000000); + regmap_write(pcie->cfg, H2X_TX_DESC_DATA, val); + + regmap_write_bits(pcie->cfg, H2X_STS, PCIE_TRIGGER_TX, PCIE_TRIGGER_TX); + + ret = regmap_read_poll_timeout(pcie->cfg, H2X_STS, cfg_val, + (cfg_val & PCIE_TX_IDLE), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CT tx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), cfg_val); + ret = PCIBIOS_SET_FAILED; + goto out; + } + + regmap_write_bits(pcie->cfg, H2X_INT_STS, PCIE_TX_IDLE_CLEAR, + PCIE_TX_IDLE_CLEAR); + + regmap_read(pcie->cfg, H2X_STS, &cfg_val); + switch (cfg_val & PCIE_STATUS_OF_TX) { + case PCIE_RC_L_TX_COMPLETE: + case PCIE_RC_H_TX_COMPLETE: + ret = readl_poll_timeout(pcie->reg + H2X_DEV_STS, isr, + (isr & PCIE_RC_RX_DONE_ISR), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CT rx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), isr); + ret = PCIBIOS_SET_FAILED; + goto out; + } + break; + } + ret = PCIBIOS_SUCCESSFUL; +out: + writel(readl(pcie->reg + H2X_DEV_STS), pcie->reg + H2X_DEV_STS); + pcie->tx_tag++; + return ret; +} + +static bool aspeed_ast2700_get_link(struct aspeed_pcie *pcie) +{ + u32 reg; + bool link; + + if (pcie->domain == 2) { + regmap_read(pcie->pciephy, PEHR_MISC_344, ®); + link = !!(reg & LINK_STATUS_GEN2); + } else { + regmap_read(pcie->pciephy, PEHR_MISC_358, ®); + link = !!(reg & LINK_STATUS_GEN4); + } + + return link; +} + +static int aspeed_ast2700_rd_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct aspeed_pcie *pcie = bus->sysdata; + u32 bdf_offset, status; + u8 type; + int ret; + + if ((bus->number == pcie->host_bus_num && devfn != 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == pcie->host_bus_num) { + /* Internal access to bridge */ + writel(0xF << 16 | (where & ~3), pcie->reg + H2X_CFGI_TLP); + writel(CFGI_TLP_FIRE, pcie->reg + H2X_CFGI_CTRL); + *val = readl(pcie->reg + H2X_CFGI_RET_DATA); + } else { + bdf_offset = ((bus->number) << 24) | (PCI_SLOT(devfn) << 19) | + (PCI_FUNC(devfn) << 16) | (where & ~3); + + pcie->tx_tag %= 0xF; + + type = (bus->number == (pcie->host_bus_num + 1)) ? + PCI_HEADER_TYPE_NORMAL : + PCI_HEADER_TYPE_BRIDGE; + + writel(CRG_READ_FMTTYPE(type) | CRG_PAYLOAD_SIZE, pcie->reg + H2X_CFGE_TLP_1ST); + writel(0x40100F | (pcie->tx_tag << 8), pcie->reg + H2X_CFGE_TLP_NEXT); + writel(bdf_offset, pcie->reg + H2X_CFGE_TLP_NEXT); + writel(CFGE_TX_IDLE | CFGE_RX_BUSY, pcie->reg + H2X_CFGE_INT_STS); + writel(CFGE_TLP_FIRE, pcie->reg + H2X_CFGE_CTRL); + + ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status, + (status & CFGE_TX_IDLE), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CR tx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), status); + goto out; + } + + ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status, + (status & CFGE_RX_BUSY), 0, 50000); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CR rx timeoutsts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), status); + goto out; + } + *val = readl(pcie->reg + H2X_CFGE_RET_DATA); + } + + switch (size) { + case 1: + *val = (*val >> ((where & 3) * 8)) & 0xff; + break; + case 2: + *val = (*val >> ((where & 2) * 8)) & 0xffff; + break; + } + + writel(status, pcie->reg + H2X_CFGE_INT_STS); + pcie->tx_tag++; + return PCIBIOS_SUCCESSFUL; +out: + *val = ~0; + writel(status, pcie->reg + H2X_CFGE_INT_STS); + pcie->tx_tag++; + return PCIBIOS_SET_FAILED; +} + +static int aspeed_ast2700_wr_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct aspeed_pcie *pcie = bus->sysdata; + u32 shift = 8 * (where & 3); + u8 byte_en; + u32 bdf_offset, status, type; + int ret; + + if ((bus->number == pcie->host_bus_num && devfn != 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 1: + byte_en = 1 << (where % 4); + val = (val & 0xff) << shift; + break; + case 2: + byte_en = 0x3 << (2 * ((where >> 1) % 2)); + val = (val & 0xffff) << shift; + break; + default: + byte_en = 0xf; + break; + } + + if (bus->number == pcie->host_bus_num) { + /* Internal access to bridge */ + writel(0x100000 | byte_en << 16 | (where & ~3), pcie->reg + H2X_CFGI_TLP); + writel(val, pcie->reg + H2X_CFGI_WR_DATA); + writel(CFGI_TLP_FIRE, pcie->reg + H2X_CFGI_CTRL); + } else { + bdf_offset = (bus->number << 24) | (PCI_SLOT(devfn) << 19) | + (PCI_FUNC(devfn) << 16) | (where & ~3); + pcie->tx_tag %= 0xF; + + type = (bus->number == (pcie->host_bus_num + 1)) ? + PCI_HEADER_TYPE_NORMAL : + PCI_HEADER_TYPE_BRIDGE; + + writel(CRG_WRITE_FMTTYPE(type) | CRG_PAYLOAD_SIZE, pcie->reg + H2X_CFGE_TLP_1ST); + writel(0x401000 | (pcie->tx_tag << 8) | byte_en, pcie->reg + H2X_CFGE_TLP_NEXT); + writel(bdf_offset, pcie->reg + H2X_CFGE_TLP_NEXT); + writel(val, pcie->reg + H2X_CFGE_TLP_NEXT); + writel(CFGE_TX_IDLE | CFGE_RX_BUSY, pcie->reg + H2X_CFGE_INT_STS); + writel(CFGE_TLP_FIRE, pcie->reg + H2X_CFGE_CTRL); + + ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status, + (status & CFGE_TX_IDLE), 0, 50); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CT tx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), status); + ret = PCIBIOS_SET_FAILED; + goto out; + } + + ret = readl_poll_timeout(pcie->reg + H2X_CFGE_INT_STS, status, + (status & CFGE_RX_BUSY), 0, 50000); + if (ret) { + dev_err(pcie->dev, + "[%X:%02X:%02X.%02X]CT rx timeout sts: 0x%08x\n", + pcie->domain, bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), status); + ret = PCIBIOS_SET_FAILED; + goto out; + } + + (void)readl(pcie->reg + H2X_CFGE_RET_DATA); + } + ret = PCIBIOS_SUCCESSFUL; +out: + writel(status, pcie->reg + H2X_CFGE_INT_STS); + pcie->tx_tag++; + return ret; +} + +static struct pci_ops aspeed_ast2600_pcie_ops = { + .read = aspeed_ast2600_rd_conf, + .write = aspeed_ast2600_wr_conf, +}; + +static struct pci_ops aspeed_ast2700_pcie_ops = { + .read = aspeed_ast2700_rd_conf, + .write = aspeed_ast2700_wr_conf, +}; + +#ifdef CONFIG_PCI_MSI +static void aspeed_msi_compose_msi_msg(struct irq_data *data, + struct msi_msg *msg) +{ + struct aspeed_pcie *pcie = irq_data_get_irq_chip_data(data); + + msg->address_hi = 0; + msg->address_lo = pcie->platform->msi_address; + msg->data = data->hwirq; +} + +static int aspeed_msi_set_affinity(struct irq_data *irq_data, + const struct cpumask *mask, bool force) +{ + return -EINVAL; +} + +static struct irq_chip aspeed_msi_bottom_irq_chip = { + .name = "ASPEED MSI", + .irq_compose_msi_msg = aspeed_msi_compose_msi_msg, + .irq_set_affinity = aspeed_msi_set_affinity, +}; + +static int aspeed_irq_msi_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *args) +{ + struct aspeed_pcie *pcie = domain->host_data; + int bit; + int i; + + mutex_lock(&pcie->lock); + + bit = bitmap_find_free_region(pcie->msi_irq_in_use, MAX_MSI_HOST_IRQS, + get_count_order(nr_irqs)); + + mutex_unlock(&pcie->lock); + + if (bit < 0) + return -ENOSPC; + + for (i = 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, bit + i, + &aspeed_msi_bottom_irq_chip, + domain->host_data, handle_simple_irq, NULL, + NULL); + } + + return 0; +} + +static void aspeed_irq_msi_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + struct irq_data *data = irq_domain_get_irq_data(domain, virq); + struct aspeed_pcie *pcie = irq_data_get_irq_chip_data(data); + + mutex_lock(&pcie->lock); + + bitmap_release_region(pcie->msi_irq_in_use, data->hwirq, + get_count_order(nr_irqs)); + + mutex_unlock(&pcie->lock); +} + +static const struct irq_domain_ops aspeed_msi_domain_ops = { + .alloc = aspeed_irq_msi_domain_alloc, + .free = aspeed_irq_msi_domain_free, +}; + +static struct irq_chip aspeed_msi_irq_chip = { + .name = "PCIe MSI", + .irq_enable = pci_msi_unmask_irq, + .irq_disable = pci_msi_mask_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, +}; + +static struct msi_domain_info aspeed_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), + .chip = &aspeed_msi_irq_chip, +}; +#endif + +static void aspeed_pcie_irq_domain_free(struct aspeed_pcie *pcie) +{ + if (pcie->irq_domain) { + irq_domain_remove(pcie->irq_domain); + pcie->irq_domain = NULL; + } +#ifdef CONFIG_PCI_MSI + if (pcie->msi_domain) { + irq_domain_remove(pcie->msi_domain); + pcie->msi_domain = NULL; + } + + if (pcie->dev_domain) { + irq_domain_remove(pcie->dev_domain); + pcie->dev_domain = NULL; + } +#endif +} + +static int aspeed_pcie_init_irq_domain(struct aspeed_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct device_node *node = dev->of_node; + struct device_node *pcie_intc_node; + int ret; + + pcie_intc_node = of_get_next_child(node, NULL); + if (!pcie_intc_node) + return dev_err_probe(dev, -ENODEV, "No PCIe Intc node found\n"); + + pcie->irq_domain = + irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, &aspeed_intx_domain_ops, pcie); + of_node_put(pcie_intc_node); + if (!pcie->irq_domain) { + ret = dev_err_probe(dev, -ENOMEM, "failed to get an INTx IRQ domain\n"); + goto err; + } + + writel(0, pcie->reg + pcie->platform->reg_intx_en); + writel(~0, pcie->reg + pcie->platform->reg_intx_sts); + +#ifdef CONFIG_PCI_MSI + pcie->dev_domain = + irq_domain_add_linear(NULL, MAX_MSI_HOST_IRQS, &aspeed_msi_domain_ops, pcie); + if (!pcie->dev_domain) { + ret = dev_err_probe(pcie->dev, -ENOMEM, "failed to create IRQ domain\n"); + goto err; + } + + pcie->msi_domain = pci_msi_create_irq_domain(dev_fwnode(pcie->dev), &aspeed_msi_domain_info, + pcie->dev_domain); + if (!pcie->msi_domain) { + ret = dev_err_probe(pcie->dev, -ENOMEM, "failed to create MSI domain\n"); + goto err; + } + + writel(~0, pcie->reg + pcie->platform->reg_msi_en); + writel(~0, pcie->reg + pcie->platform->reg_msi_en + 0x04); + writel(~0, pcie->reg + pcie->platform->reg_msi_sts); + writel(~0, pcie->reg + pcie->platform->reg_msi_sts + 0x04); +#endif + return 0; +err: + aspeed_pcie_irq_domain_free(pcie); + return ret; +} + +static void aspeed_pcie_port_init(struct aspeed_pcie *pcie) +{ + u32 link_sts = 0; + + regmap_write(pcie->pciephy, PEHR_LOCK, PCIE_UNLOCK); + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) { + regmap_write(pcie->pciephy, PEHR_GLOBAL, + RC_SYNC_RESET_DISABLE | ROOT_COMPLEX_ID(0x3) | PCIE_RC_SLOT_ENABLE); + regmap_write(pcie->pciephy, PEHR_MISC_10, 0xd7040022 | DATALINK_REPORT_CAPABLE); + regmap_write(pcie->pciephy, PEHR_MISC_14, + HOTPLUG_CAPABLE_ENABLE | HOTPLUG_SURPRISE_ENABLE | + ATTENTION_BUTTON_ENABLE); + } else { + regmap_write(pcie->pciephy, PEHR_GLOBAL, ROOT_COMPLEX_ID(0x3)); + } + + if (pcie->perst_rc_out) { + mdelay(100); + gpiod_set_value(pcie->perst_rc_out, 1); + } + + reset_control_deassert(pcie->perst); + mdelay(500); + + writel(PCIE_RX_DMA_EN | PCIE_RX_LINEAR | PCIE_RX_MSI_SEL | PCIE_RX_MSI_EN | + PCIE_Wait_RX_TLP_CLR | PCIE_RC_RX_ENABLE | PCIE_RC_ENABLE, + pcie->reg + H2X_DEV_CTRL); + + writel(0x28, pcie->reg + H2X_DEV_TX_TAG); + + regmap_read(pcie->pciephy, PEHR_LINK, &link_sts); + if (link_sts & PCIE_LINK_STS) + // aspeed_pcie_set_slot_power_limit(pcie); + dev_info(pcie->dev, "PCIE- Link up\n"); + else + dev_info(pcie->dev, "PCIE- Link down\n"); +} + + +static ssize_t hotplug_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct aspeed_pcie *pcie = dev_get_drvdata(dev); + + pcie->hotplug_event = 1; + + if (of_device_is_compatible(pcie->dev->of_node, "aspeed,ast2700-pcie")) { + regmap_write_bits(pcie->pciephy, PEHR_MISC_1B8, SW_ATT_BTN, SW_ATT_BTN); + regmap_clear_bits(pcie->pciephy, PEHR_MISC_1B8, SW_ATT_BTN); + } + + return len; +} + +static DEVICE_ATTR_WO(hotplug); + +static void aspeed_pcie_reset_work(struct work_struct *work) +{ + struct aspeed_pcie *pcie = + container_of(work, typeof(*pcie), rst_dwork.work); + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct pci_bus *parent = host->bus; + struct pci_dev *dev, *temp; + u32 link_sts = 0; + u16 command; + + pci_lock_rescan_remove(); + + list_for_each_entry_safe_reverse(dev, temp, &parent->devices, + bus_list) { + pci_dev_get(dev); + pci_stop_and_remove_bus_device(dev); + /* + * Ensure that no new Requests will be generated from + * the device. + */ + pci_read_config_word(dev, PCI_COMMAND, &command); + command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); + command |= PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(dev, PCI_COMMAND, command); + pci_dev_put(dev); + } + + /* + * With perst_rc_out GPIO, the perst will only affect our PCIe controller, so it only + * needs to stay low for 1ms. + * Without perst_rc_out GPIO, the perst will affect external devices, so it needs to + * follow the spec and stay low for at least 100ms. + */ + reset_control_assert(pcie->perst); + if (pcie->perst_rc_out) { + gpiod_set_value(pcie->perst_rc_out, 0); + mdelay(1); + } else { + mdelay(100); + } + reset_control_deassert(pcie->perst); + if (pcie->perst_rc_out) { + mdelay(100); + gpiod_set_value(pcie->perst_rc_out, 1); + } + mdelay(10); + + regmap_read(pcie->pciephy, PEHR_LINK, &link_sts); + if (link_sts & PCIE_LINK_STS) + dev_info(pcie->dev, "PCIE- Link up\n"); + else + dev_info(pcie->dev, "PCIE- Link down\n"); + + pci_rescan_bus(host->bus); + pci_unlock_rescan_remove(); +} + +static irqreturn_t pcie_rst_irq_handler(int irq, void *dev_id) +{ + struct aspeed_pcie *pcie = dev_id; + + schedule_delayed_work(&pcie->rst_dwork, 0); + + return IRQ_HANDLED; +} + +static int aspeed_ast2600_setup(struct platform_device *pdev) +{ + struct aspeed_pcie *pcie = platform_get_drvdata(pdev); + struct device *dev = pcie->dev; + int ret; + + if (pcie->host_bus_num != 0x80) { + dev_err(dev, "AST2600 only supports to start bus number 0x80\n"); + return -EINVAL; + } + + pcie->ahbc = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,ahbc"); + if (IS_ERR(pcie->ahbc)) + return dev_err_probe(dev, PTR_ERR(pcie->ahbc), "failed to map ahbc base\n"); + + reset_control_assert(pcie->h2xrst); + mdelay(5); + reset_control_deassert(pcie->h2xrst); + + regmap_write(pcie->ahbc, AHBC_KEY, AHBC_UNLOCK); + regmap_update_bits(pcie->ahbc, AHBC_ADDR_MAPPING, PCIE_RC_MEMORY_EN, PCIE_RC_MEMORY_EN); + regmap_write(pcie->ahbc, AHBC_KEY, 0x1); + + regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG0, 0xe0006000); + regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG1, 0); + regmap_write(pcie->cfg, H2X_AHB_ADDR_CONFIG2, ~0); + + regmap_write(pcie->cfg, H2X_CTRL, H2X_BRIDGE_EN); + + aspeed_pcie_port_init(pcie); + + pcie->host->ops = &aspeed_ast2600_pcie_ops; + + pcie->perst_ep_in = devm_gpiod_get_optional(pcie->dev, "perst-ep-in", GPIOD_IN); + if (pcie->perst_ep_in) { + gpiod_set_debounce(pcie->perst_ep_in, 100); + irq_set_irq_type(gpiod_to_irq(pcie->perst_ep_in), IRQ_TYPE_EDGE_BOTH); + ret = devm_request_irq(pcie->dev, gpiod_to_irq(pcie->perst_ep_in), + pcie_rst_irq_handler, IRQF_SHARED, "PERST monitor", pcie); + if (ret) + return dev_err_probe(pcie->dev, ret, "Failed to request gpio irq\n"); + INIT_DELAYED_WORK(&pcie->rst_dwork, aspeed_pcie_reset_work); + } + pcie->perst_owner = + devm_gpiod_get_optional(pcie->dev, "perst-owner", GPIOD_OUT_HIGH); + + return 0; +} + +static int aspeed_ast2700_setup(struct platform_device *pdev) +{ + struct aspeed_pcie *pcie = platform_get_drvdata(pdev); + struct device *dev = pcie->dev; + u32 cfg_val; + + reset_control_assert(pcie->perst); + + regmap_write(pcie->pciephy, PEHR_MISC_70, 0xa00c0); + regmap_write(pcie->pciephy, PEHR_MISC_78, 0x80030); + regmap_write(pcie->pciephy, PEHR_MISC_58, LOCAL_SCALE_SUP); + + regmap_update_bits(pcie->cfg, SCU_60, + RC_E2M_PATH_EN | RC_H2XS_PATH_EN | RC_H2XD_PATH_EN | RC_H2XX_PATH_EN | + RC_UPSTREAM_MEM_EN, + RC_E2M_PATH_EN | RC_H2XS_PATH_EN | RC_H2XD_PATH_EN | RC_H2XX_PATH_EN | + RC_UPSTREAM_MEM_EN); + regmap_write(pcie->cfg, SCU_64, 0xff00ff00); + regmap_write(pcie->cfg, SCU_70, 0); + regmap_write(pcie->cfg, SCU_78, (pcie->domain == 1) ? BIT(31) : 0); + + reset_control_assert(pcie->h2xrst); + mdelay(10); + reset_control_deassert(pcie->h2xrst); + + regmap_write(pcie->pciephy, PEHR_MISC_5C, 0x40000000); + regmap_read(pcie->pciephy, PEHR_MISC_60, &cfg_val); + regmap_write(pcie->pciephy, PEHR_MISC_60, + (cfg_val & ~PORT_TPYE) | FIELD_PREP(PORT_TPYE, PORT_TYPE_ROOT)); + + writel(0, pcie->reg + H2X_CTRL); + writel(H2X_BRIDGE_EN | H2X_BRIDGE_DIRECT_EN, pcie->reg + H2X_CTRL); + + /* The BAR mapping: + * CPU Node0(domain 0): 0x60000000 + * CPU Node1(domain 1): 0x80000000 + * IO (domain 2): 0xa0000000 + */ + writel(0x60000000 + (0x20000000 * pcie->domain), pcie->reg + H2X_REMAP_DIRECT_ADDR); + + /* Prepare for 64-bit BAR pref */ + writel(0x3, pcie->reg + H2X_REMAP_PREF_ADDR); + + reset_control_deassert(pcie->perst); + if (pcie->perst_rc_out) + gpiod_set_value(pcie->perst_rc_out, 1); + mdelay(1000); + + pcie->host->ops = &aspeed_ast2700_pcie_ops; + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) { + regmap_write_bits(pcie->pciephy, PEHR_MISC_44, ENABLE_SLOT_CAP, + ENABLE_SLOT_CAP); + regmap_write(pcie->pciephy, PEHR_MISC_3C, + HOTPLUG_CAPABLE_ENABLE | HOTPLUG_SURPRISE_ENABLE | + ATTENTION_BUTTON_ENABLE); + regmap_write_bits(pcie->pciephy, PEHR_MISC_38, + DATALINK_REPORT_CAP, DATALINK_REPORT_CAP); + } + + if (!aspeed_ast2700_get_link(pcie)) + dev_info(dev, "PCIe Link DOWN"); + else + dev_info(dev, "PCIe Link UP"); + + return 0; +} + +static int aspeed_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pci_host_bridge *host; + struct aspeed_pcie *pcie; + struct device_node *node = dev->of_node; + struct resource bus_range; + const void *md = of_device_get_match_data(dev); + int irq, ret; + + if (!md) + return -ENODEV; + + host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); + if (!host) + return -ENOMEM; + + pcie = pci_host_bridge_priv(host); + pcie->dev = dev; + pcie->tx_tag = 0; + platform_set_drvdata(pdev, pcie); + + pcie->platform = md; + pcie->host = host; + + if (of_pci_parse_bus_range(node, &bus_range)) { + dev_warn(dev, "Failed to parse bus range\n"); + pcie->host_bus_num = 0; + } + pcie->host_bus_num = bus_range.start; + + pcie->reg = devm_platform_ioremap_resource(pdev, 0); + + pcie->domain = of_get_pci_domain_nr(node); + + pcie->cfg = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,pciecfg"); + if (IS_ERR(pcie->cfg)) + return dev_err_probe(dev, PTR_ERR(pcie->cfg), "Failed to map pciecfg base\n"); + + pcie->pciephy = syscon_regmap_lookup_by_phandle(node, "aspeed,pciephy"); + if (IS_ERR(pcie->pciephy)) + return dev_err_probe(dev, PTR_ERR(pcie->pciephy), "Failed to map pciephy base\n"); + + pcie->h2xrst = devm_reset_control_get_exclusive(dev, "h2x"); + if (IS_ERR(pcie->h2xrst)) + return dev_err_probe(dev, PTR_ERR(pcie->h2xrst), "Failed to get h2x reset\n"); + + pcie->perst = devm_reset_control_get_exclusive(dev, "perst"); + if (IS_ERR(pcie->perst)) + return dev_err_probe(dev, PTR_ERR(pcie->perst), "Failed to get perst reset\n"); + + pcie->perst_rc_out = devm_gpiod_get_optional(dev, "perst-rc-out", + GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); + + ret = devm_mutex_init(dev, &pcie->lock); + if (ret) + return dev_err_probe(dev, ret, "failed to init mutex\n"); + + ret = pcie->platform->setup(pdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to setup PCIe RC\n"); + + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) { + ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_hotplug.attr); + if (ret) + return dev_err_probe(&pdev->dev, ret, "unable to create sysfs interface\n"); + } + + host->sysdata = pcie; + + ret = aspeed_pcie_init_irq_domain(pcie); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize IntX/MSI domain\n"); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get IRQ\n"); + + ret = devm_request_irq(dev, irq, aspeed_pcie_intr_handler, IRQF_SHARED, + dev_name(dev), pcie); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + + pcie->clock = clk_get(dev, NULL); + if (IS_ERR(pcie->clock)) + return dev_err_probe(dev, PTR_ERR(pcie->clock), "Failed to request clock\n"); + + ret = clk_prepare_enable(pcie->clock); + if (ret) { + clk_put(pcie->clock); + return dev_err_probe(dev, ret, "Failed to enable the clock\n"); + } + + return pci_host_probe(host); +} + +static void aspeed_pcie_remove(struct platform_device *pdev) +{ + struct aspeed_pcie *pcie = platform_get_drvdata(pdev); + + if (pcie->clock) { + clk_disable_unprepare(pcie->clock); + clk_put(pcie->clock); + } + + pci_stop_root_bus(pcie->host->bus); + pci_remove_root_bus(pcie->host->bus); + aspeed_pcie_irq_domain_free(pcie); +} + +static struct aspeed_pcie_rc_platform pcie_rc_ast2600 = { + .setup = aspeed_ast2600_setup, + .reg_intx_en = 0x04, + .reg_intx_sts = 0x08, + .reg_msi_en = 0x20, + .reg_msi_sts = 0x28, + .msi_address = 0x1e77005c, +}; + +static struct aspeed_pcie_rc_platform pcie_rc_ast2700 = { + .setup = aspeed_ast2700_setup, + .reg_intx_en = 0x40, + .reg_intx_sts = 0x48, + .reg_msi_en = 0x50, + .reg_msi_sts = 0x58, + .msi_address = 0x000000f0, +}; + +static const struct of_device_id aspeed_pcie_of_match[] = { + { .compatible = "aspeed,ast2600-pcie", .data = &pcie_rc_ast2600 }, + { .compatible = "aspeed,ast2700-pcie", .data = &pcie_rc_ast2700 }, + {} +}; + +static struct platform_driver aspeed_pcie_driver = { + .driver = { + .name = "aspeed-pcie", + .suppress_bind_attrs = true, + .of_match_table = aspeed_pcie_of_match, + }, + .probe = aspeed_pcie_probe, + .remove_new = aspeed_pcie_remove, +}; + +module_platform_driver(aspeed_pcie_driver); + diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig index 574c6e05844aed..819a259686ecf7 100644 --- a/drivers/soc/aspeed/Kconfig +++ b/drivers/soc/aspeed/Kconfig @@ -7,34 +7,6 @@ menu "ASPEED SoC drivers" config ASPEED_BMC_DEV tristate "ASPEED BMC Device" -config ASPEED_LPC_CTRL - tristate "ASPEED LPC firmware cycle control" - select REGMAP - select MFD_SYSCON - default ARCH_ASPEED - help - Control LPC firmware cycle mappings through 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_SNOOP - tristate "ASPEED LPC snoop support" - select REGMAP - select MFD_SYSCON - default ARCH_ASPEED - help - Provides a driver to control the LPC snoop interface which - 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 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_UART_ROUTING tristate "ASPEED uart routing control" select REGMAP @@ -45,16 +17,6 @@ config ASPEED_UART_ROUTING users to perform runtime configuration of the RX muxes among the UART controllers and I/O pins. -config ASPEED_P2A_CTRL - tristate "ASPEED P2A (VGA MMIO to BMC) bridge control" - select REGMAP - select MFD_SYSCON - default ARCH_ASPEED - help - Control ASPEED P2A VGA MMIO to BMC mappings through ioctl()s. The - driver also provides an interface for userspace mappings to a - pre-defined region. - config ASPEED_SOCINFO bool "ASPEED SoC Information driver" default ARCH_ASPEED @@ -63,22 +25,13 @@ config ASPEED_SOCINFO help Say yes to support decoding of ASPEED BMC information. -config ASPEED_XDMA - tristate "ASPEED XDMA Engine Driver" - select REGMAP - select MFD_SYSCON - depends on HAS_DMA - help - Enable support for the XDMA Engine found on the ASPEED BMC - SoCs. The XDMA engine can perform PCIe DMA operations between the BMC - and a host processor. - -config ASPEED_SBC - bool "ASPEED Secure Boot Controller driver" - default MACH_ASPEED_G6 +config AST2700_ESPI + tristate "ASPEED AST2700 eSPI slave driver" help - Say yes to provide information about the secure boot controller in - debugfs. + Enable driver support for Aspeed AST2700 eSPI engine. The eSPI engine + plays as a slave device in BMC to communicate with the Host over + the eSPI interface. The four eSPI channels, namely peripheral, + virtual wire, out-of-band, and flash are supported. config ASPEED_UDMA tristate "Aspeed UDMA Engine Driver" @@ -88,33 +41,16 @@ config ASPEED_UDMA SOCs. The UDMA engine can perform UART DMA operations between the memory buffer and the UART/VUART devices. -config ASPEED_AST2700_ESPI - tristate "ASPEED AST2700 eSPI slave driver" - help - Enable driver support for Aspeed AST2700 eSPI engine. The eSPI engine - plays as a slave device in BMC to communicate with the Host over - the eSPI interface. The four eSPI channels, namely peripheral, - virtual wire, out-of-band, and flash are supported. - -config AST2600_ESPI - tristate - depends on ASPEED_ESPI - help - Enable driver support for Aspeed AST2600 eSPI engine. - -config AST2700_ESPI - tristate - depends on ASPEED_ESPI +config ASPEED_XDMA + tristate "ASPEED XDMA Engine Driver" + select REGMAP + select MFD_SYSCON + depends on HAS_DMA help - Enable driver support for Aspeed AST2600 eSPI engine. + Enable support for the XDMA Engine found on the ASPEED BMC + SoCs. The XDMA engine can perform PCIe DMA operations between the BMC + and a host processor. -config ASPEED_LPC_PCC - tristate "Aspeed Post Code Capture support" - depends on ARCH_ASPEED && REGMAP && MFD_SYSCON - help - Provides a driver to control the LPC PCC interface, - allowing the BMC to snoop data bytes written by the - the host to an arbitrary LPC I/O port. endmenu endif diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile index 8ace6c044702ae..728120e96c13b8 100644 --- a/drivers/soc/aspeed/Makefile +++ b/drivers/soc/aspeed/Makefile @@ -1,16 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o -obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o -obj-$(CONFIG_ASPEED_LPC_PCC) += aspeed-lpc-pcc.o +obj-$(CONFIG_ASPEED_BMC_DEV) += aspeed-bmc-dev.o obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o -obj-$(CONFIG_ASPEED_P2A_CTRL) += aspeed-p2a-ctrl.o obj-$(CONFIG_ASPEED_SOCINFO) += aspeed-socinfo.o -obj-$(CONFIG_ASPEED_SBC) += aspeed-sbc.o obj-$(CONFIG_ASPEED_XDMA) += aspeed-xdma.o +obj-$(CONFIG_AST2700_ESPI) += ast2700-espi.o obj-$(CONFIG_ASPEED_UDMA) += aspeed-udma.o -obj-$(CONFIG_AST2600_ESPI) += ast2600-espi.o -obj-$(CONFIG_ASPEED_AST2700_ESPI) += ast2700-espi.o -obj-$(CONFIG_ASPEED_BMC_DEV) += aspeed-bmc-dev.o obj-$(CONFIG_ARCH_ASPEED) += aspeed-usb-phy.o obj-$(CONFIG_ARCH_ASPEED) += aspeed-usb-hp.o -obj-$(CONFIG_ASPEED_MCTP) += ../../net/mctp/mctp-pcie.o aspeed-mctp.o diff --git a/drivers/soc/aspeed/aspeed-bmc-dev.c b/drivers/soc/aspeed/aspeed-bmc-dev.c index 68ce4c5eb0db40..57061b1816425c 100644 --- a/drivers/soc/aspeed/aspeed-bmc-dev.c +++ b/drivers/soc/aspeed/aspeed-bmc-dev.c @@ -22,8 +22,6 @@ #include #include -static DEFINE_IDA(bmc_device_ida); - #define SCU_TRIGGER_MSI /* AST2600 SCU */ @@ -38,6 +36,7 @@ static DEFINE_IDA(bmc_device_ida); /* AST2700 SCU */ #define SCU0_REVISION_ID 0x0 #define REVISION_ID GENMASK(23, 16) +#define SCU0_PCIE_CONF_CTRL 0x970 /* Host2BMC */ #define ASPEED_BMC_MEM_BAR 0xF10 #define PCIE2PCI_MEM_BAR_ENABLE BIT(1) @@ -119,7 +118,6 @@ struct aspeed_bmc_device { struct miscdevice miscdev; int id; void __iomem *reg_base; - void __iomem *bmc_mem_virt; dma_addr_t bmc_mem_phy; phys_addr_t bmc_mem_size; @@ -131,10 +129,9 @@ struct aspeed_bmc_device { const struct aspeed_platform *platform; /* AST2700 */ - struct regmap *config; struct regmap *device; struct regmap *e2m; - /*AST2600*/ + struct regmap *scu; int pcie_irq; }; @@ -180,9 +177,8 @@ static ssize_t aspeed_ast2600_queue_rx(struct file *filp, struct kobject *kobj, int ret; ret = wait_event_interruptible(queue->rx_wait, - ((readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & HOST2BMC_ENABLE_INTB) && !(readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & - ((index == QUEUE1) ? HOST2BMC_Q1_EMPTY : HOST2BMC_Q2_EMPTY)))); + ((index == QUEUE1) ? HOST2BMC_Q1_EMPTY : HOST2BMC_Q2_EMPTY))); if (ret) return -EINTR; @@ -191,7 +187,7 @@ static ssize_t aspeed_ast2600_queue_rx(struct file *filp, struct kobject *kobj, regmap_read(bmc_device->scu, ASPEED_SCU04, &scu_id); if (scu_id == AST2600A3_SCU04) { - writel(BMC2HOST_INT_STS_DOORBELL, + writel(BMC2HOST_INT_STS_DOORBELL | BMC2HOST_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS); } else { //A0 : BIT(12) A1 : BIT(15) @@ -251,22 +247,17 @@ static ssize_t aspeed_ast2700_queue_rx(struct file *filp, struct kobject *kobj, int index = queue->index; u32 *data = (u32 *)buf; int ret; - u32 status; ret = wait_event_interruptible(queue->rx_wait, - ((readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & HOST2BMC_ENABLE_INTB) && !(readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & - ((index == QUEUE1) ? HOST2BMC_Q1_EMPTY : HOST2BMC_Q2_EMPTY)))); - status = readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); - dev_info(bmc_device->dev, "aspeed_ast2700_queue_rx(): status=0x%x\n", status); - + ((index == QUEUE1) ? HOST2BMC_Q1_EMPTY : HOST2BMC_Q2_EMPTY))); if (ret) return -EINTR; data[0] = readl(bmc_device->reg_base + ((index == QUEUE1) ? ASPEED_BMC_HOST2BMC_Q1 : ASPEED_BMC_HOST2BMC_Q2)); - writel(BMC2HOST_INT_STS_DOORBELL, + writel(BMC2HOST_INT_STS_DOORBELL | BMC2HOST_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS); return sizeof(u32); @@ -320,19 +311,11 @@ static irqreturn_t aspeed_bmc_dev_isr(int irq, void *dev_id) struct aspeed_bmc_device *bmc_device = dev_id; u32 host2bmc_q_sts = readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); - dev_info(bmc_device->dev, "aspeed_bmc_dev_isr(): host2bmc_q_sts=0x%x\n", host2bmc_q_sts); - if (host2bmc_q_sts & HOST2BMC_INT_STS_DOORBELL) writel(HOST2BMC_INT_STS_DOORBELL, bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); if (host2bmc_q_sts & HOST2BMC_ENABLE_INTB) - { writel(HOST2BMC_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); - if (!(host2bmc_q_sts & HOST2BMC_Q1_EMPTY)) - wake_up_interruptible(&bmc_device->queue[QUEUE1].rx_wait); - if (!(host2bmc_q_sts & HOST2BMC_Q2_EMPTY)) - wake_up_interruptible(&bmc_device->queue[QUEUE2].rx_wait); - } if (host2bmc_q_sts & HOST2BMC_Q1_FULL) dev_info(bmc_device->dev, "Q1 Full\n"); @@ -343,9 +326,15 @@ static irqreturn_t aspeed_bmc_dev_isr(int irq, void *dev_id) if (!(readl(bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS) & BMC2HOST_Q1_FULL)) wake_up_interruptible(&bmc_device->queue[QUEUE1].tx_wait); + if (!(readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & HOST2BMC_Q1_EMPTY)) + wake_up_interruptible(&bmc_device->queue[QUEUE1].rx_wait); + if (!(readl(bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS) & BMC2HOST_Q2_FULL)) wake_up_interruptible(&bmc_device->queue[QUEUE2].tx_wait); + if (!(readl(bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS) & HOST2BMC_Q2_EMPTY)) + wake_up_interruptible(&bmc_device->queue[QUEUE2].rx_wait); + return IRQ_HANDLED; } @@ -395,7 +384,7 @@ static int aspeed_ast2600_init(struct platform_device *pdev) writel(bmc_device->bmc_mem_phy, bmc_device->reg_base + ASPEED_BMC_MEM_BAR_REMAP); //Setting BMC to Host Q register - writel(BMC2HOST_Q2_FULL_UNMASK | BMC2HOST_Q1_FULL_UNMASK, + writel(BMC2HOST_Q2_FULL_UNMASK | BMC2HOST_Q1_FULL_UNMASK | BMC2HOST_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS); writel(HOST2BMC_Q2_FULL_UNMASK | HOST2BMC_Q1_FULL_UNMASK | HOST2BMC_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); @@ -407,17 +396,10 @@ static int aspeed_ast2700_init(struct platform_device *pdev) { struct aspeed_bmc_device *bmc_device = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - u32 pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_IRQ | - SCU_PCIE_CONF_BMC_DEV_EN_MMIO | SCU_PCIE_CONF_BMC_DEV_EN; + u32 pcie_config_ctl; u32 scu_id; int i; - bmc_device->config = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,config"); - if (IS_ERR(bmc_device->config)) { - dev_err(&pdev->dev, "failed to find config regmap\n"); - return PTR_ERR(bmc_device->config); - } - bmc_device->device = syscon_regmap_lookup_by_phandle(dev->of_node, "aspeed,device"); if (IS_ERR(bmc_device->device)) { dev_err(&pdev->dev, "failed to find device regmap\n"); @@ -436,31 +418,31 @@ static int aspeed_ast2700_init(struct platform_device *pdev) return PTR_ERR(bmc_device->scu); } - if (bmc_device->pcie2lpc) - pcie_config_ctl |= SCU_PCIE_CONF_BMC_DEV_EN_E2L | - SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE; - - regmap_update_bits(bmc_device->config, 0x10, pcie_config_ctl, pcie_config_ctl); + if (bmc_device->pcie2lpc) { + pcie_config_ctl = SCU_PCIE_CONF_BMC_DEV_EN_E2L | + SCU_PCIE_CONF_BMC_DEV_EN_LPC_DECODE; + regmap_update_bits(bmc_device->scu, SCU0_PCIE_CONF_CTRL, + pcie_config_ctl, pcie_config_ctl); + } /* update class code to others as it is a MFD device */ regmap_write(bmc_device->device, 0x18, 0xff000027); - //MSI + /* MSI */ regmap_update_bits(bmc_device->device, 0x74, GENMASK(7, 4), BIT(7) | (5 << 4)); - - //EnPCIaMSI_EnPCIaIntA_EnPCIaMst_EnPCIaDev - //Disable MSI[bit25] in ast2700A0 int only + /* EnPCIaMSI:BIT(25), EnPCIaIntA:BIT(17), EnPCIaMst:BIT(9), EnPCIaDev:BIT(1) */ regmap_read(bmc_device->scu, SCU0_REVISION_ID, &scu_id); if (scu_id & REVISION_ID) regmap_update_bits(bmc_device->device, 0x70, BIT(25) | BIT(17) | BIT(9) | BIT(1), BIT(25) | BIT(17) | BIT(9) | BIT(1)); else + /* Disable MSI[bit25] in ast2700A0 int only */ regmap_update_bits(bmc_device->device, 0x70, BIT(17) | BIT(9) | BIT(1), BIT(25) | BIT(17) | BIT(9) | BIT(1)); - //bar size check for 4k align + /* bar size check for 4k align */ for (i = 1; i < 16; i++) { if ((bmc_device->bmc_mem_size / 4096) == (1 << (i - 1))) break; @@ -477,22 +459,15 @@ static int aspeed_ast2700_init(struct platform_device *pdev) */ regmap_write(bmc_device->device, 0x1c, ((bmc_device->bmc_mem_phy) >> 4) | i); - /* - * BAR assign in e2m - * e2m0:12c21000 - * 108:host2bmc-0 for pcie0 - * 128:host2bmc-1 for pcie0 - * e2m1:12c22000 - * 108:host2bmc-0 for pcie1 - * 128:host2bmc-1 for pcie1 - */ - if (bmc_device->id) - regmap_write(bmc_device->e2m, 0x128, ((bmc_device->bmc_mem_phy) >> 4) | i); - else + if (bmc_device->id == 0) + /* Node 0 Bar 0 */ regmap_write(bmc_device->e2m, 0x108, ((bmc_device->bmc_mem_phy) >> 4) | i); + else + /* Node 1 Bar 0 */ + regmap_write(bmc_device->e2m, 0x128, ((bmc_device->bmc_mem_phy) >> 4) | i); - //Setting BMC to Host Q register - writel(BMC2HOST_Q2_FULL_UNMASK | BMC2HOST_Q1_FULL_UNMASK, + /* Setting BMC to Host Q register */ + writel(BMC2HOST_Q2_FULL_UNMASK | BMC2HOST_Q1_FULL_UNMASK | BMC2HOST_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_BMC2HOST_STS); writel(HOST2BMC_Q2_FULL_UNMASK | HOST2BMC_Q1_FULL_UNMASK | HOST2BMC_ENABLE_INTB, bmc_device->reg_base + ASPEED_BMC_HOST2BMC_STS); @@ -589,27 +564,19 @@ static int aspeed_bmc_device_probe(struct platform_device *pdev) struct device_node *np; int ret = 0, i; - dev_info(dev, "aspeed_bmc_device_probe: start\n"); - if (!md) - { - dev_err(dev, "aspeed_bmc_device_probe: Error no md\n"); return -ENODEV; - } bmc_device = devm_kzalloc(&pdev->dev, sizeof(struct aspeed_bmc_device), GFP_KERNEL); if (!bmc_device) - { - dev_err(dev, "aspeed_bmc_device_probe: Error no Mem\n"); return -ENOMEM; - } dev_set_drvdata(dev, bmc_device); bmc_device->platform = md; - bmc_device->id = ida_simple_get(&bmc_device_ida, 0, 0, GFP_KERNEL); + bmc_device->id = of_alias_get_id(dev->of_node, "bmcdev"); if (bmc_device->id < 0) - goto out_region; + bmc_device->id = 0; bmc_device->dev = dev; bmc_device->reg_base = devm_platform_ioremap_resource(pdev, 0); @@ -633,12 +600,6 @@ static int aspeed_bmc_device_probe(struct platform_device *pdev) bmc_device->bmc_mem_phy = res.start; bmc_device->bmc_mem_size = resource_size(&res); - bmc_device->bmc_mem_virt = devm_ioremap_resource(dev, &res); - if (!bmc_device->bmc_mem_virt) { - dev_err(dev, "cannot map bmc dev memory region\n"); - ret = -ENOMEM; - goto out_region; - } bmc_device->irq = platform_get_irq(pdev, 0); if (bmc_device->irq < 0) { @@ -692,20 +653,17 @@ static int aspeed_bmc_device_probe(struct platform_device *pdev) return 0; out_free_misc: - dev_err(dev, "aspeed_bmc_device_probe: err out_free_misc\n"); misc_deregister(&bmc_device->miscdev); out_free_queue: - dev_err(dev, "aspeed_bmc_device_probe: err out_free_queue\n"); for (i = 0; i < ASPEED_QUEUE_NUM; i++) sysfs_remove_bin_file(&pdev->dev.kobj, &bmc_device->queue[i].bin); out_irq: devm_free_irq(&pdev->dev, bmc_device->irq, bmc_device); out_unmap: iounmap(bmc_device->reg_base); - devm_iounmap(&pdev->dev, bmc_device->bmc_mem_virt); out_region: devm_kfree(&pdev->dev, bmc_device); - dev_err(dev, "aspeed bmc device: driver init failed (ret=%d)!\n", ret); + dev_warn(dev, "aspeed bmc device: driver init failed (ret=%d)!\n", ret); return ret; } @@ -722,8 +680,6 @@ static int aspeed_bmc_device_remove(struct platform_device *pdev) iounmap(bmc_device->reg_base); - devm_iounmap(&pdev->dev, bmc_device->bmc_mem_virt); - devm_kfree(&pdev->dev, bmc_device); return 0; diff --git a/drivers/soc/aspeed/aspeed-espi-comm.h b/drivers/soc/aspeed/aspeed-espi-comm.h index b50393c80dc624..29468437ad6fd3 100644 --- a/drivers/soc/aspeed/aspeed-espi-comm.h +++ b/drivers/soc/aspeed/aspeed-espi-comm.h @@ -165,11 +165,21 @@ struct aspeed_espi_ioc { * Read the input value of GPIO over the VW channel * - ASPEED_ESPI_VW_PUT_GPIO_VAL * Write the output value of GPIO over the VW channel + * - ASPEED_ESPI_VW_GET_GPIO_VAL1 (new feature in AST2700) + * Read the input value1 of GPIO over the VW channel + * - ASPEED_ESPI_VW_PUT_GPIO_VAL1 (new feature in AST2700) + * Write the output value1 of GPIO over the VW channel */ #define ASPEED_ESPI_VW_GET_GPIO_VAL _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ - 0x10, uint8_t) + 0x10, uint32_t) #define ASPEED_ESPI_VW_PUT_GPIO_VAL _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ - 0x11, uint8_t) + 0x11, uint32_t) +#ifdef CONFIG_ARM64 +#define ASPEED_ESPI_VW_GET_GPIO_VAL1 _IOR(__ASPEED_ESPI_IOCTL_MAGIC, \ + 0x12, uint32_t) +#define ASPEED_ESPI_VW_PUT_GPIO_VAL1 _IOW(__ASPEED_ESPI_IOCTL_MAGIC, \ + 0x13, uint32_t) +#endif /* * Out-of-band Channel (CH2) * - ASPEED_ESPI_OOB_GET_RX diff --git a/drivers/soc/aspeed/aspeed-host-bmc-dev.c b/drivers/soc/aspeed/aspeed-host-bmc-dev.c new file mode 100644 index 00000000000000..44525ba12e807d --- /dev/null +++ b/drivers/soc/aspeed/aspeed-host-bmc-dev.c @@ -0,0 +1,1434 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) ASPEED Technology Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "aspeed-pcie-mmbi.h" + +#define PCI_BMC_HOST2BMC_Q1 0x30000 +#define PCI_BMC_HOST2BMC_Q2 0x30010 +#define PCI_BMC_BMC2HOST_Q1 0x30020 +#define PCI_BMC_BMC2HOST_Q2 0x30030 +#define PCI_BMC_BMC2HOST_STS 0x30040 +#define BMC2HOST_INT_STS_DOORBELL BIT(31) +#define BMC2HOST_ENABLE_INTB BIT(30) + +#define BMC2HOST_Q1_FULL BIT(27) +#define BMC2HOST_Q1_EMPTY BIT(26) +#define BMC2HOST_Q2_FULL BIT(25) +#define BMC2HOST_Q2_EMPTY BIT(24) +#define BMC2HOST_Q1_FULL_UNMASK BIT(23) +#define BMC2HOST_Q1_EMPTY_UNMASK BIT(22) +#define BMC2HOST_Q2_FULL_UNMASK BIT(21) +#define BMC2HOST_Q2_EMPTY_UNMASK BIT(20) + +#define PCI_BMC_HOST2BMC_STS 0x30044 +#define HOST2BMC_INT_STS_DOORBELL BIT(31) +#define HOST2BMC_ENABLE_INTB BIT(30) + +#define HOST2BMC_Q1_FULL BIT(27) +#define HOST2BMC_Q1_EMPTY BIT(26) +#define HOST2BMC_Q2_FULL BIT(25) +#define HOST2BMC_Q2_EMPTY BIT(24) +#define HOST2BMC_Q1_FULL_UNMASK BIT(23) +#define HOST2BMC_Q1_EMPTY_UNMASK BIT(22) +#define HOST2BMC_Q2_FULL_UNMASK BIT(21) +#define HOST2BMC_Q2_EMPTY_UNMASK BIT(20) + +static DEFINE_IDA(bmc_device_ida); + +#define MMBI_MAX_INST 6 +#define VUART_MAX_PARMS 2 +#define ASPEED_QUEUE_NUM 2 +#define MAX_MSI_NUM 8 + +enum aspeed_platform_id { + ASPEED, + ASPEED_AST2700_SOC1, +}; + +enum queue_index { + QUEUE1 = 0, + QUEUE2, +}; + +enum msi_index { + BMC_MSI, + MBX_MSI, + VUART0_MSI, + VUART1_MSI, + MMBI0_MSI, + MMBI1_MSI, + MMBI2_MSI, + MMBI3_MSI, +}; + +/* Match msi_index */ +static int ast2600_msi_idx_table[MAX_MSI_NUM] = { 4, 21, 16, 15 }; +static int ast2700_soc0_msi_idx_table[MAX_MSI_NUM] = { 0, 11, 6, 5, 28, 29, 30, 31 }; +/* ARRAY = MMIB0_MSI, MMBI1_MSI, MMBI2_MSI, MMBI3_MSI, MMBI4_MSI, MMBI5_MSI */ +static int ast2700_soc1_msi_idx_table[MAX_MSI_NUM] = { 1, 2, 3, 4, 5, 6 }; + +struct aspeed_platform { + int (*setup)(struct pci_dev *pdev); +}; +struct aspeed_queue_message { + /* Queue waiters for idle engine */ + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + struct kernfs_node *kn; + struct bin_attribute bin; + int index; + struct aspeed_pci_bmc_dev *pci_bmc_device; +}; + +struct aspeed_pcie_mmbi { + resource_size_t base; + resource_size_t mem_size; + void __iomem *mem; + u32 segment_size; + int irq; + int id; + struct aspeed_mmbi_channel chan; + const char *dev_name; +}; + +struct aspeed_pci_bmc_dev { + struct device *dev; + struct miscdevice miscdev; + struct aspeed_platform *platform; + kernel_ulong_t driver_data; + int id; + + unsigned long mem_bar_base; + unsigned long mem_bar_size; + void __iomem *mem_bar_reg; + + unsigned long message_bar_base; + unsigned long message_bar_size; + void __iomem *msg_bar_reg; + + void __iomem *pcie_sio_decode_addr; + + struct aspeed_queue_message queue[ASPEED_QUEUE_NUM]; + + void __iomem *sio_mbox_reg; + struct uart_8250_port uart[VUART_MAX_PARMS]; + int uart_line[VUART_MAX_PARMS]; + + /* Interrupt + * The index of array is using to enum msi_index + */ + int *msi_idx_table; + + bool ast2700_soc1; + + /* AST2700 MMBI */ + struct aspeed_pcie_mmbi mmbi[MMBI_MAX_INST]; + int mmbi_start_msi; +}; + +#define PCIE_DEVICE_SIO_ADDR (0x2E * 4) +#define BMC_MULTI_MSI 32 + +#define DRIVER_NAME "aspeed-host-bmc-dev" + +static int mmbi_desc_init(struct aspeed_mmbi_channel *chan); + +static u8 mmbi_get_bmc_rdy(struct aspeed_mmbi_channel *chan) +{ + struct host_ros hros; + + memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros)); + + return hros.b_rdy; +} + +static u8 mmbi_get_bmc_up(struct aspeed_mmbi_channel *chan) +{ + struct host_ros hros; + + memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros)); + + return hros.b_up; +} + +static u8 mmbi_get_bmc_rst(struct aspeed_mmbi_channel *chan) +{ + struct host_ros hros; + + memcpy_fromio(&hros, chan->hros_vmem, sizeof(hros)); + + return hros.b_rst; +} + +static u8 mmbi_get_host_rst(struct aspeed_mmbi_channel *chan) +{ + struct host_rws hrws; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + + return hrws.h_rst; +} + +static u8 mmbi_get_host_up(struct aspeed_mmbi_channel *chan) +{ + struct host_rws hrws; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + + return hrws.h_up; +} + +static void mmbi_set_host_rst(struct aspeed_mmbi_channel *chan, bool set) +{ + struct host_rws hrws; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + hrws.h_rst = set; + memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws)); +} + +static void mmbi_set_host_rdy(struct aspeed_mmbi_channel *chan, bool set) +{ + struct host_rws hrws; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + hrws.h_rdy = set; + memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws)); +} + +static void mmbi_set_host_up(struct aspeed_mmbi_channel *chan, bool set) +{ + struct host_rws hrws; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + hrws.h_up = set; + memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws)); +} + +static void get_h2b_avail_buf_len(struct aspeed_mmbi_channel *chan, ssize_t *avail_buf_len) +{ + struct device *dev = chan->dev; + u32 h2b_rp, h2b_wp; + + h2b_rp = GET_H2B_READ_POINTER(chan); + h2b_wp = GET_H2B_WRITE_POINTER(chan); + dev_dbg(dev, "MMBI HRWS - h2b_rp: 0x%0x, h2b_wp: 0x%0x\n", h2b_rp, h2b_wp); + + if (h2b_wp >= h2b_rp) + *avail_buf_len = chan->h2b_cb_size - h2b_wp + h2b_rp; + else + *avail_buf_len = h2b_rp - h2b_wp; +} + +static u8 mmbi_get_state(struct aspeed_mmbi_channel *chan) +{ + u8 state = 0; + + state = mmbi_get_bmc_up(chan) << 3; + state |= mmbi_get_bmc_rst(chan) << 2; + state |= mmbi_get_host_up(chan) << 1; + state |= mmbi_get_host_rst(chan); + + dev_dbg(chan->dev, "MMBI state: 0x%x\n", state); + + return state; +} + +static void raise_h2b_interrupt(struct aspeed_mmbi_channel *chan) +{ + if (!chan->bmc_int_en) + return; + + writeb(chan->bmc_int_value, chan->desc_vmem + chan->bmc_int_location); +} + +static int mmbi_state_check(struct aspeed_mmbi_channel *chan) +{ + enum mmbi_state current_state = mmbi_get_state(chan); + struct device *dev = chan->dev; + int ret; + + switch (current_state) { + case INIT_COMPLETED: + dev_dbg(dev, "Get INIT_COMPLETED state from BMC"); + + ret = mmbi_desc_init(chan); + if (ret) { + dev_warn(dev, "Check MMBI signature timeout\n"); + raise_h2b_interrupt(chan); + } + return 1; + case RESET_REQ_BY_BMC: + dev_dbg(dev, "Get RESET_REQ_BY_BMC state from BMC"); + + /* Change state to RESET_ACKED */ + mmbi_set_host_rst(chan, 1); + + dev_dbg(dev, "Change state to RESET_ACKED to BMC"); + raise_h2b_interrupt(chan); + default: + break; + } + + return 0; +} + +static int mmbi_bmc_up_check(struct aspeed_mmbi_channel *chan) +{ + u64 __timeout_us = 1000; + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); + + for (;;) { + enum mmbi_state current_state = mmbi_get_state(chan); + + if (current_state == INIT_COMPLETED) + break; + if (__timeout_us && ktime_compare(ktime_get(), __timeout) > 0) + return -EAGAIN; + } + + return 0; +} + +static void update_host_rws(struct aspeed_mmbi_channel *chan, unsigned int w_len, + unsigned int r_len) +{ + struct device *dev = chan->dev; + struct host_rws hrws; + u32 h2b_wp, b2h_rp; + + h2b_wp = GET_H2B_WRITE_POINTER(chan); + b2h_rp = GET_B2H_READ_POINTER(chan); + + dev_dbg(dev, "MMBI HRWS - b2h_rp: 0x%0x, h2b_wp: 0x%0x\n", b2h_rp, h2b_wp); + + /* Advance the H2B CB offset for next write */ + if ((h2b_wp + w_len) <= chan->h2b_cb_size) + h2b_wp += w_len; + else + h2b_wp = h2b_wp + w_len - chan->h2b_cb_size; + + /* Advance the B2H CB offset till where BMC read data */ + if ((b2h_rp + r_len) <= chan->b2h_cb_size) + b2h_rp += r_len; + else + b2h_rp = b2h_rp + r_len - chan->b2h_cb_size; + + memcpy_fromio(&hrws, chan->hrws_vmem, sizeof(hrws)); + + hrws.h2b_wp = FIELD_GET(H2B_WRITE_POINTER_MASK, h2b_wp); + hrws.b2h_rp = FIELD_GET(B2H_READ_POINTER_MASK, b2h_rp); + memcpy_toio(chan->hrws_vmem, &hrws, sizeof(hrws)); + dev_dbg(dev, "Updating HRWS - b2h_rp: 0x%0x, h2b_wp: 0x%0x\n", b2h_rp, h2b_wp); + + if (w_len != 0) + raise_h2b_interrupt(chan); +} + +static int get_mmbi_header(struct aspeed_mmbi_channel *chan, u32 *data_length, u8 *type, + u32 *unread_data_len, u8 *padding) +{ + u32 h2b_wp, h2b_rp, b2h_wp, b2h_rp; + struct mmbi_header header; + + h2b_wp = GET_H2B_WRITE_POINTER(chan); + h2b_rp = GET_H2B_READ_POINTER(chan); + b2h_wp = GET_B2H_WRITE_POINTER(chan); + b2h_rp = GET_B2H_READ_POINTER(chan); + dev_dbg(chan->dev, "MMBI HRWS - h2b_wp: 0x%0x, b2h_rp: 0x%0x\n", h2b_wp, b2h_rp); + dev_dbg(chan->dev, "MMBI HROS - b2h_wp: 0x%0x, h2b_rp: 0x%0x\n", b2h_wp, h2b_rp); + + if (b2h_wp >= b2h_rp) + *unread_data_len = b2h_wp - b2h_rp; + else + *unread_data_len = chan->b2h_cb_size - b2h_rp + b2h_wp; + + if (*unread_data_len < sizeof(struct mmbi_header)) { + dev_dbg(chan->dev, "No data to read(%d - %d)\n", b2h_wp, b2h_rp); + return -EAGAIN; + } + + dev_dbg(chan->dev, "READ MMBI header from: %p\n", chan->b2h_cb_vmem + b2h_rp); + + /* Extract MMBI protocol - protocol type and length */ + if ((b2h_rp + sizeof(header)) <= chan->b2h_cb_size) { + memcpy_fromio(&header, chan->b2h_cb_vmem + b2h_rp, sizeof(header)); + } else { + ssize_t chunk_len = chan->b2h_cb_size - b2h_rp; + + memcpy_fromio(&header, chan->b2h_cb_vmem + b2h_rp, chunk_len); + memcpy_fromio(((u8 *)&header) + chunk_len, chan->b2h_cb_vmem, + sizeof(header) - chunk_len); + } + + *data_length = (header.pkt_len << 2) - sizeof(header) - header.pkt_pad; + *padding = header.pkt_pad; + *type = header.pkt_type; + + return 0; +} + +static int aspeed_mmbi_write(struct aspeed_mmbi_channel *chan, const char *buffer, size_t len, + protocol_type type) +{ + struct device *dev = chan->dev; + struct mmbi_header header = {0}; + ssize_t avail_buf_len; + ssize_t total_len; + ssize_t wt_offset; + ssize_t chunk_len; + ssize_t end_offset; + u8 padding = 0; + + /* If BMC READY bit is not set, Just discard the write. */ + if (!GET_BMC_READY_BIT(chan)) { + dev_dbg(dev, "Host not ready, discarding request...\n"); + return -EAGAIN; + } + + get_h2b_avail_buf_len(chan, &avail_buf_len); + + dev_dbg(dev, "H2B buffer empty space: %zd\n", avail_buf_len); + + /* Header size */ + total_len = len + 4; + + padding = total_len & 0x3; + if (padding) + padding = 4 - padding; + total_len += padding; + + /* Empty space should be more than write request data size */ + if (avail_buf_len <= sizeof(header) || (total_len > (avail_buf_len - sizeof(header)))) + return -ENOSPC; + + /* Fill multi-protocol header */ + header.pkt_type = type; + header.pkt_len = total_len >> 2; + header.pkt_pad = padding; + + wt_offset = GET_H2B_WRITE_POINTER(chan); + end_offset = chan->h2b_cb_size; + + /* Copy Header */ + if ((end_offset - wt_offset) >= sizeof(header)) { + memcpy_toio(chan->h2b_cb_vmem + wt_offset, &header, sizeof(header)); + wt_offset += sizeof(header); + } else { + chunk_len = end_offset - wt_offset; + dev_dbg(dev, "Write header chunk_len: %zd\n", chunk_len); + memcpy_toio(chan->h2b_cb_vmem + wt_offset, &header, chunk_len); + memcpy_toio(chan->h2b_cb_vmem, (u8 *)&header + chunk_len, + (sizeof(header) - chunk_len)); + wt_offset = (sizeof(header) - chunk_len); + } + + /* Write the data */ + if ((end_offset - wt_offset) >= len) { + memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer, len); + wt_offset += len; + } else { + chunk_len = end_offset - wt_offset; + dev_dbg(dev, "Write data chunk_len: %zd\n", chunk_len); + memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer, chunk_len); + wt_offset = 0; + memcpy_toio(&chan->h2b_cb_vmem[wt_offset], buffer + chunk_len, len - chunk_len); + wt_offset += len - chunk_len; + } + + update_host_rws(chan, total_len, 0); + + return 0; +} + +static void aspeed_mmbi_read(struct aspeed_mmbi_channel *chan, char *buffer, size_t len, u8 padding) +{ + struct device *dev = chan->dev; + ssize_t rd_offset; + u32 b2h_rp; + + b2h_rp = GET_B2H_READ_POINTER(chan); + if ((b2h_rp + sizeof(struct mmbi_header)) <= chan->b2h_cb_size) + rd_offset = b2h_rp + sizeof(struct mmbi_header); + else + rd_offset = b2h_rp + sizeof(struct mmbi_header) - chan->b2h_cb_size; + + /* Extract data and copy to user space application */ + dev_dbg(dev, "READ MMBI Data from: %p and length: %zd\n", + chan->b2h_cb_vmem + rd_offset, len); + + if ((chan->b2h_cb_size - rd_offset) >= len) { + memcpy_fromio(buffer, chan->b2h_cb_vmem + rd_offset, len); + rd_offset += len; + } else { + ssize_t chunk_len; + + chunk_len = chan->b2h_cb_size - rd_offset; + dev_dbg(dev, "Read data chunk_len: %zd\n", chunk_len); + memcpy_fromio(buffer, chan->b2h_cb_vmem + rd_offset, chunk_len); + + rd_offset = 0; + memcpy_fromio(buffer + chunk_len, chan->b2h_cb_vmem + rd_offset, + len - chunk_len); + } + + update_host_rws(chan, 0, len + sizeof(struct mmbi_header) + padding); +} + +static void mctp_mmbi_rx(struct aspeed_mmbi_channel *chan) +{ + struct net_device *ndev; + struct sk_buff *skb; + struct mctp_skb_cb *cb; + u32 req_data_len, unread_data_len; + u8 type, padding; + int status; + + if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0) + return; + + dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d, Unread data: %d\n", __func__, + req_data_len, type, unread_data_len); + + ndev = chan->ndev; + + skb = netdev_alloc_skb(ndev, req_data_len); + if (!skb) { + ndev->stats.rx_dropped++; + update_host_rws(chan, 0, req_data_len + sizeof(struct mmbi_header)); + return; + } + + skb->protocol = htons(ETH_P_MCTP); + aspeed_mmbi_read(chan, skb_put(skb, req_data_len), req_data_len, padding); + skb_reset_network_header(skb); + + cb = __mctp_cb(skb); + cb->halen = 0; + + status = netif_rx(skb); + if (status == NET_RX_SUCCESS) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += req_data_len; + } else { + ndev->stats.rx_dropped++; + } +} + +static netdev_tx_t mctp_mmbi_tx(struct sk_buff *skb, struct net_device *ndev) +{ + struct aspeed_mmbi_mctp *mctp = netdev_priv(ndev); + int ret; + + if (!mmbi_get_bmc_rdy(&mctp->mmbi->chan) || skb->len > MCTP_MMBI_MTU_MAX) { + ndev->stats.tx_dropped++; + goto out; + } + + ret = aspeed_mmbi_write(&mctp->mmbi->chan, skb->data, skb->len, MMBI_PROTOCOL_MCTP); + if (ret) { + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; + } + + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; +out: + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static const struct net_device_ops mctp_mmbi_netdev_ops = { + .ndo_start_xmit = mctp_mmbi_tx, +}; + +static void aspeed_mctp_mmbi_setup(struct net_device *ndev) +{ + ndev->type = ARPHRD_MCTP; + + /* we limit at the fixed MTU, which is also the MCTP-standard + * baseline MTU, so is also our minimum + */ + ndev->mtu = MCTP_MMBI_MTU; + ndev->max_mtu = MCTP_MMBI_MTU_MAX; + ndev->min_mtu = MCTP_MMBI_MTU_MIN; + + ndev->hard_header_len = 0; + ndev->addr_len = 0; + ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; + ndev->flags = IFF_NOARP; + ndev->netdev_ops = &mctp_mmbi_netdev_ops; + ndev->needs_free_netdev = true; +} + +static int aspeed_mmbi_mctp_init(struct aspeed_mmbi_channel *chan) +{ + struct aspeed_mmbi_mctp *mctp; + struct net_device *ndev; + char name[32]; + int ret; + + snprintf(name, sizeof(name), "mctpmmbi%d", chan->mmbi->id); + ndev = alloc_netdev(sizeof(*mctp), name, NET_NAME_ENUM, aspeed_mctp_mmbi_setup); + if (!ndev) + return -ENOMEM; + mctp = netdev_priv(ndev); + mctp->ndev = ndev; + mctp->mmbi = chan->mmbi; + + chan->ndev = ndev; + + ret = register_netdev(ndev); + if (ret) + goto free_netdev; + + return 0; + +free_netdev: + free_netdev(ndev); + + return ret; +} + +static struct aspeed_pci_bmc_dev *file_aspeed_bmc_device(struct file *file) +{ + return container_of(file->private_data, struct aspeed_pci_bmc_dev, miscdev); +} + +static int aspeed_pci_bmc_dev_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = file_aspeed_bmc_device(file); + unsigned long vsize = vma->vm_end - vma->vm_start; + pgprot_t prot = vma->vm_page_prot; + + if (vma->vm_pgoff + vsize > pci_bmc_dev->mem_bar_base + 0x100000) + return -EINVAL; + + prot = pgprot_noncached(prot); + + if (remap_pfn_range(vma, vma->vm_start, + (pci_bmc_dev->mem_bar_base >> PAGE_SHIFT) + vma->vm_pgoff, + vsize, prot)) + return -EAGAIN; + + return 0; +} + +static const struct file_operations aspeed_pci_bmc_dev_fops = { + .owner = THIS_MODULE, + .mmap = aspeed_pci_bmc_dev_mmap, +}; + +static ssize_t aspeed_queue_rx(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct aspeed_queue_message *queue = attr->private; + struct aspeed_pci_bmc_dev *pci_bmc_device = queue->pci_bmc_device; + int index = queue->index; + u32 *data = (u32 *)buf; + int ret; + + ret = wait_event_interruptible(queue->rx_wait, + !(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS) & + ((index == QUEUE1) ? BMC2HOST_Q1_EMPTY : BMC2HOST_Q2_EMPTY))); + if (ret) + return -EINTR; + + data[0] = readl(pci_bmc_device->msg_bar_reg + + ((index == QUEUE1) ? PCI_BMC_BMC2HOST_Q1 : PCI_BMC_BMC2HOST_Q2)); + + writel(HOST2BMC_INT_STS_DOORBELL | HOST2BMC_ENABLE_INTB, + pci_bmc_device->msg_bar_reg + PCI_BMC_HOST2BMC_STS); + + return sizeof(u32); +} + +static ssize_t aspeed_queue_tx(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct aspeed_queue_message *queue = attr->private; + struct aspeed_pci_bmc_dev *pci_bmc_device = queue->pci_bmc_device; + int index = queue->index; + u32 tx_buff; + int ret; + + if (count != sizeof(u32)) + return -EINVAL; + + ret = wait_event_interruptible(queue->tx_wait, + !(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_HOST2BMC_STS) & + ((index == QUEUE1) ? HOST2BMC_Q1_FULL : HOST2BMC_Q2_FULL))); + if (ret) + return -EINTR; + + memcpy(&tx_buff, buf, 4); + writel(tx_buff, pci_bmc_device->msg_bar_reg + + ((index == QUEUE1) ? PCI_BMC_HOST2BMC_Q1 : PCI_BMC_HOST2BMC_Q2)); + //trigger to host + writel(HOST2BMC_INT_STS_DOORBELL | HOST2BMC_ENABLE_INTB, + pci_bmc_device->msg_bar_reg + PCI_BMC_HOST2BMC_STS); + + return sizeof(u32); +} + +static irqreturn_t aspeed_pci_host_bmc_device_interrupt(int irq, void *dev_id) +{ + struct aspeed_pci_bmc_dev *pci_bmc_device = dev_id; + u32 bmc2host_q_sts = readl(pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS); + + if (bmc2host_q_sts & BMC2HOST_INT_STS_DOORBELL) + writel(BMC2HOST_INT_STS_DOORBELL, + pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS); + + if (bmc2host_q_sts & BMC2HOST_ENABLE_INTB) + writel(BMC2HOST_ENABLE_INTB, pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS); + + if (bmc2host_q_sts & BMC2HOST_Q1_FULL) + dev_info(pci_bmc_device->dev, "Q1 Full\n"); + + if (bmc2host_q_sts & BMC2HOST_Q2_FULL) + dev_info(pci_bmc_device->dev, "Q2 Full\n"); + + //check q1 + if (!(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_HOST2BMC_STS) & HOST2BMC_Q1_FULL)) + wake_up_interruptible(&pci_bmc_device->queue[QUEUE1].tx_wait); + + if (!(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS) & BMC2HOST_Q1_EMPTY)) + wake_up_interruptible(&pci_bmc_device->queue[QUEUE1].rx_wait); + //chech q2 + if (!(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_HOST2BMC_STS) & HOST2BMC_Q2_FULL)) + wake_up_interruptible(&pci_bmc_device->queue[QUEUE2].tx_wait); + + if (!(readl(pci_bmc_device->msg_bar_reg + PCI_BMC_BMC2HOST_STS) & BMC2HOST_Q2_EMPTY)) + wake_up_interruptible(&pci_bmc_device->queue[QUEUE2].rx_wait); + + return IRQ_HANDLED; +} + +static irqreturn_t aspeed_pci_host_mbox_interrupt(int irq, void *dev_id) +{ + struct aspeed_pci_bmc_dev *pci_bmc_device = dev_id; + u32 isr = readl(pci_bmc_device->sio_mbox_reg + 0x94); + + if (isr & BIT(7)) + writel(BIT(7), pci_bmc_device->sio_mbox_reg + 0x94); + + return IRQ_HANDLED; +} + +static void aspeed_mmbi_work_func(struct work_struct *workq) +{ + struct aspeed_mmbi_channel *chan = container_of(workq, struct aspeed_mmbi_channel, work); + u32 weight = 256, req_data_len, unread_data_len; + u8 type, padding; + int i; + + for (i = 0; i < weight; i++) { + if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0) + return; + + dev_dbg(chan->dev, "%s: Length: 0x%0x, Protocol Type: %d\n", + __func__, req_data_len, type); + + if (type == MMBI_PROTOCOL_MCTP) + mctp_mmbi_rx(chan); + else + /* Discard data and advance the hrws */ + update_host_rws(chan, 0, req_data_len + sizeof(struct mmbi_header) + padding); + + raise_h2b_interrupt(chan); + } + + if (get_mmbi_header(chan, &req_data_len, &type, &unread_data_len, &padding) != 0) + queue_work(system_unbound_wq, &chan->work); +} + +static irqreturn_t aspeed_pci_mmbi_isr(int irq, void *dev_id) +{ + struct aspeed_pcie_mmbi *mmbi = dev_id; + struct aspeed_mmbi_channel *chan = &mmbi->chan; + ssize_t avail_buf_len; + + get_h2b_avail_buf_len(chan, &avail_buf_len); + if (avail_buf_len > MCTP_MMBI_MTU_MAX) { + if (netif_queue_stopped(chan->ndev)) { + dev_dbg(chan->dev, "Wake up mctp net device\n"); + netif_wake_queue(chan->ndev); + } + } + + if (mmbi_state_check(chan)) + return IRQ_HANDLED; + + queue_work(system_unbound_wq, &chan->work); + + return IRQ_HANDLED; +} + +static void aspeed_pci_setup_irq_resource(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + + /* Assign static msi index table by platform */ + if (pdev->revision == 0x27) { + if (pci_bmc_dev->driver_data == ASPEED) { + pci_bmc_dev->msi_idx_table = ast2700_soc0_msi_idx_table; + } else { + pci_bmc_dev->msi_idx_table = ast2700_soc1_msi_idx_table; + pci_bmc_dev->ast2700_soc1 = true; + } + } else { + pci_bmc_dev->msi_idx_table = ast2600_msi_idx_table; + } + + if (pci_alloc_irq_vectors(pdev, 1, BMC_MULTI_MSI, PCI_IRQ_LEGACY | PCI_IRQ_MSI) <= 1) + /* Set all msi index to the first vector */ + memset(pci_bmc_dev->msi_idx_table, 0, sizeof(int) * MAX_MSI_NUM); +} + +static int aspeed_pci_bmc_device_setup_queue(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_device = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret, i; + + for (i = 0; i < ASPEED_QUEUE_NUM; i++) { + struct aspeed_queue_message *queue = &pci_bmc_device->queue[i]; + + init_waitqueue_head(&queue->tx_wait); + init_waitqueue_head(&queue->rx_wait); + + sysfs_bin_attr_init(&queue->bin); + + /* Queue name index starts from 1 */ + queue->bin.attr.name = + devm_kasprintf(dev, GFP_KERNEL, "pci-bmc-dev-queue%d", (i + 1)); + queue->bin.attr.mode = 0600; + queue->bin.read = aspeed_queue_rx; + queue->bin.write = aspeed_queue_tx; + queue->bin.size = 4; + queue->bin.private = queue; + + ret = sysfs_create_bin_file(&pdev->dev.kobj, &queue->bin); + if (ret) { + dev_err(dev, "error for bin%d file\n", i); + return ret; + } + + queue->kn = kernfs_find_and_get(dev->kobj.sd, queue->bin.attr.name); + if (!queue->kn) { + sysfs_remove_bin_file(&dev->kobj, &queue->bin); + return ret; + } + + queue->index = i; + queue->pci_bmc_device = pci_bmc_device; + } + + return 0; +} + +static int aspeed_pci_bmc_device_setup_vuart(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + u16 vuart_ioport; + int ret, i; + + for (i = 0; i < VUART_MAX_PARMS; i++) { + /* Assign the line to non-exist device */ + pci_bmc_dev->uart_line[i] = -ENOENT; + vuart_ioport = 0x3F8 - (i * 0x100); + pci_bmc_dev->uart[i].port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + pci_bmc_dev->uart[i].port.uartclk = 115200 * 16; + pci_bmc_dev->uart[i].port.irq = + pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[VUART0_MSI + i]); + pci_bmc_dev->uart[i].port.dev = dev; + pci_bmc_dev->uart[i].port.iotype = UPIO_MEM32; + pci_bmc_dev->uart[i].port.iobase = 0; + pci_bmc_dev->uart[i].port.mapbase = + pci_bmc_dev->message_bar_base + (vuart_ioport << 2); + pci_bmc_dev->uart[i].port.membase = 0; + pci_bmc_dev->uart[i].port.type = PORT_16550A; + pci_bmc_dev->uart[i].port.flags |= (UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE); + pci_bmc_dev->uart[i].port.regshift = 2; + ret = serial8250_register_8250_port(&pci_bmc_dev->uart[i]); + if (ret < 0) { + dev_err_probe(dev, ret, "Can't setup PCIe VUART\n"); + return ret; + } + pci_bmc_dev->uart_line[i] = ret; + } + return 0; +} + +static int aspeed_pci_bmc_device_setup_memory_mapping(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + pci_bmc_dev->miscdev.minor = MISC_DYNAMIC_MINOR; + pci_bmc_dev->miscdev.name = + devm_kasprintf(dev, GFP_KERNEL, "%s%d", DRIVER_NAME, pci_bmc_dev->id); + pci_bmc_dev->miscdev.fops = &aspeed_pci_bmc_dev_fops; + pci_bmc_dev->miscdev.parent = dev; + + ret = misc_register(&pci_bmc_dev->miscdev); + if (ret) { + pr_err("host bmc register fail %d\n", ret); + return ret; + } + + return 0; +} + +static int aspeed_pci_bmc_device_setup_mbox(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + /* setup mbox */ + pci_bmc_dev->pcie_sio_decode_addr = pci_bmc_dev->msg_bar_reg + PCIE_DEVICE_SIO_ADDR; + writel(0xaa, pci_bmc_dev->pcie_sio_decode_addr); + writel(0xa5, pci_bmc_dev->pcie_sio_decode_addr); + writel(0xa5, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x07, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x0e, pci_bmc_dev->pcie_sio_decode_addr + 0x04); + /* disable */ + writel(0x30, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x00, pci_bmc_dev->pcie_sio_decode_addr + 0x04); + /* set decode address 0x100 */ + writel(0x60, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x01, pci_bmc_dev->pcie_sio_decode_addr + 0x04); + writel(0x61, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x00, pci_bmc_dev->pcie_sio_decode_addr + 0x04); + /* enable */ + writel(0x30, pci_bmc_dev->pcie_sio_decode_addr); + writel(0x01, pci_bmc_dev->pcie_sio_decode_addr + 0x04); + pci_bmc_dev->sio_mbox_reg = pci_bmc_dev->msg_bar_reg + 0x400; + + ret = devm_request_irq(dev, + pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[MBX_MSI]), + aspeed_pci_host_mbox_interrupt, IRQF_SHARED, + devm_kasprintf(dev, GFP_KERNEL, "aspeed-sio-mbox%d", pci_bmc_dev->id), + pci_bmc_dev); + if (ret) { + pr_err("host bmc device Unable to get IRQ %d\n", ret); + return ret; + } + + return 0; +} + +static int mmbi_signature_check(struct aspeed_mmbi_channel *chan) +{ + u8 signature[6]; + u64 __timeout_us = 1000; + ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); + + for (;;) { + memcpy_fromio(signature, chan->desc_vmem, 6); + if (!memcmp(MMBI_SIGNATURE, signature, 6)) + break; + if (__timeout_us && ktime_compare(ktime_get(), __timeout) > 0) + return -ETIMEDOUT; + } + return 0; +} + +static int mmbi_desc_init(struct aspeed_mmbi_channel *chan) +{ + struct aspeed_pcie_mmbi *mmbi = chan->mmbi; + struct device *dev = chan->dev; + struct mmbi_cap_desc desc; + u8 __iomem *desc_base = chan->desc_vmem; + int ret; + + /* First, check mmbi signature "#MMBI$" */ + ret = mmbi_signature_check(chan); + if (ret) { + dev_warn(dev, "Check MMBI signature timeout\n"); + return ret; + } + + memcpy_fromio(&desc, chan->desc_vmem, sizeof(desc)); + + /* HROS */ + if (((desc.bt_desc.h_ros_p << 3) + sizeof(struct host_ros)) >= mmbi->mem_size) { + dev_warn(dev, "HROS is out of range"); + return -EINVAL; + } + chan->hros_vmem = desc_base + (desc.bt_desc.h_ros_p << 3); + + /* HRWS */ + if (((desc.bt_desc.h_rws_p << 3) + sizeof(struct host_rws)) >= mmbi->mem_size) { + dev_warn(dev, "HRWS is out of range"); + return -EINVAL; + } + chan->hrws_vmem = desc_base + (desc.bt_desc.h_rws_p << 3); + + ret = mmbi_bmc_up_check(chan); + if (ret) { + dev_warn(dev, "Check BMC up timeout\n"); + return ret; + } + + /* Implementations of MMBI described in this document shall indicate version 1 of MMBI */ + if (desc.version != 1) { + dev_warn(dev, "MMBI version must be 1"); + goto err_mismatch; + } + + /* This MMBI interface is intended for OS use */ + if (desc.os_use != 1) { + dev_warn(dev, "This MMBI does not provide for OS"); + goto err_mismatch; + } + + /* Current application is only MMBI Variable Packet Size Circular Buffers (VPSCB) v1 */ + if (desc.buffer_type != 1) { + dev_warn(dev, "The buffer type is not VPSCB: (%d)", desc.buffer_type); + goto err_mismatch; + } + + /* B2H Buffer */ + if (((desc.b2h_ba << 3) + desc.b2h_l) > mmbi->mem_size) { + dev_warn(dev, "B2H buffer is out of range"); + goto err_mismatch; + } + chan->b2h_cb_vmem = desc_base + (desc.b2h_ba << 3); + chan->b2h_cb_size = desc.b2h_l; + + /* H2B Buffer */ + if (((desc.h2b_ba << 3) + desc.h2b_l) > mmbi->mem_size) { + dev_warn(dev, "H2B buffer is out of range"); + goto err_mismatch; + } + chan->h2b_cb_vmem = desc_base + (desc.h2b_ba << 3); + chan->h2b_cb_size = desc.h2b_l; + + dev_dbg(dev, "B2H mapped addr - desc: %p, hros: %p, b2h_cb: %p\n", + chan->desc_vmem, chan->hros_vmem, chan->b2h_cb_vmem); + dev_dbg(dev, "H2B mapped addr - hrws: %p, h2b_cb: %p\n", chan->hrws_vmem, + chan->h2b_cb_vmem); + + dev_dbg(dev, "B2H buffer size: 0x%0x\n", chan->b2h_cb_size); + dev_dbg(dev, "H2B buffer size: 0x%0x\n", chan->h2b_cb_size); + + /* Host Interrupt */ + chan->host_int_en = !!desc.bt_desc.h_int_t; + if (chan->host_int_en) { + /* 1 for PCIe */ + if (desc.bt_desc.h_int_t != 1) + chan->host_int_en = 0; + else + chan->host_int_location = desc.bt_desc.h_int_l; + } + + /* BMC Interrupt */ + chan->bmc_int_en = !!desc.bt_desc.bmc_int_t; + if (chan->bmc_int_en) { + if (desc.bt_desc.bmc_int_t != 1) { + chan->bmc_int_en = 0; + } else { + chan->bmc_int_location = desc.bt_desc.bmc_int_l; + chan->bmc_int_vmem = desc_base + chan->bmc_int_location; + chan->bmc_int_value = desc.bt_desc.bmc_int_v; + } + } + + INIT_WORK(&chan->work, aspeed_mmbi_work_func); + + return 0; +err_mismatch: + /* Change state to INIT_MISMATCH */ + mmbi_set_host_rst(chan, 1); + return -EINVAL; +} + +static int aspeed_pci_mmbi_init(struct aspeed_pcie_mmbi *mmbi) +{ + struct aspeed_mmbi_channel *chan = &mmbi->chan; + struct device *dev = chan->dev; + int ret; + + chan->desc_vmem = mmbi->mem; + chan->mmbi = mmbi; + + ret = mmbi_desc_init(chan); + if (ret) { + dev_err(dev, "Unable to init mmbi desc\n"); + return ret; + } + + /* Initialize MTCP function */ + ret = aspeed_mmbi_mctp_init(chan); + if (ret) { + dev_err(dev, "Unable to init mctp\n"); + return ret; + } + + /* Change state to NORMAL_RUNTIME */ + mmbi_set_host_up(chan, 1); + mmbi_set_host_rdy(chan, 1); + /* Trigger BMC to finish normal runtime state */ + raise_h2b_interrupt(chan); + + return 0; +} + +/* AST2700 PCIe MMBI + * SoC : | 0 | 1 | + * BAR : | 2 3 4 5 | 0 1 2 3 4 5 | + * MMBI: | 0 1 2 3 | 0 1 2 3 4 5 | + */ +static void aspeed_pci_bmc_device_setup_mmbi(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + struct aspeed_pcie_mmbi *mmbi; + u32 start_bar = 2, mmbi_max_inst = 4, start_msi = MMBI0_MSI; /* AST2700 SoC0 */ + int i, rc = 0; + + /* AST2700 A1 supports MMBI */ + if (pdev->revision != 0x27) + return; + + if (pci_bmc_dev->ast2700_soc1) { + /* AST2700 SoC1 */ + start_bar = 0; + mmbi_max_inst = 6; + start_msi = 0; + } + + for (i = 0; i < mmbi_max_inst; i++) { + mmbi = &pci_bmc_dev->mmbi[i]; + + /* Get MMBI BAR resource */ + mmbi->base = pci_resource_start(pdev, start_bar + i); + mmbi->mem_size = pci_resource_len(pdev, start_bar + i); + + /* Check if there is bar */ + if (!mmbi->mem_size) + continue; + + mmbi->mem = pci_ioremap_bar(pdev, start_bar + i); + if (!mmbi->mem) { + mmbi->mem_size = 0; + continue; + } + + mmbi->chan.dev = &pdev->dev; + mmbi->dev_name = devm_kasprintf(mmbi->chan.dev, GFP_KERNEL, "pci-mmbi%d", i); + mmbi->id = i; + rc = aspeed_pci_mmbi_init(mmbi); + if (rc < 0) { + pr_err("Initialize MMBI device failed.\n"); + goto free_ioremap; + } + + if (mmbi->chan.host_int_en) { + mmbi->irq = pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[start_msi + i]); + rc = devm_request_irq(&pdev->dev, mmbi->irq, aspeed_pci_mmbi_isr, + IRQF_SHARED, mmbi->dev_name, mmbi); + if (rc) { + pr_err("MMBI device %s unable to get IRQ %d\n", mmbi->dev_name, rc); + mmbi->irq = 0; + goto free_ioremap; + } + } else { + mmbi->irq = 0; + } + continue; +free_ioremap: + mmbi->mem_size = 0; + pci_iounmap(pdev, mmbi->mem); + } +} + +static void aspeed_pci_host_bmc_device_release_queue(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + int i; + + for (i = 0; i < ASPEED_QUEUE_NUM; i++) + sysfs_remove_bin_file(&pdev->dev.kobj, &pci_bmc_dev->queue[i].bin); +} + +static void aspeed_pci_host_bmc_device_release_vuart(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + int i; + + for (i = 0; i < VUART_MAX_PARMS; i++) { + if (pci_bmc_dev->uart_line[i] >= 0) + serial8250_unregister_port(pci_bmc_dev->uart_line[i]); + } +} + +static void aspeed_pci_host_bmc_device_release_memory_mapping(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + + if (!list_empty(&pci_bmc_dev->miscdev.list)) + misc_deregister(&pci_bmc_dev->miscdev); +} + +static void aspeed_pci_release_mmbi(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + struct aspeed_pcie_mmbi *mmbi; + int i; + + if (pdev->revision != 0x27) + return; + + for (i = 0; i < MMBI_MAX_INST; i++) { + mmbi = &pci_bmc_dev->mmbi[i]; + + if (mmbi->mem_size == 0) + continue; + + cancel_work_sync(&mmbi->chan.work); + + mmbi_set_host_rdy(&mmbi->chan, 0); + mmbi_set_host_up(&mmbi->chan, 0); + + unregister_netdev(mmbi->chan.ndev); + + if (mmbi->mem) + pci_iounmap(pdev, mmbi->mem); + if (mmbi->irq != 0) + devm_free_irq(&pdev->dev, mmbi->irq, mmbi); + } +} + +static int aspeed_pci_host_setup(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + int rc = 0; + + /* Get share memory BAR */ + pci_bmc_dev->mem_bar_base = pci_resource_start(pdev, 0); + pci_bmc_dev->mem_bar_size = pci_resource_len(pdev, 0); + pci_bmc_dev->mem_bar_reg = pci_ioremap_bar(pdev, 0); + if (!pci_bmc_dev->mem_bar_reg) + return -ENOMEM; + + /* Get Message BAR */ + pci_bmc_dev->message_bar_base = pci_resource_start(pdev, 1); + pci_bmc_dev->message_bar_size = pci_resource_len(pdev, 1); + pci_bmc_dev->msg_bar_reg = pci_ioremap_bar(pdev, 1); + if (!pci_bmc_dev->msg_bar_reg) { + rc = -ENOMEM; + goto out_free0; + } + + /* AST2600 ERRTA40: dummy read */ + if (pdev->revision < 0x27) + (void)__raw_readl((void __iomem *)pci_bmc_dev->msg_bar_reg); + + rc = aspeed_pci_bmc_device_setup_queue(pdev); + if (rc) { + pr_err("Cannot setup Queue Message"); + goto out_free1; + } + + rc = aspeed_pci_bmc_device_setup_memory_mapping(pdev); + if (rc) { + pr_err("Cannot setup Memory Mapping"); + goto out_free_queue; + } + + rc = aspeed_pci_bmc_device_setup_mbox(pdev); + if (rc) { + pr_err("Cannot setup Mailnbox"); + goto out_free_mmapping; + } + + rc = aspeed_pci_bmc_device_setup_vuart(pdev); + if (rc) { + pr_err("Cannot setup Virtual UART"); + goto out_free_mbox; + } + + rc = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[BMC_MSI]), + aspeed_pci_host_bmc_device_interrupt, IRQF_SHARED, + pci_bmc_dev->miscdev.name, pci_bmc_dev); + if (rc) { + pr_err("Get BMC DEVICE IRQ failed. (err=%d)\n", rc); + goto out_free_uart; + } + + /* Setup AST2700 PCIe MMBI device */ + aspeed_pci_bmc_device_setup_mmbi(pdev); + + return 0; + +out_free_uart: + aspeed_pci_host_bmc_device_release_vuart(pdev); +out_free_mbox: + devm_free_irq(&pdev->dev, pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[MBX_MSI]), + pci_bmc_dev); +out_free_mmapping: + aspeed_pci_host_bmc_device_release_memory_mapping(pdev); +out_free_queue: + aspeed_pci_host_bmc_device_release_queue(pdev); +out_free1: + pci_iounmap(pdev, pci_bmc_dev->msg_bar_reg); +out_free0: + pci_iounmap(pdev, pci_bmc_dev->mem_bar_reg); + + pci_release_regions(pdev); + return rc; +} + +static int aspeed_pci_host_mmbi_device_setup(struct pci_dev *pdev) +{ + aspeed_pci_bmc_device_setup_mmbi(pdev); + return 0; +} + +static struct aspeed_platform aspeed_pcie_host[] = { + { .setup = aspeed_pci_host_setup }, + { .setup = aspeed_pci_host_mmbi_device_setup }, + { 0 } +}; + +static int aspeed_pci_host_bmc_device_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev; + int rc = 0; + + pr_info("ASPEED BMC PCI ID %04x:%04x, IRQ=%u\n", pdev->vendor, pdev->device, pdev->irq); + + pci_bmc_dev = devm_kzalloc(&pdev->dev, sizeof(*pci_bmc_dev), GFP_KERNEL); + if (!pci_bmc_dev) + return -ENOMEM; + + /* Get platform id */ + pci_bmc_dev->driver_data = ent->driver_data; + pci_bmc_dev->platform = &aspeed_pcie_host[ent->driver_data]; + + pci_bmc_dev->id = ida_simple_get(&bmc_device_ida, 0, 0, GFP_KERNEL); + if (pci_bmc_dev->id < 0) + return pci_bmc_dev->id; + + rc = pci_enable_device(pdev); + if (rc) { + dev_err(&pdev->dev, "pci_enable_device() returned error %d\n", rc); + return rc; + } + + pci_set_master(pdev); + pci_set_drvdata(pdev, pci_bmc_dev); + + /* Prepare IRQ resource */ + aspeed_pci_setup_irq_resource(pdev); + + /* Setup BMC PCI device */ + rc = pci_bmc_dev->platform->setup(pdev); + if (rc) { + dev_err(&pdev->dev, "ASPEED PCIe Host device returned error %d\n", rc); + pci_free_irq_vectors(pdev); + pci_disable_device(pdev); + return rc; + } + + return 0; +} + +static void aspeed_pci_host_bmc_device_remove(struct pci_dev *pdev) +{ + struct aspeed_pci_bmc_dev *pci_bmc_dev = pci_get_drvdata(pdev); + + if (pci_bmc_dev->driver_data == ASPEED) { + aspeed_pci_host_bmc_device_release_queue(pdev); + aspeed_pci_host_bmc_device_release_memory_mapping(pdev); + aspeed_pci_host_bmc_device_release_vuart(pdev); + + devm_free_irq(&pdev->dev, pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[BMC_MSI]), + pci_bmc_dev); + devm_free_irq(&pdev->dev, pci_irq_vector(pdev, pci_bmc_dev->msi_idx_table[MBX_MSI]), + pci_bmc_dev); + } + + aspeed_pci_release_mmbi(pdev); + + ida_simple_remove(&bmc_device_ida, pci_bmc_dev->id); + + pci_iounmap(pdev, pci_bmc_dev->msg_bar_reg); + pci_iounmap(pdev, pci_bmc_dev->mem_bar_reg); + + pci_free_irq_vectors(pdev); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +/** + * This table holds the list of (VendorID,DeviceID) supported by this driver + * + */ +static struct pci_device_id aspeed_host_bmc_dev_pci_ids[] = { + /* ASPEED BMC Device */ + { PCI_DEVICE(0x1A03, 0x2402), .class = 0xFF0000, .class_mask = 0xFFFF00, + .driver_data = ASPEED }, + /* AST2700 SoC1 MMBI device */ + { PCI_DEVICE(0x1A03, 0x2402), .class = 0x0C0C00, .class_mask = (0xFFFF00), + .driver_data = ASPEED_AST2700_SOC1 }, + { + 0, + } +}; + +MODULE_DEVICE_TABLE(pci, aspeed_host_bmc_dev_pci_ids); + +static struct pci_driver aspeed_host_bmc_dev_driver = { + .name = DRIVER_NAME, + .id_table = aspeed_host_bmc_dev_pci_ids, + .probe = aspeed_pci_host_bmc_device_probe, + .remove = aspeed_pci_host_bmc_device_remove, +}; + +static int __init aspeed_host_bmc_device_init(void) +{ + return pci_register_driver(&aspeed_host_bmc_dev_driver); +} + +static void aspeed_host_bmc_device_exit(void) +{ + /* unregister pci driver */ + pci_unregister_driver(&aspeed_host_bmc_dev_driver); +} + +late_initcall(aspeed_host_bmc_device_init); +module_exit(aspeed_host_bmc_device_exit); + +MODULE_AUTHOR("Ryan Chen "); +MODULE_DESCRIPTION("ASPEED Host BMC DEVICE Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c index e87038009d1b2c..258894ed234b3d 100644 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c @@ -332,12 +332,14 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) return rc; } -static void aspeed_lpc_ctrl_remove(struct platform_device *pdev) +static int aspeed_lpc_ctrl_remove(struct platform_device *pdev) { struct aspeed_lpc_ctrl *lpc_ctrl = dev_get_drvdata(&pdev->dev); misc_deregister(&lpc_ctrl->miscdev); clk_disable_unprepare(lpc_ctrl->clk); + + return 0; } static const struct of_device_id aspeed_lpc_ctrl_match[] = { @@ -353,7 +355,7 @@ static struct platform_driver aspeed_lpc_ctrl_driver = { .of_match_table = aspeed_lpc_ctrl_match, }, .probe = aspeed_lpc_ctrl_probe, - .remove_new = aspeed_lpc_ctrl_remove, + .remove = aspeed_lpc_ctrl_remove, }; module_platform_driver(aspeed_lpc_ctrl_driver); diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c new file mode 100644 index 00000000000000..4b6a1693ec80fa --- /dev/null +++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2017 IBM Corporation + * Copyright 2021 Aspeed Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "aspeed-mbox" + +static DEFINE_IDA(aspeed_mbox_ida); + +#define ASPEED_MBOX_DR(dr, n) (dr + (n * 4)) +#define ASPEED_MBOX_STR(str, n) (str + (n / 8) * 4) +#define ASPEED_MBOX_BIE(bie, n) (bie + (n / 8) * 4) +#define ASPEED_MBOX_HIE(hie, n) (hie + (n / 8) * 4) + +#define ASPEED_MBOX_BCR_RECV BIT(7) +#define ASPEED_MBOX_BCR_MASK BIT(1) +#define ASPEED_MBOX_BCR_SEND BIT(0) + +/* ioctl code */ +#define ASPEED_MBOX_IOCTL 0xA3 +#define ASPEED_MBOX_IOCTL_GET_SIZE \ + _IOR(ASPEED_MBOX_IOCTL, 0, struct aspeed_mbox_ioctl_data) + +struct aspeed_mbox_ioctl_data { + unsigned int data; +}; + +struct aspeed_mbox_model { + unsigned int dr_num; + + /* offsets to the MBOX registers */ + unsigned int dr; + unsigned int str; + unsigned int bcr; + unsigned int hcr; + unsigned int bie; + unsigned int hie; +}; + +struct aspeed_mbox { + int mdev_id; + struct miscdevice mdev; + struct regmap *map; + unsigned int base; + wait_queue_head_t queue; + struct mutex mutex; + const struct aspeed_mbox_model *model; +}; + +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->map, mbox->base + reg, &val); + + if (rc) + dev_err(mbox->mdev.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->map, mbox->base + reg, data); + + if (rc) + dev_err(mbox->mdev.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, mdev); +} + +static int aspeed_mbox_open(struct inode *inode, struct file *file) +{ + struct aspeed_mbox *mbox = file_mbox(file); + const struct aspeed_mbox_model *model = mbox->model; + + if (atomic_inc_return(&aspeed_mbox_open_count) == 1) { + /* + * Clear the interrupt status bit if it was left on and unmask + * interrupts. + * ASPEED_MBOX_BCR_RECV bit is W1C, this also unmasks in 1 step + */ + aspeed_mbox_outb(mbox, ASPEED_MBOX_BCR_RECV, model->bcr); + 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); + const struct aspeed_mbox_model *model = mbox->model; + char __user *p = buf; + ssize_t ret; + int i; + + if (!access_ok(buf, count)) + return -EFAULT; + + if (count + *ppos > model->dr_num) + return -EINVAL; + + if (file->f_flags & O_NONBLOCK) { + if (!(aspeed_mbox_inb(mbox, model->bcr) & + ASPEED_MBOX_BCR_RECV)) + return -EAGAIN; + } else if (wait_event_interruptible(mbox->queue, + aspeed_mbox_inb(mbox, model->bcr) & + ASPEED_MBOX_BCR_RECV)) { + return -ERESTARTSYS; + } + + mutex_lock(&mbox->mutex); + + for (i = *ppos; count > 0 && i < model->dr_num; i++) { + uint8_t reg = aspeed_mbox_inb(mbox, ASPEED_MBOX_DR(model->dr, i)); + + ret = __put_user(reg, p); + if (ret) + goto out_unlock; + + p++; + count--; + } + + /* ASPEED_MBOX_BCR_RECV bit is write to clear, this also unmasks in 1 step */ + aspeed_mbox_outb(mbox, ASPEED_MBOX_BCR_RECV, model->bcr); + 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 struct aspeed_mbox_model *model = mbox->model; + const char __user *p = buf; + ssize_t ret; + char c; + int i; + + if (!access_ok(buf, count)) + return -EFAULT; + + if (count + *ppos > model->dr_num) + return -EINVAL; + + mutex_lock(&mbox->mutex); + + for (i = *ppos; count > 0 && i < model->dr_num; i++) { + ret = __get_user(c, p); + if (ret) + goto out_unlock; + + aspeed_mbox_outb(mbox, c, ASPEED_MBOX_DR(model->dr, i)); + p++; + count--; + } + + aspeed_mbox_outb(mbox, ASPEED_MBOX_BCR_SEND, model->bcr); + ret = p - buf; + +out_unlock: + mutex_unlock(&mbox->mutex); + return ret; +} + +static __poll_t aspeed_mbox_poll(struct file *file, poll_table *wait) +{ + struct aspeed_mbox *mbox = file_mbox(file); + const struct aspeed_mbox_model *model = mbox->model; + __poll_t mask = 0; + + poll_wait(file, &mbox->queue, wait); + + if (aspeed_mbox_inb(mbox, model->bcr) & ASPEED_MBOX_BCR_RECV) + mask |= POLLIN; + + return mask; +} + +static int aspeed_mbox_release(struct inode *inode, struct file *file) +{ + atomic_dec(&aspeed_mbox_open_count); + return 0; +} + +static long aspeed_mbox_ioctl(struct file *file, unsigned int cmd, + unsigned long param) +{ + long ret = 0; + struct aspeed_mbox *mbox = file_mbox(file); + const struct aspeed_mbox_model *model = mbox->model; + struct aspeed_mbox_ioctl_data data; + + switch (cmd) { + case ASPEED_MBOX_IOCTL_GET_SIZE: + data.data = model->dr_num; + if (copy_to_user((void __user *)param, &data, sizeof(data))) + ret = -EFAULT; + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +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, + .unlocked_ioctl = aspeed_mbox_ioctl, +}; + +static irqreturn_t aspeed_mbox_irq(int irq, void *arg) +{ + struct aspeed_mbox *mbox = arg; + const struct aspeed_mbox_model *model = mbox->model; + + if (!(aspeed_mbox_inb(mbox, model->bcr) & ASPEED_MBOX_BCR_RECV)) + return IRQ_NONE; + + /* + * Leave the status bit set so that we know the data is for us, + * clear it once it has been read. + */ + + /* Mask it off, we'll clear it when we the data gets read */ + aspeed_mbox_outb(mbox, ASPEED_MBOX_BCR_MASK, model->bcr); + + wake_up(&mbox->queue); + return IRQ_HANDLED; +} + +static int aspeed_mbox_config_irq(struct aspeed_mbox *mbox, + struct platform_device *pdev) +{ + const struct aspeed_mbox_model *model = mbox->model; + struct device *dev = &pdev->dev; + int i, rc, irq; + + irq = irq_of_parse_and_map(dev->of_node, 0); + if (!irq) + return -ENODEV; + + rc = devm_request_irq(dev, irq, aspeed_mbox_irq, + IRQF_SHARED, DEVICE_NAME, mbox); + if (rc < 0) { + dev_err(dev, "Unable to request IRQ %d\n", irq); + return rc; + } + + /* + * Disable all register based interrupts. + */ + for (i = 0; i < model->dr_num / 8; ++i) + aspeed_mbox_outb(mbox, 0x00, ASPEED_MBOX_BIE(model->bie, i)); + + /* These registers are write one to clear. Clear them. */ + for (i = 0; i < model->dr_num / 8; ++i) + aspeed_mbox_outb(mbox, 0xff, ASPEED_MBOX_STR(model->str, i)); + + aspeed_mbox_outb(mbox, ASPEED_MBOX_BCR_RECV, model->bcr); + 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->model = of_device_get_match_data(dev); + if (IS_ERR(mbox->model)) { + dev_err(dev, "Couldn't get model data\n"); + return -ENODEV; + } + + mbox->map = syscon_node_to_regmap( + pdev->dev.parent->of_node); + if (IS_ERR(mbox->map)) { + dev_err(dev, "Couldn't get regmap\n"); + return -ENODEV; + } + + mutex_init(&mbox->mutex); + init_waitqueue_head(&mbox->queue); + + mbox->mdev_id = ida_alloc(&aspeed_mbox_ida, GFP_KERNEL); + if (mbox->mdev_id < 0) { + dev_err(dev, "cannot allocate device ID\n"); + return mbox->mdev_id; + } + + mbox->mdev.minor = MISC_DYNAMIC_MINOR; + mbox->mdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, mbox->mdev_id); + mbox->mdev.fops = &aspeed_mbox_fops; + mbox->mdev.parent = dev; + rc = misc_register(&mbox->mdev); + if (rc) { + dev_err(dev, "Unable to register device\n"); + return rc; + } + + rc = aspeed_mbox_config_irq(mbox, pdev); + if (rc) { + dev_err(dev, "Failed to configure IRQ\n"); + misc_deregister(&mbox->mdev); + return rc; + } + + return 0; +} + +static int aspeed_mbox_remove(struct platform_device *pdev) +{ + struct aspeed_mbox *mbox = dev_get_drvdata(&pdev->dev); + + misc_deregister(&mbox->mdev); + + return 0; +} + +static const struct aspeed_mbox_model ast2400_model = { + .dr_num = 16, + .dr = 0x0, + .str = 0x40, + .bcr = 0x48, + .hcr = 0x4c, + .bie = 0x50, + .hie = 0x58, +}; + +static const struct aspeed_mbox_model ast2500_model = { + .dr_num = 16, + .dr = 0x0, + .str = 0x40, + .bcr = 0x48, + .hcr = 0x4c, + .bie = 0x50, + .hie = 0x58, +}; + +static const struct aspeed_mbox_model ast2600_model = { + .dr_num = 32, + .dr = 0x0, + .str = 0x80, + .bcr = 0x90, + .hcr = 0x94, + .bie = 0xa0, + .hie = 0xb0, +}; + +static const struct aspeed_mbox_model ast2700_model = { + .dr_num = 32, + .dr = 0x0, + .str = 0x80, + .bcr = 0x90, + .hcr = 0x94, + .bie = 0xa0, + .hie = 0xb0, +}; + +static const struct of_device_id aspeed_mbox_match[] = { + { .compatible = "aspeed,ast2400-mbox", + .data = &ast2400_model }, + { .compatible = "aspeed,ast2500-mbox", + .data = &ast2500_model }, + { .compatible = "aspeed,ast2600-mbox", + .data = &ast2600_model }, + { .compatible = "aspeed,ast2700-mbox", + .data = &ast2700_model }, + { }, +}; + +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_DEVICE_TABLE(of, aspeed_mbox_match); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Cyril Bur "); +MODULE_AUTHOR("Chia-Wei Wang +#include #include #include #include @@ -22,6 +23,9 @@ static DEFINE_IDA(aspeed_pcc_ida); +#define HICR5 0x80 +#define HICR5_EN_SNP0W BIT(0) +#define HICR5_EN_SNP1W BIT(2) #define HICR6 0x084 #define HICR6_EN2BMODE BIT(19) #define SNPWADR 0x090 @@ -69,6 +73,9 @@ static DEFINE_IDA(aspeed_pcc_ida); #define PCC_DMA_BUFSZ (256 * SZ_1K) +/* Except for the 1-byte threshold, the rest represent fractions of the FIFO. + * Ex. PCC_FIFO_THR_1_EIGHTH means 1/8th of the FIFO size. + */ enum pcc_fifo_threshold { PCC_FIFO_THR_1_BYTE, PCC_FIFO_THR_1_EIGHTH, @@ -78,7 +85,6 @@ enum pcc_fifo_threshold { PCC_FIFO_THR_5_EIGHTH, PCC_FIFO_THR_6_EIGHTH, PCC_FIFO_THR_7_EIGHTH, - PCC_FIFO_THR_8_EIGHTH, }; enum pcc_record_mode { @@ -102,21 +108,17 @@ struct aspeed_pcc_dma { uint32_t size; }; -struct aspeed_pcc { +struct aspeed_pcc_ctrl { struct device *dev; struct regmap *regmap; int irq; - uint32_t rec_mode; uint32_t port; - uint32_t port_xbits; - uint32_t port_hbits_select; - uint32_t dma_mode; struct aspeed_pcc_dma dma; struct kfifo fifo; wait_queue_head_t wq; struct miscdevice mdev; int mdev_id; - bool a2600_15; + spinlock_t lock; /* protects access to the FIFO and DMA pointer */ }; static inline bool is_valid_rec_mode(uint32_t mode) @@ -130,12 +132,12 @@ static inline bool is_valid_high_bits_select(uint32_t sel) } static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { int rc; unsigned int copied; - struct aspeed_pcc *pcc = container_of(file->private_data, - struct aspeed_pcc, + struct aspeed_pcc_ctrl *pcc = container_of(file->private_data, + struct aspeed_pcc_ctrl, mdev); if (kfifo_is_empty(&pcc->fifo)) { @@ -154,12 +156,11 @@ static ssize_t aspeed_pcc_file_read(struct file *file, char __user *buffer, } static __poll_t aspeed_pcc_file_poll(struct file *file, - struct poll_table_struct *pt) + struct poll_table_struct *pt) { - struct aspeed_pcc *pcc = container_of( - file->private_data, - struct aspeed_pcc, - mdev); + struct aspeed_pcc_ctrl *pcc = container_of(file->private_data, + struct aspeed_pcc_ctrl, + mdev); poll_wait(file, &pcc->wq, pt); @@ -175,25 +176,29 @@ static const struct file_operations pcc_fops = { static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg) { uint32_t reg, rptr, wptr; - struct aspeed_pcc *pcc = (struct aspeed_pcc*)arg; + struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg; struct kfifo *fifo = &pcc->fifo; + spin_lock(&pcc->lock); + regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_INT_STATUS_DMA_DONE); + regmap_read(pcc->regmap, PCCR6, ®); wptr = (reg & PCCR6_DMA_CUR_ADDR) - (pcc->dma.addr & PCCR6_DMA_CUR_ADDR); rptr = pcc->dma.rptr; - do { - if (kfifo_is_full(fifo)) - kfifo_skip(fifo); - - kfifo_put(fifo, pcc->dma.virt[rptr]); - - rptr = (rptr + 1) % pcc->dma.size; - } while (rptr != wptr); - - pcc->dma.rptr = rptr; + /* If kfifo is empty or has enough space, insert new data; + * otherwise, discard the new data. + */ + if (rptr <= wptr) { + kfifo_in(fifo, pcc->dma.virt + rptr, wptr - rptr); + } else { + /* Handle wrap-around case */ + kfifo_in(fifo, pcc->dma.virt + rptr, pcc->dma.size - rptr); + kfifo_in(fifo, pcc->dma.virt, wptr); + } - regmap_write_bits(pcc->regmap, PCCR2, PCCR2_INT_STATUS_DMA_DONE, PCCR2_INT_STATUS_DMA_DONE); + pcc->dma.rptr = wptr; + spin_unlock(&pcc->lock); wake_up_interruptible(&pcc->wq); @@ -202,32 +207,17 @@ static irqreturn_t aspeed_pcc_dma_isr(int irq, void *arg) static irqreturn_t aspeed_pcc_isr(int irq, void *arg) { - uint32_t sts, reg; - struct aspeed_pcc *pcc = (struct aspeed_pcc*)arg; - struct kfifo *fifo = &pcc->fifo; + uint32_t sts; + struct aspeed_pcc_ctrl *pcc = (struct aspeed_pcc_ctrl *)arg; regmap_read(pcc->regmap, PCCR2, &sts); - if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT | PCCR2_INT_STATUS_RX_AVAIL | PCCR2_INT_STATUS_DMA_DONE))) + if (!(sts & (PCCR2_INT_STATUS_RX_TMOUT | + PCCR2_INT_STATUS_RX_AVAIL | + PCCR2_INT_STATUS_DMA_DONE))) return IRQ_NONE; - if (pcc->dma_mode) - return aspeed_pcc_dma_isr(irq, arg); - - while (sts & PCCR2_INT_STATUS_DATA_RDY) { - regmap_read(pcc->regmap, PCCR3, ®); - - if (kfifo_is_full(fifo)) - kfifo_skip(fifo); - - kfifo_put(fifo, reg & PCCR3_FIFO_DATA_MASK); - - regmap_read(pcc->regmap, PCCR2, &sts); - } - - wake_up_interruptible(&pcc->wq); - - return IRQ_HANDLED; + return aspeed_pcc_dma_isr(irq, arg); } /* @@ -237,24 +227,15 @@ static irqreturn_t aspeed_pcc_isr(int irq, void *arg) * eSPI response when PCC is used for port I/O byte snooping * over eSPI. */ -static int aspeed_a2600_15(struct aspeed_pcc *pcc, struct device *dev) +static int aspeed_a2600_15(struct aspeed_pcc_ctrl *pcc, struct device *dev) { - struct device_node *np; - u32 hicrb_en; + u32 hicr5_en, hicrb_en; /* abort if snoop is enabled */ - np = of_find_compatible_node(dev->parent->of_node, NULL, "aspeed,ast2600-lpc-snoop"); - if (np) { - if (of_device_is_available(np)) { - dev_err(dev, "A2600-15 should be applied with snoop disabled\n"); - return -EPERM; - } - } - - /* abort if port is not 4-bytes continuous range */ - if (pcc->port_xbits != 0x3) { - dev_err(dev, "A2600-15 should be applied on 4-bytes continuous I/O address range\n"); - return -EINVAL; + regmap_read(pcc->regmap, HICR5, &hicr5_en); + if (hicr5_en & (HICR5_EN_SNP0W | HICR5_EN_SNP1W)) { + dev_err(dev, "A2600-15 should be applied with snoop disabled\n"); + return -EPERM; } /* set SNPWADR of snoop device */ @@ -270,112 +251,91 @@ static int aspeed_a2600_15(struct aspeed_pcc *pcc, struct device *dev) return 0; } -static int aspeed_pcc_enable(struct aspeed_pcc *pcc, struct device *dev) +static int aspeed_pcc_enable(struct aspeed_pcc_ctrl *pcc, struct device *dev) { int rc; - if (pcc->a2600_15) { - rc = aspeed_a2600_15(pcc, dev); - if (rc) - return rc; - } + rc = aspeed_a2600_15(pcc, dev); + if (rc) + return rc; - /* record mode */ + /* record mode: Set 2-Byte mode. */ regmap_update_bits(pcc->regmap, PCCR0, PCCR0_MODE_SEL_MASK, - pcc->rec_mode << PCCR0_MODE_SEL_SHIFT); + PCC_REC_2B << PCCR0_MODE_SEL_SHIFT); /* port address */ regmap_update_bits(pcc->regmap, PCCR1, PCCR1_BASE_ADDR_MASK, pcc->port << PCCR1_BASE_ADDR_SHIFT); - /* port address high bits selection or parser control */ + /* Set address high bits selection to 0b01 for address bit[5:4] */ regmap_update_bits(pcc->regmap, PCCR0, PCCR0_ADDR_SEL_MASK, - pcc->port_hbits_select << PCCR0_ADDR_SEL_SHIFT); + PCC_PORT_HBITS_SEL_45 << PCCR0_ADDR_SEL_SHIFT); - /* port address dont care bits */ + /* Set LPC don't care address to 0x3 for port 80~83h */ regmap_update_bits(pcc->regmap, PCCR1, PCCR1_DONT_CARE_BITS_MASK, - pcc->port_xbits << PCCR1_DONT_CARE_BITS_SHIFT); + 0x3 << PCCR1_DONT_CARE_BITS_SHIFT); /* set DMA ring buffer size and enable interrupts */ - if (pcc->dma_mode) { - regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff); - regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK, - (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT); - regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK, - (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT); - regmap_update_bits(pcc->regmap, PCCR0, - PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE, - PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE); - } else { - regmap_update_bits(pcc->regmap, PCCR0, PCCR0_RX_TRIG_LVL_MASK, - PCC_FIFO_THR_4_EIGHTH << PCCR0_RX_TRIG_LVL_SHIFT); - regmap_update_bits(pcc->regmap, PCCR0, - PCCR0_EN_RX_TMOUT_INT | PCCR0_EN_RX_AVAIL_INT, - PCCR0_EN_RX_TMOUT_INT | PCCR0_EN_RX_AVAIL_INT); - } + regmap_write(pcc->regmap, PCCR4, pcc->dma.addr & 0xffffffff); +#ifdef CONFIG_ARM64 + regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_ADDRH_MASK, + (pcc->dma.addr >> 32) << PCCR5_DMA_ADDRH_SHIFT); +#endif + regmap_update_bits(pcc->regmap, PCCR5, PCCR5_DMA_LEN_MASK, + (pcc->dma.size / 4) << PCCR5_DMA_LEN_SHIFT); + regmap_update_bits(pcc->regmap, PCCR0, + PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE, + PCCR0_EN_DMA_INT | PCCR0_EN_DMA_MODE); + + regmap_update_bits(pcc->regmap, PCCR0, + PCCR0_RX_TRIG_LVL_MASK, + PCC_FIFO_THR_2_EIGHTH << PCCR0_RX_TRIG_LVL_SHIFT); regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN, PCCR0_EN); return 0; } +static int aspeed_pcc_disable(struct aspeed_pcc_ctrl *pcc) +{ + /* Disable PCC and DMA Mode for safety */ + regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN | PCCR0_EN_DMA_MODE, 0); + + /* Clear Rx FIFO. */ + regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1); + + /* Clear All interrupts status. */ + regmap_write(pcc->regmap, PCCR2, + PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE | + PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B); + + return 0; +} + static int aspeed_pcc_probe(struct platform_device *pdev) { int rc; - struct aspeed_pcc *pcc; + struct aspeed_pcc_ctrl *pcc; struct device *dev = &pdev->dev; uint32_t fifo_size = PAGE_SIZE; - pcc = devm_kzalloc(&pdev->dev, sizeof(*pcc), GFP_KERNEL); + pcc = devm_kzalloc(dev, sizeof(*pcc), GFP_KERNEL); if (!pcc) return -ENOMEM; - pcc->dev = dev; - rc = of_property_read_u32(dev->of_node, "port-addr", &pcc->port); - if (rc) { - dev_err(dev, "cannot get port address\n"); - return -ENODEV; - } - - /* optional, by default: 0 -> 1-Byte mode */ - of_property_read_u32(dev->of_node, "rec-mode", &pcc->rec_mode); - if (!is_valid_rec_mode(pcc->rec_mode)) { - dev_err(dev, "invalid record mode: %u\n", - pcc->rec_mode); - return -EINVAL; - } + pcc->regmap = syscon_node_to_regmap(dev->parent->of_node); + if (IS_ERR(pcc->regmap)) + return dev_err_probe(dev, PTR_ERR(pcc->regmap), "Couldn't get regmap\n"); - /* optional, by default: 0 -> no don't care bits */ - of_property_read_u32(dev->of_node, "port-addr-xbits", &pcc->port_xbits); - - /* - * optional, by default: 0 -> no high address bits - * - * Note that when record mode is set to 1-Byte, this - * property is ignored and the corresponding HW bits - * behave as read/write cycle parser control with the - * value set to 0b11 - */ - if (pcc->rec_mode) { - of_property_read_u32(dev->of_node, "port-addr-hbits-select", - &pcc->port_hbits_select); - if (!is_valid_high_bits_select(pcc->port_hbits_select)) { - dev_err(dev, "invalid high address bits selection: %u\n", - pcc->port_hbits_select); - return -EINVAL; - } + rc = of_property_read_u32(dev->of_node, "pcc-ports", &pcc->port); + if (rc) { + dev_err(dev, "no pcc ports configured\n"); + return rc; } - else - pcc->port_hbits_select = 0x3; - - /* AP note A2600-15 */ - pcc->a2600_15 = of_property_read_bool(dev->of_node, "A2600-15"); - if (pcc->a2600_15) - dev_info(dev, "A2600-15 AP note patch is selected\n"); rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); if (rc) { @@ -383,54 +343,39 @@ static int aspeed_pcc_probe(struct platform_device *pdev) return rc; } - pcc->dma_mode = of_property_read_bool(dev->of_node, "dma-mode"); - if (pcc->dma_mode) { - pcc->dma.size = PCC_DMA_BUFSZ; - pcc->dma.virt = dmam_alloc_coherent(dev, - pcc->dma.size, - &pcc->dma.addr, - GFP_KERNEL); - if (!pcc->dma.virt) { - dev_err(dev, "cannot allocate DMA buffer\n"); - return -ENOMEM; - } - - fifo_size = roundup(pcc->dma.size, PAGE_SIZE); - } - - rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL); - if (rc) { - dev_err(dev, "cannot allocate kFIFO\n"); + pcc->dma.size = PCC_DMA_BUFSZ; + pcc->dma.virt = dmam_alloc_coherent(dev, + pcc->dma.size, + &pcc->dma.addr, + GFP_KERNEL); + if (!pcc->dma.virt) { + dev_err(dev, "cannot allocate DMA buffer\n"); return -ENOMEM; } - pcc->regmap = syscon_node_to_regmap(pdev->dev.parent->of_node); - if (IS_ERR(pcc->regmap)) { - dev_err(dev, "cannot map register\n"); - return -ENODEV; - } - - /* Disable PCC and DMA Mode for safety */ - regmap_update_bits(pcc->regmap, PCCR0, PCCR0_EN | PCCR0_EN_DMA_MODE, 0); + fifo_size = roundup(pcc->dma.size, PAGE_SIZE); + rc = kfifo_alloc(&pcc->fifo, fifo_size, GFP_KERNEL); + if (rc) + return rc; - /* Clear Rx FIFO. */ - regmap_update_bits(pcc->regmap, PCCR0, PCCR0_CLR_RX_FIFO, 1); + spin_lock_init(&pcc->lock); - /* Clear All interrupts status. */ - regmap_write(pcc->regmap, PCCR2, - PCCR2_INT_STATUS_RX_OVER | PCCR2_INT_STATUS_DMA_DONE | - PCCR2_INT_STATUS_PATTERN_A | PCCR2_INT_STATUS_PATTERN_B); + /* Disable PCC to clean up DMA buffer before request IRQ. */ + rc = aspeed_pcc_disable(pcc); + if (rc) { + dev_err(dev, "Couldn't disable PCC\n"); + goto err_free_kfifo; + } pcc->irq = platform_get_irq(pdev, 0); if (pcc->irq < 0) { - dev_err(dev, "cannot get IRQ\n"); - rc = -ENODEV; + rc = pcc->irq; goto err_free_kfifo; } rc = devm_request_irq(dev, pcc->irq, aspeed_pcc_isr, 0, DEVICE_NAME, pcc); if (rc < 0) { - dev_err(dev, "cannot request IRQ handler\n"); + dev_err(dev, "Couldn't request IRQ %d\n", pcc->irq); goto err_free_kfifo; } @@ -438,8 +383,8 @@ static int aspeed_pcc_probe(struct platform_device *pdev) pcc->mdev_id = ida_alloc(&aspeed_pcc_ida, GFP_KERNEL); if (pcc->mdev_id < 0) { - dev_err(dev, "cannot allocate ID\n"); - return pcc->mdev_id; + dev_err(dev, "Couldn't allocate ID\n"); + goto err_free_kfifo; } pcc->mdev.parent = dev; @@ -449,25 +394,26 @@ static int aspeed_pcc_probe(struct platform_device *pdev) pcc->mdev.fops = &pcc_fops; rc = misc_register(&pcc->mdev); if (rc) { - dev_err(dev, "cannot register misc device\n"); - goto err_free_kfifo; + dev_err(dev, "Couldn't register misc device\n"); + goto err_free_ida; } rc = aspeed_pcc_enable(pcc, dev); if (rc) { - dev_err(dev, "cannot enable PCC\n"); + dev_err(dev, "Couldn't enable PCC\n"); goto err_dereg_mdev; } - dev_set_drvdata(&pdev->dev, pcc); - - dev_info(dev, "module loaded\n"); + dev_set_drvdata(dev, pcc); return 0; err_dereg_mdev: misc_deregister(&pcc->mdev); +err_free_ida: + ida_free(&aspeed_pcc_ida, pcc->mdev_id); + err_free_kfifo: kfifo_free(&pcc->fifo); @@ -477,16 +423,16 @@ static int aspeed_pcc_probe(struct platform_device *pdev) static int aspeed_pcc_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct aspeed_pcc *pcc = dev_get_drvdata(dev); + struct aspeed_pcc_ctrl *pcc = dev_get_drvdata(dev); kfifo_free(&pcc->fifo); + ida_free(&aspeed_pcc_ida, pcc->mdev_id); misc_deregister(&pcc->mdev); return 0; } static const struct of_device_id aspeed_pcc_table[] = { - { .compatible = "aspeed,ast2500-lpc-pcc" }, { .compatible = "aspeed,ast2600-lpc-pcc" }, { }, }; diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index aad3873c0e9a39..773dbcbc03a6cd 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -200,15 +200,11 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR; lpc_snoop->chan[channel].miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel); - if (!lpc_snoop->chan[channel].miscdev.name) { - rc = -ENOMEM; - goto err_free_fifo; - } lpc_snoop->chan[channel].miscdev.fops = &snoop_fops; lpc_snoop->chan[channel].miscdev.parent = dev; rc = misc_register(&lpc_snoop->chan[channel].miscdev); if (rc) - goto err_free_fifo; + return rc; /* Enable LPC snoop channel at requested port */ switch (channel) { @@ -225,8 +221,7 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, hicrb_en = HICRB_ENSNP1D; break; default: - rc = -EINVAL; - goto err_misc_deregister; + return -EINVAL; } regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en); @@ -236,12 +231,6 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, regmap_update_bits(lpc_snoop->regmap, HICRB, hicrb_en, hicrb_en); - return 0; - -err_misc_deregister: - misc_deregister(&lpc_snoop->chan[channel].miscdev); -err_free_fifo: - kfifo_free(&lpc_snoop->chan[channel].fifo); return rc; } @@ -342,7 +331,7 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) return rc; } -static void aspeed_lpc_snoop_remove(struct platform_device *pdev) +static int aspeed_lpc_snoop_remove(struct platform_device *pdev) { struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); @@ -351,6 +340,8 @@ static void aspeed_lpc_snoop_remove(struct platform_device *pdev) aspeed_lpc_disable_snoop(lpc_snoop, 1); clk_disable_unprepare(lpc_snoop->clk); + + return 0; } static const struct aspeed_lpc_snoop_model_data ast2400_model_data = { @@ -377,7 +368,7 @@ static struct platform_driver aspeed_lpc_snoop_driver = { .of_match_table = aspeed_lpc_snoop_match, }, .probe = aspeed_lpc_snoop_probe, - .remove_new = aspeed_lpc_snoop_remove, + .remove = aspeed_lpc_snoop_remove, }; module_platform_driver(aspeed_lpc_snoop_driver); diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c index 8610ddacc7bc9c..548f44da28a92e 100644 --- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c +++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c @@ -383,11 +383,13 @@ static int aspeed_p2a_ctrl_probe(struct platform_device *pdev) return rc; } -static void aspeed_p2a_ctrl_remove(struct platform_device *pdev) +static int aspeed_p2a_ctrl_remove(struct platform_device *pdev) { struct aspeed_p2a_ctrl *p2a_ctrl = dev_get_drvdata(&pdev->dev); misc_deregister(&p2a_ctrl->miscdev); + + return 0; } #define SCU2C_DRAM BIT(25) @@ -431,7 +433,7 @@ static struct platform_driver aspeed_p2a_ctrl_driver = { .of_match_table = aspeed_p2a_ctrl_match, }, .probe = aspeed_p2a_ctrl_probe, - .remove_new = aspeed_p2a_ctrl_remove, + .remove = aspeed_p2a_ctrl_remove, }; module_platform_driver(aspeed_p2a_ctrl_driver); diff --git a/drivers/soc/aspeed/aspeed-socinfo.c b/drivers/soc/aspeed/aspeed-socinfo.c index 7ee7f291109e65..67e9ac3d08ecc8 100644 --- a/drivers/soc/aspeed/aspeed-socinfo.c +++ b/drivers/soc/aspeed/aspeed-socinfo.c @@ -12,9 +12,7 @@ static struct { const char *name; const u32 id; -} - -const rev_table[] = { +} const rev_table[] = { /* AST2400 */ { "AST2400", 0x02000303 }, { "AST1400", 0x02010103 }, @@ -63,7 +61,7 @@ static const char *siliconid_to_rev(u32 siliconid) case 3: return "A2"; } - } else if (gen == 0x6) { + } else { /* AST2600 */ switch (rev) { case 0: @@ -75,12 +73,6 @@ static const char *siliconid_to_rev(u32 siliconid) case 3: return "A3"; } - } else { - /* AST2700 */ - switch (rev) { - case 0: - return "A0"; - } } return "??"; diff --git a/drivers/soc/aspeed/aspeed-uart-routing.c b/drivers/soc/aspeed/aspeed-uart-routing.c index 5453a7bf31054c..cc74d5fa698b2b 100644 --- a/drivers/soc/aspeed/aspeed-uart-routing.c +++ b/drivers/soc/aspeed/aspeed-uart-routing.c @@ -985,12 +985,14 @@ static int aspeed_uart_routing_probe(struct platform_device *pdev) return 0; } -static void aspeed_uart_routing_remove(struct platform_device *pdev) +static int aspeed_uart_routing_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct aspeed_uart_routing *uart_routing = platform_get_drvdata(pdev); sysfs_remove_group(&dev->kobj, uart_routing->attr_grp); + + return 0; } static const struct of_device_id aspeed_uart_routing_table[] = { @@ -1013,7 +1015,7 @@ static struct platform_driver aspeed_uart_routing_driver = { .of_match_table = aspeed_uart_routing_table, }, .probe = aspeed_uart_routing_probe, - .remove_new = aspeed_uart_routing_remove, + .remove = aspeed_uart_routing_remove, }; module_platform_driver(aspeed_uart_routing_driver); diff --git a/drivers/soc/aspeed/aspeed-udma.c b/drivers/soc/aspeed/aspeed-udma.c index 9f7b58fb7b5162..8dc6f3cfc1db1c 100644 --- a/drivers/soc/aspeed/aspeed-udma.c +++ b/drivers/soc/aspeed/aspeed-udma.c @@ -60,7 +60,6 @@ enum aspeed_udma_bufsz_code { struct aspeed_udma_chan { dma_addr_t dma_addr; - struct circ_buf *rb; u32 rb_sz; aspeed_udma_cb_t cb; @@ -160,9 +159,9 @@ int aspeed_udma_free_rx_chan(u32 ch_no) } EXPORT_SYMBOL(aspeed_udma_free_rx_chan); -static int aspeed_udma_request_chan(u32 ch_no, dma_addr_t addr, - struct circ_buf *rb, u32 rb_sz, - aspeed_udma_cb_t cb, void *id, bool dis_tmout, bool is_tx) +static int aspeed_udma_request_chan(u32 ch_no, dma_addr_t addr, u32 rb_sz, + aspeed_udma_cb_t cb, void *id, + bool dis_tmout, bool is_tx) { int retval = 0; int rbsz_code; @@ -176,11 +175,6 @@ static int aspeed_udma_request_chan(u32 ch_no, dma_addr_t addr, goto out; } - if (IS_ERR_OR_NULL(rb) || IS_ERR_OR_NULL(rb->buf)) { - retval = -EINVAL; - goto out; - } - rbsz_code = aspeed_udma_get_bufsz_code(rb_sz); if (rbsz_code < 0) { retval = -EINVAL; @@ -224,7 +218,6 @@ static int aspeed_udma_request_chan(u32 ch_no, dma_addr_t addr, } ch = (is_tx) ? &udma->tx_chs[ch_no] : &udma->rx_chs[ch_no]; - ch->rb = rb; ch->rb_sz = rb_sz; ch->cb = cb; ch->cb_arg = id; @@ -237,20 +230,18 @@ static int aspeed_udma_request_chan(u32 ch_no, dma_addr_t addr, return 0; } -int aspeed_udma_request_tx_chan(u32 ch_no, dma_addr_t addr, - struct circ_buf *rb, u32 rb_sz, +int aspeed_udma_request_tx_chan(u32 ch_no, dma_addr_t addr, u32 rb_sz, aspeed_udma_cb_t cb, void *id, bool dis_tmout) { - return aspeed_udma_request_chan(ch_no, addr, rb, rb_sz, cb, id, + return aspeed_udma_request_chan(ch_no, addr, rb_sz, cb, id, dis_tmout, true); } EXPORT_SYMBOL(aspeed_udma_request_tx_chan); -int aspeed_udma_request_rx_chan(u32 ch_no, dma_addr_t addr, - struct circ_buf *rb, u32 rb_sz, +int aspeed_udma_request_rx_chan(u32 ch_no, dma_addr_t addr, u32 rb_sz, aspeed_udma_cb_t cb, void *id, bool dis_tmout) { - return aspeed_udma_request_chan(ch_no, addr, rb, rb_sz, cb, id, + return aspeed_udma_request_chan(ch_no, addr, rb_sz, cb, id, dis_tmout, false); } EXPORT_SYMBOL(aspeed_udma_request_rx_chan); diff --git a/drivers/soc/aspeed/aspeed-usb-hp.c b/drivers/soc/aspeed/aspeed-usb-hp.c index dd34f27416fea0..c2e6f87d2313ac 100644 --- a/drivers/soc/aspeed/aspeed-usb-hp.c +++ b/drivers/soc/aspeed/aspeed-usb-hp.c @@ -27,12 +27,13 @@ static const struct of_device_id aspeed_usb_hp_dt_ids[] = { { .compatible = "aspeed,ast2700-usb3bhp", }, - { + { .compatible = "aspeed,ast2700-usb2ahp", }, { .compatible = "aspeed,ast2700-usb2bhp", }, + {} }; MODULE_DEVICE_TABLE(of, aspeed_usb_hp_dt_ids); @@ -50,7 +51,7 @@ static int aspeed_usb_hp_probe(struct platform_device *pdev) int rc = 0; if (of_device_is_compatible(pdev->dev.of_node, - "ast2600-usb2ahp")) { + "aspeed,ast2600-usb2ahp")) { dev_info(&pdev->dev, "Initialized AST2600 USB2AHP\n"); return 0; } @@ -151,4 +152,3 @@ module_platform_driver(aspeed_usb_hp_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Neal Liu "); - diff --git a/drivers/soc/aspeed/aspeed-usb-phy.c b/drivers/soc/aspeed/aspeed-usb-phy.c index 22f78e216a5977..7aa7b484bd035f 100644 --- a/drivers/soc/aspeed/aspeed-usb-phy.c +++ b/drivers/soc/aspeed/aspeed-usb-phy.c @@ -111,4 +111,3 @@ module_platform_driver(aspeed_usb_phy_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Neal Liu "); - diff --git a/drivers/soc/aspeed/aspeed-xdma.c b/drivers/soc/aspeed/aspeed-xdma.c index 579937ee374557..26ed27cf72d851 100644 --- a/drivers/soc/aspeed/aspeed-xdma.c +++ b/drivers/soc/aspeed/aspeed-xdma.c @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -33,12 +35,16 @@ #define SCU_AST2600_MISC_CTRL 0x0c0 #define SCU_AST2600_MISC_CTRL_XDMA_BMC BIT(8) +#define SCU_AST2700_MISC_CTRL_XDMA_CLIENT BIT(4) #define SCU_AST2600_DEBUG_CTRL 0x0c8 -#define DEBUG_CTRL_XDMA_DISABLE BIT(2) +#define DEBUG_CTRL_AST2600_XDMA_DISABLE BIT(2) +#define DEBUG_CTRL_AST2700_XDMA_DISABLE BIT(8) #define SCU_AST2500_PCIE_CONF 0x180 #define SCU_AST2600_PCIE_CONF 0xc20 +#define SCU_AST2700_PCIE0_CONF 0x970 +#define SCU_AST2700_PCIE1_CONF 0x9B0 #define SCU_PCIE_CONF_VGA_EN BIT(0) #define SCU_PCIE_CONF_VGA_EN_MMIO BIT(1) #define SCU_PCIE_CONF_VGA_EN_LPC BIT(2) @@ -53,9 +59,16 @@ #define SCU_PCIE_CONF_BMC_EN_IRQ BIT(13) #define SCU_PCIE_CONF_BMC_EN_DMA BIT(14) +#define SCU_AST2700_PCIE0_CTRL 0xa60 +#define SCU_AST2700_PCIE1_CTRL 0xae0 +#define SCU_AST2700_PCIE_CTRL_DMA_EN BIT(2) + #define SCU_AST2500_BMC_CLASS_REV 0x19c #define SCU_AST2600_BMC_CLASS_REV 0xc68 +#define SCU_AST2700_PCIE0_BMC_CLASS_REV 0xa18 +#define SCU_AST2700_PCIE1_BMC_CLASS_REV 0xa98 #define SCU_BMC_CLASS_REV_XDMA 0xff000001 +#define SCU_BMC_CLASS_REV_MASK 0xffffff00 #define XDMA_CMDQ_SIZE PAGE_SIZE #define XDMA_NUM_CMDS \ @@ -90,6 +103,16 @@ #define XDMA_CMD_AST2600_CMD_LINE_SIZE GENMASK_ULL(14, 0) #define XDMA_CMD_AST2600_CMD_MULTILINE_SIZE GENMASK_ULL(14, 12) +#define XDMA_CMD_AST2700_PITCH_BMC GENMASK_ULL(62, 48) +#define XDMA_CMD_AST2700_PITCH_HOST GENMASK_ULL(46, 32) +#define XDMA_CMD_AST2700_CMD_64_EN BIT_ULL(40) +#define XDMA_CMD_AST2700_CMD_IRQ_BMC BIT_ULL(37) +#define XDMA_CMD_AST2700_CMD_UPSTREAM BIT_ULL(32) +#define XDMA_CMD_AST2700_CMD_LINE_NO GENMASK_ULL(27, 16) +#define XDMA_CMD_AST2700_CMD_LINE_SIZE GENMASK_ULL(14, 0) +#define XDMA_CMD_AST2700_CMD_MULTILINE_SIZE GENMASK_ULL(14, 12) +#define XDMA_CMD_AST2700_BMC_ADDR GENMASK_ULL(34, 0) + #define XDMA_AST2500_QUEUE_ENTRY_SIZE 4 #define XDMA_AST2500_HOST_CMDQ_ADDR0 0x00 #define XDMA_AST2500_HOST_CMDQ_ENDP 0x04 @@ -164,6 +187,36 @@ #define XDMA_AST2600_INPRG_US_CMD20 0x70 #define XDMA_AST2600_INPRG_US_CMD21 0x74 +#define XDMA_AST2700_QUEUE_ENTRY_SIZE 2 +#define XDMA_AST2700_BMC_CMDQ_ADDR0 0x10 +#define XDMA_AST2700_BMC_CMDQ_ADDR1 0x14 +#define XDMA_AST2700_BMC_CMDQ_ENDP 0x18 +#define XDMA_AST2700_BMC_CMDQ_WRITEP 0x1c +#define XDMA_AST2700_BMC_CMDQ_READP 0x20 +#define XDMA_AST2700_CTRL 0x38 +#define XDMA_AST2700_CTRL_US_COMP BIT(16) +#define XDMA_AST2700_CTRL_DS_COMP BIT(17) +#define XDMA_AST2700_CTRL_DS_DIRTY BIT(18) +#define XDMA_AST2700_CTRL_IDLE BIT(19) +#define XDMA_AST2700_CTRL_DS_SIZE_256 BIT(20) +#define XDMA_AST2700_STATUS 0x3c +#define XDMA_AST2700_STATUS_US_COMP BIT(16) +#define XDMA_AST2700_STATUS_DS_COMP BIT(17) +#define XDMA_AST2700_STATUS_DS_DIRTY BIT(18) +#define XDMA_AST2700_STATUS_IDLE BIT(19) +#define XDMA_AST2700_INPRG_DS_CMD00 0x40 +#define XDMA_AST2700_INPRG_DS_CMD01 0x44 +#define XDMA_AST2700_INPRG_DS_CMD10 0x48 +#define XDMA_AST2700_INPRG_DS_CMD11 0x4c +#define XDMA_AST2700_INPRG_DS_CMD20 0x50 +#define XDMA_AST2700_INPRG_DS_CMD21 0x54 +#define XDMA_AST2700_INPRG_US_CMD00 0x60 +#define XDMA_AST2700_INPRG_US_CMD01 0x64 +#define XDMA_AST2700_INPRG_US_CMD10 0x68 +#define XDMA_AST2700_INPRG_US_CMD11 0x6c +#define XDMA_AST2700_INPRG_US_CMD20 0x70 +#define XDMA_AST2700_INPRG_US_CMD21 0x74 + struct aspeed_xdma_cmd { u64 host_addr; u64 pitch; @@ -173,6 +226,7 @@ struct aspeed_xdma_cmd { struct aspeed_xdma_regs { u8 bmc_cmdq_addr; + u8 bmc_cmdq_addr_ext; u8 bmc_cmdq_endp; u8 bmc_cmdq_writep; u8 bmc_cmdq_readp; @@ -193,12 +247,13 @@ struct aspeed_xdma_chip { u32 scu_bmc_class; u32 scu_misc_ctrl; u32 scu_pcie_conf; + u32 scu_pcie_ctrl; unsigned int queue_entry_size; struct aspeed_xdma_regs regs; struct aspeed_xdma_status_bits status_bits; unsigned int (*set_cmd)(struct aspeed_xdma *ctx, struct aspeed_xdma_cmd cmds[2], - struct aspeed_xdma_op *op, u32 bmc_addr); + struct aspeed_xdma_op *op, u64 bmc_addr); }; struct aspeed_xdma_client; @@ -233,8 +288,8 @@ struct aspeed_xdma { struct work_struct reset_work; - u32 mem_phys; - u32 mem_size; + phys_addr_t mem_phys; + phys_addr_t mem_size; void *mem_virt; dma_addr_t mem_coherent; dma_addr_t cmdq_phys; @@ -253,6 +308,15 @@ struct aspeed_xdma_client { u32 size; }; +/* Kernel client structure for async transfers */ +struct aspeed_xdma_kernel_client { + struct aspeed_xdma_client client; + void (*callback)(void *data, bool error); + void *callback_data; + struct completion done; + bool error; +}; + #define CREATE_TRACE_POINTS #include @@ -282,6 +346,10 @@ static void aspeed_xdma_init_eng(struct aspeed_xdma *ctx) aspeed_xdma_writel(ctx, ctx->chip->regs.bmc_cmdq_writep, 0); aspeed_xdma_writel(ctx, ctx->chip->regs.control, ctx->chip->control); aspeed_xdma_writel(ctx, ctx->chip->regs.bmc_cmdq_addr, ctx->cmdq_phys); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (ctx->chip->regs.bmc_cmdq_addr_ext) + aspeed_xdma_writel(ctx, ctx->chip->regs.bmc_cmdq_addr_ext, ctx->cmdq_phys >> 32); +#endif ctx->cmd_idx = 0; spin_unlock_irqrestore(&ctx->engine_lock, flags); @@ -290,7 +358,7 @@ static void aspeed_xdma_init_eng(struct aspeed_xdma *ctx) static unsigned int aspeed_xdma_ast2500_set_cmd(struct aspeed_xdma *ctx, struct aspeed_xdma_cmd cmds[2], struct aspeed_xdma_op *op, - u32 bmc_addr) + u64 bmc_addr) { unsigned int rc = 1; unsigned int pitch = 1; @@ -302,7 +370,7 @@ static unsigned int aspeed_xdma_ast2500_set_cmd(struct aspeed_xdma *ctx, u64 cmd_pitch = (op->direction ? XDMA_CMD_AST2500_PITCH_UPSTREAM : 0) | XDMA_CMD_AST2500_PITCH_ID; - dev_dbg(ctx->dev, "xdma %s ast2500: bmc[%08x] len[%08x] host[%08x]\n", + dev_dbg(ctx->dev, "xdma %s ast2500: bmc[%08llx] len[%08x] host[%08x]\n", op->direction ? "upstream" : "downstream", bmc_addr, op->len, (u32)op->host_addr); @@ -345,7 +413,7 @@ static unsigned int aspeed_xdma_ast2500_set_cmd(struct aspeed_xdma *ctx, cmds[0].host_addr = op->host_addr; cmds[0].pitch = cmd_pitch | - ((u64)bmc_addr & XDMA_CMD_AST2500_PITCH_ADDR) | + (bmc_addr & XDMA_CMD_AST2500_PITCH_ADDR) | FIELD_PREP(XDMA_CMD_AST2500_PITCH_HOST, pitch) | FIELD_PREP(XDMA_CMD_AST2500_PITCH_BMC, pitch); cmds[0].cmd = cmd | FIELD_PREP(XDMA_CMD_AST2500_CMD_LINE_NO, line_no) | @@ -361,7 +429,7 @@ static unsigned int aspeed_xdma_ast2500_set_cmd(struct aspeed_xdma *ctx, static unsigned int aspeed_xdma_ast2600_set_cmd(struct aspeed_xdma *ctx, struct aspeed_xdma_cmd cmds[2], struct aspeed_xdma_op *op, - u32 bmc_addr) + u64 bmc_addr) { unsigned int rc = 1; unsigned int pitch = 1; @@ -374,11 +442,11 @@ static unsigned int aspeed_xdma_ast2600_set_cmd(struct aspeed_xdma *ctx, (op->host_addr + (u64)op->len) & 0xffffffff00000000ULL) cmd |= XDMA_CMD_AST2600_CMD_64_EN; - dev_dbg(ctx->dev, "xdma %s ast2600: bmc[%08x] len[%08x] " + dev_dbg(ctx->dev, "xdma %s ast2600: bmc[%08llx] len[%08x] " "host[%016llx]\n", op->direction ? "upstream" : "downstream", bmc_addr, op->len, op->host_addr); - if (op->len > XDMA_CMD_AST2600_CMD_LINE_SIZE) { + if ((op->host_addr & 0xff) + op->len > XDMA_CMD_AST2600_CMD_LINE_SIZE) { unsigned int rem; unsigned int total; @@ -413,7 +481,7 @@ static unsigned int aspeed_xdma_ast2600_set_cmd(struct aspeed_xdma *ctx, } cmds[0].host_addr = op->host_addr; - cmds[0].pitch = ((u64)bmc_addr & XDMA_CMD_AST2600_PITCH_ADDR) | + cmds[0].pitch = (bmc_addr & XDMA_CMD_AST2600_PITCH_ADDR) | FIELD_PREP(XDMA_CMD_AST2600_PITCH_HOST, pitch) | FIELD_PREP(XDMA_CMD_AST2600_PITCH_BMC, pitch); cmds[0].cmd = cmd | FIELD_PREP(XDMA_CMD_AST2600_CMD_LINE_NO, line_no) | @@ -426,6 +494,73 @@ static unsigned int aspeed_xdma_ast2600_set_cmd(struct aspeed_xdma *ctx, return rc; } +static unsigned int aspeed_xdma_ast2700_set_cmd(struct aspeed_xdma *ctx, + struct aspeed_xdma_cmd cmds[2], + struct aspeed_xdma_op *op, + u64 bmc_addr) +{ + unsigned int rc = 1; + unsigned int pitch = 1; + unsigned int line_no = 1; + unsigned int line_size = op->len; + u64 cmd = XDMA_CMD_AST2700_CMD_IRQ_BMC | + (op->direction ? XDMA_CMD_AST2700_CMD_UPSTREAM : 0); + + if (op->host_addr & 0xffffffff00000000ULL || + (op->host_addr + (u64)op->len) & 0xffffffff00000000ULL) + cmd |= XDMA_CMD_AST2700_CMD_64_EN; + + dev_dbg(ctx->dev, "xdma %s ast2700: bmc[%08llx] len[%08x] host[%016llx]\n", + op->direction ? "upstream" : "downstream", + bmc_addr, op->len, op->host_addr); + + if (op->len > XDMA_CMD_AST2700_CMD_LINE_SIZE) { + unsigned int rem; + unsigned int total; + + line_no = op->len / XDMA_CMD_AST2700_CMD_MULTILINE_SIZE; + total = XDMA_CMD_AST2700_CMD_MULTILINE_SIZE * line_no; + rem = op->len - total; + line_size = XDMA_CMD_AST2700_CMD_MULTILINE_SIZE; + pitch = line_size; + + if (rem) { + // TODO: why +total? + u64 rbmc = bmc_addr + total; + + cmds[1].host_addr = op->host_addr + (u64)total; + cmds[1].pitch = + FIELD_PREP(XDMA_CMD_AST2700_PITCH_HOST, 1) | + FIELD_PREP(XDMA_CMD_AST2700_PITCH_BMC, 1); + cmds[1].cmd = cmd | + FIELD_PREP(XDMA_CMD_AST2700_CMD_LINE_NO, 1) | + FIELD_PREP(XDMA_CMD_AST2700_CMD_LINE_SIZE, + rem); + cmds[1].reserved = rbmc & XDMA_CMD_AST2700_BMC_ADDR; + + print_hex_dump_debug("xdma rem ", DUMP_PREFIX_OFFSET, + 16, 1, &cmds[1], sizeof(*cmds), + true); + + cmd &= ~XDMA_CMD_AST2700_CMD_IRQ_BMC; + + rc++; + } + } + cmds[0].host_addr = op->host_addr; + cmds[0].pitch = + FIELD_PREP(XDMA_CMD_AST2700_PITCH_HOST, pitch) | + FIELD_PREP(XDMA_CMD_AST2700_PITCH_BMC, pitch); + cmds[0].cmd = cmd | FIELD_PREP(XDMA_CMD_AST2700_CMD_LINE_NO, line_no) | + FIELD_PREP(XDMA_CMD_AST2700_CMD_LINE_SIZE, line_size); + cmds[0].reserved = bmc_addr & XDMA_CMD_AST2700_BMC_ADDR; + + print_hex_dump_debug("xdma cmd ", DUMP_PREFIX_OFFSET, 16, 1, cmds, + sizeof(*cmds), true); + + return rc; +} + static int aspeed_xdma_start(struct aspeed_xdma *ctx, unsigned int num_cmds, struct aspeed_xdma_cmd cmds[2], bool upstream, struct aspeed_xdma_client *client) @@ -474,11 +609,13 @@ static int aspeed_xdma_start(struct aspeed_xdma *ctx, unsigned int num_cmds, static void aspeed_xdma_done(struct aspeed_xdma *ctx, bool error) { unsigned long flags; + struct aspeed_xdma_client *client; spin_lock_irqsave(&ctx->client_lock, flags); - if (ctx->current_client) { - ctx->current_client->error = error; - ctx->current_client->in_progress = false; + client = ctx->current_client; + if (client) { + client->error = error; + client->in_progress = false; ctx->current_client = NULL; } spin_unlock_irqrestore(&ctx->client_lock, flags); @@ -580,6 +717,9 @@ static ssize_t aspeed_xdma_write(struct file *file, const char __user *buf, if (len != sizeof(op)) return -EINVAL; + if (READ_ONCE(client->in_progress)) + return -EBUSY; + if (copy_from_user(&op, buf, len)) return -EFAULT; @@ -645,6 +785,9 @@ static __poll_t aspeed_xdma_poll(struct file *file, mask |= EPOLLOUT | EPOLLWRNORM; } + if (mask) + aspeed_xdma_reset(ctx); + return mask; } @@ -729,8 +872,8 @@ static int aspeed_xdma_mmap(struct file *file, struct vm_area_struct *vma) rc = io_remap_pfn_range(vma, vma->vm_start, client->phys >> PAGE_SHIFT, client->size, vma->vm_page_prot); if (rc) { - dev_warn(ctx->dev, "mmap err: v[%08lx] to p[%08x], s[%08x]\n", - vma->vm_start, (u32)client->phys, client->size); + dev_warn(ctx->dev, "mmap err: v[%08lx] to p[%pa], s[%08x]\n", + vma->vm_start, &client->phys, client->size); gen_pool_free(ctx->pool, (unsigned long)client->virt, client->size); @@ -743,8 +886,8 @@ static int aspeed_xdma_mmap(struct file *file, struct vm_area_struct *vma) } trace_xdma_mmap(client); - dev_dbg(ctx->dev, "mmap: v[%08lx] to p[%08x], s[%08x]\n", - vma->vm_start, (u32)client->phys, client->size); + dev_dbg(ctx->dev, "mmap: v[%08lx] to p[%pa], s[%08x]\n", + vma->vm_start, &client->phys, client->size); return 0; } @@ -774,10 +917,11 @@ static int aspeed_xdma_release(struct inode *inode, struct file *file) spin_lock_irqsave(&ctx->client_lock, flags); if (client == ctx->current_client) { + /* Clear current_client first to prevent use-after-free */ + ctx->current_client = NULL; + spin_lock(&ctx->engine_lock); - if (ctx->in_reset) { - ctx->current_client = NULL; - } else { + if (!ctx->in_reset) { ctx->in_reset = true; reset = true; } @@ -785,8 +929,11 @@ static int aspeed_xdma_release(struct inode *inode, struct file *file) } spin_unlock_irqrestore(&ctx->client_lock, flags); - if (reset) + if (reset) { + /* Wait for any pending reset work to complete before freeing client */ + flush_work(&ctx->reset_work); aspeed_xdma_reset(ctx); + } if (client->virt) { gen_pool_free(ctx->pool, (unsigned long)client->virt, @@ -839,8 +986,9 @@ static int aspeed_xdma_init_scu(struct aspeed_xdma *ctx, struct device *dev) if (pcie_device_bmc) { selection = bmc; - regmap_write(scu, ctx->chip->scu_bmc_class, - SCU_BMC_CLASS_REV_XDMA); + regmap_update_bits(scu, ctx->chip->scu_bmc_class, + SCU_BMC_CLASS_REV_MASK, + SCU_BMC_CLASS_REV_XDMA); } else { selection = vga; } @@ -849,13 +997,25 @@ static int aspeed_xdma_init_scu(struct aspeed_xdma *ctx, struct device *dev) selection); if (ctx->chip->scu_misc_ctrl) { + u32 mask = (ctx->chip->regs.bmc_cmdq_addr_ext) + ? SCU_AST2700_MISC_CTRL_XDMA_CLIENT + : SCU_AST2600_MISC_CTRL_XDMA_BMC; + u32 disable = DEBUG_CTRL_AST2600_XDMA_DISABLE; + + if (ctx->chip->regs.bmc_cmdq_addr_ext) + disable |= DEBUG_CTRL_AST2700_XDMA_DISABLE; + regmap_update_bits(scu, ctx->chip->scu_misc_ctrl, - SCU_AST2600_MISC_CTRL_XDMA_BMC, - SCU_AST2600_MISC_CTRL_XDMA_BMC); + mask, mask); - /* Allow XDMA to be used on AST2600 */ regmap_update_bits(scu, SCU_AST2600_DEBUG_CTRL, - DEBUG_CTRL_XDMA_DISABLE, 0); + disable, 0); + } + + if (ctx->chip->scu_pcie_ctrl) { + regmap_update_bits(scu, ctx->chip->scu_pcie_ctrl, + SCU_AST2700_PCIE_CTRL_DMA_EN, + SCU_AST2700_PCIE_CTRL_DMA_EN); } } else { dev_warn(dev, "Unable to configure PCIe: %ld; continuing.\n", @@ -924,12 +1084,13 @@ static int aspeed_xdma_iomap(struct aspeed_xdma *ctx, static int aspeed_xdma_probe(struct platform_device *pdev) { - int rc; + int rc, id; struct aspeed_xdma *ctx; struct reserved_mem *mem; struct device *dev = &pdev->dev; struct device_node *memory_region; const void *md = of_device_get_match_data(dev); + bool rc_f; if (!md) return -ENODEV; @@ -946,6 +1107,8 @@ static int aspeed_xdma_probe(struct platform_device *pdev) INIT_WORK(&ctx->reset_work, aspeed_xdma_reset_work); init_waitqueue_head(&ctx->wait); + rc_f = of_find_property(dev->of_node, "pcie_rc", NULL) ? 1 : 0; + rc = aspeed_xdma_iomap(ctx, pdev); if (rc) { dev_err(dev, "Failed to map registers.\n"); @@ -959,7 +1122,7 @@ static int aspeed_xdma_probe(struct platform_device *pdev) goto err_noirq; } - rc = request_irq(ctx->irq, aspeed_xdma_irq, 0, DEVICE_NAME, ctx); + rc = request_irq(ctx->irq, aspeed_xdma_irq, 0, dev_name(dev), ctx); if (rc < 0) { dev_err(dev, "Failed to request IRQ %d.\n", ctx->irq); goto err_noirq; @@ -979,10 +1142,12 @@ static int aspeed_xdma_probe(struct platform_device *pdev) goto err_noreset; } - ctx->reset_rc = reset_control_get_exclusive(dev, "root-complex"); - if (IS_ERR(ctx->reset_rc)) { - dev_dbg(dev, "Failed to request reset RC control.\n"); - ctx->reset_rc = NULL; + if (rc_f) { + ctx->reset_rc = reset_control_get_exclusive(dev, "root-complex"); + if (IS_ERR(ctx->reset_rc)) { + dev_dbg(dev, "Failed to request reset RC control.\n"); + ctx->reset_rc = NULL; + } } memory_region = of_parse_phandle(dev->of_node, "memory-region", 0); @@ -1075,9 +1240,13 @@ static int aspeed_xdma_probe(struct platform_device *pdev) aspeed_xdma_init_eng(ctx); + id = of_alias_get_id(dev->of_node, "xdma"); + if (id < 0) + id = 0; + ctx->misc.minor = MISC_DYNAMIC_MINOR; ctx->misc.fops = &aspeed_xdma_fops; - ctx->misc.name = "aspeed-xdma"; + ctx->misc.name = kasprintf(GFP_KERNEL, "%s%d", DEVICE_NAME, id); ctx->misc.parent = dev; rc = misc_register(&ctx->misc); if (rc) { @@ -1094,7 +1263,7 @@ static int aspeed_xdma_probe(struct platform_device *pdev) dev_warn(dev, "Failed to find PCI-E IRQ.\n"); } else { rc = request_irq(ctx->pcie_irq, aspeed_xdma_pcie_irq, - IRQF_SHARED, DEVICE_NAME, ctx); + IRQF_SHARED, dev_name(dev), ctx); if (rc < 0) { dev_warn(dev, "Failed to request PCI-E IRQ %d.\n", rc); ctx->pcie_irq = -1; @@ -1158,9 +1327,11 @@ static const struct aspeed_xdma_chip aspeed_ast2500_xdma_chip = { .scu_bmc_class = SCU_AST2500_BMC_CLASS_REV, .scu_misc_ctrl = 0, .scu_pcie_conf = SCU_AST2500_PCIE_CONF, + .scu_pcie_ctrl = 0, .queue_entry_size = XDMA_AST2500_QUEUE_ENTRY_SIZE, .regs = { .bmc_cmdq_addr = XDMA_AST2500_BMC_CMDQ_ADDR, + .bmc_cmdq_addr_ext = 0, .bmc_cmdq_endp = XDMA_AST2500_BMC_CMDQ_ENDP, .bmc_cmdq_writep = XDMA_AST2500_BMC_CMDQ_WRITEP, .bmc_cmdq_readp = XDMA_AST2500_BMC_CMDQ_READP, @@ -1181,9 +1352,11 @@ static const struct aspeed_xdma_chip aspeed_ast2600_xdma_chip = { .scu_bmc_class = SCU_AST2600_BMC_CLASS_REV, .scu_misc_ctrl = SCU_AST2600_MISC_CTRL, .scu_pcie_conf = SCU_AST2600_PCIE_CONF, + .scu_pcie_ctrl = 0, .queue_entry_size = XDMA_AST2600_QUEUE_ENTRY_SIZE, .regs = { .bmc_cmdq_addr = XDMA_AST2600_BMC_CMDQ_ADDR, + .bmc_cmdq_addr_ext = 0, .bmc_cmdq_endp = XDMA_AST2600_BMC_CMDQ_ENDP, .bmc_cmdq_writep = XDMA_AST2600_BMC_CMDQ_WRITEP, .bmc_cmdq_readp = XDMA_AST2600_BMC_CMDQ_READP, @@ -1198,6 +1371,56 @@ static const struct aspeed_xdma_chip aspeed_ast2600_xdma_chip = { .set_cmd = aspeed_xdma_ast2600_set_cmd, }; +static const struct aspeed_xdma_chip aspeed_ast2700_xdma0_chip = { + .control = XDMA_AST2700_CTRL_US_COMP | XDMA_AST2700_CTRL_DS_COMP | + XDMA_AST2700_CTRL_DS_DIRTY, + .scu_bmc_class = SCU_AST2700_PCIE0_BMC_CLASS_REV, + .scu_misc_ctrl = SCU_AST2600_MISC_CTRL, + .scu_pcie_conf = SCU_AST2700_PCIE0_CONF, + .scu_pcie_ctrl = SCU_AST2700_PCIE0_CTRL, + .queue_entry_size = XDMA_AST2700_QUEUE_ENTRY_SIZE, + .regs = { + .bmc_cmdq_addr = XDMA_AST2700_BMC_CMDQ_ADDR0, + .bmc_cmdq_addr_ext = XDMA_AST2700_BMC_CMDQ_ADDR1, + .bmc_cmdq_endp = XDMA_AST2700_BMC_CMDQ_ENDP, + .bmc_cmdq_writep = XDMA_AST2700_BMC_CMDQ_WRITEP, + .bmc_cmdq_readp = XDMA_AST2700_BMC_CMDQ_READP, + .control = XDMA_AST2700_CTRL, + .status = XDMA_AST2700_STATUS, + }, + .status_bits = { + .us_comp = XDMA_AST2700_STATUS_US_COMP, + .ds_comp = XDMA_AST2700_STATUS_DS_COMP, + .ds_dirty = XDMA_AST2700_STATUS_DS_DIRTY, + }, + .set_cmd = aspeed_xdma_ast2700_set_cmd, +}; + +static const struct aspeed_xdma_chip aspeed_ast2700_xdma1_chip = { + .control = XDMA_AST2700_CTRL_US_COMP | XDMA_AST2700_CTRL_DS_COMP | + XDMA_AST2700_CTRL_DS_DIRTY, + .scu_bmc_class = SCU_AST2700_PCIE1_BMC_CLASS_REV, + .scu_misc_ctrl = SCU_AST2600_MISC_CTRL, + .scu_pcie_conf = SCU_AST2700_PCIE1_CONF, + .scu_pcie_ctrl = SCU_AST2700_PCIE1_CTRL, + .queue_entry_size = XDMA_AST2700_QUEUE_ENTRY_SIZE, + .regs = { + .bmc_cmdq_addr = XDMA_AST2700_BMC_CMDQ_ADDR0, + .bmc_cmdq_addr_ext = XDMA_AST2700_BMC_CMDQ_ADDR1, + .bmc_cmdq_endp = XDMA_AST2700_BMC_CMDQ_ENDP, + .bmc_cmdq_writep = XDMA_AST2700_BMC_CMDQ_WRITEP, + .bmc_cmdq_readp = XDMA_AST2700_BMC_CMDQ_READP, + .control = XDMA_AST2700_CTRL, + .status = XDMA_AST2700_STATUS, + }, + .status_bits = { + .us_comp = XDMA_AST2700_STATUS_US_COMP, + .ds_comp = XDMA_AST2700_STATUS_DS_COMP, + .ds_dirty = XDMA_AST2700_STATUS_DS_DIRTY, + }, + .set_cmd = aspeed_xdma_ast2700_set_cmd, +}; + static const struct of_device_id aspeed_xdma_match[] = { { .compatible = "aspeed,ast2500-xdma", @@ -1207,9 +1430,202 @@ static const struct of_device_id aspeed_xdma_match[] = { .compatible = "aspeed,ast2600-xdma", .data = &aspeed_ast2600_xdma_chip, }, + { + .compatible = "aspeed,ast2700-xdma0", + .data = &aspeed_ast2700_xdma0_chip, + }, + { + .compatible = "aspeed,ast2700-xdma1", + .data = &aspeed_ast2700_xdma1_chip, + }, { }, }; +/** + * aspeed_xdma_get - Get a reference to an ASPEED XDMA engine + * @dev: Device requesting the XDMA engine + * + * Looks up the XDMA device via device tree "aspeed,xdma" property + * and returns a reference to it. + */ +struct aspeed_xdma *aspeed_xdma_get(struct device *dev) +{ + struct device_node *xdma_node; + struct platform_device *xdma_pdev; + struct aspeed_xdma *ctx; + + xdma_node = of_parse_phandle(dev->of_node, "aspeed,xdma", 0); + if (!xdma_node) + return ERR_PTR(-ENODEV); + + xdma_pdev = of_find_device_by_node(xdma_node); + of_node_put(xdma_node); + if (!xdma_pdev) + return ERR_PTR(-EPROBE_DEFER); + + ctx = platform_get_drvdata(xdma_pdev); + if (!ctx) { + platform_device_put(xdma_pdev); + return ERR_PTR(-EPROBE_DEFER); + } + + kobject_get(&ctx->kobj); + return ctx; +} +EXPORT_SYMBOL_GPL(aspeed_xdma_get); + +/** + * aspeed_xdma_put - Release a reference to an ASPEED XDMA engine + * @ctx: XDMA context + */ +void aspeed_xdma_put(struct aspeed_xdma *ctx) +{ + if (ctx) + kobject_put(&ctx->kobj); +} +EXPORT_SYMBOL_GPL(aspeed_xdma_put); + +/** + * aspeed_xdma_alloc_coherent - Allocate DMA-capable memory + * @ctx: XDMA context + * @size: Size of memory to allocate + * @dma_handle: Output parameter for DMA address + */ +void *aspeed_xdma_alloc_coherent(struct aspeed_xdma *ctx, size_t size, + dma_addr_t *dma_handle) +{ + void *virt; + + if (!ctx || !dma_handle) + return NULL; + + virt = gen_pool_dma_alloc(ctx->pool, size, dma_handle); + if (virt) + dev_dbg(ctx->dev, "Allocated %zu bytes at virt=%p dma=%pad\n", + size, virt, dma_handle); + + return virt; +} +EXPORT_SYMBOL_GPL(aspeed_xdma_alloc_coherent); + +/** + * aspeed_xdma_free_coherent - Free DMA-capable memory + * @ctx: XDMA context + * @size: Size of memory to free + * @vaddr: Virtual address + * @dma_handle: DMA address + */ +void aspeed_xdma_free_coherent(struct aspeed_xdma *ctx, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + if (!ctx || !vaddr) + return; + + dev_dbg(ctx->dev, "Freeing %zu bytes at virt=%p dma=%pad\n", + size, vaddr, &dma_handle); + gen_pool_free(ctx->pool, (unsigned long)vaddr, size); +} +EXPORT_SYMBOL_GPL(aspeed_xdma_free_coherent); + +/** + * aspeed_xdma_transfer - Perform an asynchronous DMA transfer + * @ctx: XDMA context + * @bmc_addr: Physical address on BMC side + * @host_addr: Physical address on host side + * @len: Length of transfer + * @upstream: Transfer direction (true = BMC->host, false = host->BMC) + * @callback: Completion callback + * @callback_data: Data to pass to callback + */ +int aspeed_xdma_transfer(struct aspeed_xdma *ctx, dma_addr_t bmc_addr, + u64 host_addr, u32 len, bool upstream, + void (*callback)(void *data, bool error), + void *callback_data) +{ + struct aspeed_xdma_kernel_client *kclient; + struct aspeed_xdma_op op; + struct aspeed_xdma_cmd cmds[2]; + unsigned int num_cmds; + int rc; + + if (!ctx || !callback) + return -EINVAL; + + kclient = kzalloc(sizeof(*kclient), GFP_KERNEL); + if (!kclient) + return -ENOMEM; + + kclient->client.ctx = ctx; + kclient->client.phys = bmc_addr; + kclient->client.size = len; + kclient->callback = callback; + kclient->callback_data = callback_data; + + op.host_addr = host_addr; + op.len = len; + op.direction = upstream ? ASPEED_XDMA_DIRECTION_UPSTREAM : + ASPEED_XDMA_DIRECTION_DOWNSTREAM; + + num_cmds = ctx->chip->set_cmd(ctx, cmds, &op, bmc_addr); + + rc = aspeed_xdma_start(ctx, num_cmds, cmds, upstream, + &kclient->client); + if (rc) { + kfree(kclient); + return rc; + } + + return 0; +} +EXPORT_SYMBOL_GPL(aspeed_xdma_transfer); + +/** + * aspeed_xdma_transfer_sync - Perform a synchronous DMA transfer + * @ctx: XDMA context + * @bmc_addr: Physical address on BMC side + * @host_addr: Physical address on host side + * @len: Length of transfer + * @upstream: Transfer direction (true = BMC->host, false = host->BMC) + */ +int aspeed_xdma_transfer_sync(struct aspeed_xdma *ctx, dma_addr_t bmc_addr, + u64 host_addr, u32 len, bool upstream) +{ + struct aspeed_xdma_kernel_client kclient; + struct aspeed_xdma_op op; + struct aspeed_xdma_cmd cmds[2]; + unsigned int num_cmds; + int rc; + + if (!ctx) + return -EINVAL; + + memset(&kclient, 0, sizeof(kclient)); + kclient.client.ctx = ctx; + kclient.client.phys = bmc_addr; + kclient.client.size = len; + kclient.callback = NULL; + + op.host_addr = host_addr; + op.len = len; + op.direction = upstream ? ASPEED_XDMA_DIRECTION_UPSTREAM : + ASPEED_XDMA_DIRECTION_DOWNSTREAM; + + num_cmds = ctx->chip->set_cmd(ctx, cmds, &op, bmc_addr); + + rc = aspeed_xdma_start(ctx, num_cmds, cmds, upstream, + &kclient.client); + if (rc) + return rc; + + /* Wait for transfer to complete using the wait queue */ + rc = wait_event_interruptible(ctx->wait, !kclient.client.in_progress); + if (rc) + return -EINTR; + + return kclient.client.error ? -EIO : 0; +} +EXPORT_SYMBOL_GPL(aspeed_xdma_transfer_sync); + static struct platform_driver aspeed_xdma_driver = { .probe = aspeed_xdma_probe, .remove = aspeed_xdma_remove, diff --git a/drivers/soc/aspeed/ast2700-espi.c b/drivers/soc/aspeed/ast2700-espi.c index f9715b4a581917..7bb4348ac7901a 100644 --- a/drivers/soc/aspeed/ast2700-espi.c +++ b/drivers/soc/aspeed/ast2700-espi.c @@ -10,15 +10,18 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include #include +#include #include "ast2700-espi.h" @@ -79,6 +82,7 @@ struct ast2700_espi_perif { dma_addr_t pc_rx_addr; } dma; + bool rtc_enable; bool rx_ready; wait_queue_head_t wq; @@ -650,6 +654,33 @@ static void ast2700_espi_perif_isr(struct ast2700_espi *espi) } } +static void ast2700_espi_perif_sw_reset(struct ast2700_espi *espi) +{ + struct device *dev; + uint32_t reg; + + dev = espi->dev; + + reg = readl(espi->regs + ESPI_CH0_CTRL); + reg &= ~(ESPI_CH0_CTRL_NP_TX_RST + | ESPI_CH0_CTRL_NP_RX_RST + | ESPI_CH0_CTRL_PC_TX_RST + | ESPI_CH0_CTRL_PC_RX_RST + | ESPI_CH0_CTRL_NP_TX_DMA_EN + | ESPI_CH0_CTRL_PC_TX_DMA_EN + | ESPI_CH0_CTRL_PC_RX_DMA_EN + | ESPI_CH0_CTRL_SW_RDY); + writel(reg, espi->regs + ESPI_CH0_CTRL); + + udelay(1); + + reg |= (ESPI_CH0_CTRL_NP_TX_RST + | ESPI_CH0_CTRL_NP_RX_RST + | ESPI_CH0_CTRL_PC_TX_RST + | ESPI_CH0_CTRL_PC_RX_RST); + writel(reg, espi->regs + ESPI_CH0_CTRL); +} + static void ast2700_espi_perif_reset(struct ast2700_espi *espi) { struct ast2700_espi_perif *perif; @@ -681,24 +712,12 @@ static void ast2700_espi_perif_reset(struct ast2700_espi *espi) reg = readl(espi->regs + ESPI_CH0_CTRL); reg |= (ESPI_CH0_CTRL_MCYC_RD_DIS | ESPI_CH0_CTRL_MCYC_WR_DIS); - reg &= ~(ESPI_CH0_CTRL_NP_TX_RST - | ESPI_CH0_CTRL_NP_RX_RST - | ESPI_CH0_CTRL_PC_TX_RST - | ESPI_CH0_CTRL_PC_RX_RST - | ESPI_CH0_CTRL_NP_TX_DMA_EN + reg &= ~(ESPI_CH0_CTRL_NP_TX_DMA_EN | ESPI_CH0_CTRL_PC_TX_DMA_EN | ESPI_CH0_CTRL_PC_RX_DMA_EN | ESPI_CH0_CTRL_SW_RDY); writel(reg, espi->regs + ESPI_CH0_CTRL); - udelay(1); - - reg |= (ESPI_CH0_CTRL_NP_TX_RST - | ESPI_CH0_CTRL_NP_RX_RST - | ESPI_CH0_CTRL_PC_TX_RST - | ESPI_CH0_CTRL_PC_RX_RST); - writel(reg, espi->regs + ESPI_CH0_CTRL); - if (perif->mmbi.enable) { reg = readl(espi->regs + ESPI_MMBI_CTRL); reg &= ~ESPI_MMBI_CTRL_EN; @@ -757,6 +776,11 @@ static void ast2700_espi_perif_reset(struct ast2700_espi *espi) | ESPI_CH0_CTRL_PC_RX_DMA_EN; writel(reg, espi->regs + ESPI_CH0_CTRL); } + if (perif->rtc_enable) { + reg = readl(espi->regs + ESPI_CAP_GEN) + | ESPI_CAP_GEN_RTC_SUP; + writel(reg, espi->regs + ESPI_CAP_GEN); + } writel(ESPI_CH0_INT_EN_PC_RX_CMPLT, espi->regs + ESPI_CH0_INT_EN); @@ -886,6 +910,16 @@ static int ast2700_espi_perif_probe(struct ast2700_espi *espi) return -EINVAL; } + np = of_parse_phandle(dev->of_node, "memory-region", 0); + if (np) { + of_reserved_mem_device_init(dev); + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (rc) { + dev_err(dev, "Failed to mask DMA.\n"); + return -ENODEV; + } + } + perif->mcyc.virt = dmam_alloc_coherent(dev, perif->mcyc.size, &perif->mcyc.taddr, GFP_KERNEL); if (!perif->mcyc.virt) { @@ -917,6 +951,7 @@ static int ast2700_espi_perif_probe(struct ast2700_espi *espi) return -ENOMEM; } } + perif->rtc_enable = of_property_read_bool(dev->of_node, "perif-rtc-enable"); perif->mdev.parent = dev; perif->mdev.minor = MISC_DYNAMIC_MINOR; @@ -1014,24 +1049,57 @@ static long ast2700_espi_vw_ioctl(struct file *fp, unsigned int cmd, unsigned lo { struct ast2700_espi_vw *vw; struct ast2700_espi *espi; - uint64_t gpio; + uint32_t gpio0, gpio1; + uint32_t hw_mode; vw = container_of(fp->private_data, struct ast2700_espi_vw, mdev); espi = container_of(vw, struct ast2700_espi, vw); - gpio = ((uint64_t)vw->gpio.val1 << 32) | vw->gpio.val0; + gpio0 = vw->gpio.val0; + gpio1 = vw->gpio.val1; + hw_mode = vw->gpio.hw_mode; + + if (hw_mode) { + dev_err(espi->dev, "HW mode: vGPIO reflect on physical GPIO. Get state from GPIO driver.\n"); + return -EFAULT; + } switch (cmd) { case ASPEED_ESPI_VW_GET_GPIO_VAL: - if (put_user(gpio, (uint64_t __user *)arg)) + if (put_user(gpio0, (uint32_t __user *)arg)) { + dev_err(espi->dev, "failed to get vGPIO value0\n"); return -EFAULT; + } + + dev_info(espi->dev, "Get vGPIO value0: 0x%x\n", gpio0); break; case ASPEED_ESPI_VW_PUT_GPIO_VAL: - if (get_user(gpio, (uint64_t __user *)arg)) + if (get_user(gpio0, (uint32_t __user *)arg)) { + dev_err(espi->dev, "failed to put vGPIO value0\n"); return -EFAULT; + } - writel(gpio >> 32, espi->regs + ESPI_CH1_GPIO_VAL1); - writel(gpio & 0xffffffff, espi->regs + ESPI_CH1_GPIO_VAL0); + dev_info(espi->dev, "Put vGPIO value0: 0x%x\n", gpio0); + writel(gpio0, espi->regs + ESPI_CH1_GPIO_VAL0); + break; + + case ASPEED_ESPI_VW_GET_GPIO_VAL1: + if (put_user(gpio1, (uint32_t __user *)arg)) { + dev_err(espi->dev, "failed to get vGPIO value1\n"); + return -EFAULT; + } + + dev_info(espi->dev, "Get vGPIO value1: 0x%x\n", gpio1); + break; + + case ASPEED_ESPI_VW_PUT_GPIO_VAL1: + if (get_user(gpio1, (uint32_t __user *)arg)) { + dev_err(espi->dev, "failed to put vGPIO value1\n"); + return -EFAULT; + } + + dev_info(espi->dev, "Put vGPIO value1: 0x%x\n", gpio1); + writel(gpio1, espi->regs + ESPI_CH1_GPIO_VAL1); break; default: @@ -1922,7 +1990,10 @@ static void ast2700_espi_flash_reset(struct ast2700_espi *espi) static int ast2700_espi_flash_probe(struct ast2700_espi *espi) { struct ast2700_espi_flash *flash; + struct device_node *np; + struct resource res; struct device *dev; + void *virt; int rc; dev = espi->dev; @@ -1939,17 +2010,25 @@ static int ast2700_espi_flash_probe(struct ast2700_espi *espi) flash->edaf.mode = EDAF_MODE_HW; of_property_read_u32(dev->of_node, "flash-edaf-mode", &flash->edaf.mode); + dev_info(dev, "eDAF mode: 0x%x\n", flash->edaf.mode); if (flash->edaf.mode == EDAF_MODE_MIX) { - rc = of_property_read_u64(dev->of_node, "flash-edaf-tgt-addr", &flash->edaf.taddr); - if (rc || !IS_ALIGNED(flash->edaf.taddr, FLASH_EDAF_ALIGN)) { - dev_err(dev, "cannot get 16MB-aligned eDAF address\n"); + np = of_parse_phandle(dev->of_node, "flash-edaf-tgt-addr", 0); + if (!np || of_address_to_resource(np, 0, &res)) { + dev_err(dev, "cannot get eDAF memory region\n"); return -ENODEV; } - rc = of_property_read_u64(dev->of_node, "flash-edaf-size", &flash->edaf.size); - if (rc || !IS_ALIGNED(flash->edaf.size, FLASH_EDAF_ALIGN)) { - dev_err(dev, "cannot get 16MB-aligned eDAF size\n"); - return -ENODEV; + of_node_put(np); + + flash->edaf.taddr = res.start; + flash->edaf.size = resource_size(&res); + dev_info(dev, "eDAF address: 0x%llx\n", flash->edaf.taddr); + dev_info(dev, "eDAF size: 0x%llx\n", flash->edaf.size); + + virt = devm_ioremap_resource(dev, &res); + if (!virt) { + dev_err(dev, "cannot map eDAF memory region\n"); + return -ENOMEM; } } @@ -2037,6 +2116,7 @@ static irqreturn_t ast2700_espi_isr(int irq, void *arg) ast2700_espi_flash_isr(espi); if (sts & ESPI_INT_STS_RST_DEASSERT) { + ast2700_espi_perif_sw_reset(espi); ast2700_espi_perif_reset(espi); ast2700_espi_vw_reset(espi); ast2700_espi_oob_reset(espi); @@ -2052,6 +2132,7 @@ static int ast2700_espi_probe(struct platform_device *pdev) struct ast2700_espi *espi; struct resource *res; struct device *dev; + struct regmap *scu1; uint32_t reg; int rc; @@ -2069,6 +2150,15 @@ static int ast2700_espi_probe(struct platform_device *pdev) return rc; } + scu1 = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); + if (IS_ERR(scu1)) { + dev_err(dev, "failed to find SCU1 regmap\n"); + return PTR_ERR(scu1); + } + rc = regmap_update_bits(scu1, SCU1_DDR, + SCU1_DDR_DIS_ESPI0_AHB | SCU1_DDR_DIS_ESPI1_AHB, + 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "cannot get resource\n"); diff --git a/drivers/soc/aspeed/ast2700-espi.h b/drivers/soc/aspeed/ast2700-espi.h index cd1206b36c5cf9..6b29004965a071 100644 --- a/drivers/soc/aspeed/ast2700-espi.h +++ b/drivers/soc/aspeed/ast2700-espi.h @@ -8,6 +8,11 @@ #include #include "aspeed-espi-comm.h" +/* SCU regiseters */ +#define SCU1_DDR 0x0c8 +#define SCU1_DDR_DIS_ESPI0_AHB BIT(0) +#define SCU1_DDR_DIS_ESPI1_AHB BIT(1) + /* global registers */ #define ESPI_CTRL 0x000 #define ESPI_STS 0x004 @@ -23,6 +28,7 @@ #define ESPI_INT_EN_RST_ASSERT BIT(30) #define ESPI_DEV_ID 0x010 #define ESPI_CAP_GEN 0x014 +#define ESPI_CAP_GEN_RTC_SUP BIT(29) #define ESPI_CAP_CH0 0x018 #define ESPI_CAP_CH1 0x01c #define ESPI_CAP_CH2 0x020 @@ -124,7 +130,7 @@ #define ESPI_CH1_GPIO_VAL0 0x250 #define ESPI_CH1_GPIO_VAL1 0x254 #define ESPI_CH1_GPIO_DIR0 0x258 -#define ESPI_CH1_GPIO_DIR1 0x258 +#define ESPI_CH1_GPIO_DIR1 0x25c #define ESPI_CH1_GPIO_RSTSEL0 0x260 #define ESPI_CH1_GPIO_RSTSEL1 0x264 #define ESPI_CH1_GPIO_GRP 0x268 diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a03525a3a3a9bc..dde6a401065027 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -120,14 +120,14 @@ config SPI_ASPEED_SMC only supports SPI NOR. config SPI_ASPEED_TXRX - tristate "Aspeed SPI controllers" - depends on ARCH_ASPEED || COMPILE_TEST - depends on OF - help - This enables support for SPI controller driver in the Aspeed - AST2600, AST2500 and AST2400 SoCs when attached - to SPI device chips with half-duplex mode. On AST2700, - full-duplex mode can be enabled. + tristate "Aspeed SPI controllers" + depends on ARCH_ASPEED || COMPILE_TEST + depends on OF + help + This enables support for SPI controller driver in the Aspeed + AST2600, AST2500 and AST2400 SoCs when attached + to SPI device chips with half-duplex mode. On AST2700, + full-duplex mode can be enabled. config SPI_ATMEL tristate "Atmel SPI Controller" diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9c658595968ad8..2a1ee03c35cbb0 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_SPI_AMLOGIC_SPIFC_A1) += spi-amlogic-spifc-a1.o obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o obj-$(CONFIG_SPI_ASPEED_SMC) += spi-aspeed-smc.o -obj-$(CONFIG_SPI_ASPEED_TXRX) += spi-aspeed-txrx.o +obj-$(CONFIG_SPI_ASPEED_TXRX) += spi-aspeed-txrx.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o obj-$(CONFIG_SPI_AT91_USART) += spi-at91-usart.o diff --git a/drivers/spi/spi-aspeed-txrx.c b/drivers/spi/spi-aspeed-txrx.c index 01a026082f6bb9..3d4272bc5388a3 100644 --- a/drivers/spi/spi-aspeed-txrx.c +++ b/drivers/spi/spi-aspeed-txrx.c @@ -27,6 +27,7 @@ #define SPI_CTRL 0x04 #define SPI_CE0_CTRL 0x10 #define SPI_DECODE_ADDR_REG 0x30 +#define SPI_MISC_CTRL 0x54 #define SPI_FULL_DUPLEX_RX_REG 0x1e4 @@ -38,8 +39,6 @@ #define SPI_CE_INACTIVE BIT(2) #define SPI_CMD_USER_MODE (0x3) -#define SPI_FULL_DUPLEX 0x00000001 - struct aspeed_spi_host { phys_addr_t ahb_base_phy; size_t ahb_window_sz; @@ -51,11 +50,8 @@ struct aspeed_spi_host { u32 ahb_clk; u32 ctrl_val[5]; void __iomem *chip_ahb_base[5]; - /* lock: make sure only a user can access the controller once. */ - struct mutex lock; u8 cs_change; const struct aspeed_spi_info *info; - u32 flag; }; struct aspeed_spi_info { @@ -345,18 +341,15 @@ static void aspeed_spi_stop_user(struct spi_device *spi) } static void aspeed_spi_transfer_tx(struct aspeed_spi_host *host, const u8 *tx_buf, - u8 *rx_buf, void *dst, u32 len, - bool *full_duplex_rx) + u8 *rx_buf, void *dst, u32 len) { u32 i; for (i = 0; i < len; i++) { writeb(tx_buf[i], dst); - if (rx_buf && (host->flag & SPI_FULL_DUPLEX)) { + if (rx_buf && tx_buf == rx_buf) rx_buf[i] = readb(host->ctrl_reg + SPI_FULL_DUPLEX_RX_REG); - *full_duplex_rx = true; - } } } @@ -369,22 +362,22 @@ static int aspeed_spi_transfer(struct spi_controller *ctlr, struct spi_device *spi = msg->spi; struct spi_transfer *xfer; const u8 *tx_buf; - bool full_duplex_rx; u8 *rx_buf; u32 cs; u32 j = 0; - u32 ctrl_val; + u32 ctrl_val, normal_mode; void __iomem *ctrl_reg; - if (host->cs_change == 0) { - mutex_lock(&host->lock); + if (host->cs_change == 0) aspeed_spi_start_user(spi); - } cs = spi->chip_select; ctrl_reg = host->ctrl_reg + SPI_CE0_CTRL + cs * 4; ctrl_val = readl(ctrl_reg); + normal_mode = readl(host->ctrl_reg + SPI_MISC_CTRL); + writel(0x0, host->ctrl_reg + SPI_MISC_CTRL); + dev_dbg(dev, "cs: %d\n", cs); list_for_each_entry(xfer, &msg->transfers, transfer_list) { @@ -397,8 +390,6 @@ static int aspeed_spi_transfer(struct spi_controller *ctlr, tx_buf = xfer->tx_buf; rx_buf = xfer->rx_buf; - full_duplex_rx = false; - if (tx_buf) { ctrl_val &= ~SPI_IO_MASK; if (spi->mode & SPI_TX_DUAL) @@ -414,10 +405,10 @@ static int aspeed_spi_transfer(struct spi_controller *ctlr, aspeed_spi_transfer_tx(host, tx_buf, rx_buf, (void *)host->chip_ahb_base[cs], - xfer->len, &full_duplex_rx); + xfer->len); } - if (rx_buf && !full_duplex_rx) { + if (rx_buf && rx_buf != tx_buf) { ctrl_val &= ~SPI_IO_MASK; if (spi->mode & SPI_RX_DUAL) ctrl_val |= SPI_DUAL_IO_MODE; @@ -443,10 +434,9 @@ static int aspeed_spi_transfer(struct spi_controller *ctlr, msg->status = 0; - spi_finalize_current_message(ctlr); + writel(normal_mode, host->ctrl_reg + SPI_MISC_CTRL); - if (host->cs_change == 0) - mutex_unlock(&host->lock); + spi_finalize_current_message(ctlr); return 0; } @@ -527,10 +517,6 @@ static int aspeed_spi_probe(struct platform_device *pdev) return err; } - host->flag = 0; - if (of_property_read_bool(dev->of_node, "spi-aspeed-full-duplex")) - host->flag |= SPI_FULL_DUPLEX; - host->ctrl->setup = aspeed_spi_setup; host->ctrl->transfer_one_message = aspeed_spi_transfer; host->ctrl->num_chipselect = host->info->max_cs; @@ -540,8 +526,6 @@ static int aspeed_spi_probe(struct platform_device *pdev) aspeed_spi_enable(host, true); aspeed_spi_chip_set_type(host); - mutex_init(&host->lock); - err = devm_spi_register_controller(dev, host->ctrl); if (err) { dev_err(dev, "failed to register SPI controller\n"); @@ -552,7 +536,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) disable_clk: clk_disable_unprepare(host->clk); - mutex_destroy(&host->lock); + return err; } @@ -562,7 +546,6 @@ static int aspeed_spi_remove(struct platform_device *pdev) aspeed_spi_enable(host, false); clk_disable_unprepare(host->clk); - mutex_destroy(&host->lock); return 0; } @@ -641,4 +624,3 @@ MODULE_AUTHOR("Ryan Chen"); MODULE_AUTHOR("Chin-Ting Kuo"); MODULE_LICENSE("GPL"); - diff --git a/drivers/tty/serial/8250/8250_aspeed.c b/drivers/tty/serial/8250/8250_aspeed.c index c4de2ad7426d35..404c4ad50f0885 100644 --- a/drivers/tty/serial/8250/8250_aspeed.c +++ b/drivers/tty/serial/8250/8250_aspeed.c @@ -22,22 +22,24 @@ #include "8250.h" #define DEVICE_NAME "aspeed-uart" +#define UNKNOWN 0 +#define AST2500_PLAT 1 +#define AST2600_PLAT 2 +#define AST2700_PLAT 3 /* offsets for the aspeed virtual uart registers */ #define VUART_GCRA 0x20 #define VUART_GCRA_VUART_EN BIT(0) #define VUART_GCRA_SIRQ_POLARITY BIT(1) +#define VUART_GCRA_CHARACTER_TIMEOUT_TIME_MASK GENMASK(3, 2) #define VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5) -#define VUART_GCRA_SLV_TIMEOUT_WIDTH_MASK GENMASK(3, 2) -#define VUART_GCRA_SLV_TIMEOUT_WIDTH_SHIFT 2 -#define VUART_GCRA_SLV_TIMEOUT_WIDTH_SEL 3 /* 64*LCLK or 1/28800 sec */ #define VUART_GCRB 0x24 #define VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4) #define VUART_GCRB_HOST_SIRQ_SHIFT 4 -#define VUART_GCRG 0x38 -#define VUART_GCRG_SLV_TIMEOUT_WIDTH_EN BIT(1) #define VUART_ADDRL 0x28 #define VUART_ADDRH 0x2c +#define VUART_GCRG 0x38 +#define VUART_GCRG_CHARACTER_TIMEOUT_TIME_CONTROL BIT(1) #define DMA_TX_BUFSZ PAGE_SIZE #define DMA_RX_BUFSZ (64 * 1024) @@ -48,6 +50,7 @@ struct ast8250_vuart { u32 port; u32 sirq; u32 sirq_pol; + bool character_timeout_time_en; }; struct ast8250_udma { @@ -69,6 +72,7 @@ struct ast8250_udma { struct ast8250_data { int line; + struct resource *res; u8 __iomem *regs; bool is_vuart; @@ -84,26 +88,26 @@ struct ast8250_data { static void ast8250_dma_tx_complete(int tx_rb_rptr, void *id) { u32 count; - unsigned long flags; - struct uart_port *port = (struct uart_port*)id; + unsigned long flags; + struct uart_port *port = id; struct ast8250_data *data = port->private_data; - spin_lock_irqsave(&port->lock, flags); + uart_port_lock_irqsave(port, &flags); count = CIRC_CNT(tx_rb_rptr, port->state->xmit.tail, data->dma.tx_rbsz); port->state->xmit.tail = tx_rb_rptr; port->icount.tx += count; - if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); + if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); - spin_unlock_irqrestore(&port->lock, flags); + uart_port_unlock_irqrestore(port, flags); } static void ast8250_dma_rx_complete(int rx_rb_wptr, void *id) { unsigned long flags; - struct uart_port *up = (struct uart_port*)id; + struct uart_port *up = id; struct tty_port *tp = &up->state->port; struct ast8250_data *data = up->private_data; struct ast8250_udma *dma = &data->dma; @@ -111,7 +115,7 @@ static void ast8250_dma_rx_complete(int rx_rb_wptr, void *id) u32 rx_rbsz = dma->rx_rbsz; u32 count = 0; - spin_lock_irqsave(&up->lock, flags); + uart_port_lock_irqsave(up, &flags); rx_rb->head = rx_rb_wptr; @@ -126,7 +130,7 @@ static void ast8250_dma_rx_complete(int rx_rb_wptr, void *id) rx_rb->tail += count; rx_rb->tail %= rx_rbsz; - up->icount.rx += count; + up->icount.rx += count; } if (count) { @@ -134,7 +138,7 @@ static void ast8250_dma_rx_complete(int rx_rb_wptr, void *id) tty_flip_buffer_push(tp); } - spin_unlock_irqrestore(&up->lock, flags); + uart_port_unlock_irqrestore(up, flags); } static void ast8250_dma_start_tx(struct uart_port *port) @@ -184,6 +188,18 @@ static void ast8250_vuart_init(struct ast8250_data *data) else reg &= ~VUART_GCRA_SIRQ_POLARITY; writeb(reg, data->regs + VUART_GCRA); + + if (vuart->character_timeout_time_en) { + /* Character timeout time */ + reg = readb(data->regs + VUART_GCRA); + reg |= VUART_GCRA_CHARACTER_TIMEOUT_TIME_MASK; + writeb(reg, data->regs + VUART_GCRA); + + /* Character timeout time by LCLK control bit */ + reg = readb(data->regs + VUART_GCRG); + reg |= VUART_GCRG_CHARACTER_TIMEOUT_TIME_CONTROL; + writeb(reg, data->regs + VUART_GCRG); + } } static void ast8250_vuart_set_host_tx_discard(struct ast8250_data *data, bool discard) @@ -264,14 +280,14 @@ static int ast8250_startup(struct uart_port *port) } rc = aspeed_udma_request_tx_chan(dma->ch, dma->tx_addr, - dma->tx_rb, dma->tx_rbsz, ast8250_dma_tx_complete, port, dma->tx_tmout_dis); + dma->tx_rbsz, ast8250_dma_tx_complete, port, dma->tx_tmout_dis); if (rc) { dev_err(port->dev, "failed to request DMA TX channel\n"); goto free_dma_n_out; } rc = aspeed_udma_request_rx_chan(dma->ch, dma->rx_addr, - dma->rx_rb, dma->rx_rbsz, ast8250_dma_rx_complete, port, dma->rx_tmout_dis); + dma->rx_rbsz, ast8250_dma_rx_complete, port, dma->rx_tmout_dis); if (rc) { dev_err(port->dev, "failed to request DMA RX channel\n"); goto free_dma_n_out; @@ -344,61 +360,19 @@ static int __maybe_unused ast8250_resume(struct device *dev) return 0; } -static void ast8250_vuart_set_slave_timeout_width(struct ast8250_data *data, - unsigned int width) -{ - /* get register value and set slave timeout width select */ - u32 reg = readl(data->regs + VUART_GCRA); - reg &= ~VUART_GCRA_SLV_TIMEOUT_WIDTH_MASK; - reg |= (width << VUART_GCRA_SLV_TIMEOUT_WIDTH_SHIFT); - printk(KERN_INFO "eSPI vuart %x\n", reg); - writel(reg, data->regs + VUART_GCRA); - - /* get and set slave timeout width enable */ - reg = readl(data->regs + VUART_GCRG); - reg |= VUART_GCRG_SLV_TIMEOUT_WIDTH_EN; - writel(reg, data->regs + VUART_GCRG); -} - -static int ast8250_probe(struct platform_device *pdev) +static int ast8250_probe_of(struct platform_device *pdev, struct uart_port *p, + struct ast8250_data *data) { - int rc; - struct uart_8250_port uart = {}; - struct uart_port *port = &uart.port; struct device *dev = &pdev->dev; - struct ast8250_data *data; - - struct resource *res; - u32 irq; - - rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); - if (rc) { - dev_err(dev, "cannot set 64-bits DMA mask\n"); - return rc; - } - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - data->dma.rx_rb = devm_kzalloc(dev, sizeof(data->dma.rx_rb), GFP_KERNEL); - if (data->dma.rx_rb == NULL) - return -ENOMEM; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "failed to get IRQ number\n"); - return irq; - } + int rc; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { + data->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!data->res) { dev_err(dev, "failed to get register base\n"); return -ENODEV; } - data->regs = devm_ioremap(dev, res->start, resource_size(res)); + data->regs = devm_ioremap(dev, data->res->start, resource_size(data->res)); if (IS_ERR(data->regs)) { dev_err(dev, "failed to map registers\n"); return PTR_ERR(data->regs); @@ -410,18 +384,12 @@ static int ast8250_probe(struct platform_device *pdev) return -ENODEV; } - rc = clk_prepare_enable(data->clk); - if (rc) { - dev_err(dev, "failed to enable clock\n"); - return rc; - } - data->rst = devm_reset_control_get_optional_exclusive(dev, NULL); - if (!IS_ERR(data->rst)) - reset_control_deassert(data->rst); data->is_vuart = of_property_read_bool(dev->of_node, "virtual"); if (data->is_vuart) { + u32 plat = (unsigned long)of_device_get_match_data(dev); + rc = of_property_read_u32(dev->of_node, "port", &data->vuart.port); if (rc) { dev_err(dev, "failed to get VUART port address\n"); @@ -440,10 +408,10 @@ static int ast8250_probe(struct platform_device *pdev) return -ENODEV; } - ast8250_vuart_init(data); - ast8250_vuart_set_host_tx_discard(data, true); - ast8250_vuart_set_enable(data, true); - ast8250_vuart_set_slave_timeout_width(data, VUART_GCRA_SLV_TIMEOUT_WIDTH_SEL); + if (plat == AST2700_PLAT) + data->vuart.character_timeout_time_en = true; + else + data->vuart.character_timeout_time_en = false; } data->use_dma = of_property_read_bool(dev->of_node, "dma-mode"); @@ -458,24 +426,69 @@ static int ast8250_probe(struct platform_device *pdev) data->dma.rx_tmout_dis = of_property_read_bool(dev->of_node, "dma-rx-timeout-disable"); } + return 0; +} + +static int ast8250_probe(struct platform_device *pdev) +{ + int rc; + struct uart_8250_port uart = {}; + struct uart_port *port = &uart.port; + struct device *dev = &pdev->dev; + struct ast8250_data *data; + + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (rc) { + dev_err(dev, "cannot set 64-bits DMA mask\n"); + return rc; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dma.rx_rb = devm_kzalloc(dev, sizeof(data->dma.rx_rb), GFP_KERNEL); + if (!data->dma.rx_rb) + return -ENOMEM; + + rc = ast8250_probe_of(pdev, port, data); + if (rc) + return rc; + + rc = clk_prepare_enable(data->clk); + if (rc) { + dev_err(dev, "failed to enable clock\n"); + return rc; + } + + if (!IS_ERR(data->rst)) + reset_control_deassert(data->rst); + + if (data->is_vuart) { + ast8250_vuart_init(data); + ast8250_vuart_set_host_tx_discard(data, true); + ast8250_vuart_set_enable(data, true); + } + spin_lock_init(&port->lock); port->dev = dev; - port->type = PORT_16550A; - port->irq = irq; - port->line = of_alias_get_id(dev->of_node, "serial"); - port->handle_irq = ast8250_handle_irq; - port->mapbase = res->start; - port->mapsize = resource_size(res); + port->mapbase = data->res->start; + port->mapsize = resource_size(data->res); port->membase = data->regs; - port->uartclk = clk_get_rate(data->clk); - port->regshift = 2; - port->iotype = UPIO_MEM32; port->flags = UPF_FIXED_TYPE | UPF_FIXED_PORT | UPF_SHARE_IRQ; port->startup = ast8250_startup; port->shutdown = ast8250_shutdown; port->private_data = data; uart.bugs |= UART_BUG_TXRACE; + rc = uart_read_port_properties(port); + if (rc) + return rc; + + port->type = PORT_16550A; + port->handle_irq = ast8250_handle_irq; + port->uartclk = clk_get_rate(data->clk); + data->line = serial8250_register_8250_port(&uart); if (data->line < 0) { dev_err(dev, "failed to register 8250 port\n"); @@ -491,12 +504,12 @@ static int ast8250_probe(struct platform_device *pdev) static int ast8250_remove(struct platform_device *pdev) { - struct ast8250_data *data = platform_get_drvdata(pdev); + struct ast8250_data *data = platform_get_drvdata(pdev); if (data->is_vuart) ast8250_vuart_set_enable(data, false); - serial8250_unregister_port(data->line); + serial8250_unregister_port(data->line); return 0; } @@ -505,9 +518,9 @@ static const struct dev_pm_ops ast8250_pm_ops = { }; static const struct of_device_id ast8250_of_match[] = { - { .compatible = "aspeed,ast2500-uart" }, - { .compatible = "aspeed,ast2600-uart" }, - { .compatible = "aspeed,ast2700-uart" }, + { .compatible = "aspeed,ast2500-uart", .data = (void *)AST2500_PLAT}, + { .compatible = "aspeed,ast2600-uart", .data = (void *)AST2600_PLAT}, + { .compatible = "aspeed,ast2700-uart", .data = (void *)AST2700_PLAT}, { }, }; diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index f73fcd2f9776f9..0cb06dfd3ef174 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -359,6 +359,61 @@ static void ast_vhub_remove(struct platform_device *pdev) vhub->ep0_bufs = NULL; } +static int ast_vhub_init_uart(struct device *dev, struct ast_vhub *vhub) +{ + const struct device_node *np = dev->of_node; + void __iomem *regs = vhub->regs + 0x800; + int i, rc = 0; + int num_ports; + u32 ports[AST_VHUB_NUM_UART_PORTS], port; + u32 mode_sel = 0, dev_en = 0; + + num_ports = of_property_count_u32_elems(np, "aspeed,uart-ports"); + if (num_ports == -EINVAL) { + /* Property not found */ + return 0; + } + if (num_ports < 0) { + dev_err(dev, "Failed to read uart-ports property\n"); + return num_ports; + } + if (num_ports > AST_VHUB_NUM_UART_PORTS) { + dev_warn(dev, "Too many UART ports (%d), max is %d\n", + num_ports, AST_VHUB_NUM_UART_PORTS); + num_ports = AST_VHUB_NUM_UART_PORTS; + } + + rc = of_property_read_u32_array(np, "aspeed,uart-ports", + ports, num_ports); + if (rc) + return rc; + + dev_en = readl(regs + AST_VHUB_COM_EN_CTRL); + + for (i = 0; i < num_ports; i++) { + // io-die uart only + if (ports[i] == 4 || ports[i] > AST_VHUB_NUM_UART_PORTS) { + dev_warn(dev, "Ignoring invalid UART port %d\n", + ports[i]); + continue; + } + + if (ports[i] < 4) + port = ports[i]; + else + port = ports[i] - 1; + + mode_sel |= (0x2 << (port * 2)); + dev_en |= BIT(port + 16); + } + + dev_info(dev, "Enabled UART ports\n"); + + writel(mode_sel, regs + AST_VHUB_COM_MODE_SEL); + writel(dev_en, regs + AST_VHUB_COM_EN_CTRL); + return 0; +} + static int ast_vhub_probe(struct platform_device *pdev) { enum usb_device_speed max_speed; @@ -451,6 +506,8 @@ static int ast_vhub_probe(struct platform_device *pdev) vhub->regs + pdata->txfifo_fix_reg); } + ast_vhub_init_uart(&pdev->dev, vhub); + /* Check if we need to limit the HW to USB1 */ max_speed = usb_get_maximum_speed(&pdev->dev); if (max_speed != USB_SPEED_UNKNOWN && max_speed < USB_SPEED_HIGH) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h index fce1f004d24802..78abf0a7c9b4fd 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h +++ b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h @@ -199,6 +199,14 @@ #define VHUB_DSC1_IN_SET_LEN(x) ((x) & 0xfff) #define VHUB_DSC1_IN_LEN(x) ((x) & 0xfff) +/*********************************** + * * + * USB2COM register definitions * + * * + ***********************************/ +#define AST_VHUB_COM_MODE_SEL 0x10 +#define AST_VHUB_COM_EN_CTRL 0x1C + /**************************************** * * * Data structures and misc definitions * @@ -218,6 +226,8 @@ * values are 256 and 32) */ +#define AST_VHUB_NUM_UART_PORTS 15 /* USB2COM ports */ + struct ast_vhub; struct ast_vhub_dev; diff --git a/include/dt-bindings/clock/aspeed,ast2700-scu.h b/include/dt-bindings/clock/aspeed,ast2700-scu.h index cecd8c9e0ecfd6..bacf712e8e04cf 100644 --- a/include/dt-bindings/clock/aspeed,ast2700-scu.h +++ b/include/dt-bindings/clock/aspeed,ast2700-scu.h @@ -13,61 +13,64 @@ #define SCU0_CLK_24M 1 #define SCU0_CLK_192M 2 #define SCU0_CLK_UART 3 +#define SCU0_CLK_UART_DIV13 3 #define SCU0_CLK_PSP 4 #define SCU0_CLK_HPLL 5 #define SCU0_CLK_HPLL_DIV2 6 #define SCU0_CLK_HPLL_DIV4 7 -#define SCU0_CLK_DPLL 8 -#define SCU0_CLK_MPLL 9 -#define SCU0_CLK_MPLL_DIV2 10 -#define SCU0_CLK_MPLL_DIV4 11 -#define SCU0_CLK_MPLL_DIV8 12 -#define SCU0_CLK_D0 13 -#define SCU0_CLK_D1 14 -#define SCU0_CLK_CRT0 15 -#define SCU0_CLK_CRT1 16 -#define SCU0_CLK_MPHY 17 -#define SCU0_CLK_AXI0 18 -#define SCU0_CLK_AXI1 19 -#define SCU0_CLK_AHBMUX 20 -#define SCU0_CLK_AHB 21 -#define SCU0_CLK_APB 22 -#define SCU0_CLK_UART4 23 -#define SCU0_CLK_EMMCMUX 24 -#define SCU0_CLK_EMMC 25 -#define SCU0_CLK_U2PHY_CLK12M 26 -#define SCU0_CLK_U2PHY_REFCLK 27 +#define SCU0_CLK_HPLL_DIV_AHB 8 +#define SCU0_CLK_DPLL 9 +#define SCU0_CLK_MPLL 10 +#define SCU0_CLK_MPLL_DIV2 11 +#define SCU0_CLK_MPLL_DIV4 12 +#define SCU0_CLK_MPLL_DIV8 13 +#define SCU0_CLK_MPLL_DIV_AHB 14 +#define SCU0_CLK_D0 15 +#define SCU0_CLK_D1 16 +#define SCU0_CLK_CRT0 17 +#define SCU0_CLK_CRT1 18 +#define SCU0_CLK_MPHY 19 +#define SCU0_CLK_AXI0 20 +#define SCU0_CLK_AXI1 21 +#define SCU0_CLK_AHB 22 +#define SCU0_CLK_APB 23 +#define SCU0_CLK_UART4 24 +#define SCU0_CLK_EMMCMUX 25 +#define SCU0_CLK_EMMC 26 +#define SCU0_CLK_U2PHY_CLK12M 27 +#define SCU0_CLK_U2PHY_REFCLK 28 /* SOC0 clk-gate */ -#define SCU0_CLK_GATE_MCLK 28 -#define SCU0_CLK_GATE_ECLK 29 -#define SCU0_CLK_GATE_2DCLK 30 -#define SCU0_CLK_GATE_VCLK 31 -#define SCU0_CLK_GATE_BCLK 32 -#define SCU0_CLK_GATE_VGA0CLK 33 -#define SCU0_CLK_GATE_REFCLK 34 -#define SCU0_CLK_GATE_PORTBUSB2CLK 35 -#define SCU0_CLK_GATE_UHCICLK 36 -#define SCU0_CLK_GATE_VGA1CLK 37 -#define SCU0_CLK_GATE_DDRPHYCLK 38 -#define SCU0_CLK_GATE_E2M0CLK 39 -#define SCU0_CLK_GATE_HACCLK 40 -#define SCU0_CLK_GATE_PORTAUSB2CLK 41 -#define SCU0_CLK_GATE_UART4CLK 42 -#define SCU0_CLK_GATE_SLICLK 43 -#define SCU0_CLK_GATE_DACCLK 44 -#define SCU0_CLK_GATE_DP 45 -#define SCU0_CLK_GATE_E2M1CLK 46 -#define SCU0_CLK_GATE_CRT0CLK 47 -#define SCU0_CLK_GATE_CRT1CLK 48 -#define SCU0_CLK_GATE_ECDSACLK 49 -#define SCU0_CLK_GATE_RSACLK 50 -#define SCU0_CLK_GATE_RVAS0CLK 51 -#define SCU0_CLK_GATE_UFSCLK 52 -#define SCU0_CLK_GATE_EMMCCLK 53 -#define SCU0_CLK_GATE_RVAS1CLK 54 -#define SCU0_CLK_MPHYSRC 55 +#define SCU0_CLK_GATE_MCLK 29 +#define SCU0_CLK_GATE_ECLK 30 +#define SCU0_CLK_GATE_2DCLK 31 +#define SCU0_CLK_GATE_VCLK 32 +#define SCU0_CLK_GATE_BCLK 33 +#define SCU0_CLK_GATE_VGA0CLK 34 +#define SCU0_CLK_GATE_REFCLK 35 +#define SCU0_CLK_GATE_PORTBUSB2CLK 36 +#define SCU0_CLK_GATE_UHCICLK 37 +#define SCU0_CLK_GATE_VGA1CLK 38 +#define SCU0_CLK_GATE_DDRPHYCLK 39 +#define SCU0_CLK_GATE_E2M0CLK 40 +#define SCU0_CLK_GATE_HACCLK 41 +#define SCU0_CLK_GATE_PORTAUSB2CLK 42 +#define SCU0_CLK_GATE_UART4CLK 43 +#define SCU0_CLK_GATE_SLICLK 44 +#define SCU0_CLK_GATE_DACCLK 45 +#define SCU0_CLK_GATE_DP 46 +#define SCU0_CLK_GATE_E2M1CLK 47 +#define SCU0_CLK_GATE_CRT0CLK 48 +#define SCU0_CLK_GATE_CRT1CLK 49 +#define SCU0_CLK_GATE_ECDSACLK 50 +#define SCU0_CLK_GATE_RSACLK 51 +#define SCU0_CLK_GATE_RVAS0CLK 52 +#define SCU0_CLK_GATE_UFSCLK 53 +#define SCU0_CLK_GATE_EMMCCLK 54 +#define SCU0_CLK_GATE_RVAS1CLK 55 #define SCU0_CLK_U2PHY_REFCLKSRC 56 +#define SCU0_CLK_AHBMUX 57 +#define SCU0_CLK_MPHYSRC 58 /* SOC1 clk */ #define SCU1_CLKIN 0 @@ -159,6 +162,6 @@ #define SCU1_CLK_GATE_PORTCUSB2CLK 84 #define SCU1_CLK_GATE_PORTDUSB2CLK 85 #define SCU1_CLK_GATE_LTPI1TXCLK 86 +#define SCU1_CLK_I3C 87 -#define SCU1_CLK_I3C 87 #endif diff --git a/include/dt-bindings/clock/ast2600-clock.h b/include/dt-bindings/clock/ast2600-clock.h index 1e049dae41753b..ace3db51fd45bc 100644 --- a/include/dt-bindings/clock/ast2600-clock.h +++ b/include/dt-bindings/clock/ast2600-clock.h @@ -72,7 +72,7 @@ #define ASPEED_CLK_D1CLK 55 #define ASPEED_CLK_VCLK 56 #define ASPEED_CLK_LHCLK 57 -#define ASPEED_CLK_UART 58 +#define ASPEED_CLK_UART5 58 #define ASPEED_CLK_UARTX 59 #define ASPEED_CLK_SDIO 60 #define ASPEED_CLK_EMMC 61 @@ -86,6 +86,9 @@ #define ASPEED_CLK_MAC3RCLK 69 #define ASPEED_CLK_MAC4RCLK 70 #define ASPEED_CLK_I3C 71 +#define ASPEED_CLK_HUARTX 72 +#define ASPEED_CLK_UXCLK 73 +#define ASPEED_CLK_HUXCLK 74 /* Only list resets here that are not part of a clock gate + reset pair */ #define ASPEED_RESET_ESPI 57 @@ -118,10 +121,15 @@ #define ASPEED_RESET_DEV_MCTP 24 #define ASPEED_RESET_RC_MCTP 23 #define ASPEED_RESET_JTAG_MASTER 22 -#define ASPEED_RESET_PCIE_DEV_O 21 -#define ASPEED_RESET_PCIE_DEV_OEN 20 -#define ASPEED_RESET_PCIE_RC_O 19 -#define ASPEED_RESET_PCIE_RC_OEN 18 +#define ASPEED_RESET_PCIE_DEV_OE 21 +#define ASPEED_RESET_PCIE_DEV_O 20 +#define ASPEED_RESET_PCIE_RC_OE 19 +#define ASPEED_RESET_PCIE_RC_O 18 +#define ASPEED_RESET_EMMC 16 +#define ASPEED_RESET_CRT 13 +#define ASPEED_RESET_MAC2 12 +#define ASPEED_RESET_MAC1 11 +#define ASPEED_RESET_RVAS 9 #define ASPEED_RESET_VIDEO 6 #define ASPEED_RESET_PCI_DP 5 #define ASPEED_RESET_HACE 4 diff --git a/include/dt-bindings/gpio/aspeed-gpio.h b/include/dt-bindings/gpio/aspeed-gpio.h index 5b5013b0f23907..56fc4889b2c4a1 100644 --- a/include/dt-bindings/gpio/aspeed-gpio.h +++ b/include/dt-bindings/gpio/aspeed-gpio.h @@ -42,8 +42,6 @@ #define ASPEED_GPIO_PORT_AA 26 #define ASPEED_GPIO_PORT_AB 27 #define ASPEED_GPIO_PORT_AC 28 -#define ASPEED_GPIO_PORT_AD 29 -#define ASPEED_GPIO_PORT_AE 30 #define ASPEED_GPIO(port, offset) \ ((ASPEED_GPIO_PORT_##port * 8) + offset) diff --git a/include/dt-bindings/reset/aspeed,ast2700-scu.h b/include/dt-bindings/reset/aspeed,ast2700-scu.h index d53c719b7a6699..8a8e5ac4f19b3b 100644 --- a/include/dt-bindings/reset/aspeed,ast2700-scu.h +++ b/include/dt-bindings/reset/aspeed,ast2700-scu.h @@ -120,5 +120,6 @@ #define SCU1_RESET_H2X 61 #define SCU1_RESET_I3CDMA 62 #define SCU1_RESET_PCIE2RST 63 +#define SCU1_RESET_XPCS 64 /* for AST2755 */ #endif /* _MACH_ASPEED_AST2700_RESET_H_ */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 1293c38ddb7f73..7368faaa839a8f 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -608,6 +608,24 @@ struct clk *clk_register_gate(struct device *dev, const char *name, __devm_clk_hw_register_gate((dev), NULL, (name), (parent_name), NULL, \ NULL, (flags), (reg), (bit_idx), \ (clk_gate_flags), (lock)) +/** + * devm_clk_hw_register_gate_parent_hw - register a gate clock with the clock + * framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_hw: pointer to parent clk + * @flags: framework-specific flags for this clock + * @reg: register address to control gating of this clock + * @bit_idx: which bit in the register controls gating of this clock + * @clk_gate_flags: gate-specific flags for this clock + * @lock: shared register lock for this clock + */ +#define devm_clk_hw_register_gate_parent_hw(dev, name, parent_hw, flags, \ + reg, bit_idx, clk_gate_flags, \ + lock) \ + __devm_clk_hw_register_gate((dev), NULL, (name), NULL, (parent_hw), \ + NULL, (flags), (reg), (bit_idx), \ + (clk_gate_flags), (lock)) /** * devm_clk_hw_register_gate_parent_data - register a gate clock with the * clock framework diff --git a/include/linux/soc/aspeed/aspeed-udma.h b/include/linux/soc/aspeed/aspeed-udma.h index 33acea745f1c67..439d901c1c0ff4 100644 --- a/include/linux/soc/aspeed/aspeed-udma.h +++ b/include/linux/soc/aspeed/aspeed-udma.h @@ -1,8 +1,6 @@ #ifndef __ASPEED_UDMA_H__ #define __ASPEED_UDMA_H__ -#include - typedef void (*aspeed_udma_cb_t)(int rb_rwptr, void *id); enum aspeed_udma_ops { @@ -17,11 +15,9 @@ void aspeed_udma_set_rx_rptr(u32 ch_no, u32 rptr); void aspeed_udma_tx_chan_ctrl(u32 ch_no, enum aspeed_udma_ops op); void aspeed_udma_rx_chan_ctrl(u32 ch_no, enum aspeed_udma_ops op); -int aspeed_udma_request_tx_chan(u32 ch_no, dma_addr_t addr, - struct circ_buf *rb, u32 rb_sz, +int aspeed_udma_request_tx_chan(u32 ch_no, dma_addr_t addr, u32 rb_sz, aspeed_udma_cb_t cb, void *id, bool en_tmout); -int aspeed_udma_request_rx_chan(u32 ch_no, dma_addr_t addr, - struct circ_buf *rb, u32 rb_sz, +int aspeed_udma_request_rx_chan(u32 ch_no, dma_addr_t addr, u32 rb_sz, aspeed_udma_cb_t cb, void *id, bool en_tmout); int aspeed_udma_free_tx_chan(u32 ch_no);