linux/drivers/usb/phy/phy-keystone.c
<<
>>
Prefs
   1/*
   2 * phy-keystone - USB PHY, talking to dwc3 controller in Keystone.
   3 *
   4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * Author: WingMan Kwok <w-kwok2@ti.com>
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/usb/usb_phy_generic.h>
  22#include <linux/io.h>
  23#include <linux/of.h>
  24
  25#include "phy-generic.h"
  26
  27/* USB PHY control register offsets */
  28#define USB_PHY_CTL_UTMI                0x0000
  29#define USB_PHY_CTL_PIPE                0x0004
  30#define USB_PHY_CTL_PARAM_1             0x0008
  31#define USB_PHY_CTL_PARAM_2             0x000c
  32#define USB_PHY_CTL_CLOCK               0x0010
  33#define USB_PHY_CTL_PLL                 0x0014
  34
  35#define PHY_REF_SSP_EN                  BIT(29)
  36
  37struct keystone_usbphy {
  38        struct usb_phy_generic  usb_phy_gen;
  39        void __iomem                    *phy_ctrl;
  40};
  41
  42static inline u32 keystone_usbphy_readl(void __iomem *base, u32 offset)
  43{
  44        return readl(base + offset);
  45}
  46
  47static inline void keystone_usbphy_writel(void __iomem *base,
  48                                          u32 offset, u32 value)
  49{
  50        writel(value, base + offset);
  51}
  52
  53static int keystone_usbphy_init(struct usb_phy *phy)
  54{
  55        struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
  56        u32 val;
  57
  58        val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
  59        keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
  60                                val | PHY_REF_SSP_EN);
  61        return 0;
  62}
  63
  64static void keystone_usbphy_shutdown(struct usb_phy *phy)
  65{
  66        struct keystone_usbphy *k_phy = dev_get_drvdata(phy->dev);
  67        u32 val;
  68
  69        val  = keystone_usbphy_readl(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK);
  70        keystone_usbphy_writel(k_phy->phy_ctrl, USB_PHY_CTL_CLOCK,
  71                                val &= ~PHY_REF_SSP_EN);
  72}
  73
  74static int keystone_usbphy_probe(struct platform_device *pdev)
  75{
  76        struct device           *dev = &pdev->dev;
  77        struct keystone_usbphy  *k_phy;
  78        struct resource         *res;
  79        int ret;
  80
  81        k_phy = devm_kzalloc(dev, sizeof(*k_phy), GFP_KERNEL);
  82        if (!k_phy)
  83                return -ENOMEM;
  84
  85        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  86        k_phy->phy_ctrl = devm_ioremap_resource(dev, res);
  87        if (IS_ERR(k_phy->phy_ctrl))
  88                return PTR_ERR(k_phy->phy_ctrl);
  89
  90        ret = usb_phy_gen_create_phy(dev, &k_phy->usb_phy_gen, NULL);
  91        if (ret)
  92                return ret;
  93
  94        k_phy->usb_phy_gen.phy.init = keystone_usbphy_init;
  95        k_phy->usb_phy_gen.phy.shutdown = keystone_usbphy_shutdown;
  96
  97        platform_set_drvdata(pdev, k_phy);
  98
  99        return usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
 100}
 101
 102static int keystone_usbphy_remove(struct platform_device *pdev)
 103{
 104        struct keystone_usbphy *k_phy = platform_get_drvdata(pdev);
 105
 106        usb_remove_phy(&k_phy->usb_phy_gen.phy);
 107
 108        return 0;
 109}
 110
 111static const struct of_device_id keystone_usbphy_ids[] = {
 112        { .compatible = "ti,keystone-usbphy" },
 113        { }
 114};
 115MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
 116
 117static struct platform_driver keystone_usbphy_driver = {
 118        .probe          = keystone_usbphy_probe,
 119        .remove         = keystone_usbphy_remove,
 120        .driver         = {
 121                .name   = "keystone-usbphy",
 122                .of_match_table = keystone_usbphy_ids,
 123        },
 124};
 125
 126module_platform_driver(keystone_usbphy_driver);
 127
 128MODULE_ALIAS("platform:keystone-usbphy");
 129MODULE_AUTHOR("Texas Instruments Inc.");
 130MODULE_DESCRIPTION("Keystone USB phy driver");
 131MODULE_LICENSE("GPL v2");
 132