From f45e756958099c35d6afb746df1d40a1c6302cfc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 07 Nov 2023 06:20:23 +0000
Subject: [PATCH] enable wifi gpio
---
kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 264 insertions(+), 5 deletions(-)
diff --git a/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 870e60a..9f87f16 100644
--- a/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -24,6 +24,7 @@
#include <linux/of_net.h>
#include <linux/gpio.h>
#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -77,6 +78,7 @@
struct clk *pclk_mac;
struct clk *clk_phy;
struct clk *pclk_xpcs;
+ struct clk *clk_xpcs_eee;
struct reset_control *phy_reset;
@@ -85,6 +87,8 @@
struct regmap *grf;
struct regmap *xpcs;
+
+ unsigned char otp_data;
};
/* XPCS */
@@ -1322,6 +1326,208 @@
.set_rmii_speed = rk3399_set_rmii_speed,
};
+#define RK3528_VO_GRF_GMAC_CON 0X60018
+#define RK3528_VPU_GRF_GMAC_CON5 0X40018
+#define RK3528_VPU_GRF_GMAC_CON6 0X4001c
+
+#define RK3528_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15)
+#define RK3528_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15)
+#define RK3528_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14)
+#define RK3528_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14)
+
+#define RK3528_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3528_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0xFF, 0)
+
+#define RK3528_GMAC0_PHY_INTF_SEL_RMII GRF_BIT(1)
+#define RK3528_GMAC1_PHY_INTF_SEL_RGMII GRF_CLR_BIT(8)
+#define RK3528_GMAC1_PHY_INTF_SEL_RMII GRF_BIT(8)
+
+#define RK3528_GMAC1_CLK_SELET_CRU GRF_CLR_BIT(12)
+#define RK3528_GMAC1_CLK_SELET_IO GRF_BIT(12)
+
+#define RK3528_GMAC0_CLK_RMII_DIV2 GRF_BIT(3)
+#define RK3528_GMAC0_CLK_RMII_DIV20 GRF_CLR_BIT(3)
+#define RK3528_GMAC1_CLK_RMII_DIV2 GRF_BIT(10)
+#define RK3528_GMAC1_CLK_RMII_DIV20 GRF_CLR_BIT(10)
+
+#define RK3528_GMAC1_CLK_RGMII_DIV1 \
+ (GRF_CLR_BIT(11) | GRF_CLR_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV5 \
+ (GRF_BIT(11) | GRF_BIT(10))
+#define RK3528_GMAC1_CLK_RGMII_DIV50 \
+ (GRF_BIT(11) | GRF_CLR_BIT(10))
+
+#define RK3528_GMAC0_CLK_RMII_GATE GRF_BIT(2)
+#define RK3528_GMAC0_CLK_RMII_NOGATE GRF_CLR_BIT(2)
+#define RK3528_GMAC1_CLK_RMII_GATE GRF_BIT(9)
+#define RK3528_GMAC1_CLK_RMII_NOGATE GRF_CLR_BIT(9)
+
+#define RK3528_VO_GRF_MACPHY_CON0 0X6001c
+#define RK3528_VO_GRF_MACPHY_CON1 0X60020
+
+#define RK3528_VO_GRF_MACPHY_SHUTDOWN GRF_BIT(1)
+#define RK3528_VO_GRF_MACPHY_POWERUP GRF_CLR_BIT(1)
+#define RK3528_VO_GRF_MACPHY_INTERNAL_RMII_SEL GRF_BIT(6)
+#define RK3528_VO_GRF_MACPHY_24M_CLK_SEL (GRF_BIT(8) | GRF_BIT(9))
+#define RK3528_VO_GRF_MACPHY_PHY_ID GRF_BIT(11)
+
+#define RK3528_VO_GRF_MACPHY_BGS HIWORD_UPDATE(0x0, 0xf, 0)
+
+static void rk3528_set_to_rgmii(struct rk_priv_data *bsp_priv,
+ int tx_delay, int rx_delay)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+
+ if (IS_ERR(bsp_priv->grf)) {
+ dev_err(dev, "Missing rockchip,grf property\n");
+ return;
+ }
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RGMII);
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ DELAY_ENABLE(RK3528, tx_delay, rx_delay));
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON6,
+ DELAY_VALUE(RK3528, tx_delay, rx_delay));
+}
+
+static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int id = bsp_priv->bus_id;
+
+ if (IS_ERR(bsp_priv->grf)) {
+ dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+ return;
+ }
+
+ if (id == 1)
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5,
+ RK3528_GMAC1_PHY_INTF_SEL_RMII);
+ else
+ regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON,
+ RK3528_GMAC0_PHY_INTF_SEL_RMII);
+}
+
+static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int val = 0;
+
+ switch (speed) {
+ case 10:
+ val = RK3528_GMAC1_CLK_RGMII_DIV50;
+ break;
+ case 100:
+ val = RK3528_GMAC1_CLK_RGMII_DIV5;
+ break;
+ case 1000:
+ val = RK3528_GMAC1_CLK_RGMII_DIV1;
+ break;
+ default:
+ goto err;
+ }
+
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, val);
+ return;
+err:
+ dev_err(dev, "unknown RGMII speed value for GMAC speed=%d", speed);
+}
+
+static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+ struct device *dev = &bsp_priv->pdev->dev;
+ unsigned int val, offset, id = bsp_priv->bus_id;
+
+ switch (speed) {
+ case 10:
+ val = (id == 1) ? RK3528_GMAC1_CLK_RMII_DIV20 :
+ RK3528_GMAC0_CLK_RMII_DIV20;
+ break;
+ case 100:
+ val = (id == 1) ? RK3528_GMAC1_CLK_RMII_DIV2 :
+ RK3528_GMAC0_CLK_RMII_DIV2;
+ break;
+ default:
+ goto err;
+ }
+
+ offset = (id == 1) ? RK3528_VPU_GRF_GMAC_CON5 : RK3528_VO_GRF_GMAC_CON;
+ regmap_write(bsp_priv->grf, offset, val);
+
+ return;
+err:
+ dev_err(dev, "unknown RMII speed value for GMAC speed=%d", speed);
+}
+
+static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv,
+ bool input, bool enable)
+{
+ unsigned int value, id = bsp_priv->bus_id;
+
+ if (id == 1) {
+ value = input ? RK3528_GMAC1_CLK_SELET_IO :
+ RK3528_GMAC1_CLK_SELET_CRU;
+ value |= enable ? RK3528_GMAC1_CLK_RMII_NOGATE :
+ RK3528_GMAC1_CLK_RMII_GATE;
+ regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, value);
+ } else {
+ value = enable ? RK3528_GMAC0_CLK_RMII_NOGATE :
+ RK3528_GMAC0_CLK_RMII_GATE;
+ regmap_write(bsp_priv->grf, RK3528_VO_GRF_GMAC_CON, value);
+ }
+}
+
+static void rk3528_integrated_sphy_power(struct rk_priv_data *priv, bool up)
+{
+ struct device *dev = &priv->pdev->dev;
+ unsigned int id = priv->bus_id;
+
+ /* Only GMAC0 support integrated phy */
+ if (id > 0)
+ return;
+
+ if (IS_ERR(priv->grf) || !priv->phy_reset) {
+ dev_err(dev, "%s: Missing rockchip,grf or phy_reset property\n",
+ __func__);
+ return;
+ }
+
+ if (up) {
+ unsigned int bgs = RK3528_VO_GRF_MACPHY_BGS;
+
+ reset_control_assert(priv->phy_reset);
+ udelay(20);
+ regmap_write(priv->grf, RK3528_VO_GRF_MACPHY_CON0,
+ RK3528_VO_GRF_MACPHY_POWERUP |
+ RK3528_VO_GRF_MACPHY_INTERNAL_RMII_SEL |
+ RK3528_VO_GRF_MACPHY_24M_CLK_SEL |
+ RK3528_VO_GRF_MACPHY_PHY_ID);
+
+ if (priv->otp_data > 0)
+ bgs = HIWORD_UPDATE(priv->otp_data, 0xf, 0);
+
+ regmap_write(priv->grf, RK3528_VO_GRF_MACPHY_CON1, bgs);
+ usleep_range(10 * 1000, 12 * 1000);
+ reset_control_deassert(priv->phy_reset);
+ usleep_range(50 * 1000, 60 * 1000);
+ } else {
+ regmap_write(priv->grf, RK3528_VO_GRF_MACPHY_CON0,
+ RK3528_VO_GRF_MACPHY_SHUTDOWN);
+ }
+}
+
+static const struct rk_gmac_ops rk3528_ops = {
+ .set_to_rgmii = rk3528_set_to_rgmii,
+ .set_to_rmii = rk3528_set_to_rmii,
+ .set_rgmii_speed = rk3528_set_rgmii_speed,
+ .set_rmii_speed = rk3528_set_rmii_speed,
+ .set_clock_selection = rk3528_set_clock_selection,
+ .integrated_phy_power = rk3528_integrated_sphy_power,
+};
+
#define RK3568_GRF_GMAC0_CON0 0X0380
#define RK3568_GRF_GMAC0_CON1 0X0384
#define RK3568_GRF_GMAC1_CON0 0X0388
@@ -1708,8 +1914,10 @@
bsp_priv->phy_iface == PHY_INTERFACE_MODE_QSGMII) {
bsp_priv->pclk_xpcs = devm_clk_get(dev, "pclk_xpcs");
if (IS_ERR(bsp_priv->pclk_xpcs))
- dev_err(dev, "cannot get clock %s\n",
- "pclk_xpcs");
+ dev_err(dev, "cannot get clock %s\n", "pclk_xpcs");
+ bsp_priv->clk_xpcs_eee = devm_clk_get(dev, "clk_xpcs_eee");
+ if (IS_ERR(bsp_priv->clk_xpcs_eee))
+ dev_err(dev, "cannot get clock %s\n", "clk_xpcs_eee");
}
bsp_priv->clk_mac_speed = devm_clk_get(dev, "clk_mac_speed");
@@ -1777,6 +1985,9 @@
if (!IS_ERR(bsp_priv->pclk_xpcs))
clk_prepare_enable(bsp_priv->pclk_xpcs);
+ if (!IS_ERR(bsp_priv->clk_xpcs_eee))
+ clk_prepare_enable(bsp_priv->clk_xpcs_eee);
+
if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
bsp_priv->ops->set_clock_selection(bsp_priv, bsp_priv->clock_input,
true);
@@ -1813,6 +2024,8 @@
clk_disable_unprepare(bsp_priv->clk_mac_speed);
clk_disable_unprepare(bsp_priv->pclk_xpcs);
+
+ clk_disable_unprepare(bsp_priv->clk_xpcs_eee);
/**
* if (!IS_ERR(bsp_priv->clk_mac))
@@ -1926,10 +2139,34 @@
bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
"phy-is-integrated");
if (bsp_priv->integrated_phy) {
+ unsigned char *efuse_buf;
+ struct nvmem_cell *cell;
+ size_t len;
+
bsp_priv->phy_reset = of_reset_control_get(plat->phy_node, NULL);
if (IS_ERR(bsp_priv->phy_reset)) {
dev_err(&pdev->dev, "No PHY reset control found.\n");
bsp_priv->phy_reset = NULL;
+ }
+
+ /* Read bgs from OTP if it exists */
+ cell = nvmem_cell_get(dev, "bgs");
+ if (IS_ERR(cell)) {
+ if (PTR_ERR(cell) != -EPROBE_DEFER)
+ dev_info(dev, "failed to get bgs cell: %ld, use default\n",
+ PTR_ERR(cell));
+ else
+ return ERR_CAST(cell);
+ } else {
+ efuse_buf = nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
+ if (!IS_ERR(efuse_buf)) {
+ if (len == 1)
+ bsp_priv->otp_data = efuse_buf[0];
+ kfree(efuse_buf);
+ } else {
+ dev_err(dev, "failed to get efuse buf, use default\n");
+ }
}
}
}
@@ -2109,13 +2346,16 @@
{
}
+
+static unsigned char macaddr[6];
+extern ssize_t at24_mac_read(unsigned char* addr);
void rk_get_eth_addr(void *priv, unsigned char *addr)
{
struct rk_priv_data *bsp_priv = priv;
struct device *dev = &bsp_priv->pdev->dev;
unsigned char ethaddr[ETH_ALEN * MAX_ETH] = {0};
- int ret, id = bsp_priv->bus_id;
-
+ int ret,i, id = bsp_priv->bus_id;
+#if 0
rk_devinfo_get_eth_mac(addr);
if (is_valid_ether_addr(addr))
goto out;
@@ -2146,6 +2386,22 @@
} else {
memcpy(addr, ðaddr[id * ETH_ALEN], ETH_ALEN);
}
+#endif
+ #if 1
+ if (at24_mac_read(macaddr) > 0) {
+ printk("ben %s: at24_mac_read Success!! \n", __func__);
+ memcpy(addr, macaddr, 6);
+
+ printk("Read the Ethernet MAC address from :");
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", addr[i]);
+
+ printk("%2.2x\n", addr[i]);
+ } else {
+ printk("ben %s: at24_mac_read Failed!! \n", __func__);
+ goto out;
+ }
+ #endif
out:
dev_err(dev, "%s: mac address: %pM\n", __func__, addr);
@@ -2284,6 +2540,9 @@
#ifdef CONFIG_CPU_RK3399
{ .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
#endif
+#ifdef CONFIG_CPU_RK3528
+ { .compatible = "rockchip,rk3528-gmac", .data = &rk3528_ops },
+#endif
#ifdef CONFIG_CPU_RK3568
{ .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
#endif
@@ -2306,7 +2565,7 @@
.of_match_table = rk_gmac_dwmac_match,
},
};
-module_platform_driver(rk_gmac_dwmac_driver);
+module_platform_driver1(rk_gmac_dwmac_driver);
MODULE_AUTHOR("Chen-Zhi (Roger Chen) <roger.chen@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK3288 DWMAC specific glue layer");
--
Gitblit v1.6.2