drivers: mdio: Add ESP32 MDIO driver
The MDIO driver is required to for ESP32 Ethernet Signed-off-by: Grant Ramsay <grant.ramsay@hotmail.com>
This commit is contained in:
parent
58de4291d5
commit
113f868ddf
|
@ -4,3 +4,4 @@ zephyr_library()
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_MDIO_SHELL mdio_shell.c)
|
zephyr_library_sources_ifdef(CONFIG_MDIO_SHELL mdio_shell.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MDIO_ATMEL_SAM mdio_sam.c)
|
zephyr_library_sources_ifdef(CONFIG_MDIO_ATMEL_SAM mdio_sam.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_MDIO_ESP32 mdio_esp32.c)
|
||||||
|
|
|
@ -25,6 +25,7 @@ config MDIO_SHELL
|
||||||
|
|
||||||
# Include these first so that any properties (e.g. defaults) below can be
|
# Include these first so that any properties (e.g. defaults) below can be
|
||||||
# overridden (by defining symbols in multiple locations)
|
# overridden (by defining symbols in multiple locations)
|
||||||
|
source "drivers/mdio/Kconfig.esp32"
|
||||||
source "drivers/mdio/Kconfig.sam"
|
source "drivers/mdio/Kconfig.sam"
|
||||||
|
|
||||||
config MDIO_INIT_PRIORITY
|
config MDIO_INIT_PRIORITY
|
||||||
|
|
9
drivers/mdio/Kconfig.esp32
Normal file
9
drivers/mdio/Kconfig.esp32
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2022 Grant Ramsay <grant.ramsay@hotmail.com>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config MDIO_ESP32
|
||||||
|
bool "ESP32 MDIO driver"
|
||||||
|
depends on SOC_ESP32
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable ESP32 MCU Family MDIO driver.
|
162
drivers/mdio/mdio_esp32.c
Normal file
162
drivers/mdio/mdio_esp32.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Grant Ramsay <grant.ramsay@hotmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT espressif_esp32_mdio
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include <zephyr/drivers/clock_control.h>
|
||||||
|
#include <zephyr/drivers/mdio.h>
|
||||||
|
#include <zephyr/drivers/pinctrl.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <esp_mac.h>
|
||||||
|
#include <hal/emac_hal.h>
|
||||||
|
#include <hal/emac_ll.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(mdio_esp32, CONFIG_MDIO_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define PHY_OPERATION_TIMEOUT_US 1000
|
||||||
|
|
||||||
|
struct mdio_esp32_dev_data {
|
||||||
|
struct k_sem sem;
|
||||||
|
emac_hal_context_t hal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mdio_esp32_dev_config {
|
||||||
|
const struct pinctrl_dev_config *pcfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mdio_transfer(const struct device *dev, uint8_t prtad, uint8_t devad,
|
||||||
|
bool write, uint16_t data_in, uint16_t *data_out)
|
||||||
|
{
|
||||||
|
struct mdio_esp32_dev_data *const dev_data = dev->data;
|
||||||
|
|
||||||
|
k_sem_take(&dev_data->sem, K_FOREVER);
|
||||||
|
|
||||||
|
if (emac_ll_is_mii_busy(dev_data->hal.mac_regs)) {
|
||||||
|
LOG_ERR("phy busy");
|
||||||
|
k_sem_give(&dev_data->sem);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write) {
|
||||||
|
emac_ll_set_phy_data(dev_data->hal.mac_regs, data_in);
|
||||||
|
}
|
||||||
|
emac_hal_set_phy_cmd(&dev_data->hal, prtad, devad, write);
|
||||||
|
|
||||||
|
/* Poll until operation complete */
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for (uint32_t t_us = 0; t_us < PHY_OPERATION_TIMEOUT_US; t_us += 100) {
|
||||||
|
k_sleep(K_USEC(100));
|
||||||
|
if (!emac_ll_is_mii_busy(dev_data->hal.mac_regs)) {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
LOG_ERR("phy timeout");
|
||||||
|
k_sem_give(&dev_data->sem);
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!write && data_out != NULL) {
|
||||||
|
*data_out = emac_ll_get_phy_data(dev_data->hal.mac_regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_give(&dev_data->sem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mdio_esp32_read(const struct device *dev, uint8_t prtad, uint8_t devad,
|
||||||
|
uint16_t *data)
|
||||||
|
{
|
||||||
|
return mdio_transfer(dev, prtad, devad, false, 0, data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mdio_esp32_write(const struct device *dev, uint8_t prtad,
|
||||||
|
uint8_t devad, uint16_t data)
|
||||||
|
{
|
||||||
|
return mdio_transfer(dev, prtad, devad, true, data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mdio_esp32_bus_enable(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mdio_esp32_bus_disable(const struct device *dev)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mdio_esp32_initialize(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mdio_esp32_dev_config *const cfg = dev->config;
|
||||||
|
struct mdio_esp32_dev_data *const dev_data = dev->data;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
k_sem_init(&dev_data->sem, 1, 1);
|
||||||
|
|
||||||
|
res = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
|
||||||
|
if (res != 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct device *clock_dev =
|
||||||
|
DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_NODELABEL(mdio)));
|
||||||
|
clock_control_subsys_t clock_subsys =
|
||||||
|
(clock_control_subsys_t)DT_CLOCKS_CELL(DT_NODELABEL(mdio), offset);
|
||||||
|
|
||||||
|
res = clock_control_on(clock_dev, clock_subsys);
|
||||||
|
if (res != 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only the mac registers are required for MDIO */
|
||||||
|
dev_data->hal.mac_regs = &EMAC_MAC;
|
||||||
|
|
||||||
|
/* Init MDIO clock */
|
||||||
|
emac_hal_set_csr_clock_range(&dev_data->hal, esp_clk_apb_freq());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mdio_driver_api mdio_esp32_driver_api = {
|
||||||
|
.read = mdio_esp32_read,
|
||||||
|
.write = mdio_esp32_write,
|
||||||
|
.bus_enable = mdio_esp32_bus_enable,
|
||||||
|
.bus_disable = mdio_esp32_bus_disable,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MDIO_ESP32_CONFIG(n) \
|
||||||
|
static const struct mdio_esp32_dev_config mdio_esp32_dev_config_##n = { \
|
||||||
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MDIO_ESP32_PROTOCOL_ASSERT(n) \
|
||||||
|
BUILD_ASSERT(DT_INST_ENUM_IDX(n, protocol) == CLAUSE_22, \
|
||||||
|
"ESP32 MDIO only supports CLAUSE_22 protocol")
|
||||||
|
|
||||||
|
#define MDIO_ESP32_DEVICE(n) \
|
||||||
|
MDIO_ESP32_PROTOCOL_ASSERT(n); \
|
||||||
|
PINCTRL_DT_INST_DEFINE(n); \
|
||||||
|
MDIO_ESP32_CONFIG(n); \
|
||||||
|
static struct mdio_esp32_dev_data mdio_esp32_dev_data##n; \
|
||||||
|
DEVICE_DT_INST_DEFINE(n, \
|
||||||
|
&mdio_esp32_initialize, \
|
||||||
|
NULL, \
|
||||||
|
&mdio_esp32_dev_data##n, \
|
||||||
|
&mdio_esp32_dev_config_##n, POST_KERNEL, \
|
||||||
|
CONFIG_MDIO_INIT_PRIORITY, \
|
||||||
|
&mdio_esp32_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(MDIO_ESP32_DEVICE)
|
|
@ -14,7 +14,15 @@
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL);
|
LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL);
|
||||||
|
|
||||||
#define MDIO_NODE_ID DT_COMPAT_GET_ANY_STATUS_OKAY(atmel_sam_mdio)
|
#if DT_HAS_COMPAT_STATUS_OKAY(atmel_sam_mdio)
|
||||||
|
#define DT_DRV_COMPAT atmel_sam_mdio
|
||||||
|
#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_mdio)
|
||||||
|
#define DT_DRV_COMPAT espressif_esp32_mdio
|
||||||
|
#else
|
||||||
|
#error "No known devicetree compatible match for MDIO shell"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MDIO_NODE_ID DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the entire 5-bit address space of the MDIO bus
|
* Scan the entire 5-bit address space of the MDIO bus
|
||||||
|
|
10
dts/bindings/mdio/espressif,esp32-mdio.yaml
Normal file
10
dts/bindings/mdio/espressif,esp32-mdio.yaml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2022 Grant Ramsay <grant.ramsay@hotmail.com>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: ESP32 MDIO Driver node
|
||||||
|
|
||||||
|
compatible: "espressif,esp32-mdio"
|
||||||
|
|
||||||
|
include:
|
||||||
|
- name: mdio-controller.yaml
|
||||||
|
- name: pinctrl-device.yaml
|
|
@ -42,6 +42,13 @@
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mdio: mdio {
|
||||||
|
compatible = "espressif,esp32-mdio";
|
||||||
|
protocol = "clause 22";
|
||||||
|
clocks = <&rtc ESP32_EMAC_MODULE>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
pinctrl: pin-controller {
|
pinctrl: pin-controller {
|
||||||
compatible = "espressif,esp32-pinctrl";
|
compatible = "espressif,esp32-pinctrl";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
Loading…
Reference in a new issue