phy-pxa-usb.c (9817B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 Marvell International Ltd. All rights reserved. 4 * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk> 5 */ 6 7#include <dt-bindings/phy/phy.h> 8#include <linux/clk.h> 9#include <linux/delay.h> 10#include <linux/io.h> 11#include <linux/module.h> 12#include <linux/of_address.h> 13#include <linux/phy/phy.h> 14#include <linux/platform_device.h> 15 16/* phy regs */ 17#define UTMI_REVISION 0x0 18#define UTMI_CTRL 0x4 19#define UTMI_PLL 0x8 20#define UTMI_TX 0xc 21#define UTMI_RX 0x10 22#define UTMI_IVREF 0x14 23#define UTMI_T0 0x18 24#define UTMI_T1 0x1c 25#define UTMI_T2 0x20 26#define UTMI_T3 0x24 27#define UTMI_T4 0x28 28#define UTMI_T5 0x2c 29#define UTMI_RESERVE 0x30 30#define UTMI_USB_INT 0x34 31#define UTMI_DBG_CTL 0x38 32#define UTMI_OTG_ADDON 0x3c 33 34/* For UTMICTRL Register */ 35#define UTMI_CTRL_USB_CLK_EN (1 << 31) 36/* pxa168 */ 37#define UTMI_CTRL_SUSPEND_SET1 (1 << 30) 38#define UTMI_CTRL_SUSPEND_SET2 (1 << 29) 39#define UTMI_CTRL_RXBUF_PDWN (1 << 24) 40#define UTMI_CTRL_TXBUF_PDWN (1 << 11) 41 42#define UTMI_CTRL_INPKT_DELAY_SHIFT 30 43#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT 28 44#define UTMI_CTRL_PU_REF_SHIFT 20 45#define UTMI_CTRL_ARC_PULLDN_SHIFT 12 46#define UTMI_CTRL_PLL_PWR_UP_SHIFT 1 47#define UTMI_CTRL_PWR_UP_SHIFT 0 48 49/* For UTMI_PLL Register */ 50#define UTMI_PLL_PLLCALI12_SHIFT 29 51#define UTMI_PLL_PLLCALI12_MASK (0x3 << 29) 52 53#define UTMI_PLL_PLLVDD18_SHIFT 27 54#define UTMI_PLL_PLLVDD18_MASK (0x3 << 27) 55 56#define UTMI_PLL_PLLVDD12_SHIFT 25 57#define UTMI_PLL_PLLVDD12_MASK (0x3 << 25) 58 59#define UTMI_PLL_CLK_BLK_EN_SHIFT 24 60#define CLK_BLK_EN (0x1 << 24) 61#define PLL_READY (0x1 << 23) 62#define KVCO_EXT (0x1 << 22) 63#define VCOCAL_START (0x1 << 21) 64 65#define UTMI_PLL_KVCO_SHIFT 15 66#define UTMI_PLL_KVCO_MASK (0x7 << 15) 67 68#define UTMI_PLL_ICP_SHIFT 12 69#define UTMI_PLL_ICP_MASK (0x7 << 12) 70 71#define UTMI_PLL_FBDIV_SHIFT 4 72#define UTMI_PLL_FBDIV_MASK (0xFF << 4) 73 74#define UTMI_PLL_REFDIV_SHIFT 0 75#define UTMI_PLL_REFDIV_MASK (0xF << 0) 76 77/* For UTMI_TX Register */ 78#define UTMI_TX_REG_EXT_FS_RCAL_SHIFT 27 79#define UTMI_TX_REG_EXT_FS_RCAL_MASK (0xf << 27) 80 81#define UTMI_TX_REG_EXT_FS_RCAL_EN_SHIFT 26 82#define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK (0x1 << 26) 83 84#define UTMI_TX_TXVDD12_SHIFT 22 85#define UTMI_TX_TXVDD12_MASK (0x3 << 22) 86 87#define UTMI_TX_CK60_PHSEL_SHIFT 17 88#define UTMI_TX_CK60_PHSEL_MASK (0xf << 17) 89 90#define UTMI_TX_IMPCAL_VTH_SHIFT 14 91#define UTMI_TX_IMPCAL_VTH_MASK (0x7 << 14) 92 93#define REG_RCAL_START (0x1 << 12) 94 95#define UTMI_TX_LOW_VDD_EN_SHIFT 11 96 97#define UTMI_TX_AMP_SHIFT 0 98#define UTMI_TX_AMP_MASK (0x7 << 0) 99 100/* For UTMI_RX Register */ 101#define UTMI_REG_SQ_LENGTH_SHIFT 15 102#define UTMI_REG_SQ_LENGTH_MASK (0x3 << 15) 103 104#define UTMI_RX_SQ_THRESH_SHIFT 4 105#define UTMI_RX_SQ_THRESH_MASK (0xf << 4) 106 107#define UTMI_OTG_ADDON_OTG_ON (1 << 0) 108 109enum pxa_usb_phy_version { 110 PXA_USB_PHY_MMP2, 111 PXA_USB_PHY_PXA910, 112 PXA_USB_PHY_PXA168, 113}; 114 115struct pxa_usb_phy { 116 struct phy *phy; 117 void __iomem *base; 118 enum pxa_usb_phy_version version; 119}; 120 121/***************************************************************************** 122 * The registers read/write routines 123 *****************************************************************************/ 124 125static unsigned int u2o_get(void __iomem *base, unsigned int offset) 126{ 127 return readl_relaxed(base + offset); 128} 129 130static void u2o_set(void __iomem *base, unsigned int offset, 131 unsigned int value) 132{ 133 u32 reg; 134 135 reg = readl_relaxed(base + offset); 136 reg |= value; 137 writel_relaxed(reg, base + offset); 138 readl_relaxed(base + offset); 139} 140 141static void u2o_clear(void __iomem *base, unsigned int offset, 142 unsigned int value) 143{ 144 u32 reg; 145 146 reg = readl_relaxed(base + offset); 147 reg &= ~value; 148 writel_relaxed(reg, base + offset); 149 readl_relaxed(base + offset); 150} 151 152static void u2o_write(void __iomem *base, unsigned int offset, 153 unsigned int value) 154{ 155 writel_relaxed(value, base + offset); 156 readl_relaxed(base + offset); 157} 158 159static int pxa_usb_phy_init(struct phy *phy) 160{ 161 struct pxa_usb_phy *pxa_usb_phy = phy_get_drvdata(phy); 162 void __iomem *base = pxa_usb_phy->base; 163 int loops; 164 165 dev_info(&phy->dev, "initializing Marvell PXA USB PHY"); 166 167 /* Initialize the USB PHY power */ 168 if (pxa_usb_phy->version == PXA_USB_PHY_PXA910) { 169 u2o_set(base, UTMI_CTRL, (1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT) 170 | (1<<UTMI_CTRL_PU_REF_SHIFT)); 171 } 172 173 u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT); 174 u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT); 175 176 /* UTMI_PLL settings */ 177 u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK 178 | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK 179 | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK 180 | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK); 181 182 u2o_set(base, UTMI_PLL, 0xee<<UTMI_PLL_FBDIV_SHIFT 183 | 0xb<<UTMI_PLL_REFDIV_SHIFT | 3<<UTMI_PLL_PLLVDD18_SHIFT 184 | 3<<UTMI_PLL_PLLVDD12_SHIFT | 3<<UTMI_PLL_PLLCALI12_SHIFT 185 | 1<<UTMI_PLL_ICP_SHIFT | 3<<UTMI_PLL_KVCO_SHIFT); 186 187 /* UTMI_TX */ 188 u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK 189 | UTMI_TX_TXVDD12_MASK | UTMI_TX_CK60_PHSEL_MASK 190 | UTMI_TX_IMPCAL_VTH_MASK | UTMI_TX_REG_EXT_FS_RCAL_MASK 191 | UTMI_TX_AMP_MASK); 192 u2o_set(base, UTMI_TX, 3<<UTMI_TX_TXVDD12_SHIFT 193 | 4<<UTMI_TX_CK60_PHSEL_SHIFT | 4<<UTMI_TX_IMPCAL_VTH_SHIFT 194 | 8<<UTMI_TX_REG_EXT_FS_RCAL_SHIFT | 3<<UTMI_TX_AMP_SHIFT); 195 196 /* UTMI_RX */ 197 u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK 198 | UTMI_REG_SQ_LENGTH_MASK); 199 u2o_set(base, UTMI_RX, 7<<UTMI_RX_SQ_THRESH_SHIFT 200 | 2<<UTMI_REG_SQ_LENGTH_SHIFT); 201 202 /* UTMI_IVREF */ 203 if (pxa_usb_phy->version == PXA_USB_PHY_PXA168) { 204 /* 205 * fixing Microsoft Altair board interface with NEC hub issue - 206 * Set UTMI_IVREF from 0x4a3 to 0x4bf 207 */ 208 u2o_write(base, UTMI_IVREF, 0x4bf); 209 } 210 211 /* toggle VCOCAL_START bit of UTMI_PLL */ 212 udelay(200); 213 u2o_set(base, UTMI_PLL, VCOCAL_START); 214 udelay(40); 215 u2o_clear(base, UTMI_PLL, VCOCAL_START); 216 217 /* toggle REG_RCAL_START bit of UTMI_TX */ 218 udelay(400); 219 u2o_set(base, UTMI_TX, REG_RCAL_START); 220 udelay(40); 221 u2o_clear(base, UTMI_TX, REG_RCAL_START); 222 udelay(400); 223 224 /* Make sure PHY PLL is ready */ 225 loops = 0; 226 while ((u2o_get(base, UTMI_PLL) & PLL_READY) == 0) { 227 mdelay(1); 228 loops++; 229 if (loops > 100) { 230 dev_warn(&phy->dev, "calibrate timeout, UTMI_PLL %x\n", 231 u2o_get(base, UTMI_PLL)); 232 break; 233 } 234 } 235 236 if (pxa_usb_phy->version == PXA_USB_PHY_PXA168) { 237 u2o_set(base, UTMI_RESERVE, 1 << 5); 238 /* Turn on UTMI PHY OTG extension */ 239 u2o_write(base, UTMI_OTG_ADDON, 1); 240 } 241 242 return 0; 243 244} 245 246static int pxa_usb_phy_exit(struct phy *phy) 247{ 248 struct pxa_usb_phy *pxa_usb_phy = phy_get_drvdata(phy); 249 void __iomem *base = pxa_usb_phy->base; 250 251 dev_info(&phy->dev, "deinitializing Marvell PXA USB PHY"); 252 253 if (pxa_usb_phy->version == PXA_USB_PHY_PXA168) 254 u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON); 255 256 u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN); 257 u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN); 258 u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN); 259 u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT); 260 u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT); 261 262 return 0; 263} 264 265static const struct phy_ops pxa_usb_phy_ops = { 266 .init = pxa_usb_phy_init, 267 .exit = pxa_usb_phy_exit, 268 .owner = THIS_MODULE, 269}; 270 271static const struct of_device_id pxa_usb_phy_of_match[] = { 272 { 273 .compatible = "marvell,mmp2-usb-phy", 274 .data = (void *)PXA_USB_PHY_MMP2, 275 }, { 276 .compatible = "marvell,pxa910-usb-phy", 277 .data = (void *)PXA_USB_PHY_PXA910, 278 }, { 279 .compatible = "marvell,pxa168-usb-phy", 280 .data = (void *)PXA_USB_PHY_PXA168, 281 }, 282 { }, 283}; 284MODULE_DEVICE_TABLE(of, pxa_usb_phy_of_match); 285 286static int pxa_usb_phy_probe(struct platform_device *pdev) 287{ 288 struct device *dev = &pdev->dev; 289 struct pxa_usb_phy *pxa_usb_phy; 290 struct phy_provider *provider; 291 const struct of_device_id *of_id; 292 293 pxa_usb_phy = devm_kzalloc(dev, sizeof(struct pxa_usb_phy), GFP_KERNEL); 294 if (!pxa_usb_phy) 295 return -ENOMEM; 296 297 of_id = of_match_node(pxa_usb_phy_of_match, dev->of_node); 298 if (of_id) 299 pxa_usb_phy->version = (enum pxa_usb_phy_version)of_id->data; 300 else 301 pxa_usb_phy->version = PXA_USB_PHY_MMP2; 302 303 pxa_usb_phy->base = devm_platform_ioremap_resource(pdev, 0); 304 if (IS_ERR(pxa_usb_phy->base)) { 305 dev_err(dev, "failed to remap PHY regs\n"); 306 return PTR_ERR(pxa_usb_phy->base); 307 } 308 309 pxa_usb_phy->phy = devm_phy_create(dev, NULL, &pxa_usb_phy_ops); 310 if (IS_ERR(pxa_usb_phy->phy)) { 311 dev_err(dev, "failed to create PHY\n"); 312 return PTR_ERR(pxa_usb_phy->phy); 313 } 314 315 phy_set_drvdata(pxa_usb_phy->phy, pxa_usb_phy); 316 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 317 if (IS_ERR(provider)) { 318 dev_err(dev, "failed to register PHY provider\n"); 319 return PTR_ERR(provider); 320 } 321 322 if (!dev->of_node) { 323 phy_create_lookup(pxa_usb_phy->phy, "usb", "mv-udc"); 324 phy_create_lookup(pxa_usb_phy->phy, "usb", "pxa-u2oehci"); 325 phy_create_lookup(pxa_usb_phy->phy, "usb", "mv-otg"); 326 } 327 328 dev_info(dev, "Marvell PXA USB PHY"); 329 return 0; 330} 331 332static struct platform_driver pxa_usb_phy_driver = { 333 .probe = pxa_usb_phy_probe, 334 .driver = { 335 .name = "pxa-usb-phy", 336 .of_match_table = pxa_usb_phy_of_match, 337 }, 338}; 339module_platform_driver(pxa_usb_phy_driver); 340 341MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>"); 342MODULE_DESCRIPTION("Marvell PXA USB PHY Driver"); 343MODULE_LICENSE("GPL v2");