diff --git a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts index bc9e98fe0f013..9a41d11ec3877 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts @@ -20,10 +20,6 @@ mmc2 = &sdio; }; - chosen { - stdout-path = "serial0:1500000n8"; - }; - leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -48,6 +44,14 @@ }; }; + bt_reg_on_h: bt-reg-on-regulator { + compatible = "regulator-fixed"; + regulator-name = "bt_reg_on"; + enable-active-high; + gpio = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; + regulator-always-on; + }; + sdio_pwrseq: sdio-pwrseq { compatible = "mmc-pwrseq-simple"; pinctrl-0 = <&wifi_enable_h>; @@ -129,6 +133,11 @@ }; }; +&fiq_debugger{ + rockchip,serial-id = <0>; + status = "okay"; +}; + &cpu0 { cpu-supply = <&vdd_core>; }; @@ -144,6 +153,16 @@ status = "okay"; }; +&io_domains { + status = "okay"; + vccio0-supply = <&vcc_io>; + vccio1-supply = <&vcc_io>; + vccio2-supply = <&vcc_1v8>; + vccio3-supply = <&vcc_1v8>; + vccio4-supply = <&vcc_1v8>; + vccio5-supply = <&vcc_io>; +}; + &gmac { clock_in_out = "output"; phy-handle = <&rtl8201f>; @@ -176,10 +195,6 @@ pinctrl-0 = <&rtc_32k>; bluetooth { - bt_reg_on: bt-reg-on { - rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; - }; - bt_wake_host: bt-wake-host { rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; }; @@ -235,13 +250,12 @@ &sdio { #address-cells = <1>; #size-cells = <0>; + max-frequency = <150000000>; + bus-width = <4>; cap-sd-highspeed; cap-sdio-irq; keep-power-in-suspend; - max-frequency = <100000000>; mmc-pwrseq = <&sdio_pwrseq>; - no-mmc; - no-sd; non-removable; sd-uhs-sdr50; vmmc-supply = <&vcc_io>; @@ -249,7 +263,6 @@ status = "okay"; rtl8723ds: wifi@1 { - reg = <1>; interrupt-parent = <&gpio0>; interrupts = ; interrupt-names = "host-wake"; @@ -283,7 +296,7 @@ &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer>; - status = "okay"; + status = "disabled"; }; &uart4 { @@ -293,10 +306,9 @@ bluetooth { compatible = "realtek,rtl8723ds-bt"; device-wake-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; - enable-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; host-wake-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; - pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>; + pinctrl-0 = <&bt_wake_host &host_wake_bt>; }; }; diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index 44a39f7b93d95..7c9567f2a2e9b 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -1133,6 +1133,7 @@ CONFIG_RPMSG_ROCKCHIP_MBOX=y CONFIG_RPMSG_VIRTIO=y CONFIG_CPU_PX30=y CONFIG_CPU_RK1808=y +CONFIG_CPU_RK3308=y CONFIG_CPU_RK3328=y CONFIG_CPU_RK3399=y CONFIG_CPU_RK3528=y diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fc101c3393f81..5733aed95ae17 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -66,6 +66,16 @@ #define RTL8211F_LCR_ADDR 0x10 #define RTL8211F_EEELCR_ADDR 0x11 +#define RTL8201F_PHY_ID 0x001cc816 +#define RTL8201F_PHY_ID_MASK 0x001fffff +#define RTL8201F_LED_PAGE 0x07 +#define RTL8201F_LEDS_CFG 0x11 +#define RTL8201F_LEDS_CFG_MASK GENMASK(7, 0) +#define RTL8201F_LED0_LINK_100 BIT(1) +#define RTL8201F_LED1_ACTIVITY BIT(7) +#define RTL8201F_LEDS_FUNC 0x13 +#define RTL8201F_CUSTOMIZED_LED BIT(3) + /* Module parameters */ #define TX_TIMEO 5000 static int watchdog = TX_TIMEO; @@ -3679,6 +3689,7 @@ static int stmmac_request_irq_single(struct net_device *dev) /* Request the Wake IRQ in case of another line * is used for WoL */ + priv->wol_irq_disabled = true; if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) { ret = request_irq(priv->wol_irq, stmmac_interrupt, IRQF_SHARED, dev->name, dev); @@ -4203,11 +4214,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) if (dma_mapping_error(priv->device, des)) goto dma_map_err; - tx_q->tx_skbuff_dma[first_entry].buf = des; - tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); - tx_q->tx_skbuff_dma[first_entry].map_as_page = false; - tx_q->tx_skbuff_dma[first_entry].buf_type = STMMAC_TXBUF_T_SKB; - if (priv->dma_cap.addr64 <= 32) { first->des0 = cpu_to_le32(des); @@ -4226,6 +4232,23 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue); + /* In case two or more DMA transmit descriptors are allocated for this + * non-paged SKB data, the DMA buffer address should be saved to + * tx_q->tx_skbuff_dma[].buf corresponding to the last descriptor, + * and leave the other tx_q->tx_skbuff_dma[].buf as NULL to guarantee + * that stmmac_tx_clean() does not unmap the entire DMA buffer too early + * since the tail areas of the DMA buffer can be accessed by DMA engine + * sooner or later. + * By saving the DMA buffer address to tx_q->tx_skbuff_dma[].buf + * corresponding to the last descriptor, stmmac_tx_clean() will unmap + * this DMA buffer right after the DMA engine completely finishes the + * full buffer transmission. + */ + tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des; + tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_headlen(skb); + tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = false; + tx_q->tx_skbuff_dma[tx_q->cur_tx].buf_type = STMMAC_TXBUF_T_SKB; + /* Prepare fragments */ for (i = 0; i < nfrags; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; @@ -7090,6 +7113,9 @@ static int phy_rtl8211f_led_fixup(struct phy_device *phydev) { u32 val, val2; + if (phydev->phy_id == RTL8201F_PHY_ID) + return 0; + /* Switch to Page 0x0d04 */ phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0d04); @@ -7115,6 +7141,9 @@ static int phy_rtl8211f_led_fixup(struct phy_device *phydev) static int phy_rtl8211f_eee_fixup(struct phy_device *phydev) { + if (phydev->phy_id == RTL8201F_PHY_ID) + return 0; + phy_write(phydev, 31, 0x0000); phy_write(phydev, 0, 0x8000); mdelay(20); @@ -7129,6 +7158,24 @@ static int phy_rtl8211f_eee_fixup(struct phy_device *phydev) return 0; } +static int phy_rtl8201f_led_fixup(struct phy_device *phydev) +{ + int ret; + + /* LED0 is yellow (100M link); LED1 is green (activity). */ + ret = phy_modify_paged(phydev, RTL8201F_LED_PAGE, + RTL8201F_LEDS_CFG, RTL8201F_LEDS_CFG_MASK, + RTL8201F_LED0_LINK_100 | + RTL8201F_LED1_ACTIVITY); + if (ret < 0) + return ret; + + return phy_modify_paged(phydev, RTL8201F_LED_PAGE, + RTL8201F_LEDS_FUNC, + RTL8201F_CUSTOMIZED_LED, + RTL8201F_CUSTOMIZED_LED); +} + /** * stmmac_dvr_probe * @device: device pointer @@ -7425,6 +7472,13 @@ int stmmac_dvr_probe(struct device *device, dev_warn(priv->device, "Failed to register fixup for PHY RTL8211F disabling EEE.\n"); } + /* Register fixup for PHY RTL8201F */ + ret = phy_register_fixup_for_uid(RTL8201F_PHY_ID, + RTL8201F_PHY_ID_MASK, + phy_rtl8201f_led_fixup); + if (ret) + dev_warn(priv->device, "Failed to register fixup for PHY RTL8201F.\n"); + return ret; error_netdev_register: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index be80ca6534ac9..abd1077fdd40e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -8,6 +8,7 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#include #include #include #include @@ -293,62 +294,80 @@ static int stmmac_mtl_setup(struct platform_device *pdev, } /** - * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources - * @plat: driver data platform structure - * @np: device tree node - * @dev: device pointer - * Description: - * The mdio bus will be allocated in case of a phy transceiver is on board; - * it will be NULL if the fixed-link is configured. - * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated - * in any case (for DSA, mdio must be registered even if fixed-link). - * The table below sums the supported configurations: - * ------------------------------- - * snps,phy-addr | Y - * ------------------------------- - * phy-handle | Y - * ------------------------------- - * fixed-link | N - * ------------------------------- - * snps,dwmac-mdio | - * even if | Y - * fixed-link | - * ------------------------------- + * stmmac_of_get_mdio() - Gets the MDIO bus from the devicetree. + * @np: devicetree node + * + * The MDIO bus will be searched for in the following ways: + * 1. The compatible is "snps,dwc-qos-ethernet-4.10" && a "mdio" named + * child node exists + * 2. A child node with the "snps,dwmac-mdio" compatible is present * - * It returns 0 in case of success otherwise -ENODEV. + * Return: The MDIO node if present otherwise NULL */ -static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, - struct device_node *np, struct device *dev) +static struct device_node *stmmac_of_get_mdio(struct device_node *np) { - bool mdio = !of_phy_is_fixed_link(np); static const struct of_device_id need_mdio_ids[] = { { .compatible = "snps,dwc-qos-ethernet-4.10" }, {}, }; + struct device_node *mdio_node = NULL; if (of_match_node(need_mdio_ids, np)) { - plat->mdio_node = of_get_child_by_name(np, "mdio"); + mdio_node = of_get_child_by_name(np, "mdio"); } else { /** * If snps,dwmac-mdio is passed from DT, always register * the MDIO */ - for_each_child_of_node(np, plat->mdio_node) { - if (of_device_is_compatible(plat->mdio_node, + for_each_child_of_node(np, mdio_node) { + if (of_device_is_compatible(mdio_node, "snps,dwmac-mdio")) break; } } - if (plat->mdio_node) { + return mdio_node; +} + +/** + * stmmac_mdio_setup() - Populate platform related MDIO structures. + * @plat: driver data platform structure + * @np: devicetree node + * @dev: device pointer + * + * This searches for MDIO information from the devicetree. + * If an MDIO node is found, it's assigned to plat->mdio_node and + * plat->mdio_bus_data is allocated. + * If no connection can be determined, just plat->mdio_bus_data is allocated + * to indicate a bus should be created and scanned for a phy. + * If it's determined there's no MDIO bus needed, both are left NULL. + * + * This expects that plat->phy_node has already been searched for. + * + * Return: 0 on success, errno otherwise. + */ +static int stmmac_mdio_setup(struct plat_stmmacenet_data *plat, + struct device_node *np, struct device *dev) +{ + bool legacy_mdio; + + plat->mdio_node = stmmac_of_get_mdio(np); + if (plat->mdio_node) dev_dbg(dev, "Found MDIO subnode\n"); - mdio = true; - } - if (mdio) { - plat->mdio_bus_data = - devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), - GFP_KERNEL); + /* Legacy devicetrees allowed for no MDIO bus description and expect + * the bus to be scanned for devices. If there's no phy or fixed-link + * described assume this is the case since there must be something + * connected to the MAC. + */ + legacy_mdio = !of_phy_is_fixed_link(np) && !plat->phy_node; + if (legacy_mdio) + dev_info(dev, "Deprecated MDIO bus assumption used\n"); + + if (plat->mdio_node || legacy_mdio) { + plat->mdio_bus_data = devm_kzalloc(dev, + sizeof(*plat->mdio_bus_data), + GFP_KERNEL); if (!plat->mdio_bus_data) return -ENOMEM; @@ -453,10 +472,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); - /* To Configure PHY by using all device-tree supported properties */ - rc = stmmac_dt_phy(plat, np, &pdev->dev); - if (rc) - return ERR_PTR(rc); + rc = stmmac_mdio_setup(plat, np, &pdev->dev); + if (rc) { + ret = ERR_PTR(rc); + goto error_put_phy; + } of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); @@ -545,8 +565,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL); if (!dma_cfg) { - stmmac_remove_config_dt(pdev, plat); - return ERR_PTR(-ENOMEM); + ret = ERR_PTR(-ENOMEM); + goto error_put_mdio; } plat->dma_cfg = dma_cfg; @@ -577,8 +597,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) rc = stmmac_mtl_setup(pdev, plat); if (rc) { - stmmac_remove_config_dt(pdev, plat); - return ERR_PTR(rc); + ret = ERR_PTR(rc); + goto error_put_mdio; } /* clock setup */ @@ -630,10 +650,48 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) clk_disable_unprepare(plat->pclk); error_pclk_get: clk_disable_unprepare(plat->stmmac_clk); +error_put_mdio: + of_node_put(plat->mdio_node); +error_put_phy: + of_node_put(plat->phy_node); return ret; } +static void devm_stmmac_remove_config_dt(void *data) +{ + struct plat_stmmacenet_data *plat = data; + + clk_disable_unprepare(plat->stmmac_clk); + clk_disable_unprepare(plat->pclk); + of_node_put(plat->mdio_node); + of_node_put(plat->phy_node); +} + +/** + * devm_stmmac_probe_config_dt + * @pdev: platform_device structure + * @mac: MAC address to use + * Description: Devres variant of stmmac_probe_config_dt(). + */ +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) +{ + struct plat_stmmacenet_data *plat; + int ret; + + plat = stmmac_probe_config_dt(pdev, mac); + if (IS_ERR(plat)) + return plat; + + ret = devm_add_action_or_reset(&pdev->dev, + devm_stmmac_remove_config_dt, plat); + if (ret) + return ERR_PTR(ret); + + return plat; +} + /** * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt() * @pdev: platform_device structure @@ -656,12 +714,19 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) return ERR_PTR(-EINVAL); } +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) +{ + return ERR_PTR(-EINVAL); +} + void stmmac_remove_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat) { } #endif /* CONFIG_OF */ EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); +EXPORT_SYMBOL_GPL(devm_stmmac_probe_config_dt); EXPORT_SYMBOL_GPL(stmmac_remove_config_dt); int stmmac_get_platform_resources(struct platform_device *pdev, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index 3fff3f59d73d8..2102c6d41464c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -13,6 +13,8 @@ struct plat_stmmacenet_data * stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); +struct plat_stmmacenet_data * +devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); void stmmac_remove_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat); diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 6582d331e72db..c64f7f2bab4ae 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -52,6 +52,12 @@ RTL8201F_ISR_DUPLEX | \ RTL8201F_ISR_LINK) #define RTL8201F_IER 0x13 +#define RTL8201F_IER_ANERR BIT(11) +#define RTL8201F_IER_DUPLEX BIT(12) +#define RTL8201F_IER_LINK BIT(13) +#define RTL8201F_IER_MASK (RTL8201F_IER_ANERR | \ + RTL8201F_IER_DUPLEX | \ + RTL8201F_IER_LINK) #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) @@ -164,11 +170,13 @@ static int rtl8201_config_intr(struct phy_device *phydev) if (err) return err; - val = BIT(13) | BIT(12) | BIT(11); - err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); + val = RTL8201F_IER_MASK; + err = phy_modify_paged(phydev, 0x7, RTL8201F_IER, + RTL8201F_IER_MASK, val); } else { val = 0; - err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); + err = phy_modify_paged(phydev, 0x7, RTL8201F_IER, + RTL8201F_IER_MASK, val); if (err) return err;