Browse Source

drivers: mdio: sy1xx add support for mdio

Add mdio support for the sensry soc sy1xx.

Signed-off-by: Sven Ginka <s.ginka@sensry.de>
pull/85245/head
Sven Ginka 7 months ago committed by Benjamin Cabé
parent
commit
e38f3e1c3c
  1. 1
      drivers/mdio/CMakeLists.txt
  2. 1
      drivers/mdio/Kconfig
  3. 10
      drivers/mdio/Kconfig.sy1xx
  4. 2
      drivers/mdio/mdio_shell.c
  5. 197
      drivers/mdio/mdio_sy1xx.c
  6. 18
      dts/bindings/mdio/sensry,sy1xx-mdio.yaml

1
drivers/mdio/CMakeLists.txt

@ -18,3 +18,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET_QOS mdio_nxp_enet_qos.c) @@ -18,3 +18,4 @@ zephyr_library_sources_ifdef(CONFIG_MDIO_NXP_ENET_QOS mdio_nxp_enet_qos.c)
zephyr_library_sources_ifdef(CONFIG_MDIO_DWCXGMAC mdio_dwcxgmac.c)
zephyr_library_sources_ifdef(CONFIG_MDIO_RENESAS_RA mdio_renesas_ra.c)
zephyr_library_sources_ifdef(CONFIG_MDIO_LAN865X mdio_lan865x.c)
zephyr_library_sources_ifdef(CONFIG_MDIO_SENSRY_SY1XX mdio_sy1xx.c)

1
drivers/mdio/Kconfig

@ -39,6 +39,7 @@ source "drivers/mdio/Kconfig.nxp_enet_qos" @@ -39,6 +39,7 @@ source "drivers/mdio/Kconfig.nxp_enet_qos"
source "drivers/mdio/Kconfig.dwcxgmac"
source "drivers/mdio/Kconfig.renesas_ra"
source "drivers/mdio/Kconfig.lan865x"
source "drivers/mdio/Kconfig.sy1xx"
config MDIO_INIT_PRIORITY
int "Init priority"

10
drivers/mdio/Kconfig.sy1xx

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
# Copyright (c) 2024 sensry.io
# SPDX-License-Identifier: Apache-2.0
config MDIO_SENSRY_SY1XX
bool "Sensry SY1XX MDIO driver"
select PINCTRL
depends on DT_HAS_SENSRY_SY1XX_MDIO_ENABLED
default y
help
Enable Sensry SY1xx SOC Family MDIO driver.

2
drivers/mdio/mdio_shell.c

@ -43,6 +43,8 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL); @@ -43,6 +43,8 @@ LOG_MODULE_REGISTER(mdio_shell, CONFIG_LOG_DEFAULT_LEVEL);
#define DT_DRV_COMPAT st_stm32_mdio
#elif DT_HAS_COMPAT_STATUS_OKAY(snps_dwcxgmac_mdio)
#define DT_DRV_COMPAT snps_dwcxgmac_mdio
#elif DT_HAS_COMPAT_STATUS_OKAY(sensry_sy1xx_mdio)
#define DT_DRV_COMPAT sensry_sy1xx_mdio
#else
#error "No known devicetree compatible match for MDIO shell"
#endif

197
drivers/mdio/mdio_sy1xx.c

@ -0,0 +1,197 @@ @@ -0,0 +1,197 @@
/*
* Copyright (c) 2024 sensry.io
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT sensry_sy1xx_mdio
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sy1xx_mdio, CONFIG_MDIO_LOG_LEVEL);
#include <zephyr/drivers/mdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/pinctrl.h>
#include <udma.h>
struct sy1xx_mdio_dev_config {
const struct pinctrl_dev_config *pcfg;
uint32_t base_addr;
uint32_t mdc_freq;
};
struct sy1xx_mdio_dev_data {
struct k_sem sem;
};
/* mdio register offsets */
#define SY1XX_MDIO_CFG_REG 0x0000
#define SY1XX_MDIO_CTRL_REG 0x0004
#define SY1XX_MDIO_READ_DATA_REG 0x0008
#define SY1XX_MDIO_WRITE_DATA_REG 0x000c
#define SY1XX_MDIO_IRQ_REG 0x0010
/* mdio config register bit offsets */
#define SY1XX_MDIO_CFG_DIV_OFFS (0)
#define SY1XX_MDIO_CFG_EN_OFFS (8)
/* mdio ctrl register bit offsets */
#define SY1XX_MDIO_CTRL_READY_OFFS (0)
#define SY1XX_MDIO_CTRL_INIT_OFFS (8)
#define SY1XX_MDIO_CTRL_REG_ADDR_OFFS (16)
#define SY1XX_MDIO_CTRL_PHY_ADDR_OFFS (24)
#define SY1XX_MDIO_CTRL_OP_OFFS (30)
/* mdio ctrl operations */
#define SY1XX_MDIO_CTRL_OP_WRITE (0x1)
#define SY1XX_MDIO_CTRL_OP_READ (0x2)
#define SY1XX_MDIO_READ_WRITE_WAIT_TIME_US (15)
#define SY1XX_MDIO_READ_WRITE_RETRY_COUNT (5)
static int sy1xx_mdio_wait_for_ready(const struct device *dev);
static int sy1xx_mdio_initialize(const struct device *dev)
{
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
int ret;
uint32_t divider;
uint32_t reg;
/* zero mdio controller regs */
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_CFG_REG);
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_WRITE_DATA_REG);
sys_write32(0x0, cfg->base_addr + SY1XX_MDIO_IRQ_REG);
/* prepare mdio clock and enable mdio controller */
divider = (((sy1xx_soc_get_peripheral_clock() / cfg->mdc_freq) / 2) - 1) & 0xff;
reg = (divider << SY1XX_MDIO_CFG_DIV_OFFS) | BIT(SY1XX_MDIO_CFG_EN_OFFS);
LOG_DBG("config, div: %d, freq: %d", divider, cfg->mdc_freq);
sys_write32(reg, cfg->base_addr + SY1XX_MDIO_CFG_REG);
/* PAD config */
ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
LOG_ERR("failed to configure pins");
return ret;
}
ret = sy1xx_mdio_wait_for_ready(dev);
if (ret < 0) {
LOG_ERR("not ready");
return ret;
}
return 0;
}
static uint32_t sy1xx_mdio_is_ready(const struct device *dev)
{
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
uint32_t status = sys_read32(cfg->base_addr + SY1XX_MDIO_CTRL_REG);
return (status & BIT(SY1XX_MDIO_CTRL_READY_OFFS));
}
static int sy1xx_mdio_wait_for_ready(const struct device *dev)
{
uint32_t retries_left = SY1XX_MDIO_READ_WRITE_RETRY_COUNT;
while (!sy1xx_mdio_is_ready(dev)) {
k_sleep(K_USEC(SY1XX_MDIO_READ_WRITE_WAIT_TIME_US));
retries_left--;
if (!retries_left) {
return -EINVAL;
}
}
return 0;
}
static int sy1xx_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *data)
{
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
int ret;
uint32_t v;
prtad &= 0x1f;
regad &= 0x1f;
v = (SY1XX_MDIO_CTRL_OP_READ << SY1XX_MDIO_CTRL_OP_OFFS) |
(prtad << SY1XX_MDIO_CTRL_PHY_ADDR_OFFS) | (regad << SY1XX_MDIO_CTRL_REG_ADDR_OFFS) |
BIT(SY1XX_MDIO_CTRL_INIT_OFFS);
/* start the reading procedure */
sys_write32(v, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
/* wait for the reading operation to finish */
ret = sy1xx_mdio_wait_for_ready(dev);
if (ret < 0) {
*data = sys_read32(cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
LOG_WRN("timeout while reading from phy: %d, reg: %d, val: %d", prtad, regad,
*data);
return ret;
}
/* get the data from the read result register */
*data = sys_read32(cfg->base_addr + SY1XX_MDIO_READ_DATA_REG);
return 0;
}
static int sy1xx_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t data)
{
struct sy1xx_mdio_dev_config *cfg = (struct sy1xx_mdio_dev_config *)dev->config;
int ret;
uint32_t v;
prtad &= 0x1f;
regad &= 0x1f;
/* put the data to the write register */
sys_write32(data, cfg->base_addr + SY1XX_MDIO_WRITE_DATA_REG);
v = (SY1XX_MDIO_CTRL_OP_WRITE << SY1XX_MDIO_CTRL_OP_OFFS) |
(prtad << SY1XX_MDIO_CTRL_PHY_ADDR_OFFS) | (regad << SY1XX_MDIO_CTRL_REG_ADDR_OFFS) |
BIT(SY1XX_MDIO_CTRL_INIT_OFFS);
/* start the writing procedure */
sys_write32(v, cfg->base_addr + SY1XX_MDIO_CTRL_REG);
/* wait for the writing operation to finish */
ret = sy1xx_mdio_wait_for_ready(dev);
if (ret < 0) {
LOG_WRN("timeout while writing to phy: %d, reg: %d, val: %d", prtad, regad, data);
return ret;
}
return 0;
}
static DEVICE_API(mdio, sy1xx_mdio_driver_api) = {
.read = sy1xx_mdio_read,
.write = sy1xx_mdio_write,
};
#define SY1XX_MDIO_INIT(n) \
\
PINCTRL_DT_INST_DEFINE(n); \
\
static const struct sy1xx_mdio_dev_config sy1xx_mdio_dev_config_##n = { \
.base_addr = DT_INST_REG_ADDR(n), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.mdc_freq = DT_INST_PROP(n, clock_frequency), \
}; \
\
static struct sy1xx_mdio_dev_data sy1xx_mdio_dev_data##n; \
\
DEVICE_DT_INST_DEFINE(n, &sy1xx_mdio_initialize, NULL, &sy1xx_mdio_dev_data##n, \
&sy1xx_mdio_dev_config_##n, POST_KERNEL, CONFIG_MDIO_INIT_PRIORITY, \
&sy1xx_mdio_driver_api);
DT_INST_FOREACH_STATUS_OKAY(SY1XX_MDIO_INIT)

18
dts/bindings/mdio/sensry,sy1xx-mdio.yaml

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
# Copyright (c) 2024 sensry.io
# SPDX-License-Identifier: Apache-2.0
description: Sensry SY1XX MDIO Driver node
compatible: "sensry,sy1xx-mdio"
include: [base.yaml, mdio-controller.yaml, pinctrl-device.yaml]
properties:
reg:
required: true
pinctrl-0:
required: true
pinctrl-names:
required: true
Loading…
Cancel
Save