Skip to content

Commit

Permalink
eth: Add full-duplex configuration to ENC28J60
Browse files Browse the repository at this point in the history
The driver originally gets the full-duplex configuration
from the PHCON1 register and PDPXMD bit as stated by the
ENC298J60 specification document section 2.6 "LED Configuration".
This section trust the board to LEDB connection to signal the
full-duplex configuration.

This commit gets the full-duplex configuration from Kconfig
symbols to allow a proper functionality even when the board
is not connecting LEDB apropriately.

Change-Id: I803958409a611e23e2c3e03f40b412f1695947af
Signed-off-by: Juan Manuel Cruz <[email protected]>
  • Loading branch information
jmnlcruz authored and Anas Nashif committed Sep 17, 2016
1 parent bb4c1bd commit b97f3f3
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 38 deletions.
7 changes: 7 additions & 0 deletions drivers/ethernet/Kconfig.enc28j60
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ config ETH_ENC28J60_0_NAME
string "Driver's name"
default "ETH_0"

config ETH_EN28J60_0_FULL_DUPLEX
bool "ENC28J60 full duplex"
default y
help
Enable Full Duplex. Device is configured half duplex
when disabled.

config ETH_ENC28J60_0_INIT_PRIORITY
int
prompt "ENC28J60C init priority"
Expand Down
43 changes: 6 additions & 37 deletions drivers/ethernet/eth_enc28j60.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,6 @@ static void eth_enc28j60_read_mem(struct device *dev, uint8_t *data_buffer,
nano_fiber_sem_give(&context->spi_sem);
}

static void eth_enc28j60_read_phy(struct device *dev, uint16_t reg_addr,
int16_t *data)
{
uint8_t rl, rh;
uint8_t data_mistat;

eth_enc28j60_set_bank(dev, ENC28J60_REG_MIREGADR);
eth_enc28j60_write_reg(dev, ENC28J60_REG_MIREGADR, reg_addr);
eth_enc28j60_write_reg(dev, ENC28J60_REG_MICMD,
ENC28J60_BIT_MICMD_MIIRD);
eth_enc28j60_set_bank(dev, ENC28J60_REG_MISTAT);

do {
/* wait 10.24 useconds */
sys_thread_busy_wait(D10D24S);
eth_enc28j60_read_reg(dev, ENC28J60_REG_MISTAT,
&data_mistat);
} while ((data_mistat & ENC28J60_BIT_MISTAT_BUSY));

eth_enc28j60_set_bank(dev, ENC28J60_REG_MIREGADR);
eth_enc28j60_write_reg(dev, ENC28J60_REG_MICMD, 0x00);
eth_enc28j60_read_reg(dev, ENC28J60_REG_MIRDL, &rl);
eth_enc28j60_read_reg(dev, ENC28J60_REG_MIRDH, &rh);
*data = rl | ((uint16_t)rh << 8);
}

static void eth_enc28j60_write_phy(struct device *dev, uint16_t reg_addr,
int16_t data)
{
Expand Down Expand Up @@ -301,7 +275,7 @@ static void eth_enc28j60_init_buffers(struct device *dev)

static void eth_enc28j60_init_mac(struct device *dev)
{
struct eth_enc28j60_runtime *context = dev->driver_data;
struct eth_enc28j60_config *config = dev->config->config_info;
uint8_t data_macon;
uint8_t mac_address[6];

Expand All @@ -315,14 +289,14 @@ static void eth_enc28j60_init_mac(struct device *dev)

data_macon = ENC28J60_MAC_CONFIG;

if (context->full_duplex) {
if (config->full_duplex) {
data_macon |= ENC28J60_BIT_MACON3_FULDPX;
}

eth_enc28j60_write_reg(dev, ENC28J60_REG_MACON3, data_macon);
eth_enc28j60_write_reg(dev, ENC28J60_REG_MAIPGL, ENC28J60_MAC_NBBIPGL);

if (context->full_duplex) {
if (config->full_duplex) {
eth_enc28j60_write_reg(dev, ENC28J60_REG_MAIPGH,
ENC28J60_MAC_NBBIPGH);
eth_enc28j60_write_reg(dev, ENC28J60_REG_MABBIPG,
Expand Down Expand Up @@ -356,9 +330,9 @@ static void eth_enc28j60_init_mac(struct device *dev)

static void eth_enc28j60_init_phy(struct device *dev)
{
struct eth_enc28j60_runtime *context = dev->driver_data;
struct eth_enc28j60_config *config = dev->config->config_info;

if (context->full_duplex) {
if (config->full_duplex) {
eth_enc28j60_write_phy(dev, ENC28J60_PHY_PHCON1,
ENC28J60_BIT_PHCON1_PDPXMD);
eth_enc28j60_write_phy(dev, ENC28J60_PHY_PHCON2, 0x0);
Expand All @@ -374,7 +348,6 @@ static int eth_enc28j60_init(struct device *dev)
struct eth_enc28j60_config *config = dev->config->config_info;
struct eth_enc28j60_runtime *context = dev->driver_data;
struct spi_config spi_cfg;
uint16_t data_phy;

nano_sem_init(&context->spi_sem);
nano_fiber_sem_give(&context->spi_sem);
Expand Down Expand Up @@ -428,11 +401,6 @@ static int eth_enc28j60_init(struct device *dev)
/* Errata B7/2 */
sys_thread_busy_wait(D10D24S);

/* Select half-duplex/full-duplex from LED configuration */
eth_enc28j60_read_phy(dev, ENC28J60_PHY_PHCON1, &data_phy);
data_phy &= ENC28J60_BIT_PHCON1_PDPXMD;
context->full_duplex = !!(data_phy);

eth_enc28j60_init_buffers(dev);
eth_enc28j60_init_mac(dev);
eth_enc28j60_init_phy(dev);
Expand Down Expand Up @@ -654,6 +622,7 @@ static struct eth_enc28j60_config eth_enc28j60_0_config = {
.spi_port = CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME,
.spi_freq = CONFIG_ETH_ENC28J60_0_SPI_BUS_FREQ,
.spi_slave = CONFIG_ETH_ENC28J60_0_SLAVE,
.full_duplex = CONFIG_ETH_EN28J60_0_FULL_DUPLEX,
};

DEVICE_AND_API_INIT(eth_enc28j60_0, CONFIG_ETH_ENC28J60_0_NAME,
Expand Down
2 changes: 1 addition & 1 deletion drivers/ethernet/eth_enc28j60_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ struct eth_enc28j60_config {
const char *spi_port;
uint32_t spi_freq;
uint8_t spi_slave;
uint8_t full_duplex;
};

struct eth_enc28j60_runtime {
char __stack fiber_stack[ENC28J60_FIBER_STACK_SIZE];
struct device *gpio;
struct device *spi;
struct gpio_callback gpio_cb;
char full_duplex;
uint8_t tx_tsv[TSV_SIZE];
uint8_t rx_rsv[RSV_SIZE];
struct nano_sem tx_sem;
Expand Down

0 comments on commit b97f3f3

Please sign in to comment.