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)
128 struct phy *phys[SERDES_MAX];
187 lan_rmw(HSIO_SD_CFG_LANE_10BIT_SEL_SET(res_struct->lane_10bit_sel) | in lan966x_sd6g40_reg_cfg()
188 HSIO_SD_CFG_RX_RATE_SET(res_struct->rx_rate) | in lan966x_sd6g40_reg_cfg()
189 HSIO_SD_CFG_TX_RATE_SET(res_struct->tx_rate) | in lan966x_sd6g40_reg_cfg()
190 HSIO_SD_CFG_TX_INVERT_SET(res_struct->tx_invert) | in lan966x_sd6g40_reg_cfg()
191 HSIO_SD_CFG_RX_INVERT_SET(res_struct->rx_invert) | in lan966x_sd6g40_reg_cfg()
192 HSIO_SD_CFG_LANE_LOOPBK_EN_SET(res_struct->lane_loopbk_en) | in lan966x_sd6g40_reg_cfg()
203 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
205 lan_rmw(HSIO_MPLL_CFG_MPLL_MULTIPLIER_SET(res_struct->mpll_multiplier) | in lan966x_sd6g40_reg_cfg()
206 HSIO_MPLL_CFG_REF_CLKDIV2_SET(res_struct->ref_clkdiv2), in lan966x_sd6g40_reg_cfg()
209 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
211 lan_rmw(HSIO_SD_CFG_RX_TERM_EN_SET(res_struct->rx_term_en), in lan966x_sd6g40_reg_cfg()
213 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
217 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
223 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
229 macro->ctrl->regs, HSIO_MPLL_CFG(idx)); in lan966x_sd6g40_reg_cfg()
233 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
236 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
239 return -EIO; in lan966x_sd6g40_reg_cfg()
244 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
248 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
251 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
254 return -EIO; in lan966x_sd6g40_reg_cfg()
261 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
266 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
269 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
272 return -EIO; in lan966x_sd6g40_reg_cfg()
276 value = readl(macro->ctrl->regs + lan_offset(HSIO_SD_STAT(idx))); in lan966x_sd6g40_reg_cfg()
279 dev_err(macro->ctrl->dev, in lan966x_sd6g40_reg_cfg()
282 return -EIO; in lan966x_sd6g40_reg_cfg()
289 macro->ctrl->regs, HSIO_SD_CFG(idx)); in lan966x_sd6g40_reg_cfg()
301 ret_val->lane_10bit_sel = 0; in lan966x_sd6g40_get_conf_from_mode()
303 ret_val->mpll_multiplier = 40; in lan966x_sd6g40_get_conf_from_mode()
304 ret_val->ref_clkdiv2 = 0x1; in lan966x_sd6g40_get_conf_from_mode()
305 ret_val->tx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
306 ret_val->rx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
308 ret_val->mpll_multiplier = 100; in lan966x_sd6g40_get_conf_from_mode()
309 ret_val->ref_clkdiv2 = 0x0; in lan966x_sd6g40_get_conf_from_mode()
310 ret_val->tx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
311 ret_val->rx_rate = 0x0; in lan966x_sd6g40_get_conf_from_mode()
316 ret_val->lane_10bit_sel = 1; in lan966x_sd6g40_get_conf_from_mode()
318 ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 50 : 40; in lan966x_sd6g40_get_conf_from_mode()
319 ret_val->ref_clkdiv2 = 0x1; in lan966x_sd6g40_get_conf_from_mode()
320 ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
321 ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
323 ret_val->mpll_multiplier = macro->speed == SPEED_2500 ? 125 : 100; in lan966x_sd6g40_get_conf_from_mode()
324 ret_val->ref_clkdiv2 = 0x0; in lan966x_sd6g40_get_conf_from_mode()
325 ret_val->tx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
326 ret_val->rx_rate = macro->speed == SPEED_2500 ? 0x1 : 0x2; in lan966x_sd6g40_get_conf_from_mode()
331 return -EOPNOTSUPP; in lan966x_sd6g40_get_conf_from_mode()
350 ret_val->lane_10bit_sel = mode_args->lane_10bit_sel; in lan966x_calc_sd6g40_setup_lane()
351 ret_val->rx_rate = mode_args->rx_rate; in lan966x_calc_sd6g40_setup_lane()
352 ret_val->tx_rate = mode_args->tx_rate; in lan966x_calc_sd6g40_setup_lane()
353 ret_val->mpll_multiplier = mode_args->mpll_multiplier; in lan966x_calc_sd6g40_setup_lane()
354 ret_val->ref_clkdiv2 = mode_args->ref_clkdiv2; in lan966x_calc_sd6g40_setup_lane()
355 ret_val->rx_term_en = 0; in lan966x_calc_sd6g40_setup_lane()
358 ret_val->lane_loopbk_en = 1; in lan966x_calc_sd6g40_setup_lane()
360 ret_val->lane_loopbk_en = 0; in lan966x_calc_sd6g40_setup_lane()
362 ret_val->tx_invert = !!config.txinvert; in lan966x_calc_sd6g40_setup_lane()
363 ret_val->rx_invert = !!config.rxinvert; in lan966x_calc_sd6g40_setup_lane()
386 conf.refclk125M = macro->ctrl->ref125; in lan966x_sd6g40_setup()
404 HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 : in lan966x_rgmii_setup()
405 macro->speed == SPEED_100 ? 2 : in lan966x_rgmii_setup()
406 macro->speed == SPEED_10 ? 3 : 0), in lan966x_rgmii_setup()
410 macro->ctrl->regs, HSIO_RGMII_CFG(idx)); in lan966x_rgmii_setup()
425 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); in lan966x_rgmii_setup()
429 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2)); in lan966x_rgmii_setup()
435 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); in lan966x_rgmii_setup()
439 macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3)); in lan966x_rgmii_setup()
444 static int serdes_set_speed(struct phy *phy, int speed) in serdes_set_speed() argument
446 struct serdes_macro *macro = phy_get_drvdata(phy); in serdes_set_speed()
448 if (!phy_interface_mode_is_rgmii(macro->mode)) in serdes_set_speed()
451 macro->speed = speed; in serdes_set_speed()
452 lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode); in serdes_set_speed()
457 static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) in serdes_set_mode() argument
459 struct serdes_macro *macro = phy_get_drvdata(phy); in serdes_set_mode()
465 return -EOPNOTSUPP; in serdes_set_mode()
468 macro->speed = SPEED_2500; in serdes_set_mode()
470 macro->speed = SPEED_1000; in serdes_set_mode()
480 if (macro->idx != lan966x_serdes_muxes[i].idx || in serdes_set_mode()
483 macro->port != lan966x_serdes_muxes[i].port) in serdes_set_mode()
486 val = readl(macro->ctrl->regs + lan_offset(HSIO_HW_CFG)); in serdes_set_mode()
489 macro->ctrl->regs, HSIO_HW_CFG); in serdes_set_mode()
491 macro->mode = lan966x_serdes_muxes[i].submode; in serdes_set_mode()
493 if (macro->idx < CU_MAX) in serdes_set_mode()
496 if (macro->idx < SERDES6G_MAX) in serdes_set_mode()
498 macro->idx - (CU_MAX + 1), in serdes_set_mode()
499 macro->mode); in serdes_set_mode()
501 if (macro->idx < RGMII_MAX) in serdes_set_mode()
503 macro->idx - (SERDES6G_MAX + 1), in serdes_set_mode()
504 macro->mode); in serdes_set_mode()
506 return -EOPNOTSUPP; in serdes_set_mode()
509 return -EINVAL; in serdes_set_mode()
518 static struct phy *serdes_simple_xlate(struct device *dev, in serdes_simple_xlate()
524 if (args->args_count != 2) in serdes_simple_xlate()
525 return ERR_PTR(-EINVAL); in serdes_simple_xlate()
527 port = args->args[0]; in serdes_simple_xlate()
528 idx = args->args[1]; in serdes_simple_xlate()
531 struct serdes_macro *macro = phy_get_drvdata(ctrl->phys[i]); in serdes_simple_xlate()
533 if (idx != macro->idx) in serdes_simple_xlate()
536 macro->port = port; in serdes_simple_xlate()
537 return ctrl->phys[i]; in serdes_simple_xlate()
540 return ERR_PTR(-ENODEV); in serdes_simple_xlate()
543 static int serdes_phy_create(struct serdes_ctrl *ctrl, u8 idx, struct phy **phy) in serdes_phy_create() argument
547 *phy = devm_phy_create(ctrl->dev, NULL, &serdes_ops); in serdes_phy_create()
548 if (IS_ERR(*phy)) in serdes_phy_create()
549 return PTR_ERR(*phy); in serdes_phy_create()
551 macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL); in serdes_phy_create()
553 return -ENOMEM; in serdes_phy_create()
555 macro->idx = idx; in serdes_phy_create()
556 macro->ctrl = ctrl; in serdes_phy_create()
557 macro->port = -1; in serdes_phy_create()
559 phy_set_drvdata(*phy, macro); in serdes_phy_create()
573 ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); in serdes_probe()
575 return -ENOMEM; in serdes_probe()
577 ctrl->dev = &pdev->dev; in serdes_probe()
578 ctrl->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); in serdes_probe()
579 if (IS_ERR(ctrl->regs)) in serdes_probe()
580 return PTR_ERR(ctrl->regs); in serdes_probe()
587 ret = serdes_phy_create(ctrl, i, &ctrl->phys[i]); in serdes_probe()
594 ctrl->ref125 = (val == PLL_CONF_125MHZ || in serdes_probe()
597 dev_set_drvdata(&pdev->dev, ctrl); in serdes_probe()
599 provider = devm_of_phy_provider_register(ctrl->dev, in serdes_probe()
606 { .compatible = "microchip,lan966x-serdes", },
614 .name = "microchip,lan966x-serdes",