^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (C) 2016 Broadcom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * modify it under the terms of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * published by the Free Software Foundation version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define BLK_ADDR_REG_OFFSET 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PLL_AFE1_100MHZ_BLK 0x2100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PLL_CLK_AMP_OFFSET 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PLL_CLK_AMP_2P05V 0x2b18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int ns2_pci_phy_init(struct phy *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct mdio_device *mdiodev = phy_get_drvdata(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* select the AFE 100MHz block page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* set the 100 MHz reference clock amplitude to 2.05 v */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) rc = mdiobus_write(mdiodev->bus, mdiodev->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dev_err(&mdiodev->dev, "Error %d writing to phy\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const struct phy_ops ns2_pci_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .init = ns2_pci_phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct device *dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct phy_provider *provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (IS_ERR(phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) dev_err(dev, "failed to create Phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) phy_set_drvdata(phy, mdiodev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) provider = devm_of_phy_provider_register(&phy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) of_phy_simple_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (IS_ERR(provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dev_err(dev, "failed to register Phy provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return PTR_ERR(provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dev_info(dev, "%s PHY registered\n", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const struct of_device_id ns2_pci_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { .compatible = "brcm,ns2-pcie-phy", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct mdio_driver ns2_pci_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .mdiodrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .name = "phy-bcm-ns2-pci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .of_match_table = ns2_pci_phy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .probe = ns2_pci_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mdio_module_driver(ns2_pci_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) MODULE_AUTHOR("Broadcom");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) MODULE_ALIAS("platform:phy-bcm-ns2-pci");