1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
|
/* include/linux/usb/msm_hsusb.h
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
* Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __ASM_ARCH_MSM_HSUSB_H
#define __ASM_ARCH_MSM_HSUSB_H
#include <linux/types.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/clk.h>
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
#include <linux/power_supply.h>
#include <linux/cdev.h>
#include <linux/usb_bam.h>
#include <linux/extcon.h>
#include <linux/regulator/driver.h>
/**
* Requested USB votes for NOC frequency
*
* USB_NOC_NOM_VOTE Vote for NOM set of NOC frequencies
* USB_NOC_SVS_VOTE Vote for SVS set of NOC frequencies
*
*/
enum usb_noc_mode {
USB_NOC_NOM_VOTE = 0,
USB_NOC_SVS_VOTE,
USB_NOC_NUM_VOTE,
};
/**
* USB charger types
*
* USB_INVALID_CHARGER Invalid USB charger.
* USB_SDP_CHARGER Standard downstream port. Refers to a downstream port
* on USB2.0 compliant host/hub.
* USB_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
* USB_CDP_CHARGER Charging downstream port. Enumeration can happen and
* IDEV_CHG_MAX can be drawn irrespective of USB state.
* USB_NONCOMPLIANT_CHARGER A non-compliant charger pull DP and DM to specific
* voltages between 2.0-3.3v for identification.
*
*/
enum usb_chg_type {
USB_INVALID_CHARGER = 0,
USB_SDP_CHARGER,
USB_DCP_CHARGER,
USB_CDP_CHARGER,
USB_NONCOMPLIANT_CHARGER,
USB_FLOATED_CHARGER,
};
/**
* Maintain state for hvdcp external charger status
* DEFAULT This is used when DCP is detected
* ACTIVE This is used when ioctl is called to block LPM
* INACTIVE This is used when ioctl is called to unblock LPM
*/
enum usb_ext_chg_status {
DEFAULT = 1,
ACTIVE,
INACTIVE,
};
/**
* USB ID state
*/
enum usb_id_state {
USB_ID_GROUND = 0,
USB_ID_FLOAT,
};
#define USB_NUM_BUS_CLOCKS 3
/**
* struct msm_otg: OTG driver data. Shared by HCD and DCD.
* @otg: USB OTG Transceiver structure.
* @pdata: otg device platform data.
* @irq: IRQ number assigned for HSUSB controller.
* @async_irq: IRQ number used by some controllers during low power state
* @phy_irq: IRQ number assigned for PHY to notify events like id and line
state changes.
* @pclk: clock struct of iface_clk.
* @core_clk: clock struct of core_bus_clk.
* @sleep_clk: clock struct of sleep_clk for USB PHY.
* @phy_reset_clk: clock struct of phy_reset_clk for USB PHY. This clock is
a reset only clock and resets the PHY, ULPI bridge and
CSR wrapper.
* @phy_por_clk: clock struct of phy_por_clk for USB PHY. This clock is
a reset only clock and resets only the PHY (POR).
* @phy_csr_clk: clock struct of phy_csr_clk for USB PHY. This clock is
required to access PHY CSR registers via AHB2PHY interface.
* @bus_clks: bimc/snoc/pcnoc clock struct.
* @core_reset: Reset control for core_clk
* @phy_reset: Reset control for phy_reset_clk
* @phy_por_reset: Reset control for phy_por_clk
* @default_noc_mode: default frequency for NOC clocks - SVS or NOM
* @core_clk_rate: core clk max frequency
* @regs: ioremapped register base address.
* @usb_phy_ctrl_reg: relevant PHY_CTRL_REG register base address.
* @inputs: OTG state machine inputs(Id, SessValid etc).
* @sm_work: OTG state machine work.
* @sm_work_pending: OTG state machine work is pending, queued post pm_resume
* @resume_pending: USB h/w lpm_exit pending. Done on next sm_work run
* @pm_suspended: OTG device is system(PM) suspended.
* @pm_notify: Notifier to receive system wide PM transition events.
It is used to defer wakeup events processing until
system is RESUMED.
* @in_lpm: indicates low power mode (LPM) state.
* @async_int: IRQ line on which ASYNC interrupt arrived in LPM.
* @cur_power: The amount of mA available from downstream port.
* @otg_wq: Strict order otg workqueue for OTG works (SM/ID/SUSPEND).
* @chg_type: The type of charger attached.
* @bus_perf_client: Bus performance client handle to request BUS bandwidth
* @host_bus_suspend: indicates host bus suspend or not.
* @device_bus_suspend: indicates device bus suspend or not.
* @bus_clks_enabled: indicates pcnoc/snoc/bimc clocks are on or not.
* @is_ext_chg_dcp: To indicate whether charger detected by external entity
SMB hardware is DCP charger or not.
* @ext_id_irq: IRQ for ID interrupt.
* @phy_irq_pending: Gets set when PHY IRQ arrives in LPM.
* @id_state: Indicates USBID line status.
* @rm_pulldown: Indicates pulldown status on D+ and D- data lines.
* @extcon_vbus: Used for VBUS notification registration.
* @extcon_id: Used for ID notification registration.
* @vbus_nb: Notification callback for VBUS event.
* @id_nb: Notification callback for ID event.
* @dpdm_desc: Regulator descriptor for D+ and D- voting.
* @dpdm_rdev: Regulator class device for dpdm regulator.
* @dbg_idx: Dynamic debug buffer Index.
* @dbg_lock: Dynamic debug buffer Lock.
* @buf: Dynamic Debug Buffer.
* @max_nominal_system_clk_rate: max freq at which system clock can run in
nominal mode.
* @sdp_check: SDP detection work in case of USB_FLOAT power supply
*/
struct msm_otg {
struct usb_phy phy;
struct msm_otg_platform_data *pdata;
struct platform_device *pdev;
int irq;
int async_irq;
int phy_irq;
struct clk *xo_clk;
struct clk *pclk;
struct clk *core_clk;
struct clk *sleep_clk;
struct clk *phy_reset_clk;
struct clk *phy_por_clk;
struct clk *phy_csr_clk;
struct clk *bus_clks[USB_NUM_BUS_CLOCKS];
struct clk *phy_ref_clk;
struct reset_control *core_reset;
struct reset_control *phy_reset;
struct reset_control *phy_por_reset;
long core_clk_rate;
long core_clk_svs_rate;
long core_clk_nominal_rate;
enum usb_noc_mode default_noc_mode;
struct resource *io_res;
void __iomem *regs;
void __iomem *phy_csr_regs;
void __iomem *usb_phy_ctrl_reg;
#define ID 0
#define B_SESS_VLD 1
#define A_BUS_SUSPEND 14
unsigned long inputs;
struct work_struct sm_work;
bool sm_work_pending;
bool resume_pending;
atomic_t pm_suspended;
struct notifier_block pm_notify;
atomic_t in_lpm;
bool err_event_seen;
int async_int;
unsigned int cur_power;
struct workqueue_struct *otg_wq;
struct delayed_work id_status_work;
enum usb_chg_type chg_type;
unsigned int dcd_time;
unsigned long caps;
uint32_t bus_perf_client;
bool host_bus_suspend;
bool device_bus_suspend;
bool bus_clks_enabled;
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
* Currently only 28nm PHY has the support to allowing PHY
* power collapse since it doesn't have leakage currents while
* turning off the power rails.
*/
#define ALLOW_PHY_POWER_COLLAPSE BIT(0)
/*
* Allow PHY RETENTION mode before turning off the digital
* voltage regulator(VDDCX).
*/
#define ALLOW_PHY_RETENTION BIT(1)
/*
* Allow putting the core in Low Power mode, when
* USB bus is suspended but cable is connected.
*/
#define ALLOW_LPM_ON_DEV_SUSPEND BIT(2)
/*
* Allowing PHY regulators LPM puts the HSUSB 3.3v and 1.8v
* analog regulators into LPM while going to USB low power mode.
*/
#define ALLOW_PHY_REGULATORS_LPM BIT(3)
/*
* Allow PHY RETENTION mode before turning off the digital
* voltage regulator(VDDCX) during host mode.
*/
#define ALLOW_HOST_PHY_RETENTION BIT(4)
/*
* Allow VDD minimization without putting PHY into retention
* for fixing PHY current leakage issue when LDOs ar turned off.
*/
#define ALLOW_VDD_MIN_WITH_RETENTION_DISABLED BIT(5)
/*
* PHY can keep D+ pull-up during peripheral bus suspend and
* D+/D- pull-down during host bus suspend without any
* re-work. This is possible only when PHY DVDD is supplied
* by a PMIC LDO (unlike VDDCX/VDDMX).
*/
#define ALLOW_BUS_SUSPEND_WITHOUT_REWORK BIT(6)
unsigned long lpm_flags;
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
#define XO_SHUTDOWN BIT(2)
#define CLOCKS_DOWN BIT(3)
#define PHY_REGULATORS_LPM BIT(4)
int reset_counter;
unsigned int online;
dev_t ext_chg_dev;
struct pinctrl *phy_pinctrl;
bool is_ext_chg_dcp;
struct qpnp_vadc_chip *vadc_dev;
int ext_id_irq;
bool phy_irq_pending;
enum usb_id_state id_state;
bool rm_pulldown;
struct extcon_dev *extcon_vbus;
struct extcon_dev *extcon_id;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
struct regulator_desc dpdm_rdesc;
struct regulator_dev *dpdm_rdev;
/* Maximum debug message length */
#define DEBUG_MSG_LEN 128UL
/* Maximum number of messages */
#define DEBUG_MAX_MSG 256UL
unsigned int dbg_idx;
rwlock_t dbg_lock;
char (buf[DEBUG_MAX_MSG])[DEBUG_MSG_LEN]; /* buffer */
unsigned int vbus_state;
unsigned int usb_irq_count;
int pm_qos_latency;
unsigned int notify_current_mA;
struct pm_qos_request pm_qos_req_dma;
struct delayed_work perf_vote_work;
struct delayed_work sdp_check;
struct work_struct notify_chg_current_work;
};
struct ci13xxx_platform_data {
u8 usb_core_id;
/*
* value of 2^(log2_itc-1) will be used as the interrupt threshold
* (ITC), when log2_itc is between 1 to 7.
*/
int log2_itc;
bool l1_supported;
bool enable_ahb2ahb_bypass;
bool enable_streaming;
bool enable_axi_prefetch;
};
#ifdef CONFIG_USB_BAM
void msm_bam_set_usb_host_dev(struct device *dev);
int msm_do_bam_disable_enable(enum usb_ctrl ctrl);
#else
static inline void msm_bam_set_usb_host_dev(struct device *dev) {}
int msm_do_bam_disable_enable(enum usb_ctrl ctrl) { return true; }
#endif
#ifdef CONFIG_USB_CI13XXX_MSM
void msm_hw_soft_reset(void);
#else
static inline void msm_hw_soft_reset(void)
{
}
#endif
#endif
|