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