Skip to content

Commit c4cb45e

Browse files
arvinfnashif
authored andcommitted
drivers: mdio: add Atmel SAM MDIO driver
MDIO driver for ATSAM platform with Ethernet. Signed-off-by: Arvin Farahmand <[email protected]>
1 parent 419b103 commit c4cb45e

File tree

5 files changed

+178
-0
lines changed

5 files changed

+178
-0
lines changed

drivers/mdio/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
zephyr_library()
4+
5+
zephyr_library_sources_ifdef(CONFIG_MDIO_ATMEL_SAM mdio_sam.c)

drivers/mdio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if MDIO
1515

1616
# Include these first so that any properties (e.g. defaults) below can be
1717
# overridden (by defining symbols in multiple locations)
18+
source "drivers/mdio/Kconfig.sam"
1819

1920
config MDIO_INIT_PRIORITY
2021
int "Init priority"

drivers/mdio/Kconfig.sam

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2021 IP-Logix Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config MDIO_ATMEL_SAM
5+
bool "Atmel SAM MDIO driver"
6+
depends on ETH_SAM_GMAC
7+
default y
8+
help
9+
Enable Atmel SAM MCU Family MDIO driver.

drivers/mdio/mdio_sam.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright (c) 2021 IP-Logix Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT atmel_sam_mdio
8+
9+
#include <errno.h>
10+
#include <device.h>
11+
#include <init.h>
12+
#include <soc.h>
13+
#include <drivers/mdio.h>
14+
15+
#include <logging/log.h>
16+
LOG_MODULE_REGISTER(mdio_sam, CONFIG_MDIO_LOG_LEVEL);
17+
18+
/* GMAC */
19+
#ifdef CONFIG_SOC_FAMILY_SAM0
20+
#define GMAC_MAN MAN.reg
21+
#define GMAC_NSR NSR.reg
22+
#define GMAC_NCR NCR.reg
23+
#endif
24+
25+
struct mdio_sam_dev_data {
26+
struct k_sem sem;
27+
};
28+
29+
struct mdio_sam_dev_config {
30+
Gmac * const regs;
31+
int protocol;
32+
};
33+
34+
#define DEV_NAME(dev) ((dev)->name)
35+
#define DEV_DATA(dev) ((struct mdio_sam_dev_data *const)(dev)->data)
36+
#define DEV_CFG(dev) \
37+
((const struct mdio_sam_dev_config *const)(dev)->config)
38+
39+
static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad,
40+
uint8_t rw, uint16_t data_in, uint16_t *data_out)
41+
{
42+
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev);
43+
struct mdio_sam_dev_data *const data = DEV_DATA(dev);
44+
int timeout = 50;
45+
46+
k_sem_take(&data->sem, K_FOREVER);
47+
48+
/* Write mdio transaction */
49+
if (cfg->protocol == CLAUSE_45) {
50+
cfg->regs->GMAC_MAN = (GMAC_MAN_OP(rw ? 0x2 : 0x3))
51+
| GMAC_MAN_WTN(0x02)
52+
| GMAC_MAN_PHYA(prtad)
53+
| GMAC_MAN_REGA(devad)
54+
| GMAC_MAN_DATA(data_in);
55+
56+
} else if (cfg->protocol == CLAUSE_22) {
57+
cfg->regs->GMAC_MAN = GMAC_MAN_CLTTO
58+
| (GMAC_MAN_OP(rw ? 0x2 : 0x1))
59+
| GMAC_MAN_WTN(0x02)
60+
| GMAC_MAN_PHYA(prtad)
61+
| GMAC_MAN_REGA(devad)
62+
| GMAC_MAN_DATA(data_in);
63+
64+
} else {
65+
LOG_ERR("Unsupported protocol");
66+
}
67+
68+
/* Wait until done */
69+
while (!(cfg->regs->GMAC_NSR & GMAC_NSR_IDLE)) {
70+
if (timeout-- == 0U) {
71+
LOG_ERR("transfer timedout %s", DEV_NAME(dev));
72+
k_sem_give(&data->sem);
73+
74+
return -ETIMEDOUT;
75+
}
76+
77+
k_sleep(K_MSEC(5));
78+
}
79+
80+
if (data_out) {
81+
*data_out = cfg->regs->GMAC_MAN & GMAC_MAN_DATA_Msk;
82+
}
83+
84+
k_sem_give(&data->sem);
85+
86+
return 0;
87+
}
88+
89+
static int mdio_sam_read(const struct device *dev, uint8_t prtad, uint8_t devad,
90+
uint16_t *data)
91+
{
92+
return mdio_transfer(dev, prtad, devad, 1, 0, data);
93+
}
94+
95+
static int mdio_sam_write(const struct device *dev, uint8_t prtad,
96+
uint8_t devad, uint16_t data)
97+
{
98+
return mdio_transfer(dev, prtad, devad, 0, data, NULL);
99+
}
100+
101+
static void mdio_sam_bus_enable(const struct device *dev)
102+
{
103+
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev);
104+
105+
cfg->regs->GMAC_NCR |= GMAC_NCR_MPE;
106+
}
107+
108+
static void mdio_sam_bus_disable(const struct device *dev)
109+
{
110+
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev);
111+
112+
cfg->regs->GMAC_NCR &= ~GMAC_NCR_MPE;
113+
}
114+
115+
static int mdio_sam_initialize(const struct device *dev)
116+
{
117+
struct mdio_sam_dev_data *const data = DEV_DATA(dev);
118+
119+
k_sem_init(&data->sem, 1, 1);
120+
121+
return 0;
122+
}
123+
124+
static const struct mdio_driver_api mdio_sam_driver_api = {
125+
.read = mdio_sam_read,
126+
.write = mdio_sam_write,
127+
.bus_enable = mdio_sam_bus_enable,
128+
.bus_disable = mdio_sam_bus_disable,
129+
};
130+
131+
#define MDIO_SAM_CONFIG(n) \
132+
static const struct mdio_sam_dev_config mdio_sam_dev_config_##n = { \
133+
.regs = (Gmac *)DT_REG_ADDR(DT_PARENT(DT_DRV_INST(n))), \
134+
.protocol = DT_ENUM_IDX(DT_DRV_INST(n), protocol), \
135+
};
136+
137+
#define MDIO_SAM_DEVICE(n) \
138+
MDIO_SAM_CONFIG(n); \
139+
static struct mdio_sam_dev_data mdio_sam_dev_data##n; \
140+
DEVICE_DT_INST_DEFINE(n, \
141+
&mdio_sam_initialize, \
142+
NULL, \
143+
&mdio_sam_dev_data##n, \
144+
&mdio_sam_dev_config_##n, POST_KERNEL, \
145+
CONFIG_MDIO_INIT_PRIORITY, \
146+
&mdio_sam_driver_api);
147+
148+
DT_INST_FOREACH_STATUS_OKAY(MDIO_SAM_DEVICE)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2021 IP-Logix Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Atmel SAM Family MDIO Driver node
5+
6+
compatible: "atmel,sam-mdio"
7+
8+
include: mdio-controller.yaml
9+
10+
properties:
11+
pinctrl-0:
12+
type: phandles
13+
required: false
14+
description: |
15+
PIO pin configuration for MDC, and MDIO signals.
16+
17+
For example the GMAC on SAME7x would be
18+
pinctrl-0 = <&pd8a_gmac_gmdc &pd9a_gmac_gmdio>;

0 commit comments

Comments
 (0)