summaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2017-06-08 22:04:25 +0200
committerKishon Vijay Abraham I <kishon@ti.com>2017-06-16 13:22:25 +0530
commitb20f506f6c63a3e6ee77aa4d519e4880c8a9d2f4 (patch)
tree59e5f5e39310703a551d3aef39cecdba3468d967 /drivers/phy
parent412512c4f924cb508895237722b36f673f5e113c (diff)
downloadlinux-b20f506f6c63a3e6ee77aa4d519e4880c8a9d2f4.tar.bz2
phy: bcm-ns-usb3: use pointer for PHY writing function
Our current writing function accesses PHY directly bypassing MDIO layer. The aim is to extend this module to also behave as MDIO driver. This will require using different writing function which can be handled cleanly by having an extra pointer like this. Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb3.c98
1 files changed, 56 insertions, 42 deletions
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
index 5e89326886dc..3d0fe5728029 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
@@ -53,6 +53,8 @@ struct bcm_ns_usb3 {
void __iomem *dmp;
void __iomem *ccb_mii;
struct phy *phy;
+
+ int (*phy_write)(struct bcm_ns_usb3 *usb3, u16 reg, u16 value);
};
static const struct of_device_id bcm_ns_usb3_id_table[] = {
@@ -68,51 +70,10 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = {
};
MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
-static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
- u32 mask, u32 value, unsigned long timeout)
-{
- unsigned long deadline = jiffies + timeout;
- u32 val;
-
- do {
- val = readl(addr);
- if ((val & mask) == value)
- return 0;
- cpu_relax();
- udelay(10);
- } while (!time_after_eq(jiffies, deadline));
-
- dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
-
- return -EBUSY;
-}
-
-static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
-{
- return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
- 0x0100, 0x0000,
- usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
-}
-
static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
u16 value)
{
- u32 tmp = 0;
- int err;
-
- err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
- if (err < 0) {
- dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
- return err;
- }
-
- /* TODO: Use a proper MDIO bus layer */
- tmp |= 0x58020000; /* Magic value for MDIO PHY write */
- tmp |= reg << 18;
- tmp |= value;
- writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
-
- return bcm_ns_usb3_mii_mng_wait_idle(usb3);
+ return usb3->phy_write(usb3, reg, value);
}
static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
@@ -233,6 +194,57 @@ static const struct phy_ops ops = {
.owner = THIS_MODULE,
};
+/**************************************************
+ * Platform driver code
+ **************************************************/
+
+static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
+ u32 mask, u32 value, unsigned long timeout)
+{
+ unsigned long deadline = jiffies + timeout;
+ u32 val;
+
+ do {
+ val = readl(addr);
+ if ((val & mask) == value)
+ return 0;
+ cpu_relax();
+ udelay(10);
+ } while (!time_after_eq(jiffies, deadline));
+
+ dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
+
+ return -EBUSY;
+}
+
+static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3)
+{
+ return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL,
+ 0x0100, 0x0000,
+ usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
+}
+
+static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+ u16 value)
+{
+ u32 tmp = 0;
+ int err;
+
+ err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
+ if (err < 0) {
+ dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
+ return err;
+ }
+
+ /* TODO: Use a proper MDIO bus layer */
+ tmp |= 0x58020000; /* Magic value for MDIO PHY write */
+ tmp |= reg << 18;
+ tmp |= value;
+ writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
+
+ return bcm_ns_usb3_mii_mng_wait_idle(usb3);
+}
+
static int bcm_ns_usb3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -266,6 +278,8 @@ static int bcm_ns_usb3_probe(struct platform_device *pdev)
return PTR_ERR(usb3->ccb_mii);
}
+ usb3->phy_write = bcm_ns_usb3_platform_phy_write;
+
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {
dev_err(dev, "Failed to create PHY\n");