Skip to content

Commit

Permalink
drivers: eth_sam_gmac: use PHY driver
Browse files Browse the repository at this point in the history
This commit removes PHY and MDIO specific code from the ATSAM
Ethernet driver and instead relies on a separate PHY driver to
handle the PHY.

Signed-off-by: Arvin Farahmand <[email protected]>
  • Loading branch information
arvinf authored and nashif committed Aug 27, 2021
1 parent f845cdd commit 276996d
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 422 deletions.
7 changes: 2 additions & 5 deletions drivers/ethernet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ zephyr_library_sources_ifdef(CONFIG_ETH_GECKO
phy_gecko.c
)

zephyr_library_sources_ifdef(CONFIG_ETH_SAM_GMAC
eth_sam_gmac.c
phy_sam_gmac.c
)

zephyr_library_sources_ifdef(CONFIG_ETH_XLNX_GEM
eth_xlnx_gem.c
phy_xlnx_gem.c
Expand All @@ -27,6 +22,8 @@ zephyr_library_sources_ifdef(CONFIG_ETH_SMSC911X eth_smsc911x.c)
zephyr_library_sources_ifdef(CONFIG_ETH_STELLARIS eth_stellaris.c)
zephyr_library_sources_ifdef(CONFIG_ETH_STM32_HAL eth_stm32_hal.c)
zephyr_library_sources_ifdef(CONFIG_ETH_W5500 eth_w5500.c)
zephyr_library_sources_ifdef(CONFIG_ETH_SAM_GMAC eth_sam_gmac.c)
zephyr_library_sources_ifdef(CONFIG_DSA_KSZ8XXX dsa_ksz8xxx.c)

if(CONFIG_ETH_NATIVE_POSIX)
zephyr_library_named(drivers__ethernet__native_posix)
Expand Down
17 changes: 1 addition & 16 deletions drivers/ethernet/Kconfig.sam_gmac
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ menuconfig ETH_SAM_GMAC
bool "Atmel SAM Ethernet driver"
depends on SOC_FAMILY_SAM0 || SOC_FAMILY_SAM
select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT
select MDIO
help
Enable Atmel SAM MCU Family Ethernet driver.

Expand Down Expand Up @@ -68,14 +69,6 @@ config ETH_SAM_GMAC_BUF_RX_COUNT
fit at least two Ethernet frames: one being received by the GMAC module
and the other being processed by the higher layer networking stack.

config ETH_SAM_GMAC_MONITOR_PERIOD
int "Monitor task execution period"
default 1000
help
Monitor task execution period in milliseconds. The monitor task is
periodically executed to detect and report any changes in the PHY
link status to the operating system.

config ETH_SAM_GMAC_MAC_I2C_EEPROM
bool "Read from an I2C EEPROM"
help
Expand Down Expand Up @@ -112,14 +105,6 @@ config ETH_SAM_GMAC_MAC_I2C_DEV_NAME

endif # ETH_SAM_GMAC_MAC_I2C_EEPROM

config ETH_SAM_GMAC_PHY_ADDR
int "GMAC PHY Address"
default 0
help
GMAC PHY Address as used by IEEE 802.3, Section 2 MII compatible PHY
transceivers. If you have a single PHY on board it is safe to leave it
at 0 which is the broadcast address.

config PTP_CLOCK_SAM_GMAC
bool "SAM GMAC PTP clock driver support"
default y
Expand Down
78 changes: 32 additions & 46 deletions drivers/ethernet/eth_sam_gmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <sys/util.h>
#include <errno.h>
#include <stdbool.h>
#include <net/phy.h>
#include <net/net_pkt.h>
#include <net/net_if.h>
#include <net/ethernet.h>
#include <ethernet/eth_stats.h>
#include <drivers/i2c.h>
#include <soc.h>
#include "phy_sam_gmac.h"
#include "eth_sam_gmac_priv.h"

#include "eth.h"
Expand Down Expand Up @@ -241,9 +241,8 @@ static void tx_descriptors_init(Gmac *gmac, struct gmac_queue *queue);
static int nonpriority_queue_init(Gmac *gmac, struct gmac_queue *queue);

#if GMAC_PRIORITY_QUEUE_NUM >= 1
static inline void set_receive_buf_queue_pointer(
Gmac *gmac,
struct gmac_queue *queue)
static inline void set_receive_buf_queue_pointer(Gmac *gmac,
struct gmac_queue *queue)
{
/* Set Receive Buffer Queue Pointer Register */
if (queue->que_idx == GMAC_QUE_0) {
Expand Down Expand Up @@ -360,9 +359,8 @@ static int queue_init(Gmac *gmac, struct gmac_queue *queue)

#else

static inline void set_receive_buf_queue_pointer(
Gmac *gmac,
struct gmac_queue *queue)
static inline void set_receive_buf_queue_pointer(Gmac *gmac,
struct gmac_queue *queue)
{
gmac->GMAC_RBQB = (uint32_t)queue->rx_desc_list.buf;
}
Expand Down Expand Up @@ -1093,7 +1091,7 @@ static int gmac_init(Gmac *gmac, uint32_t gmac_ncfgr_val)
}

/* Set Network Control Register to its default value, clear stats. */
gmac->GMAC_NCR = GMAC_NCR_CLRSTAT;
gmac->GMAC_NCR = GMAC_NCR_CLRSTAT | GMAC_NCR_MPE;

/* Disable all interrupts */
gmac->GMAC_IDR = UINT32_MAX;
Expand Down Expand Up @@ -1160,14 +1158,15 @@ static int gmac_init(Gmac *gmac, uint32_t gmac_ncfgr_val)
return 0;
}

static void link_configure(Gmac *gmac, uint32_t flags)
static void link_configure(Gmac *gmac, bool full_duplex, bool speed_100M)
{
uint32_t val;

val = gmac->GMAC_NCFGR;

val &= ~(GMAC_NCFGR_FD | GMAC_NCFGR_SPD);
val |= flags & (GMAC_NCFGR_FD | GMAC_NCFGR_SPD);
val |= (full_duplex) ? GMAC_NCFGR_FD : 0;
val |= (speed_100M) ? GMAC_NCFGR_SPD : 0;

gmac->GMAC_NCFGR = val;

Expand Down Expand Up @@ -1819,47 +1818,35 @@ static void generate_mac(uint8_t mac_addr[6])
#endif
}

static void monitor_work_handler(struct k_work *work)
static void phy_link_state_changed(const struct device *pdev,
struct phy_link_state *state,
void *user_data)
{
struct eth_sam_dev_data *const dev_data =
CONTAINER_OF(work, struct eth_sam_dev_data, monitor_work);
const struct device *dev = net_if_get_device(dev_data->iface);
const struct device *dev = (struct device *) user_data;
struct eth_sam_dev_data *const dev_data = DEV_DATA(dev);
const struct eth_sam_dev_cfg *const cfg = DEV_CFG(dev);
bool link_status;
uint32_t link_config;
int result;
bool is_up;

/* Poll PHY link status */
link_status = phy_sam_gmac_link_status_get(&cfg->phy);
is_up = state->is_up;

if (link_status && !dev_data->link_up) {
if (is_up && !dev_data->link_up) {
LOG_INF("Link up");

/* Announce link up status */
dev_data->link_up = true;
net_eth_carrier_on(dev_data->iface);

/* PHY auto-negotiate link parameters */
result = phy_sam_gmac_auto_negotiate(&cfg->phy, &link_config);
if (result < 0) {
LOG_ERR("ETH PHY auto-negotiate sequence failed");
goto finally;
}

/* Set up link parameters */
link_configure(cfg->regs, link_config);
} else if (!link_status && dev_data->link_up) {
/* Set up link */
link_configure(cfg->regs,
PHY_LINK_IS_FULL_DUPLEX(state->speed),
PHY_LINK_IS_SPEED_100M(state->speed));
} else if (!is_up && dev_data->link_up) {
LOG_INF("Link down");

/* Announce link down status */
dev_data->link_up = false;
net_eth_carrier_off(dev_data->iface);
}

finally:
/* Submit delayed work */
k_work_reschedule(&dev_data->monitor_work,
K_MSEC(CONFIG_ETH_SAM_GMAC_MONITOR_PERIOD));
}

static void eth0_iface_init(struct net_if *iface)
Expand Down Expand Up @@ -1967,19 +1954,14 @@ static void eth0_iface_init(struct net_if *iface)

#endif
#endif
if (device_is_ready(cfg->phy_dev)) {
phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed,
(void *)dev);

/* PHY initialize */
result = phy_sam_gmac_init(&cfg->phy);
if (result < 0) {
LOG_ERR("ETH PHY Initialization Error");
return;
} else {
LOG_ERR("PHY device not ready");
}

/* Initialise monitor */
k_work_init_delayable(&dev_data->monitor_work, monitor_work_handler);
k_work_reschedule(&dev_data->monitor_work,
K_MSEC(CONFIG_ETH_SAM_GMAC_MONITOR_PERIOD));

/* Do not start the interface until PHY link is up */
net_if_flag_set(iface, NET_IF_NO_AUTO_START);

Expand Down Expand Up @@ -2229,7 +2211,11 @@ static const struct eth_sam_dev_cfg eth0_config = {
.pin_list_size = ARRAY_SIZE(pins_eth0),
#endif
.config_func = eth0_irq_config,
.phy = {(Gmac *)DT_INST_REG_ADDR(0), CONFIG_ETH_SAM_GMAC_PHY_ADDR},
#if DT_NODE_EXISTS(DT_CHILD(DT_DRV_INST(0), phy))
.phy_dev = DEVICE_DT_GET(DT_CHILD(DT_DRV_INST(0), phy))
#else
#error "No PHY driver specified"
#endif
};

static struct eth_sam_dev_data eth0_data = {
Expand Down
3 changes: 1 addition & 2 deletions drivers/ethernet/eth_sam_gmac_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ struct eth_sam_dev_cfg {
uint32_t pin_list_size;
#endif
void (*config_func)(void);
struct phy_sam_gmac_dev phy;
const struct device *phy_dev;
};

/* Device run time data */
Expand All @@ -277,7 +277,6 @@ struct eth_sam_dev_data {
const struct device *ptp_clock;
#endif
uint8_t mac_addr[6];
struct k_work_delayable monitor_work;
bool link_up;
struct gmac_queue queue_list[GMAC_QUEUE_NUM];
};
Expand Down
Loading

0 comments on commit 276996d

Please sign in to comment.