Merge branch '2022-08-08-networking-updates'

After checking with Ramon, take a number of reviewed network patches.
This includes:

- A number of dwc_eth_qos updates, mpc8xx_fec DM migration, NPCM7xx EMAC
  driver.
- Other assorted minor updates
This commit is contained in:
Tom Rini 2022-08-08 15:04:56 -04:00
commit ae0e1d68a9
24 changed files with 1198 additions and 308 deletions

View File

@ -734,7 +734,7 @@
clocks = <&sys_clk 6>; clocks = <&sys_clk 6>;
reset-names = "ether"; reset-names = "ether";
resets = <&sys_rst 6>; resets = <&sys_rst 6>;
phy-mode = "rgmii"; phy-mode = "rgmii-id";
local-mac-address = [00 00 00 00 00 00]; local-mac-address = [00 00 00 00 00 00];
socionext,syscon-phy-mode = <&soc_glue 0>; socionext,syscon-phy-mode = <&soc_glue 0>;

View File

@ -583,7 +583,7 @@
clocks = <&sys_clk 6>; clocks = <&sys_clk 6>;
reset-names = "ether"; reset-names = "ether";
resets = <&sys_rst 6>; resets = <&sys_rst 6>;
phy-mode = "rgmii"; phy-mode = "rgmii-id";
local-mac-address = [00 00 00 00 00 00]; local-mac-address = [00 00 00 00 00 00];
socionext,syscon-phy-mode = <&soc_glue 0>; socionext,syscon-phy-mode = <&soc_glue 0>;

View File

@ -564,7 +564,7 @@
clocks = <&sys_clk 6>; clocks = <&sys_clk 6>;
reset-names = "ether"; reset-names = "ether";
resets = <&sys_rst 6>; resets = <&sys_rst 6>;
phy-mode = "rgmii"; phy-mode = "rgmii-id";
local-mac-address = [00 00 00 00 00 00]; local-mac-address = [00 00 00 00 00 00];
socionext,syscon-phy-mode = <&soc_glue 0>; socionext,syscon-phy-mode = <&soc_glue 0>;
@ -585,7 +585,7 @@
clocks = <&sys_clk 7>; clocks = <&sys_clk 7>;
reset-names = "ether"; reset-names = "ether";
resets = <&sys_rst 7>; resets = <&sys_rst 7>;
phy-mode = "rgmii"; phy-mode = "rgmii-id";
local-mac-address = [00 00 00 00 00 00]; local-mac-address = [00 00 00 00 00 00];
socionext,syscon-phy-mode = <&soc_glue 1>; socionext,syscon-phy-mode = <&soc_glue 1>;

View File

@ -266,15 +266,3 @@ unsigned long get_tbclk(void)
return oscclk / 16; return oscclk / 16;
} }
/*
* Initializes on-chip ethernet controllers.
* to override, implement board_eth_init()
*/
int cpu_eth_init(struct bd_info *bis)
{
#if defined(CONFIG_MPC8XX_FEC)
fec_initialize(bis);
#endif
return 0;
}

View File

@ -16,6 +16,10 @@
compatible = "fsl,pq1-smc"; compatible = "fsl,pq1-smc";
}; };
FEC: fec@0 {
compatible = "fsl,pq1-fec1";
};
chosen { chosen {
stdout-path = &SERIAL; stdout-path = &SERIAL;
}; };

View File

@ -91,3 +91,4 @@ CONFIG_DM_SERIAL=y
CONFIG_WDT=y CONFIG_WDT=y
CONFIG_SHA256=y CONFIG_SHA256=y
CONFIG_LZMA=y CONFIG_LZMA=y
CONFIG_DM_ETH=y

View File

@ -523,6 +523,11 @@ config MT7628_ETH
The MediaTek MT7628 ethernet interface is used on MT7628 and The MediaTek MT7628 ethernet interface is used on MT7628 and
MT7688 based boards. MT7688 based boards.
config NET_NPCM750
bool "Nuvoton NPCM750 Ethernet MAC"
help
support NPCM750 EMAC
config NET_OCTEON config NET_OCTEON
bool "MIPS Octeon ethernet support" bool "MIPS Octeon ethernet support"
depends on ARCH_OCTEON depends on ARCH_OCTEON
@ -744,6 +749,7 @@ config RENESAS_RAVB
config MPC8XX_FEC config MPC8XX_FEC
bool "Fast Ethernet Controller on MPC8XX" bool "Fast Ethernet Controller on MPC8XX"
depends on MPC8xx depends on MPC8xx
depends on DM_ETH
select MII select MII
select SYS_DISCOVER_PHY select SYS_DISCOVER_PHY
help help

View File

@ -65,6 +65,7 @@ obj-$(CONFIG_MVMDIO) += mvmdio.o
obj-$(CONFIG_MVNETA) += mvneta.o obj-$(CONFIG_MVNETA) += mvneta.o
obj-$(CONFIG_MVPP2) += mvpp2.o obj-$(CONFIG_MVPP2) += mvpp2.o
obj-$(CONFIG_NETCONSOLE) += netconsole.o obj-$(CONFIG_NETCONSOLE) += netconsole.o
obj-$(CONFIG_NET_NPCM750) += npcm750_eth.o
obj-$(CONFIG_NET_OCTEON) += octeon/ obj-$(CONFIG_NET_OCTEON) += octeon/
obj-$(CONFIG_NET_OCTEONTX) += octeontx/ obj-$(CONFIG_NET_OCTEONTX) += octeontx/
obj-$(CONFIG_NET_OCTEONTX2) += octeontx2/ obj-$(CONFIG_NET_OCTEONTX2) += octeontx2/

View File

@ -666,10 +666,10 @@ static int dm9000_recv(struct udevice *dev, int flags, uchar **packetp)
int ret; int ret;
ret = dm9000_recv_common(db, data); ret = dm9000_recv_common(db, data);
if (ret) if (ret > 0)
*packetp = (void *)data; *packetp = (void *)data;
return ret ? ret : -EAGAIN; return ret >= 0 ? ret : -EAGAIN;
} }
static int dm9000_write_hwaddr(struct udevice *dev) static int dm9000_write_hwaddr(struct udevice *dev)

View File

@ -34,6 +34,7 @@
#include <cpu_func.h> #include <cpu_func.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <eth_phy.h>
#include <log.h> #include <log.h>
#include <malloc.h> #include <malloc.h>
#include <memalign.h> #include <memalign.h>
@ -46,7 +47,6 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/io.h> #include <asm/io.h>
#include <eth_phy.h>
#ifdef CONFIG_ARCH_IMX8M #ifdef CONFIG_ARCH_IMX8M
#include <asm/arch/clock.h> #include <asm/arch/clock.h>
#include <asm/mach-imx/sys_proto.h> #include <asm/mach-imx/sys_proto.h>
@ -789,9 +789,6 @@ static int eqos_start(struct udevice *dev)
if (!eqos->phy) { if (!eqos->phy) {
int addr = -1; int addr = -1;
addr = eqos_get_phy_addr(eqos, dev); addr = eqos_get_phy_addr(eqos, dev);
#ifdef DWC_NET_PHYADDR
addr = DWC_NET_PHYADDR;
#endif
eqos->phy = phy_connect(eqos->mii, addr, dev, eqos->phy = phy_connect(eqos->mii, addr, dev,
eqos->config->interface(dev)); eqos->config->interface(dev));
if (!eqos->phy) { if (!eqos->phy) {
@ -1399,8 +1396,6 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
if (ret) if (ret)
return -EINVAL; return -EINVAL;
eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
if (ret) { if (ret) {
pr_err("clk_get_by_name(master_bus) failed: %d", ret); pr_err("clk_get_by_name(master_bus) failed: %d", ret);
@ -1503,6 +1498,8 @@ static int eqos_probe(struct udevice *dev)
eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE);
eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE);
eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
ret = eqos_probe_resources_core(dev); ret = eqos_probe_resources_core(dev);
if (ret < 0) { if (ret < 0) {
pr_err("eqos_probe_resources_core() failed: %d", ret); pr_err("eqos_probe_resources_core() failed: %d", ret);
@ -1574,7 +1571,7 @@ static int eqos_remove(struct udevice *dev)
eqos->config->ops->eqos_stop_clks(dev); eqos->config->ops->eqos_stop_clks(dev);
eqos->config->ops->eqos_remove_resources(dev); eqos->config->ops->eqos_remove_resources(dev);
eqos_probe_resources_core(dev); eqos_remove_resources_core(dev);
debug("%s: OK\n", __func__); debug("%s: OK\n", __func__);
return 0; return 0;
@ -1609,6 +1606,7 @@ static struct eqos_ops eqos_tegra186_ops = {
.eqos_calibrate_pads = eqos_calibrate_pads_tegra186, .eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
.eqos_disable_calibration = eqos_disable_calibration_tegra186, .eqos_disable_calibration = eqos_disable_calibration_tegra186,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
.eqos_get_enetaddr = eqos_null_ops,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
}; };
@ -1637,6 +1635,7 @@ static struct eqos_ops eqos_stm32_ops = {
.eqos_calibrate_pads = eqos_null_ops, .eqos_calibrate_pads = eqos_null_ops,
.eqos_disable_calibration = eqos_null_ops, .eqos_disable_calibration = eqos_null_ops,
.eqos_set_tx_clk_speed = eqos_null_ops, .eqos_set_tx_clk_speed = eqos_null_ops,
.eqos_get_enetaddr = eqos_null_ops,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
}; };

View File

@ -119,7 +119,7 @@ static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr,
FTGMAC100_MDIO_TIMEOUT_USEC); FTGMAC100_MDIO_TIMEOUT_USEC);
if (ret) { if (ret) {
pr_err("%s: mdio read failed (phy:%d reg:%x)\n", pr_err("%s: mdio read failed (phy:%d reg:%x)\n",
priv->phydev->dev->name, phy_addr, reg_addr); bus->name, phy_addr, reg_addr);
return ret; return ret;
} }
@ -151,7 +151,7 @@ static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr,
FTGMAC100_MDIO_TIMEOUT_USEC); FTGMAC100_MDIO_TIMEOUT_USEC);
if (ret) { if (ret) {
pr_err("%s: mdio write failed (phy:%d reg:%x)\n", pr_err("%s: mdio write failed (phy:%d reg:%x)\n",
priv->phydev->dev->name, phy_addr, reg_addr); bus->name, phy_addr, reg_addr);
} }
return ret; return ret;

View File

@ -41,7 +41,7 @@ DECLARE_GLOBAL_DATA_PTR;
#endif #endif
#ifdef CONFIG_SYS_DISCOVER_PHY #ifdef CONFIG_SYS_DISCOVER_PHY
static int mii_discover_phy(struct eth_device *dev); static int mii_discover_phy(struct udevice *dev);
#endif #endif
int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg); int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
@ -111,50 +111,24 @@ struct common_buf_desc {
static struct common_buf_desc __iomem *rtx; static struct common_buf_desc __iomem *rtx;
static int fec_send(struct eth_device *dev, void *packet, int length);
static int fec_recv(struct eth_device *dev);
static int fec_init(struct eth_device *dev, struct bd_info *bd);
static void fec_halt(struct eth_device *dev);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
static void __mii_init(void); static void __mii_init(void);
#endif #endif
int fec_initialize(struct bd_info *bis) static int fec_probe(struct udevice *dev)
{ {
struct eth_device *dev; struct ether_fcc_info_s *efis = dev_get_priv(dev);
struct ether_fcc_info_s *efis; int index = dev_get_driver_data(dev);
int i; int i;
for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) { for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
dev = malloc(sizeof(*dev)); if (ether_fcc_info[i].ether_index != index)
if (dev == NULL) continue;
hang();
memset(dev, 0, sizeof(*dev)); memcpy(efis, &ether_fcc_info[i], sizeof(*efis));
/* for FEC1 make sure that the name of the interface is the same
as the old one for compatibility reasons */
if (i == 0)
strcpy(dev->name, "FEC");
else
sprintf(dev->name, "FEC%d",
ether_fcc_info[i].ether_index + 1);
efis = &ether_fcc_info[i];
/*
* reset actual phy addr
*/
efis->actual_phy_addr = -1; efis->actual_phy_addr = -1;
dev->priv = efis;
dev->init = fec_init;
dev->halt = fec_halt;
dev->send = fec_send;
dev->recv = fec_recv;
eth_register(dev);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
int retval; int retval;
struct mii_dev *mdiodev = mdio_alloc(); struct mii_dev *mdiodev = mdio_alloc();
@ -169,13 +143,13 @@ int fec_initialize(struct bd_info *bis)
return retval; return retval;
#endif #endif
} }
return 1; return 0;
} }
static int fec_send(struct eth_device *dev, void *packet, int length) static int fec_send(struct udevice *dev, void *packet, int length)
{ {
int j, rc; int j, rc;
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
fec_t __iomem *fecp = fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
@ -217,39 +191,38 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
return rc; return rc;
} }
static int fec_recv(struct eth_device *dev) static int fec_recv(struct udevice *dev, int flags, uchar **packetp)
{ {
struct ether_fcc_info_s *efis = dev->priv;
fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
int length; int length;
for (;;) {
/* section 16.9.23.2 */ /* section 16.9.23.2 */
if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) { if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY)
length = -1; return -EAGAIN;
break; /* nothing received - leave for() loop */
}
length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen); length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen);
if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) { if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) {
uchar *rx = net_rx_packets[rxIdx]; uchar *rx = net_rx_packets[rxIdx];
length -= 4;
#if defined(CONFIG_CMD_CDP) #if defined(CONFIG_CMD_CDP)
if ((rx[0] & 1) != 0 && if ((rx[0] & 1) != 0 &&
memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 && memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
!is_cdp_packet((uchar *)rx)) !is_cdp_packet((uchar *)rx))
rx = NULL; return 0;
#endif #endif
/* *packetp = rx;
* Pass the packet up to the protocol layers.
*/ return length - 4;
if (rx != NULL) } else {
net_process_received_packet(rx, length); return 0;
} }
}
static int fec_free_pkt(struct udevice *dev, uchar *packet, int length)
{
struct ether_fcc_info_s *efis = dev_get_priv(dev);
fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
/* Give the buffer back to the FEC. */ /* Give the buffer back to the FEC. */
out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0); out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0);
@ -267,9 +240,8 @@ static int fec_recv(struct eth_device *dev)
/* Try to fill Buffer Descriptors */ /* Try to fill Buffer Descriptors */
/* Descriptor polling active */ /* Descriptor polling active */
out_be32(&fecp->fec_r_des_active, 0x01000000); out_be32(&fecp->fec_r_des_active, 0x01000000);
}
return length; return 0;
} }
/************************************************************** /**************************************************************
@ -296,9 +268,9 @@ static int fec_recv(struct eth_device *dev)
#if defined(CONFIG_RMII) #if defined(CONFIG_RMII)
static inline void fec_10Mbps(struct eth_device *dev) static inline void fec_10Mbps(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
int fecidx = efis->ether_index; int fecidx = efis->ether_index;
uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
@ -309,9 +281,9 @@ static inline void fec_10Mbps(struct eth_device *dev)
setbits_be32(&immr->im_cpm.cp_cptr, mask); setbits_be32(&immr->im_cpm.cp_cptr, mask);
} }
static inline void fec_100Mbps(struct eth_device *dev) static inline void fec_100Mbps(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
int fecidx = efis->ether_index; int fecidx = efis->ether_index;
uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
@ -324,9 +296,9 @@ static inline void fec_100Mbps(struct eth_device *dev)
#endif #endif
static inline void fec_full_duplex(struct eth_device *dev) static inline void fec_full_duplex(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
fec_t __iomem *fecp = fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
@ -334,9 +306,9 @@ static inline void fec_full_duplex(struct eth_device *dev)
setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
} }
static inline void fec_half_duplex(struct eth_device *dev) static inline void fec_half_duplex(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
fec_t __iomem *fecp = fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
@ -497,9 +469,10 @@ static int fec_reset(fec_t __iomem *fecp)
return 0; return 0;
} }
static int fec_init(struct eth_device *dev, struct bd_info *bd) static int fec_start(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct eth_pdata *plat = dev_get_plat(dev);
struct ether_fcc_info_s *efis = dev_get_priv(dev);
immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
fec_t __iomem *fecp = fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
@ -529,7 +502,7 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd)
/* Set station address /* Set station address
*/ */
#define ea dev->enetaddr #define ea plat->enetaddr
out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) | out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) |
(ea[2] << 8) | ea[3]); (ea[2] << 8) | ea[3]);
out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]); out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]);
@ -665,9 +638,9 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd)
} }
static void fec_halt(struct eth_device *dev) static void fec_stop(struct udevice *dev)
{ {
struct ether_fcc_info_s *efis = dev->priv; struct ether_fcc_info_s *efis = dev_get_priv(dev);
fec_t __iomem *fecp = fec_t __iomem *fecp =
(fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
int i; int i;
@ -750,7 +723,7 @@ mii_send(uint mii_cmd)
#endif #endif
#if defined(CONFIG_SYS_DISCOVER_PHY) #if defined(CONFIG_SYS_DISCOVER_PHY)
static int mii_discover_phy(struct eth_device *dev) static int mii_discover_phy(struct udevice *dev)
{ {
#define MAX_PHY_PASSES 11 #define MAX_PHY_PASSES 11
uint phyno; uint phyno;
@ -854,3 +827,37 @@ int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
return 0; return 0;
} }
#endif #endif
static const struct eth_ops fec_ops = {
.start = fec_start,
.send = fec_send,
.recv = fec_recv,
.stop = fec_stop,
.free_pkt = fec_free_pkt,
};
static const struct udevice_id fec_ids[] = {
#ifdef CONFIG_ETHER_ON_FEC1
{
.compatible = "fsl,pq1-fec1",
.data = 0,
},
#endif
#ifdef CONFIG_ETHER_ON_FEC2
{
.compatible = "fsl,pq1-fec2",
.data = 1,
},
#endif
{ }
};
U_BOOT_DRIVER(fec) = {
.name = "fec",
.id = UCLASS_ETH,
.of_match = fec_ids,
.probe = fec_probe,
.ops = &fec_ops,
.priv_auto = sizeof(struct ether_fcc_info_s),
.plat_auto = sizeof(struct eth_pdata),
};

745
drivers/net/npcm750_eth.c Normal file
View File

@ -0,0 +1,745 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2021 Nuvoton Technology Corp.
*/
#include <common.h>
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
#include <miiphy.h>
#include <malloc.h>
#include <net.h>
#include <regmap.h>
#include <serial.h>
#include <syscon.h>
#include <asm/io.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#define MAC_ADDR_SIZE 6
#define CONFIG_TX_DESCR_NUM 32
#define CONFIG_RX_DESCR_NUM 32
#define TX_TOTAL_BUFSIZE \
((CONFIG_TX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
#define RX_TOTAL_BUFSIZE \
((CONFIG_RX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
struct npcm750_rxbd {
unsigned int sl;
unsigned int buffer;
unsigned int reserved;
unsigned int next;
} __aligned(ARCH_DMA_MINALIGN);
struct npcm750_txbd {
unsigned int mode;
unsigned int buffer;
unsigned int sl;
unsigned int next;
} __aligned(ARCH_DMA_MINALIGN);
struct emc_regs {
u32 camcmr; /* 0x00 */
u32 camen; /* 0x04 */
u32 cam0m; /* 0x08 */
u32 cam0l; /* 0x0c */
u32 cam1m; /* 0x10 */
u32 cam1l; /* 0x14 */
u32 cam2m; /* 0x18 */
u32 cam2l; /* 0x1c */
u32 cam3m; /* 0x20 */
u32 cam3l; /* 0x24 */
u32 cam4m; /* 0x28 */
u32 cam4l; /* 0x2c */
u32 cam5m; /* 0x30 */
u32 cam5l; /* 0x34 */
u32 cam6m; /* 0x38 */
u32 cam6l; /* 0x3c */
u32 cam7m; /* 0x40 */
u32 cam7l; /* 0x44 */
u32 cam8m; /* 0x48 */
u32 cam8l; /* 0x4c */
u32 cam9m; /* 0x50 */
u32 cam9l; /* 0x54 */
u32 cam10m; /* 0x58 */
u32 cam10l; /* 0x5c */
u32 cam11m; /* 0x60 */
u32 cam11l; /* 0x64 */
u32 cam12m; /* 0x68 */
u32 cam12l; /* 0x6c */
u32 cam13m; /* 0x70 */
u32 cam13l; /* 0x74 */
u32 cam14m; /* 0x78 */
u32 cam14l; /* 0x7c */
u32 cam15m; /* 0x80 */
u32 cam15l; /* 0x84 */
u32 txdlsa; /* 0x88 */
u32 rxdlsa; /* 0x8c */
u32 mcmdr; /* 0x90 */
u32 miid; /* 0x94 */
u32 miida; /* 0x98 */
u32 fftcr; /* 0x9c */
u32 tsdr; /* 0xa0 */
u32 rsdr; /* 0xa4 */
u32 dmarfc; /* 0xa8 */
u32 mien; /* 0xac */
u32 mista; /* 0xb0 */
u32 mgsta; /* 0xb4 */
u32 mpcnt; /* 0xb8 */
u32 mrpc; /* 0xbc */
u32 mrpcc; /* 0xc0 */
u32 mrepc; /* 0xc4 */
u32 dmarfs; /* 0xc8 */
u32 ctxdsa; /* 0xcc */
u32 ctxbsa; /* 0xd0 */
u32 crxdsa; /* 0xd4 */
u32 crxbsa; /* 0xd8 */
};
struct npcm750_eth_dev {
struct npcm750_txbd tdesc[CONFIG_TX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
struct npcm750_rxbd rdesc[CONFIG_RX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
u8 txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
u8 rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
struct emc_regs *emc_regs_p;
struct phy_device *phydev;
struct mii_dev *bus;
struct npcm750_txbd *curr_txd;
struct npcm750_rxbd *curr_rxd;
u32 interface;
u32 max_speed;
u32 idx;
struct regmap *gcr_regmap;
};
struct npcm750_eth_pdata {
struct eth_pdata eth_pdata;
};
/* mac controller bit */
#define MCMDR_RXON BIT(0)
#define MCMDR_ACP BIT(3)
#define MCMDR_SPCRC BIT(5)
#define MCMDR_TXON BIT(8)
#define MCMDR_NDEF BIT(9)
#define MCMDR_FDUP BIT(18)
#define MCMDR_ENMDC BIT(19)
#define MCMDR_OPMOD BIT(20)
#define MCMDR_SWR BIT(24)
/* cam command regiser */
#define CAMCMR_AUP 0x01
#define CAMCMR_AMP BIT(1)
#define CAMCMR_ABP BIT(2)
#define CAMCMR_CCAM BIT(3)
#define CAMCMR_ECMP BIT(4)
#define CAM0EN 0x01
/* mac mii controller bit */
#define MDCON BIT(19)
#define PHYAD BIT(8)
#define PHYWR BIT(16)
#define PHYBUSY BIT(17)
#define PHYPRESP BIT(18)
#define CAM_ENTRY_SIZE 0x08
/* rx and tx status */
#define TXDS_TXCP BIT(19)
#define RXDS_CRCE BIT(17)
#define RXDS_PTLE BIT(19)
#define RXDS_RXGD BIT(20)
#define RXDS_ALIE BIT(21)
#define RXDS_RP BIT(22)
/* mac interrupt status*/
#define MISTA_RXINTR BIT(0)
#define MISTA_CRCE BIT(1)
#define MISTA_RXOV BIT(2)
#define MISTA_PTLE BIT(3)
#define MISTA_RXGD BIT(4)
#define MISTA_ALIE BIT(5)
#define MISTA_RP BIT(6)
#define MISTA_MMP BIT(7)
#define MISTA_DFOI BIT(8)
#define MISTA_DENI BIT(9)
#define MISTA_RDU BIT(10)
#define MISTA_RXBERR BIT(11)
#define MISTA_CFR BIT(14)
#define MISTA_TXINTR BIT(16)
#define MISTA_TXEMP BIT(17)
#define MISTA_TXCP BIT(18)
#define MISTA_EXDEF BIT(19)
#define MISTA_NCS BIT(20)
#define MISTA_TXABT BIT(21)
#define MISTA_LC BIT(22)
#define MISTA_TDU BIT(23)
#define MISTA_TXBERR BIT(24)
#define ENSTART 0x01
#define ENRXINTR BIT(0)
#define ENCRCE BIT(1)
#define EMRXOV BIT(2)
#define ENPTLE BIT(3)
#define ENRXGD BIT(4)
#define ENALIE BIT(5)
#define ENRP BIT(6)
#define ENMMP BIT(7)
#define ENDFO BIT(8)
#define ENDENI BIT(9)
#define ENRDU BIT(10)
#define ENRXBERR BIT(11)
#define ENCFR BIT(14)
#define ENTXINTR BIT(16)
#define ENTXEMP BIT(17)
#define ENTXCP BIT(18)
#define ENTXDEF BIT(19)
#define ENNCS BIT(20)
#define ENTXABT BIT(21)
#define ENLC BIT(22)
#define ENTDU BIT(23)
#define ENTXBERR BIT(24)
#define RX_STAT_RBC 0xffff
#define RX_STAT_RXINTR BIT(16)
#define RX_STAT_CRCE BIT(17)
#define RX_STAT_PTLE BIT(19)
#define RX_STAT_RXGD BIT(20)
#define RX_STAT_ALIE BIT(21)
#define RX_STAT_RP BIT(22)
#define RX_STAT_OWNER (BIT(30) | BIT(31))
#define TX_STAT_TBC 0xffff
#define TX_STAT_TXINTR BIT(16)
#define TX_STAT_DEF BIT(17)
#define TX_STAT_TXCP BIT(19)
#define TX_STAT_EXDEF BIT(20)
#define TX_STAT_NCS BIT(21)
#define TX_STAT_TXBT BIT(22)
#define TX_STAT_LC BIT(23)
#define TX_STAT_TXHA BIT(24)
#define TX_STAT_PAU BIT(25)
#define TX_STAT_SQE BIT(26)
/* rx and tx owner bit */
#define RX_OWEN_DMA BIT(31)
#define RX_OWEN_CPU 0x00 //bit 30 & bit 31
#define TX_OWEN_DMA BIT(31)
#define TX_OWEN_CPU (~(BIT(31)))
/* tx frame desc controller bit */
#define MACTXINTEN 0x04
#define CRCMODE 0x02
#define PADDINGMODE 0x01
/* fftcr controller bit */
#define RXTHD 0x03
#define TXTHD (BIT(8) | BIT(9))
#define BLENGTH BIT(21)
/* global setting for driver */
#define RX_DESC_SIZE 128
#define TX_DESC_SIZE 64
#define MAX_RBUFF_SZ 0x600
#define MAX_TBUFF_SZ 0x600
#define TX_TIMEOUT 50
#define DELAY 1000
#define CAM0 0x0
#define RX_POLL_SIZE (RX_DESC_SIZE / 2)
#define MII_TIMEOUT 100
#define GCR_INTCR 0x3c
#define INTCR_R1EN BIT(5)
enum MIIDA_MDCCR_T {
MIIDA_MDCCR_4 = 0x00,
MIIDA_MDCCR_6 = 0x01,
MIIDA_MDCCR_8 = 0x02,
MIIDA_MDCCR_12 = 0x03,
MIIDA_MDCCR_16 = 0x04,
MIIDA_MDCCR_20 = 0x05,
MIIDA_MDCCR_24 = 0x06,
MIIDA_MDCCR_28 = 0x07,
MIIDA_MDCCR_30 = 0x08,
MIIDA_MDCCR_32 = 0x09,
MIIDA_MDCCR_36 = 0x0A,
MIIDA_MDCCR_40 = 0x0B,
MIIDA_MDCCR_44 = 0x0C,
MIIDA_MDCCR_48 = 0x0D,
MIIDA_MDCCR_54 = 0x0E,
MIIDA_MDCCR_60 = 0x0F,
};
DECLARE_GLOBAL_DATA_PTR;
static int npcm750_mdio_read(struct mii_dev *bus, int addr, int devad, int regs)
{
struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv;
struct emc_regs *reg = priv->emc_regs_p;
u32 start, val;
int timeout = CONFIG_MDIO_TIMEOUT;
val = (addr << 0x08) | regs | PHYBUSY | (MIIDA_MDCCR_60 << 20);
writel(val, &reg->miida);
start = get_timer(0);
while (get_timer(start) < timeout) {
if (!(readl(&reg->miida) & PHYBUSY)) {
val = readl(&reg->miid);
return val;
}
udelay(10);
};
return -ETIMEDOUT;
}
static int npcm750_mdio_write(struct mii_dev *bus, int addr, int devad, int regs,
u16 val)
{
struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv;
struct emc_regs *reg = priv->emc_regs_p;
ulong start;
int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
writel(val, &reg->miid);
writel((addr << 0x08) | regs | PHYBUSY | PHYWR | (MIIDA_MDCCR_60 << 20), &reg->miida);
start = get_timer(0);
while (get_timer(start) < timeout) {
if (!(readl(&reg->miida) & PHYBUSY)) {
ret = 0;
break;
}
udelay(10);
};
return ret;
}
static int npcm750_mdio_reset(struct mii_dev *bus)
{
return 0;
}
static int npcm750_mdio_init(const char *name, struct npcm750_eth_dev *priv)
{
struct emc_regs *reg = priv->emc_regs_p;
struct mii_dev *bus = mdio_alloc();
if (!bus) {
printf("Failed to allocate MDIO bus\n");
return -ENOMEM;
}
bus->read = npcm750_mdio_read;
bus->write = npcm750_mdio_write;
snprintf(bus->name, sizeof(bus->name), "%s", name);
bus->reset = npcm750_mdio_reset;
bus->priv = (void *)priv;
writel(readl(&reg->mcmdr) | MCMDR_ENMDC, &reg->mcmdr);
return mdio_register(bus);
}
static void npcm750_tx_descs_init(struct npcm750_eth_dev *priv)
{
struct emc_regs *reg = priv->emc_regs_p;
struct npcm750_txbd *desc_table_p = &priv->tdesc[0];
struct npcm750_txbd *desc_p;
u8 *txbuffs = &priv->txbuffs[0];
u32 idx;
writel((u32)desc_table_p, &reg->txdlsa);
priv->curr_txd = desc_table_p;
for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
desc_p->buffer = (u32)&txbuffs[idx * PKTSIZE_ALIGN];
desc_p->sl = 0;
desc_p->mode = 0;
desc_p->mode = TX_OWEN_CPU | PADDINGMODE | CRCMODE | MACTXINTEN;
if (idx < (CONFIG_TX_DESCR_NUM - 1))
desc_p->next = (u32)&desc_table_p[idx + 1];
else
desc_p->next = (u32)&priv->tdesc[0];
}
flush_dcache_range((ulong)&desc_table_p[0],
(ulong)&desc_table_p[CONFIG_TX_DESCR_NUM]);
}
static void npcm750_rx_descs_init(struct npcm750_eth_dev *priv)
{
struct emc_regs *reg = priv->emc_regs_p;
struct npcm750_rxbd *desc_table_p = &priv->rdesc[0];
struct npcm750_rxbd *desc_p;
u8 *rxbuffs = &priv->rxbuffs[0];
u32 idx;
flush_dcache_range((ulong)priv->rxbuffs[0],
(ulong)priv->rxbuffs[CONFIG_RX_DESCR_NUM]);
writel((u32)desc_table_p, &reg->rxdlsa);
priv->curr_rxd = desc_table_p;
for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
desc_p->sl = RX_OWEN_DMA;
desc_p->buffer = (u32)&rxbuffs[idx * PKTSIZE_ALIGN];
if (idx < (CONFIG_RX_DESCR_NUM - 1))
desc_p->next = (u32)&desc_table_p[idx + 1];
else
desc_p->next = (u32)&priv->rdesc[0];
}
flush_dcache_range((ulong)&desc_table_p[0],
(ulong)&desc_table_p[CONFIG_RX_DESCR_NUM]);
}
static void npcm750_set_fifo_threshold(struct npcm750_eth_dev *priv)
{
struct emc_regs *reg = priv->emc_regs_p;
unsigned int val;
val = RXTHD | TXTHD | BLENGTH;
writel(val, &reg->fftcr);
}
static void npcm750_set_global_maccmd(struct npcm750_eth_dev *priv)
{
struct emc_regs *reg = priv->emc_regs_p;
unsigned int val;
val = readl(&reg->mcmdr);
val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | MCMDR_NDEF;
writel(val, &reg->mcmdr);
}
static void npcm750_set_cam(struct npcm750_eth_dev *priv,
unsigned int x, unsigned char *pval)
{
struct emc_regs *reg = priv->emc_regs_p;
unsigned int msw, lsw;
msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
lsw = (pval[4] << 24) | (pval[5] << 16);
writel(lsw, &reg->cam0l + x * CAM_ENTRY_SIZE);
writel(msw, &reg->cam0m + x * CAM_ENTRY_SIZE);
writel(readl(&reg->camen) | CAM0EN, &reg->camen);
writel(CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AUP, &reg->camcmr);
}
static void npcm750_adjust_link(struct emc_regs *reg,
struct phy_device *phydev)
{
u32 val = readl(&reg->mcmdr);
if (!phydev->link) {
printf("%s: No link.\n", phydev->dev->name);
return;
}
if (phydev->speed == 100)
val |= MCMDR_OPMOD;
else
val &= ~MCMDR_OPMOD;
if (phydev->duplex)
val |= MCMDR_FDUP;
else
val &= ~MCMDR_FDUP;
writel(val, &reg->mcmdr);
debug("Speed: %d, %s duplex%s\n", phydev->speed,
(phydev->duplex) ? "full" : "half",
(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
}
static int npcm750_phy_init(struct npcm750_eth_dev *priv, void *dev)
{
struct phy_device *phydev;
int ret;
u32 address = 0x0;
phydev = phy_connect(priv->bus, address, dev, priv->interface);
if (!phydev)
return -ENODEV;
if (priv->max_speed) {
ret = phy_set_supported(phydev, priv->max_speed);
if (ret)
return ret;
}
phydev->advertising = phydev->supported;
priv->phydev = phydev;
phy_config(phydev);
return 0;
}
static int npcm750_eth_start(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct npcm750_eth_dev *priv = dev_get_priv(dev);
struct emc_regs *reg = priv->emc_regs_p;
u8 *enetaddr = pdata->enetaddr;
int ret;
writel(readl(&reg->mcmdr) & ~MCMDR_TXON & ~MCMDR_RXON, &reg->mcmdr);
writel(readl(&reg->mcmdr) | MCMDR_SWR, &reg->mcmdr);
do {
ret = readl(&reg->mcmdr);
} while (ret & MCMDR_SWR);
npcm750_rx_descs_init(priv);
npcm750_tx_descs_init(priv);
npcm750_set_cam(priv, priv->idx, enetaddr);
npcm750_set_global_maccmd(priv);
npcm750_set_fifo_threshold(priv);
/* Start up the PHY */
ret = phy_startup(priv->phydev);
if (ret) {
printf("Could not initialize PHY\n");
return ret;
}
npcm750_adjust_link(reg, priv->phydev);
writel(readl(&reg->mcmdr) | MCMDR_TXON | MCMDR_RXON, &reg->mcmdr);
return 0;
}
static int npcm750_eth_send(struct udevice *dev, void *packet, int length)
{
struct npcm750_eth_dev *priv = dev_get_priv(dev);
struct emc_regs *reg = priv->emc_regs_p;
struct npcm750_txbd *desc_p;
struct npcm750_txbd *next_desc_p;
desc_p = priv->curr_txd;
invalidate_dcache_range((ulong)desc_p, (ulong)(desc_p + 1));
/* Check if the descriptor is owned by CPU */
if (desc_p->mode & TX_OWEN_DMA) {
next_desc_p = (struct npcm750_txbd *)desc_p->next;
while ((next_desc_p != desc_p) && (next_desc_p->mode & TX_OWEN_DMA))
next_desc_p = (struct npcm750_txbd *)next_desc_p->next;
if (next_desc_p == desc_p) {
struct emc_regs *reg = priv->emc_regs_p;
writel(0, &reg->tsdr);
serial_printf("TX: overflow and exit\n");
return -EPERM;
}
desc_p = next_desc_p;
}
memcpy((void *)desc_p->buffer, packet, length);
flush_dcache_range((ulong)desc_p->buffer,
(ulong)desc_p->buffer + roundup(length, ARCH_DMA_MINALIGN));
desc_p->sl = 0;
desc_p->sl = length & TX_STAT_TBC;
desc_p->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE;
flush_dcache_range((ulong)desc_p, (ulong)(desc_p + 1));
if (!(readl(&reg->mcmdr) & MCMDR_TXON))
writel(readl(&reg->mcmdr) | MCMDR_TXON, &reg->mcmdr);
priv->curr_txd = (struct npcm750_txbd *)priv->curr_txd->next;
writel(0, &reg->tsdr);
return 0;
}
static int npcm750_eth_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct npcm750_eth_dev *priv = dev_get_priv(dev);
struct npcm750_rxbd *desc_p;
struct npcm750_rxbd *next_desc_p;
int length = -1;
desc_p = priv->curr_rxd;
invalidate_dcache_range((ulong)desc_p, (ulong)(desc_p + 1));
if ((desc_p->sl & RX_STAT_OWNER) == RX_OWEN_DMA) {
next_desc_p = (struct npcm750_rxbd *)desc_p->next;
while ((next_desc_p != desc_p) &&
((next_desc_p->sl & RX_STAT_OWNER) == RX_OWEN_CPU)) {
next_desc_p = (struct npcm750_rxbd *)next_desc_p->next;
}
if (next_desc_p == desc_p) {
struct emc_regs *reg = priv->emc_regs_p;
writel(0, &reg->rsdr);
serial_printf("RX: overflow and exit\n");
return -EPERM;
}
desc_p = next_desc_p;
}
/* Check if the descriptor is owned by CPU */
if ((desc_p->sl & RX_STAT_OWNER) == RX_OWEN_CPU) {
if (desc_p->sl & RX_STAT_RXGD) {
length = desc_p->sl & RX_STAT_RBC;
invalidate_dcache_range((ulong)desc_p->buffer,
(ulong)(desc_p->buffer + roundup(length,
ARCH_DMA_MINALIGN)));
*packetp = (u8 *)(u32)desc_p->buffer;
priv->curr_rxd = desc_p;
}
}
return length;
}
static int npcm750_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
{
struct npcm750_eth_dev *priv = dev_get_priv(dev);
struct emc_regs *reg = priv->emc_regs_p;
struct npcm750_rxbd *desc_p = priv->curr_rxd;
/*
* Make the current descriptor valid again and go to
* the next one
*/
desc_p->sl |= RX_OWEN_DMA;
flush_dcache_range((ulong)desc_p, (ulong)(desc_p + 1));
priv->curr_rxd = (struct npcm750_rxbd *)priv->curr_rxd->next;
writel(0, &reg->rsdr);
return 0;
}
static void npcm750_eth_stop(struct udevice *dev)
{
struct npcm750_eth_dev *priv = dev_get_priv(dev);
struct emc_regs *reg = priv->emc_regs_p;
writel(readl(&reg->mcmdr) & ~MCMDR_TXON, &reg->mcmdr);
writel(readl(&reg->mcmdr) & ~MCMDR_RXON, &reg->mcmdr);
priv->curr_txd = (struct npcm750_txbd *)readl(&reg->txdlsa);
priv->curr_rxd = (struct npcm750_rxbd *)readl(&reg->rxdlsa);
phy_shutdown(priv->phydev);
}
static int npcm750_eth_write_hwaddr(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct npcm750_eth_dev *priv = dev_get_priv(dev);
npcm750_set_cam(priv, CAM0, pdata->enetaddr);
return 0;
}
static int npcm750_eth_bind(struct udevice *dev)
{
return 0;
}
static int npcm750_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct npcm750_eth_dev *priv = dev_get_priv(dev);
u32 iobase = pdata->iobase;
int ret;
memset(priv, 0, sizeof(struct npcm750_eth_dev));
ret = dev_read_u32(dev, "id", &priv->idx);
if (ret) {
printf("failed to get id\n");
return -EINVAL;
}
priv->gcr_regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-gcr");
if (IS_ERR(priv->gcr_regmap))
return -EINVAL;
priv->emc_regs_p = (struct emc_regs *)iobase;
priv->interface = pdata->phy_interface;
priv->max_speed = pdata->max_speed;
if (priv->idx == 0) {
/* Enable RMII for EMC1 module */
regmap_update_bits(priv->gcr_regmap, GCR_INTCR, INTCR_R1EN, INTCR_R1EN);
}
npcm750_mdio_init(dev->name, priv);
priv->bus = miiphy_get_dev_by_name(dev->name);
ret = npcm750_phy_init(priv, dev);
return ret;
}
static int npcm750_eth_remove(struct udevice *dev)
{
struct npcm750_eth_dev *priv = dev_get_priv(dev);
free(priv->phydev);
mdio_unregister(priv->bus);
mdio_free(priv->bus);
return 0;
}
static const struct eth_ops npcm750_eth_ops = {
.start = npcm750_eth_start,
.send = npcm750_eth_send,
.recv = npcm750_eth_recv,
.free_pkt = npcm750_eth_free_pkt,
.stop = npcm750_eth_stop,
.write_hwaddr = npcm750_eth_write_hwaddr,
};
static int npcm750_eth_ofdata_to_platdata(struct udevice *dev)
{
struct npcm750_eth_pdata *npcm750_pdata = dev_get_plat(dev);
struct eth_pdata *pdata = &npcm750_pdata->eth_pdata;
const char *phy_mode;
const fdt32_t *cell;
int ret = 0;
pdata->iobase = (phys_addr_t)dev_read_addr_ptr(dev);
pdata->phy_interface = -1;
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", NULL);
if (phy_mode)
pdata->phy_interface = phy_get_interface_by_name(phy_mode);
if (pdata->phy_interface == -1) {
printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
return -EINVAL;
}
pdata->max_speed = 0;
cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL);
if (cell)
pdata->max_speed = fdt32_to_cpu(*cell);
return ret;
}
static const struct udevice_id npcm750_eth_ids[] = {
{ .compatible = "nuvoton,npcm750-emc" },
{ }
};
U_BOOT_DRIVER(eth_npcm750) = {
.name = "eth_npcm750",
.id = UCLASS_ETH,
.of_match = npcm750_eth_ids,
.of_to_plat = npcm750_eth_ofdata_to_platdata,
.bind = npcm750_eth_bind,
.probe = npcm750_eth_probe,
.remove = npcm750_eth_remove,
.ops = &npcm750_eth_ops,
.priv_auto = sizeof(struct npcm750_eth_dev),
.plat_auto = sizeof(struct npcm750_eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};

View File

@ -104,6 +104,88 @@
#define MIIM_88E151x_MODE_SGMII 1 #define MIIM_88E151x_MODE_SGMII 1
#define MIIM_88E151x_RESET_OFFS 15 #define MIIM_88E151x_RESET_OFFS 15
#if IS_ENABLED(CONFIG_DM_ETH)
static int marvell_read_page(struct phy_device *phydev)
{
return phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE);
}
static int marvell_write_page(struct phy_device *phydev, int page)
{
return phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, page);
}
/* Set and/or override some configuration registers based on the
* marvell,reg-init property stored in the of_node for the phydev.
*
* marvell,reg-init = <reg-page reg mask value>,...;
*
* There may be one or more sets of <reg-page reg mask value>:
*
* reg-page: which register bank to use.
* reg: the register.
* mask: if non-zero, ANDed with existing register value.
* value: ORed with the masked value and written to the regiser.
*
*/
static int marvell_of_reg_init(struct phy_device *phydev)
{
const __be32 *prop;
int len, i, saved_page, current_page, ret = 0;
if (!ofnode_valid(phydev->node))
return 0;
prop = ofnode_get_property(phydev->node, "marvell,reg-init", &len);
if (!prop)
return 0;
saved_page = marvell_read_page(phydev);
if (saved_page < 0)
goto err;
current_page = saved_page;
len /= sizeof(*prop);
for (i = 0; i < len - 3; i += 4) {
u16 page = be32_to_cpup(prop + i);
u16 reg = be32_to_cpup(prop + i + 1);
u16 mask = be32_to_cpup(prop + i + 2);
u16 val_bits = be32_to_cpup(prop + i + 3);
int val;
if (page != current_page) {
current_page = page;
ret = marvell_write_page(phydev, page);
if (ret < 0)
goto err;
}
val = 0;
if (mask) {
val = phy_read(phydev, MDIO_DEVAD_NONE, reg);
if (val < 0) {
ret = val;
goto err;
}
val &= mask;
}
val |= val_bits;
ret = phy_write(phydev, MDIO_DEVAD_NONE, reg, val);
if (ret < 0)
goto err;
}
err:
return marvell_write_page(phydev, saved_page);
}
#else
static int marvell_of_reg_init(struct phy_device *phydev)
{
return 0;
}
#endif /* CONFIG_DM_ETH */
static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr, static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr,
int devaddr, int regnum) int devaddr, int regnum)
{ {
@ -143,6 +225,8 @@ static int m88e1011s_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
return 0; return 0;
@ -298,6 +382,8 @@ static int m88e1111s_config(struct phy_device *phydev)
/* soft reset */ /* soft reset */
phy_reset(phydev); phy_reset(phydev);
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
genphy_restart_aneg(phydev); genphy_restart_aneg(phydev);
@ -397,6 +483,8 @@ static int m88e151x_config(struct phy_device *phydev)
/* soft reset */ /* soft reset */
phy_reset(phydev); phy_reset(phydev);
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
genphy_restart_aneg(phydev); genphy_restart_aneg(phydev);
@ -417,6 +505,8 @@ static int m88e1118_config(struct phy_device *phydev)
/* Change Page Number */ /* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
marvell_of_reg_init(phydev);
return genphy_config_aneg(phydev); return genphy_config_aneg(phydev);
} }
@ -439,6 +529,8 @@ static int m88e1121_config(struct phy_device *phydev)
{ {
int pg; int pg;
marvell_of_reg_init(phydev);
/* Configure the PHY */ /* Configure the PHY */
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
@ -479,6 +571,8 @@ static int m88e1145_config(struct phy_device *phydev)
MIIM_M88E1145_RGMII_TX_DELAY; MIIM_M88E1145_RGMII_TX_DELAY;
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
/* soft reset */ /* soft reset */
@ -511,6 +605,8 @@ static int m88e1149_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev); genphy_config_aneg(phydev);
phy_reset(phydev); phy_reset(phydev);
@ -518,6 +614,16 @@ static int m88e1149_config(struct phy_device *phydev)
return 0; return 0;
} }
/* Marvell 88E1240 */
static int m88e1240_config(struct phy_device *phydev)
{
marvell_of_reg_init(phydev);
genphy_config_aneg(phydev);
return 0;
}
/* Marvell 88E1310 */ /* Marvell 88E1310 */
static int m88e1310_config(struct phy_device *phydev) static int m88e1310_config(struct phy_device *phydev)
{ {
@ -544,6 +650,8 @@ static int m88e1310_config(struct phy_device *phydev)
/* Ensure to return to page 0 */ /* Ensure to return to page 0 */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
marvell_of_reg_init(phydev);
return genphy_config_aneg(phydev); return genphy_config_aneg(phydev);
} }
@ -578,6 +686,8 @@ static int m88e1680_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140); phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140);
marvell_of_reg_init(phydev);
res = genphy_config_aneg(phydev); res = genphy_config_aneg(phydev);
if (res < 0) if (res < 0)
return res; return res;
@ -660,6 +770,16 @@ static struct phy_driver M88E1149S_driver = {
.shutdown = &genphy_shutdown, .shutdown = &genphy_shutdown,
}; };
static struct phy_driver M88E1240_driver = {
.name = "Marvell 88E1240",
.uid = 0x1410e30,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1240_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E151x_driver = { static struct phy_driver M88E151x_driver = {
.name = "Marvell 88E151x", .name = "Marvell 88E151x",
.uid = 0x1410dd0, .uid = 0x1410dd0,
@ -702,6 +822,7 @@ int phy_marvell_init(void)
phy_register(&M88E1118R_driver); phy_register(&M88E1118R_driver);
phy_register(&M88E1111S_driver); phy_register(&M88E1111S_driver);
phy_register(&M88E1011S_driver); phy_register(&M88E1011S_driver);
phy_register(&M88E1240_driver);
phy_register(&M88E151x_driver); phy_register(&M88E151x_driver);
phy_register(&M88E1680_driver); phy_register(&M88E1680_driver);

View File

@ -984,10 +984,10 @@ struct phy_device *fixed_phy_create(ofnode node)
} }
phydev = phy_device_create(NULL, 0, PHY_FIXED_ID, false); phydev = phy_device_create(NULL, 0, PHY_FIXED_ID, false);
if (phydev) if (phydev) {
phydev->node = subnode; phydev->node = subnode;
phydev->interface = ofnode_read_phy_mode(node); phydev->interface = ofnode_read_phy_mode(node);
}
return phydev; return phydev;
} }
@ -1101,3 +1101,177 @@ int phy_modify(struct phy_device *phydev, int devad, int regnum, u16 mask,
return phy_write(phydev, devad, regnum, (ret & ~mask) | set); return phy_write(phydev, devad, regnum, (ret & ~mask) | set);
} }
/**
* phy_read - Convenience function for reading a given PHY register
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to read
* @return: value for success or negative errno for failure
*/
int phy_read(struct phy_device *phydev, int devad, int regnum)
{
struct mii_dev *bus = phydev->bus;
if (!bus || !bus->read) {
debug("%s: No bus configured\n", __func__);
return -1;
}
return bus->read(bus, phydev->addr, devad, regnum);
}
/**
* phy_write - Convenience function for writing a given PHY register
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to write
* @val: value to write to @regnum
* @return: 0 for success or negative errno for failure
*/
int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
{
struct mii_dev *bus = phydev->bus;
if (!bus || !bus->write) {
debug("%s: No bus configured\n", __func__);
return -1;
}
return bus->write(bus, phydev->addr, devad, regnum, val);
}
/**
* phy_mmd_start_indirect - Convenience function for writing MMD registers
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to write
* @return: None
*/
void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum)
{
/* Write the desired MMD Devad */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
/* Write the desired MMD register address */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
/* Select the Function : DATA with no post increment */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
(devad | MII_MMD_CTRL_NOINCR));
}
/**
* phy_read_mmd - Convenience function for reading a register
* from an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from
* @regnum: The register on the MMD to read
* @return: Value for success or negative errno for failure
*/
int phy_read_mmd(struct phy_device *phydev, int devad, int regnum)
{
struct phy_driver *drv = phydev->drv;
if (regnum > (u16)~0 || devad > 32)
return -EINVAL;
/* driver-specific access */
if (drv->read_mmd)
return drv->read_mmd(phydev, devad, regnum);
/* direct C45 / C22 access */
if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
devad == MDIO_DEVAD_NONE || !devad)
return phy_read(phydev, devad, regnum);
/* indirect C22 access */
phy_mmd_start_indirect(phydev, devad, regnum);
/* Read the content of the MMD's selected register */
return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
}
/**
* phy_write_mmd - Convenience function for writing a register
* on an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from
* @regnum: The register on the MMD to read
* @val: value to write to @regnum
* @return: 0 for success or negative errno for failure
*/
int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val)
{
struct phy_driver *drv = phydev->drv;
if (regnum > (u16)~0 || devad > 32)
return -EINVAL;
/* driver-specific access */
if (drv->write_mmd)
return drv->write_mmd(phydev, devad, regnum, val);
/* direct C45 / C22 access */
if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
devad == MDIO_DEVAD_NONE || !devad)
return phy_write(phydev, devad, regnum, val);
/* indirect C22 access */
phy_mmd_start_indirect(phydev, devad, regnum);
/* Write the data into MMD's selected register */
return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
}
/**
* phy_set_bits_mmd - Convenience function for setting bits in a register
* on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @val: bits to set
* @return: 0 for success or negative errno for failure
*/
int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
{
int value, ret;
value = phy_read_mmd(phydev, devad, regnum);
if (value < 0)
return value;
value |= val;
ret = phy_write_mmd(phydev, devad, regnum, value);
if (ret < 0)
return ret;
return 0;
}
/**
* phy_clear_bits_mmd - Convenience function for clearing bits in a register
* on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @val: bits to clear
* @return: 0 for success or negative errno for failure
*/
int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
{
int value, ret;
value = phy_read_mmd(phydev, devad, regnum);
if (value < 0)
return value;
value &= ~val;
ret = phy_write_mmd(phydev, devad, regnum, value);
if (ret < 0)
return ret;
return 0;
}

View File

@ -483,7 +483,10 @@ static int ave_start(struct udevice *dev)
priv->rx_siz = (PKTSIZE_ALIGN - priv->rx_off); priv->rx_siz = (PKTSIZE_ALIGN - priv->rx_off);
val = 0; val = 0;
if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII) if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII &&
priv->phy_mode != PHY_INTERFACE_MODE_RGMII_ID &&
priv->phy_mode != PHY_INTERFACE_MODE_RGMII_RXID &&
priv->phy_mode != PHY_INTERFACE_MODE_RGMII_TXID)
val |= AVE_CFGR_MII; val |= AVE_CFGR_MII;
writel(val, priv->iobase + AVE_CFGR); writel(val, priv->iobase + AVE_CFGR);
@ -639,6 +642,9 @@ static int ave_pro4_get_pinmode(struct ave_private *priv)
break; break;
case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_MII:
case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -693,6 +699,9 @@ static int ave_ld20_get_pinmode(struct ave_private *priv)
val = SG_ETPINMODE_RMII(0); val = SG_ETPINMODE_RMII(0);
break; break;
case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -720,6 +729,9 @@ static int ave_pxs3_get_pinmode(struct ave_private *priv)
val = SG_ETPINMODE_RMII(priv->regmap_arg); val = SG_ETPINMODE_RMII(priv->regmap_arg);
break; break;
case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
break; break;
default: default:
return -EINVAL; return -EINVAL;

View File

@ -24,8 +24,6 @@
#if defined(CONFIG_CMD_NET) #if defined(CONFIG_CMD_NET)
#define CONFIG_FEC_MXC_PHYADDR 1 #define CONFIG_FEC_MXC_PHYADDR 1
#define DWC_NET_PHYADDR 1
#define PHY_ANEG_TIMEOUT 20000 #define PHY_ANEG_TIMEOUT 20000
#endif #endif

View File

@ -42,7 +42,6 @@
#if defined(CONFIG_CMD_NET) #if defined(CONFIG_CMD_NET)
#define CONFIG_FEC_MXC_PHYADDR 4 #define CONFIG_FEC_MXC_PHYADDR 4
#define DWC_NET_PHYADDR 4
#ifdef CONFIG_DWC_ETH_QOS #ifdef CONFIG_DWC_ETH_QOS
#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */ #define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */
#endif #endif

View File

@ -138,7 +138,6 @@
#define WDOG_BASE_ADDR WDG3_BASE_ADDR #define WDOG_BASE_ADDR WDG3_BASE_ADDR
#if defined(CONFIG_CMD_NET) #if defined(CONFIG_CMD_NET)
#define DWC_NET_PHYADDR 1
#define PHY_ANEG_TIMEOUT 20000 #define PHY_ANEG_TIMEOUT 20000
#endif #endif

View File

@ -536,7 +536,9 @@ extern struct in_addr net_dns_server2;
#endif #endif
extern char net_nis_domain[32]; /* Our IS domain */ extern char net_nis_domain[32]; /* Our IS domain */
extern char net_hostname[32]; /* Our hostname */ extern char net_hostname[32]; /* Our hostname */
extern char net_root_path[64]; /* Our root path */ #ifdef CONFIG_NET
extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */
#endif
/** END OF BOOTP EXTENTIONS **/ /** END OF BOOTP EXTENTIONS **/
extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */ extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */
extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */ extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */

View File

@ -42,7 +42,6 @@ int eepro100_initialize(struct bd_info *bis);
int ep93xx_eth_initialize(u8 dev_num, int base_addr); int ep93xx_eth_initialize(u8 dev_num, int base_addr);
int eth_3com_initialize (struct bd_info * bis); int eth_3com_initialize (struct bd_info * bis);
int ethoc_initialize(u8 dev_num, int base_addr); int ethoc_initialize(u8 dev_num, int base_addr);
int fec_initialize (struct bd_info *bis);
int fecmxc_initialize(struct bd_info *bis); int fecmxc_initialize(struct bd_info *bis);
int fecmxc_initialize_multi(struct bd_info *bis, int dev_id, int phy_id, int fecmxc_initialize_multi(struct bd_info *bis, int dev_id, int phy_id,
uint32_t addr); uint32_t addr);

View File

@ -177,186 +177,6 @@ struct fixed_link {
int asym_pause; int asym_pause;
}; };
/**
* phy_read - Convenience function for reading a given PHY register
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to read
* @return: value for success or negative errno for failure
*/
static inline int phy_read(struct phy_device *phydev, int devad, int regnum)
{
struct mii_dev *bus = phydev->bus;
if (!bus || !bus->read) {
debug("%s: No bus configured\n", __func__);
return -1;
}
return bus->read(bus, phydev->addr, devad, regnum);
}
/**
* phy_write - Convenience function for writing a given PHY register
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to write
* @val: value to write to @regnum
* @return: 0 for success or negative errno for failure
*/
static inline int phy_write(struct phy_device *phydev, int devad, int regnum,
u16 val)
{
struct mii_dev *bus = phydev->bus;
if (!bus || !bus->write) {
debug("%s: No bus configured\n", __func__);
return -1;
}
return bus->write(bus, phydev->addr, devad, regnum, val);
}
/**
* phy_mmd_start_indirect - Convenience function for writing MMD registers
* @phydev: the phy_device struct
* @devad: The MMD to read from
* @regnum: register number to write
* @return: None
*/
static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad,
int regnum)
{
/* Write the desired MMD Devad */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
/* Write the desired MMD register address */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
/* Select the Function : DATA with no post increment */
phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
(devad | MII_MMD_CTRL_NOINCR));
}
/**
* phy_read_mmd - Convenience function for reading a register
* from an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from
* @regnum: The register on the MMD to read
* @return: Value for success or negative errno for failure
*/
static inline int phy_read_mmd(struct phy_device *phydev, int devad,
int regnum)
{
struct phy_driver *drv = phydev->drv;
if (regnum > (u16)~0 || devad > 32)
return -EINVAL;
/* driver-specific access */
if (drv->read_mmd)
return drv->read_mmd(phydev, devad, regnum);
/* direct C45 / C22 access */
if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
devad == MDIO_DEVAD_NONE || !devad)
return phy_read(phydev, devad, regnum);
/* indirect C22 access */
phy_mmd_start_indirect(phydev, devad, regnum);
/* Read the content of the MMD's selected register */
return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
}
/**
* phy_write_mmd - Convenience function for writing a register
* on an MMD on a given PHY.
* @phydev: The phy_device struct
* @devad: The MMD to read from
* @regnum: The register on the MMD to read
* @val: value to write to @regnum
* @return: 0 for success or negative errno for failure
*/
static inline int phy_write_mmd(struct phy_device *phydev, int devad,
int regnum, u16 val)
{
struct phy_driver *drv = phydev->drv;
if (regnum > (u16)~0 || devad > 32)
return -EINVAL;
/* driver-specific access */
if (drv->write_mmd)
return drv->write_mmd(phydev, devad, regnum, val);
/* direct C45 / C22 access */
if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
devad == MDIO_DEVAD_NONE || !devad)
return phy_write(phydev, devad, regnum, val);
/* indirect C22 access */
phy_mmd_start_indirect(phydev, devad, regnum);
/* Write the data into MMD's selected register */
return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
}
/**
* phy_set_bits_mmd - Convenience function for setting bits in a register
* on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @val: bits to set
* @return: 0 for success or negative errno for failure
*/
static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad,
u32 regnum, u16 val)
{
int value, ret;
value = phy_read_mmd(phydev, devad, regnum);
if (value < 0)
return value;
value |= val;
ret = phy_write_mmd(phydev, devad, regnum, value);
if (ret < 0)
return ret;
return 0;
}
/**
* phy_clear_bits_mmd - Convenience function for clearing bits in a register
* on MMD
* @phydev: the phy_device struct
* @devad: the MMD containing register to modify
* @regnum: register number to modify
* @val: bits to clear
* @return: 0 for success or negative errno for failure
*/
static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad,
u32 regnum, u16 val)
{
int value, ret;
value = phy_read_mmd(phydev, devad, regnum);
if (value < 0)
return value;
value &= ~val;
ret = phy_write_mmd(phydev, devad, regnum, value);
if (ret < 0)
return ret;
return 0;
}
#ifdef CONFIG_PHYLIB_10G #ifdef CONFIG_PHYLIB_10G
extern struct phy_driver gen10g_driver; extern struct phy_driver gen10g_driver;
#endif #endif
@ -508,6 +328,15 @@ static inline ofnode phy_get_ofnode(struct phy_device *phydev)
return ofnode_null(); return ofnode_null();
} }
#endif #endif
int phy_read(struct phy_device *phydev, int devad, int regnum);
int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val);
void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum);
int phy_read_mmd(struct phy_device *phydev, int devad, int regnum);
int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val);
int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
int phy_startup(struct phy_device *phydev); int phy_startup(struct phy_device *phydev);
int phy_config(struct phy_device *phydev); int phy_config(struct phy_device *phydev);
int phy_shutdown(struct phy_device *phydev); int phy_shutdown(struct phy_device *phydev);

View File

@ -168,6 +168,12 @@ config BOOTP_SERVERIP
variable, not the BOOTP server. This affects the operation of both variable, not the BOOTP server. This affects the operation of both
bootp and tftp. bootp and tftp.
config BOOTP_MAX_ROOT_PATH_LEN
int "Option 17 root path length"
default 64
help
Select maximal length of option 17 root path.
endif # if NET endif # if NET
config SYS_RX_ETH_BUFFER config SYS_RX_ETH_BUFFER

View File

@ -59,7 +59,7 @@ ulong bootp_start;
ulong bootp_timeout; ulong bootp_timeout;
char net_nis_domain[32] = {0,}; /* Our NIS domain */ char net_nis_domain[32] = {0,}; /* Our NIS domain */
char net_hostname[32] = {0,}; /* Our hostname */ char net_hostname[32] = {0,}; /* Our hostname */
char net_root_path[64] = {0,}; /* Our bootpath */ char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN] = {0,}; /* Our bootpath */
static ulong time_taken_max; static ulong time_taken_max;