Skip to content

Commit e38f3e1

Browse files
tswaehnkartben
authored andcommitted
drivers: mdio: sy1xx add support for mdio
Add mdio support for the sensry soc sy1xx. Signed-off-by: Sven Ginka <[email protected]>
1 parent f8a5ebf commit e38f3e1

File tree

6 files changed

+229
-0
lines changed

6 files changed

+229
-0
lines changed

drivers/mdio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET_QOS mdio_nxp_enet_qos.c)
1818
zephyr_library_sources_ifdef(CONFIG_MDIO_DWCXGMAC mdio_dwcxgmac.c)
1919
zephyr_library_sources_ifdef(CONFIG_MDIO_RENESAS_RA mdio_renesas_ra.c)
2020
zephyr_library_sources_ifdef(CONFIG_MDIO_LAN865X mdio_lan865x.c)
21+
zephyr_library_sources_ifdef(CONFIG_MDIO_SENSRY_SY1XX mdio_sy1xx.c)

drivers/mdio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ source "drivers/mdio/Kconfig.nxp_enet_qos"
3939
source "drivers/mdio/Kconfig.dwcxgmac"
4040
source "drivers/mdio/Kconfig.renesas_ra"
4141
source "drivers/mdio/Kconfig.lan865x"
42+
source "drivers/mdio/Kconfig.sy1xx"
4243

4344
config MDIO_INIT_PRIORITY
4445
int "Init priority"

drivers/mdio/Kconfig.sy1xx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2024 sensry.io
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config MDIO_SENSRY_SY1XX
5+
bool "Sensry SY1XX MDIO driver"
6+
select PINCTRL
7+
depends on DT_HAS_SENSRY_SY1XX_MDIO_ENABLED
8+
default y
9+
help
10+
Enable Sensry SY1xx SOC Family MDIO driver.

drivers/mdio/mdio_shell.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL);
4343
#define DT_DRV_COMPAT st_stm32_mdio
4444
#elif DT_HAS_COMPAT_STATUS_OKAY(snps_dwcxgmac_mdio)
4545
#define DT_DRV_COMPAT snps_dwcxgmac_mdio
46+
#elif DT_HAS_COMPAT_STATUS_OKAY(sensry_sy1xx_mdio)
47+
#define DT_DRV_COMPAT sensry_sy1xx_mdio
4648
#else
4749
#error "No known devicetree compatible match for MDIO shell"
4850
#endif

drivers/mdio/mdio_sy1xx.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (c) 2024 sensry.io
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT sensry_sy1xx_mdio
8+
9+
#include <zephyr/logging/log.h>
10+
LOG_MODULE_REGISTER(sy1xx_mdio, CONFIG_MDIO_LOG_LEVEL);
11+
12+
#include <zephyr/drivers/mdio.h>
13+
#include <zephyr/kernel.h>
14+
#include <zephyr/drivers/pinctrl.h>
15+
#include <udma.h>
16+
17+
struct sy1xx_mdio_dev_config {
18+
const struct pinctrl_dev_config *pcfg;
19+
uint32_t base_addr;
20+
uint32_t mdc_freq;
21+
};
22+
23+
struct sy1xx_mdio_dev_data {
24+
struct k_sem sem;
25+
};
26+
27+
/* mdio register offsets */
28+
#define SY1XX_MDIO_CFG_REG 0x0000
29+
#define SY1XX_MDIO_CTRL_REG 0x0004
30+
#define SY1XX_MDIO_READ_DATA_REG 0x0008
31+
#define SY1XX_MDIO_WRITE_DATA_REG 0x000c
32+
#define SY1XX_MDIO_IRQ_REG 0x0010
33+
34+
/* mdio config register bit offsets */
35+
#define SY1XX_MDIO_CFG_DIV_OFFS (0)
36+
#define SY1XX_MDIO_CFG_EN_OFFS (8)
37+
38+
/* mdio ctrl register bit offsets */
39+
#define SY1XX_MDIO_CTRL_READY_OFFS (0)
40+
#define SY1XX_MDIO_CTRL_INIT_OFFS (8)
41+
#define SY1XX_MDIO_CTRL_REG_ADDR_OFFS (16)
42+
#define SY1XX_MDIO_CTRL_PHY_ADDR_OFFS (24)
43+
#define SY1XX_MDIO_CTRL_OP_OFFS (30)
44+
45+
/* mdio ctrl operations */
46+
#define SY1XX_MDIO_CTRL_OP_WRITE (0x1)
47+
#define SY1XX_MDIO_CTRL_OP_READ (0x2)
48+
49+
#define SY1XX_MDIO_READ_WRITE_WAIT_TIME_US (15)
50+
#define SY1XX_MDIO_READ_WRITE_RETRY_COUNT (5)
51+
52+
static int sy1xx_mdio_wait_for_ready(const struct device *dev);
53+
54+
static int sy1xx_mdio_initialize(const struct device *dev)
55+
{
56+
57+
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
58+
int ret;
59+
uint32_t divider;
60+
uint32_t reg;
61+
62+
/* zero mdio controller regs */
63+
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_CFG_REG);
64+
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
65+
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
66+
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_WRITE_DATA_REG);
67+
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_IRQ_REG);
68+
69+
/* prepare mdio clock and enable mdio controller */
70+
divider = (((sy1xx_soc_get_peripheral_clock() / cfg->mdc_freq) / 2) - 1) & 0xff;
71+
reg = (divider << SY1XX_MDIO_CFG_DIV_OFFS) | BIT(SY1XX_MDIO_CFG_EN_OFFS);
72+
73+
LOG_DBG("config, div: %d, freq: %d", divider, cfg->mdc_freq);
74+
75+
sys_write32(reg, cfg->base_addr + SY1XX_MDIO_CFG_REG);
76+
77+
/* PAD config */
78+
ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
79+
if (ret < 0) {
80+
LOG_ERR("failed to configure pins");
81+
return ret;
82+
}
83+
84+
ret = sy1xx_mdio_wait_for_ready(dev);
85+
if (ret < 0) {
86+
LOG_ERR("not ready");
87+
return ret;
88+
}
89+
90+
return 0;
91+
}
92+
93+
static uint32_t sy1xx_mdio_is_ready(const struct device *dev)
94+
{
95+
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
96+
uint32_t status = sys_read32(cfg->base_addr + SY1XX_MDIO_CTRL_REG);
97+
98+
return (status & BIT(SY1XX_MDIO_CTRL_READY_OFFS));
99+
}
100+
101+
static int sy1xx_mdio_wait_for_ready(const struct device *dev)
102+
{
103+
uint32_t retries_left = SY1XX_MDIO_READ_WRITE_RETRY_COUNT;
104+
105+
while (!sy1xx_mdio_is_ready(dev)) {
106+
k_sleep(K_USEC(SY1XX_MDIO_READ_WRITE_WAIT_TIME_US));
107+
retries_left--;
108+
if (!retries_left) {
109+
return -EINVAL;
110+
}
111+
}
112+
return 0;
113+
}
114+
115+
static int sy1xx_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data)
116+
{
117+
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
118+
int ret;
119+
uint32_t v;
120+
121+
prtad &= 0x1f;
122+
regad &= 0x1f;
123+
124+
v = (SY1XX_MDIO_CTRL_OP_READ << SY1XX_MDIO_CTRL_OP_OFFS) |
125+
(prtad << SY1XX_MDIO_CTRL_PHY_ADDR_OFFS) | (regad << SY1XX_MDIO_CTRL_REG_ADDR_OFFS) |
126+
BIT(SY1XX_MDIO_CTRL_INIT_OFFS);
127+
128+
/* start the reading procedure */
129+
sys_write32(v, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
130+
131+
/* wait for the reading operation to finish */
132+
ret = sy1xx_mdio_wait_for_ready(dev);
133+
if (ret < 0) {
134+
*data = sys_read32(cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
135+
136+
LOG_WRN("timeout while reading from phy: %d, reg: %d, val: %d", prtad, regad,
137+
*data);
138+
return ret;
139+
}
140+
141+
/* get the data from the read result register */
142+
*data = sys_read32(cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
143+
144+
return 0;
145+
}
146+
147+
static int sy1xx_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t data)
148+
{
149+
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
150+
int ret;
151+
uint32_t v;
152+
153+
prtad &= 0x1f;
154+
regad &= 0x1f;
155+
156+
/* put the data to the write register */
157+
sys_write32(data, cfg->base_addr + SY1XX_MDIO_WRITE_DATA_REG);
158+
159+
v = (SY1XX_MDIO_CTRL_OP_WRITE << SY1XX_MDIO_CTRL_OP_OFFS) |
160+
(prtad << SY1XX_MDIO_CTRL_PHY_ADDR_OFFS) | (regad << SY1XX_MDIO_CTRL_REG_ADDR_OFFS) |
161+
BIT(SY1XX_MDIO_CTRL_INIT_OFFS);
162+
163+
/* start the writing procedure */
164+
sys_write32(v, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
165+
166+
/* wait for the writing operation to finish */
167+
ret = sy1xx_mdio_wait_for_ready(dev);
168+
if (ret < 0) {
169+
LOG_WRN("timeout while writing to phy: %d, reg: %d, val: %d", prtad, regad, data);
170+
return ret;
171+
}
172+
173+
return 0;
174+
}
175+
176+
static DEVICE_API(mdio, sy1xx_mdio_driver_api) = {
177+
.read = sy1xx_mdio_read,
178+
.write = sy1xx_mdio_write,
179+
};
180+
181+
#define SY1XX_MDIO_INIT(n) \
182+
\
183+
PINCTRL_DT_INST_DEFINE(n); \
184+
\
185+
static const struct sy1xx_mdio_dev_config sy1xx_mdio_dev_config_##n = { \
186+
.base_addr = DT_INST_REG_ADDR(n), \
187+
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
188+
.mdc_freq = DT_INST_PROP(n, clock_frequency), \
189+
}; \
190+
\
191+
static struct sy1xx_mdio_dev_data sy1xx_mdio_dev_data##n; \
192+
\
193+
DEVICE_DT_INST_DEFINE(n, &sy1xx_mdio_initialize, NULL, &sy1xx_mdio_dev_data##n, \
194+
&sy1xx_mdio_dev_config_##n, POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, \
195+
&sy1xx_mdio_driver_api);
196+
197+
DT_INST_FOREACH_STATUS_OKAY(SY1XX_MDIO_INIT)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2024 sensry.io
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Sensry SY1XX MDIO Driver node
5+
6+
compatible: "sensry,sy1xx-mdio"
7+
8+
include: [base.yaml, mdio-controller.yaml, pinctrl-device.yaml]
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
pinctrl-0:
15+
required: true
16+
17+
pinctrl-names:
18+
required: true

0 commit comments

Comments
 (0)