1*2aec85b2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*2aec85b2SThomas Gleixner // Copyright (C) 2016 Broadcom
30b56e9a7SVivek Gautam
40b56e9a7SVivek Gautam #include <linux/device.h>
50b56e9a7SVivek Gautam #include <linux/module.h>
60b56e9a7SVivek Gautam #include <linux/of_mdio.h>
70b56e9a7SVivek Gautam #include <linux/mdio.h>
80b56e9a7SVivek Gautam #include <linux/phy.h>
90b56e9a7SVivek Gautam #include <linux/phy/phy.h>
100b56e9a7SVivek Gautam
110b56e9a7SVivek Gautam #define BLK_ADDR_REG_OFFSET 0x1f
120b56e9a7SVivek Gautam #define PLL_AFE1_100MHZ_BLK 0x2100
130b56e9a7SVivek Gautam #define PLL_CLK_AMP_OFFSET 0x03
140b56e9a7SVivek Gautam #define PLL_CLK_AMP_2P05V 0x2b18
150b56e9a7SVivek Gautam
ns2_pci_phy_init(struct phy * p)160b56e9a7SVivek Gautam static int ns2_pci_phy_init(struct phy *p)
170b56e9a7SVivek Gautam {
180b56e9a7SVivek Gautam struct mdio_device *mdiodev = phy_get_drvdata(p);
190b56e9a7SVivek Gautam int rc;
200b56e9a7SVivek Gautam
210b56e9a7SVivek Gautam /* select the AFE 100MHz block page */
2265aa371eSSean Anderson rc = mdiodev_write(mdiodev, BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
230b56e9a7SVivek Gautam if (rc)
240b56e9a7SVivek Gautam goto err;
250b56e9a7SVivek Gautam
260b56e9a7SVivek Gautam /* set the 100 MHz reference clock amplitude to 2.05 v */
2765aa371eSSean Anderson rc = mdiodev_write(mdiodev, PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
280b56e9a7SVivek Gautam if (rc)
290b56e9a7SVivek Gautam goto err;
300b56e9a7SVivek Gautam
310b56e9a7SVivek Gautam return 0;
320b56e9a7SVivek Gautam
330b56e9a7SVivek Gautam err:
340b56e9a7SVivek Gautam dev_err(&mdiodev->dev, "Error %d writing to phy\n", rc);
350b56e9a7SVivek Gautam return rc;
360b56e9a7SVivek Gautam }
370b56e9a7SVivek Gautam
380b56e9a7SVivek Gautam static const struct phy_ops ns2_pci_phy_ops = {
390b56e9a7SVivek Gautam .init = ns2_pci_phy_init,
400b56e9a7SVivek Gautam .owner = THIS_MODULE,
410b56e9a7SVivek Gautam };
420b56e9a7SVivek Gautam
ns2_pci_phy_probe(struct mdio_device * mdiodev)430b56e9a7SVivek Gautam static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
440b56e9a7SVivek Gautam {
450b56e9a7SVivek Gautam struct device *dev = &mdiodev->dev;
460b56e9a7SVivek Gautam struct phy_provider *provider;
470b56e9a7SVivek Gautam struct phy *phy;
480b56e9a7SVivek Gautam
490b56e9a7SVivek Gautam phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
500b56e9a7SVivek Gautam if (IS_ERR(phy)) {
510b56e9a7SVivek Gautam dev_err(dev, "failed to create Phy\n");
520b56e9a7SVivek Gautam return PTR_ERR(phy);
530b56e9a7SVivek Gautam }
540b56e9a7SVivek Gautam
550b56e9a7SVivek Gautam phy_set_drvdata(phy, mdiodev);
560b56e9a7SVivek Gautam
570b56e9a7SVivek Gautam provider = devm_of_phy_provider_register(&phy->dev,
580b56e9a7SVivek Gautam of_phy_simple_xlate);
590b56e9a7SVivek Gautam if (IS_ERR(provider)) {
600b56e9a7SVivek Gautam dev_err(dev, "failed to register Phy provider\n");
610b56e9a7SVivek Gautam return PTR_ERR(provider);
620b56e9a7SVivek Gautam }
630b56e9a7SVivek Gautam
640b56e9a7SVivek Gautam dev_info(dev, "%s PHY registered\n", dev_name(dev));
650b56e9a7SVivek Gautam
660b56e9a7SVivek Gautam return 0;
670b56e9a7SVivek Gautam }
680b56e9a7SVivek Gautam
690b56e9a7SVivek Gautam static const struct of_device_id ns2_pci_phy_of_match[] = {
700b56e9a7SVivek Gautam { .compatible = "brcm,ns2-pcie-phy", },
710b56e9a7SVivek Gautam { /* sentinel */ },
720b56e9a7SVivek Gautam };
730b56e9a7SVivek Gautam MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
740b56e9a7SVivek Gautam
750b56e9a7SVivek Gautam static struct mdio_driver ns2_pci_phy_driver = {
760b56e9a7SVivek Gautam .mdiodrv = {
770b56e9a7SVivek Gautam .driver = {
780b56e9a7SVivek Gautam .name = "phy-bcm-ns2-pci",
790b56e9a7SVivek Gautam .of_match_table = ns2_pci_phy_of_match,
800b56e9a7SVivek Gautam },
810b56e9a7SVivek Gautam },
820b56e9a7SVivek Gautam .probe = ns2_pci_phy_probe,
830b56e9a7SVivek Gautam };
840b56e9a7SVivek Gautam mdio_module_driver(ns2_pci_phy_driver);
850b56e9a7SVivek Gautam
860b56e9a7SVivek Gautam MODULE_AUTHOR("Broadcom");
870b56e9a7SVivek Gautam MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
880b56e9a7SVivek Gautam MODULE_LICENSE("GPL v2");
890b56e9a7SVivek Gautam MODULE_ALIAS("platform:phy-bcm-ns2-pci");
90