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
27struct 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 */
31struct 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 */
96struct 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 usb_phy data structure for this
108 * purpose.
109 */
110struct intel_mid_otg_xceiv {
111	struct usb_phy		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};
149static inline
150struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct usb_phy *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
166static inline int
167intel_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
173static inline void
174intel_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