Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions boards/arm/ip_k66f/Kconfig.defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ config ETH_MCUX_0
config ETH_MCUX_RMII_EXT_CLK
default y if ETH_MCUX

config ETH_MCUX_NO_PHY_SMI
default y if ETH_MCUX

endif # NETWORKING

if PINMUX_MCUX
Expand Down
5 changes: 5 additions & 0 deletions boards/arm/ip_k66f/ip_k66f.dts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@

&enet {
status = "okay";

fixed-link {
speed = <100>;
full-duplex;
};
};

&spi1 {
Expand Down
7 changes: 7 additions & 0 deletions drivers/ethernet/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ config ETH_MCUX_RMII_EXT_CLK
Setting this option will configure MCUX clock block to feed RMII
reference clock from external source (ENET_1588_CLKIN)

config ETH_MCUX_NO_PHY_SMI
bool "Do not use SMI for PHY communication"
help
Some PHY devices, with DSA capabilities do not use SMI for
communication with MAC ENET controller. Other busses - like SPI
or I2C are used instead.

config ETH_MCUX_PHY_TICK_MS
int "PHY poll period (ms)"
default 1000
Expand Down
88 changes: 88 additions & 0 deletions drivers/ethernet/eth_mcux.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,23 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include "fsl_clock.h"
#include <drivers/clock_control.h>
#endif
#include <devicetree.h>

#include "eth.h"

#define FREESCALE_OUI_B0 0x00
#define FREESCALE_OUI_B1 0x04
#define FREESCALE_OUI_B2 0x9f

#define ETH_MCUX_FIXED_LINK_NODE \
DT_CHILD(DT_ALIAS(eth), fixed_link)
#define ETH_MCUX_FIXED_LINK \
DT_NODE_EXISTS(ETH_MCUX_FIXED_LINK_NODE)
#define ETH_MCUX_FIXED_LINK_SPEED \
DT_PROP(ETH_MCUX_FIXED_LINK_NODE, speed)
#define ETH_MCUX_FIXED_LINK_FULL_DUPLEX \
DT_PROP(ETH_MCUX_FIXED_LINK_NODE, full_duplex)

enum eth_mcux_phy_state {
eth_mcux_phy_state_initial,
eth_mcux_phy_state_reset,
Expand Down Expand Up @@ -242,6 +252,22 @@ static int eth_mcux_device_pm_control(struct device *dev, uint32_t command,
#define ETH_MCUX_PM_FUNC device_pm_control_nop
#endif /* CONFIG_NET_POWER_MANAGEMENT */

#if ETH_MCUX_FIXED_LINK
static void eth_mcux_get_phy_params(phy_duplex_t *p_phy_duplex,
phy_speed_t *p_phy_speed)
{
*p_phy_duplex = kPHY_HalfDuplex;
#if ETH_MCUX_FIXED_LINK_FULL_DUPLEX
*p_phy_duplex = kPHY_FullDuplex;
#endif

*p_phy_speed = kPHY_Speed10M;
#if ETH_MCUX_FIXED_LINK_SPEED == 100
*p_phy_speed = kPHY_Speed100M;
#endif
}
#else

static void eth_mcux_decode_duplex_and_speed(uint32_t status,
phy_duplex_t *p_phy_duplex,
phy_speed_t *p_phy_speed)
Expand All @@ -265,6 +291,7 @@ static void eth_mcux_decode_duplex_and_speed(uint32_t status,
break;
}
}
#endif /* ETH_MCUX_FIXED_LINK */

static inline struct net_if *get_iface(struct eth_context *ctx, uint16_t vlan_tag)
{
Expand All @@ -287,11 +314,16 @@ static inline struct net_if *get_iface(struct eth_context *ctx, uint16_t vlan_ta
static void eth_mcux_phy_enter_reset(struct eth_context *context)
{
/* Reset the PHY. */
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_BASICCONTROL_REG,
kENET_MiiWriteValidFrame,
PHY_BCTL_RESET_MASK);
#endif
context->phy_state = eth_mcux_phy_state_reset;
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
k_work_submit(&context->phy_work);
#endif
}

static void eth_mcux_phy_start(struct eth_context *context)
Expand All @@ -307,10 +339,19 @@ static void eth_mcux_phy_start(struct eth_context *context)
case eth_mcux_phy_state_initial:
ENET_ActiveRead(context->base);
/* Reset the PHY. */
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_BASICCONTROL_REG,
kENET_MiiWriteValidFrame,
PHY_BCTL_RESET_MASK);
#else
/*
* With no SMI communication one needs to wait for
* iface being up by the network core.
*/
k_work_submit(&context->phy_work);
break;
#endif
#ifdef CONFIG_SOC_SERIES_IMX_RT
context->phy_state = eth_mcux_phy_state_initial;
#else
Expand Down Expand Up @@ -364,7 +405,9 @@ void eth_mcux_phy_stop(struct eth_context *context)

static void eth_mcux_phy_event(struct eth_context *context)
{
#if !(defined(CONFIG_ETH_MCUX_NO_PHY_SMI) && ETH_MCUX_FIXED_LINK)
uint32_t status;
#endif
bool link_up;
#ifdef CONFIG_SOC_SERIES_IMX_RT
status_t res;
Expand Down Expand Up @@ -395,6 +438,18 @@ static void eth_mcux_phy_event(struct eth_context *context)
ctrl2);
}
context->phy_state = eth_mcux_phy_state_reset;
#endif
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
/*
* When the iface is available proceed with the eth link setup,
* otherwise reschedule the eth_mcux_phy_event and check after
* 1ms
*/
if (context->iface) {
context->phy_state = eth_mcux_phy_state_reset;
}

k_delayed_work_submit(&context->delayed_phy_work, K_MSEC(1));
#endif
break;
case eth_mcux_phy_state_closing:
Expand All @@ -407,41 +462,62 @@ static void eth_mcux_phy_event(struct eth_context *context)
break;
case eth_mcux_phy_state_reset:
/* Setup PHY autonegotiation. */
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_AUTONEG_ADVERTISE_REG,
kENET_MiiWriteValidFrame,
(PHY_100BASETX_FULLDUPLEX_MASK |
PHY_100BASETX_HALFDUPLEX_MASK |
PHY_10BASETX_FULLDUPLEX_MASK |
PHY_10BASETX_HALFDUPLEX_MASK | 0x1U));
#endif
context->phy_state = eth_mcux_phy_state_autoneg;
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
k_work_submit(&context->phy_work);
#endif
break;
case eth_mcux_phy_state_autoneg:
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
/* Setup PHY autonegotiation. */
ENET_StartSMIWrite(context->base, context->phy_addr,
PHY_BASICCONTROL_REG,
kENET_MiiWriteValidFrame,
(PHY_BCTL_AUTONEG_MASK |
PHY_BCTL_RESTART_AUTONEG_MASK));
#endif
context->phy_state = eth_mcux_phy_state_restart;
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
k_work_submit(&context->phy_work);
#endif
break;
case eth_mcux_phy_state_wait:
case eth_mcux_phy_state_restart:
/* Start reading the PHY basic status. */
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_StartSMIRead(context->base, context->phy_addr,
PHY_BASICSTATUS_REG,
kENET_MiiReadValidFrame);
#endif
context->phy_state = eth_mcux_phy_state_read_status;
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
k_work_submit(&context->phy_work);
#endif
break;
case eth_mcux_phy_state_read_status:
/* PHY Basic status is available. */
#if defined(CONFIG_ETH_MCUX_NO_PHY_SMI) && ETH_MCUX_FIXED_LINK
link_up = true;
#else
status = ENET_ReadSMIData(context->base);
link_up = status & PHY_BSTATUS_LINKSTATUS_MASK;
#endif
if (link_up && !context->link_up) {
/* Start reading the PHY control register. */
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_StartSMIRead(context->base, context->phy_addr,
PHY_CONTROL1_REG,
kENET_MiiReadValidFrame);
#endif
context->link_up = link_up;
context->phy_state = eth_mcux_phy_state_read_duplex;

Expand All @@ -450,6 +526,9 @@ static void eth_mcux_phy_event(struct eth_context *context)
net_eth_carrier_on(context->iface);
k_msleep(USEC_PER_MSEC);
}
#ifdef CONFIG_ETH_MCUX_NO_PHY_SMI
k_work_submit(&context->phy_work);
#endif
} else if (!link_up && context->link_up) {
LOG_INF("%s link down", eth_name(context->base));
context->link_up = link_up;
Expand All @@ -466,10 +545,15 @@ static void eth_mcux_phy_event(struct eth_context *context)
break;
case eth_mcux_phy_state_read_duplex:
/* PHY control register is available. */
#if defined(CONFIG_ETH_MCUX_NO_PHY_SMI) && ETH_MCUX_FIXED_LINK
eth_mcux_get_phy_params(&phy_duplex, &phy_speed);
LOG_INF("%s - Fixed Link", eth_name(context->base));
#else
status = ENET_ReadSMIData(context->base);
eth_mcux_decode_duplex_and_speed(status,
&phy_duplex,
&phy_speed);
#endif
if (phy_speed != context->phy_speed ||
phy_duplex != context->phy_duplex) {
context->phy_speed = phy_speed;
Expand Down Expand Up @@ -946,7 +1030,9 @@ static void eth_mcux_init(struct device *dev)
ENET_GetDefaultConfig(&enet_config);
enet_config.interrupt |= kENET_RxFrameInterrupt;
enet_config.interrupt |= kENET_TxFrameInterrupt;
#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
enet_config.interrupt |= kENET_MiiInterrupt;
#endif

if (IS_ENABLED(CONFIG_ETH_MCUX_PROMISCUOUS_MODE)) {
enet_config.macSpecialConfig |= kENET_ControlPromiscuousEnable;
Expand Down Expand Up @@ -993,7 +1079,9 @@ static void eth_mcux_init(struct device *dev)
ENET_AddMulticastGroup(context->base, mdns_multicast);
#endif

#ifndef CONFIG_ETH_MCUX_NO_PHY_SMI
ENET_SetSMI(context->base, sys_clock, false);
#endif

/* handle PHY setup after SMI initialization */
eth_mcux_phy_setup(context);
Expand Down
18 changes: 18 additions & 0 deletions dts/bindings/ethernet/ethernet,fixed-link.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2020, DENX Software Engineering GmbH
# Lukasz Majewski <[email protected]>
# SPDX-License-Identifier: Apache-2.0

child-binding:
description: Fixed link ethernet node
properties:
speed:
type: int
required: true
description: The speed of fixed link
enum:
- 100
- 10
full-duplex:
type: boolean
required: false
description: The fixed link operates in full duplex mode
2 changes: 1 addition & 1 deletion dts/bindings/ethernet/nxp,kinetis-ethernet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: NXP Kinetis Ethernet

compatible: "nxp,kinetis-ethernet"

include: ethernet.yaml
include: ["ethernet.yaml", "ethernet,fixed-link.yaml"]

properties:
reg:
Expand Down