From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 19 Jun 2020 17:27:27 +0200 Subject: [ARCHEOLOGY] Introducing Rockchip RK322X SoC support (#2032) > X-Git-Archeology: > recovered message: > * Introducing Rockchip rk322x SoC support > X-Git-Archeology: > recovered message: > Main features: > X-Git-Archeology: > recovered message: > - Legacy kernel flavour based upon stable v2.x rk3288 Rockchip branch (https://github.com/rockchip-linux/kernel/tree/stable-4.4-rk3288-linux-v2.x) > X-Git-Archeology: > recovered message: > - Current kernel flavour based on mainline 5.6.y kernel > X-Git-Archeology: > recovered message: > - Mainline u-boot (v2020.04) > X-Git-Archeology: > recovered message: > - Single generic tv box target (rk322x-box) which boots on all the known tv boxes > X-Git-Archeology: > recovered message: > - Hardware devices (eMMC/NAND, led wiring configuration, SoC variant selection) modulation done by user at runtime via device tree overlays - a script (rk322x-config) is provided for autodetection and simple configuration by inexperienced users; > X-Git-Archeology: > recovered message: > - Bits added to armbian-hardware-optimization to set affinity for irq handlers > X-Git-Archeology: > recovered message: > - rk322x-box targets already added to targets.conf for automatic image creation > X-Git-Archeology: > recovered message: > * Removed disabled patches > X-Git-Archeology: > recovered message: > * Restored mysteriously removed comment character > X-Git-Archeology: - Revision 23604e8a0dcdf81ec6c28ccd4b2a64b90816d8e7: https://github.com/armbian/build/commit/23604e8a0dcdf81ec6c28ccd4b2a64b90816d8e7 > X-Git-Archeology: Date: Fri, 19 Jun 2020 17:27:27 +0200 > X-Git-Archeology: From: Paolo > X-Git-Archeology: Subject: Introducing Rockchip RK322X SoC support (#2032) > X-Git-Archeology: > X-Git-Archeology: - Revision bd17d4dbd0025908b6f0aa58d74f2bc8cfedb076: https://github.com/armbian/build/commit/bd17d4dbd0025908b6f0aa58d74f2bc8cfedb076 > X-Git-Archeology: Date: Sat, 19 Sep 2020 15:20:16 +0000 > X-Git-Archeology: From: paolo > X-Git-Archeology: Subject: Many changes for rk322x target: > X-Git-Archeology: > X-Git-Archeology: - Revision c0c099e78cc4a4536c38b7b070d24cd814ab9d9e: https://github.com/armbian/build/commit/c0c099e78cc4a4536c38b7b070d24cd814ab9d9e > X-Git-Archeology: Date: Sun, 17 Jan 2021 11:23:47 +0000 > X-Git-Archeology: From: paolo > X-Git-Archeology: Subject: Added support for rk3328 FE gmac in u-boot, useful for stable ethernet MAC address > X-Git-Archeology: > X-Git-Archeology: - Revision 86abac1fd4e169712a44d245cf7adef4ee17c420: https://github.com/armbian/build/commit/86abac1fd4e169712a44d245cf7adef4ee17c420 > X-Git-Archeology: Date: Tue, 26 Oct 2021 22:14:41 +0200 > X-Git-Archeology: From: Piotr Szczepanik > X-Git-Archeology: Subject: Cleanup u-boot configurations for rockchip64 derivatives (#3150) > X-Git-Archeology: > X-Git-Archeology: - Revision 71ff7b3b989dcb7e86b7e1c00a408a2f53744ea0: https://github.com/armbian/build/commit/71ff7b3b989dcb7e86b7e1c00a408a2f53744ea0 > X-Git-Archeology: Date: Thu, 11 Nov 2021 23:49:52 +0100 > X-Git-Archeology: From: Piotr Szczepanik > X-Git-Archeology: Subject: Switched rockchip64 u-boot to v2021.07 (#3233) > X-Git-Archeology: > X-Git-Archeology: - Revision 7bc069d68138a13a3de2388450289f2622c75fce: https://github.com/armbian/build/commit/7bc069d68138a13a3de2388450289f2622c75fce > X-Git-Archeology: Date: Mon, 22 Apr 2024 12:39:09 +0200 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: move rockchip patches into rk3318_box directory > X-Git-Archeology: > X-Git-Archeology: - Revision efee17f217e58a93e795c165e303bfd0a2a0a32a: https://github.com/armbian/build/commit/efee17f217e58a93e795c165e303bfd0a2a0a32a > X-Git-Archeology: Date: Mon, 22 Apr 2024 12:39:09 +0200 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: rockchip64: bump rk3318-box uboot to v2024.01 > X-Git-Archeology: > X-Git-Archeology: - Revision 7876017d0b77bbfefbb3d112045b32d9b50db928: https://github.com/armbian/build/commit/7876017d0b77bbfefbb3d112045b32d9b50db928 > X-Git-Archeology: Date: Tue, 02 Jul 2024 23:31:50 +0000 > X-Git-Archeology: From: Paolo > X-Git-Archeology: Subject: Bump rk322x-box and rk3318-box to u-boot v2024.07-rc5 (#6855) > X-Git-Archeology: --- arch/arm/dts/rk3229-evb.dts | 32 +- arch/arm/dts/rk322x.dtsi | 8 +- arch/arm/include/asm/arch-rockchip/cru_rk322x.h | 1 + configs/evb-rk3229_defconfig | 2 + configs/evb-rk3328_defconfig | 2 + doc/device-tree-bindings/net/phy.txt | 13 + drivers/clk/rockchip/clk_rk322x.c | 14 +- drivers/clk/rockchip/clk_rk3328.c | 86 +++ drivers/net/gmac_rockchip.c | 341 +++++++++- 9 files changed, 453 insertions(+), 46 deletions(-) diff --git a/arch/arm/dts/rk3229-evb.dts b/arch/arm/dts/rk3229-evb.dts index 111111111111..222222222222 100644 --- a/arch/arm/dts/rk3229-evb.dts +++ b/arch/arm/dts/rk3229-evb.dts @@ -146,19 +146,25 @@ }; &gmac { - assigned-clocks = <&cru SCLK_MAC_EXTCLK>, <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>, <&cru SCLK_MAC_EXTCLK>; - clock_in_out = "input"; - phy-supply = <&vcc_phy>; - phy-mode = "rgmii"; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - snps,reset-gpio = <&gpio2 RK_PD0 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 1000000>; - tx_delay = <0x30>; - rx_delay = <0x10>; - status = "okay"; + assigned-clocks = <&cru SCLK_MAC_SRC>; + assigned-clock-rates = <50000000>; + clock_in_out = "output"; + phy-supply = <&vcc_phy>; + phy-mode = "rmii"; + phy-handle = <&phy>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + phy: phy@0 { + compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22"; + reg = <0>; + phy-is-integrated; + }; + }; }; &io_domains { diff --git a/arch/arm/dts/rk322x.dtsi b/arch/arm/dts/rk322x.dtsi index 111111111111..222222222222 100644 --- a/arch/arm/dts/rk322x.dtsi +++ b/arch/arm/dts/rk322x.dtsi @@ -870,13 +870,13 @@ clocks = <&cru SCLK_MAC>, <&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>, <&cru SCLK_MAC_REF>, <&cru SCLK_MAC_REFOUT>, <&cru ACLK_GMAC>, - <&cru PCLK_GMAC>; + <&cru PCLK_GMAC>, <&cru SCLK_MAC_PHY>; clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_ref", "clk_mac_refout", "aclk_mac", - "pclk_mac"; - resets = <&cru SRST_GMAC>; - reset-names = "stmmaceth"; + "pclk_mac", "clk_macphy"; + resets = <&cru SRST_GMAC>, <&cru SRST_MACPHY>; + reset-names = "stmmaceth", "mac-phy"; rockchip,grf = <&grf>; status = "disabled"; }; diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h index 111111111111..222222222222 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk322x.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk322x.h @@ -10,6 +10,7 @@ #define APLL_HZ (600 * MHz) #define GPLL_HZ (594 * MHz) +#define CPLL_HZ (500 * MHz) #define CORE_PERI_HZ 150000000 #define CORE_ACLK_HZ 300000000 diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig index 111111111111..222222222222 100644 --- a/configs/evb-rk3229_defconfig +++ b/configs/evb-rk3229_defconfig @@ -62,6 +62,8 @@ CONFIG_GMAC_ROCKCHIP=y CONFIG_PHY=y CONFIG_PINCTRL=y CONFIG_RAM=y +CONFIG_DM_RESET=y +CONFIG_RESET_ROCKCHIP=y CONFIG_SPL_RAM=y CONFIG_TPL_RAM=y CONFIG_BAUDRATE=1500000 diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 111111111111..222222222222 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -75,6 +75,8 @@ CONFIG_DM_REGULATOR_FIXED=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM=y +CONFIG_DM_RESET=y +CONFIG_RESET_ROCKCHIP=y CONFIG_SPL_RAM=y CONFIG_TPL_RAM=y CONFIG_DM_RNG=y diff --git a/doc/device-tree-bindings/net/phy.txt b/doc/device-tree-bindings/net/phy.txt index 111111111111..222222222222 100644 --- a/doc/device-tree-bindings/net/phy.txt +++ b/doc/device-tree-bindings/net/phy.txt @@ -8,6 +8,19 @@ Required properties: - reg : The ID number for the phy, usually a small integer +Optional Properties: + +- compatible: Compatible list, may contain + "ethernet-phy-ieee802.3-c22" or "ethernet-phy-ieee802.3-c45" for + PHYs that implement IEEE802.3 clause 22 or IEEE802.3 clause 45 + specifications. If neither of these are specified, the default is to + assume clause 22. + +- phy-is-integrated: If set, indicates that the PHY is integrated into the same + physical package as the Ethernet MAC. If needed, muxers should be configured + to ensure the integrated PHY is used. The absence of this property indicates + the muxers should be configured so that the external PHY is used. + Example: ethernet-phy@0 { diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c index 111111111111..222222222222 100644 --- a/drivers/clk/rockchip/clk_rk322x.c +++ b/drivers/clk/rockchip/clk_rk322x.c @@ -42,6 +42,7 @@ enum { /* use integer mode*/ static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1); static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1); +static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 3, 1); static int rkclk_set_pll(struct rk322x_cru *cru, enum rk_clk_id clk_id, const struct pll_div *div) @@ -91,11 +92,13 @@ static void rkclk_init(struct rk322x_cru *cru) rk_clrsetreg(&cru->cru_mode_con, GPLL_MODE_MASK | APLL_MODE_MASK, GPLL_MODE_SLOW << GPLL_MODE_SHIFT | - APLL_MODE_SLOW << APLL_MODE_SHIFT); + APLL_MODE_SLOW << APLL_MODE_SHIFT | + CPLL_MODE_SLOW << CPLL_MODE_SHIFT); /* init pll */ rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg); rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg); + rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg); /* * select apll as cpu/core clock pll source and @@ -168,7 +171,8 @@ static void rkclk_init(struct rk322x_cru *cru) rk_clrsetreg(&cru->cru_mode_con, GPLL_MODE_MASK | APLL_MODE_MASK, GPLL_MODE_NORM << GPLL_MODE_SHIFT | - APLL_MODE_NORM << APLL_MODE_SHIFT); + APLL_MODE_NORM << APLL_MODE_SHIFT | + CPLL_MODE_NORM << CPLL_MODE_SHIFT); } /* Get pll rate by id */ @@ -258,11 +262,10 @@ static ulong rk322x_mac_set_clk(struct rk322x_cru *cru, uint freq) ulong pll_rate; u8 div; - if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_MASK) + if (con & MAC_PLL_SEL_MASK) pll_rate = GPLL_HZ; else - /* CPLL is not set */ - return -EPERM; + pll_rate = CPLL_HZ; div = DIV_ROUND_UP(pll_rate, freq) - 1; if (div <= 0x1f) @@ -391,6 +394,7 @@ static ulong rk322x_clk_set_rate(struct clk *clk, ulong rate) case CLK_DDR: new_rate = rk322x_ddr_set_clk(priv->cru, rate); break; + case SCLK_MAC_SRC: case SCLK_MAC: new_rate = rk322x_mac_set_clk(priv->cru, rate); break; diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c index 111111111111..222222222222 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -96,6 +96,14 @@ enum { PCLK_DBG_DIV_SHIFT = 0, PCLK_DBG_DIV_MASK = 0xF << PCLK_DBG_DIV_SHIFT, + /* CLKSEL_CON26 */ + GMAC2PHY_PLL_SEL_SHIFT = 7, + GMAC2PHY_PLL_SEL_MASK = 1 << GMAC2PHY_PLL_SEL_SHIFT, + GMAC2PHY_PLL_SEL_CPLL = 0, + GMAC2PHY_PLL_SEL_GPLL = 1, + GMAC2PHY_CLK_DIV_MASK = 0x1f, + GMAC2PHY_CLK_DIV_SHIFT = 0, + /* CLKSEL_CON27 */ GMAC2IO_PLL_SEL_SHIFT = 7, GMAC2IO_PLL_SEL_MASK = 1 << GMAC2IO_PLL_SEL_SHIFT, @@ -447,6 +455,39 @@ static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate) return ret; } +static ulong rk3328_gmac2phy_src_set_clk(struct rk3328_cru *cru, ulong rate) +{ + u32 con = readl(&cru->clksel_con[26]); + ulong pll_rate; + u8 div; + + if ((con >> GMAC2PHY_PLL_SEL_SHIFT) & GMAC2PHY_PLL_SEL_GPLL) + pll_rate = GPLL_HZ; + else + pll_rate = CPLL_HZ; + + div = DIV_ROUND_UP(pll_rate, rate) - 1; + if (div <= 0x1f) + rk_clrsetreg(&cru->clksel_con[26], GMAC2PHY_CLK_DIV_MASK, + div << GMAC2PHY_CLK_DIV_SHIFT); + else + debug("Unsupported div for gmac:%d\n", div); + + return DIV_TO_RATE(pll_rate, div); +} + +static ulong rk3328_gmac2phy_set_clk(struct rk3328_cru *cru, ulong rate) +{ + struct rk3328_grf_regs *grf; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + if (readl(&grf->mac_con[2]) & BIT(10)) + /* An external clock will always generate the right rate... */ + return rate; + else + return rk3328_gmac2phy_src_set_clk(cru, rate); +} + static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id) { u32 div, con, con_id; @@ -739,6 +780,12 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) case SCLK_MAC2IO: ret = rk3328_gmac2io_set_clk(priv->cru, rate); break; + case SCLK_MAC2PHY: + ret = rk3328_gmac2phy_set_clk(priv->cru, rate); + break; + case SCLK_MAC2PHY_SRC: + ret = rk3328_gmac2phy_src_set_clk(priv->cru, rate); + break; case SCLK_PWM: ret = rk3328_pwm_set_clk(priv->cru, rate); break; @@ -868,6 +915,43 @@ static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent) return -EINVAL; } +static int rk3328_gmac2phy_set_parent(struct clk *clk, struct clk *parent) +{ + struct rk3328_grf_regs *grf; + const char *clock_output_name; + int ret; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + /* + * If the requested parent is in the same clock-controller and the id + * is SCLK_MAC2PHY_SRC ("clk_mac2phy_src"), switch to the internal clock. + */ + if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2PHY_SRC)) { + debug("%s: switching MAC CLK to SCLK_MAC2IO_PHY\n", __func__); + rk_clrreg(&grf->mac_con[2], BIT(10)); + return 0; + } + + /* + * Otherwise, we need to check the clock-output-names of the + * requested parent to see if the requested id is "phy_50m_out". + */ + ret = dev_read_string_index(parent->dev, "clock-output-names", + parent->id, &clock_output_name); + if (ret < 0) + return -ENODATA; + + /* If this is "phy_50m_out", switch to the external clock input */ + if (!strcmp(clock_output_name, "phy_50m_out")) { + debug("%s: switching MAC CLK to PHY_50M_OUT\n", __func__); + rk_setreg(&grf->mac_con[2], BIT(10)); + return 0; + } + + return -EINVAL; +} + static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) { switch (clk->id) { @@ -875,6 +959,8 @@ static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) return rk3328_gmac2io_set_parent(clk, parent); case SCLK_MAC2IO_EXT: return rk3328_gmac2io_ext_set_parent(clk, parent); + case SCLK_MAC2PHY: + return rk3328_gmac2phy_set_parent(clk, parent); case DCLK_LCDC: case USB480M: case SCLK_PDM: diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index 111111111111..222222222222 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,8 @@ #include #include #include +#include +#include #include #include #include "designware.h" @@ -42,21 +45,29 @@ DECLARE_GLOBAL_DATA_PTR; struct gmac_rockchip_plat { struct dw_eth_pdata dw_eth_pdata; bool clock_input; + bool integrated_phy; + struct reset_ctl phy_reset; int tx_delay; int rx_delay; }; struct rk_gmac_ops { - int (*fix_mac_speed)(struct dw_eth_dev *priv); + int (*fix_rmii_speed)(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv); + int (*fix_rgmii_speed)(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv); void (*set_to_rmii)(struct gmac_rockchip_plat *pdata); void (*set_to_rgmii)(struct gmac_rockchip_plat *pdata); + void (*integrated_phy_powerup)(struct gmac_rockchip_plat *pdata); }; static int gmac_rockchip_of_to_plat(struct udevice *dev) { struct gmac_rockchip_plat *pdata = dev_get_plat(dev); + struct ofnode_phandle_args args; const char *string; + int ret; string = dev_read_string(dev, "clock_in_out"); if (!strcmp(string, "input")) @@ -64,6 +75,25 @@ static int gmac_rockchip_of_to_plat(struct udevice *dev) else pdata->clock_input = false; + /* If phy-handle property is passed from DT, use it as the PHY */ + ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0, &args); + if (ret) { + debug("Cannot get phy phandle: ret=%d\n", ret); + pdata->integrated_phy = dev_read_bool(dev, "phy-is-integrated"); + } else { + debug("Found phy-handle subnode\n"); + pdata->integrated_phy = ofnode_read_bool(args.node, + "phy-is-integrated"); + } + + if (pdata->integrated_phy) { + ret = reset_get_by_name(dev, "mac-phy", &pdata->phy_reset); + if (ret) { + debug("No PHY reset control found: ret=%d\n", ret); + return ret; + } + } + /* Check the new naming-style first... */ pdata->tx_delay = dev_read_u32_default(dev, "tx_delay", -ENOENT); pdata->rx_delay = dev_read_u32_default(dev, "rx_delay", -ENOENT); @@ -77,7 +107,8 @@ static int gmac_rockchip_of_to_plat(struct udevice *dev) return designware_eth_of_to_plat(dev); } -static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int px30_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct px30_grf *grf; struct clk clk_speed; @@ -118,7 +149,43 @@ static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3228_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) +{ + struct rk322x_grf *grf; + int clk; + enum { + RK3228_GMAC_RMII_CLK_MASK = BIT(7), + RK3228_GMAC_RMII_CLK_2_5M = 0, + RK3228_GMAC_RMII_CLK_25M = BIT(7), + + RK3228_GMAC_RMII_SPEED_MASK = BIT(2), + RK3228_GMAC_RMII_SPEED_10 = 0, + RK3228_GMAC_RMII_SPEED_100 = BIT(2), + }; + + switch (priv->phydev->speed) { + case 10: + clk = RK3228_GMAC_RMII_CLK_2_5M | RK3228_GMAC_RMII_SPEED_10; + break; + case 100: + clk = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_RMII_SPEED_100; + break; + default: + debug("Unknown phy speed: %d\n", priv->phydev->speed); + return -EINVAL; + } + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->mac_con[1], + RK3228_GMAC_RMII_CLK_MASK | RK3228_GMAC_RMII_SPEED_MASK, + clk); + + return 0; +} + +static int rk3228_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk322x_grf *grf; int clk; @@ -151,7 +218,8 @@ static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3288_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk3288_grf *grf; int clk; @@ -177,7 +245,8 @@ static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3308_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk3308_grf *grf; struct clk clk_speed; @@ -218,7 +287,43 @@ static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3328_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) +{ + struct rk3328_grf_regs *grf; + int clk; + enum { + RK3328_GMAC_RMII_CLK_MASK = BIT(7), + RK3328_GMAC_RMII_CLK_2_5M = 0, + RK3328_GMAC_RMII_CLK_25M = BIT(7), + + RK3328_GMAC_RMII_SPEED_MASK = BIT(2), + RK3328_GMAC_RMII_SPEED_10 = 0, + RK3328_GMAC_RMII_SPEED_100 = BIT(2), + }; + + switch (priv->phydev->speed) { + case 10: + clk = RK3328_GMAC_RMII_CLK_2_5M | RK3328_GMAC_RMII_SPEED_10; + break; + case 100: + clk = RK3328_GMAC_RMII_CLK_25M | RK3328_GMAC_RMII_SPEED_100; + break; + default: + debug("Unknown phy speed: %d\n", priv->phydev->speed); + return -EINVAL; + } + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(pdata->integrated_phy ? &grf->mac_con[2] : &grf->mac_con[1], + RK3328_GMAC_RMII_CLK_MASK | RK3328_GMAC_RMII_SPEED_MASK, + clk); + + return 0; +} + +static int rk3328_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk3328_grf_regs *grf; int clk; @@ -251,7 +356,8 @@ static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3368_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk3368_grf *grf; int clk; @@ -283,7 +389,8 @@ static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv) +static int rk3399_gmac_fix_rgmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rk3399_grf_regs *grf; int clk; @@ -309,7 +416,8 @@ static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } -static int rv1108_set_rmii_speed(struct dw_eth_dev *priv) +static int rv1108_gmac_fix_rmii_speed(struct gmac_rockchip_plat *pdata, + struct dw_eth_dev *priv) { struct rv1108_grf *grf; int clk, speed; @@ -360,6 +468,28 @@ static void px30_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) PX30_GMAC_PHY_INTF_SEL_RMII); } +static void rk3228_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) +{ + struct rk322x_grf *grf; + enum { + RK3228_GRF_CON_RMII_MODE_MASK = BIT(11), + RK3228_GRF_CON_RMII_MODE_SEL = BIT(11), + RK3228_RMII_MODE_MASK = BIT(10), + RK3228_RMII_MODE_SEL = BIT(10), + RK3228_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), + RK3228_GMAC_PHY_INTF_SEL_RMII = BIT(6), + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->mac_con[1], + RK3228_GRF_CON_RMII_MODE_MASK | + RK3228_RMII_MODE_MASK | + RK3228_GMAC_PHY_INTF_SEL_MASK, + RK3228_GRF_CON_RMII_MODE_SEL | + RK3228_RMII_MODE_SEL | + RK3228_GMAC_PHY_INTF_SEL_RMII); +} + static void rk3228_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) { struct rk322x_grf *grf; @@ -438,6 +568,25 @@ static void rk3308_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) RK3308_GMAC_PHY_INTF_SEL_RMII); } +static void rk3328_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) +{ + struct rk3328_grf_regs *grf; + enum { + RK3328_RMII_MODE_MASK = BIT(9), + RK3328_RMII_MODE = BIT(9), + + RK3328_GMAC_PHY_INTF_SEL_MASK = GENMASK(6, 4), + RK3328_GMAC_PHY_INTF_SEL_RMII = BIT(6), + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(pdata->integrated_phy ? &grf->mac_con[2] : &grf->mac_con[1], + RK3328_RMII_MODE_MASK | + RK3328_GMAC_PHY_INTF_SEL_MASK, + RK3328_GMAC_PHY_INTF_SEL_RMII | + RK3328_RMII_MODE); +} + static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_plat *pdata) { struct rk3328_grf_regs *grf; @@ -553,6 +702,126 @@ static void rv1108_gmac_set_to_rmii(struct gmac_rockchip_plat *pdata) RV1108_GMAC_PHY_INTF_SEL_RMII); } +static void rk3228_gmac_integrated_phy_powerup(struct gmac_rockchip_plat *pdata) +{ + struct rk322x_grf *grf; + enum { + RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY_MASK = BIT(15), + RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY = BIT(15), + }; + enum { + RK3228_MACPHY_CFG_CLK_50M_MASK = BIT(14), + RK3228_MACPHY_CFG_CLK_50M = BIT(14), + + RK3228_MACPHY_RMII_MODE_MASK = GENMASK(7, 6), + RK3228_MACPHY_RMII_MODE = BIT(6), + + RK3228_MACPHY_ENABLE_MASK = BIT(0), + RK3228_MACPHY_DISENABLE = 0, + RK3228_MACPHY_ENABLE = BIT(0), + }; + enum { + RK3228_RK_GRF_CON2_MACPHY_ID_MASK = GENMASK(6, 0), + RK3228_RK_GRF_CON2_MACPHY_ID = 0x1234, + }; + enum { + RK3228_RK_GRF_CON3_MACPHY_ID_MASK = GENMASK(5, 0), + RK3228_RK_GRF_CON3_MACPHY_ID = 0x35, + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->con_iomux, + RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY_MASK, + RK3228_GRF_CON_MUX_GMAC_INTEGRATED_PHY); + + rk_clrsetreg(&grf->macphy_con[2], + RK3228_RK_GRF_CON2_MACPHY_ID_MASK, + RK3228_RK_GRF_CON2_MACPHY_ID); + + rk_clrsetreg(&grf->macphy_con[3], + RK3228_RK_GRF_CON3_MACPHY_ID_MASK, + RK3228_RK_GRF_CON3_MACPHY_ID); + + /* disabled before trying to reset it */ + rk_clrsetreg(&grf->macphy_con[0], + RK3228_MACPHY_CFG_CLK_50M_MASK | + RK3228_MACPHY_RMII_MODE_MASK | + RK3228_MACPHY_ENABLE_MASK, + RK3228_MACPHY_CFG_CLK_50M | + RK3228_MACPHY_RMII_MODE | + RK3228_MACPHY_DISENABLE); + + reset_assert(&pdata->phy_reset); + udelay(10); + reset_deassert(&pdata->phy_reset); + udelay(10); + + rk_clrsetreg(&grf->macphy_con[0], + RK3228_MACPHY_ENABLE_MASK, + RK3228_MACPHY_ENABLE); + udelay(30 * 1000); +} + +static void rk3328_gmac_integrated_phy_powerup(struct gmac_rockchip_plat *pdata) +{ + struct rk3328_grf_regs *grf; + enum { + RK3328_GRF_CON_RMII_MODE_MASK = BIT(9), + RK3328_GRF_CON_RMII_MODE = BIT(9), + }; + enum { + RK3328_MACPHY_CFG_CLK_50M_MASK = BIT(14), + RK3328_MACPHY_CFG_CLK_50M = BIT(14), + + RK3328_MACPHY_RMII_MODE_MASK = GENMASK(7, 6), + RK3328_MACPHY_RMII_MODE = BIT(6), + + RK3328_MACPHY_ENABLE_MASK = BIT(0), + RK3328_MACPHY_DISENABLE = 0, + RK3328_MACPHY_ENABLE = BIT(0), + }; + enum { + RK3328_RK_GRF_CON2_MACPHY_ID_MASK = GENMASK(6, 0), + RK3328_RK_GRF_CON2_MACPHY_ID = 0x1234, + }; + enum { + RK3328_RK_GRF_CON3_MACPHY_ID_MASK = GENMASK(5, 0), + RK3328_RK_GRF_CON3_MACPHY_ID = 0x35, + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->macphy_con[1], + RK3328_GRF_CON_RMII_MODE_MASK, + RK3328_GRF_CON_RMII_MODE); + + rk_clrsetreg(&grf->macphy_con[2], + RK3328_RK_GRF_CON2_MACPHY_ID_MASK, + RK3328_RK_GRF_CON2_MACPHY_ID); + + rk_clrsetreg(&grf->macphy_con[3], + RK3328_RK_GRF_CON3_MACPHY_ID_MASK, + RK3328_RK_GRF_CON3_MACPHY_ID); + + /* disabled before trying to reset it */ + rk_clrsetreg(&grf->macphy_con[0], + RK3328_MACPHY_CFG_CLK_50M_MASK | + RK3328_MACPHY_RMII_MODE_MASK | + RK3328_MACPHY_ENABLE_MASK, + RK3328_MACPHY_CFG_CLK_50M | + RK3328_MACPHY_RMII_MODE | + RK3328_MACPHY_DISENABLE); + + reset_assert(&pdata->phy_reset); + udelay(10); + reset_deassert(&pdata->phy_reset); + udelay(10); + + rk_clrsetreg(&grf->macphy_con[0], + RK3328_MACPHY_ENABLE_MASK, + RK3328_MACPHY_ENABLE); + udelay(30 * 1000); +} + static int gmac_rockchip_probe(struct udevice *dev) { struct gmac_rockchip_plat *pdata = dev_get_plat(dev); @@ -572,6 +841,9 @@ static int gmac_rockchip_probe(struct udevice *dev) if (ret) return ret; + if (pdata->integrated_phy && ops->integrated_phy_powerup) + ops->integrated_phy_powerup(pdata); + switch (eth_pdata->phy_interface) { case PHY_INTERFACE_MODE_RGMII: /* Set to RGMII mode */ @@ -619,7 +891,7 @@ static int gmac_rockchip_probe(struct udevice *dev) if (!pdata->clock_input) { rate = clk_set_rate(&clk, 50000000); - if (rate != 50000000) + if (rate != 50000000 && rate != 49500000) return -EINVAL; } break; @@ -655,7 +927,7 @@ static int gmac_rockchip_probe(struct udevice *dev) break; default: - debug("NO interface defined!\n"); + debug("%s: no interface defined!\n", __func__); return -ENXIO; } @@ -664,18 +936,33 @@ static int gmac_rockchip_probe(struct udevice *dev) static int gmac_rockchip_eth_start(struct udevice *dev) { - struct eth_pdata *pdata = dev_get_plat(dev); + struct eth_pdata *eth_pdata = dev_get_plat(dev); struct dw_eth_dev *priv = dev_get_priv(dev); struct rk_gmac_ops *ops = (struct rk_gmac_ops *)dev_get_driver_data(dev); + struct gmac_rockchip_plat *pdata = dev_get_plat(dev); int ret; - ret = designware_eth_init(priv, pdata->enetaddr); - if (ret) - return ret; - ret = ops->fix_mac_speed(priv); + ret = designware_eth_init(priv, eth_pdata->enetaddr); if (ret) return ret; + + switch (eth_pdata->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + ret = ops->fix_rgmii_speed(pdata, priv); + if (ret) + return ret; + break; + case PHY_INTERFACE_MODE_RMII: + ret = ops->fix_rmii_speed(pdata, priv); + if (ret) + return ret; + break; + default: + debug("%s: no interface defined!\n", __func__); + return -ENXIO; + } + ret = designware_eth_enable(priv); if (ret) return ret; @@ -693,42 +980,48 @@ const struct eth_ops gmac_rockchip_eth_ops = { }; const struct rk_gmac_ops px30_gmac_ops = { - .fix_mac_speed = px30_gmac_fix_mac_speed, + .fix_rmii_speed = px30_gmac_fix_rmii_speed, .set_to_rmii = px30_gmac_set_to_rmii, }; const struct rk_gmac_ops rk3228_gmac_ops = { - .fix_mac_speed = rk3228_gmac_fix_mac_speed, + .fix_rmii_speed = rk3228_gmac_fix_rmii_speed, + .fix_rgmii_speed = rk3228_gmac_fix_rgmii_speed, + .set_to_rmii = rk3228_gmac_set_to_rmii, .set_to_rgmii = rk3228_gmac_set_to_rgmii, + .integrated_phy_powerup = rk3228_gmac_integrated_phy_powerup, }; const struct rk_gmac_ops rk3288_gmac_ops = { - .fix_mac_speed = rk3288_gmac_fix_mac_speed, + .fix_rgmii_speed = rk3288_gmac_fix_rgmii_speed, .set_to_rgmii = rk3288_gmac_set_to_rgmii, }; const struct rk_gmac_ops rk3308_gmac_ops = { - .fix_mac_speed = rk3308_gmac_fix_mac_speed, + .fix_rmii_speed = rk3308_gmac_fix_rmii_speed, .set_to_rmii = rk3308_gmac_set_to_rmii, }; const struct rk_gmac_ops rk3328_gmac_ops = { - .fix_mac_speed = rk3328_gmac_fix_mac_speed, + .fix_rmii_speed = rk3328_gmac_fix_rmii_speed, + .fix_rgmii_speed = rk3328_gmac_fix_rgmii_speed, + .set_to_rmii = rk3328_gmac_set_to_rmii, .set_to_rgmii = rk3328_gmac_set_to_rgmii, + .integrated_phy_powerup = rk3328_gmac_integrated_phy_powerup, }; const struct rk_gmac_ops rk3368_gmac_ops = { - .fix_mac_speed = rk3368_gmac_fix_mac_speed, + .fix_rgmii_speed = rk3368_gmac_fix_rgmii_speed, .set_to_rgmii = rk3368_gmac_set_to_rgmii, }; const struct rk_gmac_ops rk3399_gmac_ops = { - .fix_mac_speed = rk3399_gmac_fix_mac_speed, + .fix_rgmii_speed = rk3399_gmac_fix_rgmii_speed, .set_to_rgmii = rk3399_gmac_set_to_rgmii, }; const struct rk_gmac_ops rv1108_gmac_ops = { - .fix_mac_speed = rv1108_set_rmii_speed, + .fix_rmii_speed = rv1108_gmac_fix_rmii_speed, .set_to_rmii = rv1108_gmac_set_to_rmii, }; -- Armbian