Commit f2f62b0d authored by Robert Slawinski's avatar Robert Slawinski Committed by Benjamin Cabé
Browse files

drivers: dm8806: smi bus error check

SMI bus error check mechanism is preventing the host SMI bus to be
interferred by noise on board level. Current implementation is checking
if data which is writing to/reading from the PHY has correct CRC sum.
If not, then writing/rading process is repeated by the number of
attempts defined in the KConfig. If repeating transmission will fail
by the numbers of ettemps defined in KConfing, drivers returns an
error.

Signed-off-by: default avatarRobert Slawinski <robert.slawinski1@gmail.com>
parent 9a236f82
Loading
Loading
Loading
Loading
+22 −1
Changes for drivers/ethernet/phy/Kconfig.dm8806: 22 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -46,4 +46,25 @@ config PHY_DM8806_THREAD_STACK_SIZE
	help
	  Stack size of thread used by the driver to handle interrupts.

endif # PHY_DM8806_TRIGGER
config PHY_DM8806_SMI_BUS_CHECK
	bool "Host SMI bus error check function"
	default y
	help
	  This functionality prevents the host SMI bus to be interferered by the
	  noise on board-level. During write procedure, the written value in
	  register will be applied until the correct checksum is written. In read
	  procedure, the hardware calculated checksum is compared with the software
	  calculated one to detect correctness of received data.

config PHY_DM8806_SMI_BUS_CHECK_REPETITION
	int "SMI bus transmission repetitions"
	depends on PHY_DM8806_SMI_BUS_CHECK
	default 5
	help
	  The numbers of SMI bus transmission repetition in case if CRC checksum
	  fails during read or write. After this numbers of repetition, the reading
	  message is dropped and will not be passed to the system. In write
	  procedure, the written value in register will be applied until the correct
	  checksum is written to the PHY register.

endif # PHY_DM8806
+248 −46
Changes for drivers/ethernet/phy/phy_dm8806.c: 248 added lines, 46 removed lines.
Original line number Diff line number Diff line
@@ -42,6 +42,204 @@ struct phy_dm8806_data {
#endif
};

#ifdef CONFIG_PHY_DM8806_SMI_BUS_CHECK
static uint16_t phy_calculate_checksum(uint16_t data, uint16_t reg_addr, uint8_t opcode)
{
	uint16_t csum[8];
	uint16_t checksum = 0;

	/* Checksum calculated formula proposed by Davicom on datasheet:
	 * DM8806-DAVICOM - par. 7.2.1:
	 * Host SMI Bus Error Check Function, page 141.
	 */
	csum[0] = (((data >> 0) & 1) ^ ((data >> 8) & 1) ^ ((reg_addr >> 0) & 1) ^
		   ((reg_addr >> 8) & 1));
	csum[1] = (((data >> 1) & 1) ^ ((data >> 9) & 1) ^ ((reg_addr >> 1) & 1) ^
		   ((reg_addr >> 9) & 1));
	csum[2] = (((data >> 2) & 1) ^ ((data >> 10) & 1) ^ ((reg_addr >> 2) & 1) ^
		   ((opcode >> 0) & 1));
	csum[3] = (((data >> 3) & 1) ^ ((data >> 11) & 1) ^ ((reg_addr >> 3) & 1) ^
		   ((opcode >> 1) & 1));
	csum[4] = (((data >> 4) & 1) ^ ((data >> 12) & 1) ^ ((reg_addr >> 4) & 1));
	csum[5] = (((data >> 5) & 1) ^ ((data >> 13) & 1) ^ ((reg_addr >> 5) & 1));
	csum[6] = (((data >> 6) & 1) ^ ((data >> 14) & 1) ^ ((reg_addr >> 6) & 1));
	csum[7] = (((data >> 7) & 1) ^ ((data >> 15) & 1) ^ ((reg_addr >> 7) & 1));
	for (int cnt = 0; cnt < 8; cnt++) {
		checksum |= (csum[cnt] << cnt);
	}
	return checksum;
}
#endif

static int phy_dm8806_write_reg(const struct device *dev, uint8_t phyad, uint8_t regad,
				uint16_t data)
{
	int res = 0;
	const struct phy_dm8806_config *cfg = dev->config;

/* SMI bus check function should be activated each time, before writing
 * procedure to the DM8806 registers. This is standard procedure described in
 * the datasheet of the DM8806.
 */
#ifdef CONFIG_PHY_DM8806_SMI_BUS_CHECK
	uint16_t checksum_status;
	bool checksum_mismatch;
	uint16_t sw_checksum = 0;
	uint16_t abs_reg;
	int repetition = 0;

	do {
		/* Set register 33AH.[0] = 1 to enable SMI Bus Error Check function. */
		res = mdio_write(cfg->mdio, DM8806_SMI_BUS_CTRL_PHY_ADDRESS,
				 DM8806_SMI_BUS_CTRL_REG_ADDRESS, DM8806_SMI_ECE);
		if (res < 0) {
			LOG_ERR("Failed to write data to PHY register: SMI_BUS_CTRL_REG_ADDRESS, "
				"error code: %d",
				res);
			return res;
		}
#endif
		res = mdio_write(cfg->mdio, phyad, regad, data);
		if (res < 0) {
			LOG_ERR("Failed to read data from PHY, error code: %d", res);
			return res;
		}
#ifdef CONFIG_PHY_DM8806_SMI_BUS_CHECK
		/* Calculate checksum */
		abs_reg = (phyad << DM8806_REGAD_WIDTH);
		abs_reg |= (regad & BIT_MASK(DM8806_REGAD_WIDTH));
		sw_checksum = phy_calculate_checksum(data, abs_reg, DM8806_PHY_WRITE);
		sw_checksum &= BIT_MASK(8);
		/* Write calculated checksum to the PHY register 339H.[7:0] */
		res = mdio_write(cfg->mdio, DM8806_SMI_BUS_ERR_CHK_PHY_ADDRESS,
				 DM8806_SMI_BUS_ERR_CHK_REG_ADDRESS, sw_checksum);
		if (res < 0) {
			LOG_ERR("Failed to write calculated checksum to the PHY register, "
				"error code: %d",
				res);
			return res;
		}

		/* Read status of the checksum from Serial Bus Error Check Register
		 * 339H.[8].
		 */
		res = mdio_read(cfg->mdio, DM8806_SMI_BUS_ERR_CHK_PHY_ADDRESS,
				DM8806_SMI_BUS_ERR_CHK_REG_ADDRESS, &checksum_status);
		if (res < 0) {
			LOG_ERR("Failed to read hardware calculated checksum from PHY, error code: "
				"%d",
				res);
			return res;
		}
		/* Checksum status is present on the 8-th bit of the Serial Bus Error
		 * Check Register (339h) [8].
		 */
		checksum_mismatch = (bool)(checksum_status & BIT(DM8806_SMI_ERR));

		/* Repeat the writing procedure for the number of attempts defined in
		 * KConfig after which the transfer will failed.
		 */
		if (CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION > 0) {
			repetition++;
			if (checksum_mismatch) {
				LOG_WRN("%d repeat of PHY read procedure due to checksum error.",
					repetition);
				if (repetition >= CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION) {
					LOG_ERR("Maximum number of PHY write repetition exceed.");
					res = (-EIO);
				}
			} else {
				break;
			}
			/* Do not repeat the transfer if repetition number is set to 0. Just check
			 * the checksum in this case and report the error in case of wrong checksum
			 * sum.
			 */
		} else {
			if (checksum_mismatch) {
				LOG_ERR("Wrong checksum, during PHY write procedure.");
				res = (-EIO);
				break;
			}
		}
	} while (repetition < CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION);
#endif

	return res;
}

static int phy_dm8806_read_reg(const struct device *dev, uint8_t phyad, uint8_t regad,
			       uint16_t *data)
{
	int res = 0;
	const struct phy_dm8806_config *cfg = dev->config;

/* SMI bus check function should be activated each time, before reading
 * procedure to the DM8806 registers. This is standard procedure described in
 * the datasheet of the DM8806.
 */
#ifdef CONFIG_PHY_DM8806_SMI_BUS_CHECK
	uint16_t hw_checksum;
	uint16_t sw_checksum = 0;
	uint16_t abs_reg;
	int repetition = 0;

	do {
		/* Set register 33AH.[0] = 1 to enable SMI Bus Error Check function. */
		res = mdio_write(cfg->mdio, DM8806_SMI_BUS_CTRL_PHY_ADDRESS,
				 DM8806_SMI_BUS_CTRL_REG_ADDRESS, DM8806_SMI_ECE);
		if (res < 0) {
			LOG_ERR("Failed to write data to PHY register: SMI_BUS_CTRL_REG_ADDRESS, "
				"error code: %d",
				res);
			return res;
		}
#endif
		res = mdio_read(cfg->mdio, phyad, regad, data);
		if (res < 0) {
			LOG_ERR("Failed to read data from PHY, error code: %d", res);
			return res;
		}
#ifdef CONFIG_PHY_DM8806_SMI_BUS_CHECK
		/* Read hardware calculated checksum from Serial Bus Error Check Register. */
		res = mdio_read(cfg->mdio, DM8806_SMI_BUS_ERR_CHK_PHY_ADDRESS,
				DM8806_SMI_BUS_ERR_CHK_REG_ADDRESS, &hw_checksum);
		if (res < 0) {
			LOG_ERR("Failed to read hardware calculated checksum from PHY, error code: "
				"%d",
				res);
			return res;
		}
		/* Calculate checksum */
		abs_reg = (phyad << DM8806_REGAD_WIDTH);
		abs_reg |= (regad & BIT_MASK(DM8806_REGAD_WIDTH));
		sw_checksum = phy_calculate_checksum(*data, abs_reg, DM8806_PHY_READ);

		if (CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION > 0) {
			repetition++;
			if (hw_checksum != sw_checksum) {
				LOG_WRN("%d repeat of PHY read procedure due to checksum error.",
					repetition);
				if (repetition >= CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION) {
					LOG_ERR("Maximum number of PHY read repetition exceed.");
					res = (-EIO);
				}
			} else {
				break;
			}
		} else {
			if (hw_checksum != sw_checksum) {
				LOG_ERR("Wrong checksum, during PHY read procedure.");
				res = (-EIO);
				break;
			}
		}
	} while (repetition < CONFIG_PHY_DM8806_SMI_BUS_CHECK_REPETITION);
#endif

	return res;
}

static void phy_dm8806_gpio_callback(const struct device *dev, struct gpio_callback *cb,
				     uint32_t pins)
{
@@ -66,9 +264,9 @@ static void phy_dm8806_thread_cb(const struct device *dev, struct phy_link_state
	/* Clear the interrupt flag, by writing "1" to LNKCHG bit of Interrupt Status
	 * Register (318h)
	 */
	mdio_read(cfg->mdio, INT_STAT_PHY_ADDR, INT_STAT_REG_ADDR, &data);
	mdio_read(cfg->mdio, DM8806_INT_STAT_PHY_ADDR, DM8806_INT_STAT_REG_ADDR, &data);
	data |= 0x1;
	mdio_write(cfg->mdio, INT_STAT_PHY_ADDR, INT_STAT_REG_ADDR, data);
	mdio_write(cfg->mdio, DM8806_INT_STAT_PHY_ADDR, DM8806_INT_STAT_REG_ADDR, data);
	gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE);
}

@@ -90,13 +288,13 @@ int phy_dm8806_port_init(const struct device *dev)
	const struct phy_dm8806_config *cfg = dev->config;

	res = gpio_pin_configure_dt(&cfg->gpio_rst, (GPIO_OUTPUT_INACTIVE | GPIO_PULL_UP));
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to configure gpio reset pin for PHY DM886 as an output");
		return res;
	}
	/* Hardware reset of the PHY DM8806 */
	gpio_pin_set_dt(&cfg->gpio_rst, true);
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to assert gpio reset pin of the PHY DM886 to physical 0");
		return res;
	}
@@ -105,7 +303,7 @@ int phy_dm8806_port_init(const struct device *dev)
	 */
	k_msleep(10);
	res = gpio_pin_set_dt(&cfg->gpio_rst, false);
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to assert gpio reset pin of the PHY DM886 to physical 1");
		return res;
	}
@@ -125,13 +323,15 @@ int phy_dm8806_init_interrupt(const struct device *dev)
	 * Activate global interrupt by writing "1" to LNKCHG of Interrupt Mask
	 * And Control Register (319h)
	 */
	res = mdio_read(cfg->mdio, INT_MASK_CTRL_PHY_ADDR, INT_MASK_CTRL_REG_ADDR, &data);
	res = mdio_read(cfg->mdio, DM8806_INT_MASK_CTRL_PHY_ADDR, DM8806_INT_MASK_CTRL_REG_ADDR,
			&data);
	if (res) {
		LOG_ERR("Failed to read IRQ_LED_CONTROL, %i", res);
		return res;
	}
	data |= 0x1;
	res = mdio_write(cfg->mdio, INT_MASK_CTRL_PHY_ADDR, INT_MASK_CTRL_REG_ADDR, data);
	res = mdio_write(cfg->mdio, DM8806_INT_MASK_CTRL_PHY_ADDR, DM8806_INT_MASK_CTRL_REG_ADDR,
			 data);
	if (res) {
		LOG_ERR("Failed to read IRQ_LED_CONTROL, %i", res);
		return res;
@@ -140,13 +340,15 @@ int phy_dm8806_init_interrupt(const struct device *dev)
	/* Activate interrupt per Ethernet port by writing "1" to LNK_EN0~3
	 * of WoL Control Register (2BBh)
	 */
	res = mdio_read(cfg->mdio, WOLL_CTRL_REG_PHY_ADDR, WOLL_CTRL_REG_REG_ADDR, &data);
	res = mdio_read(cfg->mdio, DM8806_WOLL_CTRL_REG_PHY_ADDR, DM8806_WOLL_CTRL_REG_REG_ADDR,
			&data);
	if (res) {
		LOG_ERR("Failed to read IRQ_LED_CONTROL, %i", res);
		return res;
	}
	data |= 0xF;
	res = mdio_write(cfg->mdio, WOLL_CTRL_REG_PHY_ADDR, WOLL_CTRL_REG_REG_ADDR, data);
	res = mdio_write(cfg->mdio, DM8806_WOLL_CTRL_REG_PHY_ADDR, DM8806_WOLL_CTRL_REG_REG_ADDR,
			 data);
	if (res) {
		LOG_ERR("Failed to read IRQ_LED_CONTROL, %i", res);
		return res;
@@ -162,7 +364,7 @@ int phy_dm8806_init_interrupt(const struct device *dev)
	}
	drv_data->dev = dev;
	res = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to configure gpio interrupt pin for PHY DM886 as an input");
		return res;
	}
@@ -171,7 +373,7 @@ int phy_dm8806_init_interrupt(const struct device *dev)
	 */
	gpio_init_callback(&drv_data->gpio_cb, phy_dm8806_gpio_callback, BIT(cfg->gpio_int.pin));
	res = gpio_add_callback(cfg->gpio_int.port, &drv_data->gpio_cb);
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to set PHY DM886 gpio callback");
		return res;
	}
@@ -183,7 +385,7 @@ int phy_dm8806_init_interrupt(const struct device *dev)
	 * level 1 asserted by Davicom PHY DM8806 interrupt Pin
	 */
	gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE);
	if (res != 0) {
	if (res < 0) {
		LOG_ERR("Failed to configure PHY DM886 gpio interrupt pin trigger for "
			"active edge");
		return res;
@@ -207,31 +409,31 @@ static int phy_dm8806_init(const struct device *dev)
		return ret;
	}

	ret = mdio_read(cfg->mdio, PHY_ADDRESS_18H, PORT5_MAC_CONTROL, &val);
	ret = mdio_read(cfg->mdio, DM8806_PHY_ADDRESS_18H, DM8806_PORT5_MAC_CONTROL, &val);
	if (ret) {
		LOG_ERR("Failed to read PORT5_MAC_CONTROL: %i", ret);
		return ret;
	}

	/* Activate default working mode*/
	val |= (P5_50M_INT_CLK_SOURCE | P5_50M_CLK_OUT_ENABLE | P5_EN_FORCE);
	val &= (P5_SPEED_100M | P5_FULL_DUPLEX | P5_FORCE_LINK_ON);
	val |= (DM8806_P5_50M_INT_CLK_SOURCE | DM8806_P5_50M_CLK_OUT_ENABLE | DM8806_P5_EN_FORCE);
	val &= (DM8806_P5_SPEED_100M | DM8806_P5_FULL_DUPLEX | DM8806_P5_FORCE_LINK_ON);

	ret = mdio_write(cfg->mdio, PHY_ADDRESS_18H, PORT5_MAC_CONTROL, val);
	ret = mdio_write(cfg->mdio, DM8806_PHY_ADDRESS_18H, DM8806_PORT5_MAC_CONTROL, val);
	if (ret) {
		LOG_ERR("Failed to write PORT5_MAC_CONTROL, %i", ret);
		return ret;
	}

	ret = mdio_read(cfg->mdio, PHY_ADDRESS_18H, IRQ_LED_CONTROL, &val);
	ret = mdio_read(cfg->mdio, DM8806_PHY_ADDRESS_18H, DM8806_IRQ_LED_CONTROL, &val);
	if (ret) {
		LOG_ERR("Failed to read IRQ_LED_CONTROL, %i", ret);
		return ret;
	}

	/* Activate LED blinking mode indicator mode 0. */
	val &= LED_MODE_0;
	ret = mdio_write(cfg->mdio, PHY_ADDRESS_18H, IRQ_LED_CONTROL, val);
	val &= DM8806_LED_MODE_0;
	ret = mdio_write(cfg->mdio, DM8806_PHY_ADDRESS_18H, DM8806_IRQ_LED_CONTROL, val);
	if (ret) {
		LOG_ERR("Failed to write IRQ_LED_CONTROL, %i", ret);
		return ret;
@@ -262,7 +464,7 @@ static int phy_dm8806_get_link_state(const struct device *dev, struct phy_link_s
	}
#endif
	/* Read data from Switch Per-Port Register. */
	ret = mdio_read(cfg->mdio, cfg->switch_addr, PORTX_SWITCH_STATUS, &data);
	ret = phy_dm8806_read_reg(dev, cfg->switch_addr, DM8806_PORTX_SWITCH_STATUS, &data);
	if (ret) {
		LOG_ERR("Failes to read data drom DM8806 Switch Per-Port Registers area");
		return ret;
@@ -271,18 +473,18 @@ static int phy_dm8806_get_link_state(const struct device *dev, struct phy_link_s
	 * Status Data Register
	 */
	status = data;
	status >>= SPEED_AND_DUPLEX_OFFSET;
	switch (status & SPEED_AND_DUPLEX_MASK) {
	case SPEED_10MBPS_HALF_DUPLEX:
	status >>= DM8806_SPEED_AND_DUPLEX_OFFSET;
	switch (status & DM8806_SPEED_AND_DUPLEX_MASK) {
	case DM8806_SPEED_10MBPS_HALF_DUPLEX:
		state->speed = LINK_HALF_10BASE_T;
		break;
	case SPEED_10MBPS_FULL_DUPLEX:
	case DM8806_SPEED_10MBPS_FULL_DUPLEX:
		state->speed = LINK_FULL_10BASE_T;
		break;
	case SPEED_100MBPS_HALF_DUPLEX:
	case DM8806_SPEED_100MBPS_HALF_DUPLEX:
		state->speed = LINK_HALF_100BASE_T;
		break;
	case SPEED_100MBPS_FULL_DUPLEX:
	case DM8806_SPEED_100MBPS_FULL_DUPLEX:
		state->speed = LINK_FULL_100BASE_T;
		break;
	}
@@ -290,7 +492,7 @@ static int phy_dm8806_get_link_state(const struct device *dev, struct phy_link_s
	 * Register
	 */
	status = data;
	if (status & LINK_STATUS_MASK) {
	if (status & DM8806_LINK_STATUS_MASK) {
		state->is_up = true;
	} else {
		state->is_up = false;
@@ -308,31 +510,31 @@ static int phy_dm8806_cfg_link(const struct device *dev, enum phy_link_speed adv
	req_speed = adv_speeds;
	switch (req_speed) {
	case LINK_HALF_10BASE_T:
		req_speed = MODE_10_BASET_HALF_DUPLEX;
		req_speed = DM8806_MODE_10_BASET_HALF_DUPLEX;
		break;

	case LINK_FULL_10BASE_T:
		req_speed = MODE_10_BASET_FULL_DUPLEX;
		req_speed = DM8806_MODE_10_BASET_FULL_DUPLEX;
		break;

	case LINK_HALF_100BASE_T:
		req_speed = MODE_100_BASET_HALF_DUPLEX;
		req_speed = DM8806_MODE_100_BASET_HALF_DUPLEX;
		break;

	case LINK_FULL_100BASE_T:
		req_speed = MODE_100_BASET_FULL_DUPLEX;
		req_speed = DM8806_MODE_100_BASET_FULL_DUPLEX;
		break;
	}

	/* Power down */
	ret = mdio_read(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, &data);
	ret = phy_dm8806_read_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, &data);
	if (ret) {
		LOG_ERR("Failes to read data drom DM8806");
		return ret;
	}
	k_busy_wait(500);
	data |= POWER_DOWN;
	ret = mdio_write(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, data);
	data |= DM8806_POWER_DOWN;
	ret = phy_dm8806_write_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, data);
	if (ret) {
		LOG_ERR("Failed to write data to DM8806");
		return ret;
@@ -340,14 +542,14 @@ static int phy_dm8806_cfg_link(const struct device *dev, enum phy_link_speed adv
	k_busy_wait(500);

	/* Turn off the auto-negotiation process. */
	ret = mdio_read(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, &data);
	ret = phy_dm8806_read_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, &data);
	if (ret) {
		LOG_ERR("Failed to write data to DM8806");
		return ret;
	}
	k_busy_wait(500);
	data &= ~(AUTO_NEGOTIATION);
	ret = mdio_write(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, data);
	data &= ~(DM8806_AUTO_NEGOTIATION);
	ret = phy_dm8806_write_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, data);
	if (ret) {
		LOG_ERR("Failed to write data to DM8806");
		return ret;
@@ -355,15 +557,15 @@ static int phy_dm8806_cfg_link(const struct device *dev, enum phy_link_speed adv
	k_busy_wait(500);

	/* Change the link speed. */
	ret = mdio_read(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, &data);
	ret = phy_dm8806_read_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, &data);
	if (ret) {
		LOG_ERR("Failed to read data from DM8806");
		return ret;
	}
	k_busy_wait(500);
	data &= ~(LINK_SPEED | DUPLEX_MODE);
	data &= ~(DM8806_LINK_SPEED | DM8806_DUPLEX_MODE);
	data |= req_speed;
	ret = mdio_write(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, data);
	ret = phy_dm8806_write_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, data);
	if (ret) {
		LOG_ERR("Failed to write data to DM8806");
		return ret;
@@ -371,20 +573,20 @@ static int phy_dm8806_cfg_link(const struct device *dev, enum phy_link_speed adv
	k_busy_wait(500);

	/* Power up ethernet port*/
	ret = mdio_read(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, &data);
	ret = phy_dm8806_read_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, &data);
	if (ret) {
		LOG_ERR("Failes to read data drom DM8806");
		return ret;
	}
	k_busy_wait(500);
	data &= ~(POWER_DOWN);
	ret = mdio_write(cfg->mdio, cfg->phy_addr, PORTX_PHY_CONTROL_REGISTER, data);
	data &= ~(DM8806_POWER_DOWN);
	ret = phy_dm8806_write_reg(dev, cfg->phy_addr, DM8806_PORTX_PHY_CONTROL_REGISTER, data);
	if (ret) {
		LOG_ERR("Failed to write data to DM8806");
		return ret;
	}
	k_busy_wait(500);
	return -ENOTSUP;
	return ret;
}

static int phy_dm8806_reg_read(const struct device *dev, uint16_t reg_addr, uint32_t *data)
@@ -420,14 +622,14 @@ static int phy_dm8806_link_cb_set(const struct device *dev, phy_callback_t cb, v
	const struct phy_dm8806_config *cfg = dev->config;

	res = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE);
	if (res != 0) {
	if (res < 0) {
		LOG_WRN("Failed to disable DM8806 interrupt: %i", res);
		return res;
	}
	data->link_speed_chenge_cb = cb;
	data->cb_data = user_data;
	gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_EDGE_TO_ACTIVE);
	if (res != 0) {
	if (res < 0) {
		LOG_WRN("Failed to enable DM8806 interrupt: %i", res);
		return res;
	}
+85 −58

File changed.

Preview size limit exceeded, changes collapsed.