blob: 063d90f65c0767e46dba1b4c83d9a44810b2b21e [file] [log] [blame]
/*
* Copyright (c) 2024 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/mdio.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/mdio.h>
#include "r_ether_phy.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(renesas_ra_mdio, CONFIG_MDIO_LOG_LEVEL);
#define DT_DRV_COMPAT renesas_ra_mdio
struct renesas_ra_mdio_config {
const struct pinctrl_dev_config *pincfg;
uint8_t instance;
};
struct renesas_ra_mdio_data {
struct k_mutex rw_mutex;
struct st_ether_phy_cfg ether_phy_cfg;
struct st_ether_phy_instance_ctrl ether_phy_ctrl;
};
static int renesas_ra_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t *data)
{
struct renesas_ra_mdio_data *dev_data = dev->data;
ether_phy_extended_cfg_t *ext_cfg =
(ether_phy_extended_cfg_t *)dev_data->ether_phy_cfg.p_extend;
uint32_t read;
fsp_err_t err;
ext_cfg->p_phy_lsi_cfg_list[0]->address = prtad;
k_mutex_lock(&dev_data->rw_mutex, K_FOREVER);
err = R_ETHER_PHY_Read(&dev_data->ether_phy_ctrl, regad, &read);
k_mutex_unlock(&dev_data->rw_mutex);
if (err != FSP_SUCCESS) {
return -EIO;
}
*data = read & UINT16_MAX;
return 0;
}
static int renesas_ra_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad,
uint16_t data)
{
struct renesas_ra_mdio_data *dev_data = dev->data;
ether_phy_extended_cfg_t *ext_cfg =
(ether_phy_extended_cfg_t *)dev_data->ether_phy_cfg.p_extend;
fsp_err_t err;
ext_cfg->p_phy_lsi_cfg_list[0]->address = prtad;
k_mutex_lock(&dev_data->rw_mutex, K_FOREVER);
err = R_ETHER_PHY_Write(&dev_data->ether_phy_ctrl, regad, data);
k_mutex_unlock(&dev_data->rw_mutex);
if (err != FSP_SUCCESS) {
return -EIO;
}
return 0;
}
static int renesas_ra_mdio_initialize(const struct device *dev)
{
struct renesas_ra_mdio_data *data = dev->data;
const struct renesas_ra_mdio_config *cfg = dev->config;
int err;
fsp_err_t fsp_err;
err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
if (err != 0) {
return err;
}
fsp_err = R_ETHER_PHY_Open(&data->ether_phy_ctrl, &data->ether_phy_cfg);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Failed to init mdio driver - R_ETHER_PHY_Open fail");
}
k_mutex_init(&data->rw_mutex);
return 0;
}
static DEVICE_API(mdio, renesas_ra_mdio_api) = {
.read = renesas_ra_mdio_read,
.write = renesas_ra_mdio_write,
};
#define RENSAS_RA_MDIO_INSTANCE_DEFINE(node) \
PINCTRL_DT_INST_DEFINE(node); \
static ether_phy_lsi_cfg_t renesas_ra_mdio##node##_lsi_cfg_list = { \
.type = ETHER_PHY_LSI_TYPE_CUSTOM, \
}; \
static ether_phy_extended_cfg_t renesas_ra_mdio##node##_extend = { \
.p_phy_lsi_cfg_list = \
{ \
&renesas_ra_mdio##node##_lsi_cfg_list, \
}, \
}; \
static struct renesas_ra_mdio_data renesas_ra_mdio##node##_data = { \
.ether_phy_cfg = { \
.channel = 0, \
.phy_reset_wait_time = 0x00020000, \
.mii_bit_access_wait_time = 8, \
.flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE, \
.p_extend = &renesas_ra_mdio##node##_extend, \
}}; \
static const struct renesas_ra_mdio_config renesas_ra_mdio##node##_cfg = { \
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(node)}; \
DEVICE_DT_INST_DEFINE(node, &renesas_ra_mdio_initialize, NULL, \
&renesas_ra_mdio##node##_data, &renesas_ra_mdio##node##_cfg, \
POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, &renesas_ra_mdio_api);
DT_INST_FOREACH_STATUS_OKAY(RENSAS_RA_MDIO_INSTANCE_DEFINE)