linux/drivers/staging/westbridge/astoria/api/src/cyasdma.c
<<
>>
Prefs
   1/* Cypress West Bridge API source file (cyasdma.c)
   2## ===========================
   3## Copyright (C) 2010  Cypress Semiconductor
   4##
   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.
   9##
  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.
  14##
  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## ===========================
  20*/
  21
  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"
  27
  28/*
  29 * Add the DMA queue entry to the free list to be re-used later
  30 */
  31static void
  32cy_as_dma_add_request_to_free_queue(cy_as_device *dev_p,
  33        cy_as_dma_queue_entry *req_p)
  34{
  35        uint32_t imask;
  36        imask = cy_as_hal_disable_interrupts();
  37
  38        req_p->next_p = dev_p->dma_freelist_p;
  39        dev_p->dma_freelist_p = req_p;
  40
  41        cy_as_hal_enable_interrupts(imask);
  42}
  43
  44/*
  45 * Get a DMA queue entry from the free list.
  46 */
  47static cy_as_dma_queue_entry *
  48cy_as_dma_get_dma_queue_entry(cy_as_device *dev_p)
  49{
  50        cy_as_dma_queue_entry *req_p;
  51        uint32_t imask;
  52
  53        cy_as_hal_assert(dev_p->dma_freelist_p != 0);
  54
  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);
  59
  60        return req_p;
  61}
  62
  63/*
  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.
  69 */
  70cy_as_return_status_t
  71cy_as_dma_set_max_dma_size(cy_as_device *dev_p,
  72                cy_as_end_point_number_t ep, uint32_t size)
  73{
  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;
  78        }
  79
  80        CY_AS_NUM_EP(dev_p, ep)->maxhwdata = (uint16_t)size;
  81        return CY_AS_ERROR_SUCCESS;
  82}
  83
  84/*
  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.
  90 */
  91static void
  92cy_as_dma_request_callback(
  93        cy_as_device *dev_p,
  94        uint8_t context,
  95        cy_as_ll_request_response *req_p,
  96        cy_as_ll_request_response *resp_p,
  97        cy_as_return_status_t ret)
  98{
  99        uint16_t v;
 100        uint16_t datacnt;
 101        cy_as_end_point_number_t ep;
 102
 103        (void)context;
 104
 105        cy_as_log_debug_message(5, "cy_as_dma_request_callback called");
 106
 107        /*
 108         * extract the return code from the firmware
 109         */
 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;
 114                else
 115                        ret = cy_as_ll_request_response__get_word(resp_p, 0);
 116        }
 117
 118        /*
 119         * extract the endpoint number and the transferred byte count
 120         * from the request.
 121         */
 122        v = cy_as_ll_request_response__get_word(req_p, 0);
 123        ep = (cy_as_end_point_number_t)((v >> 13) & 0x01);
 124
 125        if (ret == CY_AS_ERROR_SUCCESS) {
 126                /*
 127                 * if the firmware returns success,
 128                 * all of the data requested was
 129                 * transferred.  there are no partial
 130                 * transfers.
 131                 */
 132                datacnt = v & 0x3FF;
 133        } else {
 134                /*
 135                 * if the firmware returned an error, no data was transferred.
 136                 */
 137                datacnt = 0;
 138        }
 139
 140        /*
 141         * queue the request and response data structures for use with the
 142         * next EP0 or EP1 request.
 143         */
 144        if (ep == 0) {
 145                dev_p->usb_ep0_dma_req = req_p;
 146                dev_p->usb_ep0_dma_resp = resp_p;
 147        } else {
 148                dev_p->usb_ep1_dma_req = req_p;
 149                dev_p->usb_ep1_dma_resp = resp_p;
 150        }
 151
 152        /*
 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
 159         * function.
 160         */
 161        if (ret != CY_AS_ERROR_CANCELED)
 162                cy_as_dma_completed_callback(dev_p->tag, ep, datacnt, ret);
 163}
 164
 165/*
 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
 168 * it is disabled.
 169 */
 170static void
 171cy_as_dma_set_drq(cy_as_device *dev_p,
 172                cy_as_end_point_number_t ep, cy_bool state)
 173{
 174        uint16_t mask;
 175        uint16_t v;
 176        uint32_t intval;
 177
 178        /*
 179         * there are not DRQ register bits for EP0 and EP1
 180         */
 181        if (ep == 0 || ep == 1)
 182                return;
 183
 184        /*
 185         * disable interrupts while we do this to be sure the state of the
 186         * DRQ mask register is always well defined.
 187         */
 188        intval = cy_as_hal_disable_interrupts();
 189
 190        /*
 191         * set the DRQ bit to the given state for the ep given
 192         */
 193        mask = (1 << ep);
 194        v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK);
 195
 196        if (state)
 197                v |= mask;
 198        else
 199                v &= ~mask;
 200
 201        cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK, v);
 202        cy_as_hal_enable_interrupts(intval);
 203}
 204
 205/*
 206* Send the next DMA request for the endpoint given
 207*/
 208static void
 209cy_as_dma_send_next_dma_request(cy_as_device *dev_p, cy_as_dma_end_point *ep_p)
 210{
 211        uint32_t datacnt;
 212        void *buf_p;
 213        cy_as_dma_queue_entry *dma_p;
 214
 215        cy_as_log_debug_message(6, "cy_as_dma_send_next_dma_request called");
 216
 217        /* If the queue is empty, nothing to do */
 218        dma_p = ep_p->queue_p;
 219        if (dma_p == 0) {
 220                /*
 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.
 226                 */
 227                cy_as_dma_set_drq(dev_p, ep_p->ep, cy_false);
 228                return;
 229        }
 230
 231        cy_as_dma_end_point_set_running(ep_p);
 232
 233        /*
 234         * get the number of words that still
 235         * need to be xferred in this request.
 236         */
 237        datacnt = dma_p->size - dma_p->offset;
 238        cy_as_hal_assert(datacnt >= 0);
 239
 240        /*
 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.
 245         */
 246        cy_as_hal_assert(ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE
 247                        || ep_p->maxhaldata >= ep_p->maxhwdata);
 248
 249        /*
 250         * update the number of words that need to be xferred yet
 251         * based on the limits of the HAL layer.
 252         */
 253        if (ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE) {
 254                if (datacnt > ep_p->maxhwdata)
 255                        datacnt = ep_p->maxhwdata;
 256        } else {
 257                if (datacnt > ep_p->maxhaldata)
 258                        datacnt = ep_p->maxhaldata;
 259        }
 260
 261        /*
 262         * find a pointer to the data that needs to be transferred
 263         */
 264        buf_p = (((char *)dma_p->buf_p) + dma_p->offset);
 265
 266        /*
 267         * mark a request in transit
 268         */
 269        cy_as_dma_end_point_set_in_transit(ep_p);
 270
 271        if (ep_p->ep == 0 || ep_p->ep == 1) {
 272                /*
 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.
 281                 */
 282                if (dma_p->readreq == cy_false) {
 283                        uint16_t v;
 284                        uint16_t len;
 285                        cy_as_ll_request_response *resp_p;
 286                        cy_as_ll_request_response *req_p;
 287                        cy_as_return_status_t ret;
 288
 289                        len = (uint16_t)(datacnt / 2);
 290                        if (datacnt % 2)
 291                                len++;
 292
 293                        len++;
 294
 295                        if (ep_p->ep == 0) {
 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;
 300                        } else {
 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;
 305                        }
 306
 307                        cy_as_hal_assert(req_p != 0);
 308                        cy_as_hal_assert(resp_p != 0);
 309                        cy_as_hal_assert(len <= 64);
 310
 311                        cy_as_ll_init_request(req_p, CY_RQT_USB_EP_DATA,
 312                                CY_RQT_USB_RQT_CONTEXT, len);
 313
 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 */
 319
 320                        cy_as_ll_request_response__set_word(req_p, 0, v);
 321                        cy_as_ll_request_response__pack(req_p,
 322                                        1, datacnt, buf_p);
 323
 324                        cy_as_ll_init_response(resp_p, 1);
 325
 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");
 331                        else
 332                                cy_as_log_debug_message(5,
 333                                "+++ error sending EP 0/1 data via mailbox "
 334                                "registers - CY_AS_ERROR_TIMEOUT");
 335
 336                        if (ret != CY_AS_ERROR_SUCCESS)
 337                                cy_as_dma_completed_callback(dev_p->tag,
 338                                        ep_p->ep, 0, ret);
 339                }
 340        } else {
 341                /*
 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
 352                 * be.
 353                 */
 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);
 357                else
 358                        cy_as_hal_dma_setup_read(dev_p->tag,
 359                                ep_p->ep, buf_p, datacnt, ep_p->maxhwdata);
 360
 361                /*
 362                 * the DRQ interrupt for this endpoint should be enabled
 363                 * so that the data transfer progresses at interrupt time.
 364                 */
 365                cy_as_dma_set_drq(dev_p, ep_p->ep, cy_true);
 366        }
 367}
 368
 369/*
 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.
 375 */
 376void
 377cy_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)
 379{
 380        uint32_t mask;
 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);
 384
 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);
 389
 390
 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);
 394
 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;
 398
 399        /* Update the offset to reflect the data actually received or sent */
 400        req_p->offset += cnt;
 401
 402        /*
 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.
 411         *
 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.
 415         *
 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.
 419         */
 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);
 426
 427                /*
 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.
 432                 */
 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);
 437                else
 438                        cy_as_dma_send_next_dma_request(dev_p, ep_p);
 439        } else {
 440                /*
 441                 * we get here if ...
 442                 *      we have sent or received all of the data
 443                 *               or
 444                 *      we are doing a packet operation
 445                 *               or
 446                 *      we receive a short packet
 447                 */
 448
 449                /*
 450                 * remove this entry from the DMA queue for this endpoint.
 451                 */
 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) {
 455                        /*
 456                         * we have removed the last packet from the DMA queue,
 457                         * disable the interrupt associated with this interrupt.
 458                         */
 459                        ep_p->last_p = 0;
 460                        cy_as_hal_enable_interrupts(mask);
 461                        cy_as_dma_set_drq(dev_p, ep, cy_false);
 462                } else
 463                        cy_as_hal_enable_interrupts(mask);
 464
 465                if (req_p->cb) {
 466                        /*
 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.
 470                         *
 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.
 474                         */
 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);
 479                }
 480
 481                /*
 482                 * we are done with this request, put it on the freelist to be
 483                 * reused at a later time.
 484                 */
 485                cy_as_dma_add_request_to_free_queue(dev_p, req_p);
 486
 487                if (ep_p->queue_p == 0) {
 488                        /*
 489                         * if the endpoint is out of DMA entries, set the
 490                         * endpoint as stopped.
 491                         */
 492                        cy_as_dma_end_point_set_stopped(ep_p);
 493
 494                        /*
 495                         * the DMA queue is empty, wake any task waiting on
 496                         * the QUEUE to drain.
 497                         */
 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);
 501                        }
 502                } else {
 503                        /*
 504                         * if the queued operation is a MTP transfer,
 505                         * wait until firmware event before sending
 506                         * down the next DMA request.
 507                         */
 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);
 516                        else
 517                                cy_as_dma_send_next_dma_request(dev_p, ep_p);
 518                }
 519        }
 520}
 521
 522/*
 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.
 528*/
 529cy_as_return_status_t
 530cy_as_dma_kick_start(cy_as_device *dev_p, cy_as_end_point_number_t ep)
 531{
 532        cy_as_dma_end_point *ep_p;
 533        cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
 534
 535        ep_p = CY_AS_NUM_EP(dev_p, ep);
 536
 537        /* We are already running */
 538        if (cy_as_dma_end_point_is_running(ep_p))
 539                return CY_AS_ERROR_SUCCESS;
 540
 541        cy_as_dma_send_next_dma_request(dev_p, ep_p);
 542        return CY_AS_ERROR_SUCCESS;
 543}
 544
 545/*
 546 * This function stops the given endpoint.  Stopping and endpoint cancels
 547 * any pending DMA operations and frees all resources associated with the
 548 * given endpoint.
 549 */
 550static cy_as_return_status_t
 551cy_as_dma_stop_end_point(cy_as_device *dev_p, cy_as_end_point_number_t ep)
 552{
 553        cy_as_return_status_t ret;
 554        cy_as_dma_end_point *ep_p = CY_AS_NUM_EP(dev_p, ep);
 555
 556        /*
 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.
 560         */
 561        ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
 562        if (ret != CY_AS_ERROR_SUCCESS)
 563                return ret;
 564
 565        /*
 566         * destroy the sleep channel
 567         */
 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;
 571
 572        /*
 573         * free the memory associated with this endpoint
 574         */
 575        cy_as_hal_free(ep_p);
 576
 577        /*
 578         * set the data structure ptr to something sane since the
 579         * previous pointer is now free.
 580         */
 581        dev_p->endp[ep] = 0;
 582
 583        return ret;
 584}
 585
 586/*
 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).
 590 */
 591static cy_as_return_status_t
 592cy_as_dma_stop_internal(cy_as_device *dev_p)
 593{
 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;
 597
 598        /*
 599         * stop all of the endpoints.  this cancels all DMA requests, and
 600         * frees all resources associated with each endpoint.
 601         */
 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)
 605                        ret = lret;
 606        }
 607
 608        /*
 609         * now, free the list of DMA requests structures that we use to manage
 610         * DMA requests.
 611         */
 612        while (dev_p->dma_freelist_p) {
 613                cy_as_dma_queue_entry *req_p;
 614                uint32_t imask = cy_as_hal_disable_interrupts();
 615
 616                req_p = dev_p->dma_freelist_p;
 617                dev_p->dma_freelist_p = req_p->next_p;
 618
 619                cy_as_hal_enable_interrupts(imask);
 620
 621                cy_as_hal_free(req_p);
 622        }
 623
 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);
 628
 629        return ret;
 630}
 631
 632
 633/*
 634 * CyAsDmaStop()
 635 *
 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.
 641 */
 642cy_as_return_status_t
 643cy_as_dma_stop(cy_as_device *dev_p)
 644{
 645        cy_as_return_status_t ret;
 646
 647        ret = cy_as_dma_stop_internal(dev_p);
 648        cy_as_device_set_dma_stopped(dev_p);
 649
 650        return ret;
 651}
 652
 653/*
 654 * CyAsDmaStart()
 655 *
 656 * This function intializes the DMA module to insure it is up and running.
 657 */
 658cy_as_return_status_t
 659cy_as_dma_start(cy_as_device *dev_p)
 660{
 661        cy_as_end_point_number_t i;
 662        uint16_t cnt;
 663
 664        if (cy_as_device_is_dma_running(dev_p))
 665                return CY_AS_ERROR_ALREADY_RUNNING;
 666
 667        /*
 668         * pre-allocate DMA queue structures to be used in the interrupt context
 669         */
 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));
 673                if (entry_p == 0) {
 674                        cy_as_dma_stop_internal(dev_p);
 675                        return CY_AS_ERROR_OUT_OF_MEMORY;
 676                }
 677                cy_as_dma_add_request_to_free_queue(dev_p, entry_p);
 678        }
 679
 680        /*
 681         * pre-allocate the DMA requests for sending EP0
 682         * and EP1 data to west bridge
 683         */
 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);
 688
 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;
 692        }
 693        dev_p->usb_ep0_dma_req_save = dev_p->usb_ep0_dma_req;
 694
 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;
 700        }
 701        dev_p->usb_ep0_dma_resp_save = dev_p->usb_ep0_dma_resp;
 702
 703        /*
 704         * set the dev_p->endp to all zeros to insure cleanup is possible if
 705         * an error occurs during initialization.
 706         */
 707        cy_as_hal_mem_set(dev_p->endp, 0, sizeof(dev_p->endp));
 708
 709        /*
 710         * now, iterate through each of the endpoints and initialize each
 711         * one.
 712         */
 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;
 719                }
 720                cy_as_hal_mem_set(dev_p->endp[i], 0,
 721                        sizeof(cy_as_dma_end_point));
 722
 723                dev_p->endp[i]->ep = i;
 724                dev_p->endp[i]->queue_p = 0;
 725                dev_p->endp[i]->last_p = 0;
 726
 727                cy_as_dma_set_drq(dev_p, i, cy_false);
 728
 729                if (!cy_as_hal_create_sleep_channel(&dev_p->endp[i]->channel))
 730                        return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED;
 731        }
 732
 733        /*
 734         * tell the HAL layer who to call when the
 735         * HAL layer completes a DMA request
 736         */
 737        cy_as_hal_dma_register_callback(dev_p->tag,
 738                cy_as_dma_completed_callback);
 739
 740        /*
 741         * mark DMA as up and running on this device
 742         */
 743        cy_as_device_set_dma_running(dev_p);
 744
 745        return CY_AS_ERROR_SUCCESS;
 746}
 747
 748/*
 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
 752* transferred.
 753*/
 754cy_as_return_status_t
 755cy_as_dma_drain_queue(cy_as_device *dev_p,
 756        cy_as_end_point_number_t ep, cy_bool kickstart)
 757{
 758        cy_as_dma_end_point *ep_p;
 759        int loopcount = 1000;
 760        uint32_t mask;
 761
 762        /*
 763        * make sure the endpoint is valid
 764        */
 765        if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
 766                return CY_AS_ERROR_INVALID_ENDPOINT;
 767
 768        /* Get the endpoint pointer based on the endpoint number */
 769        ep_p = CY_AS_NUM_EP(dev_p, ep);
 770
 771        /*
 772        * if the endpoint is empty of traffic, we return
 773        * with success immediately
 774        */
 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;
 779        } else {
 780                /*
 781                 * add 10 seconds to the time out value for each 64 KB segment
 782                 * of data to be transferred.
 783                 */
 784                if (ep_p->queue_p->size > 0x10000)
 785                        loopcount += ((ep_p->queue_p->size / 0x10000) * 1000);
 786        }
 787        cy_as_hal_enable_interrupts(mask);
 788
 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;
 792
 793        /*
 794        * we disable the endpoint while the queue drains to
 795        * prevent any additional requests from being queued while we are waiting
 796        */
 797        cy_as_dma_enable_end_point(dev_p, ep,
 798                cy_false, cy_as_direction_dont_change);
 799
 800        if (kickstart) {
 801                /*
 802                * now, kick start the DMA if necessary
 803                */
 804                cy_as_dma_kick_start(dev_p, ep);
 805        }
 806
 807        /*
 808        * check one last time before we begin sleeping to see if the
 809        * queue is drained.
 810        */
 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;
 815        }
 816
 817        while (loopcount-- > 0) {
 818                /*
 819                 * sleep for 10 ms maximum (per loop) while
 820                 * waiting for the transfer to complete.
 821                 */
 822                cy_as_dma_end_point_set_sleep_state(ep_p);
 823                cy_as_hal_sleep_on(&ep_p->channel, 10);
 824
 825                /* If we timed out, the sleep bit will still be set */
 826                cy_as_dma_end_point_set_wake_state(ep_p);
 827
 828                /* Check the queue to see if is drained */
 829                if (ep_p->queue_p == 0) {
 830                        /*
 831                         * clear the endpoint running and in transit flags
 832                         * for the endpoint, now that its DMA queue is empty.
 833                         */
 834                        cy_as_dma_end_point_clear_in_transit(ep_p);
 835                        cy_as_dma_end_point_set_stopped(ep_p);
 836
 837                        cy_as_dma_enable_end_point(dev_p, ep,
 838                                cy_true, cy_as_direction_dont_change);
 839                        return CY_AS_ERROR_SUCCESS;
 840                }
 841        }
 842
 843        /*
 844         * the DMA operation that has timed out can be cancelled, so that later
 845         * operations on this queue can proceed.
 846         */
 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;
 851}
 852
 853/*
 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.
 857*/
 858cy_as_return_status_t
 859cy_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)
 862{
 863        uint32_t mask;
 864        cy_as_dma_queue_entry *entry_p;
 865        cy_as_dma_end_point *ep_p;
 866
 867        /*
 868        * make sure the endpoint is valid
 869        */
 870        if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
 871                return CY_AS_ERROR_INVALID_ENDPOINT;
 872
 873        /* Get the endpoint pointer based on the endpoint number */
 874        ep_p = CY_AS_NUM_EP(dev_p, ep);
 875
 876        if (!cy_as_dma_end_point_is_enabled(ep_p))
 877                return CY_AS_ERROR_ENDPOINT_DISABLED;
 878
 879        entry_p = cy_as_dma_get_dma_queue_entry(dev_p);
 880
 881        entry_p->buf_p = mem_p;
 882        entry_p->cb = cb;
 883        entry_p->size = size;
 884        entry_p->offset = 0;
 885        entry_p->packet = pkt;
 886        entry_p->readreq = readreq;
 887
 888        mask = cy_as_hal_disable_interrupts();
 889        entry_p->next_p = 0;
 890        if (ep_p->last_p)
 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);
 896
 897        return CY_AS_ERROR_SUCCESS;
 898}
 899
 900/*
 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.
 904*/
 905cy_as_return_status_t
 906cy_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)
 908{
 909        cy_as_dma_end_point *ep_p;
 910
 911        /*
 912        * make sure the endpoint is valid
 913        */
 914        if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
 915                return CY_AS_ERROR_INVALID_ENDPOINT;
 916
 917        /* Get the endpoint pointer based on the endpoint number */
 918        ep_p = CY_AS_NUM_EP(dev_p, ep);
 919
 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);
 924
 925        /*
 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.
 931        *
 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
 935        * endpoints.
 936        */
 937        if (ep == 0 || ep == 1)
 938                ep_p->maxhaldata = 64;
 939        else
 940                ep_p->maxhaldata = cy_as_hal_dma_max_request_size(
 941                                                dev_p->tag, ep);
 942
 943        if (enable)
 944                cy_as_dma_end_point_enable(ep_p);
 945        else
 946                cy_as_dma_end_point_disable(ep_p);
 947
 948        return CY_AS_ERROR_SUCCESS;
 949}
 950
 951/*
 952 * This function cancels any DMA operations pending with the HAL layer as well
 953 * as any DMA operation queued on the endpoint.
 954 */
 955cy_as_return_status_t
 956cy_as_dma_cancel(
 957        cy_as_device *dev_p,
 958        cy_as_end_point_number_t ep,
 959        cy_as_return_status_t err)
 960{
 961        uint32_t mask;
 962        cy_as_dma_end_point *ep_p;
 963        cy_as_dma_queue_entry *entry_p;
 964        cy_bool epstate;
 965
 966        /*
 967         * make sure the endpoint is valid
 968         */
 969        if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0]))
 970                return CY_AS_ERROR_INVALID_ENDPOINT;
 971
 972        /* Get the endpoint pointer based on the endpoint number */
 973        ep_p = CY_AS_NUM_EP(dev_p, ep);
 974
 975        if (ep_p) {
 976                /* Remember the state of the endpoint */
 977                epstate = cy_as_dma_end_point_is_enabled(ep_p);
 978
 979                /*
 980                 * disable the endpoint so no more DMA packets can be
 981                 * queued.
 982                 */
 983                cy_as_dma_enable_end_point(dev_p, ep,
 984                        cy_false, cy_as_direction_dont_change);
 985
 986                /*
 987                 * don't allow any interrupts from this endpoint
 988                 * while we get the most current request off of
 989                 * the queue.
 990                 */
 991                cy_as_dma_set_drq(dev_p, ep, cy_false);
 992
 993                /*
 994                 * cancel any pending request queued in the HAL layer
 995                 */
 996                if (cy_as_dma_end_point_in_transit(ep_p))
 997                        cy_as_hal_dma_cancel_request(dev_p->tag, ep_p->ep);
 998
 999                /*
1000                 * shutdown the DMA for this endpoint so no
1001                 * more data is transferred
1002                 */
1003                cy_as_dma_end_point_set_stopped(ep_p);
1004
1005                /*
1006                 * mark the endpoint as not in transit, because we are
1007                 * going to consume any queued requests
1008                 */
1009                cy_as_dma_end_point_clear_in_transit(ep_p);
1010
1011                /*
1012                 * now, remove each entry in the queue and call the
1013                 * associated callback stating that the request was
1014                 * canceled.
1015                 */
1016                ep_p->last_p = 0;
1017                while (ep_p->queue_p != 0) {
1018                        /* Disable interrupts to manipulate the queue */
1019                        mask = cy_as_hal_disable_interrupts();
1020
1021                        /* Remove an entry from the queue */
1022                        entry_p = ep_p->queue_p;
1023                        ep_p->queue_p = entry_p->next_p;
1024
1025                        /* Ok, the queue has been updated, we can
1026                         * turn interrupts back on */
1027                        cy_as_hal_enable_interrupts(mask);
1028
1029                        /* Call the callback indicating we have
1030                         * canceled the DMA */
1031                        if (entry_p->cb)
1032                                entry_p->cb(dev_p, ep,
1033                                        entry_p->buf_p, entry_p->size, err);
1034
1035                        cy_as_dma_add_request_to_free_queue(dev_p, entry_p);
1036                }
1037
1038                if (ep == 0 || ep == 1) {
1039                        /*
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.
1044                         */
1045                        cy_as_ll_remove_ep_data_requests(dev_p, ep);
1046                }
1047
1048                if (epstate) {
1049                        /*
1050                         * the endpoint started out enabled, so we
1051                         * re-enable the endpoint here.
1052                         */
1053                        cy_as_dma_enable_end_point(dev_p, ep,
1054                                cy_true, cy_as_direction_dont_change);
1055                }
1056        }
1057
1058        return CY_AS_ERROR_SUCCESS;
1059}
1060
1061cy_as_return_status_t
1062cy_as_dma_received_data(cy_as_device *dev_p,
1063        cy_as_end_point_number_t ep, uint32_t dsize, void *data)
1064{
1065        cy_as_dma_queue_entry *dma_p;
1066        uint8_t *src_p, *dest_p;
1067        cy_as_dma_end_point *ep_p;
1068        uint32_t xfersize;
1069
1070        /*
1071         * make sure the endpoint is valid
1072         */
1073        if (ep != 0 && ep != 1)
1074                return CY_AS_ERROR_INVALID_ENDPOINT;
1075
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;
1079        if (dma_p == 0)
1080                return CY_AS_ERROR_SUCCESS;
1081
1082        /*
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 loosing some data, but is not different than doing
1086         * non-packet reads on the other endpoints.
1087         */
1088        if (dsize > dma_p->size - dma_p->offset)
1089                dsize = dma_p->size - dma_p->offset;
1090
1091        /*
1092         * copy the data from the request packet to the DMA buffer
1093         * for the endpoint
1094         */
1095        src_p = (uint8_t *)data;
1096        dest_p = ((uint8_t *)(dma_p->buf_p)) + dma_p->offset;
1097        xfersize = dsize;
1098        while (xfersize-- > 0)
1099                *dest_p++ = *src_p++;
1100
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);
1105
1106        return CY_AS_ERROR_SUCCESS;
1107}
1108