drivers: net: phy: Add tja11xx driver
Adds the c22 tja11xx driver. Signed-off-by: Kevin Shaju <kevin.shaju@accenture.com>
This commit is contained in:
parent
67edf2292a
commit
7e56d134c2
6 changed files with 309 additions and 1 deletions
|
@ -13,5 +13,6 @@ zephyr_library_sources_ifdef(CONFIG_PHY_QUALCOMM_AR8031 phy_qualcomm_ar8031.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_PHY_REALTEK_RTL8211F phy_realtek_rtl8211f.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_TI_DP83825 phy_ti_dp83825.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_TI_DP83867 phy_ti_dp83867.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_TJA1103 phy_tja1103.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_TJA1103 phy_tja1103.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_TJA11XX phy_tja11xx.c)
|
||||
# zephyr-keep-sorted-stop
|
||||
|
|
|
@ -14,6 +14,7 @@ module-dep = LOG
|
|||
module-str = Log level for Ethernet PHY driver
|
||||
module-help = Sets log level for Ethernet PHY Device Drivers.
|
||||
source "subsys/net/Kconfig.template.log_config.net"
|
||||
source "drivers/ethernet/phy/Kconfig.tja11xx"
|
||||
source "drivers/ethernet/phy/Kconfig.tja1103"
|
||||
source "drivers/ethernet/phy/Kconfig.dm8806"
|
||||
source "drivers/ethernet/phy/Kconfig.microchip_t1s"
|
||||
|
|
12
drivers/ethernet/phy/Kconfig.tja11xx
Normal file
12
drivers/ethernet/phy/Kconfig.tja11xx
Normal file
|
@ -0,0 +1,12 @@
|
|||
# NXP PHY TJA11xx driver configuration options
|
||||
|
||||
# Copyright 2024 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config PHY_TJA11XX
|
||||
bool "TJA11XX PHY driver"
|
||||
default y
|
||||
depends on DT_HAS_NXP_TJA11XX_ENABLED
|
||||
depends on MDIO
|
||||
help
|
||||
Enable TJA11xx PHY driver.
|
254
drivers/ethernet/phy/phy_tja11xx.c
Normal file
254
drivers/ethernet/phy/phy_tja11xx.c
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright 2023 NXP
|
||||
* Copyright 2023 CogniPilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nxp_tja11xx
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/net/phy.h>
|
||||
#include <zephyr/net/mii.h>
|
||||
#include <zephyr/net/mdio.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/mdio.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(phy_tja11xx, CONFIG_PHY_LOG_LEVEL);
|
||||
|
||||
/* Extended control register */
|
||||
#define TJA11XX_EXTENDED_CONTROL 0x0017U
|
||||
/* Configuration register 1 */
|
||||
#define TJA11XX_CONFIGURATION_1 0x0018U
|
||||
|
||||
struct phy_tja11xx_config {
|
||||
const struct device *mdio;
|
||||
uint8_t phy_addr;
|
||||
};
|
||||
|
||||
struct phy_tja11xx_data {
|
||||
const struct device *dev;
|
||||
struct phy_link_state state;
|
||||
struct k_sem sem;
|
||||
phy_callback_t cb;
|
||||
void *cb_data;
|
||||
|
||||
struct k_work_delayable monitor_work;
|
||||
};
|
||||
|
||||
static inline int phy_tja11xx_c22_read(const struct device *dev, uint16_t reg, uint16_t *val)
|
||||
{
|
||||
const struct phy_tja11xx_config *const cfg = dev->config;
|
||||
|
||||
return mdio_read(cfg->mdio, cfg->phy_addr, reg, val);
|
||||
}
|
||||
|
||||
static inline int phy_tja11xx_c22_write(const struct device *dev, uint16_t reg, uint16_t val)
|
||||
{
|
||||
const struct phy_tja11xx_config *const cfg = dev->config;
|
||||
|
||||
return mdio_write(cfg->mdio, cfg->phy_addr, reg, val);
|
||||
}
|
||||
|
||||
static int phy_tja11xx_reg_read(const struct device *dev, uint16_t reg_addr, uint32_t *data)
|
||||
{
|
||||
const struct phy_tja11xx_config *cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
mdio_bus_enable(cfg->mdio);
|
||||
|
||||
ret = phy_tja11xx_c22_read(dev, reg_addr, (uint16_t *)data);
|
||||
|
||||
mdio_bus_disable(cfg->mdio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int phy_tja11xx_reg_write(const struct device *dev, uint16_t reg_addr, uint32_t data)
|
||||
{
|
||||
const struct phy_tja11xx_config *cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
mdio_bus_enable(cfg->mdio);
|
||||
|
||||
ret = phy_tja11xx_c22_write(dev, reg_addr, (uint16_t)data);
|
||||
|
||||
mdio_bus_disable(cfg->mdio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int update_link_state(const struct device *dev)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
bool link_up;
|
||||
uint16_t val;
|
||||
|
||||
if (phy_tja11xx_c22_read(dev, MII_BMSR, &val) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
link_up = (val & MII_BMSR_LINK_STATUS) != 0;
|
||||
|
||||
/* Let workqueue re-schedule and re-check if the
|
||||
* link status is unchanged this time
|
||||
*/
|
||||
if (data->state.is_up == link_up) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
data->state.is_up = link_up;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int phy_tja11xx_get_link_state(const struct device *dev, struct phy_link_state *state)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
int rc = 0;
|
||||
|
||||
k_sem_take(&data->sem, K_FOREVER);
|
||||
|
||||
memcpy(state, &data->state, sizeof(struct phy_link_state));
|
||||
|
||||
k_sem_give(&data->sem);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void invoke_link_cb(const struct device *dev)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
struct phy_link_state state;
|
||||
|
||||
if (data->cb == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send callback only on link state change */
|
||||
if (phy_tja11xx_get_link_state(dev, &state) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
data->cb(dev, &state, data->cb_data);
|
||||
}
|
||||
|
||||
static void monitor_work_handler(struct k_work *work)
|
||||
{
|
||||
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
|
||||
struct phy_tja11xx_data *const data =
|
||||
CONTAINER_OF(dwork, struct phy_tja11xx_data, monitor_work);
|
||||
const struct device *dev = data->dev;
|
||||
int rc;
|
||||
|
||||
k_sem_take(&data->sem, K_FOREVER);
|
||||
|
||||
rc = update_link_state(dev);
|
||||
|
||||
k_sem_give(&data->sem);
|
||||
|
||||
/* If link state has changed and a callback is set, invoke callback */
|
||||
if (rc == 0) {
|
||||
invoke_link_cb(dev);
|
||||
}
|
||||
|
||||
/* Submit delayed work */
|
||||
k_work_reschedule(&data->monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD));
|
||||
}
|
||||
|
||||
static void phy_tja11xx_cfg_irq_poll(const struct device *dev)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
|
||||
k_work_init_delayable(&data->monitor_work, monitor_work_handler);
|
||||
|
||||
monitor_work_handler(&data->monitor_work.work);
|
||||
}
|
||||
|
||||
static int phy_tja11xx_cfg_link(const struct device *dev, enum phy_link_speed adv_speeds)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
if (adv_speeds & LINK_FULL_100BASE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int phy_tja11xx_init(const struct device *dev)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
int ret;
|
||||
|
||||
data->dev = dev;
|
||||
data->cb = NULL;
|
||||
data->state.is_up = false;
|
||||
data->state.speed = LINK_FULL_100BASE;
|
||||
|
||||
ret = phy_tja11xx_reg_write(dev, TJA11XX_EXTENDED_CONTROL, 0x1804);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = phy_tja11xx_reg_write(dev, MII_BMCR, 0x2100);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = phy_tja11xx_reg_write(dev, TJA11XX_CONFIGURATION_1, 0x8A00);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = phy_tja11xx_reg_write(dev, TJA11XX_EXTENDED_CONTROL, 0x9804);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
phy_tja11xx_cfg_irq_poll(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int phy_tja11xx_link_cb_set(const struct device *dev, phy_callback_t cb, void *user_data)
|
||||
{
|
||||
struct phy_tja11xx_data *const data = dev->data;
|
||||
|
||||
data->cb = cb;
|
||||
data->cb_data = user_data;
|
||||
|
||||
/* Invoke the callback to notify the caller of the current
|
||||
* link status.
|
||||
*/
|
||||
invoke_link_cb(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethphy_driver_api phy_tja11xx_api = {
|
||||
.get_link = phy_tja11xx_get_link_state,
|
||||
.cfg_link = phy_tja11xx_cfg_link,
|
||||
.link_cb_set = phy_tja11xx_link_cb_set,
|
||||
.read = phy_tja11xx_reg_read,
|
||||
.write = phy_tja11xx_reg_write,
|
||||
};
|
||||
|
||||
#define TJA11xx_INITIALIZE(n) \
|
||||
static const struct phy_tja11xx_config phy_tja11xx_config_##n = { \
|
||||
.phy_addr = DT_INST_REG_ADDR(n), \
|
||||
.mdio = DEVICE_DT_GET(DT_INST_BUS(n)) \
|
||||
}; \
|
||||
static struct phy_tja11xx_data phy_tja11xx_data_##n = { \
|
||||
.sem = Z_SEM_INITIALIZER(phy_tja11xx_data_##n.sem, 1, 1), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, &phy_tja11xx_init, NULL, &phy_tja11xx_data_##n, \
|
||||
&phy_tja11xx_config_##n, POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \
|
||||
&phy_tja11xx_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(TJA11xx_INITIALIZE)
|
|
@ -30,6 +30,33 @@
|
|||
compatible = "mmio-sram";
|
||||
reg = <0x20000000 DT_SIZE_K(124)>;
|
||||
};
|
||||
|
||||
enet: ethernet@40079000 {
|
||||
compatible = "nxp,enet";
|
||||
reg = <0x40079000 0x628>;
|
||||
clocks = <&clock NXP_S32_ENET_CLK>;
|
||||
|
||||
enet_mac: ethernet {
|
||||
compatible = "nxp,enet-mac";
|
||||
interrupts = <73 0>, <74 0>, <75 0>;
|
||||
interrupt-names = "TX", "RX", "ERR";
|
||||
nxp,mdio = <&enet_mdio>;
|
||||
nxp,ptp-clock = <&enet_ptp_clock>;
|
||||
phy-connection-type = "rmii";
|
||||
};
|
||||
|
||||
enet_mdio: mdio {
|
||||
compatible = "nxp,enet-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
enet_ptp_clock: ptp_clock {
|
||||
compatible = "nxp,enet-ptp-clock";
|
||||
interrupts = <72 0>;
|
||||
clocks = <&clock NXP_S32_ENET_CLK>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
13
dts/bindings/ethernet/nxp,tja11xx.yaml
Normal file
13
dts/bindings/ethernet/nxp,tja11xx.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: TJA11xx PHY
|
||||
|
||||
compatible: "nxp,tja11xx"
|
||||
|
||||
include: phy.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
description: PHY address
|
Loading…
Add table
Add a link
Reference in a new issue