Browse Source
MDIO driver for ATSAM platform with Ethernet. Signed-off-by: Arvin Farahmand <arvinf@ip-logix.com>pull/34548/head
5 changed files with 178 additions and 0 deletions
@ -1,3 +1,5 @@
@@ -1,3 +1,5 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
zephyr_library() |
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_MDIO_ATMEL_SAM mdio_sam.c) |
||||
|
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2021 IP-Logix Inc. |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
config MDIO_ATMEL_SAM |
||||
bool "Atmel SAM MDIO driver" |
||||
depends on ETH_SAM_GMAC |
||||
default y |
||||
help |
||||
Enable Atmel SAM MCU Family MDIO driver. |
@ -0,0 +1,148 @@
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2021 IP-Logix Inc. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#define DT_DRV_COMPAT atmel_sam_mdio |
||||
|
||||
#include <errno.h> |
||||
#include <device.h> |
||||
#include <init.h> |
||||
#include <soc.h> |
||||
#include <drivers/mdio.h> |
||||
|
||||
#include <logging/log.h> |
||||
LOG_MODULE_REGISTER(mdio_sam, CONFIG_MDIO_LOG_LEVEL); |
||||
|
||||
/* GMAC */ |
||||
#ifdef CONFIG_SOC_FAMILY_SAM0 |
||||
#define GMAC_MAN MAN.reg |
||||
#define GMAC_NSR NSR.reg |
||||
#define GMAC_NCR NCR.reg |
||||
#endif |
||||
|
||||
struct mdio_sam_dev_data { |
||||
struct k_sem sem; |
||||
}; |
||||
|
||||
struct mdio_sam_dev_config { |
||||
Gmac * const regs; |
||||
int protocol; |
||||
}; |
||||
|
||||
#define DEV_NAME(dev) ((dev)->name) |
||||
#define DEV_DATA(dev) ((struct mdio_sam_dev_data *const)(dev)->data) |
||||
#define DEV_CFG(dev) \ |
||||
((const struct mdio_sam_dev_config *const)(dev)->config) |
||||
|
||||
static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad, |
||||
uint8_t rw, uint16_t data_in, uint16_t *data_out) |
||||
{ |
||||
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev); |
||||
struct mdio_sam_dev_data *const data = DEV_DATA(dev); |
||||
int timeout = 50; |
||||
|
||||
k_sem_take(&data->sem, K_FOREVER); |
||||
|
||||
/* Write mdio transaction */ |
||||
if (cfg->protocol == CLAUSE_45) { |
||||
cfg->regs->GMAC_MAN = (GMAC_MAN_OP(rw ? 0x2 : 0x3)) |
||||
| GMAC_MAN_WTN(0x02) |
||||
| GMAC_MAN_PHYA(prtad) |
||||
| GMAC_MAN_REGA(devad) |
||||
| GMAC_MAN_DATA(data_in); |
||||
|
||||
} else if (cfg->protocol == CLAUSE_22) { |
||||
cfg->regs->GMAC_MAN = GMAC_MAN_CLTTO |
||||
| (GMAC_MAN_OP(rw ? 0x2 : 0x1)) |
||||
| GMAC_MAN_WTN(0x02) |
||||
| GMAC_MAN_PHYA(prtad) |
||||
| GMAC_MAN_REGA(devad) |
||||
| GMAC_MAN_DATA(data_in); |
||||
|
||||
} else { |
||||
LOG_ERR("Unsupported protocol"); |
||||
} |
||||
|
||||
/* Wait until done */ |
||||
while (!(cfg->regs->GMAC_NSR & GMAC_NSR_IDLE)) { |
||||
if (timeout-- == 0U) { |
||||
LOG_ERR("transfer timedout %s", DEV_NAME(dev)); |
||||
k_sem_give(&data->sem); |
||||
|
||||
return -ETIMEDOUT; |
||||
} |
||||
|
||||
k_sleep(K_MSEC(5)); |
||||
} |
||||
|
||||
if (data_out) { |
||||
*data_out = cfg->regs->GMAC_MAN & GMAC_MAN_DATA_Msk; |
||||
} |
||||
|
||||
k_sem_give(&data->sem); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int mdio_sam_read(const struct device *dev, uint8_t prtad, uint8_t devad, |
||||
uint16_t *data) |
||||
{ |
||||
return mdio_transfer(dev, prtad, devad, 1, 0, data); |
||||
} |
||||
|
||||
static int mdio_sam_write(const struct device *dev, uint8_t prtad, |
||||
uint8_t devad, uint16_t data) |
||||
{ |
||||
return mdio_transfer(dev, prtad, devad, 0, data, NULL); |
||||
} |
||||
|
||||
static void mdio_sam_bus_enable(const struct device *dev) |
||||
{ |
||||
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev); |
||||
|
||||
cfg->regs->GMAC_NCR |= GMAC_NCR_MPE; |
||||
} |
||||
|
||||
static void mdio_sam_bus_disable(const struct device *dev) |
||||
{ |
||||
const struct mdio_sam_dev_config *const cfg = DEV_CFG(dev); |
||||
|
||||
cfg->regs->GMAC_NCR &= ~GMAC_NCR_MPE; |
||||
} |
||||
|
||||
static int mdio_sam_initialize(const struct device *dev) |
||||
{ |
||||
struct mdio_sam_dev_data *const data = DEV_DATA(dev); |
||||
|
||||
k_sem_init(&data->sem, 1, 1); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static const struct mdio_driver_api mdio_sam_driver_api = { |
||||
.read = mdio_sam_read, |
||||
.write = mdio_sam_write, |
||||
.bus_enable = mdio_sam_bus_enable, |
||||
.bus_disable = mdio_sam_bus_disable, |
||||
}; |
||||
|
||||
#define MDIO_SAM_CONFIG(n) \ |
||||
static const struct mdio_sam_dev_config mdio_sam_dev_config_##n = { \ |
||||
.regs = (Gmac *)DT_REG_ADDR(DT_PARENT(DT_DRV_INST(n))), \ |
||||
.protocol = DT_ENUM_IDX(DT_DRV_INST(n), protocol), \ |
||||
}; |
||||
|
||||
#define MDIO_SAM_DEVICE(n) \ |
||||
MDIO_SAM_CONFIG(n); \ |
||||
static struct mdio_sam_dev_data mdio_sam_dev_data##n; \ |
||||
DEVICE_DT_INST_DEFINE(n, \ |
||||
&mdio_sam_initialize, \ |
||||
NULL, \ |
||||
&mdio_sam_dev_data##n, \ |
||||
&mdio_sam_dev_config_##n, POST_KERNEL, \ |
||||
CONFIG_MDIO_INIT_PRIORITY, \ |
||||
&mdio_sam_driver_api); |
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(MDIO_SAM_DEVICE) |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2021 IP-Logix Inc. |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
description: Atmel SAM Family MDIO Driver node |
||||
|
||||
compatible: "atmel,sam-mdio" |
||||
|
||||
include: mdio-controller.yaml |
||||
|
||||
properties: |
||||
pinctrl-0: |
||||
type: phandles |
||||
required: false |
||||
description: | |
||||
PIO pin configuration for MDC, and MDIO signals. |
||||
|
||||
For example the GMAC on SAME7x would be |
||||
pinctrl-0 = <&pd8a_gmac_gmdc &pd9a_gmac_gmdio>; |
Loading…
Reference in new issue