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