blob: 098388489813c9a10d3766854af69a922d5e0200 [file] [log] [blame]
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +09001/*
2 * Renesas USB driver
3 *
4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 */
17#include <linux/delay.h>
18#include <linux/io.h>
19#include "./common.h"
20#include "./pipe.h"
21
22/*
Kuninori Morimoto4bd04812011-06-06 14:18:07 +090023 * packet info function
24 */
25void usbhs_pkt_update(struct usbhs_pkt *pkt,
26 struct usbhs_pipe *pipe,
27 void *buf, int len)
28{
29 pkt->pipe = pipe;
30 pkt->buf = buf;
31 pkt->length = len;
32 pkt->actual = 0;
33 pkt->maxp = 0;
34}
35
36/*
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +090037 * FIFO ctrl
38 */
39static void usbhsf_send_terminator(struct usbhs_pipe *pipe)
40{
41 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
42
43 usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
44}
45
46static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
47{
48 int timeout = 1024;
49
50 do {
51 /* The FIFO port is accessible */
52 if (usbhs_read(priv, CFIFOCTR) & FRDY)
53 return 0;
54
55 udelay(10);
56 } while (timeout--);
57
58 return -EBUSY;
59}
60
61static void usbhsf_fifo_clear(struct usbhs_pipe *pipe)
62{
63 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
64
65 if (!usbhs_pipe_is_dcp(pipe))
66 usbhsf_fifo_barrier(priv);
67
68 usbhs_write(priv, CFIFOCTR, BCLR);
69}
70
71static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
72{
73 return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
74}
75
76static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
77{
78 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
79 struct device *dev = usbhs_priv_to_dev(priv);
80 int timeout = 1024;
81 u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
82 u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
83
84 if (usbhs_pipe_is_dcp(pipe))
85 base |= (1 == write) << 5; /* ISEL */
86
87 /* "base" will be used below */
88 usbhs_write(priv, CFIFOSEL, base | MBW_32);
89
90 /* check ISEL and CURPIPE value */
91 while (timeout--) {
92 if (base == (mask & usbhs_read(priv, CFIFOSEL)))
93 return 0;
94 udelay(10);
95 }
96
97 dev_err(dev, "fifo select error\n");
98
99 return -EIO;
100}
101
102/*
103 * PIO fifo functions
104 */
105int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
106{
107 return usbhsf_fifo_select(pipe, 1);
108}
109
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900110int usbhs_fifo_write(struct usbhs_pkt *pkt)
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900111{
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900112 struct usbhs_pipe *pipe = pkt->pipe;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900113 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900114 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900115 void __iomem *addr = priv->base + CFIFO;
116 int maxp = usbhs_pipe_get_maxpacket(pipe);
117 int total_len;
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900118 u8 *buf = pkt->buf;
119 int i, ret, len;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900120
121 ret = usbhs_pipe_is_accessible(pipe);
122 if (ret < 0)
123 return ret;
124
125 ret = usbhsf_fifo_select(pipe, 1);
126 if (ret < 0)
127 return ret;
128
129 ret = usbhsf_fifo_barrier(priv);
130 if (ret < 0)
131 return ret;
132
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900133 len = min(pkt->length, maxp);
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900134 total_len = len;
135
136 /*
137 * FIXME
138 *
139 * 32-bit access only
140 */
141 if (len >= 4 &&
142 !((unsigned long)buf & 0x03)) {
143 iowrite32_rep(addr, buf, len / 4);
144 len %= 4;
145 buf += total_len - len;
146 }
147
148 /* the rest operation */
149 for (i = 0; i < len; i++)
150 iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
151
152 if (total_len < maxp)
153 usbhsf_send_terminator(pipe);
154
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900155 usbhs_pipe_enable(pipe);
156
157 /* update pkt */
158 if (info->tx_done) {
159 pkt->actual = total_len;
160 pkt->maxp = maxp;
161 info->tx_done(pkt);
162 }
163
164 return 0;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900165}
166
167int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
168{
169 int ret;
170
171 /*
172 * select pipe and enable it to prepare packet receive
173 */
174 ret = usbhsf_fifo_select(pipe, 0);
175 if (ret < 0)
176 return ret;
177
178 usbhs_pipe_enable(pipe);
179
180 return ret;
181}
182
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900183int usbhs_fifo_read(struct usbhs_pkt *pkt)
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900184{
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900185 struct usbhs_pipe *pipe = pkt->pipe;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900186 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900187 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900188 void __iomem *addr = priv->base + CFIFO;
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900189 u8 *buf = pkt->buf;
190 int rcv_len, len;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900191 int i, ret;
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900192 int total_len = 0;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900193 u32 data = 0;
194
195 ret = usbhsf_fifo_select(pipe, 0);
196 if (ret < 0)
197 return ret;
198
199 ret = usbhsf_fifo_barrier(priv);
200 if (ret < 0)
201 return ret;
202
203 rcv_len = usbhsf_fifo_rcv_len(priv);
204
205 /*
206 * Buffer clear if Zero-Length packet
207 *
208 * see
209 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
210 */
211 if (0 == rcv_len) {
212 usbhsf_fifo_clear(pipe);
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900213 goto usbhs_fifo_read_end;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900214 }
215
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900216 len = min(rcv_len, pkt->length);
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900217 total_len = len;
218
219 /*
220 * FIXME
221 *
222 * 32-bit access only
223 */
224 if (len >= 4 &&
225 !((unsigned long)buf & 0x03)) {
226 ioread32_rep(addr, buf, len / 4);
227 len %= 4;
228 buf += rcv_len - len;
229 }
230
231 /* the rest operation */
232 for (i = 0; i < len; i++) {
233 if (!(i & 0x03))
234 data = ioread32(addr);
235
236 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
237 }
238
Kuninori Morimoto4bd04812011-06-06 14:18:07 +0900239usbhs_fifo_read_end:
240 if (info->rx_done) {
241 /* update pkt */
242 pkt->actual = total_len;
243 pkt->maxp = usbhs_pipe_get_maxpacket(pipe);
244 info->rx_done(pkt);
245 }
246
247 return 0;
Kuninori Morimotoe8d548d2011-06-06 14:18:03 +0900248}