summaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs/mod.h
blob: 56b7106d254d0a263251f71d5e2d40ca51cd77f9 (plain)
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
/* SPDX-License-Identifier: GPL-1.0+ */
/*
 * Renesas USB driver
 *
 * Copyright (C) 2011 Renesas Solutions Corp.
 * Copyright (C) 2019 Renesas Electronics Corporation
 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 */
#ifndef RENESAS_USB_MOD_H
#define RENESAS_USB_MOD_H

#include <linux/spinlock.h>
#include <linux/usb/renesas_usbhs.h>
#include "common.h"

/*
 *	struct
 */
struct usbhs_irq_state {
	u16 intsts0;
	u16 intsts1;
	u16 brdysts;
	u16 nrdysts;
	u16 bempsts;
};

struct usbhs_mod {
	char *name;

	/*
	 * entry point from common.c
	 */
	int (*start)(struct usbhs_priv *priv);
	int (*stop)(struct usbhs_priv *priv);

	/*
	 * INTSTS0
	 */

	/* DVST (DVSQ) */
	int (*irq_dev_state)(struct usbhs_priv *priv,
			     struct usbhs_irq_state *irq_state);

	/* CTRT (CTSQ) */
	int (*irq_ctrl_stage)(struct usbhs_priv *priv,
			      struct usbhs_irq_state *irq_state);

	/* BEMP / BEMPSTS */
	int (*irq_empty)(struct usbhs_priv *priv,
			 struct usbhs_irq_state *irq_state);
	u16 irq_bempsts;

	/* BRDY / BRDYSTS */
	int (*irq_ready)(struct usbhs_priv *priv,
			 struct usbhs_irq_state *irq_state);
	u16 irq_brdysts;

	/*
	 * INTSTS1
	 */

	/* ATTCHE */
	int (*irq_attch)(struct usbhs_priv *priv,
			 struct usbhs_irq_state *irq_state);

	/* DTCHE */
	int (*irq_dtch)(struct usbhs_priv *priv,
			struct usbhs_irq_state *irq_state);

	/* SIGN */
	int (*irq_sign)(struct usbhs_priv *priv,
			struct usbhs_irq_state *irq_state);

	/* SACK */
	int (*irq_sack)(struct usbhs_priv *priv,
			struct usbhs_irq_state *irq_state);

	struct usbhs_priv *priv;
};

struct usbhs_mod_info {
	struct usbhs_mod *mod[USBHS_MAX];
	struct usbhs_mod *curt; /* current mod */

	/*
	 * INTSTS0 :: VBINT
	 *
	 * This function will be used as autonomy mode (runtime_pwctrl == 0)
	 * when the platform doesn't have own get_vbus function.
	 *
	 * This callback cannot be member of "struct usbhs_mod" because it
	 * will be used even though host/gadget has not been selected.
	 */
	int (*irq_vbus)(struct usbhs_priv *priv,
			struct usbhs_irq_state *irq_state);

	/*
	 * This function will be used on any gadget mode. To simplify the code,
	 * this member is in here.
	 */
	int (*get_vbus)(struct platform_device *pdev);
};

/*
 *		for host/gadget module
 */
struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id);
struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv);
void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *usb, int id);
int usbhs_mod_is_host(struct usbhs_priv *priv);
int usbhs_mod_change(struct usbhs_priv *priv, int id);
int usbhs_mod_probe(struct usbhs_priv *priv);
void usbhs_mod_remove(struct usbhs_priv *priv);

void usbhs_mod_autonomy_mode(struct usbhs_priv *priv);
void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv);

/*
 *		status functions
 */
int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state);
int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state);

/*
 *		callback functions
 */
void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod);


#define usbhs_mod_call(priv, func, param...)		\
	({						\
		struct usbhs_mod *mod;			\
		mod = usbhs_mod_get_current(priv);	\
		!mod		? -ENODEV :		\
		!mod->func	? 0 :			\
		 mod->func(param);			\
	})

#define usbhs_priv_to_modinfo(priv) (&priv->mod_info)
#define usbhs_mod_info_call(priv, func, param...)	\
({							\
	struct usbhs_mod_info *info;			\
	info = usbhs_priv_to_modinfo(priv);		\
	!info->func ? 0 :				\
	 info->func(param);				\
})

/*
 * host / gadget control
 */
#if	defined(CONFIG_USB_RENESAS_USBHS_HCD) || \
	defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE)
extern int usbhs_mod_host_probe(struct usbhs_priv *priv);
extern int usbhs_mod_host_remove(struct usbhs_priv *priv);
#else
static inline int usbhs_mod_host_probe(struct usbhs_priv *priv)
{
	return 0;
}
static inline void usbhs_mod_host_remove(struct usbhs_priv *priv)
{
}
#endif

#if	defined(CONFIG_USB_RENESAS_USBHS_UDC) || \
	defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE)
extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv);
extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv);
#else
static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
	return 0;
}
static inline void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
{
}
#endif

#endif /* RENESAS_USB_MOD_H */