1 /* 2 * IMG Pistachio USB PHY driver 3 * 4 * Copyright (C) 2015 Google, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/delay.h> 13 #include <linux/io.h> 14 #include <linux/kernel.h> 15 #include <linux/mfd/syscon.h> 16 #include <linux/module.h> 17 #include <linux/of.h> 18 #include <linux/phy/phy.h> 19 #include <linux/platform_device.h> 20 #include <linux/regmap.h> 21 22 #include <dt-bindings/phy/phy-pistachio-usb.h> 23 24 #define USB_PHY_CONTROL1 0x04 25 #define USB_PHY_CONTROL1_FSEL_SHIFT 2 26 #define USB_PHY_CONTROL1_FSEL_MASK 0x7 27 28 #define USB_PHY_STRAP_CONTROL 0x10 29 #define USB_PHY_STRAP_CONTROL_REFCLK_SHIFT 4 30 #define USB_PHY_STRAP_CONTROL_REFCLK_MASK 0x3 31 32 #define USB_PHY_STATUS 0x14 33 #define USB_PHY_STATUS_RX_PHY_CLK BIT(9) 34 #define USB_PHY_STATUS_RX_UTMI_CLK BIT(8) 35 #define USB_PHY_STATUS_VBUS_FAULT BIT(7) 36 37 struct pistachio_usb_phy { 38 struct device *dev; 39 struct regmap *cr_top; 40 struct clk *phy_clk; 41 unsigned int refclk; 42 }; 43 44 static const unsigned long fsel_rate_map[] = { 45 9600000, 46 10000000, 47 12000000, 48 19200000, 49 20000000, 50 24000000, 51 0, 52 50000000, 53 }; 54 55 static int pistachio_usb_phy_power_on(struct phy *phy) 56 { 57 struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy); 58 unsigned long timeout, rate; 59 unsigned int i; 60 int ret; 61 62 ret = clk_prepare_enable(p_phy->phy_clk); 63 if (ret < 0) { 64 dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret); 65 return ret; 66 } 67 68 regmap_update_bits(p_phy->cr_top, USB_PHY_STRAP_CONTROL, 69 USB_PHY_STRAP_CONTROL_REFCLK_MASK << 70 USB_PHY_STRAP_CONTROL_REFCLK_SHIFT, 71 p_phy->refclk << USB_PHY_STRAP_CONTROL_REFCLK_SHIFT); 72 73 rate = clk_get_rate(p_phy->phy_clk); 74 if (p_phy->refclk == REFCLK_XO_CRYSTAL && rate != 12000000) { 75 dev_err(p_phy->dev, "Unsupported rate for XO crystal: %ld\n", 76 rate); 77 ret = -EINVAL; 78 goto disable_clk; 79 } 80 81 for (i = 0; i < ARRAY_SIZE(fsel_rate_map); i++) { 82 if (rate == fsel_rate_map[i]) 83 break; 84 } 85 if (i == ARRAY_SIZE(fsel_rate_map)) { 86 dev_err(p_phy->dev, "Unsupported clock rate: %lu\n", rate); 87 ret = -EINVAL; 88 goto disable_clk; 89 } 90 91 regmap_update_bits(p_phy->cr_top, USB_PHY_CONTROL1, 92 USB_PHY_CONTROL1_FSEL_MASK << 93 USB_PHY_CONTROL1_FSEL_SHIFT, 94 i << USB_PHY_CONTROL1_FSEL_SHIFT); 95 96 timeout = jiffies + msecs_to_jiffies(200); 97 while (time_before(jiffies, timeout)) { 98 unsigned int val; 99 100 regmap_read(p_phy->cr_top, USB_PHY_STATUS, &val); 101 if (val & USB_PHY_STATUS_VBUS_FAULT) { 102 dev_err(p_phy->dev, "VBUS fault detected\n"); 103 ret = -EIO; 104 goto disable_clk; 105 } 106 if ((val & USB_PHY_STATUS_RX_PHY_CLK) && 107 (val & USB_PHY_STATUS_RX_UTMI_CLK)) 108 return 0; 109 usleep_range(1000, 1500); 110 } 111 112 dev_err(p_phy->dev, "Timed out waiting for PHY to power on\n"); 113 ret = -ETIMEDOUT; 114 115 disable_clk: 116 clk_disable_unprepare(p_phy->phy_clk); 117 return ret; 118 } 119 120 static int pistachio_usb_phy_power_off(struct phy *phy) 121 { 122 struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy); 123 124 clk_disable_unprepare(p_phy->phy_clk); 125 126 return 0; 127 } 128 129 static const struct phy_ops pistachio_usb_phy_ops = { 130 .power_on = pistachio_usb_phy_power_on, 131 .power_off = pistachio_usb_phy_power_off, 132 .owner = THIS_MODULE, 133 }; 134 135 static int pistachio_usb_phy_probe(struct platform_device *pdev) 136 { 137 struct pistachio_usb_phy *p_phy; 138 struct phy_provider *provider; 139 struct phy *phy; 140 int ret; 141 142 p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL); 143 if (!p_phy) 144 return -ENOMEM; 145 p_phy->dev = &pdev->dev; 146 platform_set_drvdata(pdev, p_phy); 147 148 p_phy->cr_top = syscon_regmap_lookup_by_phandle(p_phy->dev->of_node, 149 "img,cr-top"); 150 if (IS_ERR(p_phy->cr_top)) { 151 dev_err(p_phy->dev, "Failed to get CR_TOP registers: %ld\n", 152 PTR_ERR(p_phy->cr_top)); 153 return PTR_ERR(p_phy->cr_top); 154 } 155 156 p_phy->phy_clk = devm_clk_get(p_phy->dev, "usb_phy"); 157 if (IS_ERR(p_phy->phy_clk)) { 158 dev_err(p_phy->dev, "Failed to get usb_phy clock: %ld\n", 159 PTR_ERR(p_phy->phy_clk)); 160 return PTR_ERR(p_phy->phy_clk); 161 } 162 163 ret = of_property_read_u32(p_phy->dev->of_node, "img,refclk", 164 &p_phy->refclk); 165 if (ret < 0) { 166 dev_err(p_phy->dev, "No reference clock selector specified\n"); 167 return ret; 168 } 169 170 phy = devm_phy_create(p_phy->dev, NULL, &pistachio_usb_phy_ops); 171 if (IS_ERR(phy)) { 172 dev_err(p_phy->dev, "Failed to create PHY: %ld\n", 173 PTR_ERR(phy)); 174 return PTR_ERR(phy); 175 } 176 phy_set_drvdata(phy, p_phy); 177 178 provider = devm_of_phy_provider_register(p_phy->dev, 179 of_phy_simple_xlate); 180 if (IS_ERR(provider)) { 181 dev_err(p_phy->dev, "Failed to register PHY provider: %ld\n", 182 PTR_ERR(provider)); 183 return PTR_ERR(provider); 184 } 185 186 return 0; 187 } 188 189 static const struct of_device_id pistachio_usb_phy_of_match[] = { 190 { .compatible = "img,pistachio-usb-phy", }, 191 { }, 192 }; 193 MODULE_DEVICE_TABLE(of, pistachio_usb_phy_of_match); 194 195 static struct platform_driver pistachio_usb_phy_driver = { 196 .probe = pistachio_usb_phy_probe, 197 .driver = { 198 .name = "pistachio-usb-phy", 199 .of_match_table = pistachio_usb_phy_of_match, 200 }, 201 }; 202 module_platform_driver(pistachio_usb_phy_driver); 203 204 MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>"); 205 MODULE_DESCRIPTION("IMG Pistachio USB2.0 PHY driver"); 206 MODULE_LICENSE("GPL v2"); 207