1 /* Cypress West Bridge API source file (cyasdma.c)
2 ## ===========================
3 ## Copyright (C) 2010 Cypress Semiconductor
5 ## This program is free software; you can redistribute it and/or
6 ## modify it under the terms of the GNU General Public License
7 ## as published by the Free Software Foundation; either version 2
8 ## of the License, or (at your option) any later version.
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software
17 ## Foundation, Inc., 51 Franklin Street, Fifth Floor
18 ## Boston, MA 02110-1301, USA.
19 ## ===========================
22 #include "../../include/linux/westbridge/cyashal.h"
23 #include "../../include/linux/westbridge/cyasdma.h"
24 #include "../../include/linux/westbridge/cyaslowlevel.h"
25 #include "../../include/linux/westbridge/cyaserr.h"
26 #include "../../include/linux/westbridge/cyasregs.h"
29 * Add the DMA queue entry to the free list to be re-used later
32 cy_as_dma_add_request_to_free_queue(cy_as_device
*dev_p
,
33 cy_as_dma_queue_entry
*req_p
)
36 imask
= cy_as_hal_disable_interrupts();
38 req_p
->next_p
= dev_p
->dma_freelist_p
;
39 dev_p
->dma_freelist_p
= req_p
;
41 cy_as_hal_enable_interrupts(imask
);
45 * Get a DMA queue entry from the free list.
47 static cy_as_dma_queue_entry
*
48 cy_as_dma_get_dma_queue_entry(cy_as_device
*dev_p
)
50 cy_as_dma_queue_entry
*req_p
;
53 cy_as_hal_assert(dev_p
->dma_freelist_p
!= 0);
55 imask
= cy_as_hal_disable_interrupts();
56 req_p
= dev_p
->dma_freelist_p
;
57 dev_p
->dma_freelist_p
= req_p
->next_p
;
58 cy_as_hal_enable_interrupts(imask
);
64 * Set the maximum size that the West Bridge hardware
65 * can handle in a single DMA operation. This size
66 * may change for the P <-> U endpoints as a function
67 * of the endpoint type and whether we are running
68 * at full speed or high speed.
71 cy_as_dma_set_max_dma_size(cy_as_device
*dev_p
,
72 cy_as_end_point_number_t ep
, uint32_t size
)
74 /* In MTP mode, EP2 is allowed to have all max sizes. */
75 if ((!dev_p
->is_mtp_firmware
) || (ep
!= 0x02)) {
76 if (size
< 64 || size
> 1024)
77 return CY_AS_ERROR_INVALID_SIZE
;
80 CY_AS_NUM_EP(dev_p
, ep
)->maxhwdata
= (uint16_t)size
;
81 return CY_AS_ERROR_SUCCESS
;
85 * The callback for requests sent to West Bridge
86 * to relay endpoint data. Endpoint data for EP0
87 * and EP1 are sent using mailbox requests. This
88 * is the callback that is called when a response
89 * to a mailbox request to send data is received.
92 cy_as_dma_request_callback(
95 cy_as_ll_request_response
*req_p
,
96 cy_as_ll_request_response
*resp_p
,
97 cy_as_return_status_t ret
)
101 cy_as_end_point_number_t ep
;
105 cy_as_log_debug_message(5, "cy_as_dma_request_callback called");
108 * extract the return code from the firmware
110 if (ret
== CY_AS_ERROR_SUCCESS
) {
111 if (cy_as_ll_request_response__get_code(resp_p
) !=
112 CY_RESP_SUCCESS_FAILURE
)
113 ret
= CY_AS_ERROR_INVALID_RESPONSE
;
115 ret
= cy_as_ll_request_response__get_word(resp_p
, 0);
119 * extract the endpoint number and the transferred byte count
122 v
= cy_as_ll_request_response__get_word(req_p
, 0);
123 ep
= (cy_as_end_point_number_t
)((v
>> 13) & 0x01);
125 if (ret
== CY_AS_ERROR_SUCCESS
) {
127 * if the firmware returns success,
128 * all of the data requested was
129 * transferred. there are no partial
135 * if the firmware returned an error, no data was transferred.
141 * queue the request and response data structures for use with the
142 * next EP0 or EP1 request.
145 dev_p
->usb_ep0_dma_req
= req_p
;
146 dev_p
->usb_ep0_dma_resp
= resp_p
;
148 dev_p
->usb_ep1_dma_req
= req_p
;
149 dev_p
->usb_ep1_dma_resp
= resp_p
;
153 * call the DMA complete function so we can
154 * signal that this portion of the transfer
155 * has completed. if the low level request
156 * was canceled, we do not need to signal
157 * the completed function as the only way a
158 * cancel can happen is via the DMA cancel
161 if (ret
!= CY_AS_ERROR_CANCELED
)
162 cy_as_dma_completed_callback(dev_p
->tag
, ep
, datacnt
, ret
);
166 * Set the DRQ mask register for the given endpoint number. If state is
167 * CyTrue, the DRQ interrupt for the given endpoint is enabled, otherwise
171 cy_as_dma_set_drq(cy_as_device
*dev_p
,
172 cy_as_end_point_number_t ep
, cy_bool state
)
179 * there are not DRQ register bits for EP0 and EP1
181 if (ep
== 0 || ep
== 1)
185 * disable interrupts while we do this to be sure the state of the
186 * DRQ mask register is always well defined.
188 intval
= cy_as_hal_disable_interrupts();
191 * set the DRQ bit to the given state for the ep given
194 v
= cy_as_hal_read_register(dev_p
->tag
, CY_AS_MEM_P0_DRQ_MASK
);
201 cy_as_hal_write_register(dev_p
->tag
, CY_AS_MEM_P0_DRQ_MASK
, v
);
202 cy_as_hal_enable_interrupts(intval
);
206 * Send the next DMA request for the endpoint given
209 cy_as_dma_send_next_dma_request(cy_as_device
*dev_p
, cy_as_dma_end_point
*ep_p
)
213 cy_as_dma_queue_entry
*dma_p
;
215 cy_as_log_debug_message(6, "cy_as_dma_send_next_dma_request called");
217 /* If the queue is empty, nothing to do */
218 dma_p
= ep_p
->queue_p
;
221 * there are no pending DMA requests
222 * for this endpoint. disable the DRQ
223 * mask bits to insure no interrupts
224 * will be triggered by this endpoint
225 * until someone is interested in the data.
227 cy_as_dma_set_drq(dev_p
, ep_p
->ep
, cy_false
);
231 cy_as_dma_end_point_set_running(ep_p
);
234 * get the number of words that still
235 * need to be xferred in this request.
237 datacnt
= dma_p
->size
- dma_p
->offset
;
238 cy_as_hal_assert(datacnt
>= 0);
241 * the HAL layer should never limit the size
242 * of the transfer to something less than the
243 * maxhwdata otherwise, the data will be sent
244 * in packets that are not correct in size.
246 cy_as_hal_assert(ep_p
->maxhaldata
== CY_AS_DMA_MAX_SIZE_HW_SIZE
247 || ep_p
->maxhaldata
>= ep_p
->maxhwdata
);
250 * update the number of words that need to be xferred yet
251 * based on the limits of the HAL layer.
253 if (ep_p
->maxhaldata
== CY_AS_DMA_MAX_SIZE_HW_SIZE
) {
254 if (datacnt
> ep_p
->maxhwdata
)
255 datacnt
= ep_p
->maxhwdata
;
257 if (datacnt
> ep_p
->maxhaldata
)
258 datacnt
= ep_p
->maxhaldata
;
262 * find a pointer to the data that needs to be transferred
264 buf_p
= (((char *)dma_p
->buf_p
) + dma_p
->offset
);
267 * mark a request in transit
269 cy_as_dma_end_point_set_in_transit(ep_p
);
271 if (ep_p
->ep
== 0 || ep_p
->ep
== 1) {
273 * if this is a WRITE request on EP0 and EP1
274 * we write the data via an EP_DATA request
275 * to west bridge via the mailbox registers.
276 * if this is a READ request, we do nothing
277 * and the data will arrive via an EP_DATA
278 * request from west bridge. in the request
279 * handler for the USB context we will pass
280 * the data back into the DMA module.
282 if (dma_p
->readreq
== cy_false
) {
285 cy_as_ll_request_response
*resp_p
;
286 cy_as_ll_request_response
*req_p
;
287 cy_as_return_status_t ret
;
289 len
= (uint16_t)(datacnt
/ 2);
296 req_p
= dev_p
->usb_ep0_dma_req
;
297 resp_p
= dev_p
->usb_ep0_dma_resp
;
298 dev_p
->usb_ep0_dma_req
= 0;
299 dev_p
->usb_ep0_dma_resp
= 0;
301 req_p
= dev_p
->usb_ep1_dma_req
;
302 resp_p
= dev_p
->usb_ep1_dma_resp
;
303 dev_p
->usb_ep1_dma_req
= 0;
304 dev_p
->usb_ep1_dma_resp
= 0;
307 cy_as_hal_assert(req_p
!= 0);
308 cy_as_hal_assert(resp_p
!= 0);
309 cy_as_hal_assert(len
<= 64);
311 cy_as_ll_init_request(req_p
, CY_RQT_USB_EP_DATA
,
312 CY_RQT_USB_RQT_CONTEXT
, len
);
314 v
= (uint16_t)(datacnt
| (ep_p
->ep
<< 13) | (1 << 14));
315 if (dma_p
->offset
== 0)
316 v
|= (1 << 12);/* Set the first packet bit */
317 if (dma_p
->offset
+ datacnt
== dma_p
->size
)
318 v
|= (1 << 11);/* Set the last packet bit */
320 cy_as_ll_request_response__set_word(req_p
, 0, v
);
321 cy_as_ll_request_response__pack(req_p
,
324 cy_as_ll_init_response(resp_p
, 1);
326 ret
= cy_as_ll_send_request(dev_p
, req_p
, resp_p
,
327 cy_false
, cy_as_dma_request_callback
);
328 if (ret
== CY_AS_ERROR_SUCCESS
)
329 cy_as_log_debug_message(5,
330 "+++ send EP 0/1 data via mailbox registers");
332 cy_as_log_debug_message(5,
333 "+++ error sending EP 0/1 data via mailbox "
334 "registers - CY_AS_ERROR_TIMEOUT");
336 if (ret
!= CY_AS_ERROR_SUCCESS
)
337 cy_as_dma_completed_callback(dev_p
->tag
,
342 * this is a DMA request on an endpoint that is accessible
343 * via the P port. ask the HAL DMA capabilities to
344 * perform this. the amount of data sent is limited by the
345 * HAL max size as well as what we need to send. if the
346 * ep_p->maxhaldata is set to a value larger than the
347 * endpoint buffer size, then we will pass more than a
348 * single buffer worth of data to the HAL layer and expect
349 * the HAL layer to divide the data into packets. the last
350 * parameter here (ep_p->maxhwdata) gives the packet size for
351 * the data so the HAL layer knows what the packet size should
354 if (cy_as_dma_end_point_is_direction_in(ep_p
))
355 cy_as_hal_dma_setup_write(dev_p
->tag
,
356 ep_p
->ep
, buf_p
, datacnt
, ep_p
->maxhwdata
);
358 cy_as_hal_dma_setup_read(dev_p
->tag
,
359 ep_p
->ep
, buf_p
, datacnt
, ep_p
->maxhwdata
);
362 * the DRQ interrupt for this endpoint should be enabled
363 * so that the data transfer progresses at interrupt time.
365 cy_as_dma_set_drq(dev_p
, ep_p
->ep
, cy_true
);
370 * This function is called when the HAL layer has
371 * completed the last requested DMA operation.
372 * This function sends/receives the next batch of
373 * data associated with the current DMA request,
374 * or it is is complete, moves to the next DMA request.
377 cy_as_dma_completed_callback(cy_as_hal_device_tag tag
,
378 cy_as_end_point_number_t ep
, uint32_t cnt
, cy_as_return_status_t status
)
381 cy_as_dma_queue_entry
*req_p
;
382 cy_as_dma_end_point
*ep_p
;
383 cy_as_device
*dev_p
= cy_as_device_find_from_tag(tag
);
385 /* Make sure the HAL layer gave us good parameters */
386 cy_as_hal_assert(dev_p
!= 0);
387 cy_as_hal_assert(dev_p
->sig
== CY_AS_DEVICE_HANDLE_SIGNATURE
);
388 cy_as_hal_assert(ep
< 16);
391 /* Get the endpoint ptr */
392 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
393 cy_as_hal_assert(ep_p
->queue_p
!= 0);
395 /* Get a pointer to the current entry in the queue */
396 mask
= cy_as_hal_disable_interrupts();
397 req_p
= ep_p
->queue_p
;
399 /* Update the offset to reflect the data actually received or sent */
400 req_p
->offset
+= cnt
;
403 * if we are still sending/receiving the current packet,
404 * send/receive the next chunk basically we keep going
405 * if we have not sent/received enough data, and we are
406 * not doing a packet operation, and the last packet
407 * sent or received was a full sized packet. in other
408 * words, when we are NOT doing a packet operation, a
409 * less than full size packet (a short packet) will
410 * terminate the operation.
412 * note: if this is EP1 request and the request has
413 * timed out, it means the buffer is not free.
414 * we have to resend the data.
416 * note: for the MTP data transfers, the DMA transfer
417 * for the next packet can only be started asynchronously,
418 * after a firmware event notifies that the device is ready.
420 if (((req_p
->offset
!= req_p
->size
) && (req_p
->packet
== cy_false
) &&
421 ((cnt
== ep_p
->maxhaldata
) || ((cnt
== ep_p
->maxhwdata
) &&
422 ((ep
!= CY_AS_MTP_READ_ENDPOINT
) ||
423 (cnt
== dev_p
->usb_max_tx_size
)))))
424 || ((ep
== 1) && (status
== CY_AS_ERROR_TIMEOUT
))) {
425 cy_as_hal_enable_interrupts(mask
);
428 * and send the request again to send the next block of
429 * data. special handling for MTP transfers on E_ps 2
430 * and 6. the send_next_request will be processed based
431 * on the event sent by the firmware.
433 if ((ep
== CY_AS_MTP_WRITE_ENDPOINT
) || (
434 (ep
== CY_AS_MTP_READ_ENDPOINT
) &&
435 (!cy_as_dma_end_point_is_direction_in(ep_p
))))
436 cy_as_dma_end_point_set_stopped(ep_p
);
438 cy_as_dma_send_next_dma_request(dev_p
, ep_p
);
442 * we have sent or received all of the data
444 * we are doing a packet operation
446 * we receive a short packet
450 * remove this entry from the DMA queue for this endpoint.
452 cy_as_dma_end_point_clear_in_transit(ep_p
);
453 ep_p
->queue_p
= req_p
->next_p
;
454 if (ep_p
->last_p
== req_p
) {
456 * we have removed the last packet from the DMA queue,
457 * disable the interrupt associated with this interrupt.
460 cy_as_hal_enable_interrupts(mask
);
461 cy_as_dma_set_drq(dev_p
, ep
, cy_false
);
463 cy_as_hal_enable_interrupts(mask
);
467 * if the request has a callback associated with it,
468 * call the callback to tell the interested party that
469 * this DMA request has completed.
471 * note, we set the in_callback bit to insure that we
472 * cannot recursively call an API function that is
473 * synchronous only from a callback.
475 cy_as_device_set_in_callback(dev_p
);
476 (*req_p
->cb
)(dev_p
, ep
, req_p
->buf_p
,
477 req_p
->offset
, status
);
478 cy_as_device_clear_in_callback(dev_p
);
482 * we are done with this request, put it on the freelist to be
483 * reused at a later time.
485 cy_as_dma_add_request_to_free_queue(dev_p
, req_p
);
487 if (ep_p
->queue_p
== 0) {
489 * if the endpoint is out of DMA entries, set the
490 * endpoint as stopped.
492 cy_as_dma_end_point_set_stopped(ep_p
);
495 * the DMA queue is empty, wake any task waiting on
496 * the QUEUE to drain.
498 if (cy_as_dma_end_point_is_sleeping(ep_p
)) {
499 cy_as_dma_end_point_set_wake_state(ep_p
);
500 cy_as_hal_wake(&ep_p
->channel
);
504 * if the queued operation is a MTP transfer,
505 * wait until firmware event before sending
506 * down the next DMA request.
508 if ((ep
== CY_AS_MTP_WRITE_ENDPOINT
) ||
509 ((ep
== CY_AS_MTP_READ_ENDPOINT
) &&
510 (!cy_as_dma_end_point_is_direction_in(ep_p
))) ||
511 ((ep
== dev_p
->storage_read_endpoint
) &&
512 (!cy_as_device_is_p2s_dma_start_recvd(dev_p
)))
513 || ((ep
== dev_p
->storage_write_endpoint
) &&
514 (!cy_as_device_is_p2s_dma_start_recvd(dev_p
))))
515 cy_as_dma_end_point_set_stopped(ep_p
);
517 cy_as_dma_send_next_dma_request(dev_p
, ep_p
);
523 * This function is used to kick start DMA on a given
524 * channel. If DMA is already running on the given
525 * endpoint, nothing happens. If DMA is not running,
526 * the first entry is pulled from the DMA queue and
527 * sent/recevied to/from the West Bridge device.
529 cy_as_return_status_t
530 cy_as_dma_kick_start(cy_as_device
*dev_p
, cy_as_end_point_number_t ep
)
532 cy_as_dma_end_point
*ep_p
;
533 cy_as_hal_assert(dev_p
->sig
== CY_AS_DEVICE_HANDLE_SIGNATURE
);
535 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
537 /* We are already running */
538 if (cy_as_dma_end_point_is_running(ep_p
))
539 return CY_AS_ERROR_SUCCESS
;
541 cy_as_dma_send_next_dma_request(dev_p
, ep_p
);
542 return CY_AS_ERROR_SUCCESS
;
546 * This function stops the given endpoint. Stopping and endpoint cancels
547 * any pending DMA operations and frees all resources associated with the
550 static cy_as_return_status_t
551 cy_as_dma_stop_end_point(cy_as_device
*dev_p
, cy_as_end_point_number_t ep
)
553 cy_as_return_status_t ret
;
554 cy_as_dma_end_point
*ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
557 * cancel any pending DMA requests associated with this endpoint. this
558 * cancels any DMA requests at the HAL layer as well as dequeues any
559 * request that is currently pending.
561 ret
= cy_as_dma_cancel(dev_p
, ep
, CY_AS_ERROR_CANCELED
);
562 if (ret
!= CY_AS_ERROR_SUCCESS
)
566 * destroy the sleep channel
568 if (!cy_as_hal_destroy_sleep_channel(&ep_p
->channel
)
569 && ret
== CY_AS_ERROR_SUCCESS
)
570 ret
= CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED
;
573 * free the memory associated with this endpoint
575 cy_as_hal_free(ep_p
);
578 * set the data structure ptr to something sane since the
579 * previous pointer is now free.
587 * This method stops the USB stack. This is an internal function that does
588 * all of the work of destroying the USB stack without the protections that
589 * we provide to the API (i.e. stopping at stack that is not running).
591 static cy_as_return_status_t
592 cy_as_dma_stop_internal(cy_as_device
*dev_p
)
594 cy_as_return_status_t ret
= CY_AS_ERROR_SUCCESS
;
595 cy_as_return_status_t lret
;
596 cy_as_end_point_number_t i
;
599 * stop all of the endpoints. this cancels all DMA requests, and
600 * frees all resources associated with each endpoint.
602 for (i
= 0; i
< sizeof(dev_p
->endp
)/(sizeof(dev_p
->endp
[0])); i
++) {
603 lret
= cy_as_dma_stop_end_point(dev_p
, i
);
604 if (lret
!= CY_AS_ERROR_SUCCESS
&& ret
== CY_AS_ERROR_SUCCESS
)
609 * now, free the list of DMA requests structures that we use to manage
612 while (dev_p
->dma_freelist_p
) {
613 cy_as_dma_queue_entry
*req_p
;
614 uint32_t imask
= cy_as_hal_disable_interrupts();
616 req_p
= dev_p
->dma_freelist_p
;
617 dev_p
->dma_freelist_p
= req_p
->next_p
;
619 cy_as_hal_enable_interrupts(imask
);
621 cy_as_hal_free(req_p
);
624 cy_as_ll_destroy_request(dev_p
, dev_p
->usb_ep0_dma_req
);
625 cy_as_ll_destroy_request(dev_p
, dev_p
->usb_ep1_dma_req
);
626 cy_as_ll_destroy_response(dev_p
, dev_p
->usb_ep0_dma_resp
);
627 cy_as_ll_destroy_response(dev_p
, dev_p
->usb_ep1_dma_resp
);
636 * This function shuts down the DMA module. All resources
637 * associated with the DMA module will be freed. This
638 * routine is the API stop function. It insures that we
639 * are stopping a stack that is actually running and then
640 * calls the internal function to do the work.
642 cy_as_return_status_t
643 cy_as_dma_stop(cy_as_device
*dev_p
)
645 cy_as_return_status_t ret
;
647 ret
= cy_as_dma_stop_internal(dev_p
);
648 cy_as_device_set_dma_stopped(dev_p
);
656 * This function initializes the DMA module to insure it is up and running.
658 cy_as_return_status_t
659 cy_as_dma_start(cy_as_device
*dev_p
)
661 cy_as_end_point_number_t i
;
664 if (cy_as_device_is_dma_running(dev_p
))
665 return CY_AS_ERROR_ALREADY_RUNNING
;
668 * pre-allocate DMA queue structures to be used in the interrupt context
670 for (cnt
= 0; cnt
< 32; cnt
++) {
671 cy_as_dma_queue_entry
*entry_p
= (cy_as_dma_queue_entry
*)
672 cy_as_hal_alloc(sizeof(cy_as_dma_queue_entry
));
674 cy_as_dma_stop_internal(dev_p
);
675 return CY_AS_ERROR_OUT_OF_MEMORY
;
677 cy_as_dma_add_request_to_free_queue(dev_p
, entry_p
);
681 * pre-allocate the DMA requests for sending EP0
682 * and EP1 data to west bridge
684 dev_p
->usb_ep0_dma_req
= cy_as_ll_create_request(dev_p
,
685 CY_RQT_USB_EP_DATA
, CY_RQT_USB_RQT_CONTEXT
, 64);
686 dev_p
->usb_ep1_dma_req
= cy_as_ll_create_request(dev_p
,
687 CY_RQT_USB_EP_DATA
, CY_RQT_USB_RQT_CONTEXT
, 64);
689 if (dev_p
->usb_ep0_dma_req
== 0 || dev_p
->usb_ep1_dma_req
== 0) {
690 cy_as_dma_stop_internal(dev_p
);
691 return CY_AS_ERROR_OUT_OF_MEMORY
;
693 dev_p
->usb_ep0_dma_req_save
= dev_p
->usb_ep0_dma_req
;
695 dev_p
->usb_ep0_dma_resp
= cy_as_ll_create_response(dev_p
, 1);
696 dev_p
->usb_ep1_dma_resp
= cy_as_ll_create_response(dev_p
, 1);
697 if (dev_p
->usb_ep0_dma_resp
== 0 || dev_p
->usb_ep1_dma_resp
== 0) {
698 cy_as_dma_stop_internal(dev_p
);
699 return CY_AS_ERROR_OUT_OF_MEMORY
;
701 dev_p
->usb_ep0_dma_resp_save
= dev_p
->usb_ep0_dma_resp
;
704 * set the dev_p->endp to all zeros to insure cleanup is possible if
705 * an error occurs during initialization.
707 cy_as_hal_mem_set(dev_p
->endp
, 0, sizeof(dev_p
->endp
));
710 * now, iterate through each of the endpoints and initialize each
713 for (i
= 0; i
< sizeof(dev_p
->endp
)/sizeof(dev_p
->endp
[0]); i
++) {
714 dev_p
->endp
[i
] = (cy_as_dma_end_point
*)
715 cy_as_hal_alloc(sizeof(cy_as_dma_end_point
));
716 if (dev_p
->endp
[i
] == 0) {
717 cy_as_dma_stop_internal(dev_p
);
718 return CY_AS_ERROR_OUT_OF_MEMORY
;
720 cy_as_hal_mem_set(dev_p
->endp
[i
], 0,
721 sizeof(cy_as_dma_end_point
));
723 dev_p
->endp
[i
]->ep
= i
;
724 dev_p
->endp
[i
]->queue_p
= 0;
725 dev_p
->endp
[i
]->last_p
= 0;
727 cy_as_dma_set_drq(dev_p
, i
, cy_false
);
729 if (!cy_as_hal_create_sleep_channel(&dev_p
->endp
[i
]->channel
))
730 return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED
;
734 * tell the HAL layer who to call when the
735 * HAL layer completes a DMA request
737 cy_as_hal_dma_register_callback(dev_p
->tag
,
738 cy_as_dma_completed_callback
);
741 * mark DMA as up and running on this device
743 cy_as_device_set_dma_running(dev_p
);
745 return CY_AS_ERROR_SUCCESS
;
749 * Wait for all entries in the DMA queue associated
750 * the given endpoint to be drained. This function
751 * will not return until all the DMA data has been
754 cy_as_return_status_t
755 cy_as_dma_drain_queue(cy_as_device
*dev_p
,
756 cy_as_end_point_number_t ep
, cy_bool kickstart
)
758 cy_as_dma_end_point
*ep_p
;
759 int loopcount
= 1000;
763 * make sure the endpoint is valid
765 if (ep
>= sizeof(dev_p
->endp
)/sizeof(dev_p
->endp
[0]))
766 return CY_AS_ERROR_INVALID_ENDPOINT
;
768 /* Get the endpoint pointer based on the endpoint number */
769 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
772 * if the endpoint is empty of traffic, we return
773 * with success immediately
775 mask
= cy_as_hal_disable_interrupts();
776 if (ep_p
->queue_p
== 0) {
777 cy_as_hal_enable_interrupts(mask
);
778 return CY_AS_ERROR_SUCCESS
;
781 * add 10 seconds to the time out value for each 64 KB segment
782 * of data to be transferred.
784 if (ep_p
->queue_p
->size
> 0x10000)
785 loopcount
+= ((ep_p
->queue_p
->size
/ 0x10000) * 1000);
787 cy_as_hal_enable_interrupts(mask
);
789 /* If we are already sleeping on this endpoint, it is an error */
790 if (cy_as_dma_end_point_is_sleeping(ep_p
))
791 return CY_AS_ERROR_NESTED_SLEEP
;
794 * we disable the endpoint while the queue drains to
795 * prevent any additional requests from being queued while we are waiting
797 cy_as_dma_enable_end_point(dev_p
, ep
,
798 cy_false
, cy_as_direction_dont_change
);
802 * now, kick start the DMA if necessary
804 cy_as_dma_kick_start(dev_p
, ep
);
808 * check one last time before we begin sleeping to see if the
811 if (ep_p
->queue_p
== 0) {
812 cy_as_dma_enable_end_point(dev_p
, ep
, cy_true
,
813 cy_as_direction_dont_change
);
814 return CY_AS_ERROR_SUCCESS
;
817 while (loopcount
-- > 0) {
819 * sleep for 10 ms maximum (per loop) while
820 * waiting for the transfer to complete.
822 cy_as_dma_end_point_set_sleep_state(ep_p
);
823 cy_as_hal_sleep_on(&ep_p
->channel
, 10);
825 /* If we timed out, the sleep bit will still be set */
826 cy_as_dma_end_point_set_wake_state(ep_p
);
828 /* Check the queue to see if is drained */
829 if (ep_p
->queue_p
== 0) {
831 * clear the endpoint running and in transit flags
832 * for the endpoint, now that its DMA queue is empty.
834 cy_as_dma_end_point_clear_in_transit(ep_p
);
835 cy_as_dma_end_point_set_stopped(ep_p
);
837 cy_as_dma_enable_end_point(dev_p
, ep
,
838 cy_true
, cy_as_direction_dont_change
);
839 return CY_AS_ERROR_SUCCESS
;
844 * the DMA operation that has timed out can be cancelled, so that later
845 * operations on this queue can proceed.
847 cy_as_dma_cancel(dev_p
, ep
, CY_AS_ERROR_TIMEOUT
);
848 cy_as_dma_enable_end_point(dev_p
, ep
,
849 cy_true
, cy_as_direction_dont_change
);
850 return CY_AS_ERROR_TIMEOUT
;
854 * This function queues a write request in the DMA queue
855 * for a given endpoint. The direction of the
856 * entry will be inferred from the endpoint direction.
858 cy_as_return_status_t
859 cy_as_dma_queue_request(cy_as_device
*dev_p
,
860 cy_as_end_point_number_t ep
, void *mem_p
,
861 uint32_t size
, cy_bool pkt
, cy_bool readreq
, cy_as_dma_callback cb
)
864 cy_as_dma_queue_entry
*entry_p
;
865 cy_as_dma_end_point
*ep_p
;
868 * make sure the endpoint is valid
870 if (ep
>= sizeof(dev_p
->endp
)/sizeof(dev_p
->endp
[0]))
871 return CY_AS_ERROR_INVALID_ENDPOINT
;
873 /* Get the endpoint pointer based on the endpoint number */
874 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
876 if (!cy_as_dma_end_point_is_enabled(ep_p
))
877 return CY_AS_ERROR_ENDPOINT_DISABLED
;
879 entry_p
= cy_as_dma_get_dma_queue_entry(dev_p
);
881 entry_p
->buf_p
= mem_p
;
883 entry_p
->size
= size
;
885 entry_p
->packet
= pkt
;
886 entry_p
->readreq
= readreq
;
888 mask
= cy_as_hal_disable_interrupts();
891 ep_p
->last_p
->next_p
= entry_p
;
892 ep_p
->last_p
= entry_p
;
893 if (ep_p
->queue_p
== 0)
894 ep_p
->queue_p
= entry_p
;
895 cy_as_hal_enable_interrupts(mask
);
897 return CY_AS_ERROR_SUCCESS
;
901 * This function enables or disables and endpoint for DMA
902 * queueing. If an endpoint is disabled, any queue requests
903 * continue to be processed, but no new requests can be queued.
905 cy_as_return_status_t
906 cy_as_dma_enable_end_point(cy_as_device
*dev_p
,
907 cy_as_end_point_number_t ep
, cy_bool enable
, cy_as_dma_direction dir
)
909 cy_as_dma_end_point
*ep_p
;
912 * make sure the endpoint is valid
914 if (ep
>= sizeof(dev_p
->endp
)/sizeof(dev_p
->endp
[0]))
915 return CY_AS_ERROR_INVALID_ENDPOINT
;
917 /* Get the endpoint pointer based on the endpoint number */
918 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
920 if (dir
== cy_as_direction_out
)
921 cy_as_dma_end_point_set_direction_out(ep_p
);
922 else if (dir
== cy_as_direction_in
)
923 cy_as_dma_end_point_set_direction_in(ep_p
);
926 * get the maximum size of data buffer the HAL
927 * layer can accept. this is used when the DMA
928 * module is sending DMA requests to the HAL.
929 * the DMA module will never send down a request
930 * that is greater than this value.
932 * for EP0 and EP1, we can send no more than 64
933 * bytes of data at one time as this is the maximum
934 * size of a packet that can be sent via these
937 if (ep
== 0 || ep
== 1)
938 ep_p
->maxhaldata
= 64;
940 ep_p
->maxhaldata
= cy_as_hal_dma_max_request_size(
944 cy_as_dma_end_point_enable(ep_p
);
946 cy_as_dma_end_point_disable(ep_p
);
948 return CY_AS_ERROR_SUCCESS
;
952 * This function cancels any DMA operations pending with the HAL layer as well
953 * as any DMA operation queued on the endpoint.
955 cy_as_return_status_t
958 cy_as_end_point_number_t ep
,
959 cy_as_return_status_t err
)
962 cy_as_dma_end_point
*ep_p
;
963 cy_as_dma_queue_entry
*entry_p
;
967 * make sure the endpoint is valid
969 if (ep
>= sizeof(dev_p
->endp
)/sizeof(dev_p
->endp
[0]))
970 return CY_AS_ERROR_INVALID_ENDPOINT
;
972 /* Get the endpoint pointer based on the endpoint number */
973 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
976 /* Remember the state of the endpoint */
977 epstate
= cy_as_dma_end_point_is_enabled(ep_p
);
980 * disable the endpoint so no more DMA packets can be
983 cy_as_dma_enable_end_point(dev_p
, ep
,
984 cy_false
, cy_as_direction_dont_change
);
987 * don't allow any interrupts from this endpoint
988 * while we get the most current request off of
991 cy_as_dma_set_drq(dev_p
, ep
, cy_false
);
994 * cancel any pending request queued in the HAL layer
996 if (cy_as_dma_end_point_in_transit(ep_p
))
997 cy_as_hal_dma_cancel_request(dev_p
->tag
, ep_p
->ep
);
1000 * shutdown the DMA for this endpoint so no
1001 * more data is transferred
1003 cy_as_dma_end_point_set_stopped(ep_p
);
1006 * mark the endpoint as not in transit, because we are
1007 * going to consume any queued requests
1009 cy_as_dma_end_point_clear_in_transit(ep_p
);
1012 * now, remove each entry in the queue and call the
1013 * associated callback stating that the request was
1017 while (ep_p
->queue_p
!= 0) {
1018 /* Disable interrupts to manipulate the queue */
1019 mask
= cy_as_hal_disable_interrupts();
1021 /* Remove an entry from the queue */
1022 entry_p
= ep_p
->queue_p
;
1023 ep_p
->queue_p
= entry_p
->next_p
;
1025 /* Ok, the queue has been updated, we can
1026 * turn interrupts back on */
1027 cy_as_hal_enable_interrupts(mask
);
1029 /* Call the callback indicating we have
1030 * canceled the DMA */
1032 entry_p
->cb(dev_p
, ep
,
1033 entry_p
->buf_p
, entry_p
->size
, err
);
1035 cy_as_dma_add_request_to_free_queue(dev_p
, entry_p
);
1038 if (ep
== 0 || ep
== 1) {
1040 * if this endpoint is zero or one, we need to
1041 * clear the queue of any pending CY_RQT_USB_EP_DATA
1042 * requests as these are pending requests to send
1043 * data to the west bridge device.
1045 cy_as_ll_remove_ep_data_requests(dev_p
, ep
);
1050 * the endpoint started out enabled, so we
1051 * re-enable the endpoint here.
1053 cy_as_dma_enable_end_point(dev_p
, ep
,
1054 cy_true
, cy_as_direction_dont_change
);
1058 return CY_AS_ERROR_SUCCESS
;
1061 cy_as_return_status_t
1062 cy_as_dma_received_data(cy_as_device
*dev_p
,
1063 cy_as_end_point_number_t ep
, uint32_t dsize
, void *data
)
1065 cy_as_dma_queue_entry
*dma_p
;
1066 uint8_t *src_p
, *dest_p
;
1067 cy_as_dma_end_point
*ep_p
;
1071 * make sure the endpoint is valid
1073 if (ep
!= 0 && ep
!= 1)
1074 return CY_AS_ERROR_INVALID_ENDPOINT
;
1076 /* Get the endpoint pointer based on the endpoint number */
1077 ep_p
= CY_AS_NUM_EP(dev_p
, ep
);
1078 dma_p
= ep_p
->queue_p
;
1080 return CY_AS_ERROR_SUCCESS
;
1083 * if the data received exceeds the size of the DMA buffer,
1084 * clip the data to the size of the buffer. this can lead
1085 * to losing some data, but is not different than doing
1086 * non-packet reads on the other endpoints.
1088 if (dsize
> dma_p
->size
- dma_p
->offset
)
1089 dsize
= dma_p
->size
- dma_p
->offset
;
1092 * copy the data from the request packet to the DMA buffer
1095 src_p
= (uint8_t *)data
;
1096 dest_p
= ((uint8_t *)(dma_p
->buf_p
)) + dma_p
->offset
;
1098 while (xfersize
-- > 0)
1099 *dest_p
++ = *src_p
++;
1101 /* Signal the DMA module that we have
1102 * received data for this EP request */
1103 cy_as_dma_completed_callback(dev_p
->tag
,
1104 ep
, dsize
, CY_AS_ERROR_SUCCESS
);
1106 return CY_AS_ERROR_SUCCESS
;