1 /*
2 * Intel MID (Langwell/Penwell) USB OTG Transceiver driver
3 * Copyright (C) 2008 - 2010, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20 #ifndef __INTEL_MID_OTG_H
21 #define __INTEL_MID_OTG_H
22
23 #include <linux/pm.h>
24 #include <linux/usb/otg.h>
25 #include <linux/notifier.h>
26
27 struct intel_mid_otg_xceiv;
28
29 /* This is a common data structure for Intel MID platform to
30 * save values of the OTG state machine */
31 struct otg_hsm {
32 /* Input */
33 int a_bus_resume;
34 int a_bus_suspend;
35 int a_conn;
36 int a_sess_vld;
37 int a_srp_det;
38 int a_vbus_vld;
39 int b_bus_resume;
40 int b_bus_suspend;
41 int b_conn;
42 int b_se0_srp;
43 int b_ssend_srp;
44 int b_sess_end;
45 int b_sess_vld;
46 int id;
47 /* id values */
48 #define ID_B 0x05
49 #define ID_A 0x04
50 #define ID_ACA_C 0x03
51 #define ID_ACA_B 0x02
52 #define ID_ACA_A 0x01
53 int power_up;
54 int adp_change;
55 int test_device;
56
57 /* Internal variables */
58 int a_set_b_hnp_en;
59 int b_srp_done;
60 int b_hnp_enable;
61 int hnp_poll_enable;
62
63 /* Timeout indicator for timers */
64 int a_wait_vrise_tmout;
65 int a_wait_bcon_tmout;
66 int a_aidl_bdis_tmout;
67 int a_bidl_adis_tmout;
68 int a_bidl_adis_tmr;
69 int a_wait_vfall_tmout;
70 int b_ase0_brst_tmout;
71 int b_bus_suspend_tmout;
72 int b_srp_init_tmout;
73 int b_srp_fail_tmout;
74 int b_srp_fail_tmr;
75 int b_adp_sense_tmout;
76
77 /* Informative variables */
78 int a_bus_drop;
79 int a_bus_req;
80 int a_clr_err;
81 int b_bus_req;
82 int a_suspend_req;
83 int b_bus_suspend_vld;
84
85 /* Output */
86 int drv_vbus;
87 int loc_conn;
88 int loc_sof;
89
90 /* Others */
91 int vbus_srp_up;
92 };
93
94 /* must provide ULPI access function to read/write registers implemented in
95 * ULPI address space */
96 struct iotg_ulpi_access_ops {
97 int (*read)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 *val);
98 int (*write)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 val);
99 };
100
101 #define OTG_A_DEVICE 0x0
102 #define OTG_B_DEVICE 0x1
103
104 /*
105 * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact
106 * with device and host drivers to implement the USB OTG related feature. More
107 * function members are added based on otg_transceiver data structure for this
108 * purpose.
109 */
110 struct intel_mid_otg_xceiv {
111 struct otg_transceiver otg;
112 struct otg_hsm hsm;
113
114 /* base address */
115 void __iomem *base;
116
117 /* ops to access ulpi */
118 struct iotg_ulpi_access_ops ulpi_ops;
119
120 /* atomic notifier for interrupt context */
121 struct atomic_notifier_head iotg_notifier;
122
123 /* start/stop USB Host function */
124 int (*start_host)(struct intel_mid_otg_xceiv *iotg);
125 int (*stop_host)(struct intel_mid_otg_xceiv *iotg);
126
127 /* start/stop USB Peripheral function */
128 int (*start_peripheral)(struct intel_mid_otg_xceiv *iotg);
129 int (*stop_peripheral)(struct intel_mid_otg_xceiv *iotg);
130
131 /* start/stop ADP sense/probe function */
132 int (*set_adp_probe)(struct intel_mid_otg_xceiv *iotg,
133 bool enabled, int dev);
134 int (*set_adp_sense)(struct intel_mid_otg_xceiv *iotg,
135 bool enabled);
136
137 #ifdef CONFIG_PM
138 /* suspend/resume USB host function */
139 int (*suspend_host)(struct intel_mid_otg_xceiv *iotg,
140 pm_message_t message);
141 int (*resume_host)(struct intel_mid_otg_xceiv *iotg);
142
143 int (*suspend_peripheral)(struct intel_mid_otg_xceiv *iotg,
144 pm_message_t message);
145 int (*resume_peripheral)(struct intel_mid_otg_xceiv *iotg);
146 #endif
147
148 };
149 static inline
otg_to_mid_xceiv(struct otg_transceiver * otg)150 struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg)
151 {
152 return container_of(otg, struct intel_mid_otg_xceiv, otg);
153 }
154
155 #define MID_OTG_NOTIFY_CONNECT 0x0001
156 #define MID_OTG_NOTIFY_DISCONN 0x0002
157 #define MID_OTG_NOTIFY_HSUSPEND 0x0003
158 #define MID_OTG_NOTIFY_HRESUME 0x0004
159 #define MID_OTG_NOTIFY_CSUSPEND 0x0005
160 #define MID_OTG_NOTIFY_CRESUME 0x0006
161 #define MID_OTG_NOTIFY_HOSTADD 0x0007
162 #define MID_OTG_NOTIFY_HOSTREMOVE 0x0008
163 #define MID_OTG_NOTIFY_CLIENTADD 0x0009
164 #define MID_OTG_NOTIFY_CLIENTREMOVE 0x000a
165
166 static inline int
intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv * iotg,struct notifier_block * nb)167 intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv *iotg,
168 struct notifier_block *nb)
169 {
170 return atomic_notifier_chain_register(&iotg->iotg_notifier, nb);
171 }
172
173 static inline void
intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv * iotg,struct notifier_block * nb)174 intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv *iotg,
175 struct notifier_block *nb)
176 {
177 atomic_notifier_chain_unregister(&iotg->iotg_notifier, nb);
178 }
179
180 #endif /* __INTEL_MID_OTG_H */
181