USB: serial: visor: fix crash on detecting device without write_urbs
[pandora-kernel.git] / drivers / usb / otg / ulpi.c
1 /*
2  * Generic ULPI USB transceiver support
3  *
4  * Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
5  *
6  * Based on sources from
7  *
8  *   Sascha Hauer <s.hauer@pengutronix.de>
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 otg_transceiver *otg)
53 {
54         unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
55                              ULPI_OTG_CTRL_DM_PULLDOWN;
56
57         if (otg->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          */
64         if (otg->flags & ULPI_OTG_DP_PULLDOWN_DIS)
65                 flags &= ~ULPI_OTG_CTRL_DP_PULLDOWN;
66
67         if (otg->flags & ULPI_OTG_DM_PULLDOWN_DIS)
68                 flags &= ~ULPI_OTG_CTRL_DM_PULLDOWN;
69
70         if (otg->flags & ULPI_OTG_EXTVBUSIND)
71                 flags |= ULPI_OTG_CTRL_EXTVBUSIND;
72
73         return otg_io_write(otg, flags, ULPI_OTG_CTRL);
74 }
75
76 static int ulpi_set_fc_flags(struct otg_transceiver *otg)
77 {
78         unsigned int flags = 0;
79
80         /*
81          * ULPI Specification rev.1.1 default
82          * for XcvrSelect is Full Speed.
83          */
84         if (otg->flags & ULPI_FC_HS)
85                 flags |= ULPI_FUNC_CTRL_HIGH_SPEED;
86         else if (otg->flags & ULPI_FC_LS)
87                 flags |= ULPI_FUNC_CTRL_LOW_SPEED;
88         else if (otg->flags & ULPI_FC_FS4LS)
89                 flags |= ULPI_FUNC_CTRL_FS4LS;
90         else
91                 flags |= ULPI_FUNC_CTRL_FULL_SPEED;
92
93         if (otg->flags & ULPI_FC_TERMSEL)
94                 flags |= ULPI_FUNC_CTRL_TERMSELECT;
95
96         /*
97          * ULPI Specification rev.1.1 default
98          * for OpMode is Normal Operation.
99          */
100         if (otg->flags & ULPI_FC_OP_NODRV)
101                 flags |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
102         else if (otg->flags & ULPI_FC_OP_DIS_NRZI)
103                 flags |= ULPI_FUNC_CTRL_OPMODE_DISABLE_NRZI;
104         else if (otg->flags & ULPI_FC_OP_NSYNC_NEOP)
105                 flags |= ULPI_FUNC_CTRL_OPMODE_NOSYNC_NOEOP;
106         else
107                 flags |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
108
109         /*
110          * ULPI Specification rev.1.1 default
111          * for SuspendM is Powered.
112          */
113         flags |= ULPI_FUNC_CTRL_SUSPENDM;
114
115         return otg_io_write(otg, flags, ULPI_FUNC_CTRL);
116 }
117
118 static int ulpi_set_ic_flags(struct otg_transceiver *otg)
119 {
120         unsigned int flags = 0;
121
122         if (otg->flags & ULPI_IC_AUTORESUME)
123                 flags |= ULPI_IFC_CTRL_AUTORESUME;
124
125         if (otg->flags & ULPI_IC_EXTVBUS_INDINV)
126                 flags |= ULPI_IFC_CTRL_EXTERNAL_VBUS;
127
128         if (otg->flags & ULPI_IC_IND_PASSTHRU)
129                 flags |= ULPI_IFC_CTRL_PASSTHRU;
130
131         if (otg->flags & ULPI_IC_PROTECT_DIS)
132                 flags |= ULPI_IFC_CTRL_PROTECT_IFC_DISABLE;
133
134         return otg_io_write(otg, flags, ULPI_IFC_CTRL);
135 }
136
137 static int ulpi_set_flags(struct otg_transceiver *otg)
138 {
139         int ret;
140
141         ret = ulpi_set_otg_flags(otg);
142         if (ret)
143                 return ret;
144
145         ret = ulpi_set_ic_flags(otg);
146         if (ret)
147                 return ret;
148
149         return ulpi_set_fc_flags(otg);
150 }
151
152 static int ulpi_check_integrity(struct otg_transceiver *otg)
153 {
154         int ret, i;
155         unsigned int val = 0x55;
156
157         for (i = 0; i < 2; i++) {
158                 ret = otg_io_write(otg, val, ULPI_SCRATCH);
159                 if (ret < 0)
160                         return ret;
161
162                 ret = otg_io_read(otg, 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 otg_transceiver *otg)
179 {
180         int i, vid, pid, ret;
181         u32 ulpi_id = 0;
182
183         for (i = 0; i < 4; i++) {
184                 ret = otg_io_read(otg, 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(otg);
203         if (ret)
204                 return ret;
205
206         return ulpi_set_flags(otg);
207 }
208
209 static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
210 {
211         unsigned int flags = otg_io_read(otg, ULPI_IFC_CTRL);
212
213         if (!host) {
214                 otg->host = NULL;
215                 return 0;
216         }
217
218         otg->host = host;
219
220         flags &= ~(ULPI_IFC_CTRL_6_PIN_SERIAL_MODE |
221                    ULPI_IFC_CTRL_3_PIN_SERIAL_MODE |
222                    ULPI_IFC_CTRL_CARKITMODE);
223
224         if (otg->flags & ULPI_IC_6PIN_SERIAL)
225                 flags |= ULPI_IFC_CTRL_6_PIN_SERIAL_MODE;
226         else if (otg->flags & ULPI_IC_3PIN_SERIAL)
227                 flags |= ULPI_IFC_CTRL_3_PIN_SERIAL_MODE;
228         else if (otg->flags & ULPI_IC_CARKIT)
229                 flags |= ULPI_IFC_CTRL_CARKITMODE;
230
231         return otg_io_write(otg, flags, ULPI_IFC_CTRL);
232 }
233
234 static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
235 {
236         unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL);
237
238         flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
239
240         if (on) {
241                 if (otg->flags & ULPI_OTG_DRVVBUS)
242                         flags |= ULPI_OTG_CTRL_DRVVBUS;
243
244                 if (otg->flags & ULPI_OTG_DRVVBUS_EXT)
245                         flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
246         }
247
248         return otg_io_write(otg, flags, ULPI_OTG_CTRL);
249 }
250
251 struct otg_transceiver *
252 otg_ulpi_create(struct otg_io_access_ops *ops,
253                 unsigned int flags)
254 {
255         struct otg_transceiver *otg;
256
257         otg = kzalloc(sizeof(*otg), GFP_KERNEL);
258         if (!otg)
259                 return NULL;
260
261         otg->label      = "ULPI";
262         otg->flags      = flags;
263         otg->io_ops     = ops;
264         otg->init       = ulpi_init;
265         otg->set_host   = ulpi_set_host;
266         otg->set_vbus   = ulpi_set_vbus;
267
268         return otg;
269 }
270 EXPORT_SYMBOL_GPL(otg_ulpi_create);
271