drivers: ethernet: bugfix for Cyclone V Ethernet

bugfix for Cyclone V Ethernet Phy error and timeout overflow.
 - p->instance was incorrectly assumed to be a reference to
   the emac device, this is ammended
 - the volatile uint16_t timeout would often overflow
 - code cleanup and added more macros for housekeeping

Signed-off-by: Benjamin Kyd <benjamin.kyd@intel.com>
This commit is contained in:
Benjamin Kyd 2023-01-11 10:29:37 +00:00 committed by Maureen Helm
parent c348fb51c9
commit aad76523e1
3 changed files with 31 additions and 25 deletions

View file

@ -60,7 +60,7 @@ struct eth_cyclonev_config {
uint8_t *base;
/** BBRAM size (Unit:bytes) */
int size;
int inst_num;
uint32_t emac_index;
void (*irq_config)(void);
};
@ -315,6 +315,7 @@ static int eth_cyclonev_set_config(const struct device *dev, enum ethernet_confi
const struct ethernet_config *config)
{
struct eth_cyclonev_priv *p = dev->data;
const struct eth_cyclonev_config *cv_config = dev->config;
uint32_t reg_val;
int ret = 0;
@ -323,7 +324,7 @@ static int eth_cyclonev_set_config(const struct device *dev, enum ethernet_confi
switch (type) {
case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
memcpy(p->mac_addr, config->mac_address.addr, sizeof(p->mac_addr));
eth_cyclonev_set_mac_addr(p->mac_addr, p->instance, 0, p); /* Set MAC address */
eth_cyclonev_set_mac_addr(p->mac_addr, cv_config->emac_index, 0, p); /* Set MAC */
net_if_set_link_addr(p->iface, p->mac_addr, sizeof(p->mac_addr), NET_LINK_ETHERNET);
break;
#if defined(CONFIG_NET_PROMISCUOUS_MODE)
@ -546,6 +547,7 @@ abort:
void eth_cyclonev_isr(const struct device *dev)
{
struct eth_cyclonev_priv *p = dev->data;
const struct eth_cyclonev_config *config = dev->config;
uint32_t irq_status = 0;
uint32_t irq_status_emac = 0;
@ -617,7 +619,7 @@ void eth_cyclonev_isr(const struct device *dev)
return;
}
set_mac_conf_status(p->instance, &cfg_reg_set, p);
set_mac_conf_status(config->emac_index, &cfg_reg_set, p);
sys_write32(cfg_reg_set, GMACGRP_MAC_CONFIG_ADDR(p->base_addr));
eth_cyclonev_start(dev);
@ -857,22 +859,21 @@ int eth_cyclonev_probe(const struct device *dev)
p->base_addr = (mem_addr_t)config->base;
p->running = 0;
p->initialised = 0;
p->instance = config->inst_num;
/* EMAC HPS Interface Initialization */
/* Reset the EMAC */
eth_cyclonev_reset(p->instance);
eth_cyclonev_reset(config->emac_index);
/* Reset the PHY */
ret = alt_eth_phy_reset(p->instance, p);
ret = alt_eth_phy_reset(config->emac_index, p);
if (ret != 0) {
LOG_ERR("alt_eth_phy_reset failure!\n");
return ret;
}
/* Configure the PHY */
ret = alt_eth_phy_config(p->instance, p);
ret = alt_eth_phy_config(config->emac_index, p);
if (ret != 0) {
LOG_ERR("alt_eth_phy_config failure!\n");
return ret;
@ -891,7 +892,7 @@ int eth_cyclonev_probe(const struct device *dev)
*operation is completed).
*/
ret = eth_cyclonev_software_reset(p->instance, p);
ret = eth_cyclonev_software_reset(config->emac_index, p);
if (ret != 0) {
LOG_ERR("eth_cyclonev_software_reset failure!\n");
return ret;
@ -993,7 +994,7 @@ int eth_cyclonev_probe(const struct device *dev)
/* Enable Transmission to PHY */
);
ret = set_mac_conf_status(p->instance, &mac_config_reg_settings, p);
ret = set_mac_conf_status(config->emac_index, &mac_config_reg_settings, p);
if (ret != 0) {
return -1;
}
@ -1004,7 +1005,7 @@ int eth_cyclonev_probe(const struct device *dev)
*/
memcpy(p->mac_addr, eth_cyclonev_mac_addr, sizeof(p->mac_addr));
eth_cyclonev_set_mac_addr(p->mac_addr, p->instance, 0, p);
eth_cyclonev_set_mac_addr(p->mac_addr, config->emac_index, 0, p);
/* 5. Program the following fields to set the appropriate filters for the
* incoming frames in the MAC Frame Filter Register:
@ -1142,15 +1143,15 @@ const struct ethernet_api eth_cyclonev_api = {.iface_api.init = eth_cyclonev_ifa
.stop = eth_cyclonev_stop,
.set_config = eth_cyclonev_set_config};
#define CYCLONEV_ETH_INIT(inst) \
#define CYCLONEV_ETH_INIT(inst) \
\
static struct eth_cyclonev_priv eth_cyclonev_##inst##_data; \
static void eth_cyclonev_##inst##_irq_config(void); \
\
static const struct eth_cyclonev_config eth_cyclonev_##inst##_cfg = { \
static const struct eth_cyclonev_config eth_cyclonev_##inst##_cfg = { \
.base = (uint8_t *)(DT_INST_REG_ADDR(inst)), \
.size = DT_INST_REG_SIZE(inst), \
.inst_num = inst, \
.emac_index = DT_INST_PROP(inst, emac_index), \
.irq_config = eth_cyclonev_##inst##_irq_config, \
}; \
ETH_NET_DEVICE_DT_INST_DEFINE(inst, eth_cyclonev_probe, NULL, \
@ -1167,5 +1168,4 @@ const struct ethernet_api eth_cyclonev_api = {.iface_api.init = eth_cyclonev_ifa
DEVICE_DT_INST_GET(inst), \
0); \
irq_enable(DT_INST_IRQN(inst)); \
}
DT_INST_FOREACH_STATUS_OKAY(CYCLONEV_ETH_INIT)

View file

@ -30,7 +30,6 @@ struct eth_cyclonev_dma_desc {
struct eth_cyclonev_priv {
mem_addr_t base_addr; /* Base address */
uint32_t instance;
uint8_t mac_addr[6];
uint32_t interrupt_mask;
struct net_if *iface; /* Zephyr net_if Interface Struct (for interface initialisation) */

View file

@ -47,8 +47,8 @@
#define PHY_RESTART_AUTONEGOTIATION BIT(9)
/* Basic Status Register */
#define PHY_BSR BIT(0)
#define PHY_AUTOCAP BIT(30) /* Auto-negotiation capability */
#define PHY_BSR (1)
#define PHY_AUTOCAP BIT(3) /* Auto-negotiation capability */
#define PHY_LINKED_STATUS BIT(2)
#define PHY_AUTONEGO_COMPLETE BIT(5)
@ -58,16 +58,20 @@
#define PHYANA_10BASETFD BIT(6)
#define PHYANA_100BASETX BIT(7)
#define PHYANA_100BASETXFD BIT(8)
#define PHYSYMETRIC_PAUSE BIT(10)
#define PHYASYMETRIC_PAUSE BIT(11)
/* 1000Base-T Control */
#define PHY_1GCTL (9)
#define PHYADVERTISE_1000HALF BIT(8)
#define PHYADVERTISE_1000FULL BIT(9)
#define PHYINDICATE_PORTTYPE BIT(10)
#define PHYCONFIG_MASTER BIT(11)
#define PHYENABLE_MANUALCONFIG BIT(12)
/* PHY Control Register */
#define PHY_CR (31)
#define PHY_DUPLEX_STATUS (0x0008)
#define PHYADVERTISE_1000FULL BIT(9)
#define PHYADVERTISE_1000HALF BIT(8)
#define PHY_DUPLEX_STATUS BIT(3)
/* Extended registers */
#define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104
@ -92,7 +96,7 @@ int alt_eth_phy_write_register(uint16_t emac_instance, uint16_t phy_reg,
uint16_t phy_value, struct eth_cyclonev_priv *p)
{
uint16_t tmpreg = 0;
volatile uint16_t timeout = 0;
volatile uint32_t timeout = 0;
uint16_t phy_addr;
if (emac_instance > 1) {
@ -139,7 +143,7 @@ int alt_eth_phy_read_register(uint16_t emac_instance, uint16_t phy_reg, uint16_t
struct eth_cyclonev_priv *p)
{
uint16_t tmpreg = 0;
volatile uint16_t timeout = 0;
volatile uint32_t timeout = 0;
uint16_t phy_addr;
if (emac_instance > 1) {
@ -218,7 +222,8 @@ int alt_eth_phy_config(uint16_t instance, struct eth_cyclonev_priv *p)
{
int rc;
uint16_t rdval, timeout;
uint16_t rdval;
uint32_t timeout;
/*-------------------- Configure the PHY skew values ----------------*/
rc = alt_eth_phy_write_register_extended(instance, MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
@ -250,7 +255,7 @@ int alt_eth_phy_config(uint16_t instance, struct eth_cyclonev_priv *p)
}
rdval |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX | PHYANA_100BASETXFD |
PHYASYMETRIC_PAUSE);
PHYSYMETRIC_PAUSE);
rc = alt_eth_phy_write_register(instance, PHY_AUTON, rdval, p);
if (rc == -1) {
return rc;
@ -259,7 +264,9 @@ int alt_eth_phy_config(uint16_t instance, struct eth_cyclonev_priv *p)
/* Set Advertise capabilities for 1000 Base-T/1000 Base-T full-duplex */
rc = alt_eth_phy_write_register(instance, PHY_1GCTL,
PHYADVERTISE_1000FULL | PHYADVERTISE_1000HALF, p);
PHYADVERTISE_1000FULL | PHYADVERTISE_1000HALF |
PHYINDICATE_PORTTYPE | PHYCONFIG_MASTER | PHYENABLE_MANUALCONFIG
, p);
if (rc == -1) {
return rc;
}