Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate KSZ8863 driver to new I2C driver implementation #46

Merged
merged 1 commit into from
Jan 10, 2025
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
4 changes: 3 additions & 1 deletion ksz8863/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ The figure below shows data path when KSZ8863 is used in this Port Mode. The con

## KSZ8863 Configuration & Control interface

KSZ8863 can be managed via either I2C or SPI bus.
KSZ8863 can be managed via either I2C or SPI bus. SMI is not supported.

SMI used in KSZ8863 is a non-standard implementation of IEEE 802.3 MII management interface (MIIM). The core differences are the unusual addressing method used to get access to the full set of KSZ8863's registers and opcode numbering (MIIM sends opcode `0b10` to read and `0b01` to write, SMI expects `0b00` for both). It is impossible for ESP32 to produce opcode `0b00` by design, since it follows IEEE 802.3 MII management interface specification.

### KSZ8863 Control and Configuration

Expand Down
38 changes: 15 additions & 23 deletions ksz8863/examples/simple_switch/main/simple_switch_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
esp_err_t ret;
/* we can get the ethernet driver handle from event data */
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
/* we should not try to use KSZ8863-specific ioctl commands with the general host handle, only with port handles */
esp_eth_handle_t host_eth_handle = *(esp_eth_handle_t *)arg;

switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Up Port %" PRIi32, port_num + 1);
} else {
Expand All @@ -146,7 +148,7 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Down Port %" PRIi32, port_num + 1);
} else {
Expand Down Expand Up @@ -179,37 +181,27 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
ESP_LOGI(TAG, "~~~~~~~~~~~");
}

esp_err_t i2c_init(i2c_port_t i2c_master_port, i2c_config_t *i2c_conf)
{
esp_err_t ret;

ESP_GOTO_ON_ERROR(i2c_param_config(i2c_master_port, i2c_conf), err, TAG, "I2C parameters configuration failed");
ESP_GOTO_ON_ERROR(i2c_driver_install(i2c_master_port, i2c_conf->mode, 0, 0, 0), err, TAG, "I2C driver install failed");

return ESP_OK;
err:
return ret;
}

// board specific initialization routine, user to update per specific needs
esp_err_t ksz8863_board_specific_init(esp_eth_handle_t eth_handle)
{
esp_err_t ret = ESP_OK;

#if CONFIG_EXAMPLE_CTRL_I2C
// initialize I2C interface
i2c_config_t i2c_bus_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_io_num = CONFIG_EXAMPLE_I2C_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
.glitch_ignore_cnt = 7,
};
ESP_GOTO_ON_ERROR(i2c_init(CONFIG_EXAMPLE_I2C_MASTER_PORT, &i2c_bus_config), err, TAG, "I2C initialization failed");
i2c_master_bus_handle_t bus_handle;
ESP_GOTO_ON_ERROR(i2c_new_master_bus(&i2c_mst_config, &bus_handle), err, TAG, "I2C initialization failed");
ksz8863_ctrl_i2c_config_t i2c_dev_config = {
.bus_handle = bus_handle,
.dev_addr = KSZ8863_I2C_DEV_ADDR,
.i2c_master_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000
};
ksz8863_ctrl_intf_config_t ctrl_intf_cfg = {
.host_mode = KSZ8863_I2C_MODE,
Expand Down Expand Up @@ -318,7 +310,7 @@ void app_main(void)
ESP_ERROR_CHECK(esp_eth_driver_install(&p2_config, &p2_eth_handle));

// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, &host_eth_handle));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));

// start Ethernet driver state machines
Expand Down
38 changes: 15 additions & 23 deletions ksz8863/examples/switch_mode/main/switch_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,13 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
esp_err_t ret;
/* we can get the ethernet driver handle from event data */
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
/* we should not try to use KSZ8863-specific ioctl commands with the general host handle, only with port handles */
esp_eth_handle_t host_eth_handle = *(esp_eth_handle_t *)arg;

switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Up Port %" PRIi32, port_num + 1);
} else {
Expand All @@ -185,7 +187,7 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Down Port %" PRIi32, port_num + 1);
} else {
Expand Down Expand Up @@ -218,37 +220,27 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
ESP_LOGI(TAG, "~~~~~~~~~~~");
}

esp_err_t i2c_init(i2c_port_t i2c_master_port, i2c_config_t *i2c_conf)
{
esp_err_t ret;

ESP_GOTO_ON_ERROR(i2c_param_config(i2c_master_port, i2c_conf), err, TAG, "I2C parameters configuration failed");
ESP_GOTO_ON_ERROR(i2c_driver_install(i2c_master_port, i2c_conf->mode, 0, 0, 0), err, TAG, "I2C driver install failed");

return ESP_OK;
err:
return ret;
}

// board specific initialization routine, user to update per specific needs
esp_err_t ksz8863_board_specific_init(esp_eth_handle_t eth_handle)
{
esp_err_t ret = ESP_OK;

#if CONFIG_EXAMPLE_CTRL_I2C
// initialize I2C interface
i2c_config_t i2c_bus_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_io_num = CONFIG_EXAMPLE_I2C_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
.glitch_ignore_cnt = 7,
};
ESP_GOTO_ON_ERROR(i2c_init(CONFIG_EXAMPLE_I2C_MASTER_PORT, &i2c_bus_config), err, TAG, "I2C initialization failed");
i2c_master_bus_handle_t bus_handle;
ESP_GOTO_ON_ERROR(i2c_new_master_bus(&i2c_mst_config, &bus_handle), err, TAG, "I2C initialization failed");
ksz8863_ctrl_i2c_config_t i2c_dev_config = {
.bus_handle = bus_handle,
.dev_addr = KSZ8863_I2C_DEV_ADDR,
.i2c_master_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000
};
ksz8863_ctrl_intf_config_t ctrl_intf_cfg = {
.host_mode = KSZ8863_I2C_MODE,
Expand Down Expand Up @@ -371,7 +363,7 @@ void app_main(void)
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, ksz8863_esp_eth_new_netif_glue_switch(&sw_netif_glue_cfg)));

// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, &host_eth_handle));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));

// start Ethernet driver state machines
Expand Down
38 changes: 15 additions & 23 deletions ksz8863/examples/two_ports_mode/main/two_ports_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,13 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
esp_err_t ret;
/* we can get the ethernet driver handle from event data */
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
/* we should not try to use KSZ8863-specific ioctl commands with the general host handle, only with port handles */
esp_eth_handle_t host_eth_handle = *(esp_eth_handle_t *)arg;

switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Up Port %" PRIi32, port_num + 1);
} else {
Expand All @@ -178,7 +180,7 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
break;
case ETHERNET_EVENT_DISCONNECTED:
ret = esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num);
ret = eth_handle != host_eth_handle ? esp_eth_ioctl(eth_handle, KSZ8863_ETH_CMD_G_PORT_NUM, &port_num) : ESP_FAIL;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Ethernet Link Down Port %" PRIi32, port_num + 1);
} else {
Expand Down Expand Up @@ -211,37 +213,27 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
ESP_LOGI(TAG, "~~~~~~~~~~~");
}

esp_err_t i2c_init(i2c_port_t i2c_master_port, i2c_config_t *i2c_conf)
{
esp_err_t ret;

ESP_GOTO_ON_ERROR(i2c_param_config(i2c_master_port, i2c_conf), err, TAG, "I2C parameters configuration failed");
ESP_GOTO_ON_ERROR(i2c_driver_install(i2c_master_port, i2c_conf->mode, 0, 0, 0), err, TAG, "I2C driver install failed");

return ESP_OK;
err:
return ret;
}

// board specific initialization routine, user to update per specific needs
esp_err_t ksz8863_board_specific_init(esp_eth_handle_t eth_handle)
{
esp_err_t ret = ESP_OK;

#if CONFIG_EXAMPLE_CTRL_I2C
// initialize I2C interface
i2c_config_t i2c_bus_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_io_num = CONFIG_EXAMPLE_I2C_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000,
.sda_io_num = CONFIG_EXAMPLE_I2C_SDA_GPIO,
.glitch_ignore_cnt = 7,
};
ESP_GOTO_ON_ERROR(i2c_init(CONFIG_EXAMPLE_I2C_MASTER_PORT, &i2c_bus_config), err, TAG, "I2C initialization failed");
i2c_master_bus_handle_t bus_handle;
ESP_GOTO_ON_ERROR(i2c_new_master_bus(&i2c_mst_config, &bus_handle), err, TAG, "I2C initialization failed");
ksz8863_ctrl_i2c_config_t i2c_dev_config = {
.bus_handle = bus_handle,
.dev_addr = KSZ8863_I2C_DEV_ADDR,
.i2c_master_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.i2c_port = CONFIG_EXAMPLE_I2C_MASTER_PORT,
.scl_speed_hz = CONFIG_EXAMPLE_I2C_CLOCK_KHZ * 1000
};
ksz8863_ctrl_intf_config_t ctrl_intf_cfg = {
.host_mode = KSZ8863_I2C_MODE,
Expand Down Expand Up @@ -386,7 +378,7 @@ void app_main(void)
ESP_ERROR_CHECK(esp_netif_attach(eth_netif_port[1], esp_eth_new_netif_glue(p2_eth_handle)));

// Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, &host_eth_handle));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));

// start Ethernet driver state machines
Expand Down
2 changes: 1 addition & 1 deletion ksz8863/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "0.2.6"
version: "0.2.7"
targets:
- esp32
- esp32p4
Expand Down
6 changes: 4 additions & 2 deletions ksz8863/include/ksz8863_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#pragma once

#include "esp_err.h"
#include "driver/i2c.h"
#include "driver/i2c_master.h"
#include "driver/spi_master.h"
#include "esp_eth_driver.h" // for esp_eth_handle_t

Expand All @@ -24,7 +24,9 @@ typedef enum {

typedef struct {
uint8_t dev_addr;
i2c_port_t i2c_master_port;
uint32_t scl_speed_hz;
i2c_port_num_t i2c_port;
bogdankolendovskyy marked this conversation as resolved.
Show resolved Hide resolved
i2c_master_bus_handle_t bus_handle;
} ksz8863_ctrl_i2c_config_t;

typedef struct {
Expand Down
2 changes: 2 additions & 0 deletions ksz8863/src/esp_eth_ksz8863.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <sys/queue.h>
#include "esp_log.h"
#include "esp_check.h"
#include "driver/gpio.h"
#include "esp_rom_gpio.h"

#include "esp_eth_ksz8863.h"
#include "ksz8863.h" // registers
Expand Down
Loading
Loading