Tony Lindgren | 609adde | 2015-03-19 17:08:07 -0700 | [diff] [blame] | 1 | /* |
| 2 | * This program is free software; you can redistribute it and/or |
| 3 | * modify it under the terms of the GNU General Public License as |
| 4 | * published by the Free Software Foundation version 2. |
| 5 | * |
| 6 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any |
| 7 | * kind, whether express or implied; without even the implied warranty |
| 8 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 9 | * GNU General Public License for more details. |
| 10 | */ |
| 11 | |
| 12 | #include <linux/module.h> |
| 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/regmap.h> |
| 15 | |
| 16 | #include <linux/slab.h> |
| 17 | #include <linux/of.h> |
| 18 | #include <linux/io.h> |
| 19 | #include <linux/usb/phy_companion.h> |
| 20 | #include <linux/clk.h> |
| 21 | #include <linux/err.h> |
| 22 | #include <linux/pm_runtime.h> |
| 23 | #include <linux/delay.h> |
| 24 | #include <linux/phy/phy.h> |
| 25 | #include <linux/of_platform.h> |
| 26 | |
| 27 | #include <linux/mfd/syscon.h> |
| 28 | |
| 29 | /* |
| 30 | * TRM has two sets of USB_CTRL registers.. The correct register bits |
| 31 | * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the |
| 32 | * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at |
| 33 | * least dm816x rev c ignores writes to USB_CTRL register, but the TI |
| 34 | * kernel is writing to those so it's possible that later revisions |
| 35 | * have worknig USB_CTRL register. |
| 36 | * |
| 37 | * Also note that At least USB_CTRL register seems to be dm816x specific |
| 38 | * according to the TRM. It's possible that USBPHY_CTRL is more generic, |
| 39 | * but that would have to be checked against the SR70LX documentation |
| 40 | * which does not seem to be publicly available. |
| 41 | * |
| 42 | * Finally, the phy on dm814x and am335x is different from dm816x. |
| 43 | */ |
| 44 | #define DM816X_USB_CTRL_PHYCLKSRC BIT(8) /* 1 = PLL ref clock */ |
| 45 | #define DM816X_USB_CTRL_PHYSLEEP1 BIT(1) /* Enable the first phy */ |
| 46 | #define DM816X_USB_CTRL_PHYSLEEP0 BIT(0) /* Enable the second phy */ |
| 47 | |
| 48 | #define DM816X_USBPHY_CTRL_TXRISETUNE 1 |
| 49 | #define DM816X_USBPHY_CTRL_TXVREFTUNE 0xc |
| 50 | #define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2 |
| 51 | |
| 52 | struct dm816x_usb_phy { |
| 53 | struct regmap *syscon; |
| 54 | struct device *dev; |
| 55 | unsigned int instance; |
| 56 | struct clk *refclk; |
| 57 | struct usb_phy phy; |
| 58 | unsigned int usb_ctrl; /* Shared between phy0 and phy1 */ |
| 59 | unsigned int usbphy_ctrl; |
| 60 | }; |
| 61 | |
| 62 | static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host) |
| 63 | { |
| 64 | otg->host = host; |
| 65 | if (!host) |
| 66 | otg->state = OTG_STATE_UNDEFINED; |
| 67 | |
| 68 | return 0; |
| 69 | } |
| 70 | |
| 71 | static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg, |
| 72 | struct usb_gadget *gadget) |
| 73 | { |
| 74 | otg->gadget = gadget; |
| 75 | if (!gadget) |
| 76 | otg->state = OTG_STATE_UNDEFINED; |
| 77 | |
| 78 | return 0; |
| 79 | } |
| 80 | |
| 81 | static int dm816x_usb_phy_init(struct phy *x) |
| 82 | { |
| 83 | struct dm816x_usb_phy *phy = phy_get_drvdata(x); |
| 84 | unsigned int val; |
| 85 | int error; |
| 86 | |
| 87 | if (clk_get_rate(phy->refclk) != 24000000) |
| 88 | dev_warn(phy->dev, "nonstandard phy refclk\n"); |
| 89 | |
| 90 | /* Set PLL ref clock and put phys to sleep */ |
| 91 | error = regmap_update_bits(phy->syscon, phy->usb_ctrl, |
| 92 | DM816X_USB_CTRL_PHYCLKSRC | |
| 93 | DM816X_USB_CTRL_PHYSLEEP1 | |
| 94 | DM816X_USB_CTRL_PHYSLEEP0, |
| 95 | 0); |
| 96 | regmap_read(phy->syscon, phy->usb_ctrl, &val); |
| 97 | if ((val & 3) != 0) |
| 98 | dev_info(phy->dev, |
| 99 | "Working dm816x USB_CTRL! (0x%08x)\n", |
| 100 | val); |
| 101 | |
| 102 | /* |
| 103 | * TI kernel sets these values for "symmetrical eye diagram and |
| 104 | * better signal quality" so let's assume somebody checked the |
| 105 | * values with a scope and set them here too. |
| 106 | */ |
| 107 | regmap_read(phy->syscon, phy->usbphy_ctrl, &val); |
| 108 | val |= DM816X_USBPHY_CTRL_TXRISETUNE | |
| 109 | DM816X_USBPHY_CTRL_TXVREFTUNE | |
| 110 | DM816X_USBPHY_CTRL_TXPREEMTUNE; |
| 111 | regmap_write(phy->syscon, phy->usbphy_ctrl, val); |
| 112 | |
| 113 | return 0; |
| 114 | } |
| 115 | |
| 116 | static struct phy_ops ops = { |
| 117 | .init = dm816x_usb_phy_init, |
| 118 | .owner = THIS_MODULE, |
| 119 | }; |
| 120 | |
| 121 | static int dm816x_usb_phy_runtime_suspend(struct device *dev) |
| 122 | { |
| 123 | struct dm816x_usb_phy *phy = dev_get_drvdata(dev); |
| 124 | unsigned int mask, val; |
| 125 | int error = 0; |
| 126 | |
| 127 | mask = BIT(phy->instance); |
| 128 | val = ~BIT(phy->instance); |
| 129 | error = regmap_update_bits(phy->syscon, phy->usb_ctrl, |
| 130 | mask, val); |
| 131 | if (error) |
| 132 | dev_err(phy->dev, "phy%i failed to power off\n", |
| 133 | phy->instance); |
| 134 | clk_disable(phy->refclk); |
| 135 | |
| 136 | return 0; |
| 137 | } |
| 138 | |
| 139 | static int dm816x_usb_phy_runtime_resume(struct device *dev) |
| 140 | { |
| 141 | struct dm816x_usb_phy *phy = dev_get_drvdata(dev); |
| 142 | unsigned int mask, val; |
| 143 | int error; |
| 144 | |
| 145 | error = clk_enable(phy->refclk); |
| 146 | if (error) |
| 147 | return error; |
| 148 | |
| 149 | /* |
| 150 | * Note that at least dm816x rev c does not seem to do |
| 151 | * anything with the USB_CTRL register. But let's follow |
| 152 | * what the TI tree is doing in case later revisions use |
| 153 | * USB_CTRL. |
| 154 | */ |
| 155 | mask = BIT(phy->instance); |
| 156 | val = BIT(phy->instance); |
| 157 | error = regmap_update_bits(phy->syscon, phy->usb_ctrl, |
| 158 | mask, val); |
| 159 | if (error) { |
| 160 | dev_err(phy->dev, "phy%i failed to power on\n", |
| 161 | phy->instance); |
| 162 | clk_disable(phy->refclk); |
| 163 | return error; |
| 164 | } |
| 165 | |
| 166 | return 0; |
| 167 | } |
| 168 | |
| 169 | static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops, |
| 170 | dm816x_usb_phy_runtime_suspend, |
| 171 | dm816x_usb_phy_runtime_resume, |
| 172 | NULL); |
| 173 | |
| 174 | #ifdef CONFIG_OF |
| 175 | static const struct of_device_id dm816x_usb_phy_id_table[] = { |
| 176 | { |
| 177 | .compatible = "ti,dm8168-usb-phy", |
| 178 | }, |
| 179 | {}, |
| 180 | }; |
| 181 | MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table); |
| 182 | #endif |
| 183 | |
| 184 | static int dm816x_usb_phy_probe(struct platform_device *pdev) |
| 185 | { |
| 186 | struct dm816x_usb_phy *phy; |
| 187 | struct resource *res; |
| 188 | struct phy *generic_phy; |
| 189 | struct phy_provider *phy_provider; |
| 190 | struct usb_otg *otg; |
| 191 | const struct of_device_id *of_id; |
| 192 | const struct usb_phy_data *phy_data; |
| 193 | int error; |
| 194 | |
| 195 | of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table), |
| 196 | &pdev->dev); |
| 197 | if (!of_id) |
| 198 | return -EINVAL; |
| 199 | |
| 200 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
| 201 | if (!phy) |
| 202 | return -ENOMEM; |
| 203 | |
| 204 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 205 | if (!res) |
| 206 | return -ENOENT; |
| 207 | |
| 208 | phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
| 209 | "syscon"); |
| 210 | if (IS_ERR(phy->syscon)) |
| 211 | return PTR_ERR(phy->syscon); |
| 212 | |
| 213 | /* |
| 214 | * According to sprs614e.pdf, the first usb_ctrl is shared and |
| 215 | * the second instance for usb_ctrl is reserved.. Also the |
| 216 | * register bits are different from earlier TRMs. |
| 217 | */ |
| 218 | phy->usb_ctrl = 0x20; |
| 219 | phy->usbphy_ctrl = (res->start & 0xff) + 4; |
| 220 | if (phy->usbphy_ctrl == 0x2c) |
| 221 | phy->instance = 1; |
| 222 | |
| 223 | phy_data = of_id->data; |
| 224 | |
| 225 | otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); |
| 226 | if (!otg) |
| 227 | return -ENOMEM; |
| 228 | |
| 229 | phy->dev = &pdev->dev; |
| 230 | phy->phy.dev = phy->dev; |
| 231 | phy->phy.label = "dm8168_usb_phy"; |
| 232 | phy->phy.otg = otg; |
| 233 | phy->phy.type = USB_PHY_TYPE_USB2; |
| 234 | otg->set_host = dm816x_usb_phy_set_host; |
| 235 | otg->set_peripheral = dm816x_usb_phy_set_peripheral; |
| 236 | otg->usb_phy = &phy->phy; |
| 237 | |
| 238 | platform_set_drvdata(pdev, phy); |
| 239 | |
| 240 | phy->refclk = devm_clk_get(phy->dev, "refclk"); |
| 241 | if (IS_ERR(phy->refclk)) |
| 242 | return PTR_ERR(phy->refclk); |
| 243 | error = clk_prepare(phy->refclk); |
| 244 | if (error) |
| 245 | return error; |
| 246 | |
| 247 | pm_runtime_enable(phy->dev); |
| 248 | generic_phy = devm_phy_create(phy->dev, NULL, &ops); |
| 249 | if (IS_ERR(generic_phy)) |
| 250 | return PTR_ERR(generic_phy); |
| 251 | |
| 252 | phy_set_drvdata(generic_phy, phy); |
| 253 | |
| 254 | phy_provider = devm_of_phy_provider_register(phy->dev, |
| 255 | of_phy_simple_xlate); |
| 256 | if (IS_ERR(phy_provider)) |
| 257 | return PTR_ERR(phy_provider); |
| 258 | |
| 259 | usb_add_phy_dev(&phy->phy); |
| 260 | |
| 261 | return 0; |
| 262 | } |
| 263 | |
| 264 | static int dm816x_usb_phy_remove(struct platform_device *pdev) |
| 265 | { |
| 266 | struct dm816x_usb_phy *phy = platform_get_drvdata(pdev); |
| 267 | |
| 268 | usb_remove_phy(&phy->phy); |
| 269 | pm_runtime_disable(phy->dev); |
| 270 | clk_unprepare(phy->refclk); |
| 271 | |
| 272 | return 0; |
| 273 | } |
| 274 | |
| 275 | static struct platform_driver dm816x_usb_phy_driver = { |
| 276 | .probe = dm816x_usb_phy_probe, |
| 277 | .remove = dm816x_usb_phy_remove, |
| 278 | .driver = { |
| 279 | .name = "dm816x-usb-phy", |
| 280 | .pm = &dm816x_usb_phy_pm_ops, |
| 281 | .of_match_table = of_match_ptr(dm816x_usb_phy_id_table), |
| 282 | }, |
| 283 | }; |
| 284 | |
| 285 | module_platform_driver(dm816x_usb_phy_driver); |
| 286 | |
| 287 | MODULE_ALIAS("platform:dm816x_usb"); |
| 288 | MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>"); |
| 289 | MODULE_DESCRIPTION("dm816x usb phy driver"); |
| 290 | MODULE_LICENSE("GPL v2"); |