1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <errno.h>
9 #include <zephyr/device.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <zephyr/drivers/mdio.h>
13 #include <zephyr/net/ethernet.h>
14 #include <zephyr/net/mdio.h>
15 #include "r_ether_phy.h"
16
17 #include <zephyr/logging/log.h>
18
19 LOG_MODULE_REGISTER(renesas_ra_mdio, CONFIG_MDIO_LOG_LEVEL);
20
21 #define DT_DRV_COMPAT renesas_ra_mdio
22
23 struct renesas_ra_mdio_config {
24 const struct pinctrl_dev_config *pincfg;
25 uint8_t instance;
26 };
27
28 struct renesas_ra_mdio_data {
29 struct k_mutex rw_mutex;
30 struct st_ether_phy_cfg ether_phy_cfg;
31 struct st_ether_phy_instance_ctrl ether_phy_ctrl;
32 };
33
renesas_ra_mdio_read(const struct device * dev,uint8_t prtad,uint8_t regad,uint16_t * data)34 static int renesas_ra_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad,
35 uint16_t *data)
36 {
37 struct renesas_ra_mdio_data *dev_data = dev->data;
38 uint32_t read;
39 fsp_err_t err;
40
41 dev_data->ether_phy_ctrl.phy_lsi_address = prtad;
42
43 k_mutex_lock(&dev_data->rw_mutex, K_FOREVER);
44
45 err = R_ETHER_PHY_Read(&dev_data->ether_phy_ctrl, regad, &read);
46
47 k_mutex_unlock(&dev_data->rw_mutex);
48
49 if (err != FSP_SUCCESS) {
50 return -EIO;
51 }
52
53 *data = read & UINT16_MAX;
54
55 return 0;
56 }
57
renesas_ra_mdio_write(const struct device * dev,uint8_t prtad,uint8_t regad,uint16_t data)58 static int renesas_ra_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad,
59 uint16_t data)
60 {
61 struct renesas_ra_mdio_data *dev_data = dev->data;
62 fsp_err_t err;
63
64 dev_data->ether_phy_ctrl.phy_lsi_address = prtad;
65
66 k_mutex_lock(&dev_data->rw_mutex, K_FOREVER);
67
68 err = R_ETHER_PHY_Write(&dev_data->ether_phy_ctrl, regad, data);
69
70 k_mutex_unlock(&dev_data->rw_mutex);
71
72 if (err != FSP_SUCCESS) {
73 return -EIO;
74 }
75
76 return 0;
77 }
78
renesas_ra_mdio_initialize(const struct device * dev)79 static int renesas_ra_mdio_initialize(const struct device *dev)
80 {
81 struct renesas_ra_mdio_data *data = dev->data;
82 const struct renesas_ra_mdio_config *cfg = dev->config;
83 int err;
84 fsp_err_t fsp_err;
85
86 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
87 if (err != 0) {
88 return err;
89 }
90
91 fsp_err = R_ETHER_PHY_Open(&data->ether_phy_ctrl, &data->ether_phy_cfg);
92
93 if (fsp_err != FSP_SUCCESS) {
94 LOG_ERR("Failed to init mdio driver - R_ETHER_PHY_Open fail");
95 }
96
97 k_mutex_init(&data->rw_mutex);
98
99 return 0;
100 }
101
102 static DEVICE_API(mdio, renesas_ra_mdio_api) = {
103 .read = renesas_ra_mdio_read,
104 .write = renesas_ra_mdio_write,
105 };
106
107 #define RENSAS_RA_MDIO_INSTANCE_DEFINE(node) \
108 PINCTRL_DT_INST_DEFINE(node); \
109 static struct renesas_ra_mdio_data renesas_ra_mdio##node##_data = { \
110 .ether_phy_cfg = { \
111 .channel = 0, \
112 .phy_reset_wait_time = 0x00020000, \
113 .mii_bit_access_wait_time = 8, \
114 .phy_lsi_type = ETHER_PHY_LSI_TYPE_CUSTOM, \
115 .flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE, \
116 }}; \
117 static const struct renesas_ra_mdio_config renesas_ra_mdio##node##_cfg = { \
118 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(node)}; \
119 DEVICE_DT_INST_DEFINE(node, &renesas_ra_mdio_initialize, NULL, \
120 &renesas_ra_mdio##node##_data, &renesas_ra_mdio##node##_cfg, \
121 POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, &renesas_ra_mdio_api);
122
123 DT_INST_FOREACH_STATUS_OKAY(RENSAS_RA_MDIO_INSTANCE_DEFINE)
124