diff options
Diffstat (limited to 'drivers/phy/broadcom/phy-bcm-ns-usb2.c')
-rw-r--r-- | drivers/phy/broadcom/phy-bcm-ns-usb2.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c index 4b015b8a71c3..6a36e187d100 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c @@ -9,17 +9,23 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include <linux/slab.h> struct bcm_ns_usb2 { struct device *dev; struct clk *ref_clk; struct phy *phy; + struct regmap *clkset; + void __iomem *base; + + /* Deprecated binding */ void __iomem *dmu; }; @@ -27,7 +33,6 @@ static int bcm_ns_usb2_phy_init(struct phy *phy) { struct bcm_ns_usb2 *usb2 = phy_get_drvdata(phy); struct device *dev = usb2->dev; - void __iomem *dmu = usb2->dmu; u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv; int err = 0; @@ -44,7 +49,10 @@ static int bcm_ns_usb2_phy_init(struct phy *phy) goto err_clk_off; } - usb2ctl = readl(dmu + BCMA_DMU_CRU_USB2_CONTROL); + if (usb2->base) + usb2ctl = readl(usb2->base); + else + usb2ctl = readl(usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL); if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) { usb_pll_pdiv = usb2ctl; @@ -58,15 +66,24 @@ static int bcm_ns_usb2_phy_init(struct phy *phy) usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate; /* Unlock DMU PLL settings with some magic value */ - writel(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY); + if (usb2->clkset) + regmap_write(usb2->clkset, 0, 0x0000ea68); + else + writel(0x0000ea68, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY); /* Write USB 2.0 PLL control setting */ usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK; usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT; - writel(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL); + if (usb2->base) + writel(usb2ctl, usb2->base); + else + writel(usb2ctl, usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL); /* Lock DMU PLL settings */ - writel(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY); + if (usb2->clkset) + regmap_write(usb2->clkset, 0, 0x00000000); + else + writel(0x00000000, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY); err_clk_off: clk_disable_unprepare(usb2->ref_clk); @@ -90,15 +107,32 @@ static int bcm_ns_usb2_probe(struct platform_device *pdev) return -ENOMEM; usb2->dev = dev; - usb2->dmu = devm_platform_ioremap_resource_byname(pdev, "dmu"); - if (IS_ERR(usb2->dmu)) { - dev_err(dev, "Failed to map DMU regs\n"); - return PTR_ERR(usb2->dmu); + if (of_find_property(dev->of_node, "brcm,syscon-clkset", NULL)) { + usb2->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(usb2->base)) { + dev_err(dev, "Failed to map control reg\n"); + return PTR_ERR(usb2->base); + } + + usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node, + "brcm,syscon-clkset"); + if (IS_ERR(usb2->clkset)) { + dev_err(dev, "Failed to lookup clkset regmap\n"); + return PTR_ERR(usb2->clkset); + } + } else { + usb2->dmu = devm_platform_ioremap_resource_byname(pdev, "dmu"); + if (IS_ERR(usb2->dmu)) { + dev_err(dev, "Failed to map DMU regs\n"); + return PTR_ERR(usb2->dmu); + } + + dev_warn(dev, "using deprecated DT binding\n"); } usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk"); if (IS_ERR(usb2->ref_clk)) { - dev_err(dev, "Clock not defined\n"); + dev_err_probe(dev, PTR_ERR(usb2->ref_clk), "failed to get ref clk\n"); return PTR_ERR(usb2->ref_clk); } |