* Broadcom Northstar USB 3.0 PHY Driver
  *
  * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ * Copyright (C) 2016 Broadcom
  *
  * All magic values used for initialization (and related comments) were obtained
  * from Broadcom's SDK:
 
 #define BCM_NS_USB3_MII_MNG_TIMEOUT_US 1000    /* usecs */
 
+#define BCM_NS_USB3_PHY_BASE_ADDR_REG  0x1f
+#define BCM_NS_USB3_PHY_PLL30_BLOCK    0x8000
+#define BCM_NS_USB3_PHY_TX_PMD_BLOCK   0x8040
+#define BCM_NS_USB3_PHY_PIPE_BLOCK     0x8060
+
+/* Registers of PLL30 block */
+#define BCM_NS_USB3_PLL_CONTROL                0x01
+#define BCM_NS_USB3_PLLA_CONTROL0      0x0a
+#define BCM_NS_USB3_PLLA_CONTROL1      0x0b
+
+/* Registers of TX PMD block */
+#define BCM_NS_USB3_TX_PMD_CONTROL1    0x01
+
+/* Registers of PIPE block */
+#define BCM_NS_USB3_LFPS_CMP           0x02
+#define BCM_NS_USB3_LFPS_DEGLITCH      0x03
+
 enum bcm_ns_family {
        BCM_NS_UNKNOWN,
        BCM_NS_AX,
                                    usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US));
 }
 
-static int bcm_ns_usb3_mii_mng_write32(struct bcm_ns_usb3 *usb3, u32 value)
+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);
                return err;
        }
 
-       writel(value, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
+       /* 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 0;
 }
        udelay(2);
 
        /* USB3 PLL Block */
-       err = bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8000);
+       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
        if (err < 0)
                return err;
 
        /* Assert Ana_Pllseq start */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x58061000);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000);
 
        /* Assert CML Divider ratio to 26 */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x582a6400);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
 
        /* Asserting PLL Reset */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x582ec000);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000);
 
        /* Deaaserting PLL Reset */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x582e8000);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000);
 
        /* Waiting MII Mgt interface idle */
        bcm_ns_usb3_mii_mng_wait_idle(usb3);
        writel(0, usb3->dmp + BCMA_RESET_CTL);
 
        /* PLL frequency monitor enable */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x58069000);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000);
 
        /* PIPE Block */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8060);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_PIPE_BLOCK);
 
        /* CMPMAX & CMPMINTH setting */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x580af30d);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d);
 
        /* DEGLITCH MIN & MAX setting */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x580e6302);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302);
 
        /* TXPMD block */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8040);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
 
        /* Enabling SSC */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x58061003);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 
        /* Waiting MII Mgt interface idle */
        bcm_ns_usb3_mii_mng_wait_idle(usb3);
        udelay(2);
 
        /* PLL30 block */
-       err = bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8000);
+       err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                        BCM_NS_USB3_PHY_PLL30_BLOCK);
        if (err < 0)
                return err;
 
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x582a6400);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400);
 
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x587e80e0);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0);
 
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x580a009c);
+       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c);
 
        /* Enable SSC */
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8040);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG,
+                                  BCM_NS_USB3_PHY_TX_PMD_BLOCK);
 
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x580a21d3);
+       bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3);
 
-       bcm_ns_usb3_mii_mng_write32(usb3, 0x58061003);
+       bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003);
 
        /* Waiting MII Mgt interface idle */
        bcm_ns_usb3_mii_mng_wait_idle(usb3);