1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_imx_netc_emdio
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/mdio.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <zephyr/logging/log.h>
14 
15 #include "fsl_netc_mdio.h"
16 LOG_MODULE_REGISTER(nxp_imx_netc_emdio, CONFIG_MDIO_LOG_LEVEL);
17 
18 struct nxp_imx_netc_mdio_config {
19 	const struct pinctrl_dev_config *pincfg;
20 	const struct device *clock_dev;
21 	clock_control_subsys_t clock_subsys;
22 };
23 
24 struct nxp_imx_netc_mdio_data {
25 	struct k_mutex rw_mutex;
26 	netc_mdio_handle_t handle;
27 };
28 
nxp_imx_netc_mdio_read(const struct device * dev,uint8_t prtad,uint8_t regad,uint16_t * regval)29 static int nxp_imx_netc_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad,
30 				  uint16_t *regval)
31 {
32 	struct nxp_imx_netc_mdio_data *data = dev->data;
33 	status_t result;
34 
35 	k_mutex_lock(&data->rw_mutex, K_FOREVER);
36 	result = NETC_MDIORead(&data->handle, prtad, regad, regval);
37 	k_mutex_unlock(&data->rw_mutex);
38 
39 	return result == kStatus_Success ? 0 : -EIO;
40 }
41 
nxp_imx_netc_mdio_write(const struct device * dev,uint8_t prtad,uint8_t regad,uint16_t regval)42 static int nxp_imx_netc_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad,
43 				   uint16_t regval)
44 {
45 	struct nxp_imx_netc_mdio_data *data = dev->data;
46 	status_t result;
47 
48 	k_mutex_lock(&data->rw_mutex, K_FOREVER);
49 	result = NETC_MDIOWrite(&data->handle, prtad, regad, regval);
50 	k_mutex_unlock(&data->rw_mutex);
51 
52 	return result == kStatus_Success ? 0 : -EIO;
53 }
54 
nxp_imx_netc_mdio_initialize(const struct device * dev)55 static int nxp_imx_netc_mdio_initialize(const struct device *dev)
56 {
57 	struct nxp_imx_netc_mdio_data *data = dev->data;
58 	const struct nxp_imx_netc_mdio_config *cfg = dev->config;
59 	netc_mdio_config_t mdio_config = {0};
60 	status_t result;
61 	int err;
62 
63 	err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
64 	if (err) {
65 		return err;
66 	}
67 
68 	k_mutex_init(&data->rw_mutex);
69 
70 	err = clock_control_get_rate(cfg->clock_dev, cfg->clock_subsys, &mdio_config.srcClockHz);
71 	if (err) {
72 		return err;
73 	}
74 
75 	result = NETC_MDIOInit(&data->handle, &mdio_config);
76 	if (result != kStatus_Success) {
77 		return -EIO;
78 	}
79 
80 	return 0;
81 }
82 
83 static DEVICE_API(mdio, nxp_imx_netc_mdio_api) = {
84 	.read = nxp_imx_netc_mdio_read,
85 	.write = nxp_imx_netc_mdio_write,
86 };
87 
88 #define NXP_IMX_NETC_MDIO_INSTANCE_DEFINE(n)                                                       \
89 	PINCTRL_DT_INST_DEFINE(n);                                                                 \
90 	static struct nxp_imx_netc_mdio_data nxp_imx_netc_mdio##n##_data;                          \
91 	static const struct nxp_imx_netc_mdio_config nxp_imx_netc_mdio##n##_cfg = {                \
92 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),                                       \
93 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),                                \
94 		.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),              \
95 	};                                                                                         \
96 	DEVICE_DT_INST_DEFINE(n, &nxp_imx_netc_mdio_initialize, NULL,                              \
97 			      &nxp_imx_netc_mdio##n##_data, &nxp_imx_netc_mdio##n##_cfg,           \
98 			      POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, &nxp_imx_netc_mdio_api);
99 
100 DT_INST_FOREACH_STATUS_OKAY(NXP_IMX_NETC_MDIO_INSTANCE_DEFINE)
101