Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ulpi.c
Go to the documentation of this file.
1 /*
2  * Generic ULPI USB transceiver support
3  *
4  * Copyright (C) 2009 Daniel Mack <[email protected]>
5  *
6  * Based on sources from
7  *
8  * Sascha Hauer <[email protected]>
9  * Freescale Semiconductors
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
28 #include <linux/export.h>
29 #include <linux/usb.h>
30 #include <linux/usb/otg.h>
31 #include <linux/usb/ulpi.h>
32 
33 
34 struct ulpi_info {
35  unsigned int id;
36  char *name;
37 };
38 
39 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
40 #define ULPI_INFO(_id, _name) \
41  { \
42  .id = (_id), \
43  .name = (_name), \
44  }
45 
46 /* ULPI hardcoded IDs, used for probing */
47 static struct ulpi_info ulpi_ids[] = {
48  ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
49  ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
50 };
51 
52 static int ulpi_set_otg_flags(struct usb_phy *phy)
53 {
54  unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
56 
57  if (phy->flags & ULPI_OTG_ID_PULLUP)
58  flags |= ULPI_OTG_CTRL_ID_PULLUP;
59 
60  /*
61  * ULPI Specification rev.1.1 default
62  * for Dp/DmPulldown is enabled.
63  */
65  flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
66 
68  flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
69 
70  if (phy->flags & ULPI_OTG_EXTVBUSIND)
71  flags |= ULPI_OTG_CTRL_EXTVBUSIND;
72 
73  return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
74 }
75 
76 static int ulpi_set_fc_flags(struct usb_phy *phy)
77 {
78  unsigned int flags = 0;
79 
80  /*
81  * ULPI Specification rev.1.1 default
82  * for XcvrSelect is Full Speed.
83  */
84  if (phy->flags & ULPI_FC_HS)
86  else if (phy->flags & ULPI_FC_LS)
87  flags |= ULPI_FUNC_CTRL_LOW_SPEED;
88  else if (phy->flags & ULPI_FC_FS4LS)
89  flags |= ULPI_FUNC_CTRL_FS4LS;
90  else
92 
93  if (phy->flags & ULPI_FC_TERMSEL)
95 
96  /*
97  * ULPI Specification rev.1.1 default
98  * for OpMode is Normal Operation.
99  */
100  if (phy->flags & ULPI_FC_OP_NODRV)
102  else if (phy->flags & ULPI_FC_OP_DIS_NRZI)
104  else if (phy->flags & ULPI_FC_OP_NSYNC_NEOP)
106  else
108 
109  /*
110  * ULPI Specification rev.1.1 default
111  * for SuspendM is Powered.
112  */
113  flags |= ULPI_FUNC_CTRL_SUSPENDM;
114 
115  return usb_phy_io_write(phy, flags, ULPI_FUNC_CTRL);
116 }
117 
118 static int ulpi_set_ic_flags(struct usb_phy *phy)
119 {
120  unsigned int flags = 0;
121 
122  if (phy->flags & ULPI_IC_AUTORESUME)
123  flags |= ULPI_IFC_CTRL_AUTORESUME;
124 
125  if (phy->flags & ULPI_IC_EXTVBUS_INDINV)
127 
128  if (phy->flags & ULPI_IC_IND_PASSTHRU)
129  flags |= ULPI_IFC_CTRL_PASSTHRU;
130 
131  if (phy->flags & ULPI_IC_PROTECT_DIS)
133 
134  return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
135 }
136 
137 static int ulpi_set_flags(struct usb_phy *phy)
138 {
139  int ret;
140 
141  ret = ulpi_set_otg_flags(phy);
142  if (ret)
143  return ret;
144 
145  ret = ulpi_set_ic_flags(phy);
146  if (ret)
147  return ret;
148 
149  return ulpi_set_fc_flags(phy);
150 }
151 
152 static int ulpi_check_integrity(struct usb_phy *phy)
153 {
154  int ret, i;
155  unsigned int val = 0x55;
156 
157  for (i = 0; i < 2; i++) {
158  ret = usb_phy_io_write(phy, val, ULPI_SCRATCH);
159  if (ret < 0)
160  return ret;
161 
162  ret = usb_phy_io_read(phy, ULPI_SCRATCH);
163  if (ret < 0)
164  return ret;
165 
166  if (ret != val) {
167  pr_err("ULPI integrity check: failed!");
168  return -ENODEV;
169  }
170  val = val << 1;
171  }
172 
173  pr_info("ULPI integrity check: passed.\n");
174 
175  return 0;
176 }
177 
178 static int ulpi_init(struct usb_phy *phy)
179 {
180  int i, vid, pid, ret;
181  u32 ulpi_id = 0;
182 
183  for (i = 0; i < 4; i++) {
184  ret = usb_phy_io_read(phy, ULPI_PRODUCT_ID_HIGH - i);
185  if (ret < 0)
186  return ret;
187  ulpi_id = (ulpi_id << 8) | ret;
188  }
189  vid = ulpi_id & 0xffff;
190  pid = ulpi_id >> 16;
191 
192  pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
193 
194  for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
195  if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
196  pr_info("Found %s ULPI transceiver.\n",
197  ulpi_ids[i].name);
198  break;
199  }
200  }
201 
202  ret = ulpi_check_integrity(phy);
203  if (ret)
204  return ret;
205 
206  return ulpi_set_flags(phy);
207 }
208 
209 static int ulpi_set_host(struct usb_otg *otg, struct usb_bus *host)
210 {
211  struct usb_phy *phy = otg->phy;
212  unsigned int flags = usb_phy_io_read(phy, ULPI_IFC_CTRL);
213 
214  if (!host) {
215  otg->host = NULL;
216  return 0;
217  }
218 
219  otg->host = host;
220 
224 
225  if (phy->flags & ULPI_IC_6PIN_SERIAL)
227  else if (phy->flags & ULPI_IC_3PIN_SERIAL)
229  else if (phy->flags & ULPI_IC_CARKIT)
230  flags |= ULPI_IFC_CTRL_CARKITMODE;
231 
232  return usb_phy_io_write(phy, flags, ULPI_IFC_CTRL);
233 }
234 
235 static int ulpi_set_vbus(struct usb_otg *otg, bool on)
236 {
237  struct usb_phy *phy = otg->phy;
238  unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
239 
241 
242  if (on) {
243  if (phy->flags & ULPI_OTG_DRVVBUS)
244  flags |= ULPI_OTG_CTRL_DRVVBUS;
245 
246  if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
247  flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
248  }
249 
250  return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
251 }
252 
253 struct usb_phy *
255  unsigned int flags)
256 {
257  struct usb_phy *phy;
258  struct usb_otg *otg;
259 
260  phy = kzalloc(sizeof(*phy), GFP_KERNEL);
261  if (!phy)
262  return NULL;
263 
264  otg = kzalloc(sizeof(*otg), GFP_KERNEL);
265  if (!otg) {
266  kfree(phy);
267  return NULL;
268  }
269 
270  phy->label = "ULPI";
271  phy->flags = flags;
272  phy->io_ops = ops;
273  phy->otg = otg;
274  phy->init = ulpi_init;
275 
276  otg->phy = phy;
277  otg->set_host = ulpi_set_host;
278  otg->set_vbus = ulpi_set_vbus;
279 
280  return phy;
281 }
283