From bd1d361b3642292222f69a2cbc3d3151d9161b25 Mon Sep 17 00:00:00 2001 From: Shaojun Yang Date: Wed, 9 Nov 2022 18:19:50 +0800 Subject: [PATCH] linux kernel 4.19/4.19-rt update 20230920 drivers: remoteproc: add remote processor and rpmsg support on e2000 platform. drivers: remoteproc: Modify remoteproc-specific files especially using 'homo_' prefix substitution for 'phytium_' prefix devicetree: bindings: Add document description about homogeneous remoteproc driver arm64: dts/phytium: Rename 'rproc' node to make it more accurate. arm64: configs: Enable CONFIG_HOMO_REMOTEPROC=m in e2000_defconfig arm64: dts: remove cache description of pe220x chips drivers: gpio: fix the issue failed to register the ACPI interruption add macb patch for support USXGMII/5GBASER/2500BASEX --- .../bindings/remoteproc/homo-rproc.txt | 32 ++ .../boot/dts/phytium/e2000q-demo-board.dts | 3 + arch/arm64/boot/dts/phytium/pe2201.dtsi | 17 +- arch/arm64/boot/dts/phytium/pe2202.dtsi | 23 +- arch/arm64/boot/dts/phytium/pe2204.dtsi | 61 +--- arch/arm64/configs/phytium_defconfig | 1 + drivers/gpio/gpio-phytium-platform.c | 4 + drivers/net/ethernet/cadence/macb.h | 13 + drivers/net/ethernet/cadence/macb_main.c | 151 ++++++-- drivers/remoteproc/Kconfig | 8 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/homo_remoteproc.c | 326 ++++++++++++++++++ include/linux/phy.h | 3 + 13 files changed, 524 insertions(+), 119 deletions(-) create mode 100644 Documentation/devicetree/bindings/remoteproc/homo-rproc.txt create mode 100644 drivers/remoteproc/homo_remoteproc.c diff --git a/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt b/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt new file mode 100644 index 0000000000..3fbfaac5f1 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/homo-rproc.txt @@ -0,0 +1,32 @@ +homogeneous remoteproc driver +========================================== + +This driver implements communication between remote processors under a homogeneous CPU architecture(SMP). + +Homogeneous RemoteProc Device Node: +================================= +A homo_remoteproc device node is used to represent the remote core instance within SoC. + +Required properties: +-------------------- + - compatible : should be "homo,rproc" + - memory-region: reserved memory which will be used by remote processor + +Example: +-------- + + reserved-memory { + #address-cells = <0x2>; + #size-cells = <0x2>; + ranges; + + rproc: rproc@b0100000 { + no-map; + reg = <0x0 0xb0100000 0x0 0x19900000>; + }; + }; + + remoteproc: remoteproc@0 { + compatible = "phytium,rproc"; + memory-region = <&rproc>; + }; diff --git a/arch/arm64/boot/dts/phytium/e2000q-demo-board.dts b/arch/arm64/boot/dts/phytium/e2000q-demo-board.dts index 8215b57cc0..cbf496d985 100644 --- a/arch/arm64/boot/dts/phytium/e2000q-demo-board.dts +++ b/arch/arm64/boot/dts/phytium/e2000q-demo-board.dts @@ -240,3 +240,6 @@ &rng0 { status = "okay"; }; +&remoteproc { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/phytium/pe2201.dtsi b/arch/arm64/boot/dts/phytium/pe2201.dtsi index dfee0aec8f..29d46a1b2d 100644 --- a/arch/arm64/boot/dts/phytium/pe2201.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2201.dtsi @@ -23,22 +23,7 @@ cpu0: cpu@0 { reg = <0x0 0x200>; enable-method = "psci"; clocks = <&scmi_dvfs 2>; - - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache>; - }; - - l2_cache: l2-cache { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x40000>; - cache-line-size = <64>; - cache-sets = <16>; - }; + }; }; &soc { diff --git a/arch/arm64/boot/dts/phytium/pe2202.dtsi b/arch/arm64/boot/dts/phytium/pe2202.dtsi index 79ab5fc63e..c61a5cbbdc 100644 --- a/arch/arm64/boot/dts/phytium/pe2202.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2202.dtsi @@ -37,12 +37,6 @@ cpu_l0: cpu@0 { reg = <0x0 0x200>; enable-method = "psci"; clocks = <&scmi_dvfs 2>; - - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache>; }; cpu_l1: cpu@1 { @@ -51,22 +45,7 @@ cpu_l1: cpu@1 { reg = <0x0 0x201>; enable-method = "psci"; clocks = <&scmi_dvfs 2>; - - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache>; - }; - - l2_cache: l2-cache { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x40000>; - cache-line-size = <64>; - cache-sets = <16>; - }; + }; }; &soc { diff --git a/arch/arm64/boot/dts/phytium/pe2204.dtsi b/arch/arm64/boot/dts/phytium/pe2204.dtsi index 6fd6cb523d..1dca735fcb 100644 --- a/arch/arm64/boot/dts/phytium/pe2204.dtsi +++ b/arch/arm64/boot/dts/phytium/pe2204.dtsi @@ -10,6 +10,23 @@ / { compatible = "phytium,pe2204"; + reserved-memory { + #address-cells = <0x2>; + #size-cells = <0x2>; + ranges; + + rproc: rproc@b0100000 { + no-map; + reg = <0x0 0xb0100000 0x0 0x19900000>; + }; + }; + + remoteproc: remoteproc@0 { + compatible = "phytium,rproc"; + memory-region = <&rproc>; + status = "disabled"; + }; + aliases { ethernet0 = &macb0; ethernet1 = &macb1; @@ -49,12 +66,6 @@ cpu_l0: cpu@0 { reg = <0x0 0x200>; enable-method = "psci"; clocks = <&scmi_dvfs 2>; - - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache_l>; }; cpu_l1: cpu@1 { @@ -63,35 +74,14 @@ cpu_l1: cpu@1 { reg = <0x0 0x201>; enable-method = "psci"; clocks = <&scmi_dvfs 2>; - - i-cache-size = <0x8000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache_l>; }; - l2_cache_l: l2-cache { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x40000>; - cache-line-size = <64>; - cache-sets = <16>; - }; - cpu_b0: cpu@100 { device_type = "cpu"; compatible = "phytium,ftc664", "arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; clocks = <&scmi_dvfs 0>; - - i-cache-size = <0xc000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache_b>; }; cpu_b1: cpu@101 { @@ -100,22 +90,7 @@ cpu_b1: cpu@101 { reg = <0x0 0x100>; enable-method = "psci"; clocks = <&scmi_dvfs 1>; - - i-cache-size = <0xc000>; - i-cache-line-size = <64>; - d-cache-size = <0x8000>; - d-cache-line-size = <64>; - next-level-cache = <&l2_cache_b>; - }; - - l2_cache_b: l2-cache { - compatible = "cache"; - cache-level = <2>; - cache-unified; - cache-size = <0x100000>; - cache-line-size = <64>; - cache-sets = <16>; - }; + }; }; &soc { diff --git a/arch/arm64/configs/phytium_defconfig b/arch/arm64/configs/phytium_defconfig index 3214adf17e..e0066d0a1e 100644 --- a/arch/arm64/configs/phytium_defconfig +++ b/arch/arm64/configs/phytium_defconfig @@ -466,6 +466,7 @@ CONFIG_PLATFORM_MHU=y CONFIG_ARM_SMMU=y CONFIG_ARM_SMMU_V3=y CONFIG_REMOTEPROC=y +CONFIG_HOMO_REMOTEPROC=m CONFIG_RPMSG_CHAR=y CONFIG_RPMSG_VIRTIO=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y diff --git a/drivers/gpio/gpio-phytium-platform.c b/drivers/gpio/gpio-phytium-platform.c index eebed60191..32f1215c65 100644 --- a/drivers/gpio/gpio-phytium-platform.c +++ b/drivers/gpio/gpio-phytium-platform.c @@ -117,6 +117,10 @@ static int phytium_gpio_probe(struct platform_device *pdev) if (err) return err; + if (has_acpi_companion(dev)) { + acpi_gpiochip_request_interrupts(&gpio->gc); + } + platform_set_drvdata(pdev, gpio); dev_info(dev, "Phytium GPIO controller @%pa registered\n", &res->start); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 1968936e22..bbe50e920a 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -79,6 +79,7 @@ #define MACB_RBQPH 0x04D4 /* GEM register offsets. */ +#define GEM_NCR 0x0000 /* Network Control */ #define GEM_NCFGR 0x0004 /* Network Config */ #define GEM_USRIO 0x000c /* User IO */ #define GEM_DMACFG 0x0010 /* DMA Configuration */ @@ -260,6 +261,12 @@ #define MACB_SRTSM_OFFSET 15 #define MACB_OSSMODE_OFFSET 24 /* Enable One Step Synchro Mode */ #define MACB_OSSMODE_SIZE 1 +#define MACB_2PT5G_OFFSET 29 /* 2.5G operation selected */ +#define MACB_2PT5G_SIZE 1 + +/* GEM specific NCR bitfields. */ +#define GEM_ENABLE_HS_MAC_OFFSET 31 /* Use high speed MAC */ +#define GEM_ENABLE_HS_MAC_SIZE 1 /* Bitfields in NCFGR */ #define MACB_SPD_OFFSET 0 /* Speed */ @@ -538,6 +545,8 @@ #define GEM_RX_SCR_BYPASS_SIZE 1 #define GEM_TX_SCR_BYPASS_OFFSET 8 #define GEM_TX_SCR_BYPASS_SIZE 1 +#define GEM_RX_SYNC_RESET_OFFSET 2 +#define GEM_RX_SYNC_RESET_SIZE 1 #define GEM_TX_EN_OFFSET 1 #define GEM_TX_EN_SIZE 1 #define GEM_SIGNAL_OK_OFFSET 0 @@ -1139,6 +1148,7 @@ struct macb_config { struct clk **rx_clk, struct clk **tsu_clk); int (*init)(struct platform_device *pdev); int jumbo_max_len; + void (*sel_clk_hw)(struct macb *bp); }; struct tsu_incr { @@ -1274,6 +1284,9 @@ struct macb { int tx_bd_rd_prefetch; u32 rx_intr_mask; + + /* PHYTIUM sel clk */ + void (*sel_clk_hw)(struct macb *bp); }; #ifdef CONFIG_MACB_USE_HWSTAMP diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 584a47e3d3..5b20a14c66 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -82,6 +82,7 @@ #define HS_SPEED_2500M 2 #define HS_SPEED_5000M 3 #define HS_SPEED_10000M 4 +#define MACB_SERDES_RATE_5G 0 #define MACB_SERDES_RATE_10G 1 #define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) @@ -414,9 +415,79 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) netdev_err(dev, "adjusting tx_clk failed.\n"); } -static int phytium_gem_sel_clk(struct macb *bp) +static int phytium_mac_config(struct macb *bp) +{ + u32 old_ctrl, ctrl; + u32 old_ncr, ncr; + + netdev_dbg(bp->dev, "phytium mac config"); + + old_ncr = ncr = macb_readl(bp, NCR); + old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR); + + ncr &= ~(GEM_BIT(ENABLE_HS_MAC) | MACB_BIT(2PT5G)); + ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL) | MACB_BIT(SPD) | MACB_BIT(FD)); + if (macb_is_gem(bp)) + ctrl &= ~GEM_BIT(GBE); + + if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + ctrl |= GEM_BIT(PCSSEL) | GEM_BIT(SGMIIEN); + ncr |= MACB_BIT(2PT5G); + } else if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + ctrl |= GEM_BIT(PCSSEL); + ncr |= GEM_BIT(ENABLE_HS_MAC); + } + + if (bp->duplex) + ctrl |= MACB_BIT(FD); + + /* Apply the new configuration, if any */ + if (old_ctrl ^ ctrl) + macb_or_gem_writel(bp, NCFGR, ctrl); + + if (old_ncr ^ ncr) + macb_or_gem_writel(bp, NCR, ncr); + + return 0; +} + +static void phytium_usx_pcs_link_up(struct macb *bp) +{ + u32 config; + + if (bp->phy_interface != PHY_INTERFACE_MODE_USXGMII && + bp->phy_interface != PHY_INTERFACE_MODE_5GBASER) + return; + + netdev_dbg(bp->dev, "macb usx pcs link up"); + + config = gem_readl(bp, USX_CONTROL); + if (bp->speed == SPEED_10000) { + config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_10G, config); + config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_10000M, config); + } else if (bp->speed == SPEED_5000) { + config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_5G, config); + config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_5000M, config); + } + + config &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS)); + // reset + config |= GEM_BIT(RX_SYNC_RESET); + + gem_writel(bp, USX_CONTROL, config); + + //enable rx and tx + config &= ~(GEM_BIT(RX_SYNC_RESET)); + config |= GEM_BIT(SIGNAL_OK) | GEM_BIT(TX_EN); + + gem_writel(bp, USX_CONTROL, config); +} + +static void phytium_pe220x_sel_clk(struct macb *bp) { int speed = 0; + dev_dbg(&bp->pdev->dev, "phytium pe220x sel clk config\n"); if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { if (bp->speed == SPEED_10000) { @@ -426,7 +497,15 @@ static int phytium_gem_sel_clk(struct macb *bp) gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ speed = HS_SPEED_10000M; } - } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + if (bp->speed == SPEED_5000) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); /*0x1c10*/ + speed = HS_SPEED_5000M; + } + } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { if (bp->speed == SPEED_2500) { gem_writel(bp, DIV_SEL0_LN, 0x1); /*0x1c08*/ gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ @@ -442,7 +521,9 @@ static int phytium_gem_sel_clk(struct macb *bp) gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ speed = HS_SPEED_2500M; - } else if (bp->speed == SPEED_1000) { + } + } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (bp->speed == SPEED_1000) { gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/ gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ @@ -525,8 +606,7 @@ static int phytium_gem_sel_clk(struct macb *bp) /*HS_MAC_CONFIG(0x0050) provide rate to the external*/ gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, speed, gem_readl(bp, HS_MAC_CONFIG))); - - return 0; + return; } static void macb_handle_link_change(struct net_device *dev) @@ -584,8 +664,8 @@ static void macb_handle_link_change(struct net_device *dev) macb_set_tx_clk(bp->tx_clk, phydev->speed, dev); /* phytium need hwclock */ - if (bp->caps & MACB_CAPS_SEL_CLK_HW) - phytium_gem_sel_clk(bp); + if ((bp->caps & MACB_CAPS_SEL_CLK_HW) && bp->sel_clk_hw) + bp->sel_clk_hw(bp); netif_carrier_on(dev); netdev_info(dev, "link up (%d/%s)\n", @@ -2385,31 +2465,6 @@ static void macb_configure_dma(struct macb *bp) } } -static int macb_usx_pcs_config(struct macb *bp) -{ - gem_writel(bp, USX_CONTROL, gem_readl(bp, USX_CONTROL) | - GEM_BIT(SIGNAL_OK)); - - return 0; -} - -static void macb_usx_pcs_link_up(struct macb *bp) -{ - u32 config; - - config = gem_readl(bp, USX_CONTROL); - if (bp->speed == SPEED_10000) { - gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_10000M, - gem_readl(bp, HS_MAC_CONFIG))); - config = GEM_BFINS(SERDES_RATE, MACB_SERDES_RATE_10G, config); - config = GEM_BFINS(USX_CTRL_SPEED, HS_SPEED_10000M, config); - } - - config &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS)); - config |= GEM_BIT(TX_EN); - gem_writel(bp, USX_CONTROL, config); -} - static void macb_init_hw(struct macb *bp) { struct macb_queue *queue; @@ -2441,10 +2496,15 @@ static void macb_init_hw(struct macb *bp) if ((bp->caps & MACB_CAPS_JUMBO) && bp->jumbo_max_len) gem_writel(bp, JML, bp->jumbo_max_len); - if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { - macb_usx_pcs_config(bp); + if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_5GBASER || + bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + /* phytium need hwclock */ + if (bp->caps & MACB_CAPS_SEL_CLK_HW) + bp->sel_clk_hw(bp); + phytium_mac_config(bp); if (bp->link) - macb_usx_pcs_link_up(bp); + phytium_usx_pcs_link_up(bp); } else { bp->speed = SPEED_10; bp->duplex = DUPLEX_HALF; @@ -4194,7 +4254,7 @@ static const struct macb_config zynq_config = { .init = macb_init, }; -static const struct macb_config phytium_config = { +static const struct macb_config phytium_pe220x_config = { .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | MACB_CAPS_GEM_HAS_PTP | @@ -4204,6 +4264,7 @@ static const struct macb_config phytium_config = { .clk_init = macb_clk_init, .init = macb_init, .jumbo_max_len = 16360, + .sel_clk_hw = phytium_pe220x_sel_clk, }; static const struct of_device_id macb_dt_ids[] = { @@ -4221,7 +4282,7 @@ static const struct of_device_id macb_dt_ids[] = { { .compatible = "cdns,emac", .data = &emac_config }, { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config}, { .compatible = "cdns,zynq-gem", .data = &zynq_config }, - { .compatible = "cdns,phytium-gem", .data = &phytium_config }, + { .compatible = "cdns,phytium-gem", .data = &phytium_pe220x_config }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, macb_dt_ids); @@ -4229,7 +4290,7 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids); #ifdef CONFIG_ACPI static const struct acpi_device_id macb_acpi_ids[] = { - { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_config }, + { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_pe220x_config }, { } }; @@ -4360,6 +4421,8 @@ static int macb_probe(struct platform_device *pdev) bp->tsu_clk = tsu_clk; if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; + if (macb_config) + bp->sel_clk_hw = macb_config->sel_clk_hw; bp->wol = 0; if (device_property_read_bool(&pdev->dev, "magic-packet")) @@ -4437,6 +4500,18 @@ static int macb_probe(struct platform_device *pdev) bp->speed = SPEED_10000; } + if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + bp->link = 1; + bp->duplex = 1; + bp->speed = SPEED_5000; + } + + if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + bp->link = 1; + bp->duplex = 1; + bp->speed = SPEED_2500; + } + /* IP specific init */ err = init(pdev); if (err) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 052d4dd347..7ce83c5754 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -178,6 +178,14 @@ config ST_REMOTEPROC processor framework. This can be either built-in or a loadable module. +config HOMO_REMOTEPROC + tristate "homogeneous remoteproc support" + select RPMSG_VIRTIO + select RPMSG_CHAR + help + Say y here to support homogeneous processors via the remote processor framework. + This can be either built-in or a loadable module. + config ST_SLIM_REMOTEPROC tristate diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 03332fa7e2..78122c1e44 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -25,3 +25,4 @@ qcom_wcnss_pil-y += qcom_wcnss.o qcom_wcnss_pil-y += qcom_wcnss_iris.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o +obj-$(CONFIG_HOMO_REMOTEPROC) += homo_remoteproc.o diff --git a/drivers/remoteproc/homo_remoteproc.c b/drivers/remoteproc/homo_remoteproc.c new file mode 100644 index 0000000000..4bc919ace3 --- /dev/null +++ b/drivers/remoteproc/homo_remoteproc.c @@ -0,0 +1,326 @@ +/* + * Homogeneous Remote Processor Control Driver + * + * Copyright (C) 2022 Phytium Technology Co., Ltd. - All Rights Reserved + * Author: Shaojun Yang + * + * This program is free software; you can redistribute it and/or modify it under the terms + * of the GNU General Public License version 2 as published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "remoteproc_internal.h" + +#define RPROC_RESOURCE_ENTRIES 8 + +#define PSCI_VERSION 0x84000000 +#define CPU_SUSPEND 0xc4000001 +#define CPU_OFF 0x84000002 +#define CPU_ON 0xc4000003 +#define AFFINITY_INFO 0xc4000004 +#define MIGRATE 0xc4000005 + +static typeof(ioremap_page_range) *ioremap_page_range_sym; +static typeof(__flush_dcache_area) *__flush_dcache_area_sym; + +/* Resource table for the homo remote processors */ +struct homo_resource_table { + unsigned int version; + unsigned int num; + unsigned int reserved[2]; + unsigned int offset[RPROC_RESOURCE_ENTRIES]; + + /* Note: linux kenrel 'struct fw_rsc_vdev' has no 'type' field, here add to align data structre */ + uint32_t type; + /* rpmsg vdev entry */ + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; +}; + +struct homo_rproc { + struct rproc *rproc; + struct homo_resource_table *rsc; + + u64 phys_addr; + void *addr; + u64 size; + + int irq; + int cpu; +}; + +static struct homo_rproc *g_priv; +static struct work_struct workqueue; + +static unsigned int cpuid = 3; +module_param(cpuid, uint, 0); +MODULE_PARM_DESC(cpuid, "Cpu logical number used exclusively by the remote processor. default is 3."); + +static unsigned int sgi = 9; +module_param(sgi, uint, 0); +MODULE_PARM_DESC(sgi, "GIC SGI interrupt number for communication with remote processor. default is 9"); + +#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) + +void gicv3_ipi_send_single(int irq, u64 mpidr) +{ + u16 tlist = 0; + u64 cluster_id; + u64 sgi1r; + + /* Ensure stores to Normal memory are visible to other CPUs before sending the IPI. */ + wmb(); + + cluster_id = mpidr & ~0xffUL; + tlist |= 1 << (mpidr & 0xf); + + /* Send the IPIs for the target list of this cluster */ + sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3) | + MPIDR_TO_SGI_AFFINITY(cluster_id, 2) | + irq << 24 | + MPIDR_TO_SGI_AFFINITY(cluster_id, 1) | tlist); + gic_write_sgi1r(sgi1r); + + /* Force the above writes to ICC_SGI1R_EL1 to be executed */ + isb(); +} + +static void homo_rproc_vq_irq(struct work_struct *work) +{ + struct homo_rproc *priv = g_priv; + struct homo_resource_table *rsc = priv->rsc; + struct rproc *rproc = priv->rproc; + + rproc_vq_interrupt(rproc, rsc->rpmsg_vring0.notifyid); +} + +static void homo_rproc_interrupt(void) +{ + schedule_work(&workqueue); +} + +static int homo_rproc_start(struct rproc *rproc) +{ + int err; + struct homo_rproc *priv = rproc->priv; + int phys_cpuid = cpu_logical_map(priv->cpu); + struct arm_smccc_res smc_res; + + err = psci_ops.affinity_info(phys_cpuid, 0); + if (err == 0) + cpu_down(priv->cpu); + + INIT_WORK(&workqueue, homo_rproc_vq_irq); + + priv->rsc = (struct homo_resource_table *)rproc->table_ptr; + + /* ARMv8 requires to clean D-cache and invalidate I-cache for memory containing new instructions. */ + flush_icache_range((unsigned long)priv->addr, (unsigned long)(priv->addr + priv->size)); + + arm_smccc_smc(CPU_ON, phys_cpuid, (unsigned long long)priv->phys_addr, 0, 0, 0, 0, 0, &smc_res); + + return smc_res.a0; +} + +static int homo_rproc_stop(struct rproc *rproc) +{ + int err; + struct homo_rproc *priv = rproc->priv; + + err = psci_ops.affinity_info(cpu_logical_map(priv->cpu), 0); + if (err == 1) + cpu_up(priv->cpu); + + return 0; +} + +static void *homo_rproc_da_to_va(struct rproc *rproc, u64 da, int len) +{ + struct homo_rproc *priv = rproc->priv; + + return priv->addr + (da - rproc->bootaddr); +} + +static void homo_rproc_kick(struct rproc *rproc, int vqid) +{ + struct homo_rproc *priv = rproc->priv; + + if (rproc->state == RPROC_RUNNING) + gicv3_ipi_send_single(priv->irq, cpu_logical_map(priv->cpu)); + + return ; +} + +static const struct rproc_ops homo_rproc_ops = { + .start = homo_rproc_start, + .stop = homo_rproc_stop, + .kick = homo_rproc_kick, + .da_to_va = homo_rproc_da_to_va, +}; + +static void *homo_rproc_ioremap(phys_addr_t phys, + unsigned long virt, unsigned long size) +{ + struct vm_struct *vma; + + size = PAGE_ALIGN(size); + + if (virt) + vma = __get_vm_area(size, VM_IOREMAP, virt, virt + size + PAGE_SIZE); + else + vma = __get_vm_area(size, VM_IOREMAP, VMALLOC_START, VMALLOC_END); + if (!vma) + return NULL; + + vma->phys_addr = phys; + + if (ioremap_page_range_sym((unsigned long)vma->addr, (unsigned long)vma->addr + size, phys, PAGE_KERNEL_EXEC)) { + vunmap(vma->addr); + return NULL; + } + + return vma->addr; +} + +static int homo_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *np_mem; + struct rproc *rproc; + struct homo_rproc *priv; + u32 phandle; + int ret; + + rproc = rproc_alloc(dev, np->name, &homo_rproc_ops, + "openamp_core0.elf", sizeof(*priv)); + if (!rproc) + return -ENOMEM; + + platform_set_drvdata(pdev, rproc); + + priv = g_priv = rproc->priv; + priv->rproc = rproc; + + /* Lookup kernel symbol that is not exported out. */ + ioremap_page_range_sym = (void *)kallsyms_lookup_name("ioremap_page_range"); + if (ioremap_page_range_sym == NULL) { + dev_err(dev, "Symbol 'ioremap_page_range' not found.\n"); + return -1; + } + + __flush_dcache_area_sym = (void *)kallsyms_lookup_name("__flush_dcache_area"); + if (__flush_dcache_area_sym == NULL) { + dev_err(dev, "Symbol '__flush_dcache_area' not found.\n"); + return -1; + } + + ret = of_property_read_u32(np, "memory-region", &phandle); + if (ret) { + dev_err(dev, "Can't find memory-region for Baremetal\n"); + return ret; + } + + np_mem = of_find_node_by_phandle(phandle); + if (!np_mem) { + dev_err(dev, "Cant' find corresponding memory-region\n"); + return -EINVAL; + } else { + int n = of_property_count_elems_of_size(np_mem, "reg", sizeof(u64)); + + if (n != 2) { + dev_err(dev, "Memory address and size not found in devicetree!\n"); + return -EINVAL; + } + + of_property_read_u64_index(np_mem, "reg", 0, &priv->phys_addr); + of_property_read_u64_index(np_mem, "reg", 1, &priv->size); + + dev_info(dev, "Baremetal Address: %llx, size: %llx\n", + priv->phys_addr, priv->size); + } + + priv->rsc = NULL; + priv->addr = NULL; + + /* The following values can be modified through module parameters */ + priv->irq = sgi; + priv->cpu = cpuid; + + /* Map physical memory region reserved for homo remote processor. */ + priv->addr = homo_rproc_ioremap(priv->phys_addr, 0, priv->size); + if (!priv->addr) { + dev_err(dev, "ioremap failed\n"); + return -1; + } + dev_info(dev, "ioremap: phys_addr = %016llx, addr = %llx, size = %lld\n", + priv->phys_addr, (u64)(priv->addr), priv->size); + + rproc_set_handle_irq(homo_rproc_interrupt); + + rproc->auto_boot = false; + rproc->has_iommu = false; + + rproc_add(rproc); + + return 0; +} + +static int homo_rproc_remove(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct homo_rproc *priv = rproc->priv; + + rproc_del(rproc); + of_reserved_mem_device_release(&pdev->dev); + rproc_free(rproc); + + if (priv->addr) { + vunmap(priv->addr); + priv->addr = NULL; + } + + return 0; +} + +static const struct of_device_id homo_rproc_ids[] = { + { .compatible = "phytium,rproc", }, + { } +}; +MODULE_DEVICE_TABLE(of, homo_rproc_ids); + +static struct platform_driver homo_rproc_driver = { + .probe = homo_rproc_probe, + .remove = homo_rproc_remove, + .driver = { + .name = "homo-rproc", + .of_match_table = of_match_ptr(homo_rproc_ids), + }, +}; +module_platform_driver(homo_rproc_driver); + +MODULE_DESCRIPTION("Homogeneous Remote Processor Control Driver"); +MODULE_AUTHOR("Shaojun Yang "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/phy.h b/include/linux/phy.h index 34e6d4bbc9..0b32b1eba2 100755 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -84,6 +84,7 @@ typedef enum { PHY_INTERFACE_MODE_TRGMII, PHY_INTERFACE_MODE_1000BASEX, PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_5GBASER, PHY_INTERFACE_MODE_RXAUI, PHY_INTERFACE_MODE_XAUI, /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */ @@ -155,6 +156,8 @@ static inline const char *phy_modes(phy_interface_t interface) return "1000base-x"; case PHY_INTERFACE_MODE_2500BASEX: return "2500base-x"; + case PHY_INTERFACE_MODE_5GBASER: + return "5gbase-r"; case PHY_INTERFACE_MODE_RXAUI: return "rxaui"; case PHY_INTERFACE_MODE_XAUI: -- Gitee