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..f85dbac94294b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts @@ -21,7 +21,7 @@ }; chosen { - stdout-path = "serial0:1500000n8"; + bootargs = "root=UUID=bbc884d7-bf5a-4713-9301-03dbb8cacab0 earlycon=uart8250,mmio32,0xff0a0000 swiotlb=1 kpti=0 console=ttyFIQ0 rw rootwait coherent_pool=1m"; }; leds { @@ -129,6 +129,11 @@ }; }; +&fiq_debugger{ + rockchip,serial-id = <0>; + status = "okay"; +}; + &cpu0 { cpu-supply = <&vdd_core>; }; @@ -144,10 +149,22 @@ 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>; phy-supply = <&vcc_io>; + tx_delay = <0x30>; + rx_delay = <0x10>; status = "okay"; mdio { @@ -235,23 +252,21 @@ &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>; vqmmc-supply = <&vcc_1v8>; + non-removable; + sd-uhs-sdr104; status = "okay"; rtl8723ds: wifi@1 { - reg = <1>; interrupt-parent = <&gpio0>; - interrupts = ; + interrupts = ; interrupt-names = "host-wake"; pinctrl-names = "default"; pinctrl-0 = <&wifi_host_wake>; @@ -283,7 +298,7 @@ &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer>; - status = "okay"; + status = "disabled"; }; &uart4 { 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..52e86704414e4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -60,12 +60,6 @@ #define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) -#define RTL8211F_PHY_UID 0x001cc800 -#define RTL8211F_PHY_UID_MASK 0x001ffc00 -#define RTL8211F_PAGE_SELECT 0x1f -#define RTL8211F_LCR_ADDR 0x10 -#define RTL8211F_EEELCR_ADDR 0x11 - /* Module parameters */ #define TX_TIMEO 5000 static int watchdog = TX_TIMEO; @@ -3679,6 +3673,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 +4198,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 +4216,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]; @@ -7086,49 +7093,6 @@ void stmmac_fpe_handshake(struct stmmac_priv *priv, bool enable) } } -static int phy_rtl8211f_led_fixup(struct phy_device *phydev) -{ - u32 val, val2; - - /* Switch to Page 0x0d04 */ - phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0d04); - - /* Set LED1(Green) Link 10/100/1000M + Active, and set LED2(Yellow) Link 10/100/1000M */ - val = phy_read(phydev, RTL8211F_LCR_ADDR); - val |= (1<<5); - val |= (1<<8); - val |= (1<<10); - val |= (1<<11); - val &= (~(1<<14)); - phy_write(phydev, RTL8211F_LCR_ADDR, val); - - /* Disable LED2(Yellow) EEE LED function to keep it on when linked */ - val2 = phy_read(phydev, RTL8211F_EEELCR_ADDR); - val2 &= (~(1<<3)); - phy_write(phydev, RTL8211F_EEELCR_ADDR, val2); - - /* Switch back to the PHY's IEEE Standard Registers. Here it is Page 0 */ - phy_write(phydev, RTL8211F_PAGE_SELECT, 0); - - return 0; -} - -static int phy_rtl8211f_eee_fixup(struct phy_device *phydev) -{ - phy_write(phydev, 31, 0x0000); - phy_write(phydev, 0, 0x8000); - mdelay(20); - phy_write(phydev, 31, 0x0a4b); - phy_write(phydev, 17, 0x1110); - phy_write(phydev, 31, 0x0000); - phy_write(phydev, 13, 0x0007); - phy_write(phydev, 14, 0x003c); - phy_write(phydev, 13, 0x4007); - phy_write(phydev, 14, 0x0000); - - return 0; -} - /** * stmmac_dvr_probe * @device: device pointer @@ -7413,18 +7377,6 @@ int stmmac_dvr_probe(struct device *device, */ pm_runtime_put(device); - /* Register fixup for PHY RTL8211F */ - ret = phy_register_fixup_for_uid(RTL8211F_PHY_UID, RTL8211F_PHY_UID_MASK, phy_rtl8211f_led_fixup); - if (ret) { - dev_warn(priv->device, "Failed to register fixup for PHY RTL8211F.\n"); - } - - /* Register fixup for PHY RTL8211F disabling EEE */ - ret = phy_register_fixup_for_uid(RTL8211F_PHY_UID, RTL8211F_PHY_UID_MASK, phy_rtl8211f_eee_fixup); - if (ret) { - dev_warn(priv->device, "Failed to register fixup for PHY RTL8211F disabling EEE.\n"); - } - return ret; error_netdev_register: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 3f7f1522cc427..85ccc237972f2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -356,8 +356,8 @@ int stmmac_mdio_idle(struct mii_bus *bus) reset_gpio = devm_gpiod_get_optional(priv->device, "snps,reset", GPIOD_OUT_HIGH); - if (IS_ERR(reset_gpio)) - return PTR_ERR(reset_gpio); + if (IS_ERR_OR_NULL(reset_gpio)) + return PTR_ERR_OR_ZERO(reset_gpio); devm_gpiod_put(priv->device, reset_gpio); } @@ -386,8 +386,8 @@ int stmmac_mdio_reset(struct mii_bus *bus) reset_gpio = devm_gpiod_get_optional(priv->device, "snps,reset", GPIOD_OUT_LOW); - if (IS_ERR(reset_gpio)) - return PTR_ERR(reset_gpio); + if (IS_ERR_OR_NULL(reset_gpio)) + return PTR_ERR_OR_ZERO(reset_gpio); device_property_read_u32_array(priv->device, "snps,reset-delays-us", 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/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 701dd3949b113..c7c1f8eef1831 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1964,10 +1964,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status); static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) { #ifdef CONFIG_ARCH_ROCKCHIP - if ((iir & 0xf) != UART_IIR_RX_TIMEOUT) - return 0; - else - return up->dma->rx_dma(up); + switch (iir & 0x3f) { + case UART_IIR_RDI: + if (!up->dma->rx_running) + break; + fallthrough; + case UART_IIR_RLSI: + case UART_IIR_RX_TIMEOUT: + serial8250_rx_dma_flush(up); + return true; + } + return up->dma->rx_dma(up); #else switch (iir & 0x3f) { case UART_IIR_THRI: