drivers/ethernet: Fix and clean a bit ENC28J60 driver
Driver is still a bit messy, not using for instance the 0-copy capabilities of SPI API, but this will be fix later. Constify most of the spi buf structures, removing useless variables, renaming function with common prefix eth_enc28j60_ etc... It seems to fix an issue on verifying if tx was successful as well. Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
f9159ab6bd
commit
42902e580b
2 changed files with 201 additions and 230 deletions
|
@ -23,21 +23,17 @@
|
|||
|
||||
#define D10D24S 11
|
||||
|
||||
static void enc28j60_thread_main(void *arg1, void *unused1, void *unused2);
|
||||
|
||||
static int eth_enc28j60_soft_reset(struct device *dev)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t tx_buf[2] = {ENC28J60_SPI_SC, 0xFF};
|
||||
const struct spi_buf tx_bufs[] = {
|
||||
{
|
||||
.buf = tx_buf,
|
||||
.len = 1,
|
||||
},
|
||||
u8_t buf[2] = { ENC28J60_SPI_SC, 0xFF };
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 1,
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
return spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
|
@ -46,38 +42,34 @@ static int eth_enc28j60_soft_reset(struct device *dev)
|
|||
static void eth_enc28j60_set_bank(struct device *dev, u16_t reg_addr)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
struct spi_buf tx_bufs[1];
|
||||
struct spi_buf rx_bufs[1];
|
||||
u8_t buf[2];
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf rx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = rx_bufs,
|
||||
.count = ARRAY_SIZE(rx_bufs)
|
||||
.buffers = &rx_buf,
|
||||
.count = 1
|
||||
};
|
||||
u8_t tx_buf[2];
|
||||
u8_t rx_buf[2];
|
||||
int ret;
|
||||
|
||||
tx_buf[0] = ENC28J60_SPI_RCR | ENC28J60_REG_ECON1;
|
||||
tx_buf[1] = 0x0;
|
||||
buf[0] = ENC28J60_SPI_RCR | ENC28J60_REG_ECON1;
|
||||
buf[1] = 0x0;
|
||||
|
||||
tx_bufs[0].buf = tx_buf;
|
||||
tx_bufs[0].len = 2;
|
||||
rx_bufs[0].buf = rx_buf;
|
||||
rx_bufs[0].len = 2;
|
||||
if (!spi_transceive(context->spi, &context->spi_cfg, &tx, &rx)) {
|
||||
buf[0] = ENC28J60_SPI_WCR | ENC28J60_REG_ECON1;
|
||||
buf[1] = (buf[1] & 0xFC) | ((reg_addr >> 8) & 0x0F);
|
||||
|
||||
ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &rx);
|
||||
if (!ret) {
|
||||
tx_buf[0] = ENC28J60_SPI_WCR | ENC28J60_REG_ECON1;
|
||||
tx_buf[1] = (rx_buf[1] & 0xFC) | ((reg_addr >> 8) & 0x0F);
|
||||
|
||||
tx_bufs[0].buf = tx_buf;
|
||||
tx_bufs[0].len = 2;
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
} else {
|
||||
SYS_LOG_DBG("Failure while setting bank to %d", reg_addr);
|
||||
SYS_LOG_DBG("Failure while setting bank to 0x%04x", reg_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,20 +77,18 @@ static void eth_enc28j60_write_reg(struct device *dev, u16_t reg_addr,
|
|||
u8_t value)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t tx_buf[2];
|
||||
const struct spi_buf tx_bufs[] = {
|
||||
{
|
||||
.buf = tx_buf,
|
||||
.len = 2
|
||||
}
|
||||
u8_t buf[2];
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
tx_buf[0] = ENC28J60_SPI_WCR | (reg_addr & 0xFF);
|
||||
tx_buf[1] = value;
|
||||
buf[0] = ENC28J60_SPI_WCR | (reg_addr & 0xFF);
|
||||
buf[1] = value;
|
||||
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
}
|
||||
|
@ -107,44 +97,37 @@ static void eth_enc28j60_read_reg(struct device *dev, u16_t reg_addr,
|
|||
u8_t *value)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t tx_buf[2];
|
||||
const struct spi_buf tx_bufs[1] = {
|
||||
{
|
||||
.buf = tx_buf,
|
||||
.len = 2
|
||||
}
|
||||
u8_t buf[3];
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
u8_t rx_buf[3];
|
||||
struct spi_buf rx_bufs[1] = {
|
||||
{
|
||||
.buf = rx_buf,
|
||||
}
|
||||
struct spi_buf rx_buf = {
|
||||
.buf = buf,
|
||||
};
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = rx_bufs,
|
||||
.count = ARRAY_SIZE(rx_bufs)
|
||||
.buffers = &rx_buf,
|
||||
.count = 1
|
||||
};
|
||||
u8_t rx_size = 2;
|
||||
int ret;
|
||||
|
||||
if (reg_addr & 0xF000) {
|
||||
rx_size = 3;
|
||||
}
|
||||
|
||||
tx_buf[0] = ENC28J60_SPI_RCR | (reg_addr & 0xFF);
|
||||
tx_buf[1] = 0x0;
|
||||
rx_buf.len = rx_size;
|
||||
|
||||
rx_bufs[0].len = rx_size;
|
||||
buf[0] = ENC28J60_SPI_RCR | (reg_addr & 0xFF);
|
||||
buf[1] = 0x0;
|
||||
|
||||
ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &rx);
|
||||
if (!ret) {
|
||||
*value = rx_buf[rx_size - 1];
|
||||
if (!spi_transceive(context->spi, &context->spi_cfg, &tx, &rx)) {
|
||||
*value = buf[rx_size - 1];
|
||||
} else {
|
||||
SYS_LOG_DBG("Failure while reading register %d", reg_addr);
|
||||
SYS_LOG_DBG("Failure while reading register 0x%04x", reg_addr);
|
||||
*value = 0;
|
||||
}
|
||||
}
|
||||
|
@ -153,20 +136,18 @@ static void eth_enc28j60_set_eth_reg(struct device *dev, u16_t reg_addr,
|
|||
u8_t value)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t tx_buf[2];
|
||||
const struct spi_buf tx_bufs[1] = {
|
||||
{
|
||||
.buf = tx_buf,
|
||||
.len = 2
|
||||
}
|
||||
u8_t buf[2];
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
tx_buf[0] = ENC28J60_SPI_BFS | (reg_addr & 0xFF);
|
||||
tx_buf[1] = value;
|
||||
buf[0] = ENC28J60_SPI_BFS | (reg_addr & 0xFF);
|
||||
buf[1] = value;
|
||||
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
}
|
||||
|
@ -176,20 +157,18 @@ static void eth_enc28j60_clear_eth_reg(struct device *dev, u16_t reg_addr,
|
|||
u8_t value)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t tx_buf[2];
|
||||
const struct spi_buf tx_bufs[1] = {
|
||||
{
|
||||
.buf = tx_buf,
|
||||
.len = ARRAY_SIZE(tx_bufs)
|
||||
}
|
||||
u8_t buf[2];
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf,
|
||||
.len = 2
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
tx_buf[0] = ENC28J60_SPI_BFC | (reg_addr & 0xFF);
|
||||
tx_buf[1] = value;
|
||||
buf[0] = ENC28J60_SPI_BFC | (reg_addr & 0xFF);
|
||||
buf[1] = value;
|
||||
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
}
|
||||
|
@ -198,10 +177,12 @@ static void eth_enc28j60_write_mem(struct device *dev, u8_t *data_buffer,
|
|||
u16_t buf_len)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
struct spi_buf tx_bufs[1];
|
||||
struct spi_buf tx_buf = {
|
||||
.buf = context->mem_buf
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
u8_t *index_buf;
|
||||
u16_t num_segments;
|
||||
|
@ -215,8 +196,7 @@ static void eth_enc28j60_write_mem(struct device *dev, u8_t *data_buffer,
|
|||
++i, index_buf += MAX_BUFFER_LENGTH) {
|
||||
context->mem_buf[0] = ENC28J60_SPI_WBM;
|
||||
memcpy(context->mem_buf + 1, index_buf, MAX_BUFFER_LENGTH);
|
||||
tx_bufs[0].buf = context->mem_buf;
|
||||
tx_bufs[0].len = MAX_BUFFER_LENGTH + 1;
|
||||
tx_buf.len = MAX_BUFFER_LENGTH + 1;
|
||||
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
}
|
||||
|
@ -224,8 +204,7 @@ static void eth_enc28j60_write_mem(struct device *dev, u8_t *data_buffer,
|
|||
if (num_remaining > 0) {
|
||||
context->mem_buf[0] = ENC28J60_SPI_WBM;
|
||||
memcpy(context->mem_buf + 1, index_buf, num_remaining);
|
||||
tx_bufs[0].buf = context->mem_buf;
|
||||
tx_bufs[0].len = num_remaining + 1;
|
||||
tx_buf.len = num_remaining + 1;
|
||||
|
||||
spi_write(context->spi, &context->spi_cfg, &tx);
|
||||
}
|
||||
|
@ -235,10 +214,12 @@ static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer,
|
|||
u16_t buf_len)
|
||||
{
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
struct spi_buf tx_bufs[1];
|
||||
struct spi_buf tx_buf = {
|
||||
.buf = context->mem_buf
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_bufs,
|
||||
.count = ARRAY_SIZE(tx_bufs)
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
u16_t num_segments;
|
||||
u16_t num_remaining;
|
||||
|
@ -251,8 +232,7 @@ static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer,
|
|||
++i, data_buffer += MAX_BUFFER_LENGTH) {
|
||||
context->mem_buf[0] = ENC28J60_SPI_RBM;
|
||||
|
||||
tx_bufs[0].buf = context->mem_buf;
|
||||
tx_bufs[0].len = MAX_BUFFER_LENGTH + 1;
|
||||
tx_buf.len = MAX_BUFFER_LENGTH + 1;
|
||||
|
||||
ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &tx);
|
||||
if (!ret) {
|
||||
|
@ -268,8 +248,7 @@ static void eth_enc28j60_read_mem(struct device *dev, u8_t *data_buffer,
|
|||
if (num_remaining > 0) {
|
||||
context->mem_buf[0] = ENC28J60_SPI_RBM;
|
||||
|
||||
tx_bufs[0].buf = context->mem_buf;
|
||||
tx_bufs[0].len = num_remaining + 1;
|
||||
tx_buf.len = num_remaining + 1;
|
||||
|
||||
ret = spi_transceive(context->spi, &context->spi_cfg, &tx, &tx);
|
||||
if (!ret) {
|
||||
|
@ -420,102 +399,11 @@ static void eth_enc28j60_init_phy(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static int eth_enc28j60_init(struct device *dev)
|
||||
{
|
||||
const struct eth_enc28j60_config *config = dev->config->config_info;
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
|
||||
/* SPI config */
|
||||
context->spi_cfg.operation = SPI_WORD_SET(8);
|
||||
context->spi_cfg.frequency = config->spi_freq;
|
||||
context->spi_cfg.slave = config->spi_slave;
|
||||
|
||||
context->spi = device_get_binding((char *)config->spi_port);
|
||||
if (!context->spi) {
|
||||
|
||||
SYS_LOG_ERR("SPI master port %s not found", config->spi_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS
|
||||
context->spi_cs.gpio_dev =
|
||||
device_get_binding((char *)config->spi_cs_port);
|
||||
if (!context->spi_cs.gpio_dev) {
|
||||
SYS_LOG_ERR("SPI CS port %s not found", config->spi_cs_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
context->spi_cs.gpio_pin = config->spi_cs_pin;
|
||||
context->spi_cfg.cs = &context->spi_cs;
|
||||
#endif /* CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS */
|
||||
|
||||
/* Initialize GPIO */
|
||||
context->gpio = device_get_binding((char *)config->gpio_port);
|
||||
if (!context->gpio) {
|
||||
SYS_LOG_ERR("GPIO port %s not found", config->gpio_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(context->gpio, config->gpio_pin,
|
||||
(GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE
|
||||
| GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE))) {
|
||||
SYS_LOG_ERR("Unable to configure GPIO pin %u",
|
||||
config->gpio_pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_init_callback(&(context->gpio_cb), eth_enc28j60_gpio_callback,
|
||||
BIT(config->gpio_pin));
|
||||
|
||||
if (gpio_add_callback(context->gpio, &(context->gpio_cb))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_enable_callback(context->gpio, config->gpio_pin)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (eth_enc28j60_soft_reset(dev)) {
|
||||
SYS_LOG_ERR("Soft-reset failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Errata B7/1 */
|
||||
k_busy_wait(D10D24S);
|
||||
|
||||
eth_enc28j60_init_buffers(dev);
|
||||
eth_enc28j60_init_mac(dev);
|
||||
eth_enc28j60_init_phy(dev);
|
||||
|
||||
/* Enable interruptions */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_INTIE);
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_PKTIE);
|
||||
|
||||
/* Enable Reception */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_ECON1,
|
||||
ENC28J60_BIT_ECON1_RXEN);
|
||||
|
||||
/* Initialize semaphores */
|
||||
k_sem_init(&context->tx_rx_sem, 0, UINT_MAX);
|
||||
k_sem_init(&context->int_sem, 0, UINT_MAX);
|
||||
k_sem_give(&context->tx_rx_sem);
|
||||
|
||||
/* Start interruption-poll thread */
|
||||
k_thread_create(&context->thread, context->thread_stack,
|
||||
CONFIG_ETH_ENC28J60_RX_THREAD_STACK_SIZE,
|
||||
enc28j60_thread_main, (void *) dev, NULL, NULL,
|
||||
K_PRIO_COOP(CONFIG_ETH_ENC28J60_RX_THREAD_PRIO),
|
||||
0, K_NO_WAIT);
|
||||
|
||||
SYS_LOG_INF("ENC28J60 Initialized");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eth_enc28j60_tx(struct device *dev, struct net_pkt *pkt,
|
||||
u16_t len)
|
||||
static int eth_enc28j60_tx(struct net_if *iface, struct net_pkt *pkt)
|
||||
{
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u16_t len = net_pkt_ll_reserve(pkt) + net_pkt_get_len(pkt);
|
||||
u16_t tx_bufaddr = ENC28J60_TXSTART;
|
||||
bool first_frag = true;
|
||||
u8_t per_packet_control;
|
||||
|
@ -523,6 +411,8 @@ static int eth_enc28j60_tx(struct device *dev, struct net_pkt *pkt,
|
|||
struct net_buf *frag;
|
||||
u8_t tx_end;
|
||||
|
||||
SYS_LOG_DBG("pkt %p (len %u)", pkt, len);
|
||||
|
||||
k_sem_take(&context->tx_rx_sem, K_FOREVER);
|
||||
|
||||
/* Latest errata sheet: DS80349C
|
||||
|
@ -581,6 +471,7 @@ static int eth_enc28j60_tx(struct device *dev, struct net_pkt *pkt,
|
|||
tx_end &= ENC28J60_BIT_EIR_TXIF;
|
||||
} while (!tx_end);
|
||||
|
||||
|
||||
eth_enc28j60_read_reg(dev, ENC28J60_REG_ESTAT, &tx_end);
|
||||
|
||||
k_sem_give(&context->tx_rx_sem);
|
||||
|
@ -590,6 +481,10 @@ static int eth_enc28j60_tx(struct device *dev, struct net_pkt *pkt,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
SYS_LOG_DBG("Tx successful");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -725,19 +620,14 @@ done:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void enc28j60_thread_main(void *arg1, void *unused1, void *unused2)
|
||||
static void eth_enc28j60_rx_thread(struct device *dev)
|
||||
{
|
||||
struct device *dev = (struct device *) arg1;
|
||||
struct eth_enc28j60_runtime *context;
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
u8_t int_stat;
|
||||
|
||||
ARG_UNUSED(unused1);
|
||||
ARG_UNUSED(unused2);
|
||||
|
||||
context = dev->driver_data;
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
k_sem_take(&context->int_sem, K_FOREVER);
|
||||
|
||||
eth_enc28j60_read_reg(dev, ENC28J60_REG_EIR, &int_stat);
|
||||
if (int_stat & ENC28J60_BIT_EIR_PKTIF) {
|
||||
eth_enc28j60_rx(dev);
|
||||
|
@ -749,21 +639,6 @@ static void enc28j60_thread_main(void *arg1, void *unused1, void *unused2)
|
|||
}
|
||||
}
|
||||
|
||||
static int eth_net_tx(struct net_if *iface, struct net_pkt *pkt)
|
||||
{
|
||||
u16_t len = net_pkt_ll_reserve(pkt) + net_pkt_get_len(pkt);
|
||||
int ret;
|
||||
|
||||
SYS_LOG_DBG("pkt %p (len %u)", pkt, len);
|
||||
|
||||
ret = eth_enc28j60_tx(net_if_get_device(iface), pkt, len);
|
||||
if (ret == 0) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum ethernet_hw_caps eth_enc28j60_get_capabilities(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
@ -771,15 +646,6 @@ static enum ethernet_hw_caps eth_enc28j60_get_capabilities(struct device *dev)
|
|||
return ETHERNET_LINK_10BASE_T;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ETH_ENC28J60_0
|
||||
|
||||
static u8_t mac_address_0[6] = { MICROCHIP_OUI_B0,
|
||||
MICROCHIP_OUI_B1,
|
||||
MICROCHIP_OUI_B2,
|
||||
CONFIG_ETH_ENC28J60_0_MAC3,
|
||||
CONFIG_ETH_ENC28J60_0_MAC4,
|
||||
CONFIG_ETH_ENC28J60_0_MAC5 };
|
||||
|
||||
static void eth_enc28j60_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
|
@ -787,19 +653,123 @@ static void eth_enc28j60_iface_init(struct net_if *iface)
|
|||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
net_if_set_link_addr(iface, mac_address_0, sizeof(mac_address_0),
|
||||
net_if_set_link_addr(iface, context->mac_address,
|
||||
sizeof(context->mac_address),
|
||||
NET_LINK_ETHERNET);
|
||||
context->iface = iface;
|
||||
}
|
||||
|
||||
static const struct ethernet_api api_funcs = {
|
||||
.iface_api.init = eth_enc28j60_iface_init,
|
||||
.iface_api.send = eth_net_tx,
|
||||
.iface_api.send = eth_enc28j60_tx,
|
||||
|
||||
.get_capabilities = eth_enc28j60_get_capabilities,
|
||||
};
|
||||
|
||||
static struct eth_enc28j60_runtime eth_enc28j60_0_runtime;
|
||||
static int eth_enc28j60_init(struct device *dev)
|
||||
{
|
||||
const struct eth_enc28j60_config *config = dev->config->config_info;
|
||||
struct eth_enc28j60_runtime *context = dev->driver_data;
|
||||
|
||||
/* SPI config */
|
||||
context->spi_cfg.operation = SPI_WORD_SET(8);
|
||||
context->spi_cfg.frequency = config->spi_freq;
|
||||
context->spi_cfg.slave = config->spi_slave;
|
||||
|
||||
context->spi = device_get_binding((char *)config->spi_port);
|
||||
if (!context->spi) {
|
||||
|
||||
SYS_LOG_ERR("SPI master port %s not found", config->spi_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS
|
||||
context->spi_cs.gpio_dev =
|
||||
device_get_binding((char *)config->spi_cs_port);
|
||||
if (!context->spi_cs.gpio_dev) {
|
||||
SYS_LOG_ERR("SPI CS port %s not found", config->spi_cs_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
context->spi_cs.gpio_pin = config->spi_cs_pin;
|
||||
context->spi_cfg.cs = &context->spi_cs;
|
||||
#endif /* CONFIG_ETH_ENC28J60_0_GPIO_SPI_CS */
|
||||
|
||||
/* Initialize GPIO */
|
||||
context->gpio = device_get_binding((char *)config->gpio_port);
|
||||
if (!context->gpio) {
|
||||
SYS_LOG_ERR("GPIO port %s not found", config->gpio_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(context->gpio, config->gpio_pin,
|
||||
(GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE
|
||||
| GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE))) {
|
||||
SYS_LOG_ERR("Unable to configure GPIO pin %u",
|
||||
config->gpio_pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_init_callback(&(context->gpio_cb), eth_enc28j60_gpio_callback,
|
||||
BIT(config->gpio_pin));
|
||||
|
||||
if (gpio_add_callback(context->gpio, &(context->gpio_cb))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_enable_callback(context->gpio, config->gpio_pin)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (eth_enc28j60_soft_reset(dev)) {
|
||||
SYS_LOG_ERR("Soft-reset failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Errata B7/1 */
|
||||
k_busy_wait(D10D24S);
|
||||
|
||||
eth_enc28j60_init_buffers(dev);
|
||||
eth_enc28j60_init_mac(dev);
|
||||
eth_enc28j60_init_phy(dev);
|
||||
|
||||
/* Enable interruptions */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_INTIE);
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_EIE, ENC28J60_BIT_EIE_PKTIE);
|
||||
|
||||
/* Enable Reception */
|
||||
eth_enc28j60_set_eth_reg(dev, ENC28J60_REG_ECON1,
|
||||
ENC28J60_BIT_ECON1_RXEN);
|
||||
|
||||
/* Start interruption-poll thread */
|
||||
k_thread_create(&context->thread, context->thread_stack,
|
||||
CONFIG_ETH_ENC28J60_RX_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)eth_enc28j60_rx_thread,
|
||||
(void *)dev, NULL, NULL,
|
||||
K_PRIO_COOP(CONFIG_ETH_ENC28J60_RX_THREAD_PRIO),
|
||||
0, K_NO_WAIT);
|
||||
|
||||
SYS_LOG_INF("ENC28J60 Initialized");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ETH_ENC28J60_0
|
||||
|
||||
static struct eth_enc28j60_runtime eth_enc28j60_0_runtime = {
|
||||
.mac_address = {
|
||||
MICROCHIP_OUI_B0,
|
||||
MICROCHIP_OUI_B1,
|
||||
MICROCHIP_OUI_B2,
|
||||
CONFIG_ETH_ENC28J60_0_MAC3,
|
||||
CONFIG_ETH_ENC28J60_0_MAC4,
|
||||
CONFIG_ETH_ENC28J60_0_MAC5
|
||||
},
|
||||
.tx_rx_sem = _K_SEM_INITIALIZER(eth_enc28j60_0_runtime.tx_rx_sem,
|
||||
1, UINT_MAX),
|
||||
.int_sem = _K_SEM_INITIALIZER(eth_enc28j60_0_runtime.int_sem,
|
||||
0, UINT_MAX),
|
||||
};
|
||||
|
||||
static const struct eth_enc28j60_config eth_enc28j60_0_config = {
|
||||
.gpio_port = CONFIG_ETH_ENC28J60_0_GPIO_PORT_NAME,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue