static int lan966x_sd6g40_reg_cfg()

in microchip/lan966x_serdes.c [169:281]


static int lan966x_sd6g40_reg_cfg(struct serdes_macro *macro,
				  struct lan966x_sd6g40_setup *res_struct,
				  u32 idx)
{
	u32 value;

	/* Note: SerDes HSIO is configured in 1G_LAN mode */
	lan_rmw(HSIO_SD_CFG_LANE_10BIT_SEL_SET(res_struct->lane_10bit_sel) |
		HSIO_SD_CFG_RX_RATE_SET(res_struct->rx_rate) |
		HSIO_SD_CFG_TX_RATE_SET(res_struct->tx_rate) |
		HSIO_SD_CFG_TX_INVERT_SET(res_struct->tx_invert) |
		HSIO_SD_CFG_RX_INVERT_SET(res_struct->rx_invert) |
		HSIO_SD_CFG_LANE_LOOPBK_EN_SET(res_struct->lane_loopbk_en) |
		HSIO_SD_CFG_RX_RESET_SET(0) |
		HSIO_SD_CFG_TX_RESET_SET(0),
		HSIO_SD_CFG_LANE_10BIT_SEL |
		HSIO_SD_CFG_RX_RATE |
		HSIO_SD_CFG_TX_RATE |
		HSIO_SD_CFG_TX_INVERT |
		HSIO_SD_CFG_RX_INVERT |
		HSIO_SD_CFG_LANE_LOOPBK_EN |
		HSIO_SD_CFG_RX_RESET |
		HSIO_SD_CFG_TX_RESET,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	lan_rmw(HSIO_MPLL_CFG_MPLL_MULTIPLIER_SET(res_struct->mpll_multiplier) |
		HSIO_MPLL_CFG_REF_CLKDIV2_SET(res_struct->ref_clkdiv2),
		HSIO_MPLL_CFG_MPLL_MULTIPLIER |
		HSIO_MPLL_CFG_REF_CLKDIV2,
		macro->ctrl->regs, HSIO_MPLL_CFG(idx));

	lan_rmw(HSIO_SD_CFG_RX_TERM_EN_SET(res_struct->rx_term_en),
		HSIO_SD_CFG_RX_TERM_EN,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	lan_rmw(HSIO_MPLL_CFG_REF_SSP_EN_SET(1),
		HSIO_MPLL_CFG_REF_SSP_EN,
		macro->ctrl->regs, HSIO_MPLL_CFG(idx));

	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);

	lan_rmw(HSIO_SD_CFG_PHY_RESET_SET(0),
		HSIO_SD_CFG_PHY_RESET,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);

	lan_rmw(HSIO_MPLL_CFG_MPLL_EN_SET(1),
		HSIO_MPLL_CFG_MPLL_EN,
		macro->ctrl->regs, HSIO_MPLL_CFG(idx));

	usleep_range(7 * USEC_PER_MSEC, 8 * USEC_PER_MSEC);

	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
	value = HSIO_SD_STAT_MPLL_STATE_GET(value);
	if (value != 0x1) {
		dev_err(macro->ctrl->dev,
			"Unexpected sd_sd_stat[%u] mpll_state was 0x1 but is 0x%x\n",
			idx, value);
		return -EIO;
	}

	lan_rmw(HSIO_SD_CFG_TX_CM_EN_SET(1),
		HSIO_SD_CFG_TX_CM_EN,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);

	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
	value = HSIO_SD_STAT_TX_CM_STATE_GET(value);
	if (value != 0x1) {
		dev_err(macro->ctrl->dev,
			"Unexpected sd_sd_stat[%u] tx_cm_state was 0x1 but is 0x%x\n",
			idx, value);
		return -EIO;
	}

	lan_rmw(HSIO_SD_CFG_RX_PLL_EN_SET(1) |
		HSIO_SD_CFG_TX_EN_SET(1),
		HSIO_SD_CFG_RX_PLL_EN |
		HSIO_SD_CFG_TX_EN,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);

	/* Waiting for serdes 0 rx DPLL to lock...  */
	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
	value = HSIO_SD_STAT_RX_PLL_STATE_GET(value);
	if (value != 0x1) {
		dev_err(macro->ctrl->dev,
			"Unexpected sd_sd_stat[%u] rx_pll_state was 0x1 but is 0x%x\n",
			idx, value);
		return -EIO;
	}

	/* Waiting for serdes 0 tx operational...  */
	value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx)));
	value = HSIO_SD_STAT_TX_STATE_GET(value);
	if (value != 0x1) {
		dev_err(macro->ctrl->dev,
			"Unexpected sd_sd_stat[%u] tx_state was 0x1 but is 0x%x\n",
			idx, value);
		return -EIO;
	}

	lan_rmw(HSIO_SD_CFG_TX_DATA_EN_SET(1) |
		HSIO_SD_CFG_RX_DATA_EN_SET(1),
		HSIO_SD_CFG_TX_DATA_EN |
		HSIO_SD_CFG_RX_DATA_EN,
		macro->ctrl->regs, HSIO_SD_CFG(idx));

	return 0;
}