Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: ethernet: phy: mii: simplify if all are fixed link #87628

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 84 additions & 66 deletions drivers/ethernet/phy/phy_mii.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(phy_mii, CONFIG_PHY_LOG_LEVEL);

#define ANY_DYNAMIC_LINK UTIL_NOT(DT_ALL_INST_HAS_PROP_STATUS_OKAY(fixed_link))
#define ANY_FIXED_LINK DT_ANY_INST_HAS_PROP_STATUS_OKAY(fixed_link)

struct phy_mii_dev_config {
uint8_t phy_addr;
bool no_reset;
Expand All @@ -30,20 +33,22 @@ struct phy_mii_dev_data {
const struct device *dev;
phy_callback_t cb;
void *cb_data;
struct k_work_delayable monitor_work;
struct phy_link_state state;
struct k_sem sem;
#if ANY_DYNAMIC_LINK
struct k_work_delayable monitor_work;
bool gigabit_supported;
#endif
};

/* Offset to align capabilities bits of 1000BASE-T Control and Status regs */
#define MII_1KSTSR_OFFSET 2

#define MII_INVALID_PHY_ID UINT32_MAX

static int phy_mii_get_link_state(const struct device *dev,
struct phy_link_state *state);
static void invoke_link_cb(const struct device *dev);

#if ANY_DYNAMIC_LINK
static inline int phy_mii_reg_read(const struct device *dev, uint16_t reg_addr,
uint16_t *value)
{
Expand Down Expand Up @@ -271,20 +276,6 @@ static int update_link_state(const struct device *dev)
return 0;
}

static void invoke_link_cb(const struct device *dev)
{
struct phy_mii_dev_data *const data = dev->data;
struct phy_link_state state;

if (data->cb == NULL) {
return;
}

phy_mii_get_link_state(dev, &state);

data->cb(data->dev, &state, data->cb_data);
}

static void monitor_work_handler(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
Expand All @@ -305,8 +296,7 @@ static void monitor_work_handler(struct k_work *work)
}

/* Submit delayed work */
k_work_reschedule(&data->monitor_work,
K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
k_work_reschedule(dwork, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
}

static int phy_mii_read(const struct device *dev, uint16_t reg_addr,
Expand Down Expand Up @@ -407,6 +397,7 @@ static int phy_mii_cfg_link(const struct device *dev,

return 0;
}
#endif /* ANY_DYNAMIC_LINK */

static int phy_mii_get_link_state(const struct device *dev,
struct phy_link_state *state)
Expand All @@ -422,6 +413,20 @@ static int phy_mii_get_link_state(const struct device *dev,
return 0;
}

static void invoke_link_cb(const struct device *dev)
{
struct phy_mii_dev_data *const data = dev->data;
struct phy_link_state state;

if (data->cb == NULL) {
return;
}

phy_mii_get_link_state(dev, &state);

data->cb(dev, &state, data->cb_data);
}

static int phy_mii_link_cb_set(const struct device *dev, phy_callback_t cb,
void *user_data)
{
Expand All @@ -439,81 +444,83 @@ static int phy_mii_link_cb_set(const struct device *dev, phy_callback_t cb,
return 0;
}

static int phy_mii_initialize(const struct device *dev)
#ifdef ANY_FIXED_LINK
static int phy_mii_initialize_fixed_link(const struct device *dev)
{
const struct phy_mii_dev_config *const cfg = dev->config;
struct phy_mii_dev_data *const data = dev->data;
uint32_t phy_id;

k_sem_init(&data->sem, 1, 1);

data->dev = dev;
data->cb = NULL;

/**
* If this is a *fixed* link then we don't need to communicate
* with a PHY. We set the link parameters as configured
* and set link state to up.
*/
if (cfg->fixed) {
const static int speed_to_phy_link_speed[] = {
LINK_HALF_10BASE_T,
LINK_FULL_10BASE_T,
LINK_HALF_100BASE_T,
LINK_FULL_100BASE_T,
LINK_HALF_1000BASE_T,
LINK_FULL_1000BASE_T,
};

data->state.speed = speed_to_phy_link_speed[cfg->fixed_speed];
data->state.is_up = true;
} else {
data->state.is_up = false;

mdio_bus_enable(cfg->mdio);
const static int speed_to_phy_link_speed[] = {
LINK_HALF_10BASE_T,
LINK_FULL_10BASE_T,
LINK_HALF_100BASE_T,
LINK_FULL_100BASE_T,
LINK_HALF_1000BASE_T,
LINK_FULL_1000BASE_T,
};

if (cfg->no_reset == false) {
reset(dev);
}
data->state.speed = speed_to_phy_link_speed[cfg->fixed_speed];
data->state.is_up = true;

if (get_id(dev, &phy_id) == 0) {
if (phy_id == MII_INVALID_PHY_ID) {
LOG_ERR("No PHY found at address %d",
cfg->phy_addr);
return 0;
}
#endif /* ANY_FIXED_LINK */

return -EINVAL;
}
#if ANY_DYNAMIC_LINK
static int phy_mii_initialize_dynamic_link(const struct device *dev)
{
const struct phy_mii_dev_config *const cfg = dev->config;
struct phy_mii_dev_data *const data = dev->data;
uint32_t phy_id;

LOG_INF("PHY (%d) ID %X", cfg->phy_addr, phy_id);
}
data->state.is_up = false;

mdio_bus_enable(cfg->mdio);

data->gigabit_supported = is_gigabit_supported(dev);
if (cfg->no_reset == false) {
reset(dev);
}

/* Advertise all speeds */
phy_mii_cfg_link(dev, LINK_HALF_10BASE_T |
LINK_FULL_10BASE_T |
LINK_HALF_100BASE_T |
LINK_FULL_100BASE_T |
LINK_HALF_1000BASE_T |
LINK_FULL_1000BASE_T);
if (get_id(dev, &phy_id) == 0) {
if (phy_id == MII_INVALID_PHY_ID) {
LOG_ERR("No PHY found at address %d", cfg->phy_addr);

k_work_init_delayable(&data->monitor_work,
monitor_work_handler);
return -EINVAL;
}

monitor_work_handler(&data->monitor_work.work);
LOG_INF("PHY (%d) ID %X", cfg->phy_addr, phy_id);
}

data->gigabit_supported = is_gigabit_supported(dev);

/* Advertise all speeds */
phy_mii_cfg_link(dev, LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | LINK_HALF_100BASE_T |
LINK_FULL_100BASE_T | LINK_HALF_1000BASE_T | LINK_FULL_1000BASE_T);

k_work_init_delayable(&data->monitor_work, monitor_work_handler);

monitor_work_handler(&data->monitor_work.work);

return 0;
}
#endif /* ANY_DYNAMIC_LINK */

#define IS_FIXED_LINK(n) DT_INST_NODE_HAS_PROP(n, fixed_link)

static DEVICE_API(ethphy, phy_mii_driver_api) = {
.get_link = phy_mii_get_link_state,
.cfg_link = phy_mii_cfg_link,
.link_cb_set = phy_mii_link_cb_set,
#if ANY_DYNAMIC_LINK
.cfg_link = phy_mii_cfg_link,
.read = phy_mii_read,
.write = phy_mii_write,
#endif
};

#define PHY_MII_CONFIG(n) \
Expand All @@ -526,11 +533,22 @@ static const struct phy_mii_dev_config phy_mii_dev_config_##n = { \
DEVICE_DT_GET(DT_INST_BUS(n))) \
};

#define PHY_MII_DATA(n) \
static struct phy_mii_dev_data phy_mii_dev_data_##n = { \
.dev = DEVICE_DT_INST_GET(n), \
.cb = NULL, \
.sem = Z_SEM_INITIALIZER(phy_mii_dev_data_##n.sem, 1, 1), \
};

#define PHY_MII_INIT(n) \
COND_CODE_1(IS_FIXED_LINK(n), (&phy_mii_initialize_fixed_link), \
(&phy_mii_initialize_dynamic_link))

#define PHY_MII_DEVICE(n) \
PHY_MII_CONFIG(n); \
static struct phy_mii_dev_data phy_mii_dev_data_##n; \
PHY_MII_DATA(n); \
DEVICE_DT_INST_DEFINE(n, \
&phy_mii_initialize, \
PHY_MII_INIT(n), \
NULL, \
&phy_mii_dev_data_##n, \
&phy_mii_dev_config_##n, POST_KERNEL, \
Expand Down
Loading
Loading