mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 07:22:33 +00:00
4070e2a64c
This target adds support for the StarFive JH7100 and JH7110 SoCs, based on 6.1, as well as a couple boards equipped with these. Specifications: SoCs: JH7100: - StarFive JH7100 dual-core RISC-V (U74, RC64GC) - additional monitoring (S7) and control (E24) cores - 2Mb L2 cache JH7110: - StarFive JH7110 quad-core RISC-V (U74, RV64GC) - additional monitoring (S7) and control (E24) cores - 2Mb L2 cache Boards: VisionFive1: - JH7100 @ 1GHz - Memory: 8Gb LPDDR4 - 4x USB3.0 - 1x GBit ethernet - AMPak 6236 wifi / bluetooth - audio - powered via USB-C VisionFive2: - JH7110 @ 1.5GHz - Memory: 2/4/8Gb DDR4 - 2x Gbit ethernet - 2x USB3.0 / 2x USB2.0 - eMMC / SDIO - various multimedia input/outputs (MIPI CSI, HDMI, audio) - M.2 key M slot - PoE support - powered via USB-C Installation: Standard SD-card installation via dd-ing the generated image to an SD-card of at least 256Mb. Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
251 lines
7.1 KiB
Diff
251 lines
7.1 KiB
Diff
From d900724fdae7c41a663b31e1ed9b8ba10b998e6f Mon Sep 17 00:00:00 2001
|
|
From: Minda Chen <minda.chen@starfivetech.com>
|
|
Date: Thu, 18 May 2023 19:27:47 +0800
|
|
Subject: [PATCH 090/122] phy: starfive: Add JH7110 PCIE 2.0 PHY driver
|
|
|
|
Add Starfive JH7110 SoC PCIe 2.0 PHY driver support.
|
|
PCIe 2.0 PHY default connect to PCIe controller.
|
|
PCIe PHY can connect to USB 3.0 controller.
|
|
|
|
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
|
|
---
|
|
drivers/phy/starfive/Kconfig | 10 ++
|
|
drivers/phy/starfive/Makefile | 1 +
|
|
drivers/phy/starfive/phy-jh7110-pcie.c | 204 +++++++++++++++++++++++++
|
|
3 files changed, 215 insertions(+)
|
|
create mode 100644 drivers/phy/starfive/phy-jh7110-pcie.c
|
|
|
|
--- a/drivers/phy/starfive/Kconfig
|
|
+++ b/drivers/phy/starfive/Kconfig
|
|
@@ -12,6 +12,16 @@ config PHY_STARFIVE_DPHY_RX
|
|
system. If M is selected, the module will be called
|
|
phy-starfive-dphy-rx.
|
|
|
|
+config PHY_STARFIVE_JH7110_PCIE
|
|
+ tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
|
|
+ select GENERIC_PHY
|
|
+ select USB_PHY
|
|
+ help
|
|
+ Enable this to support the StarFive PCIe 2.0 PHY,
|
|
+ or used as USB 3.0 PHY.
|
|
+ If M is selected, the module will be called
|
|
+ phy-jh7110-pcie.ko.
|
|
+
|
|
config PHY_STARFIVE_JH7110_USB
|
|
tristate "Starfive JH7110 USB 2.0 PHY support"
|
|
depends on USB_SUPPORT
|
|
--- a/drivers/phy/starfive/Makefile
|
|
+++ b/drivers/phy/starfive/Makefile
|
|
@@ -1,3 +1,4 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
obj-$(CONFIG_PHY_STARFIVE_DPHY_RX) += phy-starfive-dphy-rx.o
|
|
+obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
|
|
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
|
|
--- /dev/null
|
|
+++ b/drivers/phy/starfive/phy-jh7110-pcie.c
|
|
@@ -0,0 +1,204 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * StarFive JH7110 PCIe 2.0 PHY driver
|
|
+ *
|
|
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
|
|
+ * Author: Minda Chen <minda.chen@starfivetech.com>
|
|
+ */
|
|
+
|
|
+#include <linux/bits.h>
|
|
+#include <linux/clk.h>
|
|
+#include <linux/err.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/mfd/syscon.h>
|
|
+#include <linux/phy/phy.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/regmap.h>
|
|
+
|
|
+#define PCIE_KVCO_LEVEL_OFF 0x28
|
|
+#define PCIE_USB3_PHY_PLL_CTL_OFF 0x7c
|
|
+#define PCIE_KVCO_TUNE_SIGNAL_OFF 0x80
|
|
+#define PCIE_USB3_PHY_ENABLE BIT(4)
|
|
+#define PHY_KVCO_FINE_TUNE_LEVEL 0x91
|
|
+#define PHY_KVCO_FINE_TUNE_SIGNALS 0xc
|
|
+
|
|
+#define USB_PDRSTN_SPLIT BIT(17)
|
|
+
|
|
+#define PCIE_PHY_MODE BIT(20)
|
|
+#define PCIE_PHY_MODE_MASK GENMASK(21, 20)
|
|
+#define PCIE_USB3_BUS_WIDTH_MASK GENMASK(3, 2)
|
|
+#define PCIE_USB3_BUS_WIDTH BIT(3)
|
|
+#define PCIE_USB3_RATE_MASK GENMASK(6, 5)
|
|
+#define PCIE_USB3_RX_STANDBY_MASK BIT(7)
|
|
+#define PCIE_USB3_PHY_ENABLE BIT(4)
|
|
+
|
|
+struct jh7110_pcie_phy {
|
|
+ struct phy *phy;
|
|
+ struct regmap *stg_syscon;
|
|
+ struct regmap *sys_syscon;
|
|
+ void __iomem *regs;
|
|
+ u32 sys_phy_connect;
|
|
+ u32 stg_pcie_mode;
|
|
+ u32 stg_pcie_usb;
|
|
+ enum phy_mode mode;
|
|
+};
|
|
+
|
|
+static int phy_usb3_mode_set(struct jh7110_pcie_phy *data)
|
|
+{
|
|
+ if (!data->stg_syscon || !data->sys_syscon) {
|
|
+ dev_err(&data->phy->dev, "doesn't support usb3 mode\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_mode,
|
|
+ PCIE_PHY_MODE_MASK, PCIE_PHY_MODE);
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb,
|
|
+ PCIE_USB3_BUS_WIDTH_MASK, 0);
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb,
|
|
+ PCIE_USB3_PHY_ENABLE, PCIE_USB3_PHY_ENABLE);
|
|
+
|
|
+ /* Connect usb 3.0 phy mode */
|
|
+ regmap_update_bits(data->sys_syscon, data->sys_phy_connect,
|
|
+ USB_PDRSTN_SPLIT, 0);
|
|
+
|
|
+ /* Configuare spread-spectrum mode: down-spread-spectrum */
|
|
+ writel(PCIE_USB3_PHY_ENABLE, data->regs + PCIE_USB3_PHY_PLL_CTL_OFF);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void phy_pcie_mode_set(struct jh7110_pcie_phy *data)
|
|
+{
|
|
+ u32 val;
|
|
+
|
|
+ /* default is PCIe mode */
|
|
+ if (!data->stg_syscon || !data->sys_syscon)
|
|
+ return;
|
|
+
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_mode,
|
|
+ PCIE_PHY_MODE_MASK, 0);
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb,
|
|
+ PCIE_USB3_BUS_WIDTH_MASK,
|
|
+ PCIE_USB3_BUS_WIDTH);
|
|
+ regmap_update_bits(data->stg_syscon, data->stg_pcie_usb,
|
|
+ PCIE_USB3_PHY_ENABLE, 0);
|
|
+
|
|
+ regmap_update_bits(data->sys_syscon, data->sys_phy_connect,
|
|
+ USB_PDRSTN_SPLIT, 0);
|
|
+
|
|
+ val = readl(data->regs + PCIE_USB3_PHY_PLL_CTL_OFF);
|
|
+ val &= ~PCIE_USB3_PHY_ENABLE;
|
|
+ writel(val, data->regs + PCIE_USB3_PHY_PLL_CTL_OFF);
|
|
+}
|
|
+
|
|
+static void phy_kvco_gain_set(struct jh7110_pcie_phy *phy)
|
|
+{
|
|
+ /* PCIe Multi-PHY PLL KVCO Gain fine tune settings: */
|
|
+ writel(PHY_KVCO_FINE_TUNE_LEVEL, phy->regs + PCIE_KVCO_LEVEL_OFF);
|
|
+ writel(PHY_KVCO_FINE_TUNE_SIGNALS, phy->regs + PCIE_KVCO_TUNE_SIGNAL_OFF);
|
|
+}
|
|
+
|
|
+static int jh7110_pcie_phy_set_mode(struct phy *_phy,
|
|
+ enum phy_mode mode, int submode)
|
|
+{
|
|
+ struct jh7110_pcie_phy *phy = phy_get_drvdata(_phy);
|
|
+ int ret;
|
|
+
|
|
+ if (mode == phy->mode)
|
|
+ return 0;
|
|
+
|
|
+ switch (mode) {
|
|
+ case PHY_MODE_USB_HOST:
|
|
+ case PHY_MODE_USB_DEVICE:
|
|
+ case PHY_MODE_USB_OTG:
|
|
+ ret = phy_usb3_mode_set(phy);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ break;
|
|
+ case PHY_MODE_PCIE:
|
|
+ phy_pcie_mode_set(phy);
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ dev_dbg(&_phy->dev, "Changing phy mode to %d\n", mode);
|
|
+ phy->mode = mode;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct phy_ops jh7110_pcie_phy_ops = {
|
|
+ .set_mode = jh7110_pcie_phy_set_mode,
|
|
+ .owner = THIS_MODULE,
|
|
+};
|
|
+
|
|
+static int jh7110_pcie_phy_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct jh7110_pcie_phy *phy;
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct phy_provider *phy_provider;
|
|
+ u32 args[2];
|
|
+
|
|
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
|
+ if (!phy)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ phy->regs = devm_platform_ioremap_resource(pdev, 0);
|
|
+ if (IS_ERR(phy->regs))
|
|
+ return PTR_ERR(phy->regs);
|
|
+
|
|
+ phy->phy = devm_phy_create(dev, NULL, &jh7110_pcie_phy_ops);
|
|
+ if (IS_ERR(phy->phy))
|
|
+ return dev_err_probe(dev, PTR_ERR(phy->regs),
|
|
+ "Failed to map phy base\n");
|
|
+
|
|
+ phy->sys_syscon =
|
|
+ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
|
|
+ "starfive,sys-syscon",
|
|
+ 1, args);
|
|
+
|
|
+ if (!IS_ERR_OR_NULL(phy->sys_syscon))
|
|
+ phy->sys_phy_connect = args[0];
|
|
+ else
|
|
+ phy->sys_syscon = NULL;
|
|
+
|
|
+ phy->stg_syscon =
|
|
+ syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
|
|
+ "starfive,stg-syscon",
|
|
+ 2, args);
|
|
+
|
|
+ if (!IS_ERR_OR_NULL(phy->stg_syscon)) {
|
|
+ phy->stg_pcie_mode = args[0];
|
|
+ phy->stg_pcie_usb = args[1];
|
|
+ } else {
|
|
+ phy->stg_syscon = NULL;
|
|
+ }
|
|
+
|
|
+ phy_kvco_gain_set(phy);
|
|
+
|
|
+ phy_set_drvdata(phy->phy, phy);
|
|
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
|
+
|
|
+ return PTR_ERR_OR_ZERO(phy_provider);
|
|
+}
|
|
+
|
|
+static const struct of_device_id jh7110_pcie_phy_of_match[] = {
|
|
+ { .compatible = "starfive,jh7110-pcie-phy" },
|
|
+ { /* sentinel */ },
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, jh7110_pcie_phy_of_match);
|
|
+
|
|
+static struct platform_driver jh7110_pcie_phy_driver = {
|
|
+ .probe = jh7110_pcie_phy_probe,
|
|
+ .driver = {
|
|
+ .of_match_table = jh7110_pcie_phy_of_match,
|
|
+ .name = "jh7110-pcie-phy",
|
|
+ }
|
|
+};
|
|
+module_platform_driver(jh7110_pcie_phy_driver);
|
|
+
|
|
+MODULE_DESCRIPTION("StarFive JH7110 PCIe 2.0 PHY driver");
|
|
+MODULE_AUTHOR("Minda Chen <minda.chen@starfivetech.com>");
|
|
+MODULE_LICENSE("GPL");
|