usb: renesas_usbhs: divide data transfer functions
[pandora-kernel.git] / drivers / usb / renesas_usbhs / fifo.c
1 /*
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 /*
23  *              packet info function
24  */
25 void 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 /*
37  *              FIFO ctrl
38  */
39 static 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
46 static 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
61 static 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
71 static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
72 {
73         return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
74 }
75
76 static 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  */
105 int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
106 {
107         return usbhsf_fifo_select(pipe, 1);
108 }
109
110 int usbhs_fifo_write(struct usbhs_pkt *pkt)
111 {
112         struct usbhs_pipe *pipe = pkt->pipe;
113         struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
114         struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
115         void __iomem *addr = priv->base + CFIFO;
116         int maxp = usbhs_pipe_get_maxpacket(pipe);
117         int total_len;
118         u8 *buf = pkt->buf;
119         int i, ret, len;
120
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
133         len = min(pkt->length, maxp);
134         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
155         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;
165 }
166
167 int 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
183 int usbhs_fifo_read(struct usbhs_pkt *pkt)
184 {
185         struct usbhs_pipe *pipe = pkt->pipe;
186         struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
187         struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
188         void __iomem *addr = priv->base + CFIFO;
189         u8 *buf = pkt->buf;
190         int rcv_len, len;
191         int i, ret;
192         int total_len = 0;
193         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);
213                 goto usbhs_fifo_read_end;
214         }
215
216         len = min(rcv_len, pkt->length);
217         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
239 usbhs_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;
248 }