linux/drivers/phy/phy-bcm-kona-usb2.c
<<
>>
Prefs
   1/*
   2 * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
   3 *
   4 * Copyright (C) 2013 Linaro Limited
   5 * Matt Porter <mporter@linaro.org>
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/clk.h>
  18#include <linux/delay.h>
  19#include <linux/err.h>
  20#include <linux/io.h>
  21#include <linux/module.h>
  22#include <linux/of.h>
  23#include <linux/phy/phy.h>
  24#include <linux/platform_device.h>
  25
  26#define OTGCTL                  (0)
  27#define OTGCTL_OTGSTAT2         BIT(31)
  28#define OTGCTL_OTGSTAT1         BIT(30)
  29#define OTGCTL_PRST_N_SW        BIT(11)
  30#define OTGCTL_HRESET_N         BIT(10)
  31#define OTGCTL_UTMI_LINE_STATE1 BIT(9)
  32#define OTGCTL_UTMI_LINE_STATE0 BIT(8)
  33
  34#define P1CTL                   (8)
  35#define P1CTL_SOFT_RESET        BIT(1)
  36#define P1CTL_NON_DRIVING       BIT(0)
  37
  38struct bcm_kona_usb {
  39        void __iomem *regs;
  40};
  41
  42static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
  43{
  44        u32 val;
  45
  46        val = readl(phy->regs + OTGCTL);
  47        if (on) {
  48                /* Configure and power PHY */
  49                val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
  50                         OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
  51                val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
  52        } else {
  53                val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
  54        }
  55        writel(val, phy->regs + OTGCTL);
  56}
  57
  58static int bcm_kona_usb_phy_init(struct phy *gphy)
  59{
  60        struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
  61        u32 val;
  62
  63        /* Soft reset PHY */
  64        val = readl(phy->regs + P1CTL);
  65        val &= ~P1CTL_NON_DRIVING;
  66        val |= P1CTL_SOFT_RESET;
  67        writel(val, phy->regs + P1CTL);
  68        writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
  69        /* Reset needs to be asserted for 2ms */
  70        mdelay(2);
  71        writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
  72
  73        return 0;
  74}
  75
  76static int bcm_kona_usb_phy_power_on(struct phy *gphy)
  77{
  78        struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
  79
  80        bcm_kona_usb_phy_power(phy, 1);
  81
  82        return 0;
  83}
  84
  85static int bcm_kona_usb_phy_power_off(struct phy *gphy)
  86{
  87        struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
  88
  89        bcm_kona_usb_phy_power(phy, 0);
  90
  91        return 0;
  92}
  93
  94static const struct phy_ops ops = {
  95        .init           = bcm_kona_usb_phy_init,
  96        .power_on       = bcm_kona_usb_phy_power_on,
  97        .power_off      = bcm_kona_usb_phy_power_off,
  98        .owner          = THIS_MODULE,
  99};
 100
 101static int bcm_kona_usb2_probe(struct platform_device *pdev)
 102{
 103        struct device *dev = &pdev->dev;
 104        struct bcm_kona_usb *phy;
 105        struct resource *res;
 106        struct phy *gphy;
 107        struct phy_provider *phy_provider;
 108
 109        phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 110        if (!phy)
 111                return -ENOMEM;
 112
 113        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 114        phy->regs = devm_ioremap_resource(&pdev->dev, res);
 115        if (IS_ERR(phy->regs))
 116                return PTR_ERR(phy->regs);
 117
 118        platform_set_drvdata(pdev, phy);
 119
 120        gphy = devm_phy_create(dev, NULL, &ops);
 121        if (IS_ERR(gphy))
 122                return PTR_ERR(gphy);
 123
 124        /* The Kona PHY supports an 8-bit wide UTMI interface */
 125        phy_set_bus_width(gphy, 8);
 126
 127        phy_set_drvdata(gphy, phy);
 128
 129        phy_provider = devm_of_phy_provider_register(dev,
 130                        of_phy_simple_xlate);
 131
 132        return PTR_ERR_OR_ZERO(phy_provider);
 133}
 134
 135static const struct of_device_id bcm_kona_usb2_dt_ids[] = {
 136        { .compatible = "brcm,kona-usb2-phy" },
 137        { /* sentinel */ }
 138};
 139
 140MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
 141
 142static struct platform_driver bcm_kona_usb2_driver = {
 143        .probe          = bcm_kona_usb2_probe,
 144        .driver         = {
 145                .name   = "bcm-kona-usb2",
 146                .of_match_table = bcm_kona_usb2_dt_ids,
 147        },
 148};
 149
 150module_platform_driver(bcm_kona_usb2_driver);
 151
 152MODULE_ALIAS("platform:bcm-kona-usb2");
 153MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
 154MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
 155MODULE_LICENSE("GPL v2");
 156