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 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