Merge branch 'main' of https://git.u-boot-project.org/u-boot/custodians/u-boot-sunxi
Beside a fix for a long standing bug in the A80 eMMC code, this adds SPI booting support for the Allwinner A523/A527/T527 class of boards. The second major feature is support for the secondary Ethernet controller on that same SoC. This might not be as important as for the kernel (I doubt that U-Boot acts as a router), but for once some boards only connect the secondary EMAC, and on others people might have the boot server only reachable via this port. There are some smaller fixes and improvements still queued up, but they need some more testing and are minor, so can land a bit later. The world build timed out, but the rest passed, and I booted that briefly on an A523 board with two Ethernet ports.
This commit is contained in:
@@ -209,6 +209,13 @@ config SUN6I_PRCM
|
||||
Support for the PRCM (Power/Reset/Clock Management) unit available
|
||||
in A31 SoC.
|
||||
|
||||
config SUNXI_SYSCON
|
||||
bool
|
||||
select SYSCON
|
||||
help
|
||||
Enable syscon driver for Allwinner system controllers, which provides
|
||||
access to the SRAM/system-control node for drivers.
|
||||
|
||||
config AXP_PMIC_BUS
|
||||
bool
|
||||
select DM_PMIC if DM_I2C
|
||||
|
||||
@@ -10,6 +10,7 @@ obj-y += board.o
|
||||
obj-y += cpu_info.o
|
||||
obj-y += dram_helpers.o
|
||||
obj-$(CONFIG_SUN6I_PRCM) += prcm.o
|
||||
obj-$(CONFIG_SUNXI_SYSCON) += syscon.o
|
||||
obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
|
||||
obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
|
||||
obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o
|
||||
|
||||
@@ -105,35 +105,30 @@
|
||||
|
||||
/*
|
||||
* Allwinner A10/A20 SoCs were using pins PC0,PC1,PC2,PC23 for booting
|
||||
* from SPI Flash, everything else is using pins PC0,PC1,PC2,PC3.
|
||||
* The H6 uses PC0, PC2, PC3, PC5, the H616 PC0, PC2, PC3, PC4.
|
||||
* from SPI Flash, later SoCs are using pins PC0,PC1,PC2,PC3.
|
||||
* Newer SoCs are all over the place.
|
||||
*/
|
||||
static void spi0_pinmux_setup(unsigned int pin_function)
|
||||
{
|
||||
/* All chips use PC2. And all chips use PC0, except R528/T113 */
|
||||
if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
|
||||
const u16 spi0_pc_pins[4] = {
|
||||
#if IS_ENABLED(CONFIG_MACH_SUN8I_R528)
|
||||
SUNXI_GPC(2), SUNXI_GPC(3), SUNXI_GPC(4), SUNXI_GPC(5)
|
||||
#elif IS_ENABLED(CONFIG_MACH_SUN55I_A523)
|
||||
SUNXI_GPC(2), SUNXI_GPC(3), SUNXI_GPC(4), SUNXI_GPC(12)
|
||||
#elif IS_ENABLED(CONFIG_MACH_SUN50I_H616)
|
||||
SUNXI_GPC(0), SUNXI_GPC(2), SUNXI_GPC(3), SUNXI_GPC(4)
|
||||
#elif IS_ENABLED(CONFIG_MACH_SUN50I_H6)
|
||||
SUNXI_GPC(0), SUNXI_GPC(2), SUNXI_GPC(3), SUNXI_GPC(5)
|
||||
#elif IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I) || \
|
||||
IS_ENABLED(CONFIG_MACH_SUN8I_R40)
|
||||
SUNXI_GPC(0), SUNXI_GPC(1), SUNXI_GPC(2), SUNXI_GPC(23)
|
||||
#else
|
||||
SUNXI_GPC(0), SUNXI_GPC(1), SUNXI_GPC(2), SUNXI_GPC(3)
|
||||
#endif
|
||||
};
|
||||
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
|
||||
|
||||
/* All chips except H6/H616/R528/T113 use PC1. */
|
||||
if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
|
||||
!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(1), pin_function);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN50I_H6) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN8I_R528))
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(5), pin_function);
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN8I_R528))
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(4), pin_function);
|
||||
|
||||
/* Older generations use PC23 for CS, newer ones use PC3. */
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN8I_R40))
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_function);
|
||||
else
|
||||
sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_function);
|
||||
for (int i = 0; i < 4; i++)
|
||||
sunxi_gpio_set_cfgpin(spi0_pc_pins[i], pin_function);
|
||||
}
|
||||
|
||||
static bool is_sun6i_gen_spi(void)
|
||||
@@ -257,7 +252,8 @@ static void spi0_init(void)
|
||||
unsigned int pin_function = SUNXI_GPC_SPI0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
|
||||
IS_ENABLED(CONFIG_SUN50I_GEN_H6))
|
||||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN55I_A523))
|
||||
pin_function = SUN50I_GPC_SPI0;
|
||||
else if (IS_ENABLED(CONFIG_MACH_SUNIV) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN8I_R528))
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2026 Junhui Liu <junhui.liu@pigmoral.tech>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <syscon.h>
|
||||
|
||||
static const struct udevice_id sunxi_syscon_ids[] = {
|
||||
{ .compatible = "allwinner,sun4i-a10-sram-controller" },
|
||||
{ .compatible = "allwinner,sun4i-a10-system-control" },
|
||||
{ .compatible = "allwinner,sun5i-a13-system-control" },
|
||||
{ .compatible = "allwinner,sun8i-a23-system-control" },
|
||||
{ .compatible = "allwinner,sun8i-h3-system-control" },
|
||||
{ .compatible = "allwinner,sun20i-d1-system-control" },
|
||||
{ .compatible = "allwinner,sun50i-a64-sram-controller" },
|
||||
{ .compatible = "allwinner,sun50i-a64-system-control" },
|
||||
{ .compatible = "allwinner,sun50i-h5-system-control" },
|
||||
{ .compatible = "allwinner,sun50i-h616-system-control" },
|
||||
{ .compatible = "allwinner,sun55i-a523-system-control" },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sunxi_syscon) = {
|
||||
.name = "sunxi_syscon",
|
||||
.id = UCLASS_SYSCON,
|
||||
.of_match = sunxi_syscon_ids,
|
||||
};
|
||||
@@ -16,6 +16,7 @@ CONFIG_DRAM_SUNXI_TPR12=0x3a373233
|
||||
CONFIG_MACH_SUN55I_A523=y
|
||||
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
CONFIG_R_I2C_ENABLE=y
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
@@ -23,10 +24,13 @@ CONFIG_SYS_I2C_MVTWSI=y
|
||||
CONFIG_SYS_I2C_SLAVE=0x7f
|
||||
CONFIG_SYS_I2C_SPEED=400000
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_SPI_FLASH_XMC=y
|
||||
CONFIG_REGULATOR_AXP=y
|
||||
CONFIG_AXP717_POWER=y
|
||||
CONFIG_AXP_I2C_ADDRESS=0x35
|
||||
CONFIG_AXP_DCDC2_VOLT=920
|
||||
CONFIG_AXP_DCDC3_VOLT=1160
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
||||
@@ -15,6 +15,7 @@ CONFIG_DRAM_SUNXI_TPR12=0x3533302f
|
||||
CONFIG_MACH_SUN55I_A523=y
|
||||
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
CONFIG_R_I2C_ENABLE=y
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
CONFIG_SPL_SUNXI_LED_STATUS=y
|
||||
CONFIG_SPL_SUNXI_LED_STATUS_GPIO=356
|
||||
# CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH is not set
|
||||
@@ -25,11 +26,19 @@ CONFIG_SYS_I2C_MVTWSI=y
|
||||
CONFIG_SYS_I2C_SLAVE=0x7f
|
||||
CONFIG_SYS_I2C_SPEED=400000
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_DM_MDIO=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_DWC_ETH_QOS=y
|
||||
CONFIG_DWC_ETH_QOS_SUNXI=y
|
||||
CONFIG_RGMII=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_REGULATOR_AXP=y
|
||||
CONFIG_AXP717_POWER=y
|
||||
CONFIG_AXP_DCDC2_VOLT=920
|
||||
CONFIG_AXP_DCDC3_VOLT=1100
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
||||
@@ -16,6 +16,7 @@ static struct ccu_clk_gate a523_gates[] = {
|
||||
[CLK_PLL_PERIPH0_200M] = GATE_DUMMY,
|
||||
[CLK_APB1] = GATE_DUMMY,
|
||||
|
||||
[CLK_MBUS_EMAC1] = GATE(0x804, BIT(12)),
|
||||
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
|
||||
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
|
||||
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
|
||||
|
||||
@@ -576,8 +576,8 @@ struct mmc *sunxi_mmc_init(int sdc_no)
|
||||
cfg->host_caps = MMC_MODE_4BIT;
|
||||
|
||||
if ((IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN8I) ||
|
||||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_MACH_SUN55I_A523)) &&
|
||||
(sdc_no == 2))
|
||||
IS_ENABLED(CONFIG_MACH_SUN9I) || IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN55I_A523)) && (sdc_no == 2))
|
||||
cfg->host_caps = MMC_MODE_8BIT;
|
||||
|
||||
cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
||||
@@ -663,7 +663,7 @@ static const struct dm_mmc_ops sunxi_mmc_ops = {
|
||||
|
||||
static unsigned get_mclk_offset(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN9I))
|
||||
return 0x410;
|
||||
|
||||
if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
|
||||
|
||||
@@ -284,6 +284,15 @@ config DWC_ETH_QOS_STM32
|
||||
The Synopsys Designware Ethernet QOS IP block with the specific
|
||||
configuration used in STM32MP soc.
|
||||
|
||||
config DWC_ETH_QOS_SUNXI
|
||||
bool "Synopsys DWC Ethernet QOS device support for Allwinner SoCs"
|
||||
depends on DWC_ETH_QOS && ARCH_SUNXI
|
||||
select REGMAP
|
||||
select SUNXI_SYSCON
|
||||
help
|
||||
The Synopsys Designware Ethernet QOS IP block with specific
|
||||
configuration used in Allwinner SoCs.
|
||||
|
||||
config DWC_ETH_QOS_TEGRA186
|
||||
bool "Synopsys DWC Ethernet QOS device support for TEGRA186"
|
||||
depends on DWC_ETH_QOS
|
||||
|
||||
@@ -26,6 +26,7 @@ obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_STM32) += dwc_eth_qos_stm32.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_SUNXI) += dwc_eth_qos_sunxi.o
|
||||
obj-$(CONFIG_DWC_ETH_XGMAC) += dwc_eth_xgmac.o
|
||||
obj-$(CONFIG_DWC_ETH_XGMAC_SOCFPGA) += dwc_eth_xgmac_socfpga.o
|
||||
obj-$(CONFIG_E1000) += e1000.o
|
||||
|
||||
@@ -1664,6 +1664,12 @@ static const struct udevice_id eqos_ids[] = {
|
||||
.compatible = "mediatek,mt8189-gmac",
|
||||
.data = (ulong)&eqos_mtk_config
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_DWC_ETH_QOS_SUNXI)
|
||||
{
|
||||
.compatible = "allwinner,sun55i-a523-gmac200",
|
||||
.data = (ulong)&eqos_sunxi_config
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -318,3 +318,4 @@ extern struct eqos_config eqos_stm32mp25_config;
|
||||
extern struct eqos_config eqos_jh7110_config;
|
||||
extern struct eqos_config eqos_adi_config;
|
||||
extern struct eqos_config eqos_mtk_config;
|
||||
extern struct eqos_config eqos_sunxi_config;
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2017 Corentin Labbe <clabbe.montjoie@gmail.com>
|
||||
* Copyright (C) 2025 Chen-Yu Tsai <wens@csie.org>
|
||||
* Copyright (C) 2026 Junhui Liu <junhui.liu@pigmoral.tech>
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <net.h>
|
||||
#include <phy.h>
|
||||
#include <power/regulator.h>
|
||||
#include <regmap.h>
|
||||
#include <reset.h>
|
||||
#include <malloc.h>
|
||||
#include <syscon.h>
|
||||
|
||||
#include "dwc_eth_qos.h"
|
||||
|
||||
#define SYSCON_REG 0x34
|
||||
|
||||
#define SYSCON_PHY_SELECT BIT(15) /* 1: internal, 0: external */
|
||||
/* RMII specific bits */
|
||||
#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */
|
||||
/* Generic system control EMAC_CLK bits */
|
||||
#define SYSCON_ETXDC_MASK GENMASK(12, 10)
|
||||
#define SYSCON_ERXDC_MASK GENMASK(9, 5)
|
||||
/* EMAC PHY Interface Type */
|
||||
#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */
|
||||
#define SYSCON_ETCS_MASK GENMASK(1, 0)
|
||||
#define SYSCON_ETCS_MII 0x0
|
||||
#define SYSCON_ETCS_EXT_GMII 0x1
|
||||
#define SYSCON_ETCS_INT_GMII 0x2
|
||||
|
||||
struct sunxi_platform_data {
|
||||
struct clk_bulk clks;
|
||||
struct reset_ctl_bulk resets;
|
||||
};
|
||||
|
||||
static int sunxi_gmac_set_syscon(struct udevice *dev,
|
||||
phy_interface_t interface_type)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
u32 val, reg = 0;
|
||||
int ret;
|
||||
|
||||
regmap = syscon_regmap_lookup_by_phandle(dev, "syscon");
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(dev, "Unable to map syscon\n");
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
if (!dev_read_u32(dev, "tx-internal-delay-ps", &val)) {
|
||||
if (val % 100) {
|
||||
dev_err(dev, "tx-delay must be a multiple of 100\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
val /= 100;
|
||||
dev_dbg(dev, "set tx-delay to %x\n", val);
|
||||
|
||||
if (!FIELD_FIT(SYSCON_ETXDC_MASK, val)) {
|
||||
dev_err(dev, "TX clock delay exceeds maximum\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg |= FIELD_PREP(SYSCON_ETXDC_MASK, val);
|
||||
}
|
||||
|
||||
if (!dev_read_u32(dev, "rx-internal-delay-ps", &val)) {
|
||||
if (val % 100) {
|
||||
dev_err(dev, "rx-delay must be a multiple of 100\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
val /= 100;
|
||||
dev_dbg(dev, "set rx-delay to %x\n", val);
|
||||
if (!FIELD_FIT(SYSCON_ERXDC_MASK, val)) {
|
||||
dev_err(dev, "Invalid RX clock delay: %d\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg |= FIELD_PREP(SYSCON_ERXDC_MASK, val);
|
||||
}
|
||||
|
||||
switch (interface_type) {
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
/* default */
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
reg |= SYSCON_RMII_EN;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported interface mode: %s\n",
|
||||
phy_interface_strings[interface_type]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(regmap, SYSCON_REG, reg);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to write to syscon\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_start_clks_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return clk_enable_bulk(&data->clks);
|
||||
}
|
||||
|
||||
static int eqos_stop_clks_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return clk_disable_bulk(&data->clks);
|
||||
}
|
||||
|
||||
static int eqos_start_resets_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data = pdata->priv_pdata;
|
||||
int ret;
|
||||
|
||||
ret = reset_deassert_bulk(&data->resets);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sunxi_gmac_set_syscon(dev, pdata->phy_interface);
|
||||
}
|
||||
|
||||
static int eqos_stop_resets_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return reset_assert_bulk(&data->resets);
|
||||
}
|
||||
|
||||
static int eqos_probe_resources_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data;
|
||||
struct udevice *phy_supply = NULL;
|
||||
int ret;
|
||||
|
||||
ret = eqos_get_base_addr_dt(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get base address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = calloc(1, sizeof(struct sunxi_platform_data));
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata->priv_pdata = data;
|
||||
|
||||
pdata->phy_interface = eqos->config->interface(dev);
|
||||
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
|
||||
dev_err(dev, "Failed to get PHY interface mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get stmmaceth clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_bulk(dev, &data->resets);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get resets: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_bulk(dev, &data->clks);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get clocks: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
|
||||
ret = device_get_supply_regulator(dev, "phy-supply", &phy_supply);
|
||||
if (ret && ret != -ENOENT) {
|
||||
dev_err(dev, "Failed to get PHY supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (phy_supply) {
|
||||
ret = regulator_set_enable_if_allowed(phy_supply, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable phy supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_remove_resources_sunxi(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct sunxi_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
reset_assert_bulk(&data->resets);
|
||||
clk_disable_bulk(&data->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct eqos_ops eqos_sunxi_ops = {
|
||||
.eqos_inval_desc = eqos_inval_desc_generic,
|
||||
.eqos_flush_desc = eqos_flush_desc_generic,
|
||||
.eqos_inval_buffer = eqos_inval_buffer_generic,
|
||||
.eqos_flush_buffer = eqos_flush_buffer_generic,
|
||||
.eqos_probe_resources = eqos_probe_resources_sunxi,
|
||||
.eqos_remove_resources = eqos_remove_resources_sunxi,
|
||||
.eqos_stop_resets = eqos_stop_resets_sunxi,
|
||||
.eqos_start_resets = eqos_start_resets_sunxi,
|
||||
.eqos_stop_clks = eqos_stop_clks_sunxi,
|
||||
.eqos_start_clks = eqos_start_clks_sunxi,
|
||||
.eqos_calibrate_pads = eqos_null_ops,
|
||||
.eqos_disable_calibration = eqos_null_ops,
|
||||
.eqos_set_tx_clk_speed = eqos_null_ops,
|
||||
.eqos_get_enetaddr = eqos_null_ops,
|
||||
};
|
||||
|
||||
struct eqos_config __maybe_unused eqos_sunxi_config = {
|
||||
.reg_access_always_ok = false,
|
||||
.mdio_wait = 10,
|
||||
.swr_wait = 50,
|
||||
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
|
||||
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_150_250,
|
||||
.axi_bus_width = EQOS_AXI_WIDTH_64,
|
||||
.interface = dev_read_phy_mode,
|
||||
.ops = &eqos_sunxi_ops
|
||||
};
|
||||
@@ -761,7 +761,8 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc =
|
||||
};
|
||||
|
||||
static const struct sunxi_pinctrl_function sun55i_a523_pinctrl_functions[] = {
|
||||
{ "gmac0", 5 }, /* PI0-PI16 */
|
||||
{ "gmac0", 5 }, /* PH0-PH7, PH9-PH10, PH14-PH18 */
|
||||
{ "gmac1", 5 }, /* PJ0-PJ9, PJ11-PJ15 */
|
||||
{ "gpio_in", 0 },
|
||||
{ "gpio_out", 1 },
|
||||
{ "mmc0", 2 }, /* PF0-PF5 */
|
||||
|
||||
@@ -587,6 +587,10 @@ static const struct udevice_id sun4i_spi_ids[] = {
|
||||
.compatible = "allwinner,sun50i-r329-spi",
|
||||
.data = (ulong)&sun50i_r329_spi_variant,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun55i-a523-spi",
|
||||
.data = (ulong)&sun50i_r329_spi_variant,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user