1/* 2 * Renesas R-Car USB phy driver 3 * 4 * Copyright (C) 2012-2013 Renesas Solutions Corp. 5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * Copyright (C) 2013 Cogent Embedded, Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/delay.h> 14#include <linux/io.h> 15#include <linux/usb/otg.h> 16#include <linux/platform_device.h> 17#include <linux/spinlock.h> 18#include <linux/module.h> 19#include <linux/platform_data/usb-rcar-phy.h> 20 21/* REGS block */ 22#define USBPCTRL0 0x00 23#define USBPCTRL1 0x04 24#define USBST 0x08 25#define USBEH0 0x0C 26#define USBOH0 0x1C 27#define USBCTL0 0x58 28 29/* High-speed signal quality characteristic control registers (R8A7778 only) */ 30#define HSQCTL1 0x24 31#define HSQCTL2 0x28 32 33/* USBPCTRL0 */ 34#define OVC2 (1 << 10) /* (R8A7779 only) */ 35 /* Switches the OVC input pin for port 2: */ 36 /* 1: USB_OVC2, 0: OVC2 */ 37#define OVC1_VBUS1 (1 << 9) /* Switches the OVC input pin for port 1: */ 38 /* 1: USB_OVC1, 0: OVC1/VBUS1 */ 39 /* Function mode: set to 0 */ 40#define OVC0 (1 << 8) /* Switches the OVC input pin for port 0: */ 41 /* 1: USB_OVC0 pin, 0: OVC0 */ 42#define OVC2_ACT (1 << 6) /* (R8A7779 only) */ 43 /* Host mode: OVC2 polarity: */ 44 /* 1: active-high, 0: active-low */ 45#define PENC (1 << 4) /* Function mode: output level of PENC1 pin: */ 46 /* 1: high, 0: low */ 47#define OVC0_ACT (1 << 3) /* Host mode: OVC0 polarity: */ 48 /* 1: active-high, 0: active-low */ 49#define OVC1_ACT (1 << 1) /* Host mode: OVC1 polarity: */ 50 /* 1: active-high, 0: active-low */ 51 /* Function mode: be sure to set to 1 */ 52#define PORT1 (1 << 0) /* Selects port 1 mode: */ 53 /* 1: function, 0: host */ 54/* USBPCTRL1 */ 55#define PHY_RST (1 << 2) 56#define PLL_ENB (1 << 1) 57#define PHY_ENB (1 << 0) 58 59/* USBST */ 60#define ST_ACT (1 << 31) 61#define ST_PLL (1 << 30) 62 63struct rcar_usb_phy_priv { 64 struct usb_phy phy; 65 spinlock_t lock; 66 67 void __iomem *reg0; 68 void __iomem *reg1; 69 int counter; 70}; 71 72#define usb_phy_to_priv(p) container_of(p, struct rcar_usb_phy_priv, phy) 73 74 75/* 76 * USB initial/install operation. 77 * 78 * This function setup USB phy. 79 * The used value and setting order came from 80 * [USB :: Initial setting] on datasheet. 81 */ 82static int rcar_usb_phy_init(struct usb_phy *phy) 83{ 84 struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); 85 struct device *dev = phy->dev; 86 struct rcar_phy_platform_data *pdata = dev_get_platdata(dev); 87 void __iomem *reg0 = priv->reg0; 88 void __iomem *reg1 = priv->reg1; 89 static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT }; 90 int i; 91 u32 val; 92 unsigned long flags; 93 94 spin_lock_irqsave(&priv->lock, flags); 95 if (priv->counter++ == 0) { 96 97 /* 98 * USB phy start-up 99 */ 100 101 /* (1) USB-PHY standby release */ 102 iowrite32(PHY_ENB, (reg0 + USBPCTRL1)); 103 104 /* (2) start USB-PHY internal PLL */ 105 iowrite32(PHY_ENB | PLL_ENB, (reg0 + USBPCTRL1)); 106 107 /* (3) set USB-PHY in accord with the conditions of usage */ 108 if (reg1) { 109 u32 hsqctl1 = pdata->ferrite_bead ? 0x41 : 0; 110 u32 hsqctl2 = pdata->ferrite_bead ? 0x0d : 7; 111 112 iowrite32(hsqctl1, reg1 + HSQCTL1); 113 iowrite32(hsqctl2, reg1 + HSQCTL2); 114 } 115 116 /* (4) USB module status check */ 117 for (i = 0; i < 1024; i++) { 118 udelay(10); 119 val = ioread32(reg0 + USBST); 120 if (val == (ST_ACT | ST_PLL)) 121 break; 122 } 123 124 if (val != (ST_ACT | ST_PLL)) { 125 dev_err(dev, "USB phy not ready\n"); 126 goto phy_init_end; 127 } 128 129 /* (5) USB-PHY reset clear */ 130 iowrite32(PHY_ENB | PLL_ENB | PHY_RST, (reg0 + USBPCTRL1)); 131 132 /* Board specific port settings */ 133 val = 0; 134 if (pdata->port1_func) 135 val |= PORT1; 136 if (pdata->penc1) 137 val |= PENC; 138 for (i = 0; i < 3; i++) { 139 /* OVCn bits follow each other in the right order */ 140 if (pdata->ovc_pin[i].select_3_3v) 141 val |= OVC0 << i; 142 /* OVCn_ACT bits are spaced by irregular intervals */ 143 if (pdata->ovc_pin[i].active_high) 144 val |= ovcn_act[i]; 145 } 146 iowrite32(val, (reg0 + USBPCTRL0)); 147 148 /* 149 * Bus alignment settings 150 */ 151 152 /* (1) EHCI bus alignment (little endian) */ 153 iowrite32(0x00000000, (reg0 + USBEH0)); 154 155 /* (1) OHCI bus alignment (little endian) */ 156 iowrite32(0x00000000, (reg0 + USBOH0)); 157 } 158 159phy_init_end: 160 spin_unlock_irqrestore(&priv->lock, flags); 161 162 return 0; 163} 164 165static void rcar_usb_phy_shutdown(struct usb_phy *phy) 166{ 167 struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); 168 void __iomem *reg0 = priv->reg0; 169 unsigned long flags; 170 171 spin_lock_irqsave(&priv->lock, flags); 172 173 if (priv->counter-- == 1) /* last user */ 174 iowrite32(0x00000000, (reg0 + USBPCTRL1)); 175 176 spin_unlock_irqrestore(&priv->lock, flags); 177} 178 179static int rcar_usb_phy_probe(struct platform_device *pdev) 180{ 181 struct rcar_usb_phy_priv *priv; 182 struct resource *res0, *res1; 183 struct device *dev = &pdev->dev; 184 void __iomem *reg0, *reg1 = NULL; 185 int ret; 186 187 if (!dev_get_platdata(&pdev->dev)) { 188 dev_err(dev, "No platform data\n"); 189 return -EINVAL; 190 } 191 192 res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); 193 reg0 = devm_ioremap_resource(dev, res0); 194 if (IS_ERR(reg0)) 195 return PTR_ERR(reg0); 196 197 res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 198 reg1 = devm_ioremap_resource(dev, res1); 199 if (IS_ERR(reg1)) 200 return PTR_ERR(reg1); 201 202 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 203 if (!priv) 204 return -ENOMEM; 205 206 priv->reg0 = reg0; 207 priv->reg1 = reg1; 208 priv->counter = 0; 209 priv->phy.dev = dev; 210 priv->phy.label = dev_name(dev); 211 priv->phy.init = rcar_usb_phy_init; 212 priv->phy.shutdown = rcar_usb_phy_shutdown; 213 spin_lock_init(&priv->lock); 214 215 ret = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2); 216 if (ret < 0) { 217 dev_err(dev, "usb phy addition error\n"); 218 return ret; 219 } 220 221 platform_set_drvdata(pdev, priv); 222 223 return ret; 224} 225 226static int rcar_usb_phy_remove(struct platform_device *pdev) 227{ 228 struct rcar_usb_phy_priv *priv = platform_get_drvdata(pdev); 229 230 usb_remove_phy(&priv->phy); 231 232 return 0; 233} 234 235static struct platform_driver rcar_usb_phy_driver = { 236 .driver = { 237 .name = "rcar_usb_phy", 238 }, 239 .probe = rcar_usb_phy_probe, 240 .remove = rcar_usb_phy_remove, 241}; 242 243module_platform_driver(rcar_usb_phy_driver); 244 245MODULE_LICENSE("GPL v2"); 246MODULE_DESCRIPTION("Renesas R-Car USB phy"); 247MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 248