Skip to content

Commit

Permalink
drivers: ethernet: w5500: Add support for WIZ550io module
Browse files Browse the repository at this point in the history
WIZ550io is a W5500 breakout board with an extra PIC12F519 MCU.
The PIC12F519 MCU initialises the W5500 with a unique MAC address
after a GPIO reset. The PIC12F519 requires a 150ms delay after GPIO
reset to configure the W5500. There is an optional "ready" GPIO
signal that can be used to reduce that delay.

Add "wiznet,wiz550io" DT_COMPAT as a specialization of the W5500
Ethernet controller. This enables support for delay after GPIO
reset, "ready" GPIO signal and using the WIZ550io preconfigured
MAC address.

Signed-off-by: Grant Ramsay <gramsay@enphaseenergy.com>
  • Loading branch information
gramsay0 committed Mar 3, 2024
1 parent aef6588 commit 4bf0643
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 1 deletion.
79 changes: 78 additions & 1 deletion drivers/ethernet/eth_w5500.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#define DT_DRV_COMPAT wiznet_w5500

/* WIZ550io extension compatible */
#define WIZ550IO_DRV_COMPAT wiznet_wiz550io

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(eth_w5500, CONFIG_ETHERNET_LOG_LEVEL);

Expand All @@ -34,6 +37,16 @@ LOG_MODULE_REGISTER(eth_w5500, CONFIG_ETHERNET_LOG_LEVEL);
#define W5500_SPI_WRITE_CONTROL(addr) \
((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2))

/* W5500 datasheet recommends 1ms delay after hardware reset for
* internal PLL to stabilize.
*/
#define W5500_RESET_DELAY_MS 1

/* WIZ550io documentation recommends 150ms delay after HW reset
* for PIC12F519 MCU to configure the W5500.
*/
#define WIZ550IO_RESET_DELAY_MS 150

static int w5500_spi_read(const struct device *dev, uint32_t addr,
uint8_t *data, uint32_t len)
{
Expand Down Expand Up @@ -579,10 +592,55 @@ static int w5500_init(const struct device *dev)
LOG_ERR("Unable to configure GPIO pin %u", config->reset.pin);
return -EINVAL;
}
gpio_pin_set_dt(&config->reset, 0);
gpio_pin_set_dt(&config->reset, 1);
k_usleep(500);
gpio_pin_set_dt(&config->reset, 0);

#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(ready_gpios)
if (config->ready.port) {
if (!gpio_is_ready_dt(&config->ready)) {
LOG_ERR("GPIO port %s not ready", config->ready.port->name);
return -EINVAL;
}
if (gpio_pin_configure_dt(&config->ready, GPIO_INPUT)) {
LOG_ERR("Unable to configure GPIO pin %u", config->ready.pin);
return -EINVAL;
}

k_timepoint_t timeout = sys_timepoint_calc(
K_MSEC(config->hw_reset_delay));

while (!gpio_pin_get_dt(&config->ready)) {
if (sys_timepoint_expired(timeout)) {
LOG_ERR("W5500 not ready");
return -ETIMEDOUT;
}
k_msleep(1);
}
} else
#endif
{
k_msleep(config->hw_reset_delay);
}
}

#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(preconfigured_mac_address)
/* WIZ550io module has a preconfigured unique MAC address
* assigned by the PIC12F519 after hardware reset. It needs to
* be read out after a hardware reset and before software reset.
*/
if (config->preconfigured_mac_address) {
err = w5500_spi_read(dev, W5500_SHAR, ctx->mac_addr, sizeof(ctx->mac_addr));
if (err ||
ctx->mac_addr[0] != WIZNET_OUI_B0 ||
ctx->mac_addr[1] != WIZNET_OUI_B1 ||
ctx->mac_addr[2] != WIZNET_OUI_B2) {
LOG_ERR("Unable to read preconfigured MAC address");
return -EIO;
}
}
#endif

err = w5500_hw_reset(dev);
if (err) {
LOG_ERR("Reset failed");
Expand Down Expand Up @@ -622,11 +680,30 @@ static struct w5500_runtime w5500_0_runtime = {
0, UINT_MAX),
};

#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(ready_gpios)
#define W5500_READY_GPIO_INIT(inst) \
.ready = GPIO_DT_SPEC_INST_GET_OR(inst, ready_gpios, { 0 }),
#else
#define W5500_READY_GPIO_INIT(inst)
#endif

#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(preconfigured_mac_address)
#define W5500_PRECONFIGURED_MAC_ADDRESS_INIT(inst) \
.preconfigured_mac_address = DT_INST_PROP(inst, preconfigured_mac_address),
#else
#define W5500_PRECONFIGURED_MAC_ADDRESS_INIT(inst)
#endif

static const struct w5500_config w5500_0_config = {
.spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), 0),
.interrupt = GPIO_DT_SPEC_INST_GET(0, int_gpios),
.reset = GPIO_DT_SPEC_INST_GET_OR(0, reset_gpios, { 0 }),
.timeout = CONFIG_ETH_W5500_TIMEOUT,
.hw_reset_delay = COND_CODE_1(
DT_NODE_HAS_COMPAT(DT_DRV_INST(0), WIZ550IO_DRV_COMPAT),
(WIZ550IO_RESET_DELAY_MS), (W5500_RESET_DELAY_MS)),
W5500_READY_GPIO_INIT(0)
W5500_PRECONFIGURED_MAC_ADDRESS_INIT(0)
};

ETH_NET_DEVICE_DT_INST_DEFINE(0,
Expand Down
7 changes: 7 additions & 0 deletions drivers/ethernet/eth_w5500_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ struct w5500_config {
void (*config_func)(void);
uint8_t full_duplex;
int32_t timeout;
int32_t hw_reset_delay;
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(ready_gpios)
struct gpio_dt_spec ready;
#endif
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(preconfigured_mac_address)
bool preconfigured_mac_address;
#endif
};

struct w5500_runtime {
Expand Down
48 changes: 48 additions & 0 deletions dts/bindings/ethernet/wiznet,wiz550io.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright (c) 2024 Enphase Energy
# SPDX-License-Identifier: Apache-2.0

description: |
WIZ550io standalone 10/100BASE-T Ethernet controller with SPI interface
and preconfigured unique MAC address.
This is a specialization of the W5500 Ethernet controller.
Example:
&spi3 {
status = "okay";
pinctrl-0 = <&spi3_sck_pb3 &spi3_miso_pb4 &spi3_mosi_pb5>;
pinctrl-names = "default";
cs-gpios = <&gpioa 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
eth_w5500: eth_w5500@0 {
status = "okay";
compatible = "wiznet,wiz550io", "wiznet,w5500";
reg = <0x0>;
spi-max-frequency = <DT_FREQ_M(80)>;
int-gpios = <&gpioa 6 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpioa 5 GPIO_ACTIVE_LOW>;
ready-gpios = <&gpiod 14 GPIO_ACTIVE_HIGH>;
preconfigured-mac-address;
};
};
compatible: "wiznet,wiz550io"

include: wiznet,w5500.yaml

properties:
ready-gpios:
type: phandle-array
description: |
Ready pin.
The WIZ550io module has an extra GPIO pin that signals
when the PIC12F519 has finished configuring the W5500.
This is optional to shorten the hardware reset delay.
preconfigured-mac-address:
type: boolean
description: |
Preconfigured W5500 MAC address.
The WIZ550io module has a preconfigured unique MAC address
assigned by the PIC12F519 after hardware reset.
This functionality depends on having a reset GPIO.
Enable this option to use that MAC address.

0 comments on commit 4bf0643

Please sign in to comment.