Lines Matching +full:cpsw +full:- +full:switch

1 // SPDX-License-Identifier: GPL-2.0
3 * Texas Instruments CPSW Port's PHY Interface Mode selection Driver
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
7 * Based on cpsw-phy-sel.c driver created by Mugunthan V N <mugunthanvnm@ti.com>
31 #define PHY_GMII_PORT(n) BIT((n) - 1)
74 const struct phy_gmii_sel_soc_data *soc_data = if_phy->priv->soc_data; in phy_gmii_sel_mode()
75 struct device *dev = if_phy->priv->dev; in phy_gmii_sel_mode()
81 return -EINVAL; in phy_gmii_sel_mode()
83 switch (submode) { in phy_gmii_sel_mode()
105 if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_QSGMII))) in phy_gmii_sel_mode()
107 if (if_phy->priv->qsgmii_main_ports & BIT(if_phy->id - 1)) in phy_gmii_sel_mode()
114 if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII))) in phy_gmii_sel_mode()
121 if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII))) in phy_gmii_sel_mode()
132 if (soc_data->features & BIT(PHY_GMII_SEL_FIXED_TX_DELAY) && in phy_gmii_sel_mode()
134 return -EINVAL; in phy_gmii_sel_mode()
136 if_phy->phy_if_mode = submode; in phy_gmii_sel_mode()
139 __func__, if_phy->id, submode, rgmii_id, in phy_gmii_sel_mode()
140 if_phy->rmii_clock_external); in phy_gmii_sel_mode()
142 regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE]; in phy_gmii_sel_mode()
145 dev_err(dev, "port%u: set mode fail %d", if_phy->id, ret); in phy_gmii_sel_mode()
149 if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE) && in phy_gmii_sel_mode()
150 if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]) { in phy_gmii_sel_mode()
151 regfield = if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]; in phy_gmii_sel_mode()
157 if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && in phy_gmii_sel_mode()
158 if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]) { in phy_gmii_sel_mode()
159 regfield = if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]; in phy_gmii_sel_mode()
161 if_phy->rmii_clock_external); in phy_gmii_sel_mode()
168 if_phy->id, phy_modes(submode)); in phy_gmii_sel_mode()
169 return -EINVAL; in phy_gmii_sel_mode()
291 .compatible = "ti,am3352-phy-gmii-sel",
295 .compatible = "ti,dra7xx-phy-gmii-sel",
299 .compatible = "ti,am43xx-phy-gmii-sel",
303 .compatible = "ti,dm814-phy-gmii-sel",
307 .compatible = "ti,am654-phy-gmii-sel",
311 .compatible = "ti,j7200-cpsw5g-phy-gmii-sel",
315 .compatible = "ti,j721e-cpsw9g-phy-gmii-sel",
319 .compatible = "ti,j784s4-cpsw9g-phy-gmii-sel",
335 int phy_id = args->args[0]; in phy_gmii_sel_of_xlate()
337 if (args->args_count < 1) in phy_gmii_sel_of_xlate()
338 return ERR_PTR(-EINVAL); in phy_gmii_sel_of_xlate()
339 if (!priv || !priv->if_phys) in phy_gmii_sel_of_xlate()
340 return ERR_PTR(-ENODEV); in phy_gmii_sel_of_xlate()
341 if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && in phy_gmii_sel_of_xlate()
342 args->args_count < 2) in phy_gmii_sel_of_xlate()
343 return ERR_PTR(-EINVAL); in phy_gmii_sel_of_xlate()
344 if (phy_id > priv->num_ports) in phy_gmii_sel_of_xlate()
345 return ERR_PTR(-EINVAL); in phy_gmii_sel_of_xlate()
346 if (phy_id != priv->if_phys[phy_id - 1].id) in phy_gmii_sel_of_xlate()
347 return ERR_PTR(-EINVAL); in phy_gmii_sel_of_xlate()
349 phy_id--; in phy_gmii_sel_of_xlate()
350 if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) in phy_gmii_sel_of_xlate()
351 priv->if_phys[phy_id].rmii_clock_external = args->args[1]; in phy_gmii_sel_of_xlate()
353 priv->if_phys[phy_id].id, args->args[1]); in phy_gmii_sel_of_xlate()
355 return priv->if_phys[phy_id].if_phy; in phy_gmii_sel_of_xlate()
361 const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; in phy_gmii_init_phy()
362 struct device *dev = priv->dev; in phy_gmii_init_phy()
368 if_phy->id = port; in phy_gmii_init_phy()
369 if_phy->priv = priv; in phy_gmii_init_phy()
371 fields = soc_data->regfields[port - 1]; in phy_gmii_init_phy()
373 field.reg += priv->reg_offset; in phy_gmii_init_phy()
377 regfield = devm_regmap_field_alloc(dev, priv->regmap, field); in phy_gmii_init_phy()
380 if_phy->fields[PHY_GMII_SEL_PORT_MODE] = regfield; in phy_gmii_init_phy()
383 field.reg += priv->reg_offset; in phy_gmii_init_phy()
384 if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE)) { in phy_gmii_init_phy()
386 priv->regmap, in phy_gmii_init_phy()
390 if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE] = regfield; in phy_gmii_init_phy()
396 field.reg += priv->reg_offset; in phy_gmii_init_phy()
397 if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) { in phy_gmii_init_phy()
399 priv->regmap, in phy_gmii_init_phy()
403 if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = regfield; in phy_gmii_init_phy()
408 if_phy->if_phy = devm_phy_create(dev, in phy_gmii_init_phy()
409 priv->dev->of_node, in phy_gmii_init_phy()
411 if (IS_ERR(if_phy->if_phy)) { in phy_gmii_init_phy()
412 ret = PTR_ERR(if_phy->if_phy); in phy_gmii_init_phy()
416 phy_set_drvdata(if_phy->if_phy, if_phy); in phy_gmii_init_phy()
423 const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; in phy_gmii_sel_init_ports()
425 struct device *dev = priv->dev; in phy_gmii_sel_init_ports()
428 if (soc_data->use_of_data) { in phy_gmii_sel_init_ports()
432 offset = of_get_address(dev->of_node, 0, &size, NULL); in phy_gmii_sel_init_ports()
434 return -EINVAL; in phy_gmii_sel_init_ports()
435 priv->num_ports = size / sizeof(u32); in phy_gmii_sel_init_ports()
436 if (!priv->num_ports) in phy_gmii_sel_init_ports()
437 return -EINVAL; in phy_gmii_sel_init_ports()
438 if (!priv->no_offset) in phy_gmii_sel_init_ports()
439 priv->reg_offset = __be32_to_cpu(*offset); in phy_gmii_sel_init_ports()
442 if_phys = devm_kcalloc(dev, priv->num_ports, in phy_gmii_sel_init_ports()
445 return -ENOMEM; in phy_gmii_sel_init_ports()
446 dev_dbg(dev, "%s %d\n", __func__, priv->num_ports); in phy_gmii_sel_init_ports()
448 for (i = 0; i < priv->num_ports; i++) { in phy_gmii_sel_init_ports()
454 priv->if_phys = if_phys; in phy_gmii_sel_init_ports()
466 struct device *dev = &pdev->dev; in phy_gmii_sel_probe()
468 struct device_node *node = dev->of_node; in phy_gmii_sel_probe()
475 of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node); in phy_gmii_sel_probe()
477 return -EINVAL; in phy_gmii_sel_probe()
479 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in phy_gmii_sel_probe()
481 return -ENOMEM; in phy_gmii_sel_probe()
483 priv->dev = &pdev->dev; in phy_gmii_sel_probe()
484 priv->soc_data = of_id->data; in phy_gmii_sel_probe()
485 soc_data = priv->soc_data; in phy_gmii_sel_probe()
486 priv->num_ports = priv->soc_data->num_ports; in phy_gmii_sel_probe()
487 priv->qsgmii_main_ports = 0; in phy_gmii_sel_probe()
491 * QSGMII main ports from the "ti,qsgmii-main-ports" property from in phy_gmii_sel_probe()
492 * the device-tree node. in phy_gmii_sel_probe()
494 for (i = 0; i < soc_data->num_qsgmii_main_ports; i++) { in phy_gmii_sel_probe()
495 of_property_read_u32_index(node, "ti,qsgmii-main-ports", i, &main_ports); in phy_gmii_sel_probe()
499 if (main_ports < 1 || main_ports > soc_data->num_ports) { in phy_gmii_sel_probe()
501 return -EINVAL; in phy_gmii_sel_probe()
503 priv->qsgmii_main_ports |= PHY_GMII_PORT(main_ports); in phy_gmii_sel_probe()
506 priv->regmap = syscon_node_to_regmap(node->parent); in phy_gmii_sel_probe()
507 if (IS_ERR(priv->regmap)) { in phy_gmii_sel_probe()
515 priv->regmap = regmap_init_mmio(dev, base, &phy_gmii_sel_regmap_cfg); in phy_gmii_sel_probe()
516 if (IS_ERR(priv->regmap)) in phy_gmii_sel_probe()
517 return dev_err_probe(dev, PTR_ERR(priv->regmap), in phy_gmii_sel_probe()
519 priv->no_offset = true; in phy_gmii_sel_probe()
526 dev_set_drvdata(&pdev->dev, priv); in phy_gmii_sel_probe()
528 priv->phy_provider = in phy_gmii_sel_probe()
531 if (IS_ERR(priv->phy_provider)) in phy_gmii_sel_probe()
532 return dev_err_probe(dev, PTR_ERR(priv->phy_provider), in phy_gmii_sel_probe()
541 struct phy_gmii_sel_phy_priv *if_phys = priv->if_phys; in phy_gmii_sel_resume_noirq()
544 for (i = 0; i < priv->num_ports; i++) { in phy_gmii_sel_resume_noirq()
550 if_phys[i].if_phy->id, ret); in phy_gmii_sel_resume_noirq()
564 .name = "phy-gmii-sel",
573 MODULE_DESCRIPTION("TI CPSW Port's PHY Interface Mode selection Driver");