Lines Matching +full:m +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0-or-later
7 #include <linux/phy.h>
8 #include <linux/phy/phy.h>
11 #include <dt-bindings/phy/phy-lan966x-serdes.h>
38 #define SERDES_MUX_GMII(i, p, m, c) \ argument
39 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_GMII, m, c)
40 #define SERDES_MUX_SGMII(i, p, m, c) \ argument
41 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c)
42 #define SERDES_MUX_QSGMII(i, p, m, c) \ argument
43 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c)
44 #define SERDES_MUX_RGMII(i, p, m, c) \ argument
45 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c), \
46 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_TXID, m, c), \
47 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_RXID, m, c), \
48 SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_ID, m, c)
130 struct phy *phys[SERDES_MAX];
189 lan_rmw(HSIO_SD_CFG_LANE_10BIT_SEL_SET(res_struct->lane_10bit_sel) | in lan966x_sd6g40_reg_cfg()
190 HSIO_SD_CFG_RX_RATE_SET(res_struct->rx_rate) | in lan966x_sd6g40_reg_cfg()
191 HSIO_SD_CFG_TX_RATE_SET(res_struct->tx_rate) | in lan966x_sd6g40_reg_cfg()
192 HSIO_SD_CFG_TX_INVERT_SET(res_struct->tx_invert) | in lan966x_sd6g40_reg_cfg()
193 HSIO_SD_CFG_RX_INVERT_SET(res_struct->rx_invert) | in lan966x_sd6g40_reg_cfg()
194 HSIO_SD_CFG_LANE_LOOPBK_EN_SET(res_struct->lane_loopbk_en) | in lan966x_sd6g40_reg_cfg()
205 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
207 lan_rmw(HSIO_MPLL_CFG_MPLL_MULTIPLIER_SET(res_struct->mpll_multiplier) | in lan966x_sd6g40_reg_cfg()
208 HSIO_MPLL_CFG_REF_CLKDIV2_SET(res_struct->ref_clkdiv2), in lan966x_sd6g40_reg_cfg()
211 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
213 lan_rmw(HSIO_SD_CFG_RX_TERM_EN_SET(res_struct->rx_term_en), in lan966x_sd6g40_reg_cfg()
215 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
219 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
225 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
231 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
235 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
238 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
241 return -EIO; in lan966x_sd6g40_reg_cfg()
246 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
250 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
253 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
256 return -EIO; in lan966x_sd6g40_reg_cfg()
263 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
268 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
271 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
274 return -EIO; in lan966x_sd6g40_reg_cfg()
278 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
281 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
284 return -EIO; in lan966x_sd6g40_reg_cfg()
291 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
303 ret_val->lane_10bit_sel = 0; in lan966x_sd6g40_get_conf_from_mode()
305 ret_val->mpll_multiplier = 40; in lan966x_sd6g40_get_conf_from_mode()
306 ret_val->ref_clkdiv2 = 0x1; in lan966x_sd6g40_get_conf_from_mode()
307 ret_val->tx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
308 ret_val->rx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
310 ret_val->mpll_multiplier = 100; in lan966x_sd6g40_get_conf_from_mode()
311 ret_val->ref_clkdiv2 = 0x0; in lan966x_sd6g40_get_conf_from_mode()
312 ret_val->tx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
313 ret_val->rx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
318 ret_val->lane_10bit_sel = 1; in lan966x_sd6g40_get_conf_from_mode()
320 ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 50 : 40; in lan966x_sd6g40_get_conf_from_mode()
321 ret_val->ref_clkdiv2 = 0x1; in lan966x_sd6g40_get_conf_from_mode()
322 ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
323 ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
325 ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 125 : 100; in lan966x_sd6g40_get_conf_from_mode()
326 ret_val->ref_clkdiv2 = 0x0; in lan966x_sd6g40_get_conf_from_mode()
327 ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
328 ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
333 return -EOPNOTSUPP; in lan966x_sd6g40_get_conf_from_mode()
352 ret_val->lane_10bit_sel = mode_args->lane_10bit_sel; in lan966x_calc_sd6g40_setup_lane()
353 ret_val->rx_rate = mode_args->rx_rate; in lan966x_calc_sd6g40_setup_lane()
354 ret_val->tx_rate = mode_args->tx_rate; in lan966x_calc_sd6g40_setup_lane()
355 ret_val->mpll_multiplier = mode_args->mpll_multiplier; in lan966x_calc_sd6g40_setup_lane()
356 ret_val->ref_clkdiv2 = mode_args->ref_clkdiv2; in lan966x_calc_sd6g40_setup_lane()
357 ret_val->rx_term_en = 0; in lan966x_calc_sd6g40_setup_lane()
360 ret_val->lane_loopbk_en = 1; in lan966x_calc_sd6g40_setup_lane()
362 ret_val->lane_loopbk_en = 0; in lan966x_calc_sd6g40_setup_lane()
364 ret_val->tx_invert = !!config.txinvert; in lan966x_calc_sd6g40_setup_lane()
365 ret_val->rx_invert = !!config.rxinvert; in lan966x_calc_sd6g40_setup_lane()
388 conf.refclk125M = macro->ctrl->ref125; in lan966x_sd6g40_setup()
406 HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 : in lan966x_rgmii_setup()
407 macro->speed == SPEED_100 ? 2 : in lan966x_rgmii_setup()
408 macro->speed == SPEED_10 ? 3 : 0), in lan966x_rgmii_setup()
412 macro->ctrl->regs, HSIO_RGMII_CFG(idx)); in lan966x_rgmii_setup()
427 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); in lan966x_rgmii_setup()
431 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); in lan966x_rgmii_setup()
437 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); in lan966x_rgmii_setup()
441 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); in lan966x_rgmii_setup()
446 static int serdes_set_speed(struct phy *phy, int speed) in serdes_set_speed() argument
448 struct serdes_macro *macro = phy_get_drvdata(phy); in serdes_set_speed()
450 if (!phy_interface_mode_is_rgmii(macro->mode)) in serdes_set_speed()
453 macro->speed = speed; in serdes_set_speed()
454 lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode); in serdes_set_speed()
459 static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) in serdes_set_mode() argument
461 struct serdes_macro *macro = phy_get_drvdata(phy); in serdes_set_mode()
467 return -EOPNOTSUPP; in serdes_set_mode()
470 macro->speed = SPEED_2500; in serdes_set_mode()
472 macro->speed = SPEED_1000; in serdes_set_mode()
482 if (macro->idx != lan966x_serdes_muxes[i].idx || in serdes_set_mode()
485 macro->port != lan966x_serdes_muxes[i].port) in serdes_set_mode()
488 val = readl(macro->ctrl->regs + lan_offset(HSIO_HW_CFG)); in serdes_set_mode()
491 macro->ctrl->regs, HSIO_HW_CFG); in serdes_set_mode()
493 macro->mode = lan966x_serdes_muxes[i].submode; in serdes_set_mode()
495 if (macro->idx < CU_MAX) in serdes_set_mode()
498 if (macro->idx < SERDES6G_MAX) in serdes_set_mode()
500 macro->idx - (CU_MAX + 1), in serdes_set_mode()
501 macro->mode); in serdes_set_mode()
503 if (macro->idx < RGMII_MAX) in serdes_set_mode()
505 macro->idx - (SERDES6G_MAX + 1), in serdes_set_mode()
506 macro->mode); in serdes_set_mode()
508 return -EOPNOTSUPP; in serdes_set_mode()
511 return -EINVAL; in serdes_set_mode()
520 static struct phy *serdes_simple_xlate(struct device *dev, in serdes_simple_xlate()
526 if (args->args_count != 2) in serdes_simple_xlate()
527 return ERR_PTR(-EINVAL); in serdes_simple_xlate()
529 port = args->args[0]; in serdes_simple_xlate()
530 idx = args->args[1]; in serdes_simple_xlate()
533 struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]); in serdes_simple_xlate()
535 if (idx != macro->idx) in serdes_simple_xlate()
538 macro->port = port; in serdes_simple_xlate()
539 return ctrl->phys[i]; in serdes_simple_xlate()
542 return ERR_PTR(-ENODEV); in serdes_simple_xlate()
545 static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy) in serdes_phy_create() argument
549 *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops); in serdes_phy_create()
550 if (IS_ERR(*phy)) in serdes_phy_create()
551 return PTR_ERR(*phy); in serdes_phy_create()
553 macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL); in serdes_phy_create()
555 return -ENOMEM; in serdes_phy_create()
557 macro->idx = idx; in serdes_phy_create()
558 macro->ctrl = ctrl; in serdes_phy_create()
559 macro->port = -1; in serdes_phy_create()
561 phy_set_drvdata(*phy, macro); in serdes_phy_create()
575 ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); in serdes_probe()
577 return -ENOMEM; in serdes_probe()
579 ctrl->dev = &pdev->dev; in serdes_probe()
580 ctrl->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); in serdes_probe()
581 if (IS_ERR(ctrl->regs)) in serdes_probe()
582 return PTR_ERR(ctrl->regs); in serdes_probe()
589 ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]); in serdes_probe()
596 ctrl->ref125 = (val == PLL_CONF_125MHZ || in serdes_probe()
599 dev_set_drvdata(&pdev->dev, ctrl); in serdes_probe()
601 provider = devm_of_phy_provider_register(ctrl->dev, in serdes_probe()
608 { .compatible = "microchip,lan966x-serdes", },
616 .name = "microchip,lan966x-serdes",