4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
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.
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
17 #include <linux/delay.h>
23 * packet info function
25 void usbhs_pkt_update(struct usbhs_pkt
*pkt
,
26 struct usbhs_pipe
*pipe
,
39 static void usbhsf_send_terminator(struct usbhs_pipe
*pipe
)
41 struct usbhs_priv
*priv
= usbhs_pipe_to_priv(pipe
);
43 usbhs_bset(priv
, CFIFOCTR
, BVAL
, BVAL
);
46 static int usbhsf_fifo_barrier(struct usbhs_priv
*priv
)
51 /* The FIFO port is accessible */
52 if (usbhs_read(priv
, CFIFOCTR
) & FRDY
)
61 static void usbhsf_fifo_clear(struct usbhs_pipe
*pipe
)
63 struct usbhs_priv
*priv
= usbhs_pipe_to_priv(pipe
);
65 if (!usbhs_pipe_is_dcp(pipe
))
66 usbhsf_fifo_barrier(priv
);
68 usbhs_write(priv
, CFIFOCTR
, BCLR
);
71 static int usbhsf_fifo_rcv_len(struct usbhs_priv
*priv
)
73 return usbhs_read(priv
, CFIFOCTR
) & DTLN_MASK
;
76 static int usbhsf_fifo_select(struct usbhs_pipe
*pipe
, int write
)
78 struct usbhs_priv
*priv
= usbhs_pipe_to_priv(pipe
);
79 struct device
*dev
= usbhs_priv_to_dev(priv
);
81 u16 mask
= ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
82 u16 base
= usbhs_pipe_number(pipe
); /* CURPIPE */
84 if (usbhs_pipe_is_dcp(pipe
))
85 base
|= (1 == write
) << 5; /* ISEL */
87 /* "base" will be used below */
88 usbhs_write(priv
, CFIFOSEL
, base
| MBW_32
);
90 /* check ISEL and CURPIPE value */
92 if (base
== (mask
& usbhs_read(priv
, CFIFOSEL
)))
97 dev_err(dev
, "fifo select error\n");
105 int usbhs_fifo_prepare_write(struct usbhs_pipe
*pipe
)
107 return usbhsf_fifo_select(pipe
, 1);
110 int usbhs_fifo_write(struct usbhs_pkt
*pkt
)
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
);
121 ret
= usbhs_pipe_is_accessible(pipe
);
125 ret
= usbhsf_fifo_select(pipe
, 1);
129 ret
= usbhsf_fifo_barrier(priv
);
133 len
= min(pkt
->length
, maxp
);
142 !((unsigned long)buf
& 0x03)) {
143 iowrite32_rep(addr
, buf
, len
/ 4);
145 buf
+= total_len
- len
;
148 /* the rest operation */
149 for (i
= 0; i
< len
; i
++)
150 iowrite8(buf
[i
], addr
+ (0x03 - (i
& 0x03)));
152 if (total_len
< maxp
)
153 usbhsf_send_terminator(pipe
);
155 usbhs_pipe_enable(pipe
);
159 pkt
->actual
= total_len
;
167 int usbhs_fifo_prepare_read(struct usbhs_pipe
*pipe
)
172 * select pipe and enable it to prepare packet receive
174 ret
= usbhsf_fifo_select(pipe
, 0);
178 usbhs_pipe_enable(pipe
);
183 int usbhs_fifo_read(struct usbhs_pkt
*pkt
)
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
;
195 ret
= usbhsf_fifo_select(pipe
, 0);
199 ret
= usbhsf_fifo_barrier(priv
);
203 rcv_len
= usbhsf_fifo_rcv_len(priv
);
206 * Buffer clear if Zero-Length packet
209 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
212 usbhsf_fifo_clear(pipe
);
213 goto usbhs_fifo_read_end
;
216 len
= min(rcv_len
, pkt
->length
);
225 !((unsigned long)buf
& 0x03)) {
226 ioread32_rep(addr
, buf
, len
/ 4);
228 buf
+= rcv_len
- len
;
231 /* the rest operation */
232 for (i
= 0; i
< len
; i
++) {
234 data
= ioread32(addr
);
236 buf
[i
] = (data
>> ((i
& 0x03) * 8)) & 0xff;
242 pkt
->actual
= total_len
;
243 pkt
->maxp
= usbhs_pipe_get_maxpacket(pipe
);