diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index f42477738f82..c070b216e1ac 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -153,5 +153,7 @@ source "drivers/staging/tidspbridge/Kconfig" source "drivers/staging/quickstart/Kconfig" +source "drivers/staging/westbridge/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a4ab683f4a69..90d89ea47b80 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_EASYCAP) += easycap/ obj-$(CONFIG_SOLO6X10) += solo6x10/ obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/ obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/ +obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/ diff --git a/drivers/staging/westbridge/Kconfig b/drivers/staging/westbridge/Kconfig new file mode 100644 index 000000000000..f7377c2f39c0 --- /dev/null +++ b/drivers/staging/westbridge/Kconfig @@ -0,0 +1,34 @@ +# +# West Bridge configuration +# + +menuconfig WESTBRIDGE + tristate "West Bridge support" + depends on HAS_IOMEM + help + This selects West Bridge Peripheral controller support. + + If you want West Bridge support, you should say Y here. + +menuconfig WESTBRIDGE_ASTORIA + bool "West Bridge Astoria support" + depends on WESTBRIDGE != n + help + This option enables support for West Bridge Astoria + +if WESTBRIDGE_ASTORIA +source "drivers/staging/westbridge/astoria/Kconfig" +endif #WESTBRIDGE_ASTORIA + +menuconfig MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + bool "WESTBRIDGE OMAP3430 Astoria PNAND HAL" + depends on ARCH_OMAP3 && WESTBRIDGE_ASTORIA + help + Include the OMAP3430 Linux Based HAL + +config WESTBRIDGE_DEBUG + bool "West Bridge debugging" + depends on WESTBRIDGE != n + help + This is an option for use by developers; most people should + say N here. This enables WESTBRIDGE core and driver debugging. \ No newline at end of file diff --git a/drivers/staging/westbridge/TODO b/drivers/staging/westbridge/TODO new file mode 100644 index 000000000000..6ca80581bbe2 --- /dev/null +++ b/drivers/staging/westbridge/TODO @@ -0,0 +1,7 @@ +TODO: +- checkpatch.pl fixes +- determine where to put the hal and common api code +- modify the driver directory structure in an intuitive way + +Please send any patches to Greg Kroah-Hartman +and David Cross . diff --git a/drivers/staging/westbridge/astoria/Kconfig b/drivers/staging/westbridge/astoria/Kconfig new file mode 100644 index 000000000000..1ce388acbfeb --- /dev/null +++ b/drivers/staging/westbridge/astoria/Kconfig @@ -0,0 +1,9 @@ +# +# West Bridge configuration +# +source "drivers/staging/westbridge/astoria/device/Kconfig" + +source "drivers/staging/westbridge/astoria/block/Kconfig" + +source "drivers/staging/westbridge/astoria/gadget/Kconfig" + diff --git a/drivers/staging/westbridge/astoria/Makefile b/drivers/staging/westbridge/astoria/Makefile new file mode 100644 index 000000000000..907bdb25804b --- /dev/null +++ b/drivers/staging/westbridge/astoria/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the kernel westbridge device drivers. +# + +ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y) + EXTRA_CFLAGS += -WESTBRIDGE_NDEBUG +endif + +obj-$(CONFIG_WESTBRIDGE) += device/ +obj-$(CONFIG_WESTBRIDGE) += block/ +obj-$(CONFIG_WESTBRIDGE) += gadget/ \ No newline at end of file diff --git a/drivers/staging/westbridge/astoria/api/Makefile b/drivers/staging/westbridge/astoria/api/Makefile new file mode 100644 index 000000000000..1c94bc7bb310 --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the kernel westbridge core. +# + +ifeq ($(CONFIG_WESTBRIDGE_DEBUG),n) + EXTRA_CFLAGS += -NDEBUG +endif + +obj-$(CONFIG_WESTBRIDGE_DEVICE_DRIVER) += cyasapi.o +cyasapi-y := src/cyasdma.o src/cyasintr.o src/cyaslep2pep.o \ + src/cyaslowlevel.o src/cyasmisc.o src/cyasmtp.o \ + src/cyasstorage.o src/cyasusb.o + + diff --git a/drivers/staging/westbridge/astoria/api/src/cyasdma.c b/drivers/staging/westbridge/astoria/api/src/cyasdma.c new file mode 100644 index 000000000000..152591d93ec2 --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasdma.c @@ -0,0 +1,1107 @@ +/* Cypress West Bridge API source file (cyasdma.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasdma.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasregs.h" + +/* + * Add the DMA queue entry to the free list to be re-used later + */ +static void +cy_as_dma_add_request_to_free_queue(cy_as_device *dev_p, + cy_as_dma_queue_entry *req_p) +{ + uint32_t imask ; + imask = cy_as_hal_disable_interrupts() ; + + req_p->next_p = dev_p->dma_freelist_p ; + dev_p->dma_freelist_p = req_p ; + + cy_as_hal_enable_interrupts(imask) ; +} + +/* + * Get a DMA queue entry from the free list. + */ +static cy_as_dma_queue_entry * +cy_as_dma_get_dma_queue_entry(cy_as_device *dev_p) +{ + cy_as_dma_queue_entry *req_p ; + uint32_t imask ; + + cy_as_hal_assert(dev_p->dma_freelist_p != 0) ; + + imask = cy_as_hal_disable_interrupts() ; + req_p = dev_p->dma_freelist_p ; + dev_p->dma_freelist_p = req_p->next_p ; + cy_as_hal_enable_interrupts(imask) ; + + return req_p ; +} + +/* + * Set the maximum size that the West Bridge hardware + * can handle in a single DMA operation. This size + * may change for the P <-> U endpoints as a function + * of the endpoint type and whether we are running + * at full speed or high speed. + */ +cy_as_return_status_t +cy_as_dma_set_max_dma_size(cy_as_device *dev_p, + cy_as_end_point_number_t ep, uint32_t size) +{ + /* In MTP mode, EP2 is allowed to have all max sizes. */ + if ((!dev_p->is_mtp_firmware) || (ep != 0x02)) { + if (size < 64 || size > 1024) + return CY_AS_ERROR_INVALID_SIZE ; + } + + CY_AS_NUM_EP(dev_p, ep)->maxhwdata = (uint16_t)size ; + return CY_AS_ERROR_SUCCESS ; +} + +/* + * The callback for requests sent to West Bridge + * to relay endpoint data. Endpoint data for EP0 + * and EP1 are sent using mailbox requests. This + * is the callback that is called when a response + * to a mailbox request to send data is received. + */ +static void +cy_as_dma_request_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *resp_p, + cy_as_return_status_t ret) +{ + uint16_t v ; + uint16_t datacnt ; + cy_as_end_point_number_t ep ; + + (void)context ; + + cy_as_log_debug_message(5, "cy_as_dma_request_callback called") ; + + /* + * extract the return code from the firmware + */ + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp_p) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(resp_p, 0) ; + } + + /* + * extract the endpoint number and the transferred byte count + * from the request. + */ + v = cy_as_ll_request_response__get_word(req_p, 0) ; + ep = (cy_as_end_point_number_t)((v >> 13) & 0x01) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + /* + * if the firmware returns success, + * all of the data requested was + * transferred. there are no partial + * transfers. + */ + datacnt = v & 0x3FF ; + } else { + /* + * if the firmware returned an error, no data was transferred. + */ + datacnt = 0 ; + } + + /* + * queue the request and response data structures for use with the + * next EP0 or EP1 request. + */ + if (ep == 0) { + dev_p->usb_ep0_dma_req = req_p ; + dev_p->usb_ep0_dma_resp = resp_p ; + } else { + dev_p->usb_ep1_dma_req = req_p ; + dev_p->usb_ep1_dma_resp = resp_p ; + } + + /* + * call the DMA complete function so we can + * signal that this portion of the transfer + * has completed. if the low level request + * was canceled, we do not need to signal + * the completed function as the only way a + * cancel can happen is via the DMA cancel + * function. + */ + if (ret != CY_AS_ERROR_CANCELED) + cy_as_dma_completed_callback(dev_p->tag, ep, datacnt, ret) ; +} + +/* + * Set the DRQ mask register for the given endpoint number. If state is + * CyTrue, the DRQ interrupt for the given endpoint is enabled, otherwise + * it is disabled. + */ +static void +cy_as_dma_set_drq(cy_as_device *dev_p, + cy_as_end_point_number_t ep, cy_bool state) +{ + uint16_t mask ; + uint16_t v ; + uint32_t intval ; + + /* + * there are not DRQ register bits for EP0 and EP1 + */ + if (ep == 0 || ep == 1) + return ; + + /* + * disable interrupts while we do this to be sure the state of the + * DRQ mask register is always well defined. + */ + intval = cy_as_hal_disable_interrupts() ; + + /* + * set the DRQ bit to the given state for the ep given + */ + mask = (1 << ep) ; + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK) ; + + if (state) + v |= mask ; + else + v &= ~mask ; + + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_DRQ_MASK, v) ; + cy_as_hal_enable_interrupts(intval) ; +} + +/* +* Send the next DMA request for the endpoint given +*/ +static void +cy_as_dma_send_next_dma_request(cy_as_device *dev_p, cy_as_dma_end_point *ep_p) +{ + uint32_t datacnt ; + void *buf_p ; + cy_as_dma_queue_entry *dma_p ; + + cy_as_log_debug_message(6, "cy_as_dma_send_next_dma_request called") ; + + /* If the queue is empty, nothing to do */ + dma_p = ep_p->queue_p ; + if (dma_p == 0) { + /* + * there are no pending DMA requests + * for this endpoint. disable the DRQ + * mask bits to insure no interrupts + * will be triggered by this endpoint + * until someone is interested in the data. + */ + cy_as_dma_set_drq(dev_p, ep_p->ep, cy_false) ; + return ; + } + + cy_as_dma_end_point_set_running(ep_p) ; + + /* + * get the number of words that still + * need to be xferred in this request. + */ + datacnt = dma_p->size - dma_p->offset ; + cy_as_hal_assert(datacnt >= 0) ; + + /* + * the HAL layer should never limit the size + * of the transfer to something less than the + * maxhwdata otherwise, the data will be sent + * in packets that are not correct in size. + */ + cy_as_hal_assert(ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE + || ep_p->maxhaldata >= ep_p->maxhwdata) ; + + /* + * update the number of words that need to be xferred yet + * based on the limits of the HAL layer. + */ + if (ep_p->maxhaldata == CY_AS_DMA_MAX_SIZE_HW_SIZE) { + if (datacnt > ep_p->maxhwdata) + datacnt = ep_p->maxhwdata ; + } else { + if (datacnt > ep_p->maxhaldata) + datacnt = ep_p->maxhaldata ; + } + + /* + * find a pointer to the data that needs to be transferred + */ + buf_p = (((char *)dma_p->buf_p) + dma_p->offset); + + /* + * mark a request in transit + */ + cy_as_dma_end_point_set_in_transit(ep_p) ; + + if (ep_p->ep == 0 || ep_p->ep == 1) { + /* + * if this is a WRITE request on EP0 and EP1 + * we write the data via an EP_DATA request + * to west bridge via the mailbox registers. + * if this is a READ request, we do nothing + * and the data will arrive via an EP_DATA + * request from west bridge. in the request + * handler for the USB context we will pass + * the data back into the DMA module. + */ + if (dma_p->readreq == cy_false) { + uint16_t v ; + uint16_t len ; + cy_as_ll_request_response *resp_p ; + cy_as_ll_request_response *req_p ; + cy_as_return_status_t ret ; + + len = (uint16_t)(datacnt / 2) ; + if (datacnt % 2) + len++ ; + + len++ ; + + if (ep_p->ep == 0) { + req_p = dev_p->usb_ep0_dma_req ; + resp_p = dev_p->usb_ep0_dma_resp ; + dev_p->usb_ep0_dma_req = 0 ; + dev_p->usb_ep0_dma_resp = 0 ; + } else { + req_p = dev_p->usb_ep1_dma_req ; + resp_p = dev_p->usb_ep1_dma_resp ; + dev_p->usb_ep1_dma_req = 0 ; + dev_p->usb_ep1_dma_resp = 0 ; + } + + cy_as_hal_assert(req_p != 0) ; + cy_as_hal_assert(resp_p != 0) ; + cy_as_hal_assert(len <= 64) ; + + cy_as_ll_init_request(req_p, CY_RQT_USB_EP_DATA, + CY_RQT_USB_RQT_CONTEXT, len) ; + + v = (uint16_t)(datacnt | (ep_p->ep << 13) | (1 << 14)) ; + if (dma_p->offset == 0) + v |= (1 << 12) ;/* Set the first packet bit */ + if (dma_p->offset + datacnt == dma_p->size) + v |= (1 << 11) ;/* Set the last packet bit */ + + cy_as_ll_request_response__set_word(req_p, 0, v) ; + cy_as_ll_request_response__pack(req_p, + 1, datacnt, buf_p) ; + + cy_as_ll_init_response(resp_p, 1) ; + + ret = cy_as_ll_send_request(dev_p, req_p, resp_p, + cy_false, cy_as_dma_request_callback) ; + if (ret == CY_AS_ERROR_SUCCESS) + cy_as_log_debug_message(5, + "+++ send EP 0/1 data via mailbox registers") ; + else + cy_as_log_debug_message(5, + "+++ error sending EP 0/1 data via mailbox " + "registers - CY_AS_ERROR_TIMEOUT") ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_dma_completed_callback(dev_p->tag, + ep_p->ep, 0, ret) ; + } + } else { + /* + * this is a DMA request on an endpoint that is accessible + * via the P port. ask the HAL DMA capabilities to + * perform this. the amount of data sent is limited by the + * HAL max size as well as what we need to send. if the + * ep_p->maxhaldata is set to a value larger than the + * endpoint buffer size, then we will pass more than a + * single buffer worth of data to the HAL layer and expect + * the HAL layer to divide the data into packets. the last + * parameter here (ep_p->maxhwdata) gives the packet size for + * the data so the HAL layer knows what the packet size should + * be. + */ + if (cy_as_dma_end_point_is_direction_in(ep_p)) + cy_as_hal_dma_setup_write(dev_p->tag, + ep_p->ep, buf_p, datacnt, ep_p->maxhwdata) ; + else + cy_as_hal_dma_setup_read(dev_p->tag, + ep_p->ep, buf_p, datacnt, ep_p->maxhwdata) ; + + /* + * the DRQ interrupt for this endpoint should be enabled + * so that the data transfer progresses at interrupt time. + */ + cy_as_dma_set_drq(dev_p, ep_p->ep, cy_true) ; + } +} + +/* + * This function is called when the HAL layer has + * completed the last requested DMA operation. + * This function sends/receives the next batch of + * data associated with the current DMA request, + * or it is is complete, moves to the next DMA request. + */ +void +cy_as_dma_completed_callback(cy_as_hal_device_tag tag, + cy_as_end_point_number_t ep, uint32_t cnt, cy_as_return_status_t status) +{ + uint32_t mask ; + cy_as_dma_queue_entry *req_p ; + cy_as_dma_end_point *ep_p ; + cy_as_device *dev_p = cy_as_device_find_from_tag(tag) ; + + /* Make sure the HAL layer gave us good parameters */ + cy_as_hal_assert(dev_p != 0) ; + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + cy_as_hal_assert(ep < 16) ; + + + /* Get the endpoint ptr */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + cy_as_hal_assert(ep_p->queue_p != 0) ; + + /* Get a pointer to the current entry in the queue */ + mask = cy_as_hal_disable_interrupts() ; + req_p = ep_p->queue_p ; + + /* Update the offset to reflect the data actually received or sent */ + req_p->offset += cnt ; + + /* + * if we are still sending/receiving the current packet, + * send/receive the next chunk basically we keep going + * if we have not sent/received enough data, and we are + * not doing a packet operation, and the last packet + * sent or received was a full sized packet. in other + * words, when we are NOT doing a packet operation, a + * less than full size packet (a short packet) will + * terminate the operation. + * + * note: if this is EP1 request and the request has + * timed out, it means the buffer is not free. + * we have to resend the data. + * + * note: for the MTP data transfers, the DMA transfer + * for the next packet can only be started asynchronously, + * after a firmware event notifies that the device is ready. + */ + if (((req_p->offset != req_p->size) && (req_p->packet == cy_false) && + ((cnt == ep_p->maxhaldata) || ((cnt == ep_p->maxhwdata) && + ((ep != CY_AS_MTP_READ_ENDPOINT) || + (cnt == dev_p->usb_max_tx_size))))) + || ((ep == 1) && (status == CY_AS_ERROR_TIMEOUT))) { + cy_as_hal_enable_interrupts(mask) ; + + /* + * and send the request again to send the next block of + * data. special handling for MTP transfers on E_ps 2 + * and 6. the send_next_request will be processed based + * on the event sent by the firmware. + */ + if ((ep == CY_AS_MTP_WRITE_ENDPOINT) || ( + (ep == CY_AS_MTP_READ_ENDPOINT) && + (!cy_as_dma_end_point_is_direction_in(ep_p)))) + cy_as_dma_end_point_set_stopped(ep_p) ; + else + cy_as_dma_send_next_dma_request(dev_p, ep_p) ; + } else { + /* + * we get here if ... + * we have sent or received all of the data + * or + * we are doing a packet operation + * or + * we receive a short packet + */ + + /* + * remove this entry from the DMA queue for this endpoint. + */ + cy_as_dma_end_point_clear_in_transit(ep_p) ; + ep_p->queue_p = req_p->next_p ; + if (ep_p->last_p == req_p) { + /* + * we have removed the last packet from the DMA queue, + * disable the interrupt associated with this interrupt. + */ + ep_p->last_p = 0 ; + cy_as_hal_enable_interrupts(mask) ; + cy_as_dma_set_drq(dev_p, ep, cy_false) ; + } else + cy_as_hal_enable_interrupts(mask) ; + + if (req_p->cb) { + /* + * if the request has a callback associated with it, + * call the callback to tell the interested party that + * this DMA request has completed. + * + * note, we set the in_callback bit to insure that we + * cannot recursively call an API function that is + * synchronous only from a callback. + */ + cy_as_device_set_in_callback(dev_p) ; + (*req_p->cb)(dev_p, ep, req_p->buf_p, + req_p->offset, status) ; + cy_as_device_clear_in_callback(dev_p) ; + } + + /* + * we are done with this request, put it on the freelist to be + * reused at a later time. + */ + cy_as_dma_add_request_to_free_queue(dev_p, req_p) ; + + if (ep_p->queue_p == 0) { + /* + * if the endpoint is out of DMA entries, set the + * endpoint as stopped. + */ + cy_as_dma_end_point_set_stopped(ep_p) ; + + /* + * the DMA queue is empty, wake any task waiting on + * the QUEUE to drain. + */ + if (cy_as_dma_end_point_is_sleeping(ep_p)) { + cy_as_dma_end_point_set_wake_state(ep_p) ; + cy_as_hal_wake(&ep_p->channel) ; + } + } else { + /* + * if the queued operation is a MTP transfer, + * wait until firmware event before sending + * down the next DMA request. + */ + if ((ep == CY_AS_MTP_WRITE_ENDPOINT) || + ((ep == CY_AS_MTP_READ_ENDPOINT) && + (!cy_as_dma_end_point_is_direction_in(ep_p))) || + ((ep == dev_p->storage_read_endpoint) && + (!cy_as_device_is_p2s_dma_start_recvd(dev_p))) + || ((ep == dev_p->storage_write_endpoint) && + (!cy_as_device_is_p2s_dma_start_recvd(dev_p)))) + cy_as_dma_end_point_set_stopped(ep_p) ; + else + cy_as_dma_send_next_dma_request(dev_p, ep_p) ; + } + } +} + +/* +* This function is used to kick start DMA on a given +* channel. If DMA is already running on the given +* endpoint, nothing happens. If DMA is not running, +* the first entry is pulled from the DMA queue and +* sent/recevied to/from the West Bridge device. +*/ +cy_as_return_status_t +cy_as_dma_kick_start(cy_as_device *dev_p, cy_as_end_point_number_t ep) +{ + cy_as_dma_end_point *ep_p ; + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + /* We are already running */ + if (cy_as_dma_end_point_is_running(ep_p)) + return CY_AS_ERROR_SUCCESS ; + + cy_as_dma_send_next_dma_request(dev_p, ep_p); + return CY_AS_ERROR_SUCCESS ; +} + +/* + * This function stops the given endpoint. Stopping and endpoint cancels + * any pending DMA operations and frees all resources associated with the + * given endpoint. + */ +static cy_as_return_status_t +cy_as_dma_stop_end_point(cy_as_device *dev_p, cy_as_end_point_number_t ep) +{ + cy_as_return_status_t ret ; + cy_as_dma_end_point *ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + /* + * cancel any pending DMA requests associated with this endpoint. this + * cancels any DMA requests at the HAL layer as well as dequeues any + * request that is currently pending. + */ + ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * destroy the sleep channel + */ + if (!cy_as_hal_destroy_sleep_channel(&ep_p->channel) + && ret == CY_AS_ERROR_SUCCESS) + ret = CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED ; + + /* + * free the memory associated with this endpoint + */ + cy_as_hal_free(ep_p) ; + + /* + * set the data structure ptr to something sane since the + * previous pointer is now free. + */ + dev_p->endp[ep] = 0 ; + + return ret ; +} + +/* + * This method stops the USB stack. This is an internal function that does + * all of the work of destroying the USB stack without the protections that + * we provide to the API (i.e. stopping at stack that is not running). + */ +static cy_as_return_status_t +cy_as_dma_stop_internal(cy_as_device *dev_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_return_status_t lret ; + cy_as_end_point_number_t i ; + + /* + * stop all of the endpoints. this cancels all DMA requests, and + * frees all resources associated with each endpoint. + */ + for (i = 0 ; i < sizeof(dev_p->endp)/(sizeof(dev_p->endp[0])) ; i++) { + lret = cy_as_dma_stop_end_point(dev_p, i) ; + if (lret != CY_AS_ERROR_SUCCESS && ret == CY_AS_ERROR_SUCCESS) + ret = lret ; + } + + /* + * now, free the list of DMA requests structures that we use to manage + * DMA requests. + */ + while (dev_p->dma_freelist_p) { + cy_as_dma_queue_entry *req_p ; + uint32_t imask = cy_as_hal_disable_interrupts() ; + + req_p = dev_p->dma_freelist_p ; + dev_p->dma_freelist_p = req_p->next_p ; + + cy_as_hal_enable_interrupts(imask) ; + + cy_as_hal_free(req_p) ; + } + + cy_as_ll_destroy_request(dev_p, dev_p->usb_ep0_dma_req) ; + cy_as_ll_destroy_request(dev_p, dev_p->usb_ep1_dma_req) ; + cy_as_ll_destroy_response(dev_p, dev_p->usb_ep0_dma_resp) ; + cy_as_ll_destroy_response(dev_p, dev_p->usb_ep1_dma_resp) ; + + return ret ; +} + + +/* + * CyAsDmaStop() + * + * This function shuts down the DMA module. All resources + * associated with the DMA module will be freed. This + * routine is the API stop function. It insures that we + * are stopping a stack that is actually running and then + * calls the internal function to do the work. + */ +cy_as_return_status_t +cy_as_dma_stop(cy_as_device *dev_p) +{ + cy_as_return_status_t ret ; + + ret = cy_as_dma_stop_internal(dev_p) ; + cy_as_device_set_dma_stopped(dev_p) ; + + return ret ; +} + +/* + * CyAsDmaStart() + * + * This function intializes the DMA module to insure it is up and running. + */ +cy_as_return_status_t +cy_as_dma_start(cy_as_device *dev_p) +{ + cy_as_end_point_number_t i ; + uint16_t cnt ; + + if (cy_as_device_is_dma_running(dev_p)) + return CY_AS_ERROR_ALREADY_RUNNING ; + + /* + * pre-allocate DMA queue structures to be used in the interrupt context + */ + for (cnt = 0 ; cnt < 32 ; cnt++) { + cy_as_dma_queue_entry *entry_p = (cy_as_dma_queue_entry *) + cy_as_hal_alloc(sizeof(cy_as_dma_queue_entry)) ; + if (entry_p == 0) { + cy_as_dma_stop_internal(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + cy_as_dma_add_request_to_free_queue(dev_p, entry_p) ; + } + + /* + * pre-allocate the DMA requests for sending EP0 + * and EP1 data to west bridge + */ + dev_p->usb_ep0_dma_req = cy_as_ll_create_request(dev_p, + CY_RQT_USB_EP_DATA, CY_RQT_USB_RQT_CONTEXT, 64) ; + dev_p->usb_ep1_dma_req = cy_as_ll_create_request(dev_p, + CY_RQT_USB_EP_DATA, CY_RQT_USB_RQT_CONTEXT, 64) ; + + if (dev_p->usb_ep0_dma_req == 0 || dev_p->usb_ep1_dma_req == 0) { + cy_as_dma_stop_internal(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + dev_p->usb_ep0_dma_req_save = dev_p->usb_ep0_dma_req ; + + dev_p->usb_ep0_dma_resp = cy_as_ll_create_response(dev_p, 1) ; + dev_p->usb_ep1_dma_resp = cy_as_ll_create_response(dev_p, 1) ; + if (dev_p->usb_ep0_dma_resp == 0 || dev_p->usb_ep1_dma_resp == 0) { + cy_as_dma_stop_internal(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + dev_p->usb_ep0_dma_resp_save = dev_p->usb_ep0_dma_resp ; + + /* + * set the dev_p->endp to all zeros to insure cleanup is possible if + * an error occurs during initialization. + */ + cy_as_hal_mem_set(dev_p->endp, 0, sizeof(dev_p->endp)) ; + + /* + * now, iterate through each of the endpoints and initialize each + * one. + */ + for (i = 0 ; i < sizeof(dev_p->endp)/sizeof(dev_p->endp[0]) ; i++) { + dev_p->endp[i] = (cy_as_dma_end_point *) + cy_as_hal_alloc(sizeof(cy_as_dma_end_point)) ; + if (dev_p->endp[i] == 0) { + cy_as_dma_stop_internal(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + cy_as_hal_mem_set(dev_p->endp[i], 0, + sizeof(cy_as_dma_end_point)) ; + + dev_p->endp[i]->ep = i ; + dev_p->endp[i]->queue_p = 0 ; + dev_p->endp[i]->last_p = 0 ; + + cy_as_dma_set_drq(dev_p, i, cy_false) ; + + if (!cy_as_hal_create_sleep_channel(&dev_p->endp[i]->channel)) + return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED ; + } + + /* + * tell the HAL layer who to call when the + * HAL layer completes a DMA request + */ + cy_as_hal_dma_register_callback(dev_p->tag, + cy_as_dma_completed_callback) ; + + /* + * mark DMA as up and running on this device + */ + cy_as_device_set_dma_running(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +/* +* Wait for all entries in the DMA queue associated +* the given endpoint to be drained. This function +* will not return until all the DMA data has been +* transferred. +*/ +cy_as_return_status_t +cy_as_dma_drain_queue(cy_as_device *dev_p, + cy_as_end_point_number_t ep, cy_bool kickstart) +{ + cy_as_dma_end_point *ep_p ; + int loopcount = 1000 ; + uint32_t mask ; + + /* + * make sure the endpoint is valid + */ + if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0])) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + /* + * if the endpoint is empty of traffic, we return + * with success immediately + */ + mask = cy_as_hal_disable_interrupts() ; + if (ep_p->queue_p == 0) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_SUCCESS ; + } else { + /* + * add 10 seconds to the time out value for each 64 KB segment + * of data to be transferred. + */ + if (ep_p->queue_p->size > 0x10000) + loopcount += ((ep_p->queue_p->size / 0x10000) * 1000) ; + } + cy_as_hal_enable_interrupts(mask) ; + + /* If we are already sleeping on this endpoint, it is an error */ + if (cy_as_dma_end_point_is_sleeping(ep_p)) + return CY_AS_ERROR_NESTED_SLEEP ; + + /* + * we disable the endpoint while the queue drains to + * prevent any additional requests from being queued while we are waiting + */ + cy_as_dma_enable_end_point(dev_p, ep, + cy_false, cy_as_direction_dont_change) ; + + if (kickstart) { + /* + * now, kick start the DMA if necessary + */ + cy_as_dma_kick_start(dev_p, ep) ; + } + + /* + * check one last time before we begin sleeping to see if the + * queue is drained. + */ + if (ep_p->queue_p == 0) { + cy_as_dma_enable_end_point(dev_p, ep, cy_true, + cy_as_direction_dont_change) ; + return CY_AS_ERROR_SUCCESS ; + } + + while (loopcount-- > 0) { + /* + * sleep for 10 ms maximum (per loop) while + * waiting for the transfer to complete. + */ + cy_as_dma_end_point_set_sleep_state(ep_p) ; + cy_as_hal_sleep_on(&ep_p->channel, 10) ; + + /* If we timed out, the sleep bit will still be set */ + cy_as_dma_end_point_set_wake_state(ep_p) ; + + /* Check the queue to see if is drained */ + if (ep_p->queue_p == 0) { + /* + * clear the endpoint running and in transit flags + * for the endpoint, now that its DMA queue is empty. + */ + cy_as_dma_end_point_clear_in_transit(ep_p) ; + cy_as_dma_end_point_set_stopped(ep_p) ; + + cy_as_dma_enable_end_point(dev_p, ep, + cy_true, cy_as_direction_dont_change) ; + return CY_AS_ERROR_SUCCESS ; + } + } + + /* + * the DMA operation that has timed out can be cancelled, so that later + * operations on this queue can proceed. + */ + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_TIMEOUT) ; + cy_as_dma_enable_end_point(dev_p, ep, + cy_true, cy_as_direction_dont_change) ; + return CY_AS_ERROR_TIMEOUT ; +} + +/* +* This function queues a write request in the DMA queue +* for a given endpoint. The direction of the +* entry will be inferred from the endpoint direction. +*/ +cy_as_return_status_t +cy_as_dma_queue_request(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *mem_p, + uint32_t size, cy_bool pkt, cy_bool readreq, cy_as_dma_callback cb) +{ + uint32_t mask ; + cy_as_dma_queue_entry *entry_p ; + cy_as_dma_end_point *ep_p ; + + /* + * make sure the endpoint is valid + */ + if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0])) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + if (!cy_as_dma_end_point_is_enabled(ep_p)) + return CY_AS_ERROR_ENDPOINT_DISABLED ; + + entry_p = cy_as_dma_get_dma_queue_entry(dev_p) ; + + entry_p->buf_p = mem_p ; + entry_p->cb = cb ; + entry_p->size = size ; + entry_p->offset = 0 ; + entry_p->packet = pkt ; + entry_p->readreq = readreq ; + + mask = cy_as_hal_disable_interrupts() ; + entry_p->next_p = 0 ; + if (ep_p->last_p) + ep_p->last_p->next_p = entry_p ; + ep_p->last_p = entry_p ; + if (ep_p->queue_p == 0) + ep_p->queue_p = entry_p ; + cy_as_hal_enable_interrupts(mask) ; + + return CY_AS_ERROR_SUCCESS ; +} + +/* +* This function enables or disables and endpoint for DMA +* queueing. If an endpoint is disabled, any queue requests +* continue to be processed, but no new requests can be queued. +*/ +cy_as_return_status_t +cy_as_dma_enable_end_point(cy_as_device *dev_p, + cy_as_end_point_number_t ep, cy_bool enable, cy_as_dma_direction dir) +{ + cy_as_dma_end_point *ep_p ; + + /* + * make sure the endpoint is valid + */ + if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0])) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + if (dir == cy_as_direction_out) + cy_as_dma_end_point_set_direction_out(ep_p) ; + else if (dir == cy_as_direction_in) + cy_as_dma_end_point_set_direction_in(ep_p) ; + + /* + * get the maximum size of data buffer the HAL + * layer can accept. this is used when the DMA + * module is sending DMA requests to the HAL. + * the DMA module will never send down a request + * that is greater than this value. + * + * for EP0 and EP1, we can send no more than 64 + * bytes of data at one time as this is the maximum + * size of a packet that can be sent via these + * endpoints. + */ + if (ep == 0 || ep == 1) + ep_p->maxhaldata = 64 ; + else + ep_p->maxhaldata = cy_as_hal_dma_max_request_size( + dev_p->tag, ep) ; + + if (enable) + cy_as_dma_end_point_enable(ep_p) ; + else + cy_as_dma_end_point_disable(ep_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +/* + * This function cancels any DMA operations pending with the HAL layer as well + * as any DMA operation queued on the endpoint. + */ +cy_as_return_status_t +cy_as_dma_cancel( + cy_as_device *dev_p, + cy_as_end_point_number_t ep, + cy_as_return_status_t err) +{ + uint32_t mask ; + cy_as_dma_end_point *ep_p ; + cy_as_dma_queue_entry *entry_p ; + cy_bool epstate ; + + /* + * make sure the endpoint is valid + */ + if (ep >= sizeof(dev_p->endp)/sizeof(dev_p->endp[0])) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + if (ep_p) { + /* Remember the state of the endpoint */ + epstate = cy_as_dma_end_point_is_enabled(ep_p) ; + + /* + * disable the endpoint so no more DMA packets can be + * queued. + */ + cy_as_dma_enable_end_point(dev_p, ep, + cy_false, cy_as_direction_dont_change) ; + + /* + * don't allow any interrupts from this endpoint + * while we get the most current request off of + * the queue. + */ + cy_as_dma_set_drq(dev_p, ep, cy_false) ; + + /* + * cancel any pending request queued in the HAL layer + */ + if (cy_as_dma_end_point_in_transit(ep_p)) + cy_as_hal_dma_cancel_request(dev_p->tag, ep_p->ep) ; + + /* + * shutdown the DMA for this endpoint so no + * more data is transferred + */ + cy_as_dma_end_point_set_stopped(ep_p) ; + + /* + * mark the endpoint as not in transit, because we are + * going to consume any queued requests + */ + cy_as_dma_end_point_clear_in_transit(ep_p) ; + + /* + * now, remove each entry in the queue and call the + * associated callback stating that the request was + * canceled. + */ + ep_p->last_p = 0 ; + while (ep_p->queue_p != 0) { + /* Disable interrupts to manipulate the queue */ + mask = cy_as_hal_disable_interrupts() ; + + /* Remove an entry from the queue */ + entry_p = ep_p->queue_p ; + ep_p->queue_p = entry_p->next_p ; + + /* Ok, the queue has been updated, we can + * turn interrupts back on */ + cy_as_hal_enable_interrupts(mask) ; + + /* Call the callback indicating we have + * canceled the DMA */ + if (entry_p->cb) + entry_p->cb(dev_p, ep, + entry_p->buf_p, entry_p->size, err) ; + + cy_as_dma_add_request_to_free_queue(dev_p, entry_p) ; + } + + if (ep == 0 || ep == 1) { + /* + * if this endpoint is zero or one, we need to + * clear the queue of any pending CY_RQT_USB_EP_DATA + * requests as these are pending requests to send + * data to the west bridge device. + */ + cy_as_ll_remove_ep_data_requests(dev_p, ep) ; + } + + if (epstate) { + /* + * the endpoint started out enabled, so we + * re-enable the endpoint here. + */ + cy_as_dma_enable_end_point(dev_p, ep, + cy_true, cy_as_direction_dont_change) ; + } + } + + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_dma_received_data(cy_as_device *dev_p, + cy_as_end_point_number_t ep, uint32_t dsize, void *data) +{ + cy_as_dma_queue_entry *dma_p ; + uint8_t *src_p, *dest_p ; + cy_as_dma_end_point *ep_p ; + uint32_t xfersize ; + + /* + * make sure the endpoint is valid + */ + if (ep != 0 && ep != 1) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + dma_p = ep_p->queue_p ; + if (dma_p == 0) + return CY_AS_ERROR_SUCCESS ; + + /* + * if the data received exceeds the size of the DMA buffer, + * clip the data to the size of the buffer. this can lead + * to loosing some data, but is not different than doing + * non-packet reads on the other endpoints. + */ + if (dsize > dma_p->size - dma_p->offset) + dsize = dma_p->size - dma_p->offset ; + + /* + * copy the data from the request packet to the DMA buffer + * for the endpoint + */ + src_p = (uint8_t *)data ; + dest_p = ((uint8_t *)(dma_p->buf_p)) + dma_p->offset ; + xfersize = dsize ; + while (xfersize-- > 0) + *dest_p++ = *src_p++ ; + + /* Signal the DMA module that we have + * received data for this EP request */ + cy_as_dma_completed_callback(dev_p->tag, + ep, dsize, CY_AS_ERROR_SUCCESS) ; + + return CY_AS_ERROR_SUCCESS ; +} diff --git a/drivers/staging/westbridge/astoria/api/src/cyasintr.c b/drivers/staging/westbridge/astoria/api/src/cyasintr.c new file mode 100644 index 000000000000..aea6c3ebf067 --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasintr.c @@ -0,0 +1,143 @@ +/* Cypress West Bridge API source file (cyasintr.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasdevice.h" +#include "../../include/linux/westbridge/cyasregs.h" +#include "../../include/linux/westbridge/cyaserr.h" + +extern void cy_as_mail_box_interrupt_handler(cy_as_device *) ; + +void +cy_as_mcu_interrupt_handler(cy_as_device *dev_p) +{ + /* Read and clear the interrupt. */ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_MCU_STAT) ; + v = v ; +} + +void +cy_as_power_management_interrupt_handler(cy_as_device *dev_p) +{ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT) ; + v = v ; +} + +void +cy_as_pll_lock_loss_interrupt_handler(cy_as_device *dev_p) +{ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PLL_LOCK_LOSS_STAT) ; + v = v ; +} + +uint32_t cy_as_intr_start(cy_as_device *dev_p, cy_bool dmaintr) +{ + uint16_t v ; + + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + if (cy_as_device_is_intr_running(dev_p) != 0) + return CY_AS_ERROR_ALREADY_RUNNING ; + + v = CY_AS_MEM_P0_INT_MASK_REG_MMCUINT | + CY_AS_MEM_P0_INT_MASK_REG_MMBINT | + CY_AS_MEM_P0_INT_MASK_REG_MPMINT ; + + if (dmaintr) + v |= CY_AS_MEM_P0_INT_MASK_REG_MDRQINT ; + + /* Enable the interrupts of interest */ + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, v) ; + + /* Mark the interrupt module as initialized */ + cy_as_device_set_intr_running(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +uint32_t cy_as_intr_stop(cy_as_device *dev_p) +{ + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + if (cy_as_device_is_intr_running(dev_p) == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, 0) ; + cy_as_device_set_intr_stopped(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +void cy_as_intr_service_interrupt(cy_as_hal_device_tag tag) +{ + uint16_t v ; + cy_as_device *dev_p ; + + dev_p = cy_as_device_find_from_tag(tag) ; + + /* + * only power management interrupts can occur before the + * antioch API setup is complete. if this is a PM interrupt + * handle it here; otherwise output a warning message. + */ + if (dev_p == 0) { + v = cy_as_hal_read_register(tag, CY_AS_MEM_P0_INTR_REG) ; + if (v == CY_AS_MEM_P0_INTR_REG_PMINT) { + /* Read the PWR_MAGT_STAT register + * to clear this interrupt. */ + v = cy_as_hal_read_register(tag, + CY_AS_MEM_PWR_MAGT_STAT) ; + } else + cy_as_hal_print_message("stray antioch " + "interrupt detected" + ", tag not associated " + "with any created device.") ; + return ; + } + + /* Make sure we got a valid object from CyAsDeviceFindFromTag */ + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG) ; + + if (v & CY_AS_MEM_P0_INTR_REG_MCUINT) + cy_as_mcu_interrupt_handler(dev_p) ; + + if (v & CY_AS_MEM_P0_INTR_REG_PMINT) + cy_as_power_management_interrupt_handler(dev_p) ; + + if (v & CY_AS_MEM_P0_INTR_REG_PLLLOCKINT) + cy_as_pll_lock_loss_interrupt_handler(dev_p) ; + + /* If the interrupt module is not running, no mailbox + * interrupts are expected from the west bridge. */ + if (cy_as_device_is_intr_running(dev_p) == 0) + return ; + + if (v & CY_AS_MEM_P0_INTR_REG_MBINT) + cy_as_mail_box_interrupt_handler(dev_p) ; +} diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c b/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c new file mode 100644 index 000000000000..b28e33a1ce9d --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyaslep2pep.c @@ -0,0 +1,358 @@ +/* Cypress West Bridge API source file (cyaslep2pep.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasusb.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyasdma.h" + +typedef enum cy_as_physical_endpoint_state { + cy_as_e_p_free, + cy_as_e_p_in, + cy_as_e_p_out, + cy_as_e_p_iso_in, + cy_as_e_p_iso_out +} cy_as_physical_endpoint_state; + + +/* +* This map is used to map an index between 1 and 10 +* to a logical endpoint number. This is used to map +* LEP register indexes into actual EP numbers. +*/ +static cy_as_end_point_number_t end_point_map[] = { + 3, 5, 7, 9, 10, 11, 12, 13, 14, 15 } ; + +#define CY_AS_EPCFG_1024 (1 << 3) +#define CY_AS_EPCFG_DBL (0x02) +#define CY_AS_EPCFG_TRIPLE (0x03) +#define CY_AS_EPCFG_QUAD (0x00) + +/* + * NB: This table contains the register values for PEP1 + * and PEP3. PEP2 and PEP4 only have a bit to change the + * direction of the PEP and therefre are not represented + * in this table. + */ +static uint8_t pep_register_values[12][4] = { + /* Bit 1:0 buffering, 0 = quad, 2 = double, 3 = triple */ + /* Bit 3 size, 0 = 512, 1 = 1024 */ + { + CY_AS_EPCFG_DBL, + CY_AS_EPCFG_DBL, + },/* Config 1 - PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (2 * 512), PEP4 (2 * 512) */ + { + CY_AS_EPCFG_DBL, + CY_AS_EPCFG_QUAD, + }, /* Config 2 - PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (4 * 512), PEP4 (N/A) */ + { + CY_AS_EPCFG_DBL, + CY_AS_EPCFG_DBL | CY_AS_EPCFG_1024, + },/* Config 3 - PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (2 * 1024), PEP4(N/A) */ + { + CY_AS_EPCFG_QUAD, + CY_AS_EPCFG_DBL, + },/* Config 4 - PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (2 * 512), PEP4 (2 * 512) */ + { + CY_AS_EPCFG_QUAD, + CY_AS_EPCFG_QUAD, + },/* Config 5 - PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (4 * 512), PEP4 (N/A) */ + { + CY_AS_EPCFG_QUAD, + CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, + },/* Config 6 - PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (2 * 1024), PEP4 (N/A) */ + { + CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, + CY_AS_EPCFG_DBL, + },/* Config 7 - PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (2 * 512), PEP4 (2 * 512) */ + { + CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, + CY_AS_EPCFG_QUAD, + },/* Config 8 - PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (4 * 512), PEP4 (N/A) */ + { + CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, + CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, + },/* Config 9 - PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (2 * 1024), PEP4 (N/A)*/ + { + CY_AS_EPCFG_TRIPLE, + CY_AS_EPCFG_TRIPLE, + },/* Config 10 - PEP1 (3 * 512), PEP2 (N/A), + * PEP3 (3 * 512), PEP4 (2 * 512)*/ + { + CY_AS_EPCFG_TRIPLE | CY_AS_EPCFG_1024, + CY_AS_EPCFG_DBL, + },/* Config 11 - PEP1 (3 * 1024), PEP2 (N/A), + * PEP3 (N/A), PEP4 (2 * 512) */ + { + CY_AS_EPCFG_QUAD | CY_AS_EPCFG_1024, + CY_AS_EPCFG_DBL, + },/* Config 12 - PEP1 (4 * 1024), PEP2 (N/A), + * PEP3 (N/A), PEP4 (N/A) */ +} ; + +static cy_as_return_status_t +find_endpoint_directions(cy_as_device *dev_p, + cy_as_physical_endpoint_state epstate[4]) +{ + int i ; + cy_as_physical_endpoint_state desired ; + + /* + * note, there is no error checking here becuase + * ISO error checking happens when the API is called. + */ + for (i = 0 ; i < 10 ; i++) { + int epno = end_point_map[i] ; + if (dev_p->usb_config[epno].enabled) { + int pep = dev_p->usb_config[epno].physical ; + if (dev_p->usb_config[epno].type == cy_as_usb_iso) { + /* + * marking this as an ISO endpoint, removes the + * physical EP from consideration when + * mapping the remaining E_ps. + */ + if (dev_p->usb_config[epno].dir == cy_as_usb_in) + desired = cy_as_e_p_iso_in ; + else + desired = cy_as_e_p_iso_out ; + } else { + if (dev_p->usb_config[epno].dir == cy_as_usb_in) + desired = cy_as_e_p_in ; + else + desired = cy_as_e_p_out ; + } + + /* + * NB: Note the API calls insure that an ISO endpoint + * has a physical and logical EP number that are the + * same, therefore this condition is not enforced here. + */ + if (epstate[pep - 1] != + cy_as_e_p_free && epstate[pep - 1] != desired) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + epstate[pep - 1] = desired ; + } + } + + /* + * create the EP1 config values directly. + * both EP1OUT and EP1IN are invalid by default. + */ + dev_p->usb_ep1cfg[0] = 0 ; + dev_p->usb_ep1cfg[1] = 0 ; + if (dev_p->usb_config[1].enabled) { + if ((dev_p->usb_config[1].dir == cy_as_usb_out) || + (dev_p->usb_config[1].dir == cy_as_usb_in_out)) { + /* Set the valid bit and type field. */ + dev_p->usb_ep1cfg[0] = (1 << 7) ; + if (dev_p->usb_config[1].type == cy_as_usb_bulk) + dev_p->usb_ep1cfg[0] |= (2 << 4) ; + else + dev_p->usb_ep1cfg[0] |= (3 << 4) ; + } + + if ((dev_p->usb_config[1].dir == cy_as_usb_in) || + (dev_p->usb_config[1].dir == cy_as_usb_in_out)) { + /* Set the valid bit and type field. */ + dev_p->usb_ep1cfg[1] = (1 << 7) ; + if (dev_p->usb_config[1].type == cy_as_usb_bulk) + dev_p->usb_ep1cfg[1] |= (2 << 4) ; + else + dev_p->usb_ep1cfg[1] |= (3 << 4) ; + } + } + + return CY_AS_ERROR_SUCCESS ; +} + +static void +create_register_settings(cy_as_device *dev_p, + cy_as_physical_endpoint_state epstate[4]) +{ + int i ; + uint8_t v ; + + for (i = 0 ; i < 4 ; i++) { + if (i == 0) { + /* Start with the values that specify size */ + dev_p->usb_pepcfg[i] = + pep_register_values + [dev_p->usb_phy_config - 1][0] ; + } else if (i == 2) { + /* Start with the values that specify size */ + dev_p->usb_pepcfg[i] = + pep_register_values + [dev_p->usb_phy_config - 1][1] ; + } else + dev_p->usb_pepcfg[i] = 0 ; + + /* Adjust direction if it is in */ + if (epstate[i] == cy_as_e_p_iso_in || + epstate[i] == cy_as_e_p_in) + dev_p->usb_pepcfg[i] |= (1 << 6) ; + } + + /* Configure the logical EP registers */ + for (i = 0 ; i < 10 ; i++) { + int val ; + int epnum = end_point_map[i] ; + + v = 0x10 ; /* PEP 1, Bulk Endpoint, EP not valid */ + if (dev_p->usb_config[epnum].enabled) { + v |= (1 << 7) ; /* Enabled */ + + val = dev_p->usb_config[epnum].physical - 1 ; + cy_as_hal_assert(val >= 0 && val <= 3) ; + v |= (val << 5) ; + + switch (dev_p->usb_config[epnum].type) { + case cy_as_usb_bulk: + val = 2 ; + break ; + case cy_as_usb_int: + val = 3 ; + break ; + case cy_as_usb_iso: + val = 1 ; + break ; + default: + cy_as_hal_assert(cy_false) ; + break ; + } + v |= (val << 3) ; + } + + dev_p->usb_lepcfg[i] = v ; + } +} + + +cy_as_return_status_t +cy_as_usb_map_logical2_physical(cy_as_device *dev_p) +{ + cy_as_return_status_t ret ; + + /* Physical EPs 3 5 7 9 respectively in the array */ + cy_as_physical_endpoint_state epstate[4] = { + cy_as_e_p_free, cy_as_e_p_free, + cy_as_e_p_free, cy_as_e_p_free } ; + + /* Find the direction for the endpoints */ + ret = find_endpoint_directions(dev_p, epstate) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * now create the register settings based on the given + * assigned of logical E_ps to physical endpoints. + */ + create_register_settings(dev_p, epstate) ; + + return ret ; +} + +static uint16_t +get_max_dma_size(cy_as_device *dev_p, cy_as_end_point_number_t ep) +{ + uint16_t size = dev_p->usb_config[ep].size ; + + if (size == 0) { + switch (dev_p->usb_config[ep].type) { + case cy_as_usb_control: + size = 64 ; + break ; + + case cy_as_usb_bulk: + size = cy_as_device_is_usb_high_speed(dev_p) ? + 512 : 64 ; + break ; + + case cy_as_usb_int: + size = cy_as_device_is_usb_high_speed(dev_p) ? + 1024 : 64 ; + break ; + + case cy_as_usb_iso: + size = cy_as_device_is_usb_high_speed(dev_p) ? + 1024 : 1023 ; + break ; + } + } + + return size ; +} + +cy_as_return_status_t +cy_as_usb_set_dma_sizes(cy_as_device *dev_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint32_t i ; + + for (i = 0 ; i < 10 ; i++) { + cy_as_usb_end_point_config *config_p = + &dev_p->usb_config[end_point_map[i]] ; + if (config_p->enabled) { + ret = cy_as_dma_set_max_dma_size(dev_p, + end_point_map[i], + get_max_dma_size(dev_p, end_point_map[i])) ; + if (ret != CY_AS_ERROR_SUCCESS) + break ; + } + } + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_setup_dma(cy_as_device *dev_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint32_t i ; + + for (i = 0 ; i < 10 ; i++) { + cy_as_usb_end_point_config *config_p = + &dev_p->usb_config[end_point_map[i]] ; + if (config_p->enabled) { + /* Map the endpoint direction to the DMA direction */ + cy_as_dma_direction dir = cy_as_direction_out ; + if (config_p->dir == cy_as_usb_in) + dir = cy_as_direction_in ; + + ret = cy_as_dma_enable_end_point(dev_p, + end_point_map[i], cy_true, dir) ; + if (ret != CY_AS_ERROR_SUCCESS) + break ; + } + } + + return ret ; +} diff --git a/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c b/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c new file mode 100644 index 000000000000..70d56e9b060c --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyaslowlevel.c @@ -0,0 +1,1264 @@ +/* Cypress West Bridge API source file (cyaslowlevel.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyascast.h" +#include "../../include/linux/westbridge/cyasdevice.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyasintr.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasregs.h" + +static const uint32_t cy_as_low_level_timeout_count = 65536 * 4 ; + +/* Forward declaration */ +static cy_as_return_status_t cy_as_send_one(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) ; + +/* +* This array holds the size of the largest request we will ever recevie from +* the West Bridge device per context. The size is in 16 bit words. Note a +* size of 0xffff indicates that there will be no requests on this context +* from West Bridge. +*/ +static uint16_t max_request_length[CY_RQT_CONTEXT_COUNT] = { + 8, /* CY_RQT_GENERAL_RQT_CONTEXT - CY_RQT_INITIALIZATION_COMPLETE */ + 8, /* CY_RQT_RESOURCE_RQT_CONTEXT - none */ + 8, /* CY_RQT_STORAGE_RQT_CONTEXT - CY_RQT_MEDIA_CHANGED */ + 128, /* CY_RQT_USB_RQT_CONTEXT - CY_RQT_USB_EVENT */ + 8 /* CY_RQT_TUR_RQT_CONTEXT - CY_RQT_TURBO_CMD_FROM_HOST */ +} ; + +/* +* For the given context, this function removes the request node at the head +* of the queue from the context. This is called after all processing has +* occurred on the given request and response and we are ready to remove this +* entry from the queue. +*/ +static void +cy_as_ll_remove_request_queue_head(cy_as_device *dev_p, cy_as_context *ctxt_p) +{ + uint32_t mask, state ; + cy_as_ll_request_list_node *node_p ; + + (void)dev_p ; + cy_as_hal_assert(ctxt_p->request_queue_p != 0) ; + + mask = cy_as_hal_disable_interrupts() ; + node_p = ctxt_p->request_queue_p ; + ctxt_p->request_queue_p = node_p->next ; + cy_as_hal_enable_interrupts(mask) ; + + node_p->callback = 0 ; + node_p->rqt = 0 ; + node_p->resp = 0 ; + + /* + * note that the caller allocates and destroys the request and + * response. generally the destroy happens in the callback for + * async requests and after the wait returns for sync. the + * request and response may not actually be destroyed but may be + * managed in other ways as well. it is the responsibilty of + * the caller to deal with these in any case. the caller can do + * this in the request/response callback function. + */ + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node_p) ; + cy_as_hal_enable_interrupts(state) ; +} + +/* +* For the context given, this function sends the next request to +* West Bridge via the mailbox register, if the next request is +* ready to be sent and has not already been sent. +*/ +static void +cy_as_ll_send_next_request(cy_as_device *dev_p, cy_as_context *ctxt_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + /* + * ret == ret is equivalent to while (1) but eliminates compiler + * warnings for some compilers. + */ + while (ret == ret) { + cy_as_ll_request_list_node *node_p = ctxt_p->request_queue_p ; + if (node_p == 0) + break ; + + if (cy_as_request_get_node_state(node_p) != + CY_AS_REQUEST_LIST_STATE_QUEUED) + break ; + + cy_as_request_set_node_state(node_p, + CY_AS_REQUEST_LIST_STATE_WAITING) ; + ret = cy_as_send_one(dev_p, node_p->rqt) ; + if (ret == CY_AS_ERROR_SUCCESS) + break ; + + /* + * if an error occurs in sending the request, tell the requester + * about the error and remove the request from the queue. + */ + cy_as_request_set_node_state(node_p, + CY_AS_REQUEST_LIST_STATE_RECEIVED) ; + node_p->callback(dev_p, ctxt_p->number, + node_p->rqt, node_p->resp, ret) ; + cy_as_ll_remove_request_queue_head(dev_p, ctxt_p) ; + + /* + * this falls through to the while loop to send the next request + * since the previous request did not get sent. + */ + } +} + +/* +* This method removes an entry from the request queue of a given context. +* The entry is removed only if it is not in transit. +*/ +cy_as_remove_request_result_t +cy_as_ll_remove_request(cy_as_device *dev_p, cy_as_context *ctxt_p, + cy_as_ll_request_response *req_p, cy_bool force) +{ + uint32_t imask ; + cy_as_ll_request_list_node *node_p ; + cy_as_ll_request_list_node *tmp_p ; + uint32_t state ; + + imask = cy_as_hal_disable_interrupts() ; + if (ctxt_p->request_queue_p != 0 && + ctxt_p->request_queue_p->rqt == req_p) { + node_p = ctxt_p->request_queue_p ; + if ((cy_as_request_get_node_state(node_p) == + CY_AS_REQUEST_LIST_STATE_WAITING) && (!force)) { + cy_as_hal_enable_interrupts(imask) ; + return cy_as_remove_request_in_transit ; + } + + ctxt_p->request_queue_p = node_p->next ; + } else { + tmp_p = ctxt_p->request_queue_p ; + while (tmp_p != 0 && tmp_p->next != 0 && + tmp_p->next->rqt != req_p) + tmp_p = tmp_p->next ; + + if (tmp_p == 0 || tmp_p->next == 0) { + cy_as_hal_enable_interrupts(imask) ; + return cy_as_remove_request_not_found ; + } + + node_p = tmp_p->next ; + tmp_p->next = node_p->next ; + } + + if (node_p->callback) + node_p->callback(dev_p, ctxt_p->number, node_p->rqt, + node_p->resp, CY_AS_ERROR_CANCELED) ; + + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node_p) ; + cy_as_hal_enable_interrupts(state) ; + + cy_as_hal_enable_interrupts(imask) ; + return cy_as_remove_request_sucessful ; +} + +void +cy_as_ll_remove_all_requests(cy_as_device *dev_p, cy_as_context *ctxt_p) +{ + cy_as_ll_request_list_node *node = ctxt_p->request_queue_p ; + + while (node) { + if (cy_as_request_get_node_state(ctxt_p->request_queue_p) != + CY_AS_REQUEST_LIST_STATE_RECEIVED) + cy_as_ll_remove_request(dev_p, ctxt_p, + node->rqt, cy_true) ; + node = node->next ; + } +} + +static cy_bool +cy_as_ll_is_in_queue(cy_as_context *ctxt_p, cy_as_ll_request_response *req_p) +{ + uint32_t mask ; + cy_as_ll_request_list_node *node_p ; + + mask = cy_as_hal_disable_interrupts() ; + node_p = ctxt_p->request_queue_p ; + while (node_p) { + if (node_p->rqt == req_p) { + cy_as_hal_enable_interrupts(mask) ; + return cy_true ; + } + node_p = node_p->next ; + } + cy_as_hal_enable_interrupts(mask) ; + return cy_false ; +} + +/* +* This is the handler for mailbox data when we are trying to send data +* to the West Bridge firmware. The firmware may be trying to send us +* data and we need to queue this data to allow the firmware to move +* forward and be in a state to receive our request. Here we just queue +* the data and it is processed at a later time by the mailbox interrupt +* handler. +*/ +void +cy_as_ll_queue_mailbox_data(cy_as_device *dev_p) +{ + cy_as_context *ctxt_p ; + uint8_t context ; + uint16_t data[4] ; + int32_t i ; + + /* Read the data from mailbox 0 to determine what to do with the data */ + for (i = 3 ; i >= 0 ; i--) + data[i] = cy_as_hal_read_register(dev_p->tag, + cy_cast_int2U_int16(CY_AS_MEM_P0_MAILBOX0 + i)) ; + + context = cy_as_mbox_get_context(data[0]) ; + if (context >= CY_RQT_CONTEXT_COUNT) { + cy_as_hal_print_message("mailbox request/response received " + "with invalid context value (%d)\n", context) ; + return ; + } + + ctxt_p = dev_p->context[context] ; + + /* + * if we have queued too much data, drop future data. + */ + cy_as_hal_assert(ctxt_p->queue_index * sizeof(uint16_t) + + sizeof(data) <= sizeof(ctxt_p->data_queue)) ; + + for (i = 0 ; i < 4 ; i++) + ctxt_p->data_queue[ctxt_p->queue_index++] = data[i] ; + + cy_as_hal_assert((ctxt_p->queue_index % 4) == 0) ; + dev_p->ll_queued_data = cy_true ; +} + +void +cy_as_mail_box_process_data(cy_as_device *dev_p, uint16_t *data) +{ + cy_as_context *ctxt_p ; + uint8_t context ; + uint16_t *len_p ; + cy_as_ll_request_response *rec_p ; + uint8_t st ; + uint16_t src, dest ; + + context = cy_as_mbox_get_context(data[0]) ; + if (context >= CY_RQT_CONTEXT_COUNT) { + cy_as_hal_print_message("mailbox request/response received " + "with invalid context value (%d)\n", context) ; + return ; + } + + ctxt_p = dev_p->context[context] ; + + if (cy_as_mbox_is_request(data[0])) { + cy_as_hal_assert(ctxt_p->req_p != 0) ; + rec_p = ctxt_p->req_p ; + len_p = &ctxt_p->request_length ; + + } else { + if (ctxt_p->request_queue_p == 0 || + cy_as_request_get_node_state(ctxt_p->request_queue_p) + != CY_AS_REQUEST_LIST_STATE_WAITING) { + cy_as_hal_print_message("mailbox response received on " + "context that was not expecting a response\n") ; + cy_as_hal_print_message(" context: %d\n", context); + cy_as_hal_print_message(" contents: 0x%04x 0x%04x " + "0x%04x 0x%04x\n", + data[0], data[1], data[2], data[3]) ; + if (ctxt_p->request_queue_p != 0) + cy_as_hal_print_message(" state: 0x%02x\n", + ctxt_p->request_queue_p->state) ; + return ; + } + + /* Make sure the request has an associated response */ + cy_as_hal_assert(ctxt_p->request_queue_p->resp != 0) ; + + rec_p = ctxt_p->request_queue_p->resp ; + len_p = &ctxt_p->request_queue_p->length ; + } + + if (rec_p->stored == 0) { + /* + * this is the first cycle of the response + */ + cy_as_ll_request_response__set_code(rec_p, + cy_as_mbox_get_code(data[0])) ; + cy_as_ll_request_response__set_context(rec_p, context) ; + + if (cy_as_mbox_is_last(data[0])) { + /* This is a single cycle response */ + *len_p = rec_p->length ; + st = 1 ; + } else { + /* Ensure that enough memory has been + * reserved for the response. */ + cy_as_hal_assert(rec_p->length >= data[1]) ; + *len_p = (data[1] < rec_p->length) ? + data[1] : rec_p->length ; + st = 2 ; + } + } else + st = 1 ; + + /* Trasnfer the data from the mailboxes to the response */ + while (rec_p->stored < *len_p && st < 4) + rec_p->data[rec_p->stored++] = data[st++] ; + + if (cy_as_mbox_is_last(data[0])) { + /* NB: The call-back that is made below can cause the + * addition of more data in this queue, thus causing + * a recursive overflow of the queue. this is prevented + * by removing the request entry that is currently + * being passed up from the data queue. if this is done, + * the queue only needs to be as long as two request + * entries from west bridge. + */ + if ((ctxt_p->rqt_index > 0) && + (ctxt_p->rqt_index <= ctxt_p->queue_index)) { + dest = 0 ; + src = ctxt_p->rqt_index ; + + while (src < ctxt_p->queue_index) + ctxt_p->data_queue[dest++] = + ctxt_p->data_queue[src++] ; + + ctxt_p->rqt_index = 0 ; + ctxt_p->queue_index = dest ; + cy_as_hal_assert((ctxt_p->queue_index % 4) == 0) ; + } + + if (ctxt_p->request_queue_p != 0 && rec_p == + ctxt_p->request_queue_p->resp) { + /* + * if this is the last cycle of the response, call the + * callback and reset for the next response. + */ + cy_as_ll_request_response *resp_p = + ctxt_p->request_queue_p->resp ; + resp_p->length = ctxt_p->request_queue_p->length ; + cy_as_request_set_node_state(ctxt_p->request_queue_p, + CY_AS_REQUEST_LIST_STATE_RECEIVED) ; + + cy_as_device_set_in_callback(dev_p) ; + ctxt_p->request_queue_p->callback(dev_p, context, + ctxt_p->request_queue_p->rqt, + resp_p, CY_AS_ERROR_SUCCESS) ; + + cy_as_device_clear_in_callback(dev_p) ; + + cy_as_ll_remove_request_queue_head(dev_p, ctxt_p) ; + cy_as_ll_send_next_request(dev_p, ctxt_p) ; + } else { + /* Send the request to the appropriate + * module to handle */ + cy_as_ll_request_response *request_p = ctxt_p->req_p ; + ctxt_p->req_p = 0 ; + if (ctxt_p->request_callback) { + cy_as_device_set_in_callback(dev_p) ; + ctxt_p->request_callback(dev_p, context, + request_p, 0, CY_AS_ERROR_SUCCESS) ; + cy_as_device_clear_in_callback(dev_p) ; + } + cy_as_ll_init_request(request_p, 0, + context, request_p->length) ; + ctxt_p->req_p = request_p ; + } + } +} + +/* +* This is the handler for processing queued mailbox data +*/ +void +cy_as_mail_box_queued_data_handler(cy_as_device *dev_p) +{ + uint16_t i ; + + /* + * if more data gets queued in between our entering this call + * and the end of the iteration on all contexts; we should + * continue processing the queued data. + */ + while (dev_p->ll_queued_data) { + dev_p->ll_queued_data = cy_false ; + for (i = 0 ; i < CY_RQT_CONTEXT_COUNT ; i++) { + uint16_t offset ; + cy_as_context *ctxt_p = dev_p->context[i] ; + cy_as_hal_assert((ctxt_p->queue_index % 4) == 0) ; + + offset = 0 ; + while (offset < ctxt_p->queue_index) { + ctxt_p->rqt_index = offset + 4 ; + cy_as_mail_box_process_data(dev_p, + ctxt_p->data_queue + offset) ; + offset = ctxt_p->rqt_index ; + } + ctxt_p->queue_index = 0 ; + } + } +} + +/* +* This is the handler for the mailbox interrupt. This function reads +* data from the mailbox registers until a complete request or response +* is received. When a complete request is received, the callback +* associated with requests on that context is called. When a complete +* response is recevied, the callback associated with the request that +* generated the reponse is called. +*/ +void +cy_as_mail_box_interrupt_handler(cy_as_device *dev_p) +{ + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + /* + * queue the mailbox data to preserve + * order for later processing. + */ + cy_as_ll_queue_mailbox_data(dev_p) ; + + /* + * process what was queued and anything that may be pending + */ + cy_as_mail_box_queued_data_handler(dev_p) ; +} + +cy_as_return_status_t +cy_as_ll_start(cy_as_device *dev_p) +{ + uint16_t i ; + + if (cy_as_device_is_low_level_running(dev_p)) + return CY_AS_ERROR_ALREADY_RUNNING ; + + dev_p->ll_sending_rqt = cy_false ; + dev_p->ll_abort_curr_rqt = cy_false ; + + for (i = 0 ; i < CY_RQT_CONTEXT_COUNT ; i++) { + dev_p->context[i] = (cy_as_context *) + cy_as_hal_alloc(sizeof(cy_as_context)) ; + if (dev_p->context[i] == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + dev_p->context[i]->number = (uint8_t)i ; + dev_p->context[i]->request_callback = 0 ; + dev_p->context[i]->request_queue_p = 0 ; + dev_p->context[i]->last_node_p = 0 ; + dev_p->context[i]->req_p = cy_as_ll_create_request(dev_p, + 0, (uint8_t)i, max_request_length[i]) ; + dev_p->context[i]->queue_index = 0 ; + + if (!cy_as_hal_create_sleep_channel + (&dev_p->context[i]->channel)) + return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED ; + } + + cy_as_device_set_low_level_running(dev_p) ; + return CY_AS_ERROR_SUCCESS ; +} + +/* +* Shutdown the low level communications module. This operation will +* also cancel any queued low level requests. +*/ +cy_as_return_status_t +cy_as_ll_stop(cy_as_device *dev_p) +{ + uint8_t i ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_context *ctxt_p ; + uint32_t mask ; + + for (i = 0 ; i < CY_RQT_CONTEXT_COUNT ; i++) { + ctxt_p = dev_p->context[i] ; + if (!cy_as_hal_destroy_sleep_channel(&ctxt_p->channel)) + return CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED ; + + /* + * now, free any queued requests and assocaited responses + */ + while (ctxt_p->request_queue_p) { + uint32_t state ; + cy_as_ll_request_list_node *node_p = + ctxt_p->request_queue_p ; + + /* Mark this pair as in a cancel operation */ + cy_as_request_set_node_state(node_p, + CY_AS_REQUEST_LIST_STATE_CANCELING) ; + + /* Tell the caller that we are canceling this request */ + /* NB: The callback is responsible for destroying the + * request and the response. we cannot count on the + * contents of these two after calling the callback. + */ + node_p->callback(dev_p, i, node_p->rqt, + node_p->resp, CY_AS_ERROR_CANCELED) ; + + /* Remove the pair from the queue */ + mask = cy_as_hal_disable_interrupts() ; + ctxt_p->request_queue_p = node_p->next ; + cy_as_hal_enable_interrupts(mask) ; + + /* Free the list node */ + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node_p) ; + cy_as_hal_enable_interrupts(state) ; + } + + cy_as_ll_destroy_request(dev_p, dev_p->context[i]->req_p) ; + cy_as_hal_free(dev_p->context[i]) ; + dev_p->context[i] = 0 ; + + } + cy_as_device_set_low_level_stopped(dev_p) ; + + return ret ; +} + +void +cy_as_ll_init_request(cy_as_ll_request_response *req_p, + uint16_t code, uint16_t context, uint16_t length) +{ + uint16_t totallen = sizeof(cy_as_ll_request_response) + + (length - 1) * sizeof(uint16_t) ; + + cy_as_hal_mem_set(req_p, 0, totallen) ; + req_p->length = length ; + cy_as_ll_request_response__set_code(req_p, code) ; + cy_as_ll_request_response__set_context(req_p, context) ; + cy_as_ll_request_response__set_request(req_p) ; +} + +/* +* Create a new request. +*/ +cy_as_ll_request_response * +cy_as_ll_create_request(cy_as_device *dev_p, uint16_t code, + uint8_t context, uint16_t length) +{ + cy_as_ll_request_response *req_p ; + uint32_t state ; + uint16_t totallen = sizeof(cy_as_ll_request_response) + + (length - 1) * sizeof(uint16_t) ; + + (void)dev_p ; + + state = cy_as_hal_disable_interrupts() ; + req_p = cy_as_hal_c_b_alloc(totallen) ; + cy_as_hal_enable_interrupts(state) ; + if (req_p) + cy_as_ll_init_request(req_p, code, context, length) ; + + return req_p ; +} + +/* +* Destroy a request. +*/ +void +cy_as_ll_destroy_request(cy_as_device *dev_p, cy_as_ll_request_response *req_p) +{ + uint32_t state ; + (void)dev_p ; + (void)req_p ; + + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(req_p) ; + cy_as_hal_enable_interrupts(state) ; + +} + +void +cy_as_ll_init_response(cy_as_ll_request_response *req_p, uint16_t length) +{ + uint16_t totallen = sizeof(cy_as_ll_request_response) + + (length - 1) * sizeof(uint16_t) ; + + cy_as_hal_mem_set(req_p, 0, totallen) ; + req_p->length = length ; + cy_as_ll_request_response__set_response(req_p) ; +} + +/* +* Create a new response +*/ +cy_as_ll_request_response * +cy_as_ll_create_response(cy_as_device *dev_p, uint16_t length) +{ + cy_as_ll_request_response *req_p ; + uint32_t state ; + uint16_t totallen = sizeof(cy_as_ll_request_response) + + (length - 1) * sizeof(uint16_t) ; + + (void)dev_p ; + + state = cy_as_hal_disable_interrupts() ; + req_p = cy_as_hal_c_b_alloc(totallen) ; + cy_as_hal_enable_interrupts(state) ; + if (req_p) + cy_as_ll_init_response(req_p, length) ; + + return req_p ; +} + +/* +* Destroy the new response +*/ +void +cy_as_ll_destroy_response(cy_as_device *dev_p, cy_as_ll_request_response *req_p) +{ + uint32_t state ; + (void)dev_p ; + (void)req_p ; + + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(req_p) ; + cy_as_hal_enable_interrupts(state) ; +} + +static uint16_t +cy_as_read_intr_status( + cy_as_device *dev_p) +{ + uint32_t mask ; + cy_bool bloop = cy_true ; + uint16_t v = 0, last = 0xffff; + + /* + * before determining if the mailboxes are ready for more data, + * we first check the mailbox interrupt to see if we need to + * receive data. this prevents a dead-lock condition that can + * occur when both sides are trying to receive data. + */ + while (last == last) { + /* + * disable interrupts to be sure we don't process the mailbox + * here and have the interrupt routine try to read this data + * as well. + */ + mask = cy_as_hal_disable_interrupts() ; + + /* + * see if there is data to be read. + */ + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG) ; + if ((v & CY_AS_MEM_P0_INTR_REG_MBINT) == 0) { + cy_as_hal_enable_interrupts(mask) ; + break ; + } + + /* + * queue the mailbox data for later processing. + * this allows the firmware to move forward and + * service the requst from the P port. + */ + cy_as_ll_queue_mailbox_data(dev_p) ; + + /* + * enable interrupts again to service mailbox + * interrupts appropriately + */ + cy_as_hal_enable_interrupts(mask) ; + } + + /* + * now, all data is received + */ + last = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD ; + while (bloop) { + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD ; + if (v == last) + break ; + + last = v ; + } + + return v ; +} + +/* +* Send a single request or response using the mail box register. +* This function does not deal with the internal queues at all, +* but only sends the request or response across to the firmware +*/ +static cy_as_return_status_t +cy_as_send_one( + cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + int i ; + uint16_t mb0, v ; + int32_t loopcount ; + uint32_t int_stat ; + +#ifdef _DEBUG + if (cy_as_ll_request_response__is_request(req_p)) { + switch (cy_as_ll_request_response__get_context(req_p)) { + case CY_RQT_GENERAL_RQT_CONTEXT: + cy_as_hal_assert(req_p->length * 2 + 2 < + CY_CTX_GEN_MAX_DATA_SIZE) ; + break ; + + case CY_RQT_RESOURCE_RQT_CONTEXT: + cy_as_hal_assert(req_p->length * 2 + 2 < + CY_CTX_RES_MAX_DATA_SIZE) ; + break ; + + case CY_RQT_STORAGE_RQT_CONTEXT: + cy_as_hal_assert(req_p->length * 2 + 2 < + CY_CTX_STR_MAX_DATA_SIZE) ; + break ; + + case CY_RQT_USB_RQT_CONTEXT: + cy_as_hal_assert(req_p->length * 2 + 2 < + CY_CTX_USB_MAX_DATA_SIZE) ; + break ; + } + } +#endif + + /* Write the request to the mail box registers */ + if (req_p->length > 3) { + uint16_t length = req_p->length ; + int which = 0 ; + int st = 1 ; + + dev_p->ll_sending_rqt = cy_true ; + while (which < length) { + loopcount = cy_as_low_level_timeout_count ; + do { + v = cy_as_read_intr_status(dev_p) ; + + } while (v && loopcount-- > 0) ; + + if (v) { + cy_as_hal_print_message( + ">>>>>> LOW LEVEL TIMEOUT " + "%x %x %x %x\n", + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX0), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX1), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX2), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX3)) ; + return CY_AS_ERROR_TIMEOUT ; + } + + if (dev_p->ll_abort_curr_rqt) { + dev_p->ll_sending_rqt = cy_false ; + dev_p->ll_abort_curr_rqt = cy_false ; + return CY_AS_ERROR_CANCELED ; + } + + int_stat = cy_as_hal_disable_interrupts() ; + + /* + * check again whether the mailbox is free. + * it is possible that an ISR came in and + * wrote into the mailboxes since we last + * checked the status. + */ + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MB_STAT) & + CY_AS_MEM_P0_MCU_MBNOTRD ; + if (v) { + /* Go back to the original check since + * the mailbox is not free. */ + cy_as_hal_enable_interrupts(int_stat) ; + continue ; + } + + if (which == 0) { + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX1, length) ; + st = 2 ; + } else { + st = 1; + } + + while ((which < length) && (st < 4)) { + cy_as_hal_write_register(dev_p->tag, + cy_cast_int2U_int16 + (CY_AS_MEM_MCU_MAILBOX0 + st), + req_p->data[which++]) ; + st++ ; + } + + mb0 = req_p->box0 ; + if (which == length) { + dev_p->ll_sending_rqt = cy_false ; + mb0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK ; + } + + if (dev_p->ll_abort_curr_rqt) { + dev_p->ll_sending_rqt = cy_false ; + dev_p->ll_abort_curr_rqt = cy_false ; + cy_as_hal_enable_interrupts(int_stat) ; + return CY_AS_ERROR_CANCELED ; + } + + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX0, mb0) ; + + /* Wait for the MBOX interrupt to be high */ + cy_as_hal_sleep150() ; + cy_as_hal_enable_interrupts(int_stat) ; + } + } else { +check_mailbox_availability: + /* + * wait for the mailbox registers to become available. this + * should be a very quick wait as the firmware is designed + * to accept requests at interrupt time and queue them for + * future processing. + */ + loopcount = cy_as_low_level_timeout_count ; + do { + v = cy_as_read_intr_status(dev_p) ; + + } while (v && loopcount-- > 0) ; + + if (v) { + cy_as_hal_print_message( + ">>>>>> LOW LEVEL TIMEOUT %x %x %x %x\n", + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX0), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX1), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX2), + cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_MCU_MAILBOX3)) ; + return CY_AS_ERROR_TIMEOUT ; + } + + int_stat = cy_as_hal_disable_interrupts(); + + /* + * check again whether the mailbox is free. it is + * possible that an ISR came in and wrote into the + * mailboxes since we last checked the status. + */ + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_MCU_MB_STAT) & + CY_AS_MEM_P0_MCU_MBNOTRD ; + if (v) { + /* Go back to the original check + * since the mailbox is not free. */ + cy_as_hal_enable_interrupts(int_stat) ; + goto check_mailbox_availability ; + } + + /* Write the data associated with the request + * into the mbox registers 1 - 3 */ + v = 0 ; + for (i = req_p->length - 1 ; i >= 0 ; i--) + cy_as_hal_write_register(dev_p->tag, + cy_cast_int2U_int16(CY_AS_MEM_MCU_MAILBOX1 + i), + req_p->data[i]) ; + + /* Write the mbox register 0 to trigger the interrupt */ + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_MCU_MAILBOX0, + req_p->box0 | CY_AS_REQUEST_RESPONSE_LAST_MASK) ; + + cy_as_hal_sleep150() ; + cy_as_hal_enable_interrupts(int_stat); + } + + return CY_AS_ERROR_SUCCESS ; +} + +/* +* This function queues a single request to be sent to the firmware. +*/ +extern cy_as_return_status_t +cy_as_ll_send_request( + cy_as_device *dev_p, + /* The request to send */ + cy_as_ll_request_response *req, + /* Storage for a reply, must be sure + * it is of sufficient size */ + cy_as_ll_request_response *resp, + /* If true, this is a synchronous request */ + cy_bool sync, + /* Callback to call when reply is received */ + cy_as_response_callback cb +) +{ + cy_as_context *ctxt_p ; + uint16_t box0 = req->box0 ; + uint8_t context ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_list_node *node_p ; + uint32_t mask, state ; + + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE); + + context = cy_as_mbox_get_context(box0) ; + cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT) ; + ctxt_p = dev_p->context[context] ; + + /* Allocate the list node */ + state = cy_as_hal_disable_interrupts() ; + node_p = cy_as_hal_c_b_alloc(sizeof(cy_as_ll_request_list_node)) ; + cy_as_hal_enable_interrupts(state) ; + + if (node_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Initialize the list node */ + node_p->callback = cb ; + node_p->length = 0 ; + node_p->next = 0 ; + node_p->resp = resp ; + node_p->rqt = req ; + node_p->state = CY_AS_REQUEST_LIST_STATE_QUEUED ; + if (sync) + cy_as_request_node_set_sync(node_p) ; + + /* Put the request into the queue */ + mask = cy_as_hal_disable_interrupts() ; + if (ctxt_p->request_queue_p == 0) { + /* Empty queue */ + ctxt_p->request_queue_p = node_p ; + ctxt_p->last_node_p = node_p ; + } else { + ctxt_p->last_node_p->next = node_p ; + ctxt_p->last_node_p = node_p ; + } + cy_as_hal_enable_interrupts(mask) ; + cy_as_ll_send_next_request(dev_p, ctxt_p) ; + + if (!cy_as_device_is_in_callback(dev_p)) { + mask = cy_as_hal_disable_interrupts() ; + cy_as_mail_box_queued_data_handler(dev_p) ; + cy_as_hal_enable_interrupts(mask) ; + } + + return ret ; +} + +static void +cy_as_ll_send_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + (void)rqt ; + (void)resp ; + (void)ret ; + + + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + /* + * storage the state to return to the caller + */ + dev_p->ll_error = ret ; + + /* + * now wake the caller + */ + cy_as_hal_wake(&dev_p->context[context]->channel) ; +} + +cy_as_return_status_t +cy_as_ll_send_request_wait_reply( + cy_as_device *dev_p, + /* The request to send */ + cy_as_ll_request_response *req, + /* Storage for a reply, must be + * sure it is of sufficient size */ + cy_as_ll_request_response *resp + ) +{ + cy_as_return_status_t ret ; + uint8_t context ; + /* Larger 8 sec time-out to handle the init + * delay for slower storage devices in USB FS. */ + uint32_t loopcount = 800 ; + cy_as_context *ctxt_p ; + + /* Get the context for the request */ + context = cy_as_ll_request_response__get_context(req) ; + cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT) ; + ctxt_p = dev_p->context[context] ; + + ret = cy_as_ll_send_request(dev_p, req, resp, + cy_true, cy_as_ll_send_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + while (loopcount-- > 0) { + /* + * sleep while we wait on the response. receiving the reply will + * wake this thread. we will wait, at most 2 seconds (10 ms*200 + * tries) before we timeout. note if the reply arrives, we will + * not sleep the entire 10 ms, just til the reply arrives. + */ + cy_as_hal_sleep_on(&ctxt_p->channel, 10) ; + + /* + * if the request has left the queue, it means the request has + * been sent and the reply has been received. this means we can + * return to the caller and be sure the reply has been received. + */ + if (!cy_as_ll_is_in_queue(ctxt_p, req)) + return dev_p->ll_error ; + } + + /* Remove the QueueListNode for this request. */ + cy_as_ll_remove_request(dev_p, ctxt_p, req, cy_true) ; + + return CY_AS_ERROR_TIMEOUT ; +} + +cy_as_return_status_t +cy_as_ll_register_request_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_response_callback cb) +{ + cy_as_context *ctxt_p ; + cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT) ; + ctxt_p = dev_p->context[context] ; + + ctxt_p->request_callback = cb ; + return CY_AS_ERROR_SUCCESS ; +} + +void +cy_as_ll_request_response__pack( + cy_as_ll_request_response *req_p, + uint32_t offset, + uint32_t length, + void *data_p) +{ + uint16_t dt ; + uint8_t *dp = (uint8_t *)data_p ; + + while (length > 1) { + dt = ((*dp++) << 8) ; + dt |= (*dp++) ; + cy_as_ll_request_response__set_word(req_p, offset, dt) ; + offset++ ; + length -= 2 ; + } + + if (length == 1) { + dt = (*dp << 8) ; + cy_as_ll_request_response__set_word(req_p, offset, dt) ; + } +} + +void +cy_as_ll_request_response__unpack( + cy_as_ll_request_response *req_p, + uint32_t offset, + uint32_t length, + void *data_p) +{ + uint8_t *dp = (uint8_t *)data_p ; + + while (length-- > 0) { + uint16_t val = cy_as_ll_request_response__get_word + (req_p, offset++) ; + *dp++ = (uint8_t)((val >> 8) & 0xff) ; + + if (length) { + length-- ; + *dp++ = (uint8_t)(val & 0xff) ; + } + } +} + +extern cy_as_return_status_t +cy_as_ll_send_status_response( + cy_as_device *dev_p, + uint8_t context, + uint16_t code, + uint8_t clear_storage) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response resp ; + cy_as_ll_request_response *resp_p = &resp ; + + cy_as_hal_mem_set(resp_p, 0, sizeof(resp)) ; + resp_p->length = 1 ; + cy_as_ll_request_response__set_response(resp_p) ; + cy_as_ll_request_response__set_context(resp_p, context) ; + + if (clear_storage) + cy_as_ll_request_response__set_clear_storage_flag(resp_p) ; + + cy_as_ll_request_response__set_code(resp_p, CY_RESP_SUCCESS_FAILURE) ; + cy_as_ll_request_response__set_word(resp_p, 0, code) ; + + ret = cy_as_send_one(dev_p, resp_p) ; + + return ret ; +} + +extern cy_as_return_status_t +cy_as_ll_send_data_response( + cy_as_device *dev_p, + uint8_t context, + uint16_t code, + uint16_t length, + void *data) +{ + cy_as_ll_request_response *resp_p ; + uint16_t wlen ; + uint8_t respbuf[256] ; + + if (length > 192) + return CY_AS_ERROR_INVALID_SIZE ; + + /* Word length for bytes */ + wlen = length / 2 ; + + /* If byte length odd, add one more */ + if (length % 2) + wlen++ ; + + /* One for the length of field */ + wlen++ ; + + resp_p = (cy_as_ll_request_response *)respbuf ; + cy_as_hal_mem_set(resp_p, 0, sizeof(respbuf)) ; + resp_p->length = wlen ; + cy_as_ll_request_response__set_context(resp_p, context) ; + cy_as_ll_request_response__set_code(resp_p, code) ; + + cy_as_ll_request_response__set_word(resp_p, 0, length) ; + cy_as_ll_request_response__pack(resp_p, 1, length, data) ; + + return cy_as_send_one(dev_p, resp_p) ; +} + +static cy_bool +cy_as_ll_is_e_p_transfer_related_request(cy_as_ll_request_response *rqt_p, + cy_as_end_point_number_t ep) +{ + uint16_t v ; + uint8_t type = cy_as_ll_request_response__get_code(rqt_p) ; + + if (cy_as_ll_request_response__get_context(rqt_p) != + CY_RQT_USB_RQT_CONTEXT) + return cy_false ; + + /* + * when cancelling outstanding EP0 data transfers, any pending + * setup ACK requests also need to be cancelled. + */ + if ((ep == 0) && (type == CY_RQT_ACK_SETUP_PACKET)) + return cy_true ; + + if (type != CY_RQT_USB_EP_DATA) + return cy_false ; + + v = cy_as_ll_request_response__get_word(rqt_p, 0) ; + if ((cy_as_end_point_number_t)((v >> 13) & 1) != ep) + return cy_false ; + + return cy_true ; +} + +cy_as_return_status_t +cy_as_ll_remove_ep_data_requests(cy_as_device *dev_p, + cy_as_end_point_number_t ep) +{ + cy_as_context *ctxt_p ; + cy_as_ll_request_list_node *node_p ; + uint32_t imask ; + + /* + * first, remove any queued requests + */ + ctxt_p = dev_p->context[CY_RQT_USB_RQT_CONTEXT] ; + if (ctxt_p) { + for (node_p = ctxt_p->request_queue_p; node_p; + node_p = node_p->next) { + if (cy_as_ll_is_e_p_transfer_related_request + (node_p->rqt, ep)) { + cy_as_ll_remove_request(dev_p, ctxt_p, + node_p->rqt, cy_false) ; + break ; + } + } + + /* + * now, deal with any request that may be in transit + */ + imask = cy_as_hal_disable_interrupts() ; + + if (ctxt_p->request_queue_p != 0 && + cy_as_ll_is_e_p_transfer_related_request + (ctxt_p->request_queue_p->rqt, ep) && + cy_as_request_get_node_state(ctxt_p->request_queue_p) == + CY_AS_REQUEST_LIST_STATE_WAITING) { + cy_as_hal_print_message("need to remove an in-transit " + "request to antioch\n") ; + + /* + * if the request has not been fully sent to west bridge + * yet, abort sending. otherwise, terminate the request + * with a CANCELED status. firmware will already have + * terminated this transfer. + */ + if (dev_p->ll_sending_rqt) + dev_p->ll_abort_curr_rqt = cy_true ; + else { + uint32_t state ; + + node_p = ctxt_p->request_queue_p ; + if (node_p->callback) + node_p->callback(dev_p, ctxt_p->number, + node_p->rqt, node_p->resp, + CY_AS_ERROR_CANCELED) ; + + ctxt_p->request_queue_p = node_p->next ; + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node_p) ; + cy_as_hal_enable_interrupts(state) ; + } + } + + cy_as_hal_enable_interrupts(imask) ; + } + + return CY_AS_ERROR_SUCCESS ; +} diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c new file mode 100644 index 000000000000..7c1c945873d5 --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c @@ -0,0 +1,3474 @@ +/* Cypress West Bridge API source file (cyasmisc.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasmisc.h" +#include "../../include/linux/westbridge/cyasdma.h" +#include "../../include/linux/westbridge/cyasintr.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasregs.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyasprotocol.h" + +/* +* The device list, the only global in the API +*/ +static cy_as_device *g_device_list; + +/* + * The current debug level + */ +static uint8_t debug_level; + +/* + * This function sets the debug level for the API + * + */ +void +cy_as_misc_set_log_level(uint8_t level) +{ + debug_level = level ; +} + +#ifdef CY_AS_LOG_SUPPORT + +/* + * This function is a low level logger for the API. + */ +void +cy_as_log_debug_message(int level, const char *str) +{ + if (level <= debug_level) + cy_as_hal_print_message("log %d: %s\n", level, str) ; +} + +#endif + +#define cy_as_check_device_ready(dev_p) \ +{\ + if (!(dev_p) || ((dev_p)->sig != \ + CY_AS_DEVICE_HANDLE_SIGNATURE)) \ + return CY_AS_ERROR_INVALID_HANDLE ; \ +\ + if (!cy_as_device_is_configured(dev_p)) \ + return CY_AS_ERROR_NOT_CONFIGURED ; \ +\ + if (!cy_as_device_is_firmware_loaded(dev_p))\ + return CY_AS_ERROR_NO_FIRMWARE ; \ +} + +/* Find an West Bridge device based on a TAG */ +cy_as_device * +cy_as_device_find_from_tag(cy_as_hal_device_tag tag) +{ + cy_as_device *dev_p ; + + for (dev_p = g_device_list; dev_p != 0; dev_p = dev_p->next_p) { + if (dev_p->tag == tag) + return dev_p ; + } + + return 0 ; +} + +/* Map a pre-V1.2 media type to the V1.2+ bus number */ +static void +cy_as_bus_from_media_type(cy_as_media_type type, + cy_as_bus_number_t *bus) +{ + if (type == cy_as_media_nand) + *bus = 0 ; + else + *bus = 1 ; +} + +static cy_as_return_status_t +my_handle_response_no_data(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* +* Create a new West Bridge device +*/ +cy_as_return_status_t +cy_as_misc_create_device(cy_as_device_handle *handle_p, + cy_as_hal_device_tag tag) +{ + cy_as_device *dev_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_log_debug_message(6, "cy_as_misc_create_device called") ; + + dev_p = (cy_as_device *)cy_as_hal_alloc(sizeof(cy_as_device)) ; + if (dev_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + cy_as_hal_mem_set(dev_p, 0, sizeof(cy_as_device)) ; + + /* + * dynamically allocating this buffer to ensure that it is + * word aligned. + */ + dev_p->usb_ep_data = (uint8_t *)cy_as_hal_alloc(64 * sizeof(uint8_t)) ; + if (dev_p->usb_ep_data == 0) { + cy_as_hal_free(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + dev_p->sig = CY_AS_DEVICE_HANDLE_SIGNATURE ; + dev_p->tag = tag ; + dev_p->usb_max_tx_size = 0x40 ; + + dev_p->storage_write_endpoint = CY_AS_P2S_WRITE_ENDPOINT ; + dev_p->storage_read_endpoint = CY_AS_P2S_READ_ENDPOINT ; + + dev_p->func_cbs_misc = cy_as_create_c_b_queue(CYAS_FUNC_CB) ; + if (dev_p->func_cbs_misc == 0) + goto destroy ; + + dev_p->func_cbs_res = cy_as_create_c_b_queue(CYAS_FUNC_CB) ; + if (dev_p->func_cbs_res == 0) + goto destroy ; + + dev_p->func_cbs_stor = cy_as_create_c_b_queue(CYAS_FUNC_CB) ; + if (dev_p->func_cbs_stor == 0) + goto destroy ; + + dev_p->func_cbs_usb = cy_as_create_c_b_queue(CYAS_FUNC_CB) ; + if (dev_p->func_cbs_usb == 0) + goto destroy ; + + dev_p->func_cbs_mtp = cy_as_create_c_b_queue(CYAS_FUNC_CB) ; + if (dev_p->func_cbs_mtp == 0) + goto destroy ; + + /* + * allocate memory for the DMA module here. it is then marked idle, and + * will be activated when cy_as_misc_configure_device is called. + */ + ret = cy_as_dma_start(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + cy_as_device_set_dma_stopped(dev_p) ; + + /* + * allocate memory for the low level module here. this module is also + * activated only when cy_as_misc_configure_device is called. + */ + ret = cy_as_ll_start(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + cy_as_device_set_low_level_stopped(dev_p) ; + + dev_p->next_p = g_device_list ; + g_device_list = dev_p ; + + *handle_p = dev_p ; + cy_as_hal_init_dev_registers(tag, cy_false) ; + return CY_AS_ERROR_SUCCESS ; + +destroy: + /* Free any queues that were successfully allocated. */ + if (dev_p->func_cbs_misc) + cy_as_destroy_c_b_queue(dev_p->func_cbs_misc) ; + + if (dev_p->func_cbs_res) + cy_as_destroy_c_b_queue(dev_p->func_cbs_res) ; + + if (dev_p->func_cbs_stor) + cy_as_destroy_c_b_queue(dev_p->func_cbs_stor) ; + + if (dev_p->func_cbs_usb) + cy_as_destroy_c_b_queue(dev_p->func_cbs_usb) ; + + if (dev_p->func_cbs_mtp) + cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp) ; + + cy_as_hal_free(dev_p->usb_ep_data) ; + cy_as_hal_free(dev_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + else + return CY_AS_ERROR_OUT_OF_MEMORY ; +} + +/* +* Destroy an existing West Bridge device +*/ +cy_as_return_status_t +cy_as_misc_destroy_device(cy_as_device_handle handle) +{ + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_destroy_device called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * if the USB stack is still running, + * it must be stopped first + */ + if (dev_p->usb_count > 0) + return CY_AS_ERROR_STILL_RUNNING ; + + /* + * if the STORAGE stack is still running, + * it must be stopped first + */ + if (dev_p->storage_count > 0) + return CY_AS_ERROR_STILL_RUNNING ; + + if (cy_as_device_is_intr_running(dev_p)) + ret = cy_as_intr_stop(dev_p) ; + + ret = cy_as_ll_stop(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_intr_start(dev_p, dev_p->use_int_drq) ; + return ret ; + } + + ret = cy_as_dma_stop(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_intr_start(dev_p, dev_p->use_int_drq) ; + return ret ; + } + + /* Reset the West Bridge device. */ + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, + CY_AS_MEM_RST_CTRL_REG_HARD) ; + + /* + * remove the device from the device list + */ + if (g_device_list == dev_p) { + g_device_list = dev_p->next_p ; + } else { + cy_as_device *tmp_p = g_device_list ; + while (tmp_p && tmp_p->next_p != dev_p) + tmp_p = tmp_p->next_p ; + + cy_as_hal_assert(tmp_p != 0) ; + tmp_p->next_p = dev_p->next_p ; + } + + /* + * reset the signature so this will not be detected + * as a valid handle + */ + dev_p->sig = 0 ; + + cy_as_destroy_c_b_queue(dev_p->func_cbs_misc) ; + cy_as_destroy_c_b_queue(dev_p->func_cbs_res) ; + cy_as_destroy_c_b_queue(dev_p->func_cbs_stor) ; + cy_as_destroy_c_b_queue(dev_p->func_cbs_usb) ; + cy_as_destroy_c_b_queue(dev_p->func_cbs_mtp) ; + + /* + * free the memory associated with the device + */ + cy_as_hal_free(dev_p->usb_ep_data) ; + cy_as_hal_free(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +/* +* Determine the endian mode for the processor we are +* running on, then set the endian mode register +*/ +static void +cy_as_setup_endian_mode(cy_as_device *dev_p) +{ + /* + * In general, we always set west bridge intothe little + * endian mode. this causes the data on bit 0 internally + * to come out on data line 0 externally and it is generally + * what we want regardless of the endian mode of the + * processor. this capability in west bridge should be + * labeled as a "SWAP" capability and can be used to swap the + * bytes of data in and out of west bridge. this is + * useful if there is DMA hardware that requires this for some + * reason I cannot imagine at this time. basically if the + * wires are connected correctly, we should never need to + * change the endian-ness of west bridge. + */ + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_ENDIAN, + CY_AS_LITTLE_ENDIAN) ; +} + +/* +* Query the West Bridge device and determine if we are an standby mode +*/ +cy_as_return_status_t +cy_as_misc_in_standby(cy_as_device_handle handle, cy_bool *standby) +{ + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_in_standby called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (cy_as_device_is_pin_standby(dev_p) || + cy_as_device_is_register_standby(dev_p)) { + *standby = cy_true ; + } else + *standby = cy_false ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +cy_as_misc_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) ; + + +static void +my_misc_callback(cy_as_device *dev_p, uint8_t context, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *resp_p, + cy_as_return_status_t ret) +{ + (void)resp_p ; + (void)context ; + (void)ret ; + + switch (cy_as_ll_request_response__get_code(req_p)) { + case CY_RQT_INITIALIZATION_COMPLETE: + { + uint16_t v ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_GENERAL_RQT_CONTEXT, + CY_AS_ERROR_SUCCESS, 0) ; + cy_as_device_set_firmware_loaded(dev_p) ; + + if (cy_as_device_is_waking(dev_p)) { + /* + * this is a callback from a + * cy_as_misc_leave_standby() + * request. in this case we call + * the standby callback and clear + * the waking state. + */ + if (dev_p->misc_event_cb) + dev_p->misc_event_cb( + (cy_as_device_handle)dev_p, + cy_as_event_misc_awake, 0) ; + cy_as_device_clear_waking(dev_p) ; + } else { + v = cy_as_ll_request_response__get_word + (req_p, 3) ; + + /* + * store the media supported on + * each of the device buses. + */ + dev_p->media_supported[0] = + (uint8_t)(v & 0xFF) ; + dev_p->media_supported[1] = + (uint8_t)((v >> 8) & 0xFF) ; + + v = cy_as_ll_request_response__get_word + (req_p, 4) ; + + dev_p->is_mtp_firmware = + (cy_bool)((v >> 8) & 0xFF) ; + + if (dev_p->misc_event_cb) + dev_p->misc_event_cb( + (cy_as_device_handle)dev_p, + cy_as_event_misc_initialized, 0) ; + } + + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_P0_VM_SET) ; + + if (v & CY_AS_MEM_P0_VM_SET_CFGMODE) + cy_as_hal_print_message( + "initialization message " + "recieved, but config bit " + "still set\n") ; + + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG) ; + if ((v & CY_AS_MEM_RST_RSTCMPT) == 0) + cy_as_hal_print_message( + "initialization message " + "recieved, but reset complete " + "bit still not set\n") ; + } + break ; + + case CY_RQT_OUT_OF_SUSPEND: + cy_as_ll_send_status_response(dev_p, CY_RQT_GENERAL_RQT_CONTEXT, + CY_AS_ERROR_SUCCESS, 0) ; + cy_as_device_clear_suspend_mode(dev_p) ; + + /* + * if the wakeup was caused by an async cy_as_misc_leave_suspend + * call, we have to call the corresponding callback. + */ + if (dev_p->func_cbs_misc->count > 0) { + cy_as_func_c_b_node *node = (cy_as_func_c_b_node *) + dev_p->func_cbs_misc->head_p ; + cy_as_hal_assert(node) ; + + if (cy_as_funct_c_b_type_get_type(node->data_type) == + CY_FUNCT_CB_MISC_LEAVESUSPEND) { + cy_as_hal_assert(node->cb_p != 0) ; + + node->cb_p((cy_as_device_handle)dev_p, + CY_AS_ERROR_SUCCESS, node->client_data, + CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ; + cy_as_remove_c_b_node(dev_p->func_cbs_misc) ; + } + } + + if (dev_p->misc_event_cb) + dev_p->misc_event_cb((cy_as_device_handle)dev_p, + cy_as_event_misc_wakeup, 0) ; + break ; + + case CY_RQT_DEBUG_MESSAGE: + if ((req_p->data[0] == 0) && (req_p->data[1] == 0) && + (req_p->data[2] == 0)) { + if (dev_p->misc_event_cb) + dev_p->misc_event_cb((cy_as_device_handle)dev_p, + cy_as_event_misc_heart_beat, 0) ; + } else { + cy_as_hal_print_message( + "**** debug message: %02x " + "%02x %02x %02x %02x %02x\n", + req_p->data[0] & 0xff, + (req_p->data[0] >> 8) & 0xff, + req_p->data[1] & 0xff, + (req_p->data[1] >> 8) & 0xff, + req_p->data[2] & 0xff, + (req_p->data[2] >> 8) & 0xff) ; + } + break ; + + case CY_RQT_WB_DEVICE_MISMATCH: + { + if (dev_p->misc_event_cb) + dev_p->misc_event_cb((cy_as_device_handle)dev_p, + cy_as_event_misc_device_mismatch, 0) ; + } + break ; + + case CY_RQT_BOOTLOAD_NO_FIRMWARE: + { + /* TODO Handle case when firmware is + * not found during bootloading. */ + cy_as_hal_print_message("no firmware image found " + "during bootload. device not started\n") ; + } + break ; + + default: + cy_as_hal_assert(0) ; + } +} + +static cy_bool +is_valid_silicon_id(uint16_t v) +{ + cy_bool idok = cy_false ; + + /* + * remove the revision number from the ID value + */ + v = v & CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK ; + + /* + * if this is west bridge, then we are OK. + */ + if (v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE || + v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE || + v == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE) + idok = cy_true ; + + return idok ; +} + +/* +* Configure the West Bridge device hardware +*/ +cy_as_return_status_t +cy_as_misc_configure_device(cy_as_device_handle handle, + cy_as_device_config *config_p) +{ + cy_as_return_status_t ret ; + cy_bool standby ; + cy_as_device *dev_p ; + uint16_t v ; + uint16_t fw_present; + cy_as_log_debug_message(6, "cy_as_misc_configure_device called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* Setup big endian vs little endian */ + cy_as_setup_endian_mode(dev_p) ; + + /* Now, confirm that we can talk to the West Bridge device */ + dev_p->silicon_id = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + fw_present = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG) ; + if (!(fw_present & CY_AS_MEM_RST_RSTCMPT)) { + if (!is_valid_silicon_id(dev_p->silicon_id)) + return CY_AS_ERROR_NO_ANTIOCH ; + } + /* Check for standby mode */ + ret = cy_as_misc_in_standby(handle, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + if (ret) + return CY_AS_ERROR_IN_STANDBY ; + + /* Setup P-port interface mode (CRAM / SRAM). */ + if (cy_as_device_is_astoria_dev(dev_p)) { + if (config_p->srammode) + v = CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM ; + else + v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ; + } else + v = CY_AS_MEM_P0_VM_SET_VMTYPE_RAM ; + + /* Setup synchronous versus asynchronous mode */ + if (config_p->sync) + v |= CY_AS_MEM_P0_VM_SET_IFMODE ; + if (config_p->dackmode == cy_as_device_dack_ack) + v |= CY_AS_MEM_P0_VM_SET_DACKEOB ; + if (config_p->drqpol) + v |= CY_AS_MEM_P0_VM_SET_DRQPOL ; + if (config_p->dackpol) + v |= CY_AS_MEM_P0_VM_SET_DACKPOL ; + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_VM_SET, v) ; + + if (config_p->crystal) + cy_as_device_set_crystal(dev_p) ; + else + cy_as_device_set_external_clock(dev_p) ; + + /* Register a callback to handle MISC requests from the firmware */ + cy_as_ll_register_request_callback(dev_p, + CY_RQT_GENERAL_RQT_CONTEXT, my_misc_callback) ; + + /* Now mark the DMA and low level modules as active. */ + cy_as_device_set_dma_running(dev_p) ; + cy_as_device_set_low_level_running(dev_p) ; + + /* Now, initialize the interrupt module */ + dev_p->use_int_drq = config_p->dmaintr ; + ret = cy_as_intr_start(dev_p, config_p->dmaintr) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Mark the interface as initialized */ + cy_as_device_set_configured(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +my_dma_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, + void *mem_p, + uint32_t size, + cy_as_return_status_t ret + ) +{ + cy_as_dma_end_point *ep_p ; + + (void)size ; + + /* Get the endpoint pointer based on the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, ep) ; + + /* Check the queue to see if is drained */ + if (ep_p->queue_p == 0) { + cy_as_func_c_b_node *node = + (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p ; + + cy_as_hal_assert(node) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + /* + * disable endpoint 2. the storage module + * will enable this EP if necessary. + */ + cy_as_dma_enable_end_point(dev_p, + CY_AS_FIRMWARE_ENDPOINT, + cy_false, cy_as_direction_in) ; + + /* + * clear the reset register. this releases the + * antioch micro-controller from reset and begins + * running the code at address zero. + */ + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG, 0x00) ; + } + + /* Call the user Callback */ + node->cb_p((cy_as_device_handle)dev_p, ret, node->client_data, + node->data_type, node->data) ; + cy_as_remove_c_b_node(dev_p->func_cbs_misc) ; + } else { + /* This is the header data that was allocated in the + * download firmware function, and can be safely freed + * here. */ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(mem_p) ; + cy_as_hal_enable_interrupts(state) ; + } +} + +cy_as_return_status_t +cy_as_misc_download_firmware(cy_as_device_handle handle, + const void *mem_p, + uint16_t size, + cy_as_function_callback cb, + uint32_t client) +{ + uint8_t *header ; + cy_as_return_status_t ret ; + cy_bool standby ; + cy_as_device *dev_p ; + cy_as_dma_callback dmacb = 0 ; + uint32_t state ; + + cy_as_log_debug_message(6, "cy_as_misc_download_firmware called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * if the device has not been initialized, we cannot download firmware + * to the device. + */ + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + /* + * make sure west bridge is not in standby + */ + ret = cy_as_misc_in_standby(dev_p, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (standby) + return CY_AS_ERROR_IN_STANDBY ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* + * make sure we are in configuration mode + */ + if ((cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_VM_SET) & + CY_AS_MEM_P0_VM_SET_CFGMODE) == 0) + return CY_AS_ERROR_NOT_IN_CONFIG_MODE ; + + /* Maximum firmware size is 24k */ + if (size > CY_AS_MAXIMUM_FIRMWARE_SIZE) + return CY_AS_ERROR_INVALID_SIZE ; + + /* Make sure the size is an even number of bytes as well */ + if (size & 0x01) + return CY_AS_ERROR_ALIGNMENT_ERROR ; + + /* + * write the two word header that gives the base address and + * size of the firmware image to download + */ + state = cy_as_hal_disable_interrupts() ; + header = (uint8_t *)cy_as_hal_c_b_alloc(4) ; + cy_as_hal_enable_interrupts(state) ; + if (header == NULL) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + header[0] = 0x00 ; + header[1] = 0x00 ; + header[2] = (uint8_t)(size & 0xff) ; + header[3] = (uint8_t)((size >> 8) & 0xff) ; + + /* Enable the firmware endpoint */ + ret = cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT, + cy_true, cy_as_direction_in) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * setup DMA for 64 byte packets. this is the requirement for downloading + * firmware to west bridge. + */ + cy_as_dma_set_max_dma_size(dev_p, CY_AS_FIRMWARE_ENDPOINT, 64) ; + + if (cb) + dmacb = my_dma_callback ; + + ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, header, + 4, cy_false, cy_false, dmacb) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * write the firmware image to the west bridge device + */ + ret = cy_as_dma_queue_request(dev_p, CY_AS_FIRMWARE_ENDPOINT, + (void *)mem_p, size, cy_false, cy_false, dmacb) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cb) { + cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data( + cb, client, CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, 0) ; + + if (cbnode == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + else + cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode) ; + + ret = cy_as_dma_kick_start(dev_p, CY_AS_FIRMWARE_ENDPOINT) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } else { + ret = cy_as_dma_drain_queue(dev_p, + CY_AS_FIRMWARE_ENDPOINT, cy_true) ; + + /* Free the header memory that was allocated earlier. */ + cy_as_hal_c_b_free(header) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * disable EP 2. the storage module will + * enable this EP if necessary. + */ + cy_as_dma_enable_end_point(dev_p, CY_AS_FIRMWARE_ENDPOINT, + cy_false, cy_as_direction_in) ; + + /* + * clear the reset register. this releases the west bridge + * micro-controller from reset and begins running the code at + * address zero. + */ + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG, 0x00) ; + } + + /* + * the firmware is not marked as loaded until the firmware + * initializes west bridge and a request is sent from west bridge + * to the P port processor indicating that west bridge is ready. + */ + return CY_AS_ERROR_SUCCESS ; +} + + +static cy_as_return_status_t +my_handle_response_get_firmware_version(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_get_firmware_version_data *data_p) +{ + + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t val ; + + if (cy_as_ll_request_response__get_code(reply_p) + != CY_RESP_FIRMWARE_VERSION) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + data_p->major = cy_as_ll_request_response__get_word(reply_p, 0) ; + data_p->minor = cy_as_ll_request_response__get_word(reply_p, 1) ; + data_p->build = cy_as_ll_request_response__get_word(reply_p, 2) ; + val = cy_as_ll_request_response__get_word(reply_p, 3) ; + data_p->media_type = (uint8_t)(((val >> 8) & 0xFF) | (val & 0xFF)) ; + val = cy_as_ll_request_response__get_word(reply_p, 4) ; + data_p->is_debug_mode = (cy_bool)(val & 0xFF) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_get_firmware_version(cy_as_device_handle handle, + cy_as_get_firmware_version_data *data, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_bool standby ; + cy_as_ll_request_response *req_p, *reply_p ; + + cy_as_device *dev_p ; + + (void)client ; + + cy_as_log_debug_message(6, "cy_as_misc_get_firmware_version called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* + * make sure antioch is not in standby + */ + ret = cy_as_misc_in_standby(dev_p, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + if (standby) + return CY_AS_ERROR_IN_STANDBY ; + + /* Make sure the Antioch is not in suspend mode. */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_FIRMWARE_VERSION, + CY_RQT_GENERAL_RQT_CONTEXT, 0) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* + * Reserve space for the reply, the reply data + * will not exceed three words + */ + reply_p = cy_as_ll_create_response(dev_p, 5) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* Request and response are freed in + * MyHandleResponseGetFirmwareVersion. */ + ret = my_handle_response_get_firmware_version(dev_p, + req_p, reply_p, data) ; + return ret ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, data, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} +static cy_as_return_status_t +my_handle_response_read_m_c_u_register(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + uint8_t *data_p) +{ + + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) + != CY_RESP_MCU_REGISTER_DATA) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + *data_p = (uint8_t) + (cy_as_ll_request_response__get_word(reply_p, 0)) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_get_gpio_value(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + uint8_t *data_p) +{ + + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) + != CY_RESP_GPIO_STATE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } else + *data_p = (uint8_t) + (cy_as_ll_request_response__get_word(reply_p, 0)) ; + + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + + +cy_as_return_status_t cy_as_misc_set_sd_power_polarity( + cy_as_device_handle handle, + cy_as_misc_signal_polarity polarity, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDPOLARITY, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)polarity) ; + + /* + * Reserve space for the reply, the reply data will + * not exceed one word + */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return (my_handle_response_no_data(dev_p, req_p, reply_p)) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_SETSDPOLARITY, 0, dev_p->func_cbs_misc, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the FuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + + +cy_as_return_status_t +cy_as_misc_read_m_c_u_register(cy_as_device_handle handle, + uint16_t address, + uint8_t *value, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_read_m_c_u_register called") ; + + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* Check whether the firmware supports this command. */ + if (cy_as_device_is_nand_storage_supported(dev_p)) + return CY_AS_ERROR_NOT_SUPPORTED ; + + /* Make sure the Antioch is not in suspend mode. */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_READ_MCU_REGISTER, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address) ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_MCU_REGISTER_DATA) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + *value = (uint8_t)(cy_as_ll_request_response__get_word + (reply_p, 0)) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_READMCUREGISTER, value, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + + +cy_as_return_status_t +cy_as_misc_write_m_c_u_register(cy_as_device_handle handle, + uint16_t address, + uint8_t mask, + uint8_t value, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_write_m_c_u_register called") ; + + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* Check whether the firmware supports this command. */ + if (cy_as_device_is_nand_storage_supported(dev_p)) + return CY_AS_ERROR_NOT_SUPPORTED ; + + /* Make sure the Antioch is not in suspend mode. */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_WRITE_MCU_REGISTER, + CY_RQT_GENERAL_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)address) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((mask << 8) | value)) ; + + /* + * Reserve space for the reply, the reply data + * will not exceed one word + */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_WRITEMCUREGISTER, 0, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* + * The request and response are freed as part of the + * MiscFuncCallback + */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +my_handle_response_reset(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_reset_type type) +{ + uint16_t v ; + + (void)req_p ; + (void)reply_p ; + + /* + * if the device is in suspend mode, it needs to be woken up + * so that the write to the reset control register succeeds. + * we need not however wait for the wake up procedure to be + * complete. + */ + if (cy_as_device_is_in_suspend_mode(dev_p)) { + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + cy_as_hal_sleep(1) ; + } + + if (type == cy_as_reset_hard) { + cy_as_misc_cancel_ex_requests(dev_p) ; + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_RST_CTRL_REG, + CY_AS_MEM_RST_CTRL_REG_HARD) ; + cy_as_device_set_unconfigured(dev_p) ; + cy_as_device_set_firmware_not_loaded(dev_p) ; + cy_as_device_set_dma_stopped(dev_p) ; + cy_as_device_set_low_level_stopped(dev_p) ; + cy_as_device_set_intr_stopped(dev_p) ; + cy_as_device_clear_suspend_mode(dev_p) ; + cy_as_usb_cleanup(dev_p) ; + cy_as_storage_cleanup(dev_p) ; + + /* + * wait for a small amount of time to + * allow reset to be complete. + */ + cy_as_hal_sleep(100) ; + } + + cy_as_device_clear_reset_pending(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_misc_reset(cy_as_device_handle handle, + cy_as_reset_type type, + cy_bool flush, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + cy_as_end_point_number_t i ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + (void)client ; + (void)cb ; + + cy_as_log_debug_message(6, "cy_as_misc_reset_e_x called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* + * soft reset is not supported until we close on the issues + * in the firmware with what needs to happen. + */ + if (type == cy_as_reset_soft) + return CY_AS_ERROR_NOT_YET_SUPPORTED ; + + cy_as_device_set_reset_pending(dev_p) ; + + if (flush) { + /* Unable to DrainQueues in polling mode */ + if ((dev_p->storage_cb || dev_p->storage_cb_ms) && + cy_as_hal_is_polling()) + return CY_AS_ERROR_ASYNC_PENDING ; + + /* + * shutdown the endpoints so no more traffic can be queued + */ + for (i = 0; i < 15; i++) + cy_as_dma_enable_end_point(dev_p, i, cy_false, + cy_as_direction_dont_change) ; + + /* + * if we are in normal mode, drain all traffic across all + * endpoints to be sure all traffic is flushed. if the + * device is suspended, data will not be coming in on any + * endpoint and all outstanding DMA operations can be + * cancelled. + */ + if (cy_as_device_is_in_suspend_mode(dev_p)) { + for (i = 0; i < 15; i++) + cy_as_dma_cancel(dev_p, i, + CY_AS_ERROR_CANCELED) ; + } else { + for (i = 0; i < 15; i++) { + if ((i == CY_AS_P2S_WRITE_ENDPOINT) || + (i == CY_AS_P2S_READ_ENDPOINT)) + cy_as_dma_drain_queue(dev_p, i, + cy_false) ; + else + cy_as_dma_drain_queue(dev_p, i, + cy_true) ; + } + } + } else { + /* No flush was requested, so cancel any outstanding DMAs + * so the user callbacks are called as needed + */ + if (cy_as_device_is_storage_async_pending(dev_p)) { + for (i = 0; i < 15; i++) + cy_as_dma_cancel(dev_p, i, + CY_AS_ERROR_CANCELED) ; + } + } + + ret = my_handle_response_reset(dev_p, 0, 0, type) ; + + if (cb) + /* Even though no mailbox communication was needed, + * issue the callback so the user does not need to + * special case their code. */ + cb((cy_as_device_handle)dev_p, ret, client, + CY_FUNCT_CB_MISC_RESET, 0) ; + + /* + * initialize any registers that may have been + * changed when the device was reset. + */ + cy_as_hal_init_dev_registers(dev_p->tag, cy_false) ; + + return ret ; +} + +static cy_as_return_status_t +get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource) +{ + uint8_t shift = 0 ; + uint16_t v ; + cy_as_return_status_t ret = CY_AS_ERROR_NOT_ACQUIRED ; + + switch (resource) { + case cy_as_bus_u_s_b: + shift = 4 ; + break ; + case cy_as_bus_1: + shift = 0 ; + break ; + case cy_as_bus_0: + shift = 2 ; + break ; + default: + cy_as_hal_assert(cy_false) ; + break ; + } + + /* Get the semaphore value for this resource */ + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_ALLOCATE) ; + v = (v >> shift) & 0x03 ; + + if (v == 0x03) { + ret = CY_AS_ERROR_RESOURCE_ALREADY_OWNED ; + } else if ((v & 0x01) == 0) { + /* The resource is not owned by anyone, we can try to get it */ + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ; + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ; + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_P0_RSE_ALLOCATE, (0x01 << shift)) ; + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_RSE_MASK) ; + + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_P0_RSE_ALLOCATE) ; + v = (v >> shift) & 0x03 ; + if (v == 0x03) + ret = CY_AS_ERROR_SUCCESS ; + } + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_acquire_resource(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_resource_type *resource) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + if (ret == CY_AS_ERROR_SUCCESS) { + ret = get_unallocated_resource(dev_p, *resource) ; + if (ret != CY_AS_ERROR_NOT_ACQUIRED) + ret = CY_AS_ERROR_SUCCESS ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_acquire_resource(cy_as_device_handle handle, + cy_as_resource_type *resource, + cy_bool force, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret ; + + cy_as_device *dev_p ; + + (void)client ; + + cy_as_log_debug_message(6, "cy_as_misc_acquire_resource called") ; + + if (*resource != cy_as_bus_u_s_b && *resource != + cy_as_bus_0 && *resource != cy_as_bus_1) + return CY_AS_ERROR_INVALID_RESOURCE ; + + + /* Make sure the device is ready to accept the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + + ret = get_unallocated_resource(dev_p, *resource) ; + + /* + * make sure that the callback is called if the resource is + * successfully acquired at this point. + */ + if ((ret == CY_AS_ERROR_SUCCESS) && (cb != 0)) + cb(handle, ret, client, + CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource) ; + + if (ret != CY_AS_ERROR_NOT_ACQUIRED) + return ret ; + + if (!force) + return CY_AS_ERROR_NOT_ACQUIRED ; + + /* Create the request to acquire the resource */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_ACQUIRE_RESOURCE, + CY_RQT_RESOURCE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)(*resource)) ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_ACQUIRERESOURCE, resource, + dev_p->func_cbs_res, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + ret = get_unallocated_resource(dev_p, *resource) ; + if (ret != CY_AS_ERROR_NOT_ACQUIRED) + ret = CY_AS_ERROR_SUCCESS ; + } + + return ret ; +} +cy_as_return_status_t +cy_as_misc_release_resource(cy_as_device_handle handle, + cy_as_resource_type resource) +{ + uint8_t shift = 0 ; + uint16_t v ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_release_resource called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (resource != cy_as_bus_u_s_b && resource != + cy_as_bus_0 && resource != cy_as_bus_1) + return CY_AS_ERROR_INVALID_RESOURCE ; + + switch (resource) { + case cy_as_bus_u_s_b: + shift = 4 ; + break ; + case cy_as_bus_1: + shift = 0 ; + break ; + case cy_as_bus_0: + shift = 2 ; + break ; + default: + cy_as_hal_assert(cy_false) ; + break ; + } + + /* Get the semaphore value for this resource */ + v = (cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_P0_RSE_ALLOCATE) >> shift) & 0x03 ; + if (v == 0 || v == 1 || v == 2) + return CY_AS_ERROR_RESOURCE_NOT_OWNED ; + + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_P0_RSE_MASK, (0x03 << shift)) ; + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_P0_RSE_ALLOCATE, (0x02 << shift)) ; + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_P0_RSE_MASK, 0) ; + + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_misc_set_trace_level(cy_as_device_handle handle, + uint8_t level, + cy_as_bus_number_t bus, + uint32_t device, + uint32_t unit, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_set_trace_level called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (unit > 255) + return CY_AS_ERROR_NO_SUCH_UNIT ; + + if (level >= CYAS_FW_TRACE_MAX_LEVEL) + return CY_AS_ERROR_INVALID_TRACE_LEVEL ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_TRACE_LEVEL, + CY_RQT_GENERAL_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)level) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((bus << 12) | (device << 8) | (unit))) ; + + /* + * Reserve space for the reply, the reply data will not + * exceed three words + */ + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_NOT_SUPPORTED ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_SETTRACELEVEL, 0, dev_p->func_cbs_misc, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_heart_beat_control(cy_as_device_handle handle, + cy_bool enable, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_heart_beat_control called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_CONTROL_ANTIOCH_HEARTBEAT, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)enable) ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_HEARTBEATCONTROL, 0, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_set_sd_clock_freq( + cy_as_device *dev_p, + uint8_t card_type, + uint8_t setting, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + + if (cy_as_device_is_in_callback(dev_p) && (cb == 0)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_SD_CLOCK_FREQ, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((card_type << 8) | setting)) ; + + /* Reserve space for the reply, which will not exceed one word. */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_SETSDFREQ, 0, dev_p->func_cbs_misc, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_set_low_speed_sd_freq( + cy_as_device_handle handle, + cy_as_low_speed_sd_freq setting, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_set_low_speed_sd_freq called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if ((setting != CY_AS_SD_DEFAULT_FREQ) && + (setting != CY_AS_SD_RATED_FREQ)) + return CY_AS_ERROR_INVALID_PARAMETER ; + + return my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client) ; +} + +cy_as_return_status_t +cy_as_misc_set_high_speed_sd_freq( + cy_as_device_handle handle, + cy_as_high_speed_sd_freq setting, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_set_high_speed_sd_freq called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if ((setting != CY_AS_HS_SD_FREQ_24) && + (setting != CY_AS_HS_SD_FREQ_48)) + return CY_AS_ERROR_INVALID_PARAMETER ; + + return my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client) ; +} + +cy_as_return_status_t +cy_as_misc_get_gpio_value(cy_as_device_handle handle, + cy_as_misc_gpio pin, + uint8_t *value, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_device *dev_p ; + uint16_t v ; + + cy_as_log_debug_message(6, "cy_as_misc_get_gpio_value called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* If the pin specified is UVALID, there is no need + * for firmware to be loaded. */ + if (pin == cy_as_misc_gpio_U_valid) { + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ; + *value = (uint8_t)(v & CY_AS_MEM_PMU_UPDATE_UVALID) ; + + if (cb != 0) + cb(dev_p, ret, client, + CY_FUNCT_CB_MISC_GETGPIOVALUE, value) ; + + return ret ; + } + + /* Check whether the firmware supports this command. */ + if (cy_as_device_is_nand_storage_supported(dev_p)) + return CY_AS_ERROR_NOT_SUPPORTED ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Make sure the pin selected is valid */ + if ((pin != cy_as_misc_gpio_1) && (pin != cy_as_misc_gpio_0)) + return CY_AS_ERROR_INVALID_PARAMETER ; + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_GPIO_STATE, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, ((uint8_t)pin << 8)) ; + + /* Reserve space for the reply, which will not exceed one word. */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_GPIO_STATE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + *value = (uint8_t) + cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_GETGPIOVALUE, value, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + + +cy_as_return_status_t +cy_as_misc_set_gpio_value(cy_as_device_handle handle, + cy_as_misc_gpio pin, + uint8_t value, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_device *dev_p ; + uint16_t v ; + + cy_as_log_debug_message(6, "cy_as_misc_set_gpio_value called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* If the pin specified is UVALID, there is + * no need for firmware to be loaded. */ + if (pin == cy_as_misc_gpio_U_valid) { + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PMU_UPDATE) ; + if (value) + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_PMU_UPDATE, + (v | CY_AS_MEM_PMU_UPDATE_UVALID)) ; + else + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_PMU_UPDATE, + (v & ~CY_AS_MEM_PMU_UPDATE_UVALID)) ; + + if (cb != 0) + cb(dev_p, ret, client, + CY_FUNCT_CB_MISC_SETGPIOVALUE, 0) ; + return ret ; + } + + /* Check whether the firmware supports this command. */ + if (cy_as_device_is_nand_storage_supported(dev_p)) + return CY_AS_ERROR_NOT_SUPPORTED ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Make sure the pin selected is valid */ + if ((pin < cy_as_misc_gpio_0) || (pin > cy_as_misc_gpio_U_valid)) + return CY_AS_ERROR_INVALID_PARAMETER ; + + /* Create and initialize the low level request to the firmware. */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_GPIO_STATE, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + v = (uint16_t)(((uint8_t)pin << 8) | (value > 0)) ; + cy_as_ll_request_response__set_word(req_p, 0, v) ; + + /* Reserve space for the reply, which will not exceed one word. */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_SETGPIOVALUE, 0, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_enter_standby(cy_as_device *dev_p, cy_bool pin) +{ + cy_as_misc_cancel_ex_requests(dev_p) ; + + /* Save the current values in the critical P-port + * registers, where necessary. */ + cy_as_hal_read_regs_before_standby(dev_p->tag) ; + + if (pin) { + if (cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false)) + cy_as_device_set_pin_standby(dev_p) ; + else + return CY_AS_ERROR_SETTING_WAKEUP_PIN ; + } else { + /* + * put antioch in the standby mode + */ + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_PWR_MAGT_STAT, 0x02) ; + cy_as_device_set_register_standby(dev_p) ; + } + + /* + * when the antioch comes out of standby, we have to wait until + * the firmware initialization completes before sending other + * requests down. + */ + cy_as_device_set_firmware_not_loaded(dev_p) ; + + /* + * keep west bridge interrupt disabled until the device is being woken + * up from standby. + */ + dev_p->stby_int_mask = cy_as_hal_disable_interrupts(); + + return CY_AS_ERROR_SUCCESS ; +} + +static cy_as_return_status_t +my_handle_response_enter_standby(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_bool pin) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + ret = my_enter_standby(dev_p, pin) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_enter_standby(cy_as_device_handle handle, + cy_bool pin, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_bool standby ; + + cy_as_log_debug_message(6, "cy_as_misc_enter_standby called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * if we already are in standby, do not do it again and let the + * user know via the error return. + */ + ret = cy_as_misc_in_standby(handle, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (standby == cy_true) + return CY_AS_ERROR_ALREADY_STANDBY ; + + /* + * if the user wants to transition from suspend mode to standby mode, + * the device needs to be woken up so that it can complete all pending + * operations. + */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + cy_as_misc_leave_suspend(dev_p, 0, 0) ; + + if (dev_p->usb_count) { + /* + * we do not allow west bridge to go into standby mode when the + * USB stack is initialized. you must stop the USB stack in + * order to enter standby mode. + */ + return CY_AS_ERROR_USB_RUNNING ; + } + + /* + * if the storage stack is not running, the device can directly be + * put into sleep mode. otherwise, the firmware needs to be signaled + * to prepare for going into sleep mode. + */ + if (dev_p->storage_count) { + /* + * if there are async storage operations pending, + * make one attempt to complete them. + */ + if (cy_as_device_is_storage_async_pending(dev_p)) { + /* DrainQueue will not work in polling mode */ + if (cy_as_hal_is_polling()) + return CY_AS_ERROR_ASYNC_PENDING ; + + cy_as_dma_drain_queue(dev_p, + CY_AS_P2S_READ_ENDPOINT, cy_false) ; + cy_as_dma_drain_queue(dev_p, + CY_AS_P2S_WRITE_ENDPOINT, cy_false) ; + + /* + * if more storage operations were queued + * at this stage, return an error. + */ + if (cy_as_device_is_storage_async_pending(dev_p)) + return CY_AS_ERROR_ASYNC_PENDING ; + } + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_PREPARE_FOR_STANDBY, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (!cb) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * in the HandleResponse */ + return my_handle_response_enter_standby(dev_p, + req_p, reply_p, pin) ; + + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_ENTERSTANDBY, (void *)pin, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else { + ret = my_enter_standby(dev_p, pin) ; + if (cb) + /* Even though no mailbox communication was + * needed, issue the callback so the user + * does not need to special case their code. */ + cb((cy_as_device_handle)dev_p, ret, client, + CY_FUNCT_CB_MISC_ENTERSTANDBY, 0) ; + } + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle, + cy_bool pin, + cy_bool uvalid_special, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + + dev_p = (cy_as_device *)handle ; + if (uvalid_special) + cy_as_hal_write_register(dev_p->tag, 0xc5, 0x4) ; + + return cy_as_misc_enter_standby(handle, pin, cb, client) ; +} + +cy_as_return_status_t +cy_as_misc_leave_standby(cy_as_device_handle handle, + cy_as_resource_type resource) +{ + cy_as_device *dev_p ; + uint16_t v ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint32_t count = 8 ; + uint8_t retry = 1 ; + + cy_as_log_debug_message(6, "cy_as_misc_leave_standby called") ; + (void)resource ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (cy_as_device_is_register_standby(dev_p)) { + /* + * set a flag to indicate that the west bridge is waking + * up from standby. + */ + cy_as_device_set_waking(dev_p) ; + + /* + * the initial read will not succeed, but will just wake + * the west bridge device from standby. successive reads + * should succeed and in that way we know west bridge is awake. + */ + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + + do { + /* + * we have initiated the operation to leave standby, now + * we need to wait at least N ms before trying to access + * the west bridge device to insure the PLLs have locked + * and we can talk to the device. + */ + if (cy_as_device_is_crystal(dev_p)) + cy_as_hal_sleep( + CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ; + else + cy_as_hal_sleep( + CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ; + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + + /* + * if the P-SPI interface mode is in use, there may be a + * need to re-synchronise the serial clock used for + * astoria access. + */ + if (!is_valid_silicon_id(v)) { + if (cy_as_hal_sync_device_clocks(dev_p->tag) != + cy_true) { + cy_as_hal_enable_interrupts( + dev_p->stby_int_mask) ; + return CY_AS_ERROR_TIMEOUT ; + } + } + } while (!is_valid_silicon_id(v) && count-- > 0) ; + + /* + * if we tried to read the register and could not, + * return a timeout + */ + if (count == 0) { + cy_as_hal_enable_interrupts( + dev_p->stby_int_mask) ; + return CY_AS_ERROR_TIMEOUT ; + } + + /* + * the standby flag is cleared here, after the action to + * exit standby has been taken. the wait for firmware + * initialization, is ensured by marking the firmware as + * not loaded until the init event is received. + */ + cy_as_device_clear_register_standby(dev_p) ; + + /* + * initialize any registers that may have been changed + * while the device was in standby mode. + */ + cy_as_hal_init_dev_registers(dev_p->tag, cy_true) ; + } else if (cy_as_device_is_pin_standby(dev_p)) { + /* + * set a flag to indicate that the west bridge is waking + * up from standby. + */ + cy_as_device_set_waking(dev_p) ; + +try_wakeup_again: + /* + * try to set the wakeup pin, if this fails in the HAL + * layer, return this failure to the user. + */ + if (!cy_as_hal_set_wakeup_pin(dev_p->tag, cy_true)) { + cy_as_hal_enable_interrupts(dev_p->stby_int_mask) ; + return CY_AS_ERROR_SETTING_WAKEUP_PIN ; + } + + /* + * we have initiated the operation to leave standby, now + * we need to wait at least N ms before trying to access + * the west bridge device to insure the PL_ls have locked + * and we can talk to the device. + */ + if (cy_as_device_is_crystal(dev_p)) + cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) ; + else + cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ; + + /* + * initialize any registers that may have been changed + * while the device was in standby mode. + */ + cy_as_hal_init_dev_registers(dev_p->tag, cy_true) ; + + /* + * the standby flag is cleared here, after the action to + * exit standby has been taken. the wait for firmware + * initialization, is ensured by marking the firmware as + * not loaded until the init event is received. + */ + cy_as_device_clear_pin_standby(dev_p) ; + } else { + return CY_AS_ERROR_NOT_IN_STANDBY ; + } + + /* + * the west bridge interrupt can be enabled now. + */ + cy_as_hal_enable_interrupts(dev_p->stby_int_mask) ; + + /* + * release the west bridge micro-_controller from reset, + * so that firmware initialization can complete. the attempt + * to release antioch reset is made upto 8 times. + */ + v = 0x03 ; + count = 0x08 ; + while ((v & 0x03) && (count)) { + cy_as_hal_write_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG, 0x00) ; + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_RST_CTRL_REG) ; + count-- ; + } + + if (v & 0x03) { + cy_as_hal_print_message("failed to clear antioch reset\n") ; + return CY_AS_ERROR_TIMEOUT ; + } + + /* + * if the wake-up pin is being used, wait here to make + * sure that the wake-up event is received within a + * reasonable delay. otherwise, toggle the wake-up pin + * again in an attempt to start the firmware properly. + */ + if (retry) { + count = 10 ; + while (count) { + /* If the wake-up event has been received, + * we can return. */ + if (cy_as_device_is_firmware_loaded(dev_p)) + break ; + /* If we are in polling mode, the interrupt may + * not have been serviced as yet. read the + * interrupt status register. if a pending mailbox + * interrupt is seen, we can assume that the + * wake-up event will be received soon. */ + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_P0_INTR_REG) ; + if (v & CY_AS_MEM_P0_INTR_REG_MBINT) + break ; + + cy_as_hal_sleep(10) ; + count-- ; + } + + if (!count) { + retry = 0 ; + dev_p->stby_int_mask = cy_as_hal_disable_interrupts() ; + cy_as_hal_set_wakeup_pin(dev_p->tag, cy_false) ; + cy_as_hal_sleep(10) ; + goto try_wakeup_again ; + } + } + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_register_callback( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The function to call */ + cy_as_misc_event_callback callback + ) +{ + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_misc_register_callback called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + dev_p->misc_event_cb = callback ; + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_misc_storage_changed(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_bool standby ; + cy_as_ll_request_response *req_p, *reply_p ; + + cy_as_log_debug_message(6, "cy_as_misc_storage_changed called") ; + + /* Make sure the device is ready for the command. */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* + * make sure antioch is not in standby + */ + ret = cy_as_misc_in_standby(dev_p, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (standby) + return CY_AS_ERROR_IN_STANDBY ; + + /* + * make sure westbridge is not in suspend mode. + */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_STORAGE_MEDIA_CHANGED, + CY_RQT_GENERAL_RQT_CONTEXT, 0) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_STORAGECHANGED, 0, + dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + + +cy_as_return_status_t +cy_as_misc_enter_suspend( + cy_as_device_handle handle, + cy_bool usb_wakeup_en, + cy_bool gpio_wakeup_en, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_bool standby ; + cy_as_ll_request_response *req_p, *reply_p ; + uint16_t value ; + uint32_t int_state ; + + cy_as_log_debug_message(6, "cy_as_misc_enter_suspend called") ; + + /* + * basic sanity checks to ensure that the device is initialised. + */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* + * make sure west bridge is not already in standby + */ + cy_as_misc_in_standby(dev_p, &standby) ; + if (standby) + return CY_AS_ERROR_IN_STANDBY ; + + /* + * make sure that the device is not already in suspend mode. + */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* + * make sure there is no active USB connection. + */ + if ((cy_as_device_is_usb_connected(dev_p)) && (dev_p->usb_last_event + != cy_as_event_usb_suspend)) + return CY_AS_ERROR_USB_CONNECTED ; + + /* + * make sure that there are no async requests at this point in time. + */ + int_state = cy_as_hal_disable_interrupts() ; + if ((dev_p->func_cbs_misc->count) || (dev_p->func_cbs_res->count) || + (dev_p->func_cbs_stor->count) || (dev_p->func_cbs_usb->count)) { + cy_as_hal_enable_interrupts(int_state) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + cy_as_hal_enable_interrupts(int_state) ; + + /* Create the request to send to the Antioch device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_ENTER_SUSPEND_MODE, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply data will not + * exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Wakeup control flags. */ + value = 0x0001 ; + if (usb_wakeup_en) + value |= 0x04 ; + if (gpio_wakeup_en) + value |= 0x02 ; + cy_as_ll_request_response__set_word(req_p, 0, value) ; + + if (cb != 0) { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_ENTERSUSPEND, + 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, + cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return CY_AS_ERROR_SUCCESS ; + } else { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } + +destroy: + if (ret == CY_AS_ERROR_SUCCESS) + cy_as_device_set_suspend_mode(dev_p) ; + + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_leave_suspend( + cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + uint16_t v, count ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_log_debug_message(6, "cy_as_misc_leave_suspend called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* Make sure we are in suspend mode. */ + if (cy_as_device_is_in_suspend_mode(dev_p)) { + if (cb) { + cy_as_func_c_b_node *cbnode = + cy_as_create_func_c_b_node_data(cb, client, + CY_FUNCT_CB_MISC_LEAVESUSPEND, 0) ; + if (cbnode == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_insert_c_b_node(dev_p->func_cbs_misc, cbnode) ; + } + + /* + * do a read from the ID register so that the CE assertion + * will wake west bridge. the read is repeated until the + * read comes back with valid data. + */ + count = 8 ; + + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + + while (!is_valid_silicon_id(v) && count-- > 0) { + cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ; + v = cy_as_hal_read_register(dev_p->tag, + CY_AS_MEM_CM_WB_CFG_ID) ; + } + + /* + * if we tried to read the register and could not, + * return a timeout + */ + if (count == 0) + return CY_AS_ERROR_TIMEOUT ; + } else + return CY_AS_ERROR_NOT_IN_SUSPEND ; + + if (cb == 0) { + /* + * wait until the in suspend mode flag is cleared. + */ + count = 20 ; + while ((cy_as_device_is_in_suspend_mode(dev_p)) + && (count--)) { + cy_as_hal_sleep(CY_AS_LEAVE_STANDBY_DELAY_CLOCK) ; + } + + if (cy_as_device_is_in_suspend_mode(dev_p)) + ret = CY_AS_ERROR_TIMEOUT ; + } + + return ret ; +} + +cy_as_return_status_t +cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle, + uint8_t numzones, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_bool standby ; + cy_as_ll_request_response *req_p, *reply_p ; + + cy_as_device *dev_p ; + + (void)client ; + + cy_as_log_debug_message(6, "cy_as_misc_switch_pnand_mode called") ; + + /* Make sure we have a valid device */ + dev_p = (cy_as_device *)handle ; + cy_as_check_device_ready(dev_p) ; + + /* + * make sure antioch is not in standby + */ + ret = cy_as_misc_in_standby(dev_p, &standby) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + if (standby) + return CY_AS_ERROR_IN_STANDBY ; + + /* Make sure the Antioch is not in suspend mode. */ + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_RESERVE_LNA_BOOT_AREA, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + cy_as_ll_request_response__set_word(req_p, + 0, (uint16_t)numzones) ; + + /* Reserve space for the reply, the reply data will not + * exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MISC_RESERVELNABOOTAREA, + 0, dev_p->func_cbs_misc, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_misc_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_func_c_b_node* +cy_as_create_func_c_b_node_data(cy_as_function_callback cb, + uint32_t client, + cy_as_funct_c_b_type type, + void *data) +{ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_func_c_b_node *node = cy_as_hal_c_b_alloc( + sizeof(cy_as_func_c_b_node)) ; + cy_as_hal_enable_interrupts(state) ; + if (node != 0) { + node->node_type = CYAS_FUNC_CB ; + node->cb_p = cb ; + node->client_data = client ; + node->data_type = type ; + if (data != 0) + node->data_type |= CY_FUNCT_CB_DATA ; + else + node->data_type |= CY_FUNCT_CB_NODATA ; + node->data = data ; + node->next_p = 0 ; + } + return node ; +} + +cy_as_func_c_b_node* +cy_as_create_func_c_b_node(cy_as_function_callback cb, + uint32_t client) +{ + return cy_as_create_func_c_b_node_data(cb, client, + CY_FUNCT_CB_NODATA, 0) ; +} + +void +cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node) +{ + uint32_t state ; + + node->node_type = CYAS_INVALID ; + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node) ; + cy_as_hal_enable_interrupts(state) ; +} + +cy_as_usb_func_c_b_node* +cy_as_create_usb_func_c_b_node( + cy_as_usb_function_callback cb, uint32_t client) +{ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_usb_func_c_b_node *node = cy_as_hal_c_b_alloc( + sizeof(cy_as_usb_func_c_b_node)) ; + cy_as_hal_enable_interrupts(state) ; + if (node != 0) { + node->type = CYAS_USB_FUNC_CB ; + node->cb_p = cb ; + node->client_data = client ; + node->next_p = 0 ; + } + return node ; +} + +void +cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node) +{ + uint32_t state ; + + node->type = CYAS_INVALID ; + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node) ; + cy_as_hal_enable_interrupts(state) ; +} + +cy_as_usb_io_c_b_node* +cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb) +{ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_usb_io_c_b_node *node = cy_as_hal_c_b_alloc( + sizeof(cy_as_usb_io_c_b_node)) ; + cy_as_hal_enable_interrupts(state) ; + if (node != 0) { + node->type = CYAS_USB_IO_CB ; + node->cb_p = cb ; + node->next_p = 0 ; + } + return node ; +} + +void +cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node) +{ + uint32_t state ; + + node->type = CYAS_INVALID ; + + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node) ; + cy_as_hal_enable_interrupts(state) ; +} + +cy_as_storage_io_c_b_node* +cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb, + cy_as_media_type media, uint32_t device_index, + uint32_t unit, uint32_t block_addr, cy_as_oper_type oper, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_storage_io_c_b_node *node = cy_as_hal_c_b_alloc( + sizeof(cy_as_storage_io_c_b_node)) ; + cy_as_hal_enable_interrupts(state) ; + if (node != 0) { + node->type = CYAS_STORAGE_IO_CB ; + node->cb_p = cb ; + node->media = media ; + node->device_index = device_index ; + node->unit = unit ; + node->block_addr = block_addr ; + node->oper = oper ; + node->req_p = req_p ; + node->reply_p = reply_p ; + node->next_p = 0 ; + } + return node ; +} + +void +cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node) +{ + uint32_t state ; + node->type = CYAS_INVALID ; + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(node) ; + cy_as_hal_enable_interrupts(state) ; +} + +cy_as_c_b_queue * +cy_as_create_c_b_queue(cy_as_c_b_node_type type) +{ + uint32_t state = cy_as_hal_disable_interrupts() ; + cy_as_c_b_queue *queue = cy_as_hal_c_b_alloc( + sizeof(cy_as_c_b_queue)) ; + cy_as_hal_enable_interrupts(state) ; + if (queue) { + queue->type = type ; + queue->head_p = 0 ; + queue->tail_p = 0 ; + queue->count = 0 ; + } + + return queue ; +} + +void +cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue) +{ + uint32_t state ; + queue->type = CYAS_INVALID ; + queue->head_p = 0 ; + queue->tail_p = 0 ; + queue->count = 0 ; + state = cy_as_hal_disable_interrupts() ; + cy_as_hal_c_b_free(queue) ; + cy_as_hal_enable_interrupts(state) ; +} + +/* Inserts a CyAsCBNode into the queue, the + * node type must match the queue type*/ +void +cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void*cbnode) +{ + uint32_t int_state ; + + int_state = cy_as_hal_disable_interrupts() ; + + cy_as_hal_assert(queue_p != 0) ; + + switch (queue_p->type) { + case CYAS_USB_FUNC_CB: + { + cy_as_usb_func_c_b_node *node = + (cy_as_usb_func_c_b_node *)cbnode ; + cy_as_usb_func_c_b_node *tail = + (cy_as_usb_func_c_b_node *)queue_p->tail_p ; + + cy_as_hal_assert(node->type == CYAS_USB_FUNC_CB) ; + cy_as_hal_assert(tail == 0 || + tail->type == CYAS_USB_FUNC_CB) ; + if (queue_p->head_p == 0) + queue_p->head_p = node ; + else + tail->next_p = node ; + + queue_p->tail_p = node ; + } + break ; + + case CYAS_USB_IO_CB: + { + cy_as_usb_io_c_b_node *node = + (cy_as_usb_io_c_b_node *)cbnode ; + cy_as_usb_io_c_b_node *tail = + (cy_as_usb_io_c_b_node *)queue_p->tail_p ; + + cy_as_hal_assert(node->type == CYAS_USB_IO_CB) ; + cy_as_hal_assert(tail == 0 || + tail->type == CYAS_USB_IO_CB) ; + if (queue_p->head_p == 0) + queue_p->head_p = node ; + else + tail->next_p = node ; + + queue_p->tail_p = node ; + } + break ; + + case CYAS_STORAGE_IO_CB: + { + cy_as_storage_io_c_b_node *node = + (cy_as_storage_io_c_b_node *)cbnode ; + cy_as_storage_io_c_b_node *tail = + (cy_as_storage_io_c_b_node *)queue_p->tail_p ; + + cy_as_hal_assert(node->type == CYAS_STORAGE_IO_CB) ; + cy_as_hal_assert(tail == 0 || + tail->type == CYAS_STORAGE_IO_CB) ; + if (queue_p->head_p == 0) + queue_p->head_p = node ; + else + tail->next_p = node ; + + queue_p->tail_p = node ; + } + break ; + + case CYAS_FUNC_CB: + { + cy_as_func_c_b_node *node = + (cy_as_func_c_b_node *)cbnode ; + cy_as_func_c_b_node *tail = + (cy_as_func_c_b_node *)queue_p->tail_p ; + + cy_as_hal_assert(node->node_type == CYAS_FUNC_CB) ; + cy_as_hal_assert(tail == 0 || + tail->node_type == CYAS_FUNC_CB) ; + if (queue_p->head_p == 0) + queue_p->head_p = node ; + else + tail->next_p = node ; + + queue_p->tail_p = node ; + } + break ; + + default: + cy_as_hal_assert(cy_false) ; + break ; + } + + queue_p->count++ ; + + cy_as_hal_enable_interrupts(int_state) ; +} + +/* Removes the tail node from the queue and frees it */ +void +cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p) +{ + uint32_t int_state ; + + int_state = cy_as_hal_disable_interrupts() ; + + if (queue_p->count > 0) { + /* + * the worst case length of the queue should be + * under 10 elements, and the average case should + * be just 1 element. so, we just employ a linear + * search to find the node to be freed. + */ + switch (queue_p->type) { + case CYAS_FUNC_CB: + { + cy_as_func_c_b_node *node = + (cy_as_func_c_b_node *) + queue_p->head_p ; + cy_as_func_c_b_node *tail = + (cy_as_func_c_b_node *) + queue_p->tail_p ; + if (node != tail) { + while (node->next_p != tail) + node = node->next_p ; + node->next_p = 0 ; + queue_p->tail_p = node ; + } + cy_as_destroy_func_c_b_node(tail) ; + } + break ; + + case CYAS_USB_FUNC_CB: + { + cy_as_usb_func_c_b_node *node = + (cy_as_usb_func_c_b_node *) + queue_p->head_p ; + cy_as_usb_func_c_b_node *tail = + (cy_as_usb_func_c_b_node *) + queue_p->tail_p ; + if (node != tail) { + while (node->next_p != tail) + node = node->next_p ; + node->next_p = 0 ; + queue_p->tail_p = node ; + } + + cy_as_destroy_usb_func_c_b_node(tail) ; + } + break ; + + case CYAS_USB_IO_CB: + { + cy_as_usb_io_c_b_node *node = + (cy_as_usb_io_c_b_node *) + queue_p->head_p ; + cy_as_usb_io_c_b_node *tail = + (cy_as_usb_io_c_b_node *) + queue_p->tail_p ; + if (node != tail) { + while (node->next_p != tail) + node = node->next_p ; + node->next_p = 0 ; + queue_p->tail_p = node ; + } + cy_as_destroy_usb_io_c_b_node(tail) ; + } + break ; + + case CYAS_STORAGE_IO_CB: + { + cy_as_storage_io_c_b_node *node = + (cy_as_storage_io_c_b_node *) + queue_p->head_p ; + cy_as_storage_io_c_b_node *tail = + (cy_as_storage_io_c_b_node *) + queue_p->tail_p ; + if (node != tail) { + while (node->next_p != tail) + node = node->next_p ; + node->next_p = 0 ; + queue_p->tail_p = node ; + } + cy_as_destroy_storage_io_c_b_node(tail) ; + } + break ; + + default: + cy_as_hal_assert(cy_false) ; + } + + queue_p->count-- ; + if (queue_p->count == 0) { + queue_p->head_p = 0 ; + queue_p->tail_p = 0 ; + } + } + + cy_as_hal_enable_interrupts(int_state) ; +} + +/* Removes the first CyAsCBNode from the queue and frees it */ +void +cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p) +{ + uint32_t int_state ; + + int_state = cy_as_hal_disable_interrupts() ; + + cy_as_hal_assert(queue_p->count >= 0) ; + if (queue_p->count > 0) { + if (queue_p->type == CYAS_USB_FUNC_CB) { + cy_as_usb_func_c_b_node *node = + (cy_as_usb_func_c_b_node *) + queue_p->head_p ; + queue_p->head_p = node->next_p ; + cy_as_destroy_usb_func_c_b_node(node) ; + } else if (queue_p->type == CYAS_USB_IO_CB) { + cy_as_usb_io_c_b_node *node = + (cy_as_usb_io_c_b_node *) + queue_p->head_p ; + queue_p->head_p = node->next_p ; + cy_as_destroy_usb_io_c_b_node(node) ; + } else if (queue_p->type == CYAS_STORAGE_IO_CB) { + cy_as_storage_io_c_b_node *node = + (cy_as_storage_io_c_b_node *) + queue_p->head_p ; + queue_p->head_p = node->next_p ; + cy_as_destroy_storage_io_c_b_node(node) ; + } else if (queue_p->type == CYAS_FUNC_CB) { + cy_as_func_c_b_node *node = + (cy_as_func_c_b_node *) + queue_p->head_p ; + queue_p->head_p = node->next_p ; + cy_as_destroy_func_c_b_node(node) ; + } else { + cy_as_hal_assert(cy_false) ; + } + + queue_p->count-- ; + if (queue_p->count == 0) { + queue_p->head_p = 0 ; + queue_p->tail_p = 0 ; + } + } + + cy_as_hal_enable_interrupts(int_state) ; +} + +void my_print_func_c_b_node(cy_as_func_c_b_node *node) +{ + cy_as_funct_c_b_type type = + cy_as_funct_c_b_type_get_type(node->data_type) ; + cy_as_hal_print_message("[cd:%2u dt:%2u cb:0x%08x " + "d:0x%08x nt:%1i]", node->client_data, type, + (uint32_t)node->cb_p, (uint32_t)node->data, + node->node_type) ; +} + +void my_print_c_b_queue(cy_as_c_b_queue *queue_p) +{ + uint32_t i = 0 ; + + cy_as_hal_print_message("| count: %u type: ", queue_p->count) ; + + if (queue_p->type == CYAS_USB_FUNC_CB) { + cy_as_hal_print_message("USB_FUNC_CB\n") ; + } else if (queue_p->type == CYAS_USB_IO_CB) { + cy_as_hal_print_message("USB_IO_CB\n") ; + } else if (queue_p->type == CYAS_STORAGE_IO_CB) { + cy_as_hal_print_message("STORAGE_IO_CB\n") ; + } else if (queue_p->type == CYAS_FUNC_CB) { + cy_as_func_c_b_node *node = queue_p->head_p ; + cy_as_hal_print_message("FUNC_CB\n") ; + if (queue_p->count > 0) { + cy_as_hal_print_message("| head->") ; + + for (i = 0; i < queue_p->count; i++) { + if (node) { + cy_as_hal_print_message("->") ; + my_print_func_c_b_node(node) ; + node = node->next_p ; + } else + cy_as_hal_print_message("->[NULL]\n") ; + } + + cy_as_hal_print_message("\n| tail->") ; + my_print_func_c_b_node(queue_p->tail_p) ; + cy_as_hal_print_message("\n") ; + } + } else { + cy_as_hal_print_message("INVALID\n") ; + } + + cy_as_hal_print_message("|----------\n") ; +} + + +/* Removes and frees all pending callbacks */ +void +cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p) +{ + uint32_t int_state = cy_as_hal_disable_interrupts() ; + + while (queue_p->count != 0) + cy_as_remove_c_b_node(queue_p) ; + + cy_as_hal_enable_interrupts(int_state) ; +} + +cy_as_return_status_t +cy_as_misc_send_request(cy_as_device *dev_p, + cy_as_function_callback cb, + uint32_t client, + cy_as_funct_c_b_type type, + void *data, + cy_as_c_b_queue *queue, + uint16_t req_type, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_response_callback rcb) +{ + + cy_as_func_c_b_node *cbnode = cy_as_create_func_c_b_node_data(cb, + client, type, data) ; + cy_as_return_status_t ret ; + + if (cbnode == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + else + cy_as_insert_c_b_node(queue, cbnode) ; + + req_p->flags |= req_type ; + + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_false, rcb) ; + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_remove_c_b_tail_node(queue) ; + + return ret ; +} + +void +cy_as_misc_cancel_ex_requests(cy_as_device *dev_p) +{ + int i ; + for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) + cy_as_ll_remove_all_requests(dev_p, dev_p->context[i]) ; +} + + +static void +cy_as_misc_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + cy_as_func_c_b_node *node = NULL ; + cy_as_return_status_t ret ; + + cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) + == CY_AS_REQUEST_RESPONSE_EX ; + cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) + == CY_AS_REQUEST_RESPONSE_MS ; + uint8_t code ; + uint32_t type ; + uint8_t cntxt ; + + cy_as_hal_assert(ex_request || ms_request) ; + (void) ex_request; + (void) ms_request; + (void)context ; + + cntxt = cy_as_ll_request_response__get_context(rqt) ; + code = cy_as_ll_request_response__get_code(rqt) ; + + switch (cntxt) { + case CY_RQT_GENERAL_RQT_CONTEXT: + cy_as_hal_assert(dev_p->func_cbs_misc->count != 0) ; + cy_as_hal_assert(dev_p->func_cbs_misc->type == CYAS_FUNC_CB) ; + node = (cy_as_func_c_b_node *)dev_p->func_cbs_misc->head_p ; + type = cy_as_funct_c_b_type_get_type(node->data_type) ; + + switch (code) { + case CY_RQT_GET_FIRMWARE_VERSION: + cy_as_hal_assert(node->data != 0) ; + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_GETFIRMWAREVERSION) ; + ret = my_handle_response_get_firmware_version(dev_p, + rqt, resp, + (cy_as_get_firmware_version_data *)node->data); + break ; + case CY_RQT_READ_MCU_REGISTER: + cy_as_hal_assert(node->data != 0) ; + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_READMCUREGISTER) ; + ret = my_handle_response_read_m_c_u_register(dev_p, rqt, + resp, (uint8_t *)node->data) ; + break ; + case CY_RQT_GET_GPIO_STATE: + cy_as_hal_assert(node->data != 0) ; + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_GETGPIOVALUE) ; + ret = my_handle_response_get_gpio_value(dev_p, rqt, + resp, (uint8_t *)node->data) ; + break ; + case CY_RQT_SET_SD_CLOCK_FREQ: + cy_as_hal_assert(type == CY_FUNCT_CB_MISC_SETSDFREQ) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_CONTROL_ANTIOCH_HEARTBEAT: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_HEARTBEATCONTROL) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_WRITE_MCU_REGISTER: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_WRITEMCUREGISTER) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_STORAGE_MEDIA_CHANGED: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_STORAGECHANGED) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_SET_GPIO_STATE: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_SETGPIOVALUE) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_SET_TRACE_LEVEL: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_SETTRACELEVEL) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + if (ret == CY_AS_ERROR_INVALID_RESPONSE) + ret = CY_AS_ERROR_NOT_SUPPORTED ; + break ; + case CY_RQT_PREPARE_FOR_STANDBY: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_ENTERSTANDBY) ; + ret = my_handle_response_enter_standby(dev_p, rqt, resp, + (cy_bool)node->data) ; + break ; + case CY_RQT_ENTER_SUSPEND_MODE: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_ENTERSUSPEND) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + if (ret == CY_AS_ERROR_SUCCESS) + cy_as_device_set_suspend_mode(dev_p) ; + + break ; + case CY_RQT_RESERVE_LNA_BOOT_AREA: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_RESERVELNABOOTAREA) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_SDPOLARITY: + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_SETSDPOLARITY) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + break ; + + case CY_RQT_RESOURCE_RQT_CONTEXT: + cy_as_hal_assert(dev_p->func_cbs_res->count != 0) ; + cy_as_hal_assert(dev_p->func_cbs_res->type == CYAS_FUNC_CB) ; + node = (cy_as_func_c_b_node *)dev_p->func_cbs_res->head_p ; + type = cy_as_funct_c_b_type_get_type(node->data_type) ; + + switch (code) { + case CY_RQT_ACQUIRE_RESOURCE: + /* The node->data field is actually an enum value + * which could be 0, thus no assert is done */ + cy_as_hal_assert(type == + CY_FUNCT_CB_MISC_ACQUIRERESOURCE) ; + ret = my_handle_response_acquire_resource(dev_p, rqt, + resp, (cy_as_resource_type *)node->data) ; + break ; + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + break ; + + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + + /* + * if the low level layer returns a direct error, use the + * corresponding error code. if not, use the error code + * based on the response from firmware. + */ + if (stat == CY_AS_ERROR_SUCCESS) + stat = ret ; + + /* Call the user Callback */ + node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data, + node->data_type, node->data) ; + if (cntxt == CY_RQT_GENERAL_RQT_CONTEXT) + cy_as_remove_c_b_node(dev_p->func_cbs_misc) ; + else + cy_as_remove_c_b_node(dev_p->func_cbs_res) ; + +} + + + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c new file mode 100644 index 000000000000..3725800aa7be --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c @@ -0,0 +1,1128 @@ +/* Cypress West Bridge API header file (cyasmtp.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasmtp.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasdma.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" + +static void +cy_as_mtp_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) ; + +static cy_as_return_status_t +is_mtp_active(cy_as_device *dev_p) +{ + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->mtp_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +my_mtp_request_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *resp_p, + cy_as_return_status_t ret) +{ + uint16_t val, ev, status ; + uint16_t mtp_datalen = 0 ; + uint32_t bytecount_l, bytecount_h ; + cy_as_mtp_send_object_complete_data send_obj_data ; + cy_as_mtp_get_object_complete_data get_obj_data ; + cy_as_dma_end_point *ep_p ; + + uint8_t code = cy_as_ll_request_response__get_code(req_p) ; + + (void)resp_p ; + (void)context ; + (void)ret ; + + switch (code) { + case CY_RQT_MTP_EVENT: + val = cy_as_ll_request_response__get_word(req_p, 0) ; + /* MSB indicates status of read/write */ + status = (val >> 8) & 0xFF ; + /* event type */ + ev = val & 0xFF ; + switch (ev) { + case 0: /* SendObject Complete */ + { + bytecount_l = + cy_as_ll_request_response__get_word + (req_p, 1) ; + bytecount_h = + cy_as_ll_request_response__get_word + (req_p, 2) ; + send_obj_data.byte_count = + (bytecount_h << 16) | bytecount_l ; + + send_obj_data.status = status ; + + /* use the byte count again */ + bytecount_l = + cy_as_ll_request_response__get_word + (req_p, 3) ; + bytecount_h = + cy_as_ll_request_response__get_word + (req_p, 4) ; + send_obj_data.transaction_id = + (bytecount_h << 16) | bytecount_l ; + + dev_p->mtp_turbo_active = cy_false ; + + if (dev_p->mtp_event_cb) + dev_p->mtp_event_cb( + (cy_as_device_handle) dev_p, + cy_as_mtp_send_object_complete, + &send_obj_data) ; + } + break ; + + case 1: /* GetObject Complete */ + { + bytecount_l = + cy_as_ll_request_response__get_word + (req_p, 1) ; + bytecount_h = + cy_as_ll_request_response__get_word + (req_p, 2) ; + + get_obj_data.byte_count = + (bytecount_h << 16) | bytecount_l ; + + get_obj_data.status = status ; + + dev_p->mtp_turbo_active = cy_false ; + + if (dev_p->mtp_event_cb) + dev_p->mtp_event_cb( + (cy_as_device_handle) dev_p, + cy_as_mtp_get_object_complete, + &get_obj_data); + } + break ; + + case 2: /* BlockTable Needed */ + { + if (dev_p->mtp_event_cb) + dev_p->mtp_event_cb( + (cy_as_device_handle) dev_p, + cy_as_mtp_block_table_needed, 0); + } + break ; + default: + cy_as_hal_print_message("invalid event type\n") ; + cy_as_ll_send_data_response(dev_p, + CY_RQT_TUR_RQT_CONTEXT, + CY_RESP_MTP_INVALID_EVENT, + sizeof(ev), &ev) ; + break ; + } + break ; + + case CY_RQT_TURBO_CMD_FROM_HOST: + { + mtp_datalen = + cy_as_ll_request_response__get_word(req_p, 1) ; + + /* Get the endpoint pointer based on + * the endpoint number */ + ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_READ_ENDPOINT) ; + + /* The event should arrive only after the DMA operation + * has been queued. */ + cy_as_hal_assert(ep_p->queue_p != 0) ; + + /* Put the len in ep data information in + * dmaqueue and kick start the queue */ + cy_as_hal_assert(ep_p->queue_p->size >= mtp_datalen) ; + + if (mtp_datalen == 0) { + cy_as_dma_completed_callback(dev_p->tag, + CY_AS_MTP_READ_ENDPOINT, 0, + CY_AS_ERROR_SUCCESS) ; + } else { + ep_p->maxhwdata = mtp_datalen ; + + /* + * make sure that the DMA status for this + * EP is not running, so that the call to + * cy_as_dma_kick_start gets this transfer + * going. note: in MTP mode, we never leave + * a DMA transfer of greater than one packet + * running. so, it is okay to override the + * status here and start the next packet + * transfer. + */ + cy_as_dma_end_point_set_stopped(ep_p) ; + + /* Kick start the queue if it is not running */ + cy_as_dma_kick_start(dev_p, + CY_AS_MTP_READ_ENDPOINT); + } + } + break ; + + case CY_RQT_TURBO_START_WRITE_DMA: + { + /* + * now that the firmware is ready to receive the + * next packet of data, start the corresponding + * DMA transfer. first, ensure that a DMA + * operation is still pending in the queue for the + * write endpoint. + */ + cy_as_ll_send_status_response(dev_p, + CY_RQT_TUR_RQT_CONTEXT, + CY_AS_ERROR_SUCCESS, 0) ; + + ep_p = CY_AS_NUM_EP(dev_p, CY_AS_MTP_WRITE_ENDPOINT) ; + cy_as_hal_assert(ep_p->queue_p != 0) ; + + cy_as_dma_end_point_set_stopped(ep_p) ; + cy_as_dma_kick_start(dev_p, CY_AS_MTP_WRITE_ENDPOINT) ; + } + break ; + + default: + cy_as_hal_print_message("invalid request received " + "on TUR context\n") ; + val = req_p->box0 ; + cy_as_ll_send_data_response(dev_p, CY_RQT_TUR_RQT_CONTEXT, + CY_RESP_INVALID_REQUEST, sizeof(val), &val) ; + break ; + } +} + +static cy_as_return_status_t +my_handle_response_no_data(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_mtp_start(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + dev_p->mtp_count++ ; + + cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_READ_ENDPOINT, + cy_true, cy_as_direction_out) ; + dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].enabled = cy_true ; + dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].dir = cy_as_usb_out ; + dev_p->usb_config[CY_AS_MTP_READ_ENDPOINT].type = cy_as_usb_bulk ; + + cy_as_dma_enable_end_point(dev_p, CY_AS_MTP_WRITE_ENDPOINT, + cy_true, cy_as_direction_in) ; + dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].enabled = cy_true ; + dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].dir = cy_as_usb_in ; + dev_p->usb_config[CY_AS_MTP_WRITE_ENDPOINT].type = cy_as_usb_bulk ; + + /* Packet size is 512 bytes */ + cy_as_dma_set_max_dma_size(dev_p, 0x02, 0x0200) ; + /* Packet size is 64 bytes until a switch to high speed happens.*/ + cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_ll_register_request_callback(dev_p, + CY_RQT_TUR_RQT_CONTEXT, 0) ; + + cy_as_device_clear_m_s_s_pending(dev_p) ; + + return ret ; +} + + +cy_as_return_status_t +cy_as_mtp_start(cy_as_device_handle handle, + cy_as_mtp_event_callback event_c_b, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (cy_as_device_is_m_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + if (dev_p->storage_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (dev_p->usb_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (dev_p->is_mtp_firmware == 0) + return CY_AS_ERROR_NOT_SUPPORTED ; + + cy_as_device_set_m_s_s_pending(dev_p) ; + + if (dev_p->mtp_count == 0) { + + dev_p->mtp_event_cb = event_c_b ; + /* + * we register here becuase the start request may cause + * events to occur before the response to the start request. + */ + cy_as_ll_register_request_callback(dev_p, + CY_RQT_TUR_RQT_CONTEXT, my_mtp_request_callback) ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_START_MTP, CY_RQT_TUR_RQT_CONTEXT, 0) ; + if (req_p == 0) { + cy_as_device_clear_m_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_device_clear_m_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_mtp_start(dev_p, req_p, + reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_START, 0, dev_p->func_cbs_mtp, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else { + dev_p->mtp_count++ ; + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_MTP_START, 0) ; + } + + cy_as_device_clear_m_s_s_pending(dev_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_mtp_stop(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* + * we sucessfully shutdown the stack, so decrement + * to make the count zero. + */ + dev_p->mtp_count-- ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_ll_register_request_callback(dev_p, + CY_RQT_TUR_RQT_CONTEXT, 0) ; + + cy_as_device_clear_m_s_s_pending(dev_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_mtp_stop(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p = 0, *reply_p = 0 ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_mtp_stop called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_mtp_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (cy_as_device_is_m_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + cy_as_device_set_m_s_s_pending(dev_p) ; + + if (dev_p->mtp_count == 1) { + /* Create the request to send to the West + * Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_MTP, + CY_RQT_TUR_RQT_CONTEXT, 0) ; + if (req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_mtp_stop(dev_p, req_p, + reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_STOP, 0, dev_p->func_cbs_mtp, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else if (dev_p->mtp_count > 1) { + + dev_p->mtp_count-- ; + + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_MTP_STOP, 0) ; + } + + cy_as_device_clear_m_s_s_pending(dev_p) ; + + return ret ; +} + +static void +mtp_write_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(resp, 0) ; + } + + if (ret != CY_AS_ERROR_SUCCESS) { + /* Firmware failed the request. Cancel the DMA transfer. */ + cy_as_dma_cancel(dev_p, 0x04, CY_AS_ERROR_CANCELED) ; + cy_as_device_clear_storage_async_pending(dev_p) ; + } + + cy_as_ll_destroy_response(dev_p, resp) ; + cy_as_ll_destroy_request(dev_p, rqt) ; +} + +static void +async_write_request_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, uint32_t size, + cy_as_return_status_t err) +{ + cy_as_device_handle h ; + cy_as_function_callback cb ; + + (void)size ; + (void)buf_p ; + (void)ep ; + + + cy_as_log_debug_message(6, "async_write_request_callback called") ; + + h = (cy_as_device_handle)dev_p ; + + cb = dev_p->mtp_cb ; + dev_p->mtp_cb = 0 ; + + cy_as_device_clear_storage_async_pending(dev_p) ; + + if (cb) + cb(h, err, dev_p->mtp_client, dev_p->mtp_op, 0) ; + +} + +static void +sync_mtp_callback(cy_as_device *dev_p, cy_as_end_point_number_t ep, + void *buf_p, uint32_t size, cy_as_return_status_t err) +{ + (void)ep ; + (void)buf_p ; + (void)size ; + + dev_p->mtp_error = err ; +} + +static cy_as_return_status_t +cy_as_mtp_operation(cy_as_device *dev_p, + cy_as_mtp_block_table *blk_table, + uint32_t num_bytes, + uint32_t transaction_id, + cy_as_function_callback cb, + uint32_t client, + uint8_t rqttype + ) +{ + cy_as_ll_request_response *req_p = 0, *reply_p = 0 ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint32_t mask = 0 ; + cy_as_funct_c_b_type mtp_cb_op = 0 ; + uint16_t size = 2 ; + + if (dev_p->mtp_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (rqttype == CY_RQT_INIT_SEND_OBJECT) { + mtp_cb_op = CY_FUNCT_CB_MTP_INIT_SEND_OBJECT ; + dev_p->mtp_turbo_active = cy_true ; + } else if (rqttype == CY_RQT_INIT_GET_OBJECT) { + mtp_cb_op = CY_FUNCT_CB_MTP_INIT_GET_OBJECT ; + dev_p->mtp_turbo_active = cy_true ; + } else + mtp_cb_op = CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE ; + + ret = is_mtp_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (CY_RQT_INIT_GET_OBJECT == rqttype) + size = 4 ; + + /* Create the request to send to the West + * Bridge device */ + req_p = cy_as_ll_create_request(dev_p, rqttype, + CY_RQT_TUR_RQT_CONTEXT, size) ; + if (req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)(num_bytes & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((num_bytes >> 16) & 0xFFFF)) ; + + /* If it is GET_OBJECT, send transaction id as well*/ + if (CY_RQT_INIT_GET_OBJECT == rqttype) { + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(transaction_id & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 3, + (uint16_t)((transaction_id >> 16) & 0xFFFF)) ; + } + + if (cb == 0) { + /* Queue the DMA request for block table write */ + ret = cy_as_dma_queue_request(dev_p, 4, blk_table, + sizeof(cy_as_mtp_block_table), cy_false, + cy_false, sync_mtp_callback) ; + + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, 4, CY_AS_ERROR_CANCELED) ; + cy_as_device_clear_storage_async_pending(dev_p) ; + + goto destroy ; + } + + ret = cy_as_dma_drain_queue(dev_p, 4, cy_true) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = dev_p->mtp_error ; + goto destroy ; + } else { +#if 0 + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_INIT_SEND_OBJECT, + 0, dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; +#endif + + /* Protection from interrupt driven code */ + /* since we are using storage EP4 check if any + * storage activity is pending */ + mask = cy_as_hal_disable_interrupts() ; + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + cy_as_device_set_storage_async_pending(dev_p) ; + cy_as_hal_enable_interrupts(mask) ; + + dev_p->mtp_cb = cb ; + dev_p->mtp_client = client ; + dev_p->mtp_op = mtp_cb_op ; + + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_false, mtp_write_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = cy_as_dma_queue_request(dev_p, 4, blk_table, + sizeof(cy_as_mtp_block_table), cy_false, cy_false, + async_write_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Kick start the queue if it is not running */ + cy_as_dma_kick_start(dev_p, 4) ; + + return CY_AS_ERROR_SUCCESS ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_mtp_init_send_object(cy_as_device_handle handle, + cy_as_mtp_block_table *blk_table, + uint32_t num_bytes, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_device *dev_p ; + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + return cy_as_mtp_operation(dev_p, blk_table, num_bytes, 0, cb, + client, CY_RQT_INIT_SEND_OBJECT) ; + +} + +cy_as_return_status_t +cy_as_mtp_init_get_object(cy_as_device_handle handle, + cy_as_mtp_block_table *blk_table, + uint32_t num_bytes, + uint32_t transaction_id, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_device *dev_p ; + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + return cy_as_mtp_operation(dev_p, blk_table, num_bytes, + transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT) ; + +} + +static cy_as_return_status_t +my_handle_response_cancel_send_object(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_mtp_cancel_send_object(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p = 0, *reply_p = 0 ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (dev_p->mtp_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_CANCEL_SEND_OBJECT, CY_RQT_TUR_RQT_CONTEXT, 0) ; + if (req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_cancel_send_object(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT, 0, + dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_cancel_get_object(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_mtp_cancel_get_object(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p = 0, *reply_p = 0 ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (dev_p->mtp_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_CANCEL_GET_OBJECT, + CY_RQT_TUR_RQT_CONTEXT, 0) ; + if (req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_cancel_get_object(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT, 0, + dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_mtp_send_block_table(cy_as_device_handle handle, + cy_as_mtp_block_table *blk_table, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p ; + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + return cy_as_mtp_operation(dev_p, blk_table, 0, 0, cb, + client, CY_RQT_SEND_BLOCK_TABLE) ; +} + +static void +cy_as_mtp_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + cy_as_func_c_b_node* node = (cy_as_func_c_b_node *) + dev_p->func_cbs_mtp->head_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code ; + cy_bool delay_callback = cy_false ; + + cy_as_hal_assert(dev_p->func_cbs_mtp->count != 0) ; + cy_as_hal_assert(dev_p->func_cbs_mtp->type == CYAS_FUNC_CB) ; + + (void)context ; + + /* The Handlers are responsible for Deleting the + * rqt and resp when they are finished + */ + code = cy_as_ll_request_response__get_code(rqt) ; + switch (code) { + case CY_RQT_START_MTP: + ret = my_handle_response_mtp_start(dev_p, rqt, + resp, stat) ; + break ; + case CY_RQT_STOP_MTP: + ret = my_handle_response_mtp_stop(dev_p, rqt, + resp, stat) ; + break ; +#if 0 + case CY_RQT_INIT_SEND_OBJECT: + ret = my_handle_response_init_send_object(dev_p, + rqt, resp, stat, cy_true) ; + delay_callback = cy_true ; + break ; +#endif + case CY_RQT_CANCEL_SEND_OBJECT: + ret = my_handle_response_cancel_send_object(dev_p, + rqt, resp, stat) ; + break ; +#if 0 + case CY_RQT_INIT_GET_OBJECT: + ret = my_handle_response_init_get_object(dev_p, + rqt, resp, stat, cy_true) ; + delay_callback = cy_true ; + break ; +#endif + case CY_RQT_CANCEL_GET_OBJECT: + ret = my_handle_response_cancel_get_object(dev_p, + rqt, resp, stat) ; + break ; +#if 0 + case CY_RQT_SEND_BLOCK_TABLE: + ret = my_handle_response_send_block_table(dev_p, rqt, + resp, stat, cy_true) ; + delay_callback = cy_true ; + break ; +#endif + case CY_RQT_ENABLE_USB_PATH: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + if (ret == CY_AS_ERROR_SUCCESS) + dev_p->is_storage_only_mode = cy_false ; + break ; + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + + /* + * if the low level layer returns a direct error, use the + * corresponding error code. if not, use the error code + * based on the response from firmware. + */ + if (stat == CY_AS_ERROR_SUCCESS) + stat = ret ; + + if (!delay_callback) { + node->cb_p((cy_as_device_handle)dev_p, stat, node->client_data, + node->data_type, node->data) ; + cy_as_remove_c_b_node(dev_p->func_cbs_mtp) ; + } +} + +cy_as_return_status_t +cy_as_mtp_storage_only_start(cy_as_device_handle handle) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->storage_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + dev_p->is_storage_only_mode = cy_true ; + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_mtp_storage_only_stop(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->storage_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (dev_p->is_storage_only_mode == cy_false) + return CY_AS_ERROR_SUCCESS ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_ENABLE_USB_PATH, CY_RQT_TUR_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = my_handle_response_no_data(dev_p, req_p, + reply_p) ; + if (ret == CY_AS_ERROR_SUCCESS) + dev_p->is_storage_only_mode = cy_false ; + return ret ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY, 0, + dev_p->func_cbs_mtp, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_mtp_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} diff --git a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c new file mode 100644 index 000000000000..c7c3cda261db --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c @@ -0,0 +1,4104 @@ +/* Cypress West Bridge API source file (cyasstorage.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* +* Storage Design +* +* The storage module is fairly straight forward once the +* DMA and LOWLEVEL modules have been designed. The +* storage module simple takes requests from the user, queues +* the associated DMA requests for action, and then sends +* the low level requests to the West Bridge firmware. +* +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasstorage.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasdevice.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyasdma.h" +#include "../../include/linux/westbridge/cyasregs.h" + +/* Map a pre-V1.2 media type to the V1.2+ bus number */ +cy_as_return_status_t +cy_an_map_bus_from_media_type(cy_as_device *dev_p, + cy_as_media_type type, cy_as_bus_number_t *bus) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code = (uint8_t)(1 << type) ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + + if (dev_p->media_supported[0] & code) { + if (dev_p->media_supported[1] & code) { + /* + * this media type could be supported on multiple + * buses. so, report an address resolution error. + */ + ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR ; + } else + *bus = 0 ; + } else { + if (dev_p->media_supported[1] & code) + *bus = 1 ; + else + ret = CY_AS_ERROR_NO_SUCH_MEDIA ; + } + + return ret ; +} + +static uint16_t +create_address(cy_as_bus_number_t bus, uint32_t device, uint8_t unit) +{ + cy_as_hal_assert(bus >= 0 && bus < CY_AS_MAX_BUSES) ; + cy_as_hal_assert(device < 16) ; + + return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit) ; +} + +cy_as_media_type +cy_as_storage_get_media_from_address(uint16_t v) +{ + cy_as_media_type media = cy_as_media_max_media_value ; + + switch (v & 0xFF) { + case 0x00: + break; + case 0x01: + media = cy_as_media_nand ; + break ; + case 0x02: + media = cy_as_media_sd_flash ; + break ; + case 0x04: + media = cy_as_media_mmc_flash ; + break ; + case 0x08: + media = cy_as_media_ce_ata ; + break ; + case 0x10: + media = cy_as_media_sdio ; + break ; + default: + cy_as_hal_assert(0) ; + break ; + } + + return media ; +} + +cy_as_bus_number_t +cy_as_storage_get_bus_from_address(uint16_t v) +{ + cy_as_bus_number_t bus = (cy_as_bus_number_t)((v >> 12) & 0x0f) ; + cy_as_hal_assert(bus >= 0 && bus < CY_AS_MAX_BUSES) ; + return bus ; +} + +uint32_t +cy_as_storage_get_device_from_address(uint16_t v) +{ + return (uint32_t)((v >> 8) & 0x0f) ; +} + +static uint8_t +get_unit_from_address(uint16_t v) +{ + return (uint8_t)(v & 0xff) ; +} + +static cy_as_return_status_t +cy_as_map_bad_addr(uint16_t val) +{ + cy_as_return_status_t ret = CY_AS_ERROR_INVALID_RESPONSE ; + + switch (val) { + case 0: + ret = CY_AS_ERROR_NO_SUCH_BUS ; + break ; + case 1: + ret = CY_AS_ERROR_NO_SUCH_DEVICE ; + break ; + case 2: + ret = CY_AS_ERROR_NO_SUCH_UNIT ; + break ; + case 3: + ret = CY_AS_ERROR_INVALID_BLOCK ; + break ; + } + + return ret ; +} + +static void +my_storage_request_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *resp_p, + cy_as_return_status_t ret) +{ + uint16_t val ; + uint16_t addr ; + cy_as_bus_number_t bus; + uint32_t device; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + cy_as_dma_end_point *ep_p = NULL ; + + (void)resp_p ; + (void)context ; + (void)ret ; + + switch (cy_as_ll_request_response__get_code(req_p)) { + case CY_RQT_MEDIA_CHANGED: + cy_as_ll_send_status_response(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + + /* Media has either been inserted or removed */ + addr = cy_as_ll_request_response__get_word(req_p, 0) ; + + bus = cy_as_storage_get_bus_from_address(addr); + device = cy_as_storage_get_device_from_address(addr); + + /* Clear the entry for this device to force re-query later */ + cy_as_hal_mem_set(&(dev_p->storage_device_info[bus][device]), 0, + sizeof(dev_p->storage_device_info[bus][device])) ; + + val = cy_as_ll_request_response__get_word(req_p, 1) ; + if (dev_p->storage_event_cb_ms) { + if (val == 1) + dev_p->storage_event_cb_ms(h, bus, + device, cy_as_storage_removed, 0) ; + else + dev_p->storage_event_cb_ms(h, bus, + device, cy_as_storage_inserted, 0) ; + } else if (dev_p->storage_event_cb) { + if (val == 1) + dev_p->storage_event_cb(h, bus, + cy_as_storage_removed, 0) ; + else + dev_p->storage_event_cb(h, bus, + cy_as_storage_inserted, 0) ; + } + + break ; + + case CY_RQT_ANTIOCH_CLAIM: + cy_as_ll_send_status_response(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + if (dev_p->storage_event_cb || dev_p->storage_event_cb_ms) { + val = cy_as_ll_request_response__get_word(req_p, 0) ; + if (dev_p->storage_event_cb_ms) { + if (val & 0x0100) + dev_p->storage_event_cb_ms(h, 0, 0, + cy_as_storage_antioch, 0) ; + if (val & 0x0200) + dev_p->storage_event_cb_ms(h, 1, 0, + cy_as_storage_antioch, 0) ; + } else { + if (val & 0x01) + dev_p->storage_event_cb(h, + cy_as_media_nand, + cy_as_storage_antioch, 0) ; + if (val & 0x02) + dev_p->storage_event_cb(h, + cy_as_media_sd_flash, + cy_as_storage_antioch, 0) ; + if (val & 0x04) + dev_p->storage_event_cb(h, + cy_as_media_mmc_flash, + cy_as_storage_antioch, 0) ; + if (val & 0x08) + dev_p->storage_event_cb(h, + cy_as_media_ce_ata, + cy_as_storage_antioch, 0) ; + } + } + break ; + + case CY_RQT_ANTIOCH_RELEASE: + cy_as_ll_send_status_response(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + val = cy_as_ll_request_response__get_word(req_p, 0) ; + if (dev_p->storage_event_cb_ms) { + if (val & 0x0100) + dev_p->storage_event_cb_ms(h, 0, 0, + cy_as_storage_processor, 0) ; + if (val & 0x0200) + dev_p->storage_event_cb_ms(h, 1, 0, + cy_as_storage_processor, 0) ; + } else if (dev_p->storage_event_cb) { + if (val & 0x01) + dev_p->storage_event_cb(h, + cy_as_media_nand, + cy_as_storage_processor, 0) ; + if (val & 0x02) + dev_p->storage_event_cb(h, + cy_as_media_sd_flash, + cy_as_storage_processor, 0) ; + if (val & 0x04) + dev_p->storage_event_cb(h, + cy_as_media_mmc_flash, + cy_as_storage_processor, 0) ; + if (val & 0x08) + dev_p->storage_event_cb(h, + cy_as_media_ce_ata, + cy_as_storage_processor, 0) ; + } + break ; + + + case CY_RQT_SDIO_INTR: + cy_as_ll_send_status_response(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + val = cy_as_ll_request_response__get_word(req_p, 0) ; + if (dev_p->storage_event_cb_ms) { + if (val & 0x0100) + dev_p->storage_event_cb_ms(h, 1, 0, + cy_as_sdio_interrupt, 0) ; + else + dev_p->storage_event_cb_ms(h, 0, 0, + cy_as_sdio_interrupt, 0) ; + + } else if (dev_p->storage_event_cb) { + dev_p->storage_event_cb(h, + cy_as_media_sdio, cy_as_sdio_interrupt, 0) ; + } + break; + + case CY_RQT_P2S_DMA_START: + /* Do the DMA setup for the waiting operation. */ + cy_as_ll_send_status_response(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + cy_as_device_set_p2s_dma_start_recvd(dev_p) ; + if (dev_p->storage_oper == cy_as_op_read) { + ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_READ_ENDPOINT) ; + cy_as_dma_end_point_set_stopped(ep_p) ; + cy_as_dma_kick_start(dev_p, CY_AS_P2S_READ_ENDPOINT) ; + } else { + ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ; + cy_as_dma_end_point_set_stopped(ep_p) ; + cy_as_dma_kick_start(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ; + } + break ; + + default: + cy_as_hal_print_message("invalid request received " + "on storage context\n") ; + val = req_p->box0 ; + cy_as_ll_send_data_response(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, + CY_RESP_INVALID_REQUEST, sizeof(val), &val) ; + break ; + } +} + +static cy_as_return_status_t +is_storage_active(cy_as_device *dev_p) +{ + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->storage_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +cy_as_storage_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) ; + +static cy_as_return_status_t +my_handle_response_no_data(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_storage_start(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (dev_p->storage_count > 0 && ret == + CY_AS_ERROR_ALREADY_RUNNING) + ret = CY_AS_ERROR_SUCCESS ; + + ret = cy_as_dma_enable_end_point(dev_p, + CY_AS_P2S_WRITE_ENDPOINT, cy_true, cy_as_direction_in) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = cy_as_dma_set_max_dma_size(dev_p, + CY_AS_P2S_WRITE_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = cy_as_dma_enable_end_point(dev_p, + CY_AS_P2S_READ_ENDPOINT, cy_true, cy_as_direction_out) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = cy_as_dma_set_max_dma_size(dev_p, + CY_AS_P2S_READ_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + cy_as_ll_register_request_callback(dev_p, + CY_RQT_STORAGE_RQT_CONTEXT, my_storage_request_callback) ; + + /* Create the request/response used for storage reads and writes. */ + dev_p->storage_rw_req_p = cy_as_ll_create_request(dev_p, + 0, CY_RQT_STORAGE_RQT_CONTEXT, 5) ; + if (dev_p->storage_rw_req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY; + goto destroy; + } + + dev_p->storage_rw_resp_p = cy_as_ll_create_response(dev_p, 5) ; + if (dev_p->storage_rw_resp_p == 0) { + cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p) ; + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + /* Increment the storage count only if + * the above functionality succeeds.*/ + if (ret == CY_AS_ERROR_SUCCESS) { + if (dev_p->storage_count == 0) { + cy_as_hal_mem_set(dev_p->storage_device_info, + 0, sizeof(dev_p->storage_device_info)) ; + dev_p->is_storage_only_mode = cy_false ; + } + + dev_p->storage_count++ ; + } + + cy_as_device_clear_s_s_s_pending(dev_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_start(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (cy_as_device_is_s_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + cy_as_device_set_s_s_s_pending(dev_p) ; + + if (dev_p->storage_count == 0) { + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_START_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) { + cy_as_device_clear_s_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Reserve space for the reply, the reply data + * will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_device_clear_s_s_s_pending(dev_p) ; + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_storage_start(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_START, 0, dev_p->func_cbs_stor, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as + * part of the FuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else { + dev_p->storage_count++ ; + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0) ; + } + + cy_as_device_clear_s_s_s_pending(dev_p) ; + + return ret ; +} + + +static cy_as_return_status_t +my_handle_response_storage_stop(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p) ; + cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p) ; + dev_p->storage_count-- ; + } + + cy_as_device_clear_s_s_s_pending(dev_p) ; + + return ret ; +} +cy_as_return_status_t +cy_as_storage_stop(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_storage_async_pending(dev_p)) + return CY_AS_ERROR_ASYNC_PENDING ; + + if (cy_as_device_is_s_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + cy_as_device_set_s_s_s_pending(dev_p) ; + + if (dev_p->storage_count == 1) { + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_STOP_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 0) ; + if (req_p == 0) { + cy_as_device_clear_s_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Reserve space for the reply, the reply data + * will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_device_clear_s_s_s_pending(dev_p) ; + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_storage_stop(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_STOP, 0, dev_p->func_cbs_stor, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else if (dev_p->storage_count > 1) { + dev_p->storage_count-- ; + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0) ; + } + + cy_as_device_clear_s_s_s_pending(dev_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_register_callback(cy_as_device_handle handle, + cy_as_storage_event_callback callback) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->storage_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + dev_p->storage_event_cb = NULL ; + dev_p->storage_event_cb_ms = callback ; + + return CY_AS_ERROR_SUCCESS ; +} + + + +static cy_as_return_status_t +my_handle_response_storage_claim(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_NO_SUCH_ADDRESS) { + ret = cy_as_map_bad_addr( + cy_as_ll_request_response__get_word(reply_p, 3)) ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_MEDIA_CLAIMED_RELEASED) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* The response must be about the address I am + * trying to claim or the firmware is broken */ + if ((cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(req_p, 0)) != + cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(reply_p, 0))) || + (cy_as_storage_get_device_from_address( + cy_as_ll_request_response__get_word(req_p, 0)) != + cy_as_storage_get_device_from_address( + cy_as_ll_request_response__get_word(reply_p, 0)))) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_word(reply_p, 1) != 1) + ret = CY_AS_ERROR_NOT_ACQUIRED ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_storage_claim(cy_as_device *dev_p, + void *data, + cy_as_bus_number_t bus, + uint32_t device, + uint16_t req_flags, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (dev_p->mtp_count > 0) + return CY_AS_ERROR_NOT_VALID_IN_MTP ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_CLAIM_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, + 0, create_address(bus, device, 0)) ; + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 4) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_storage_claim(dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_CLAIM, data, dev_p->func_cbs_stor, + req_flags, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of + * the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_claim(cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + return my_storage_claim(dev_p, NULL, bus, device, + CY_AS_REQUEST_RESPONSE_MS, cb, client) ; +} + +static cy_as_return_status_t +my_handle_response_storage_release(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_NO_SUCH_ADDRESS) { + ret = cy_as_map_bad_addr( + cy_as_ll_request_response__get_word(reply_p, 3)) ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_MEDIA_CLAIMED_RELEASED) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* The response must be about the address I am + * trying to release or the firmware is broken */ + if ((cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(req_p, 0)) != + cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(reply_p, 0))) || + (cy_as_storage_get_device_from_address( + cy_as_ll_request_response__get_word(req_p, 0)) != + cy_as_storage_get_device_from_address( + cy_as_ll_request_response__get_word(reply_p, 0)))) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + + if (cy_as_ll_request_response__get_word(reply_p, 1) != 0) + ret = CY_AS_ERROR_NOT_RELEASED ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_storage_release(cy_as_device *dev_p, + void *data, + cy_as_bus_number_t bus, + uint32_t device, + uint16_t req_flags, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (dev_p->mtp_count > 0) + return CY_AS_ERROR_NOT_VALID_IN_MTP ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_RELEASE_STORAGE, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word( + req_p, 0, create_address(bus, device, 0)) ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 4) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_storage_release( + dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_RELEASE, data, dev_p->func_cbs_stor, + req_flags, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as + * part of the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_release(cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + return my_storage_release(dev_p, NULL, bus, device, + CY_AS_REQUEST_RESPONSE_MS, cb, client) ; +} + +static cy_as_return_status_t +my_handle_response_storage_query_bus(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + uint32_t *count) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code = cy_as_ll_request_response__get_code(reply_p) ; + uint16_t v ; + + if (code == CY_RESP_NO_SUCH_ADDRESS) { + ret = CY_AS_ERROR_NO_SUCH_BUS ; + goto destroy ; + } + + if (code != CY_RESP_BUS_DESCRIPTOR) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* + * verify that the response corresponds to the bus that was queried. + */ + if (cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(req_p, 0)) != + cy_as_storage_get_bus_from_address( + cy_as_ll_request_response__get_word(reply_p, 0))) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + v = cy_as_ll_request_response__get_word(reply_p, 1) ; + if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) { + /* + * this request is only for the count of devices + * on the bus. there is no need to check the media type. + */ + if (v) + *count = 1 ; + else + *count = 0 ; + } else { + /* + * this request is for the count of devices of a + * particular type. we need to check whether the media + * type found matches the queried type. + */ + cy_as_media_type queried = (cy_as_media_type) + cy_as_ll_request_response__get_word(req_p, 1) ; + cy_as_media_type found = + cy_as_storage_get_media_from_address(v); + + if (queried == found) + *count = 1 ; + else + *count = 0 ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +my_storage_query_bus(cy_as_device *dev_p, + cy_as_bus_number_t bus, + cy_as_media_type type, + uint16_t req_flags, + uint32_t *count, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_funct_c_b_type cb_type = CY_FUNCT_CB_STOR_QUERYBUS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Create the request to send to the Antioch device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_QUERY_BUS, CY_RQT_STORAGE_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, + 0, create_address(bus, 0, 0)) ; + cy_as_ll_request_response__set_word(req_p, 1, (uint16_t)type) ; + + /* Reserve space for the reply, the reply data + * will not exceed two words. */ + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + req_p->flags |= req_flags; + return my_handle_response_storage_query_bus(dev_p, + req_p, reply_p, count) ; + } else { + if (req_flags == CY_AS_REQUEST_RESPONSE_EX) + cb_type = CY_FUNCT_CB_STOR_QUERYMEDIA ; + + ret = cy_as_misc_send_request(dev_p, cb, client, cb_type, + count, dev_p->func_cbs_stor, req_flags, + req_p, reply_p, cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of + * the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_query_bus(cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t *count, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + return my_storage_query_bus(dev_p, bus, cy_as_media_max_media_value, + CY_AS_REQUEST_RESPONSE_MS, count, cb, client) ; +} + +cy_as_return_status_t +cy_as_storage_query_media(cy_as_device_handle handle, + cy_as_media_type type, + uint32_t *count, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_bus_number_t bus ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + ret = cy_an_map_bus_from_media_type(dev_p, type, &bus) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + return my_storage_query_bus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX, + count, cb, client) ; +} + +static cy_as_return_status_t +my_handle_response_storage_query_device(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + void *data_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t v ; + cy_as_bus_number_t bus ; + cy_as_media_type type ; + uint32_t device ; + cy_bool removable ; + cy_bool writeable ; + cy_bool locked ; + uint16_t block_size ; + uint32_t number_units ; + uint32_t number_eus ; + + if (cy_as_ll_request_response__get_code(reply_p) + == CY_RESP_NO_SUCH_ADDRESS) { + ret = cy_as_map_bad_addr( + cy_as_ll_request_response__get_word(reply_p, 3)) ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_DEVICE_DESCRIPTOR) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* Unpack the response */ + v = cy_as_ll_request_response__get_word(reply_p, 0) ; + type = cy_as_storage_get_media_from_address(v) ; + bus = cy_as_storage_get_bus_from_address(v) ; + device = cy_as_storage_get_device_from_address(v) ; + + block_size = cy_as_ll_request_response__get_word(reply_p, 1) ; + + v = cy_as_ll_request_response__get_word(reply_p, 2) ; + removable = (v & 0x8000) ? cy_true : cy_false ; + writeable = (v & 0x0100) ? cy_true : cy_false ; + locked = (v & 0x0200) ? cy_true : cy_false ; + number_units = (v & 0xff) ; + + number_eus = (cy_as_ll_request_response__get_word(reply_p, 3) << 16) + | cy_as_ll_request_response__get_word(reply_p, 4) ; + + /* Store the results based on the version of originating function */ + if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) { + cy_as_storage_query_device_data *store_p = + (cy_as_storage_query_device_data *)data_p ; + + /* Make sure the response is about the address we asked + * about - if not, firmware error */ + if ((bus != store_p->bus) || (device != store_p->device)) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + store_p->desc_p.type = type ; + store_p->desc_p.removable = removable ; + store_p->desc_p.writeable = writeable ; + store_p->desc_p.block_size = block_size ; + store_p->desc_p.number_units = number_units ; + store_p->desc_p.locked = locked ; + store_p->desc_p.erase_unit_size = number_eus ; + dev_p->storage_device_info[bus][device] = store_p->desc_p ; + } else { + cy_as_storage_query_device_data_dep *store_p = + (cy_as_storage_query_device_data_dep *)data_p ; + + /* Make sure the response is about the address we asked + * about - if not, firmware error */ + if ((type != store_p->type) || (device != store_p->device)) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + store_p->desc_p.type = type ; + store_p->desc_p.removable = removable ; + store_p->desc_p.writeable = writeable ; + store_p->desc_p.block_size = block_size ; + store_p->desc_p.number_units = number_units ; + store_p->desc_p.locked = locked ; + store_p->desc_p.erase_unit_size = number_eus ; + dev_p->storage_device_info[bus][device] = store_p->desc_p ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_storage_query_device(cy_as_device *dev_p, + void *data_p, + uint16_t req_flags, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Create the request to send to the Antioch device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, device, 0)) ; + + /* Reserve space for the reply, the reply data + * will not exceed five words. */ + reply_p = cy_as_ll_create_response(dev_p, 5) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + req_p->flags |= req_flags; + return my_handle_response_storage_query_device(dev_p, + req_p, reply_p, data_p) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_QUERYDEVICE, data_p, + dev_p->func_cbs_stor, req_flags, req_p, + reply_p, cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_query_device(cy_as_device_handle handle, + cy_as_storage_query_device_data *data_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + return my_storage_query_device(dev_p, data_p, + CY_AS_REQUEST_RESPONSE_MS, data_p->bus, + data_p->device, cb, client) ; +} + +static cy_as_return_status_t +my_handle_response_storage_query_unit(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + void *data_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_bus_number_t bus ; + uint32_t device ; + uint32_t unit ; + cy_as_media_type type ; + uint16_t block_size ; + uint32_t start_block ; + uint32_t unit_size ; + uint16_t v ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_NO_SUCH_ADDRESS) { + ret = cy_as_map_bad_addr( + cy_as_ll_request_response__get_word(reply_p, 3)) ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_UNIT_DESCRIPTOR) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* Unpack the response */ + v = cy_as_ll_request_response__get_word(reply_p, 0) ; + bus = cy_as_storage_get_bus_from_address(v) ; + device = cy_as_storage_get_device_from_address(v) ; + unit = get_unit_from_address(v) ; + + type = cy_as_storage_get_media_from_address( + cy_as_ll_request_response__get_word(reply_p, 1)); + + block_size = cy_as_ll_request_response__get_word(reply_p, 2) ; + start_block = cy_as_ll_request_response__get_word(reply_p, 3) + | (cy_as_ll_request_response__get_word(reply_p, 4) << 16) ; + unit_size = cy_as_ll_request_response__get_word(reply_p, 5) + | (cy_as_ll_request_response__get_word(reply_p, 6) << 16) ; + + /* Store the results based on the version of + * originating function */ + if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) { + cy_as_storage_query_unit_data *store_p = + (cy_as_storage_query_unit_data *)data_p ; + + /* Make sure the response is about the address we + * asked about - if not, firmware error */ + if (bus != store_p->bus || device != store_p->device || + unit != store_p->unit) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + store_p->desc_p.type = type ; + store_p->desc_p.block_size = block_size ; + store_p->desc_p.start_block = start_block ; + store_p->desc_p.unit_size = unit_size ; + } else { + cy_as_storage_query_unit_data_dep *store_p = + (cy_as_storage_query_unit_data_dep *)data_p ; + + /* Make sure the response is about the media type we asked + * about - if not, firmware error */ + if ((type != store_p->type) || (device != store_p->device) || + (unit != store_p->unit)) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + store_p->desc_p.type = type ; + store_p->desc_p.block_size = block_size ; + store_p->desc_p.start_block = start_block ; + store_p->desc_p.unit_size = unit_size ; + } + + dev_p->storage_device_info[bus][device].type = type ; + dev_p->storage_device_info[bus][device].block_size = block_size ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_storage_query_unit(cy_as_device *dev_p, + void *data_p, + uint16_t req_flags, + cy_as_bus_number_t bus, + uint32_t device, + uint32_t unit, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_QUERY_UNIT, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + if (device > 255) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (unit > 255) + return CY_AS_ERROR_NO_SUCH_UNIT ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, device, (uint8_t)unit)) ; + + /* Reserve space for the reply, the reply data + * will be of seven words. */ + reply_p = cy_as_ll_create_response(dev_p, 7) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + req_p->flags |= req_flags ; + return my_handle_response_storage_query_unit(dev_p, + req_p, reply_p, data_p) ; + } else { + + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_QUERYUNIT, data_p, + dev_p->func_cbs_stor, req_flags, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_query_unit(cy_as_device_handle handle, + cy_as_storage_query_unit_data *data_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + return my_storage_query_unit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS, + data_p->bus, data_p->device, data_p->unit, cb, client) ; +} + + +static cy_as_return_status_t +cy_as_get_block_size(cy_as_device *dev_p, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_function_callback cb) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_QUERY_DEVICE, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, device, 0)) ; + + reply_p = cy_as_ll_create_response(dev_p, 4) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) + == CY_RESP_NO_SUCH_ADDRESS) { + ret = CY_AS_ERROR_NO_SUCH_BUS ; + goto destroy ; + } + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_DEVICE_DESCRIPTOR) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* Make sure the response is about the media type we asked + * about - if not, firmware error */ + if ((cy_as_storage_get_bus_from_address + (cy_as_ll_request_response__get_word(reply_p, 0)) + != bus) || (cy_as_storage_get_device_from_address + (cy_as_ll_request_response__get_word(reply_p, 0)) + != device)) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + + dev_p->storage_device_info[bus][device].block_size = + cy_as_ll_request_response__get_word(reply_p, 1) ; + } else + ret = CY_AS_ERROR_INVALID_REQUEST ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +my_storage_device_control( + cy_as_device *dev_p, + cy_as_bus_number_t bus, + uint32_t device, + cy_bool card_detect_en, + cy_bool write_prot_en, + cy_as_storage_card_detect config_detect, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret ; + cy_bool use_gpio = cy_false ; + + (void)device ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + /* If SD is not supported on the specified bus, + * then return ERROR */ + if ((dev_p->media_supported[bus] == 0) || + (dev_p->media_supported[bus] & (1<func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_device_control(cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_bool card_detect_en, + cy_bool write_prot_en, + cy_as_storage_card_detect config_detect, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + return my_storage_device_control(dev_p, bus, device, card_detect_en, + write_prot_en, config_detect, cb, client); +} + +static void +cy_as_async_storage_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, uint32_t size, + cy_as_return_status_t ret) +{ + cy_as_storage_callback_dep cb ; + cy_as_storage_callback cb_ms ; + + (void)size ; + (void)buf_p ; + (void)ep ; + + cy_as_device_clear_storage_async_pending(dev_p) ; + + /* + * if the LL request callback has already been called, + * the user callback has to be called from here. + */ + if (!dev_p->storage_wait) { + cy_as_hal_assert(dev_p->storage_cb != NULL || + dev_p->storage_cb_ms != NULL) ; + cb = dev_p->storage_cb ; + cb_ms = dev_p->storage_cb_ms ; + + dev_p->storage_cb = 0 ; + dev_p->storage_cb_ms = 0 ; + + if (ret == CY_AS_ERROR_SUCCESS) + ret = dev_p->storage_error ; + + if (cb_ms) { + cb_ms((cy_as_device_handle)dev_p, + dev_p->storage_bus_index, + dev_p->storage_device_index, + dev_p->storage_unit, + dev_p->storage_block_addr, + dev_p->storage_oper, ret) ; + } else { + cb((cy_as_device_handle)dev_p, + dev_p->storage_device_info + [dev_p->storage_bus_index] + [dev_p->storage_device_index].type, + dev_p->storage_device_index, + dev_p->storage_unit, + dev_p->storage_block_addr, + dev_p->storage_oper, ret) ; + } + } else + dev_p->storage_error = ret ; +} + +static void +cy_as_async_storage_reply_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + cy_as_storage_callback_dep cb ; + cy_as_storage_callback cb_ms ; + uint8_t reqtype ; + (void)rqt ; + (void)context ; + + reqtype = cy_as_ll_request_response__get_code(rqt) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp) == + CY_RESP_ANTIOCH_DEFERRED_ERROR) { + ret = cy_as_ll_request_response__get_word + (resp, 0) & 0x00FF ; + } else if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + } + + if (ret != CY_AS_ERROR_SUCCESS) { + if (reqtype == CY_RQT_READ_BLOCK) + cy_as_dma_cancel(dev_p, + dev_p->storage_read_endpoint, ret) ; + else + cy_as_dma_cancel(dev_p, + dev_p->storage_write_endpoint, ret) ; + } + + dev_p->storage_wait = cy_false ; + + /* + * if the DMA callback has already been called, the + * user callback has to be called from here. + */ + if (!cy_as_device_is_storage_async_pending(dev_p)) { + cy_as_hal_assert(dev_p->storage_cb != NULL || + dev_p->storage_cb_ms != NULL) ; + cb = dev_p->storage_cb ; + cb_ms = dev_p->storage_cb_ms ; + + dev_p->storage_cb = 0 ; + dev_p->storage_cb_ms = 0 ; + + if (ret == CY_AS_ERROR_SUCCESS) + ret = dev_p->storage_error ; + + if (cb_ms) { + cb_ms((cy_as_device_handle)dev_p, + dev_p->storage_bus_index, + dev_p->storage_device_index, + dev_p->storage_unit, + dev_p->storage_block_addr, + dev_p->storage_oper, ret) ; + } else { + cb((cy_as_device_handle)dev_p, + dev_p->storage_device_info + [dev_p->storage_bus_index] + [dev_p->storage_device_index].type, + dev_p->storage_device_index, + dev_p->storage_unit, + dev_p->storage_block_addr, + dev_p->storage_oper, ret) ; + } + } else + dev_p->storage_error = ret ; +} + +static cy_as_return_status_t +cy_as_storage_async_oper(cy_as_device *dev_p, cy_as_end_point_number_t ep, + uint8_t reqtype, uint16_t req_flags, cy_as_bus_number_t bus, + uint32_t device, uint32_t unit, uint32_t block, void *data_p, + uint16_t num_blocks, cy_as_storage_callback_dep callback, + cy_as_storage_callback callback_ms) +{ + uint32_t mask ; + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (unit > 255) + return CY_AS_ERROR_NO_SUCH_UNIT ; + + /* We are supposed to return sucess if the number of + * blocks is zero + */ + if (num_blocks == 0) { + if (callback_ms) + callback_ms((cy_as_device_handle)dev_p, + bus, device, unit, block, + ((reqtype == CY_RQT_WRITE_BLOCK) + ? cy_as_op_write : cy_as_op_read), + CY_AS_ERROR_SUCCESS) ; + else + callback((cy_as_device_handle)dev_p, + dev_p->storage_device_info[bus][device].type, + device, unit, block, + ((reqtype == CY_RQT_WRITE_BLOCK) ? + cy_as_op_write : cy_as_op_read), + CY_AS_ERROR_SUCCESS) ; + + return CY_AS_ERROR_SUCCESS ; + } + + if (dev_p->storage_device_info[bus][device].block_size == 0) + return CY_AS_ERROR_QUERY_DEVICE_NEEDED ; + + /* + * since async operations can be triggered by interrupt + * code, we must insure that we do not get multiple + * async operations going at one time and protect this + * test and set operation from interrupts. also need to + * check for pending async MTP writes + */ + mask = cy_as_hal_disable_interrupts() ; + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait) || + (cy_as_device_is_usb_async_pending(dev_p, 6))) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + + cy_as_device_set_storage_async_pending(dev_p) ; + cy_as_device_clear_p2s_dma_start_recvd(dev_p) ; + cy_as_hal_enable_interrupts(mask) ; + + /* + * storage information about the currently outstanding request + */ + dev_p->storage_cb = callback ; + dev_p->storage_cb_ms = callback_ms ; + dev_p->storage_bus_index = bus ; + dev_p->storage_device_index = device ; + dev_p->storage_unit = unit ; + dev_p->storage_block_addr = block ; + + /* Initialise the request to send to the West Bridge. */ + req_p = dev_p->storage_rw_req_p ; + cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5) ; + + /* Initialise the space for reply from the West Bridge. */ + reply_p = dev_p->storage_rw_resp_p ; + cy_as_ll_init_response(reply_p, 5) ; + + /* Remember which version of the API originated the request */ + req_p->flags |= req_flags ; + + /* Setup the DMA request and adjust the storage + * operation if we are reading */ + if (reqtype == CY_RQT_READ_BLOCK) { + ret = cy_as_dma_queue_request(dev_p, ep, data_p, + dev_p->storage_device_info[bus][device].block_size + * num_blocks, cy_false, cy_true, + cy_as_async_storage_callback) ; + dev_p->storage_oper = cy_as_op_read ; + } else if (reqtype == CY_RQT_WRITE_BLOCK) { + ret = cy_as_dma_queue_request(dev_p, ep, data_p, + dev_p->storage_device_info[bus][device].block_size * + num_blocks, cy_false, cy_false, + cy_as_async_storage_callback) ; + dev_p->storage_oper = cy_as_op_write ; + } + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_device_clear_storage_async_pending(dev_p) ; + return ret ; + } + + cy_as_ll_request_response__set_word(req_p, + 0, create_address(bus, (uint8_t)device, (uint8_t)unit)) ; + cy_as_ll_request_response__set_word(req_p, + 1, (uint16_t)((block >> 16) & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, + 2, (uint16_t)(block & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, + 3, (uint16_t)((num_blocks >> 8) & 0x00ff)) ; + cy_as_ll_request_response__set_word(req_p, + 4, (uint16_t)((num_blocks << 8) & 0xff00)) ; + + /* Set the burst mode flag. */ + if (dev_p->is_storage_only_mode) + req_p->data[4] |= 0x0001; + + /* Send the request and wait for completion + * of storage request */ + dev_p->storage_wait = cy_true ; + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_true, cy_as_async_storage_reply_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + cy_as_device_clear_storage_async_pending(dev_p) ; + } + + return ret ; +} + +static void +cy_as_sync_storage_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, + uint32_t size, cy_as_return_status_t err) +{ + (void)ep ; + (void)buf_p ; + (void)size ; + + dev_p->storage_error = err ; +} + +static void +cy_as_sync_storage_reply_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + uint8_t reqtype ; + (void)rqt ; + + reqtype = cy_as_ll_request_response__get_code(rqt) ; + + if (cy_as_ll_request_response__get_code(resp) == + CY_RESP_ANTIOCH_DEFERRED_ERROR) { + ret = cy_as_ll_request_response__get_word(resp, 0) & 0x00FF ; + + if (ret != CY_AS_ERROR_SUCCESS) { + if (reqtype == CY_RQT_READ_BLOCK) + cy_as_dma_cancel(dev_p, + dev_p->storage_read_endpoint, ret) ; + else + cy_as_dma_cancel(dev_p, + dev_p->storage_write_endpoint, ret) ; + } + } else if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + + dev_p->storage_wait = cy_false ; + dev_p->storage_error = ret ; + + /* Wake any threads/processes that are waiting on + * the read/write completion. */ + cy_as_hal_wake(&dev_p->context[context]->channel) ; +} + +static cy_as_return_status_t +cy_as_storage_sync_oper(cy_as_device *dev_p, + cy_as_end_point_number_t ep, uint8_t reqtype, + cy_as_bus_number_t bus, uint32_t device, + uint32_t unit, uint32_t block, void *data_p, + uint16_t num_blocks) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_context *ctxt_p ; + uint32_t loopcount = 200 ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (unit > 255) + return CY_AS_ERROR_NO_SUCH_UNIT ; + + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) + return CY_AS_ERROR_ASYNC_PENDING ; + + /* Also need to check for pending Async MTP writes */ + if (cy_as_device_is_usb_async_pending(dev_p, 6)) + return CY_AS_ERROR_ASYNC_PENDING ; + + /* We are supposed to return sucess if the number of + * blocks is zero + */ + if (num_blocks == 0) + return CY_AS_ERROR_SUCCESS ; + + if (dev_p->storage_device_info[bus][device].block_size == 0) { + /* + * normally, a given device has been queried via + * the query device call before a read request is issued. + * therefore, this normally will not be run. + */ + ret = cy_as_get_block_size(dev_p, bus, device, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + /* Initialise the request to send to the West Bridge. */ + req_p = dev_p->storage_rw_req_p ; + cy_as_ll_init_request(req_p, reqtype, + CY_RQT_STORAGE_RQT_CONTEXT, 5) ; + + /* Initialise the space for reply from + * the West Bridge. */ + reply_p = dev_p->storage_rw_resp_p ; + cy_as_ll_init_response(reply_p, 5) ; + cy_as_device_clear_p2s_dma_start_recvd(dev_p) ; + + /* Setup the DMA request */ + if (reqtype == CY_RQT_READ_BLOCK) { + ret = cy_as_dma_queue_request(dev_p, ep, data_p, + dev_p->storage_device_info[bus][device].block_size * + num_blocks, cy_false, + cy_true, cy_as_sync_storage_callback) ; + dev_p->storage_oper = cy_as_op_read ; + } else if (reqtype == CY_RQT_WRITE_BLOCK) { + ret = cy_as_dma_queue_request(dev_p, ep, data_p, + dev_p->storage_device_info[bus][device].block_size * + num_blocks, cy_false, cy_false, + cy_as_sync_storage_callback) ; + dev_p->storage_oper = cy_as_op_write ; + } + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, (uint8_t)unit)) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((block >> 16) & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(block & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, 3, + (uint16_t)((num_blocks >> 8) & 0x00ff)) ; + cy_as_ll_request_response__set_word(req_p, 4, + (uint16_t)((num_blocks << 8) & 0xff00)) ; + + /* Set the burst mode flag. */ + if (dev_p->is_storage_only_mode) + req_p->data[4] |= 0x0001; + + /* Send the request and wait for + * completion of storage request */ + dev_p->storage_wait = cy_true ; + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true, + cy_as_sync_storage_reply_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + } else { + /* Setup the DMA request */ + ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ; + ret = cy_as_dma_drain_queue(dev_p, ep, cy_false) ; + + while (loopcount-- > 0) { + if (dev_p->storage_wait == cy_false) + break ; + cy_as_hal_sleep_on(&ctxt_p->channel, 10) ; + } + + if (dev_p->storage_wait == cy_true) { + dev_p->storage_wait = cy_false ; + cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true) ; + ret = CY_AS_ERROR_TIMEOUT ; + } + + if (ret == CY_AS_ERROR_SUCCESS) + ret = dev_p->storage_error ; + } + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_read(cy_as_device_handle handle, + cy_as_bus_number_t bus, uint32_t device, + uint32_t unit, uint32_t block, + void *data_p, uint16_t num_blocks) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + return cy_as_storage_sync_oper(dev_p, dev_p->storage_read_endpoint, + CY_RQT_READ_BLOCK, bus, device, + unit, block, data_p, num_blocks) ; +} + +cy_as_return_status_t +cy_as_storage_write(cy_as_device_handle handle, + cy_as_bus_number_t bus, uint32_t device, + uint32_t unit, uint32_t block, void *data_p, + uint16_t num_blocks) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (dev_p->mtp_turbo_active) + return CY_AS_ERROR_NOT_VALID_DURING_MTP ; + + return cy_as_storage_sync_oper(dev_p, + dev_p->storage_write_endpoint, + CY_RQT_WRITE_BLOCK, bus, device, + unit, block, data_p, num_blocks) ; +} + + +cy_as_return_status_t +cy_as_storage_read_async(cy_as_device_handle handle, + cy_as_bus_number_t bus, uint32_t device, uint32_t unit, + uint32_t block, void *data_p, uint16_t num_blocks, + cy_as_storage_callback callback) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (callback == 0) + return CY_AS_ERROR_NULL_CALLBACK ; + + return cy_as_storage_async_oper(dev_p, + dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK, + CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, + block, data_p, num_blocks, NULL, callback); +} + +cy_as_return_status_t +cy_as_storage_write_async(cy_as_device_handle handle, + cy_as_bus_number_t bus, uint32_t device, uint32_t unit, + uint32_t block, void *data_p, uint16_t num_blocks, + cy_as_storage_callback callback) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (callback == 0) + return CY_AS_ERROR_NULL_CALLBACK ; + + if (dev_p->mtp_turbo_active) + return CY_AS_ERROR_NOT_VALID_DURING_MTP ; + + return cy_as_storage_async_oper(dev_p, + dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK, + CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block, + data_p, num_blocks, NULL, callback); +} + + +static void +my_storage_cancel_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + (void)context ; + (void)stat ; + + /* Nothing to do here, except free up the + * request and response structures. */ + cy_as_ll_destroy_response(dev_p, resp) ; + cy_as_ll_destroy_request(dev_p, rqt) ; +} + + +cy_as_return_status_t +cy_as_storage_cancel_async(cy_as_device_handle handle) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (!cy_as_device_is_storage_async_pending(dev_p)) + return CY_AS_ERROR_ASYNC_NOT_PENDING ; + + /* + * create and send a mailbox request to firmware + * asking it to abort processing of the current + * P2S operation. the rest of the cancel processing will be + * driven through the callbacks for the read/write call. + */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_ABORT_P2S_XFER, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + ret = cy_as_ll_send_request(dev_p, req_p, + reply_p, cy_false, my_storage_cancel_callback) ; + if (ret) { + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } + + return CY_AS_ERROR_SUCCESS ; +} + +/* + * This function does all the API side clean-up associated with + * CyAsStorageStop, without any communication with the firmware. + */ +void cy_as_storage_cleanup(cy_as_device *dev_p) +{ + if (dev_p->storage_count) { + cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p) ; + cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p) ; + dev_p->storage_count = 0 ; + cy_as_device_clear_scsi_messages(dev_p) ; + cy_as_hal_mem_set(dev_p->storage_device_info, + 0, sizeof(dev_p->storage_device_info)) ; + + cy_as_device_clear_storage_async_pending(dev_p) ; + dev_p->storage_cb = 0 ; + dev_p->storage_cb_ms = 0 ; + dev_p->storage_wait = cy_false ; + } +} + +static cy_as_return_status_t +my_handle_response_sd_reg_read( + cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_storage_sd_reg_read_data *info) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t resp_type, i ; + uint16_t resp_len ; + uint8_t length = info->length ; + uint8_t *data_p = info->buf_p ; + + resp_type = cy_as_ll_request_response__get_code(reply_p) ; + if (resp_type == CY_RESP_SD_REGISTER_DATA) { + uint16_t *resp_p = reply_p->data + 1 ; + uint16_t temp ; + + resp_len = cy_as_ll_request_response__get_word(reply_p, 0) ; + cy_as_hal_assert(resp_len >= length) ; + + /* + * copy the values into the output buffer after doing the + * necessary bit shifting. the bit shifting is required because + * the data comes out of the west bridge with a 6 bit offset. + */ + i = 0 ; + while (length) { + temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10)) ; + i++ ; + + *data_p++ = (uint8_t)(temp >> 8) ; + length-- ; + + if (length) { + *data_p++ = (uint8_t)(temp & 0xFF) ; + length-- ; + } + } + } else { + if (resp_type == CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + + cy_as_ll_destroy_response(dev_p, reply_p) ; + cy_as_ll_destroy_request(dev_p, req_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_sd_register_read( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint8_t device, + cy_as_sd_card_reg_type reg_type, + cy_as_storage_sd_reg_read_data *data_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t length ; + + /* + * sanity checks required before sending the request to the + * firmware. + */ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (reg_type > cy_as_sd_reg_CSD) + return CY_AS_ERROR_INVALID_PARAMETER ; + + /* If SD/MMC media is not supported on the + * addressed bus, return error. */ + if ((dev_p->media_supported[bus] & (1 << cy_as_media_sd_flash)) == 0) + return CY_AS_ERROR_INVALID_PARAMETER ; + + /* + * find the amount of data to be returned. this will be the minimum of + * the actual data length, and the length requested. + */ + switch (reg_type) { + case cy_as_sd_reg_OCR: + length = CY_AS_SD_REG_OCR_LENGTH ; + break ; + case cy_as_sd_reg_CID: + length = CY_AS_SD_REG_CID_LENGTH ; + break ; + case cy_as_sd_reg_CSD: + length = CY_AS_SD_REG_CSD_LENGTH ; + break ; + + default: + length = 0 ; + cy_as_hal_assert(0) ; + } + + if (length < data_p->length) + data_p->length = length ; + length = data_p->length ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SD_REGISTER_READ, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (create_address(bus, device, 0) | (uint16_t)reg_type)) ; + + reply_p = cy_as_ll_create_response(dev_p, + CY_AS_SD_REG_MAX_RESP_LENGTH) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_sd_reg_read(dev_p, + req_p, reply_p, data_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_SDREGISTERREAD, data_p, + dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * MiscFuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_create_p_partition( + /* Handle to the device of interest */ + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + /* of P-port only partition in blocks */ + uint32_t size, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Partitions cannot be created or deleted while + * the USB stack is active. */ + if (dev_p->usb_count) + return CY_AS_ERROR_USB_RUNNING ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_STORAGE, + CY_RQT_STORAGE_RQT_CONTEXT, 3) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, 0x00)); + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((size >> 16) & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(size & 0xffff)) ; + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_no_data(dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_PARTITION, 0, dev_p->func_cbs_stor, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * FuncCallback */ + return ret ; + + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_remove_p_partition( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Partitions cannot be created or deleted while + * the USB stack is active. */ + if (dev_p->usb_count) + return CY_AS_ERROR_USB_RUNNING ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_ERASE, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_request_response__set_word(req_p, + 0, create_address(bus, (uint8_t)device, 0x00)); + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_no_data(dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_stor, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the FuncCallback */ + return ret ; + + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_get_transfer_amount(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_m_s_c_progress_data *data) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code = cy_as_ll_request_response__get_code(reply_p) ; + uint16_t v1, v2 ; + + if (code != CY_RESP_TRANSFER_COUNT) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + v1 = cy_as_ll_request_response__get_word(reply_p, 0) ; + v2 = cy_as_ll_request_response__get_word(reply_p, 1) ; + data->wr_count = (uint32_t)((v1 << 16) | v2) ; + + v1 = cy_as_ll_request_response__get_word(reply_p, 2) ; + v2 = cy_as_ll_request_response__get_word(reply_p, 3) ; + data->rd_count = (uint32_t)((v1 << 16) | v2) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_storage_get_transfer_amount( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_m_s_c_progress_data *data_p, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* Check if the firmware image supports this feature. */ + if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] + == (1 << cy_as_media_nand))) + return CY_AS_ERROR_NOT_SUPPORTED ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_TRANSFER_AMOUNT, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply data + * will not exceed four words. */ + reply_p = cy_as_ll_create_response(dev_p, 4) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, 0x00)); + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_get_transfer_amount(dev_p, + req_p, reply_p, data_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT, (void *)data_p, + dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed as part of the + * FuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; + +} + +cy_as_return_status_t +cy_as_storage_erase( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint32_t erase_unit, + uint16_t num_erase_units, + cy_as_function_callback cb, + uint32_t client + ) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_storage_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (dev_p->storage_device_info[bus][device].block_size == 0) + return CY_AS_ERROR_QUERY_DEVICE_NEEDED ; + + /* If SD is not supported on the specified bus, then return ERROR */ + if (dev_p->storage_device_info[bus][device].type != + cy_as_media_sd_flash) + return CY_AS_ERROR_NOT_SUPPORTED; + + if (num_erase_units == 0) + return CY_AS_ERROR_SUCCESS ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_ERASE, + CY_RQT_STORAGE_RQT_CONTEXT, 5) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply + * data will not exceed four words. */ + reply_p = cy_as_ll_create_response(dev_p, 4) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, 0x00)); + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((erase_unit >> 16) & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(erase_unit & 0xffff)) ; + cy_as_ll_request_response__set_word(req_p, 3, + (uint16_t)((num_erase_units >> 8) & 0x00ff)) ; + cy_as_ll_request_response__set_word(req_p, 4, + (uint16_t)((num_erase_units << 8) & 0xff00)) ; + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = my_handle_response_no_data(dev_p, req_p, reply_p) ; + + /* If error = "invalid response", this (very likely) means + * that we are not using the SD-only firmware module which + * is the only one supporting storage_erase. in this case + * force a "non supported" error code */ + if (ret == CY_AS_ERROR_INVALID_RESPONSE) + ret = CY_AS_ERROR_NOT_SUPPORTED; + + return ret ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_STOR_ERASE, 0, dev_p->func_cbs_stor, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_storage_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* The request and response are freed + * as part of the FuncCallback */ + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static void +cy_as_storage_func_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + cy_as_func_c_b_node *node = (cy_as_func_c_b_node *) + dev_p->func_cbs_stor->head_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) + == CY_AS_REQUEST_RESPONSE_EX ; + cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) + == CY_AS_REQUEST_RESPONSE_MS ; + uint8_t code ; + uint8_t cntxt ; + + cy_as_hal_assert(ex_request || ms_request) ; + cy_as_hal_assert(dev_p->func_cbs_stor->count != 0) ; + cy_as_hal_assert(dev_p->func_cbs_stor->type == CYAS_FUNC_CB) ; + (void) ex_request; + (void) ms_request; + + (void)context ; + + cntxt = cy_as_ll_request_response__get_context(rqt) ; + cy_as_hal_assert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT) ; + + code = cy_as_ll_request_response__get_code(rqt) ; + switch (code) { + case CY_RQT_START_STORAGE: + ret = my_handle_response_storage_start(dev_p, rqt, resp, stat) ; + break ; + case CY_RQT_STOP_STORAGE: + ret = my_handle_response_storage_stop(dev_p, rqt, resp, stat) ; + break ; + case CY_RQT_CLAIM_STORAGE: + ret = my_handle_response_storage_claim(dev_p, rqt, resp) ; + break ; + case CY_RQT_RELEASE_STORAGE: + ret = my_handle_response_storage_release(dev_p, rqt, resp) ; + break ; + case CY_RQT_QUERY_MEDIA: + cy_as_hal_assert(cy_false) ;/* Not used any more. */ + break ; + case CY_RQT_QUERY_BUS: + cy_as_hal_assert(node->data != 0) ; + ret = my_handle_response_storage_query_bus(dev_p, + rqt, resp, (uint32_t *)node->data) ; + break ; + case CY_RQT_QUERY_DEVICE: + cy_as_hal_assert(node->data != 0) ; + ret = my_handle_response_storage_query_device(dev_p, + rqt, resp, node->data) ; + break ; + case CY_RQT_QUERY_UNIT: + cy_as_hal_assert(node->data != 0) ; + ret = my_handle_response_storage_query_unit(dev_p, + rqt, resp, node->data) ; + break ; + case CY_RQT_SD_INTERFACE_CONTROL: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_SD_REGISTER_READ: + cy_as_hal_assert(node->data != 0) ; + ret = my_handle_response_sd_reg_read(dev_p, rqt, resp, + (cy_as_storage_sd_reg_read_data *)node->data) ; + break ; + case CY_RQT_PARTITION_STORAGE: + ret = my_handle_response_no_data(dev_p, rqt, resp); + break ; + case CY_RQT_PARTITION_ERASE: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_GET_TRANSFER_AMOUNT: + cy_as_hal_assert(node->data != 0) ; + ret = my_handle_response_get_transfer_amount(dev_p, + rqt, resp, (cy_as_m_s_c_progress_data *)node->data) ; + break ; + case CY_RQT_ERASE: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + + /* If error = "invalid response", this (very likely) + * means that we are not using the SD-only firmware + * module which is the only one supporting storage_erase. + * in this case force a "non supported" error code */ + if (ret == CY_AS_ERROR_INVALID_RESPONSE) + ret = CY_AS_ERROR_NOT_SUPPORTED; + + break ; + + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + + /* + * if the low level layer returns a direct error, use the + * corresponding error code. if not, use the error code + * based on the response from firmware. + */ + if (stat == CY_AS_ERROR_SUCCESS) + stat = ret ; + + /* Call the user callback, if there is one */ + if (node->cb_p) + node->cb_p((cy_as_device_handle)dev_p, stat, + node->client_data, node->data_type, node->data) ; + cy_as_remove_c_b_node(dev_p->func_cbs_stor) ; +} + + +static void +cy_as_sdio_sync_reply_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + (void)rqt ; + + if ((cy_as_ll_request_response__get_code(resp) == + CY_RESP_SDIO_GET_TUPLE) || + (cy_as_ll_request_response__get_code(resp) == + CY_RESP_SDIO_EXT)) { + ret = cy_as_ll_request_response__get_word(resp, 0) ; + if ((ret & 0x00FF) != CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(rqt) == + CY_RQT_SDIO_READ_EXTENDED) + cy_as_dma_cancel(dev_p, + dev_p->storage_read_endpoint, ret) ; + else + cy_as_dma_cancel(dev_p, + dev_p->storage_write_endpoint, ret) ; + } + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + + dev_p->storage_rw_resp_p = resp; + dev_p->storage_wait = cy_false ; + if (((ret & 0x00FF) == CY_AS_ERROR_IO_ABORTED) || ((ret & 0x00FF) + == CY_AS_ERROR_IO_SUSPENDED)) + dev_p->storage_error = (ret & 0x00FF); + else + dev_p->storage_error = (ret & 0x00FF) ? + CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS ; + + /* Wake any threads/processes that are waiting on + * the read/write completion. */ + cy_as_hal_wake(&dev_p->context[context]->channel); +} + +cy_as_return_status_t +cy_as_sdio_device_check( + cy_as_device *dev_p, + cy_as_bus_number_t bus, + uint32_t device) +{ + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (bus < 0 || bus >= CY_AS_MAX_BUSES) + return CY_AS_ERROR_NO_SUCH_BUS ; + + if (device >= CY_AS_MAX_STORAGE_DEVICES) + return CY_AS_ERROR_NO_SUCH_DEVICE ; + + if (!cy_as_device_is_astoria_dev(dev_p)) + return CY_AS_ERROR_NOT_SUPPORTED ; + + return (is_storage_active(dev_p)) ; +} + +cy_as_return_status_t +cy_as_sdio_direct_io( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t is_write, + uint8_t *data_p) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t resp_data; + + /* + * sanity checks required before sending the request to the + * firmware. + */ + cy_as_device *dev_p = (cy_as_device *)handle ; + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + + if (!(cy_as_sdio_check_function_initialized(handle, + bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no)) + return CY_AS_ERROR_FUNCTION_SUSPENDED; + + req_p = cy_as_ll_create_request(dev_p, (is_write == cy_true) ? + CY_RQT_SDIO_WRITE_DIRECT : CY_RQT_SDIO_READ_DIRECT, + CY_RQT_STORAGE_RQT_CONTEXT, 3) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /*Setting up request*/ + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + /* D1 */ + if (is_write == cy_true) { + cy_as_ll_request_response__set_word(req_p, 1, + ((argument<<8) | 0x0080 | (n_function_no<<4) | + ((misc_buf&CY_SDIO_RAW)<<3) | + ((misc_buf&CY_SDIO_REARM_INT)>>5) | + (uint16_t)(address>>15))); + } else { + cy_as_ll_request_response__set_word(req_p, 1, + (n_function_no<<4) | ((misc_buf&CY_SDIO_REARM_INT)>>5) | + (uint16_t)(address>>15)); + } + /* D2 */ + cy_as_ll_request_response__set_word(req_p, 2, + ((uint16_t)((address&0x00007fff)<<1))) ; + + /*Create response*/ + reply_p = cy_as_ll_create_response(dev_p, 2) ; + + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /*Sending the request*/ + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /*Check reply type*/ + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SDIO_DIRECT) { + resp_data = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (resp_data >> 8) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else if (data_p != 0) + *(uint8_t *)(data_p) = (uint8_t)(resp_data&0x00ff); + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + +destroy: + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + + +cy_as_return_status_t +cy_as_sdio_direct_read( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint8_t *data_p) +{ + return cy_as_sdio_direct_io(handle, bus, device, n_function_no, + address, misc_buf, 0x00, cy_false, data_p); +} + +cy_as_return_status_t +cy_as_sdio_direct_write( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t *data_p) +{ + return cy_as_sdio_direct_io(handle, bus, device, n_function_no, + address, misc_buf, argument, cy_true, data_p); +} + +/*Cmd53 IO*/ +cy_as_return_status_t +cy_as_sdio_extended_i_o( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t is_write, + uint8_t *data_p , + uint8_t is_resume) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t resp_type; + uint8_t reqtype; + uint16_t resp_data; + cy_as_context *ctxt_p ; + uint32_t dmasize, loopcount = 200; + cy_as_end_point_number_t ep; + + cy_as_device *dev_p = (cy_as_device *)handle ; + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, + bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no)) + return CY_AS_ERROR_FUNCTION_SUSPENDED; + + + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) + return CY_AS_ERROR_ASYNC_PENDING ; + + /* Request for 0 bytes of blocks is returned as a success*/ + if (argument == 0) + return CY_AS_ERROR_SUCCESS; + + /* Initialise the request to send to the West Bridge device. */ + if (is_write == cy_true) { + reqtype = CY_RQT_SDIO_WRITE_EXTENDED; + ep = dev_p->storage_write_endpoint; + } else { + reqtype = CY_RQT_SDIO_READ_EXTENDED; + ep = dev_p->storage_read_endpoint; + } + + req_p = dev_p->storage_rw_req_p ; + cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3) ; + + /* Initialise the space for reply from the Antioch. */ + reply_p = dev_p->storage_rw_resp_p ; + cy_as_ll_init_response(reply_p, 2) ; + + /* Setup the DMA request */ + if (!(misc_buf&CY_SDIO_BLOCKMODE)) { + if (argument > + dev_p->sdiocard[bus]. + function[n_function_no-1].blocksize) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + + } else { + if (argument > 511) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + } + + if (argument == 512) + argument = 0; + + dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ? + dev_p->sdiocard[bus].function[n_function_no-1].blocksize + * argument : argument; + + ret = cy_as_dma_queue_request(dev_p, ep, (void *)(data_p), + dmasize, cy_false, (is_write & cy_true) ? cy_false : + cy_true, cy_as_sync_storage_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, + n_function_no | ((is_resume) ? 0x80 : 0x00))) ; + cy_as_ll_request_response__set_word(req_p, 1, + ((uint16_t)n_function_no)<<12| + ((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR))) + << 9 | (uint16_t)(address >> 7) | + ((is_write == cy_true) ? 0x8000 : 0x0000)) ; + cy_as_ll_request_response__set_word(req_p, 2, + ((uint16_t)(address&0x0000ffff) << 9) | argument) ; + + + /* Send the request and wait for completion of storage request */ + dev_p->storage_wait = cy_true ; + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_true, cy_as_sdio_sync_reply_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + } else { + /* Setup the DMA request */ + ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ; + ret = cy_as_dma_drain_queue(dev_p, ep, cy_true) ; + + while (loopcount-- > 0) { + if (dev_p->storage_wait == cy_false) + break; + cy_as_hal_sleep_on(&ctxt_p->channel, 10) ; + } + if (dev_p->storage_wait == cy_true) { + dev_p->storage_wait = cy_false ; + cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true) ; + dev_p->storage_error = CY_AS_ERROR_TIMEOUT ; + } + + ret = dev_p->storage_error; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + resp_type = cy_as_ll_request_response__get_code( + dev_p->storage_rw_resp_p) ; + if (resp_type == CY_RESP_SDIO_EXT) { + resp_data = cy_as_ll_request_response__get_word + (reply_p, 0)&0x00ff ; + if (resp_data) + ret = CY_AS_ERROR_INVALID_REQUEST ; + + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + } + return ret; + +} + +static void +cy_as_sdio_async_reply_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + cy_as_storage_callback cb_ms ; + uint8_t reqtype ; + uint32_t pendingblocks; + (void)rqt ; + (void)context ; + + pendingblocks = 0; + reqtype = cy_as_ll_request_response__get_code(rqt) ; + if (ret == CY_AS_ERROR_SUCCESS) { + if ((cy_as_ll_request_response__get_code(resp) == + CY_RESP_SUCCESS_FAILURE) || + (cy_as_ll_request_response__get_code(resp) == + CY_RESP_SDIO_EXT)) { + ret = cy_as_ll_request_response__get_word(resp, 0) ; + ret &= 0x00FF ; + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + } + + if (ret != CY_AS_ERROR_SUCCESS) { + if (reqtype == CY_RQT_SDIO_READ_EXTENDED) + cy_as_dma_cancel(dev_p, + dev_p->storage_read_endpoint, ret) ; + else + cy_as_dma_cancel(dev_p, + dev_p->storage_write_endpoint, ret) ; + + dev_p->storage_error = ret; + } + + dev_p->storage_wait = cy_false ; + + /* + * if the DMA callback has already been called, + * the user callback has to be called from here. + */ + if (!cy_as_device_is_storage_async_pending(dev_p)) { + cy_as_hal_assert(dev_p->storage_cb_ms != NULL) ; + cb_ms = dev_p->storage_cb_ms ; + + dev_p->storage_cb = 0 ; + dev_p->storage_cb_ms = 0 ; + + if ((ret == CY_AS_ERROR_SUCCESS) || + (ret == CY_AS_ERROR_IO_ABORTED) || + (ret == CY_AS_ERROR_IO_SUSPENDED)) { + ret = dev_p->storage_error ; + pendingblocks = ((uint32_t) + cy_as_ll_request_response__get_word + (resp, 1)) << 16; + } else + ret = CY_AS_ERROR_INVALID_RESPONSE; + + cb_ms((cy_as_device_handle)dev_p, dev_p->storage_bus_index, + dev_p->storage_device_index, + (dev_p->storage_unit | pendingblocks), + dev_p->storage_block_addr, dev_p->storage_oper, ret) ; + } else + dev_p->storage_error = ret ; +} + + +cy_as_return_status_t +cy_as_sdio_extended_i_o_async( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t is_write, + uint8_t *data_p, + cy_as_storage_callback callback) +{ + + uint32_t mask ; + uint32_t dmasize; + cy_as_ll_request_response *req_p , *reply_p ; + uint8_t reqtype; + cy_as_end_point_number_t ep; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, + bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no)) + return CY_AS_ERROR_FUNCTION_SUSPENDED; + + if (callback == 0) + return CY_AS_ERROR_NULL_CALLBACK ; + + /* We are supposed to return sucess if the number of + * blocks is zero + */ + if (((misc_buf&CY_SDIO_BLOCKMODE) != 0) && (argument == 0)) { + callback(handle, bus, device, n_function_no, address, + ((is_write) ? cy_as_op_write : cy_as_op_read), + CY_AS_ERROR_SUCCESS) ; + return CY_AS_ERROR_SUCCESS ; + } + + + /* + * since async operations can be triggered by interrupt + * code, we must insure that we do not get multiple async + * operations going at one time and protect this test and + * set operation from interrupts. + */ + mask = cy_as_hal_disable_interrupts() ; + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + cy_as_device_set_storage_async_pending(dev_p) ; + cy_as_hal_enable_interrupts(mask) ; + + + /* + * storage information about the currently + * outstanding request + */ + dev_p->storage_cb_ms = callback ; + dev_p->storage_bus_index = bus ; + dev_p->storage_device_index = device ; + dev_p->storage_unit = n_function_no ; + dev_p->storage_block_addr = address ; + + if (is_write == cy_true) { + reqtype = CY_RQT_SDIO_WRITE_EXTENDED; + ep = dev_p->storage_write_endpoint; + } else { + reqtype = CY_RQT_SDIO_READ_EXTENDED; + ep = dev_p->storage_read_endpoint; + } + + /* Initialise the request to send to the West Bridge. */ + req_p = dev_p->storage_rw_req_p ; + cy_as_ll_init_request(req_p, reqtype, + CY_RQT_STORAGE_RQT_CONTEXT, 3) ; + + /* Initialise the space for reply from the West Bridge. */ + reply_p = dev_p->storage_rw_resp_p ; + cy_as_ll_init_response(reply_p, 2) ; + + if (!(misc_buf&CY_SDIO_BLOCKMODE)) { + if (argument > + dev_p->sdiocard[bus].function[n_function_no-1].blocksize) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + + } else { + if (argument > 511) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + } + + if (argument == 512) + argument = 0; + dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ? + dev_p->sdiocard[bus].function[n_function_no-1].blocksize * + argument : argument; + + /* Setup the DMA request and adjust the storage + * operation if we are reading */ + if (reqtype == CY_RQT_SDIO_READ_EXTENDED) { + ret = cy_as_dma_queue_request(dev_p, ep, + (void *)data_p, dmasize , cy_false, cy_true, + cy_as_async_storage_callback) ; + dev_p->storage_oper = cy_as_op_read ; + } else if (reqtype == CY_RQT_SDIO_WRITE_EXTENDED) { + ret = cy_as_dma_queue_request(dev_p, ep, (void *)data_p, + dmasize, cy_false, cy_false, cy_as_async_storage_callback) ; + dev_p->storage_oper = cy_as_op_write ; + } + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_device_clear_storage_async_pending(dev_p) ; + return ret ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + cy_as_ll_request_response__set_word(req_p, 1, + ((uint16_t)n_function_no) << 12 | + ((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE | CY_SDIO_OP_INCR))) + << 9 | (uint16_t)(address>>7) | + ((is_write == cy_true) ? 0x8000 : 0x0000)) ; + cy_as_ll_request_response__set_word(req_p, 2, + ((uint16_t)(address&0x0000ffff) << 9) | argument) ; + + + /* Send the request and wait for completion of storage request */ + dev_p->storage_wait = cy_true ; + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true, + cy_as_sdio_async_reply_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + cy_as_device_clear_storage_async_pending(dev_p) ; + } else { + cy_as_dma_kick_start(dev_p, ep) ; + } + + return ret ; +} + +/* CMD53 Extended Read*/ +cy_as_return_status_t +cy_as_sdio_extended_read( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t *data_p, + cy_as_sdio_callback callback) +{ + if (callback == 0) + return cy_as_sdio_extended_i_o(handle, bus, device, + n_function_no, address, misc_buf, argument, + cy_false, data_p, 0); + + return cy_as_sdio_extended_i_o_async(handle, bus, device, + n_function_no, address, misc_buf, argument, cy_false, + data_p, callback); +} + +/* CMD53 Extended Write*/ +cy_as_return_status_t +cy_as_sdio_extended_write( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint32_t address, + uint8_t misc_buf, + uint16_t argument, + uint8_t *data_p, + cy_as_sdio_callback callback) +{ + if (callback == 0) + return cy_as_sdio_extended_i_o(handle, bus, device, + n_function_no, address, misc_buf, argument, cy_true, + data_p, 0); + + return cy_as_sdio_extended_i_o_async(handle, bus, device, + n_function_no, address, misc_buf, argument, cy_true, + data_p, callback); +} + + +/* Read the CIS info tuples for the given function and Tuple ID*/ +cy_as_return_status_t +cy_as_sdio_get_c_i_s_info( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint16_t tuple_id, + uint8_t *data_p) +{ + + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t resp_data; + cy_as_context *ctxt_p ; + uint32_t loopcount = 200; + + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, bus, 0))) + return CY_AS_ERROR_INVALID_FUNCTION; + + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) + return CY_AS_ERROR_ASYNC_PENDING ; + + + /* Initialise the request to send to the Antioch. */ + req_p = dev_p->storage_rw_req_p ; + cy_as_ll_init_request(req_p, CY_RQT_SDIO_GET_TUPLE, + CY_RQT_STORAGE_RQT_CONTEXT, 2) ; + + /* Initialise the space for reply from the Antioch. */ + reply_p = dev_p->storage_rw_resp_p ; + cy_as_ll_init_response(reply_p, 3) ; + + /* Setup the DMA request */ + ret = cy_as_dma_queue_request(dev_p, dev_p->storage_read_endpoint, + data_p+1, 255, cy_false, cy_true, cy_as_sync_storage_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + + /* Set tuple id to fetch. */ + cy_as_ll_request_response__set_word(req_p, 1, tuple_id<<8) ; + + /* Send the request and wait for completion of storage request */ + dev_p->storage_wait = cy_true ; + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true, + cy_as_sdio_sync_reply_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, + dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED) ; + } else { + /* Setup the DMA request */ + ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ; + ret = cy_as_dma_drain_queue(dev_p, + dev_p->storage_read_endpoint, cy_true) ; + + while (loopcount-- > 0) { + if (dev_p->storage_wait == cy_false) + break; + cy_as_hal_sleep_on(&ctxt_p->channel, 10) ; + } + + if (dev_p->storage_wait == cy_true) { + dev_p->storage_wait = cy_false ; + cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true) ; + return CY_AS_ERROR_TIMEOUT ; + } + ret = dev_p->storage_error ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_ll_request_response__get_code + (dev_p->storage_rw_resp_p) == CY_RESP_SDIO_GET_TUPLE) { + resp_data = cy_as_ll_request_response__get_word + (reply_p, 0) ; + if (resp_data) { + ret = CY_AS_ERROR_INVALID_REQUEST ; + } else if (data_p != 0) + *(uint8_t *)data_p = (uint8_t) + (cy_as_ll_request_response__get_word + (reply_p, 0)&0x00ff); + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + } + return ret; +} + +/*Query Device*/ +cy_as_return_status_t +cy_as_sdio_query_card( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_sdio_card *data_p) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + uint8_t resp_type; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + /* Allocating memory to the SDIO device structure in dev_p */ + + cy_as_hal_mem_set(&dev_p->sdiocard[bus], 0, sizeof(cy_as_sdio_device)); + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_QUERY_CARD, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, 0)) ; + + reply_p = cy_as_ll_create_response(dev_p, 5) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + resp_type = cy_as_ll_request_response__get_code(reply_p); + if (resp_type == CY_RESP_SDIO_QUERY_CARD) { + dev_p->sdiocard[bus].card.num_functions = + (uint8_t)((reply_p->data[0]&0xff00)>>8); + dev_p->sdiocard[bus].card.memory_present = + (uint8_t)reply_p->data[0]&0x0001; + dev_p->sdiocard[bus].card.manufacturer__id = + reply_p->data[1]; + dev_p->sdiocard[bus].card.manufacturer_info = + reply_p->data[2]; + dev_p->sdiocard[bus].card.blocksize = + reply_p->data[3]; + dev_p->sdiocard[bus].card.maxblocksize = + reply_p->data[3]; + dev_p->sdiocard[bus].card.card_capability = + (uint8_t)((reply_p->data[4]&0xff00)>>8); + dev_p->sdiocard[bus].card.sdio_version = + (uint8_t)(reply_p->data[4]&0x00ff); + dev_p->sdiocard[bus].function_init_map = 0x01; + data_p->num_functions = + dev_p->sdiocard[bus].card.num_functions; + data_p->memory_present = + dev_p->sdiocard[bus].card.memory_present; + data_p->manufacturer__id = + dev_p->sdiocard[bus].card.manufacturer__id; + data_p->manufacturer_info = + dev_p->sdiocard[bus].card.manufacturer_info; + data_p->blocksize = dev_p->sdiocard[bus].card.blocksize; + data_p->maxblocksize = + dev_p->sdiocard[bus].card.maxblocksize; + data_p->card_capability = + dev_p->sdiocard[bus].card.card_capability; + data_p->sdio_version = + dev_p->sdiocard[bus].card.sdio_version; + } else { + if (resp_type == CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } +destroy: + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + +/*Reset SDIO card. */ +cy_as_return_status_t +cy_as_sdio_reset_card( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device) +{ + + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t resp_type; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (dev_p->sdiocard != 0) { + dev_p->sdiocard[bus].function_init_map = 0; + dev_p->sdiocard[bus].function_suspended_map = 0; + } + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_RESET_DEV, + CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /*Setup mailbox */ + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, 0)) ; + + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + resp_type = cy_as_ll_request_response__get_code(reply_p) ; + + if (resp_type == CY_RESP_SUCCESS_FAILURE) { + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret == CY_AS_ERROR_SUCCESS) + ret = cy_as_sdio_query_card(handle, bus, device, 0); + } else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + +destroy: + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + +/* Initialise an IO function*/ +cy_as_return_status_t +cy_as_sdio_init_function( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint8_t misc_buf) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t resp_type; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized + (handle, bus, 0))) + return CY_AS_ERROR_NOT_RUNNING; + + if ((cy_as_sdio_check_function_initialized + (handle, bus, n_function_no))) { + if (misc_buf&CY_SDIO_FORCE_INIT) + dev_p->sdiocard[bus].function_init_map &= + (~(1 << n_function_no)); + else + return CY_AS_ERROR_ALREADY_RUNNING; + } + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + + reply_p = cy_as_ll_create_response(dev_p, 5) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + resp_type = cy_as_ll_request_response__get_code(reply_p) ; + + if (resp_type == CY_RESP_SDIO_INIT_FUNCTION) { + dev_p->sdiocard[bus].function[n_function_no-1].function_code = + (uint8_t)((reply_p->data[0]&0xff00)>>8); + dev_p->sdiocard[bus].function[n_function_no-1]. + extended_func_code = (uint8_t)reply_p->data[0]&0x00ff; + dev_p->sdiocard[bus].function[n_function_no-1].blocksize = + reply_p->data[1]; + dev_p->sdiocard[bus].function[n_function_no-1]. + maxblocksize = reply_p->data[1]; + dev_p->sdiocard[bus].function[n_function_no-1].card_psn = + (uint32_t)(reply_p->data[2])<<16; + dev_p->sdiocard[bus].function[n_function_no-1].card_psn |= + (uint32_t)(reply_p->data[3]); + dev_p->sdiocard[bus].function[n_function_no-1].csa_bits = + (uint8_t)((reply_p->data[4]&0xff00)>>8); + dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support = + (uint8_t)(reply_p->data[4]&0x0001); + dev_p->sdiocard[bus].function_init_map |= (1 << n_function_no); + cy_as_sdio_clear_function_suspended(handle, bus, n_function_no); + + } else { + if (resp_type == CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_FUNCTION ; + } + +destroy: + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + +/*Query individual functions. */ +cy_as_return_status_t +cy_as_sdio_query_function( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + cy_as_sdio_func *data_p) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + cy_as_return_status_t ret; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, + bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + + data_p->blocksize = + dev_p->sdiocard[bus].function[n_function_no-1].blocksize; + data_p->card_psn = + dev_p->sdiocard[bus].function[n_function_no-1].card_psn; + data_p->csa_bits = + dev_p->sdiocard[bus].function[n_function_no-1].csa_bits; + data_p->extended_func_code = + dev_p->sdiocard[bus].function[n_function_no-1]. + extended_func_code; + data_p->function_code = + dev_p->sdiocard[bus].function[n_function_no-1].function_code; + data_p->maxblocksize = + dev_p->sdiocard[bus].function[n_function_no-1].maxblocksize; + data_p->wakeup_support = + dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support; + + return CY_AS_ERROR_SUCCESS; +} + +/* Abort the Current Extended IO Operation*/ +cy_as_return_status_t +cy_as_sdio_abort_function( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t resp_type; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, + bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + + if ((cy_as_device_is_storage_async_pending(dev_p)) || + (dev_p->storage_wait)) { + if (!(cy_as_sdio_get_card_capability(handle, bus) & + CY_SDIO_SDC)) + return CY_AS_ERROR_INVALID_COMMAND; + } + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_ABORT_IO, + CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /*Setup mailbox */ + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + resp_type = cy_as_ll_request_response__get_code(reply_p) ; + + if (resp_type == CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + + +destroy: + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; +} + +/* Suspend IO to current function*/ +cy_as_return_status_t +cy_as_sdio_suspend( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized(handle, bus, + n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (!(cy_as_sdio_check_support_bus_suspend(handle, bus))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (!(cy_as_sdio_get_card_capability(handle, bus) & CY_SDIO_SDC)) + return CY_AS_ERROR_INVALID_FUNCTION; + if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no)) + return CY_AS_ERROR_FUNCTION_SUSPENDED; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /*Setup mailbox */ + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + ret = cy_as_ll_request_response__get_code(reply_p) ; + cy_as_sdio_set_function_suspended(handle, bus, n_function_no); + } + + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/*Resume suspended function*/ +cy_as_return_status_t +cy_as_sdio_resume( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + cy_as_oper_type op, + uint8_t misc_buf, + uint16_t pendingblockcount, + uint8_t *data_p + ) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t resp_data, ret = CY_AS_ERROR_SUCCESS ; + cy_as_device *dev_p = (cy_as_device *)handle ; + + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized + (handle, bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + + /* If suspend resume is not supported return */ + if (!(cy_as_sdio_check_support_bus_suspend(handle, bus))) + return CY_AS_ERROR_INVALID_FUNCTION; + + /* if the function is not suspended return. */ + if (!(cy_as_sdio_check_function_suspended + (handle, bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /*Setup mailbox */ + cy_as_ll_request_response__set_word(req_p, 0, + create_address(bus, (uint8_t)device, n_function_no)) ; + + reply_p = cy_as_ll_create_response(dev_p, 2) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SDIO_RESUME) { + resp_data = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (resp_data & 0x00ff) { + /* Send extended read request to resume the read. */ + if (op == cy_as_op_read) { + ret = cy_as_sdio_extended_i_o(handle, bus, + device, n_function_no, 0, misc_buf, + pendingblockcount, cy_false, data_p, 1); + } else { + ret = cy_as_sdio_extended_i_o(handle, bus, + device, n_function_no, 0, misc_buf, + pendingblockcount, cy_true, data_p, 1); + } + } else { + ret = CY_AS_ERROR_SUCCESS; + } + } else { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } + +destroy: + cy_as_sdio_clear_function_suspended(handle, bus, n_function_no); + if (req_p != 0) + cy_as_ll_destroy_request(dev_p, req_p) ; + if (reply_p != 0) + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; + +} + +/*Set function blocksize. Size cannot exceed max + * block size for the function*/ +cy_as_return_status_t +cy_as_sdio_set_blocksize( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no, + uint16_t blocksize) +{ + cy_as_return_status_t ret; + cy_as_device *dev_p = (cy_as_device *)handle ; + ret = cy_as_sdio_device_check(dev_p, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized + (handle, bus, n_function_no))) + return CY_AS_ERROR_INVALID_FUNCTION; + if (n_function_no == 0) { + if (blocksize > cy_as_sdio_get_card_max_blocksize(handle, bus)) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + else if (blocksize == cy_as_sdio_get_card_blocksize + (handle, bus)) + return CY_AS_ERROR_SUCCESS; + } else { + if (blocksize > + cy_as_sdio_get_function_max_blocksize(handle, + bus, n_function_no)) + return CY_AS_ERROR_INVALID_BLOCKSIZE; + else if (blocksize == + cy_as_sdio_get_function_blocksize(handle, + bus, n_function_no)) + return CY_AS_ERROR_SUCCESS; + } + + ret = cy_as_sdio_direct_write(handle, bus, device, 0, + (uint16_t)(n_function_no << 8) | + 0x10, 0, blocksize & 0x00ff, 0); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + ret = cy_as_sdio_direct_write(handle, bus, device, 0, + (uint16_t)(n_function_no << 8) | + 0x11, 0, (blocksize & 0xff00) >> 8, 0); + + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (n_function_no == 0) + cy_as_sdio_set_card_block_size(handle, bus, blocksize); + else + cy_as_sdio_set_function_block_size(handle, + bus, n_function_no, blocksize); + return ret; +} + +/* Deinitialize an SDIO function*/ +cy_as_return_status_t +cy_as_sdio_de_init_function( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + uint8_t n_function_no) +{ + cy_as_return_status_t ret; + uint8_t temp; + + if (n_function_no == 0) + return CY_AS_ERROR_INVALID_FUNCTION; + + ret = cy_as_sdio_device_check((cy_as_device *)handle, bus, device); + if (ret != CY_AS_ERROR_SUCCESS) + return ret; + + if (!(cy_as_sdio_check_function_initialized + (handle, bus, n_function_no))) + return CY_AS_ERROR_SUCCESS; + + temp = (uint8_t)(((cy_as_device *)handle)->sdiocard[bus]. + function_init_map & (~(1 << n_function_no))); + + cy_as_sdio_direct_write(handle, bus, device, 0, 0x02, 0, temp, 0); + + ((cy_as_device *)handle)->sdiocard[bus].function_init_map &= + (~(1 << n_function_no)); + + return CY_AS_ERROR_SUCCESS; +} + + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/api/src/cyasusb.c b/drivers/staging/westbridge/astoria/api/src/cyasusb.c new file mode 100644 index 000000000000..d0ffc2cfe77a --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasusb.c @@ -0,0 +1,3718 @@ +/* Cypress West Bridge API source file (cyasusb.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasusb.h" +#include "../../include/linux/westbridge/cyaserr.h" +#include "../../include/linux/westbridge/cyasdma.h" +#include "../../include/linux/westbridge/cyaslowlevel.h" +#include "../../include/linux/westbridge/cyaslep2pep.h" +#include "../../include/linux/westbridge/cyasregs.h" +#include "../../include/linux/westbridge/cyasstorage.h" + +static cy_as_return_status_t +cy_as_usb_ack_setup_packet( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +static void +cy_as_usb_func_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) ; +/* +* Reset the USB EP0 state +*/ +static void +cy_as_usb_reset_e_p0_state(cy_as_device *dev_p) +{ + cy_as_log_debug_message(6, "cy_as_usb_reset_e_p0_state called") ; + + cy_as_device_clear_ack_delayed(dev_p) ; + cy_as_device_clear_setup_packet(dev_p) ; + if (cy_as_device_is_usb_async_pending(dev_p, 0)) + cy_as_usb_cancel_async((cy_as_device_handle)dev_p, 0) ; + + dev_p->usb_pending_buffer = 0 ; +} + +/* +* External function to map logical endpoints to physical endpoints +*/ +static cy_as_return_status_t +is_usb_active(cy_as_device *dev_p) +{ + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (dev_p->usb_count == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +usb_ack_callback(cy_as_device_handle h, + cy_as_return_status_t status, + uint32_t client, + cy_as_funct_c_b_type type, + void *data) +{ + cy_as_device *dev_p = (cy_as_device *)h ; + + (void)client ; + (void)status ; + (void)data ; + + cy_as_hal_assert(type == CY_FUNCT_CB_NODATA) ; + + if (dev_p->usb_pending_buffer) { + cy_as_usb_io_callback cb ; + + cb = dev_p->usb_cb[0] ; + dev_p->usb_cb[0] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, 0) ; + if (cb) + cb(h, 0, dev_p->usb_pending_size, + dev_p->usb_pending_buffer, dev_p->usb_error) ; + + dev_p->usb_pending_buffer = 0 ; + } + + cy_as_device_clear_setup_packet(dev_p) ; +} + +static void +my_usb_request_callback_usb_event(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + uint16_t ev ; + uint16_t val ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + + ev = cy_as_ll_request_response__get_word(req_p, 0) ; + switch (ev) { + case 0: /* Reserved */ + cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_INVALID_REQUEST, 0) ; + break ; + + case 1: /* Reserved */ + cy_as_ll_send_status_response(dev_p, CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_INVALID_REQUEST, 0) ; + break ; + + case 2: /* USB Suspend */ + dev_p->usb_last_event = cy_as_event_usb_suspend ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, cy_as_event_usb_suspend, 0) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, cy_as_event_usb_suspend, 0) ; + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + break; + + case 3: /* USB Resume */ + dev_p->usb_last_event = cy_as_event_usb_resume ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, cy_as_event_usb_resume, 0) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, cy_as_event_usb_resume, 0) ; + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + break ; + + case 4: /* USB Reset */ + /* + * if we get a USB reset, the USB host did not understand + * our response or we timed out for some reason. reset + * our internal state to be ready for another set of + * enumeration based requests. + */ + if (cy_as_device_is_ack_delayed(dev_p)) + cy_as_usb_reset_e_p0_state(dev_p) ; + + dev_p->usb_last_event = cy_as_event_usb_reset ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, cy_as_event_usb_reset, 0) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, cy_as_event_usb_reset, 0) ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + cy_as_device_clear_usb_high_speed(dev_p) ; + cy_as_usb_set_dma_sizes(dev_p) ; + dev_p->usb_max_tx_size = 0x40 ; + cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x40) ; + break ; + + case 5: /* USB Set Configuration */ + /* The configuration to set */ + val = cy_as_ll_request_response__get_word(req_p, 1) ; + dev_p->usb_last_event = cy_as_event_usb_set_config ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_set_config, &val) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, + cy_as_event_usb_set_config, &val) ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + break ; + + case 6: /* USB Speed change */ + /* Connect speed */ + val = cy_as_ll_request_response__get_word(req_p, 1) ; + dev_p->usb_last_event = cy_as_event_usb_speed_change ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_speed_change, &val) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, + cy_as_event_usb_speed_change, &val) ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + cy_as_device_set_usb_high_speed(dev_p) ; + cy_as_usb_set_dma_sizes(dev_p) ; + dev_p->usb_max_tx_size = 0x200 ; + cy_as_dma_set_max_dma_size(dev_p, 0x06, 0x200) ; + break ; + + case 7: /* USB Clear Feature */ + /* EP Number */ + val = cy_as_ll_request_response__get_word(req_p, 1) ; + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_clear_feature, &val) ; + if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, + cy_as_event_usb_clear_feature, &val) ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + break ; + + default: + cy_as_hal_print_message("invalid event type\n") ; + cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT, + CY_RESP_USB_INVALID_EVENT, sizeof(ev), &ev) ; + break ; + } +} + +static void +my_usb_request_callback_usb_data(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + cy_as_end_point_number_t ep ; + uint8_t type ; + uint16_t len ; + uint16_t val ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + + val = cy_as_ll_request_response__get_word(req_p, 0) ; + ep = (cy_as_end_point_number_t)((val >> 13) & 0x01) ; + len = (val & 0x1ff) ; + + cy_as_hal_assert(len <= 64) ; + cy_as_ll_request_response__unpack(req_p, + 1, len, dev_p->usb_ep_data) ; + + type = (uint8_t)((val >> 14) & 0x03) ; + if (type == 0) { + if (cy_as_device_is_ack_delayed(dev_p)) { + /* + * A setup packet has arrived while we are + * processing a previous setup packet. reset + * our state with respect to EP0 to be ready + * to process the new packet. + */ + cy_as_usb_reset_e_p0_state(dev_p) ; + } + + if (len != 8) + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_INVALID_REQUEST, 0) ; + else { + cy_as_device_clear_ep0_stalled(dev_p) ; + cy_as_device_set_setup_packet(dev_p) ; + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_SUCCESS, 0) ; + + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_setup_packet, + dev_p->usb_ep_data) ; + else + dev_p->usb_event_cb(h, + cy_as_event_usb_setup_packet, + dev_p->usb_ep_data) ; + + if ((!cy_as_device_is_ack_delayed(dev_p)) && + (!cy_as_device_is_ep0_stalled(dev_p))) + cy_as_usb_ack_setup_packet(h, + usb_ack_callback, 0) ; + } + } else if (type == 2) { + if (len != 0) + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_INVALID_REQUEST, 0) ; + else { + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_status_packet, 0) ; + else + dev_p->usb_event_cb(h, + cy_as_event_usb_status_packet, 0) ; + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, + CY_AS_ERROR_SUCCESS, 0) ; + } + } else if (type == 1) { + /* + * we need to hand the data associated with these + * endpoints to the DMA module. + */ + cy_as_dma_received_data(dev_p, ep, len, dev_p->usb_ep_data) ; + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; + } +} + +static void +my_usb_request_callback_inquiry(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + cy_as_usb_inquiry_data_dep cbdata ; + cy_as_usb_inquiry_data cbdata_ms ; + void *data ; + uint16_t val ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + uint8_t def_inq_data[64] ; + uint8_t evpd ; + uint8_t codepage ; + cy_bool updated ; + uint16_t length ; + + cy_as_bus_number_t bus ; + uint32_t device ; + cy_as_media_type media ; + + val = cy_as_ll_request_response__get_word(req_p, 0) ; + bus = cy_as_storage_get_bus_from_address(val) ; + device = cy_as_storage_get_device_from_address(val) ; + media = cy_as_storage_get_media_from_address(val) ; + + val = cy_as_ll_request_response__get_word(req_p, 1) ; + evpd = (uint8_t)((val >> 8) & 0x01) ; + codepage = (uint8_t)(val & 0xff) ; + + length = cy_as_ll_request_response__get_word(req_p, 2) ; + data = (void *)def_inq_data ; + + updated = cy_false ; + + if (dev_p->usb_event_cb_ms) { + cbdata_ms.bus = bus ; + cbdata_ms.device = device ; + cbdata_ms.updated = updated ; + cbdata_ms.evpd = evpd ; + cbdata_ms.codepage = codepage ; + cbdata_ms.length = length ; + cbdata_ms.data = data ; + + cy_as_hal_assert(cbdata_ms.length <= sizeof(def_inq_data)) ; + cy_as_ll_request_response__unpack(req_p, + 3, cbdata_ms.length, cbdata_ms.data) ; + + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_inquiry_before, &cbdata_ms) ; + + updated = cbdata_ms.updated; + data = cbdata_ms.data ; + length = cbdata_ms.length ; + } else if (dev_p->usb_event_cb) { + cbdata.media = media ; + cbdata.updated = updated ; + cbdata.evpd = evpd ; + cbdata.codepage = codepage ; + cbdata.length = length ; + cbdata.data = data ; + + cy_as_hal_assert(cbdata.length <= + sizeof(def_inq_data)) ; + cy_as_ll_request_response__unpack(req_p, 3, + cbdata.length, cbdata.data) ; + + dev_p->usb_event_cb(h, + cy_as_event_usb_inquiry_before, &cbdata) ; + + updated = cbdata.updated ; + data = cbdata.data ; + length = cbdata.length ; + } + + if (updated && length > 192) + cy_as_hal_print_message("an inquiry result from a " + "cy_as_event_usb_inquiry_before event " + "was greater than 192 bytes.") ; + + /* Now send the reply with the data back + * to the West Bridge device */ + if (updated && length <= 192) { + /* + * the callback function modified the inquiry + * data, ship the data back to the west bridge firmware. + */ + cy_as_ll_send_data_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, + CY_RESP_INQUIRY_DATA, length, data) ; + } else { + /* + * the callback did not modify the data, just acknowledge + * that we processed the request + */ + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1) ; + } + + if (dev_p->usb_event_cb_ms) + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_inquiry_after, &cbdata_ms) ; + else if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, + cy_as_event_usb_inquiry_after, &cbdata) ; +} + +static void +my_usb_request_callback_start_stop(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + cy_as_bus_number_t bus ; + cy_as_media_type media ; + uint32_t device ; + uint16_t val ; + + if (dev_p->usb_event_cb_ms || dev_p->usb_event_cb) { + cy_bool loej ; + cy_bool start ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + + val = cy_as_ll_request_response__get_word(req_p, 0) ; + bus = cy_as_storage_get_bus_from_address(val) ; + device = cy_as_storage_get_device_from_address(val) ; + media = cy_as_storage_get_media_from_address(val) ; + + val = cy_as_ll_request_response__get_word(req_p, 1) ; + loej = (val & 0x02) ? cy_true : cy_false ; + start = (val & 0x01) ? cy_true : cy_false ; + + if (dev_p->usb_event_cb_ms) { + cy_as_usb_start_stop_data cbdata_ms ; + + cbdata_ms.bus = bus ; + cbdata_ms.device = device ; + cbdata_ms.loej = loej ; + cbdata_ms.start = start ; + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_start_stop, &cbdata_ms) ; + + } else if (dev_p->usb_event_cb) { + cy_as_usb_start_stop_data_dep cbdata ; + + cbdata.media = media ; + cbdata.loej = loej ; + cbdata.start = start ; + dev_p->usb_event_cb(h, + cy_as_event_usb_start_stop, &cbdata) ; + } + } + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 1) ; +} + +static void +my_usb_request_callback_uknown_c_b_w(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + uint16_t val ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + uint8_t buf[16] ; + + uint8_t response[4] ; + uint16_t reqlen ; + void *request ; + uint8_t status ; + uint8_t key ; + uint8_t asc ; + uint8_t ascq ; + + val = cy_as_ll_request_response__get_word(req_p, 0) ; + /* Failed by default */ + status = 1 ; + /* Invalid command */ + key = 0x05 ; + /* Invalid command */ + asc = 0x20 ; + /* Invalid command */ + ascq = 0x00 ; + reqlen = cy_as_ll_request_response__get_word(req_p, 1) ; + request = buf ; + + cy_as_hal_assert(reqlen <= sizeof(buf)) ; + cy_as_ll_request_response__unpack(req_p, 2, reqlen, request) ; + + if (dev_p->usb_event_cb_ms) { + cy_as_usb_unknown_command_data cbdata_ms ; + cbdata_ms.bus = cy_as_storage_get_bus_from_address(val) ; + cbdata_ms.device = + cy_as_storage_get_device_from_address(val) ; + cbdata_ms.reqlen = reqlen ; + cbdata_ms.request = request ; + cbdata_ms.status = status ; + cbdata_ms.key = key ; + cbdata_ms.asc = asc ; + cbdata_ms.ascq = ascq ; + + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_unknown_storage, &cbdata_ms) ; + status = cbdata_ms.status ; + key = cbdata_ms.key ; + asc = cbdata_ms.asc ; + ascq = cbdata_ms.ascq ; + } else if (dev_p->usb_event_cb) { + cy_as_usb_unknown_command_data_dep cbdata ; + cbdata.media = + cy_as_storage_get_media_from_address(val) ; + cbdata.reqlen = reqlen ; + cbdata.request = request ; + cbdata.status = status ; + cbdata.key = key ; + cbdata.asc = asc ; + cbdata.ascq = ascq ; + + dev_p->usb_event_cb(h, + cy_as_event_usb_unknown_storage, &cbdata) ; + status = cbdata.status ; + key = cbdata.key ; + asc = cbdata.asc ; + ascq = cbdata.ascq ; + } + + response[0] = status ; + response[1] = key ; + response[2] = asc ; + response[3] = ascq ; + cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT, + CY_RESP_UNKNOWN_SCSI_COMMAND, sizeof(response), response) ; +} + +static void +my_usb_request_callback_m_s_c_progress(cy_as_device *dev_p, + cy_as_ll_request_response *req_p) +{ + uint16_t val1, val2 ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + + if ((dev_p->usb_event_cb) || (dev_p->usb_event_cb_ms)) { + cy_as_m_s_c_progress_data cbdata ; + + val1 = cy_as_ll_request_response__get_word(req_p, 0) ; + val2 = cy_as_ll_request_response__get_word(req_p, 1) ; + cbdata.wr_count = (uint32_t)((val1 << 16) | val2) ; + + val1 = cy_as_ll_request_response__get_word(req_p, 2) ; + val2 = cy_as_ll_request_response__get_word(req_p, 3) ; + cbdata.rd_count = (uint32_t)((val1 << 16) | val2) ; + + if (dev_p->usb_event_cb) + dev_p->usb_event_cb(h, + cy_as_event_usb_m_s_c_progress, &cbdata) ; + else + dev_p->usb_event_cb_ms(h, + cy_as_event_usb_m_s_c_progress, &cbdata) ; + } + + cy_as_ll_send_status_response(dev_p, + CY_RQT_USB_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ; +} + +/* +* This function processes the requests delivered from the +* firmware within the West Bridge device that are delivered +* in the USB context. These requests generally are EP0 and +* EP1 related requests or USB events. +*/ +static void +my_usb_request_callback(cy_as_device *dev_p, uint8_t context, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *resp_p, + cy_as_return_status_t ret) +{ + uint16_t val ; + uint8_t code = cy_as_ll_request_response__get_code(req_p) ; + + (void)resp_p ; + (void)context ; + (void)ret ; + + switch (code) { + case CY_RQT_USB_EVENT: + my_usb_request_callback_usb_event(dev_p, req_p) ; + break ; + + case CY_RQT_USB_EP_DATA: + dev_p->usb_last_event = cy_as_event_usb_setup_packet ; + my_usb_request_callback_usb_data(dev_p, req_p) ; + break ; + + case CY_RQT_SCSI_INQUIRY_COMMAND: + dev_p->usb_last_event = cy_as_event_usb_inquiry_after ; + my_usb_request_callback_inquiry(dev_p, req_p) ; + break ; + + case CY_RQT_SCSI_START_STOP_COMMAND: + dev_p->usb_last_event = cy_as_event_usb_start_stop ; + my_usb_request_callback_start_stop(dev_p, req_p) ; + break ; + + case CY_RQT_SCSI_UNKNOWN_COMMAND: + dev_p->usb_last_event = cy_as_event_usb_unknown_storage ; + my_usb_request_callback_uknown_c_b_w(dev_p, req_p) ; + break ; + + case CY_RQT_USB_ACTIVITY_UPDATE: + dev_p->usb_last_event = cy_as_event_usb_m_s_c_progress ; + my_usb_request_callback_m_s_c_progress(dev_p, req_p) ; + break ; + + default: + cy_as_hal_print_message("invalid request " + "received on USB context\n") ; + val = req_p->box0 ; + cy_as_ll_send_data_response(dev_p, CY_RQT_USB_RQT_CONTEXT, + CY_RESP_INVALID_REQUEST, sizeof(val), &val) ; + break ; + } +} + +static cy_as_return_status_t +my_handle_response_usb_start(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* + * mark EP 0 and EP1 as 64 byte endpoints + */ + cy_as_dma_set_max_dma_size(dev_p, 0, 64) ; + cy_as_dma_set_max_dma_size(dev_p, 1, 64) ; + + dev_p->usb_count++ ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_destroy_c_b_queue(dev_p->usb_func_cbs) ; + cy_as_ll_register_request_callback(dev_p, + CY_RQT_USB_RQT_CONTEXT, 0) ; + } + + cy_as_device_clear_u_s_s_pending(dev_p) ; + + return ret ; + +} + +/* +* This function starts the USB stack. The stack is reference +* counted so if the stack is already started, this function +* just increments the count. If the stack has not been started, +* a start request is sent to the West Bridge device. +* +* Note: Starting the USB stack does not cause the USB signals +* to be connected to the USB pins. To do this and therefore +* initiate enumeration, CyAsUsbConnect() must be called. +*/ +cy_as_return_status_t +cy_as_usb_start(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p, *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_start called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (cy_as_device_is_u_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + cy_as_device_set_u_s_s_pending(dev_p) ; + + if (dev_p->usb_count == 0) { + /* + * since we are just starting the stack, + * mark USB as not connected to the remote host + */ + cy_as_device_clear_usb_connected(dev_p) ; + dev_p->usb_phy_config = 0 ; + + /* Queue for 1.0 Async Requests, kept for + * backwards compatibility */ + dev_p->usb_func_cbs = cy_as_create_c_b_queue(CYAS_USB_FUNC_CB) ; + if (dev_p->usb_func_cbs == 0) { + cy_as_device_clear_u_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Reset the EP0 state */ + cy_as_usb_reset_e_p0_state(dev_p) ; + + /* + * we register here becuase the start request may cause + * events to occur before the response to the start request. + */ + cy_as_ll_register_request_callback(dev_p, + CY_RQT_USB_RQT_CONTEXT, my_usb_request_callback) ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_START_USB, CY_RQT_USB_RQT_CONTEXT, 0) ; + if (req_p == 0) { + cy_as_destroy_c_b_queue(dev_p->usb_func_cbs) ; + dev_p->usb_func_cbs = 0 ; + cy_as_device_clear_u_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Reserve space for the reply, the reply data + * will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_destroy_c_b_queue(dev_p->usb_func_cbs) ; + dev_p->usb_func_cbs = 0 ; + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_device_clear_u_s_s_pending(dev_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_usb_start(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, + client, CY_FUNCT_CB_USB_START, 0, + dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else { + dev_p->usb_count++ ; + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_USB_START, 0) ; + } + + cy_as_device_clear_u_s_s_pending(dev_p) ; + + return ret ; +} + +void +cy_as_usb_reset(cy_as_device *dev_p) +{ + int i ; + + cy_as_device_clear_usb_connected(dev_p) ; + + for (i = 0 ; i < sizeof(dev_p->usb_config) / + sizeof(dev_p->usb_config[0]) ; i++) { + /* + * cancel all pending USB read/write operations, as it is + * possible that the USB stack comes up in a different + * configuration with a different set of endpoints. + */ + if (cy_as_device_is_usb_async_pending(dev_p, i)) + cy_as_usb_cancel_async(dev_p, + (cy_as_end_point_number_t)i) ; + + dev_p->usb_cb[i] = 0 ; + dev_p->usb_config[i].enabled = cy_false ; + } + + dev_p->usb_phy_config = 0 ; +} + +/* + * This function does all the API side clean-up associated + * with CyAsUsbStop, without any communication with firmware. + * This needs to be done when the device is being reset while + * the USB stack is active. + */ +void +cy_as_usb_cleanup(cy_as_device *dev_p) +{ + if (dev_p->usb_count) { + cy_as_usb_reset_e_p0_state(dev_p) ; + cy_as_usb_reset(dev_p) ; + cy_as_hal_mem_set(dev_p->usb_config, 0, + sizeof(dev_p->usb_config)) ; + cy_as_destroy_c_b_queue(dev_p->usb_func_cbs) ; + + dev_p->usb_count = 0 ; + } +} + +static cy_as_return_status_t +my_handle_response_usb_stop(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* + * we sucessfully shutdown the stack, so + * decrement to make the count zero. + */ + cy_as_usb_cleanup(dev_p) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_ll_register_request_callback(dev_p, + CY_RQT_USB_RQT_CONTEXT, 0) ; + + cy_as_device_clear_u_s_s_pending(dev_p) ; + + return ret ; +} + +/* +* This function stops the USB stack. The USB stack is reference +* counted so first is reference count is decremented. If the +* reference count is then zero, a request is sent to the West +* Bridge device to stop the USB stack on the West Bridge device. +*/ +cy_as_return_status_t +cy_as_usb_stop(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p = 0, *reply_p = 0 ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_stop called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_CONNECTED ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (cy_as_device_is_u_s_s_pending(dev_p)) + return CY_AS_ERROR_STARTSTOP_PENDING ; + + cy_as_device_set_u_s_s_pending(dev_p) ; + + if (dev_p->usb_count == 1) { + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_STOP_USB, + CY_RQT_USB_RQT_CONTEXT, 0) ; + if (req_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + /* Reserve space for the reply, the reply data will not + * exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_usb_stop(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_STOP, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } else if (dev_p->usb_count > 1) { + /* + * reset all LE_ps to inactive state, after cleaning + * up any pending async read/write calls. + */ + cy_as_usb_reset(dev_p) ; + dev_p->usb_count-- ; + + if (cb) + cb(handle, ret, client, CY_FUNCT_CB_USB_STOP, 0) ; + } + + cy_as_device_clear_u_s_s_pending(dev_p) ; + + return ret ; +} + +/* +* This function registers a callback to be called when +* USB events are processed +*/ +cy_as_return_status_t +cy_as_usb_register_callback(cy_as_device_handle handle, + cy_as_usb_event_callback callback) +{ + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_register_callback called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (!cy_as_device_is_configured(dev_p)) + return CY_AS_ERROR_NOT_CONFIGURED ; + + if (!cy_as_device_is_firmware_loaded(dev_p)) + return CY_AS_ERROR_NO_FIRMWARE ; + + dev_p->usb_event_cb = NULL ; + dev_p->usb_event_cb_ms = callback ; + return CY_AS_ERROR_SUCCESS ; +} + + +static cy_as_return_status_t +my_handle_response_no_data(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_connect(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret == CY_AS_ERROR_SUCCESS) + cy_as_device_set_usb_connected(dev_p) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + + +/* +* This method asks the West Bridge device to connect the +* internal USB D+ and D- signals to the USB pins, thus +* starting the enumeration processes if the external pins +* are connnected to a USB host. If the external pins are +* not connect to a USB host, enumeration will begin as soon +* as the USB pins are connected to a host. +*/ +cy_as_return_status_t +cy_as_usb_connect(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_connect called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* 1 = Connect request */ + cy_as_ll_request_response__set_word(req_p, 0, 1) ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_connect(dev_p, req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_CONNECT, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_disconnect(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_return_status_t ret) +{ + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (ret == CY_AS_ERROR_SUCCESS) + cy_as_device_clear_usb_connected(dev_p) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} +/* +* This method forces a disconnect of the D+ and D- pins +* external to the West Bridge device from the D+ and D- +* signals internally, effectively disconnecting the West +* Bridge device from any connected USB host. +*/ +cy_as_return_status_t +cy_as_usb_disconnect(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_disconnect called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (!cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_NOT_CONNECTED ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SET_CONNECT_STATE, CY_RQT_USB_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, 0) ; + + /* Reserve space for the reply, the reply + * data will not exceed two bytes */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_disconnect(dev_p, + req_p, reply_p, ret) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_DISCONNECT, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_set_enum_config(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + /* + * we configured the west bridge device and + * enumeration is going to happen on the P port + * processor. now we must enable endpoint zero + */ + cy_as_usb_end_point_config config ; + + config.dir = cy_as_usb_in_out ; + config.type = cy_as_usb_control ; + config.enabled = cy_true ; + + ret = cy_as_usb_set_end_point_config((cy_as_device_handle *) + dev_p, 0, &config) ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* +* This method sets how the USB is enumerated and should +* be called before the CyAsUsbConnect() is called. +*/ +static cy_as_return_status_t +my_usb_set_enum_config(cy_as_device *dev_p, + uint8_t bus_mask, + uint8_t media_mask, + cy_bool use_antioch_enumeration, + uint8_t mass_storage_interface, + uint8_t mtp_interface, + cy_bool mass_storage_callbacks, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_log_debug_message(6, "cy_as_usb_set_enum_config called") ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_CONNECTED ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* if we are using MTP firmware: */ + if (dev_p->is_mtp_firmware == 1) { + /* we cannot enumerate MSC */ + if (mass_storage_interface != 0) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (bus_mask == 0) { + if (mtp_interface != 0) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + } else if (bus_mask == 2) { + /* enable EP 1 as it will be used */ + cy_as_dma_enable_end_point(dev_p, 1, cy_true, + cy_as_direction_in) ; + dev_p->usb_config[1].enabled = cy_true ; + dev_p->usb_config[1].dir = cy_as_usb_in ; + dev_p->usb_config[1].type = cy_as_usb_int ; + } else { + return CY_AS_ERROR_INVALID_CONFIGURATION ; + } + /* if we are not using MTP firmware, we cannot enumerate MTP */ + } else if (mtp_interface != 0) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + /* + * if we are not enumerating mass storage, we should + * not be providing an interface number. + */ + if (bus_mask == 0 && mass_storage_interface != 0) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + /* + * if we are going to use mtp_interface, bus mask must be 2. + */ + if (mtp_interface != 0 && bus_mask != 2) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 4) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Marshal the structure */ + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((media_mask << 8) | bus_mask)) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)use_antioch_enumeration) ; + cy_as_ll_request_response__set_word(req_p, 2, + dev_p->is_mtp_firmware ? mtp_interface : + mass_storage_interface) ; + cy_as_ll_request_response__set_word(req_p, 3, + (uint16_t)mass_storage_callbacks) ; + + /* Reserve space for the reply, the reply + * data will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_set_enum_config(dev_p, + req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_SETENUMCONFIG, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* + * This method sets how the USB is enumerated and should + * be called before the CyAsUsbConnect() is called. + */ +cy_as_return_status_t +cy_as_usb_set_enum_config(cy_as_device_handle handle, + cy_as_usb_enum_control *config_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + uint8_t bus_mask, media_mask ; + uint32_t bus, device ; + cy_as_return_status_t ret ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if ((cy_as_device_is_in_callback(dev_p)) && (cb != 0)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Since we are mapping the media types to bus with NAND to 0 + * and the rest to 1, and we are only allowing for enumerating + * all the devices on a bus we just scan the array for any + * positions where there a device is enabled and mark the bus + * to be enumerated. + */ + bus_mask = 0 ; + media_mask = 0 ; + media_mask = 0 ; + for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) { + for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; device++) { + if (config_p->devices_to_enumerate[bus][device] == + cy_true) { + bus_mask |= (0x01 << bus) ; + media_mask |= dev_p->media_supported[bus] ; + media_mask |= dev_p->media_supported[bus] ; + } + } + } + + return my_usb_set_enum_config(dev_p, bus_mask, media_mask, + config_p->antioch_enumeration, + config_p->mass_storage_interface, + config_p->mtp_interface, + config_p->mass_storage_callbacks, + cb, + client + ) ; +} + + +static cy_as_return_status_t +my_handle_response_get_enum_config(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + void *config_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t val ; + uint8_t bus_mask ; + uint32_t bus ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_USB_CONFIG) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + /* Marshal the reply */ + if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) { + uint32_t device ; + cy_bool state; + cy_as_usb_enum_control *ms_config_p = + (cy_as_usb_enum_control *)config_p; + + bus_mask = (uint8_t) + (cy_as_ll_request_response__get_word + (reply_p, 0) & 0xFF) ; + for (bus = 0; bus < CY_AS_MAX_BUSES; bus++) { + if (bus_mask & (1 << bus)) + state = cy_true ; + else + state = cy_false ; + + for (device = 0; device < CY_AS_MAX_STORAGE_DEVICES; + device++) + ms_config_p->devices_to_enumerate[bus][device] + = state ; + } + + ms_config_p->antioch_enumeration = + (cy_bool)cy_as_ll_request_response__get_word + (reply_p, 1) ; + + val = cy_as_ll_request_response__get_word(reply_p, 2) ; + if (dev_p->is_mtp_firmware) { + ms_config_p->mass_storage_interface = 0 ; + ms_config_p->mtp_interface = (uint8_t)(val & 0xFF) ; + } else { + ms_config_p->mass_storage_interface = + (uint8_t)(val & 0xFF) ; + ms_config_p->mtp_interface = 0 ; + } + ms_config_p->mass_storage_callbacks = (cy_bool)(val >> 8) ; + + /* + * firmware returns an invalid interface number for mass storage, + * if mass storage is not enabled. this needs to be converted to + * zero to match the input configuration. + */ + if (bus_mask == 0) { + if (dev_p->is_mtp_firmware) + ms_config_p->mtp_interface = 0 ; + else + ms_config_p->mass_storage_interface = 0 ; + } + } else { + cy_as_usb_enum_control_dep *ex_config_p = + (cy_as_usb_enum_control_dep *)config_p; + + ex_config_p->enum_mass_storage = (uint8_t) + ((cy_as_ll_request_response__get_word + (reply_p, 0) >> 8) & 0xFF) ; + ex_config_p->antioch_enumeration = (cy_bool) + cy_as_ll_request_response__get_word(reply_p, 1) ; + + val = cy_as_ll_request_response__get_word(reply_p, 2) ; + ex_config_p->mass_storage_interface = (uint8_t)(val & 0xFF) ; + ex_config_p->mass_storage_callbacks = (cy_bool)(val >> 8) ; + + /* + * firmware returns an invalid interface number for mass + * storage, if mass storage is not enabled. this needs to + * be converted to zero to match the input configuration. + */ + if (ex_config_p->enum_mass_storage == 0) + ex_config_p->mass_storage_interface = 0 ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* +* This sets up the request for the enumerateion configuration +* information, based on if the request is from the old pre-1.2 +* functions. +*/ +static cy_as_return_status_t +my_usb_get_enum_config(cy_as_device_handle handle, + uint16_t req_flags, + void *config_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_get_enum_config called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_GET_USB_CONFIG, CY_RQT_USB_RQT_CONTEXT, 0) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply data + * will not exceed two bytes */ + reply_p = cy_as_ll_create_response(dev_p, 3) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + /* we need to know the type of request to + * know how to manage the data */ + req_p->flags |= req_flags; + return my_handle_response_get_enum_config(dev_p, + req_p, reply_p, config_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_GETENUMCONFIG, config_p, + dev_p->func_cbs_usb, req_flags, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* + * This method returns the enumerateion configuration information + * from the West Bridge device. Generally this is not used by + * client software but is provided mostly for debug information. + * We want a method to read all state information from the device. + */ +cy_as_return_status_t +cy_as_usb_get_enum_config(cy_as_device_handle handle, + cy_as_usb_enum_control *config_p, + cy_as_function_callback cb, + uint32_t client) +{ + return my_usb_get_enum_config(handle, + CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client); +} + + +/* +* This method sets the USB descriptor for a given entity. +*/ +cy_as_return_status_t +cy_as_usb_set_descriptor(cy_as_device_handle handle, + cy_as_usb_desc_type type, + uint8_t index, + void *desc_p, + uint16_t length, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint16_t pktlen ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_set_descriptor called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (length > CY_AS_MAX_USB_DESCRIPTOR_SIZE) + return CY_AS_ERROR_INVALID_DESCRIPTOR ; + + pktlen = (uint16_t)length / 2 ; + if (length % 2) + pktlen++ ; + pktlen += 2 ; /* 1 for type, 1 for length */ + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, CY_RQT_SET_DESCRIPTOR, + CY_RQT_USB_RQT_CONTEXT, (uint16_t)pktlen) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((uint8_t)type | (index << 8))) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)length) ; + cy_as_ll_request_response__pack(req_p, 2, length, desc_p) ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_no_data(dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_SETDESCRIPTOR, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* + * This method clears all descriptors that were previously + * stored on the West Bridge through CyAsUsbSetDescriptor calls. + */ +cy_as_return_status_t +cy_as_usb_clear_descriptors(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_clear_descriptors called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if ((cy_as_device_is_in_callback(dev_p)) && (cb == 0)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_CLEAR_DESCRIPTORS, CY_RQT_USB_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_no_data(dev_p, req_p, reply_p) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_CLEARDESCRIPTORS, 0, + dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_get_descriptor(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_get_descriptor_data *data) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint32_t retlen ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SUCCESS_FAILURE) { + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + goto destroy ; + } else if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_USB_DESCRIPTOR) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + retlen = cy_as_ll_request_response__get_word(reply_p, 0) ; + if (retlen > data->length) { + ret = CY_AS_ERROR_INVALID_SIZE ; + goto destroy ; + } + + ret = CY_AS_ERROR_SUCCESS ; + cy_as_ll_request_response__unpack(reply_p, 1, + retlen, data->desc_p) ; + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +/* +* This method retreives the USB descriptor for a given type. +*/ +cy_as_return_status_t +cy_as_usb_get_descriptor(cy_as_device_handle handle, + cy_as_usb_desc_type type, + uint8_t index, + cy_as_get_descriptor_data *data, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_get_descriptor called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_GET_DESCRIPTOR, CY_RQT_USB_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((uint8_t)type | (index << 8))) ; + + /* Add one for the length field */ + reply_p = cy_as_ll_create_response(dev_p, + CY_AS_MAX_USB_DESCRIPTOR_SIZE + 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply( + dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return my_handle_response_get_descriptor(dev_p, + req_p, reply_p, data) ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_GETDESCRIPTOR, data, + dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, + reply_p, cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_set_physical_configuration(cy_as_device_handle handle, + uint8_t config) +{ + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, + "cy_as_usb_set_physical_configuration called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_CONNECTED ; + + if (config < 1 || config > 12) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + dev_p->usb_phy_config = config ; + + return CY_AS_ERROR_SUCCESS ; +} + +static cy_bool +is_physical_valid(uint8_t config, cy_as_end_point_number_t ep) +{ + static uint8_t validmask[12] = { + 0x0f, /* Config 1 - 1, 2, 3, 4 */ + 0x07, /* Config 2 - 1, 2, 3 */ + 0x07, /* Config 3 - 1, 2, 3 */ + 0x0d, /* Config 4 - 1, 3, 4 */ + 0x05, /* Config 5 - 1, 3 */ + 0x05, /* Config 6 - 1, 3 */ + 0x0d, /* Config 7 - 1, 3, 4 */ + 0x05, /* Config 8 - 1, 3 */ + 0x05, /* Config 9 - 1, 3 */ + 0x0d, /* Config 10 - 1, 3, 4 */ + 0x09, /* Config 11 - 1, 4 */ + 0x01 /* Config 12 - 1 */ + } ; + + return (validmask[config - 1] & (1 << (ep - 1))) ? cy_true : cy_false ; +} + +/* +* This method sets the configuration for an endpoint +*/ +cy_as_return_status_t +cy_as_usb_set_end_point_config(cy_as_device_handle handle, + cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p) +{ + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_set_end_point_config called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_CONNECTED ; + + if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + if (ep == 0) { + /* Endpoint 0 must be 64 byte, dir IN/OUT, + * and control type */ + if (config_p->dir != cy_as_usb_in_out || + config_p->type != cy_as_usb_control) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + } else if (ep == 1) { + if ((dev_p->is_mtp_firmware == 1) && + (dev_p->usb_config[1].enabled == cy_true)) { + return CY_AS_ERROR_INVALID_ENDPOINT ; + } + + /* + * EP1 can only be used either as an OUT ep, or as an IN ep. + */ + if ((config_p->type == cy_as_usb_control) || + (config_p->type == cy_as_usb_iso) || + (config_p->dir == cy_as_usb_in_out)) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + } else { + if (config_p->dir == cy_as_usb_in_out || + config_p->type == cy_as_usb_control) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (!is_physical_valid(dev_p->usb_phy_config, + config_p->physical)) + return CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT ; + + /* + * ISO endpoints must be on E_ps 3, 5, 7 or 9 as + * they need to align directly with the underlying + * physical endpoint. + */ + if (config_p->type == cy_as_usb_iso) { + if (ep != 3 && ep != 5 && ep != 7 && ep != 9) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (ep == 3 && config_p->physical != 1) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (ep == 5 && config_p->physical != 2) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (ep == 7 && config_p->physical != 3) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + + if (ep == 9 && config_p->physical != 4) + return CY_AS_ERROR_INVALID_CONFIGURATION ; + } + } + + /* Store the configuration information until a + * CyAsUsbCommitConfig is done */ + dev_p->usb_config[ep] = *config_p ; + + /* If the endpoint is enabled, enable DMA associated + * with the endpoint */ + /* + * we make some assumptions that we check here. we assume + * that the direction fields for the DMA module are the same + * values as the direction values for the USB module. + */ + cy_as_hal_assert((int)cy_as_usb_in == (int)cy_as_direction_in); + cy_as_hal_assert((int)cy_as_usb_out == (int)cy_as_direction_out); + cy_as_hal_assert((int)cy_as_usb_in_out == (int)cy_as_direction_in_out) ; + + return cy_as_dma_enable_end_point(dev_p, ep, + config_p->enabled, (cy_as_dma_direction)config_p->dir) ; +} + +cy_as_return_status_t +cy_as_usb_get_end_point_config(cy_as_device_handle handle, + cy_as_end_point_number_t ep, cy_as_usb_end_point_config *config_p) +{ + cy_as_return_status_t ret ; + + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_get_end_point_config called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (ep >= 16 || ep == 2 || ep == 4 || ep == 6 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + *config_p = dev_p->usb_config[ep] ; + + return CY_AS_ERROR_SUCCESS ; +} + +/* +* Commit the configuration of the various endpoints to the hardware. +*/ +cy_as_return_status_t +cy_as_usb_commit_config(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + uint32_t i ; + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + cy_as_device *dev_p ; + uint16_t data ; + + cy_as_log_debug_message(6, "cy_as_usb_commit_config called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_usb_connected(dev_p)) + return CY_AS_ERROR_USB_CONNECTED ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* + * this performs the mapping based on informatation that was + * previously stored on the device about the various endpoints + * and how they are configured. the output of this mapping is + * setting the the 14 register values contained in usb_lepcfg + * and usb_pepcfg + */ + ret = cy_as_usb_map_logical2_physical(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* + * now, package the information about the various logical and + * physical endpoint configuration registers and send it + * across to the west bridge device. + */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_SET_USB_CONFIG_REGISTERS, CY_RQT_USB_RQT_CONTEXT, 8) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_hal_print_message("USB configuration: %d\n", + dev_p->usb_phy_config) ; + cy_as_hal_print_message("EP1OUT: 0x%02x EP1IN: 0x%02x\n", + dev_p->usb_ep1cfg[0], dev_p->usb_ep1cfg[1]) ; + cy_as_hal_print_message("PEP registers: 0x%02x 0x%02x 0x%02x 0x%02x\n", + dev_p->usb_pepcfg[0], dev_p->usb_pepcfg[1], + dev_p->usb_pepcfg[2], dev_p->usb_pepcfg[3]) ; + + cy_as_hal_print_message("LEP registers: 0x%02x 0x%02x 0x%02x " + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + dev_p->usb_lepcfg[0], dev_p->usb_lepcfg[1], + dev_p->usb_lepcfg[2], dev_p->usb_lepcfg[3], + dev_p->usb_lepcfg[4], dev_p->usb_lepcfg[5], + dev_p->usb_lepcfg[6], dev_p->usb_lepcfg[7], + dev_p->usb_lepcfg[8], dev_p->usb_lepcfg[9]) ; + + /* Write the EP1OUTCFG and EP1INCFG data in the first word. */ + data = (uint16_t)((dev_p->usb_ep1cfg[0] << 8) | + dev_p->usb_ep1cfg[1]) ; + cy_as_ll_request_response__set_word(req_p, 0, data) ; + + /* Write the PEP CFG data in the next 2 words */ + for (i = 0 ; i < 4 ; i += 2) { + data = (uint16_t)((dev_p->usb_pepcfg[i] << 8) | + dev_p->usb_pepcfg[i + 1]) ; + cy_as_ll_request_response__set_word(req_p, + 1 + i / 2, data) ; + } + + /* Write the LEP CFG data in the next 5 words */ + for (i = 0 ; i < 10 ; i += 2) { + data = (uint16_t)((dev_p->usb_lepcfg[i] << 8) | + dev_p->usb_lepcfg[i + 1]) ; + cy_as_ll_request_response__set_word(req_p, + 3 + i / 2, data) ; + } + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + ret = my_handle_response_no_data(dev_p, + req_p, reply_p) ; + + if (ret == CY_AS_ERROR_SUCCESS) + ret = cy_as_usb_setup_dma(dev_p) ; + + return ret ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_COMMITCONFIG, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static void +sync_request_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, + uint32_t size, cy_as_return_status_t err) +{ + (void)ep ; + (void)buf_p ; + + dev_p->usb_error = err ; + dev_p->usb_actual_cnt = size ; +} + +static void +async_read_request_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, + uint32_t size, cy_as_return_status_t err) +{ + cy_as_device_handle h ; + + cy_as_log_debug_message(6, + "async_read_request_callback called") ; + + h = (cy_as_device_handle)dev_p ; + + if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) { + dev_p->usb_pending_buffer = buf_p ; + dev_p->usb_pending_size = size ; + dev_p->usb_error = err ; + cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0) ; + } else { + cy_as_usb_io_callback cb ; + + cb = dev_p->usb_cb[ep] ; + dev_p->usb_cb[ep] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, ep) ; + if (cb) + cb(h, ep, size, buf_p, err) ; + } +} + +static void +async_write_request_callback(cy_as_device *dev_p, + cy_as_end_point_number_t ep, void *buf_p, + uint32_t size, cy_as_return_status_t err) +{ + cy_as_device_handle h ; + + cy_as_log_debug_message(6, + "async_write_request_callback called") ; + + h = (cy_as_device_handle)dev_p ; + + if (ep == 0 && cy_as_device_is_ack_delayed(dev_p)) { + dev_p->usb_pending_buffer = buf_p ; + dev_p->usb_pending_size = size ; + dev_p->usb_error = err ; + + /* The west bridge protocol generates ZLPs as required. */ + cy_as_usb_ack_setup_packet(h, usb_ack_callback, 0) ; + } else { + cy_as_usb_io_callback cb ; + + cb = dev_p->usb_cb[ep] ; + dev_p->usb_cb[ep] = 0 ; + + cy_as_device_clear_usb_async_pending(dev_p, ep) ; + if (cb) + cb(h, ep, size, buf_p, err) ; + } +} + +static void +my_turbo_rqt_callback(cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + uint8_t code ; + + (void)context ; + (void)stat ; + + /* The Handlers are responsible for Deleting the rqt and resp when + * they are finished + */ + code = cy_as_ll_request_response__get_code(rqt) ; + switch (code) { + case CY_RQT_TURBO_SWITCH_ENDPOINT: + cy_as_hal_assert(stat == CY_AS_ERROR_SUCCESS) ; + cy_as_ll_destroy_request(dev_p, rqt) ; + cy_as_ll_destroy_response(dev_p, resp) ; + break; + default: + cy_as_hal_assert(cy_false) ; + break ; + } +} + +/* Send a mailbox request to prepare the endpoint for switching */ +static cy_as_return_status_t +my_send_turbo_switch(cy_as_device *dev_p, uint32_t size, cy_bool pktread) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + + /* Create the request to send to the West Bridge device */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_TURBO_SWITCH_ENDPOINT, CY_RQT_TUR_RQT_CONTEXT, 3) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Reserve space for the reply, the reply data will + * not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)pktread) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((size >> 16) & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(size & 0xFFFF)) ; + + ret = cy_as_ll_send_request(dev_p, req_p, + reply_p, cy_false, my_turbo_rqt_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_request(dev_p, reply_p) ; + return ret ; + } + + return CY_AS_ERROR_SUCCESS ; +} + +cy_as_return_status_t +cy_as_usb_read_data(cy_as_device_handle handle, + cy_as_end_point_number_t ep, cy_bool pktread, + uint32_t dsize, uint32_t *dataread, void *data) +{ + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_read_data called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (ep >= 16 || ep == 4 || ep == 6 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* EP2 is available for reading when MTP is active */ + if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* If the endpoint is disabled, we cannot + * write data to the endpoint */ + if (!dev_p->usb_config[ep].enabled) + return CY_AS_ERROR_ENDPOINT_DISABLED ; + + if (dev_p->usb_config[ep].dir != cy_as_usb_out) + return CY_AS_ERROR_USB_BAD_DIRECTION ; + + ret = cy_as_dma_queue_request(dev_p, ep, data, dsize, + pktread, cy_true, sync_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (ep == CY_AS_MTP_READ_ENDPOINT) { + ret = my_send_turbo_switch(dev_p, dsize, pktread) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, ret) ; + return ret ; + } + + ret = cy_as_dma_drain_queue(dev_p, ep, cy_false) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } else { + ret = cy_as_dma_drain_queue(dev_p, ep, cy_true) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + ret = dev_p->usb_error ; + *dataread = dev_p->usb_actual_cnt ; + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_read_data_async(cy_as_device_handle handle, + cy_as_end_point_number_t ep, cy_bool pktread, + uint32_t dsize, void *data, cy_as_usb_io_callback cb) +{ + cy_as_return_status_t ret ; + uint32_t mask ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_read_data_async called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (ep >= 16 || ep == 4 || ep == 6 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* EP2 is available for reading when MTP is active */ + if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_READ_ENDPOINT) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* If the endpoint is disabled, we cannot + * write data to the endpoint */ + if (!dev_p->usb_config[ep].enabled) + return CY_AS_ERROR_ENDPOINT_DISABLED ; + + if (dev_p->usb_config[ep].dir != cy_as_usb_out && + dev_p->usb_config[ep].dir != cy_as_usb_in_out) + return CY_AS_ERROR_USB_BAD_DIRECTION ; + + /* + * since async operations can be triggered by interrupt + * code, we must insure that we do not get multiple async + * operations going at one time and protect this test and + * set operation from interrupts. + */ + mask = cy_as_hal_disable_interrupts() ; + if (cy_as_device_is_usb_async_pending(dev_p, ep)) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + cy_as_device_set_usb_async_pending(dev_p, ep) ; + + /* + * if this is for EP0, we set this bit to delay the + * ACK response until after this read has completed. + */ + if (ep == 0) + cy_as_device_set_ack_delayed(dev_p) ; + + cy_as_hal_enable_interrupts(mask) ; + + cy_as_hal_assert(dev_p->usb_cb[ep] == 0) ; + dev_p->usb_cb[ep] = cb ; + + ret = cy_as_dma_queue_request(dev_p, ep, data, dsize, + pktread, cy_true, async_read_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (ep == CY_AS_MTP_READ_ENDPOINT) { + ret = my_send_turbo_switch(dev_p, dsize, pktread) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, ret) ; + return ret ; + } + } else { + /* Kick start the queue if it is not running */ + cy_as_dma_kick_start(dev_p, ep) ; + } + return ret ; +} + +cy_as_return_status_t +cy_as_usb_write_data(cy_as_device_handle handle, + cy_as_end_point_number_t ep, uint32_t dsize, void *data) +{ + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_write_data called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (ep >= 16 || ep == 2 || ep == 4 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* EP6 is available for writing when MTP is active */ + if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* If the endpoint is disabled, we cannot + * write data to the endpoint */ + if (!dev_p->usb_config[ep].enabled) + return CY_AS_ERROR_ENDPOINT_DISABLED ; + + if (dev_p->usb_config[ep].dir != cy_as_usb_in && + dev_p->usb_config[ep].dir != cy_as_usb_in_out) + return CY_AS_ERROR_USB_BAD_DIRECTION ; + + /* Write on Turbo endpoint */ + if (ep == CY_AS_MTP_WRITE_ENDPOINT) { + cy_as_ll_request_response *req_p, *reply_p ; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST, + CY_RQT_TUR_RQT_CONTEXT, 3) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, + 0, 0x0006) ; /* EP number to use. */ + cy_as_ll_request_response__set_word(req_p, + 1, (uint16_t)((dsize >> 16) & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, + 2, (uint16_t)(dsize & 0xFFFF)) ; + + /* Reserve space for the reply, the reply data + * will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (dsize) { + ret = cy_as_dma_queue_request(dev_p, + ep, data, dsize, cy_false, + cy_false, sync_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word + (reply_p, 0); + } + + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + if (ret != CY_AS_ERROR_SUCCESS) { + if (dsize) + cy_as_dma_cancel(dev_p, ep, ret) ; + return ret ; + } + + /* If this is a zero-byte write, firmware will + * handle it. there is no need to do any work here. + */ + if (!dsize) + return CY_AS_ERROR_SUCCESS ; + } else { + ret = cy_as_dma_queue_request(dev_p, ep, data, dsize, + cy_false, cy_false, sync_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + if (ep != CY_AS_MTP_WRITE_ENDPOINT) + ret = cy_as_dma_drain_queue(dev_p, ep, cy_true) ; + else + ret = cy_as_dma_drain_queue(dev_p, ep, cy_false) ; + + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + ret = dev_p->usb_error ; + return ret ; +} + +static void +mtp_write_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + cy_as_usb_io_callback cb ; + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + + cy_as_hal_assert(context == CY_RQT_TUR_RQT_CONTEXT) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(resp, 0) ; + } + + /* If this was a zero byte transfer request, we can + * call the callback from here. */ + if ((cy_as_ll_request_response__get_word(rqt, 1) == 0) && + (cy_as_ll_request_response__get_word(rqt, 2) == 0)) { + cb = dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] ; + dev_p->usb_cb[CY_AS_MTP_WRITE_ENDPOINT] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, + CY_AS_MTP_WRITE_ENDPOINT) ; + if (cb) + cb(h, CY_AS_MTP_WRITE_ENDPOINT, 0, 0, ret) ; + + goto destroy ; + } + + if (ret != CY_AS_ERROR_SUCCESS) { + /* Firmware failed the request. Cancel the DMA transfer. */ + cy_as_dma_cancel(dev_p, 0x06, CY_AS_ERROR_CANCELED) ; + dev_p->usb_cb[0x06] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, 0x06) ; + } + +destroy: + cy_as_ll_destroy_response(dev_p, resp) ; + cy_as_ll_destroy_request(dev_p, rqt) ; +} + +cy_as_return_status_t +cy_as_usb_write_data_async(cy_as_device_handle handle, + cy_as_end_point_number_t ep, uint32_t dsize, void *data, + cy_bool spacket, cy_as_usb_io_callback cb) +{ + uint32_t mask ; + cy_as_return_status_t ret ; + cy_as_device *dev_p ; + + cy_as_log_debug_message(6, "cy_as_usb_write_data_async called") ; + + dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (ep >= 16 || ep == 2 || ep == 4 || ep == 8) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* EP6 is available for writing when MTP is active */ + if (dev_p->mtp_count == 0 && ep == CY_AS_MTP_WRITE_ENDPOINT) + return CY_AS_ERROR_INVALID_ENDPOINT ; + + /* If the endpoint is disabled, we cannot + * write data to the endpoint */ + if (!dev_p->usb_config[ep].enabled) + return CY_AS_ERROR_ENDPOINT_DISABLED ; + + if (dev_p->usb_config[ep].dir != cy_as_usb_in && + dev_p->usb_config[ep].dir != cy_as_usb_in_out) + return CY_AS_ERROR_USB_BAD_DIRECTION ; + + /* + * since async operations can be triggered by interrupt + * code, we must insure that we do not get multiple + * async operations going at one time and + * protect this test and set operation from interrupts. + */ + mask = cy_as_hal_disable_interrupts() ; + if (cy_as_device_is_usb_async_pending(dev_p, ep)) { + cy_as_hal_enable_interrupts(mask) ; + return CY_AS_ERROR_ASYNC_PENDING ; + } + + cy_as_device_set_usb_async_pending(dev_p, ep) ; + + if (ep == 0) + cy_as_device_set_ack_delayed(dev_p) ; + + cy_as_hal_enable_interrupts(mask) ; + + cy_as_hal_assert(dev_p->usb_cb[ep] == 0) ; + dev_p->usb_cb[ep] = cb ; + dev_p->usb_spacket[ep] = spacket ; + + /* Write on Turbo endpoint */ + if (ep == CY_AS_MTP_WRITE_ENDPOINT) { + cy_as_ll_request_response *req_p, *reply_p ; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST, + CY_RQT_TUR_RQT_CONTEXT, 3) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + cy_as_ll_request_response__set_word(req_p, 0, + 0x0006) ; /* EP number to use. */ + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)((dsize >> 16) & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)(dsize & 0xFFFF)) ; + + /* Reserve space for the reply, the reply data + * will not exceed one word */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (dsize) { + ret = cy_as_dma_queue_request(dev_p, ep, data, + dsize, cy_false, cy_false, + async_write_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_false, mtp_write_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + if (dsize) + cy_as_dma_cancel(dev_p, ep, ret) ; + return ret ; + } + + /* Firmware will handle a zero byte transfer + * without any DMA transfers. */ + if (!dsize) + return CY_AS_ERROR_SUCCESS ; + } else { + ret = cy_as_dma_queue_request(dev_p, ep, data, dsize, + cy_false, cy_false, async_write_request_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + } + + /* Kick start the queue if it is not running */ + if (ep != CY_AS_MTP_WRITE_ENDPOINT) + cy_as_dma_kick_start(dev_p, ep) ; + + return CY_AS_ERROR_SUCCESS ; +} + +static void +my_usb_cancel_async_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + uint8_t ep ; + (void)context ; + + ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0) ; + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(resp, 0) ; + } + + cy_as_ll_destroy_request(dev_p, rqt) ; + cy_as_ll_destroy_response(dev_p, resp) ; + + if (ret == CY_AS_ERROR_SUCCESS) { + cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + dev_p->usb_cb[ep] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, ep) ; + } +} + +cy_as_return_status_t +cy_as_usb_cancel_async(cy_as_device_handle handle, + cy_as_end_point_number_t ep) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p, *reply_p ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ep &= 0x7F; /* Remove the direction bit. */ + if (!cy_as_device_is_usb_async_pending(dev_p, ep)) + return CY_AS_ERROR_ASYNC_NOT_PENDING; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_suspend_mode(dev_p)) + return CY_AS_ERROR_IN_SUSPEND ; + + if ((ep == CY_AS_MTP_WRITE_ENDPOINT) || + (ep == CY_AS_MTP_READ_ENDPOINT)) { + /* Need firmware support for the cancel operation. */ + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_CANCEL_ASYNC_TRANSFER, + CY_RQT_TUR_RQT_CONTEXT, 1) ; + + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)ep) ; + + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_false, my_usb_cancel_async_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + return ret ; + } + } else { + ret = cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + dev_p->usb_cb[ep] = 0 ; + cy_as_device_clear_usb_async_pending(dev_p, ep) ; + } + + return CY_AS_ERROR_SUCCESS ; +} + +static void +cy_as_usb_ack_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t ret) +{ + cy_as_func_c_b_node *node = (cy_as_func_c_b_node *) + dev_p->func_cbs_usb->head_p ; + + (void)context ; + + if (ret == CY_AS_ERROR_SUCCESS) { + if (cy_as_ll_request_response__get_code(resp) != + CY_RESP_SUCCESS_FAILURE) + ret = CY_AS_ERROR_INVALID_RESPONSE ; + else + ret = cy_as_ll_request_response__get_word(resp, 0) ; + } + + node->cb_p((cy_as_device_handle)dev_p, ret, + node->client_data, node->data_type, node->data) ; + cy_as_remove_c_b_node(dev_p->func_cbs_usb) ; + + cy_as_ll_destroy_request(dev_p, rqt) ; + cy_as_ll_destroy_response(dev_p, resp) ; + cy_as_device_clear_ack_delayed(dev_p) ; +} + +static cy_as_return_status_t +cy_as_usb_ack_setup_packet(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p ; + cy_as_ll_request_response *reply_p ; + cy_as_func_c_b_node *cbnode ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p) && cb == 0) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + cy_as_hal_assert(cb != 0) ; + + cbnode = cy_as_create_func_c_b_node(cb, client); + if (cbnode == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + req_p = cy_as_ll_create_request(dev_p, 0, + CY_RQT_USB_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + cy_as_ll_init_request(req_p, CY_RQT_ACK_SETUP_PACKET, + CY_RQT_USB_RQT_CONTEXT, 1) ; + cy_as_ll_init_response(reply_p, 1) ; + + req_p->flags |= CY_AS_REQUEST_RESPONSE_EX ; + + cy_as_insert_c_b_node(dev_p->func_cbs_usb, cbnode) ; + + ret = cy_as_ll_send_request(dev_p, req_p, reply_p, + cy_false, cy_as_usb_ack_callback) ; + + return ret ; +} + +/* + * Flush all data in logical EP that is being NAK-ed or + * Stall-ed, so that this does not continue to block data + * on other LEPs that use the same physical EP. + */ +static void +cy_as_usb_flush_logical_e_p( + cy_as_device *dev_p, + uint16_t ep) +{ + uint16_t addr, val, count ; + + addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ; + val = cy_as_hal_read_register(dev_p->tag, addr) ; + + while (val) { + count = ((val & 0xFFF) + 1) / 2 ; + while (count--) + val = cy_as_hal_read_register(dev_p->tag, ep) ; + + cy_as_hal_write_register(dev_p->tag, addr, 0) ; + val = cy_as_hal_read_register(dev_p->tag, addr) ; + } +} + +static cy_as_return_status_t +cy_as_usb_nak_stall_request(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + uint16_t request, + cy_bool state, + cy_as_usb_function_callback cb, + cy_as_function_callback fcb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + uint16_t data ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + if (cb) + cy_as_hal_assert(fcb == 0) ; + if (fcb) + cy_as_hal_assert(cb == 0) ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p) && cb == 0 && fcb == 0) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + req_p = cy_as_ll_create_request(dev_p, + request, CY_RQT_USB_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Set the endpoint */ + data = (uint8_t)ep ; + cy_as_ll_request_response__set_word(req_p, 0, data) ; + + /* Set stall state to stalled */ + cy_as_ll_request_response__set_word(req_p, 1, (uint8_t)state) ; + + if (cb || fcb) { + void *cbnode ; + cy_as_c_b_queue *queue ; + if (cb) { + cbnode = cy_as_create_usb_func_c_b_node(cb, client) ; + queue = dev_p->usb_func_cbs ; + } else { + cbnode = cy_as_create_func_c_b_node(fcb, client) ; + queue = dev_p->func_cbs_usb ; + req_p->flags |= CY_AS_REQUEST_RESPONSE_EX ; + } + + if (cbnode == 0) { + ret = CY_AS_ERROR_OUT_OF_MEMORY ; + goto destroy ; + } else + cy_as_insert_c_b_node(queue, cbnode) ; + + + if (cy_as_device_is_setup_packet(dev_p)) { + /* No Ack is needed on a stall request on EP0 */ + if ((state == cy_true) && (ep == 0)) { + cy_as_device_set_ep0_stalled(dev_p) ; + } else { + cy_as_device_set_ack_delayed(dev_p) ; + req_p->flags |= + CY_AS_REQUEST_RESPONSE_DELAY_ACK ; + } + } + + ret = cy_as_ll_send_request(dev_p, req_p, + reply_p, cy_false, cy_as_usb_func_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + if (req_p->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK) + cy_as_device_rem_ack_delayed(dev_p) ; + cy_as_remove_c_b_tail_node(queue) ; + + goto destroy ; + } + } else { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) != + CY_RESP_SUCCESS_FAILURE) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + + if ((ret == CY_AS_ERROR_SUCCESS) && + (request == CY_RQT_STALL_ENDPOINT)) { + if ((ep > 1) && (state != 0) && + (dev_p->usb_config[ep].dir == cy_as_usb_out)) + cy_as_usb_flush_logical_e_p(dev_p, ep) ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + } + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_get_stall(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_bool *state_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code = cy_as_ll_request_response__get_code(reply_p) ; + + if (code == CY_RESP_SUCCESS_FAILURE) { + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + goto destroy ; + } else if (code != CY_RESP_ENDPOINT_STALL) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0) ; + ret = CY_AS_ERROR_SUCCESS ; + + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +my_handle_response_get_nak(cy_as_device *dev_p, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_bool *state_p) +{ + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + uint8_t code = cy_as_ll_request_response__get_code(reply_p) ; + + if (code == CY_RESP_SUCCESS_FAILURE) { + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + goto destroy ; + } else if (code != CY_RESP_ENDPOINT_NAK) { + ret = CY_AS_ERROR_INVALID_RESPONSE ; + goto destroy ; + } + + *state_p = (cy_bool)cy_as_ll_request_response__get_word(reply_p, 0) ; + ret = CY_AS_ERROR_SUCCESS ; + + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static cy_as_return_status_t +cy_as_usb_get_nak_stall(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + uint16_t request, + uint16_t response, + cy_bool *state_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + uint16_t data ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + + (void)response ; + + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p) && !cb) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + req_p = cy_as_ll_create_request(dev_p, request, + CY_RQT_USB_RQT_CONTEXT, 1) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* Set the endpoint */ + data = (uint8_t)ep ; + cy_as_ll_request_response__set_word(req_p, 0, (uint16_t)ep) ; + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, + req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (request == CY_RQT_GET_STALL) + return my_handle_response_get_stall(dev_p, + req_p, reply_p, state_p) ; + else + return my_handle_response_get_nak(dev_p, + req_p, reply_p, state_p) ; + + } else { + cy_as_funct_c_b_type type ; + + if (request == CY_RQT_GET_STALL) + type = CY_FUNCT_CB_USB_GETSTALL ; + else + type = CY_FUNCT_CB_USB_GETNAK ; + + ret = cy_as_misc_send_request(dev_p, cb, client, type, + state_p, dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_set_nak(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate direction + * bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_count > 0) + return CY_AS_ERROR_NOT_VALID_IN_MTP ; + + return cy_as_usb_nak_stall_request(handle, ep, + CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client) ; +} + + +cy_as_return_status_t +cy_as_usb_clear_nak(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate + * direction bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_count > 0) + return CY_AS_ERROR_NOT_VALID_IN_MTP ; + + return cy_as_usb_nak_stall_request(handle, ep, + CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client) ; +} + +cy_as_return_status_t +cy_as_usb_get_nak(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_bool *nak_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate + * direction bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_count > 0) + return CY_AS_ERROR_NOT_VALID_IN_MTP ; + + return cy_as_usb_get_nak_stall(handle, ep, + CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK, + nak_p, cb, client) ; +} + + +cy_as_return_status_t +cy_as_usb_set_stall(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate + * direction bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_turbo_active) + return CY_AS_ERROR_NOT_VALID_DURING_MTP ; + + return cy_as_usb_nak_stall_request(handle, ep, + CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client) ; +} + +cy_as_return_status_t +cy_as_usb_clear_stall(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate + * direction bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_turbo_active) + return CY_AS_ERROR_NOT_VALID_DURING_MTP ; + + return cy_as_usb_nak_stall_request(handle, ep, + CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client) ; +} + +cy_as_return_status_t +cy_as_usb_get_stall(cy_as_device_handle handle, + cy_as_end_point_number_t ep, + cy_bool *stall_p, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + /* + * we send the firmware the EP# with the appropriate + * direction bit, regardless of what the user gave us. + */ + ep &= 0x0f ; + if (dev_p->usb_config[ep].dir == cy_as_usb_in) + ep |= 0x80 ; + + if (dev_p->mtp_turbo_active) + return CY_AS_ERROR_NOT_VALID_DURING_MTP ; + + return cy_as_usb_get_nak_stall(handle, ep, + CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client) ; +} + +cy_as_return_status_t +cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if (cy_as_device_is_in_callback(dev_p)) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + if (dev_p->usb_last_event != cy_as_event_usb_suspend) + return CY_AS_ERROR_NOT_IN_SUSPEND ; + + req_p = cy_as_ll_create_request(dev_p, + CY_RQT_USB_REMOTE_WAKEUP, CY_RQT_USB_RQT_CONTEXT, 0) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, 0, + dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, + reply_p, cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle, + uint32_t wr_sectors, + uint32_t rd_sectors, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + if ((cb == 0) && (cy_as_device_is_in_callback(dev_p))) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + /* Check if the firmware version supports this feature. */ + if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] == + (1 << cy_as_media_nand))) + return CY_AS_ERROR_NOT_SUPPORTED ; + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_USB_STORAGE_MONITOR, + CY_RQT_USB_RQT_CONTEXT, 4) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Set the read and write count parameters into + * the request structure. */ + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((wr_sectors >> 16) & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 1, + (uint16_t)(wr_sectors & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 2, + (uint16_t)((rd_sectors >> 16) & 0xFFFF)) ; + cy_as_ll_request_response__set_word(req_p, 3, + (uint16_t)(rd_sectors & 0xFFFF)) ; + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, 0, + dev_p->func_cbs_usb, CY_AS_REQUEST_RESPONSE_EX, + req_p, reply_p, cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +cy_as_return_status_t +cy_as_usb_select_m_s_partitions( + cy_as_device_handle handle, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_usb_m_s_type_t type, + cy_as_function_callback cb, + uint32_t client) +{ + cy_as_return_status_t ret ; + cy_as_ll_request_response *req_p , *reply_p ; + uint16_t val ; + + cy_as_device *dev_p = (cy_as_device *)handle ; + if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) + return CY_AS_ERROR_INVALID_HANDLE ; + + ret = is_usb_active(dev_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + return ret ; + + /* This API has to be made before SetEnumConfig is called. */ + if (dev_p->usb_config[0].enabled) + return CY_AS_ERROR_INVALID_CALL_SEQUENCE ; + + if ((cb == 0) && (cy_as_device_is_in_callback(dev_p))) + return CY_AS_ERROR_INVALID_IN_CALLBACK ; + + req_p = cy_as_ll_create_request(dev_p, CY_RQT_MS_PARTITION_SELECT, + CY_RQT_USB_RQT_CONTEXT, 2) ; + if (req_p == 0) + return CY_AS_ERROR_OUT_OF_MEMORY ; + + /* A single status word response type */ + reply_p = cy_as_ll_create_response(dev_p, 1) ; + if (reply_p == 0) { + cy_as_ll_destroy_request(dev_p, req_p) ; + return CY_AS_ERROR_OUT_OF_MEMORY ; + } + + /* Set the read and write count parameters into + * the request structure. */ + cy_as_ll_request_response__set_word(req_p, 0, + (uint16_t)((bus << 8) | device)) ; + + val = 0 ; + if ((type == cy_as_usb_m_s_unit0) || (type == cy_as_usb_m_s_both)) + val |= 1 ; + if ((type == cy_as_usb_m_s_unit1) || (type == cy_as_usb_m_s_both)) + val |= (1 << 8) ; + + cy_as_ll_request_response__set_word(req_p, 1, val) ; + + if (cb == 0) { + ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p) ; + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + + if (cy_as_ll_request_response__get_code(reply_p) == + CY_RESP_SUCCESS_FAILURE) + ret = cy_as_ll_request_response__get_word(reply_p, 0) ; + else + ret = CY_AS_ERROR_INVALID_RESPONSE ; + } else { + ret = cy_as_misc_send_request(dev_p, cb, client, + CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_usb, + CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p, + cy_as_usb_func_callback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + goto destroy ; + return ret ; + } + +destroy: + cy_as_ll_destroy_request(dev_p, req_p) ; + cy_as_ll_destroy_response(dev_p, reply_p) ; + + return ret ; +} + +static void +cy_as_usb_func_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_ll_request_response *rqt, + cy_as_ll_request_response *resp, + cy_as_return_status_t stat) +{ + cy_as_usb_func_c_b_node* node = (cy_as_usb_func_c_b_node *) + dev_p->usb_func_cbs->head_p ; + cy_as_func_c_b_node* fnode = (cy_as_func_c_b_node *) + dev_p->func_cbs_usb->head_p ; + cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS ; + + cy_as_device_handle h = (cy_as_device_handle)dev_p ; + cy_bool delayed_ack = (rqt->flags & CY_AS_REQUEST_RESPONSE_DELAY_ACK) + == CY_AS_REQUEST_RESPONSE_DELAY_ACK; + cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) + == CY_AS_REQUEST_RESPONSE_EX ; + cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) + == CY_AS_REQUEST_RESPONSE_MS ; + uint8_t code ; + uint8_t ep, state ; + + if (!ex_request && !ms_request) { + cy_as_hal_assert(dev_p->usb_func_cbs->count != 0) ; + cy_as_hal_assert(dev_p->usb_func_cbs->type == + CYAS_USB_FUNC_CB) ; + } else { + cy_as_hal_assert(dev_p->func_cbs_usb->count != 0) ; + cy_as_hal_assert(dev_p->func_cbs_usb->type == CYAS_FUNC_CB) ; + } + + (void)context ; + + /* The Handlers are responsible for Deleting the rqt and resp when + * they are finished + */ + code = cy_as_ll_request_response__get_code(rqt) ; + switch (code) { + case CY_RQT_START_USB: + ret = my_handle_response_usb_start(dev_p, rqt, resp, stat) ; + break ; + case CY_RQT_STOP_USB: + ret = my_handle_response_usb_stop(dev_p, rqt, resp, stat) ; + break ; + case CY_RQT_SET_CONNECT_STATE: + if (!cy_as_ll_request_response__get_word(rqt, 0)) + ret = my_handle_response_disconnect( + dev_p, rqt, resp, stat) ; + else + ret = my_handle_response_connect( + dev_p, rqt, resp, stat) ; + break ; + case CY_RQT_GET_CONNECT_STATE: + break ; + case CY_RQT_SET_USB_CONFIG: + ret = my_handle_response_set_enum_config(dev_p, rqt, resp) ; + break ; + case CY_RQT_GET_USB_CONFIG: + cy_as_hal_assert(fnode->data != 0) ; + ret = my_handle_response_get_enum_config(dev_p, + rqt, resp, fnode->data) ; + break ; + case CY_RQT_STALL_ENDPOINT: + ep = (uint8_t)cy_as_ll_request_response__get_word(rqt, 0) ; + state = (uint8_t)cy_as_ll_request_response__get_word(rqt, 1) ; + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + if ((ret == CY_AS_ERROR_SUCCESS) && (ep > 1) && (state != 0) + && (dev_p->usb_config[ep].dir == cy_as_usb_out)) + cy_as_usb_flush_logical_e_p(dev_p, ep) ; + break ; + case CY_RQT_GET_STALL: + cy_as_hal_assert(fnode->data != 0) ; + ret = my_handle_response_get_stall(dev_p, + rqt, resp, (cy_bool *)fnode->data) ; + break ; + case CY_RQT_SET_DESCRIPTOR: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_GET_DESCRIPTOR: + cy_as_hal_assert(fnode->data != 0) ; + ret = my_handle_response_get_descriptor(dev_p, + rqt, resp, (cy_as_get_descriptor_data *)fnode->data) ; + break; + case CY_RQT_SET_USB_CONFIG_REGISTERS: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + if (ret == CY_AS_ERROR_SUCCESS) + ret = cy_as_usb_setup_dma(dev_p) ; + break ; + case CY_RQT_ENDPOINT_SET_NAK: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_GET_ENDPOINT_NAK: + cy_as_hal_assert(fnode->data != 0) ; + ret = my_handle_response_get_nak(dev_p, + rqt, resp, (cy_bool *)fnode->data) ; + break ; + case CY_RQT_ACK_SETUP_PACKET: + break ; + case CY_RQT_USB_REMOTE_WAKEUP: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_CLEAR_DESCRIPTORS: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_USB_STORAGE_MONITOR: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + case CY_RQT_MS_PARTITION_SELECT: + ret = my_handle_response_no_data(dev_p, rqt, resp) ; + break ; + default: + ret = CY_AS_ERROR_INVALID_RESPONSE ; + cy_as_hal_assert(cy_false) ; + break ; + } + + /* + * if the low level layer returns a direct error, use + * the corresponding error code. if not, use the error + * code based on the response from firmware. + */ + if (stat == CY_AS_ERROR_SUCCESS) + stat = ret ; + + if (ex_request || ms_request) { + fnode->cb_p((cy_as_device_handle)dev_p, stat, + fnode->client_data, fnode->data_type, fnode->data) ; + cy_as_remove_c_b_node(dev_p->func_cbs_usb) ; + } else { + node->cb_p((cy_as_device_handle)dev_p, stat, + node->client_data) ; + cy_as_remove_c_b_node(dev_p->usb_func_cbs) ; + } + + if (delayed_ack) { + cy_as_hal_assert(cy_as_device_is_ack_delayed(dev_p)) ; + cy_as_device_rem_ack_delayed(dev_p) ; + + /* + * send the ACK if required. + */ + if (!cy_as_device_is_ack_delayed(dev_p)) + cy_as_usb_ack_setup_packet(h, + usb_ack_callback, 0) ; + } +} + + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c new file mode 100644 index 000000000000..a0759ee76249 --- /dev/null +++ b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c @@ -0,0 +1,2450 @@ +/* Cypress WestBridge OMAP3430 Kernel Hal source file (cyashalomap_kernel.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* include seems broken moving for patch submission + * #include + * #include + * #include + * #include + * #include + * #include + * #include + * #include + * #include + */ +#include +#include +#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h" +#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h" +#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h" +#include "../../../include/linux/westbridge/cyaserr.h" +#include "../../../include/linux/westbridge/cyasregs.h" +#include "../../../include/linux/westbridge/cyasdma.h" +#include "../../../include/linux/westbridge/cyasintr.h" + +#define HAL_REV "1.1.0" + +/* + * uncomment to enable 16bit pnand interface + */ +#define PNAND_16BIT_MODE + +/* + * selects one of 3 versions of pnand_lbd_read() + * PNAND_LBD_READ_NO_PFE - original 8/16 bit code + * reads through the gpmc CONTROLLER REGISTERS + * ENABLE_GPMC_PF_ENGINE - USES GPMC PFE FIFO reads, in 8 bit mode, + * same speed as the above + * PFE_LBD_READ_V2 - slightly diffrenet, performance same as above + */ +#define PNAND_LBD_READ_NO_PFE +/* #define ENABLE_GPMC_PF_ENGINE */ +/* #define PFE_LBD_READ_V2 */ + +/* + * westbrige astoria ISR options to limit number of + * back to back DMA transfers per ISR interrupt + */ +#define MAX_DRQ_LOOPS_IN_ISR 4 + +/* + * debug prints enabling + *#define DBGPRN_ENABLED + *#define DBGPRN_DMA_SETUP_RD + *#define DBGPRN_DMA_SETUP_WR + */ + + +/* + * For performance reasons, we handle storage endpoint transfers upto 4 KB + * within the HAL itself. + */ + #define CYASSTORAGE_WRITE_EP_NUM (4) + #define CYASSTORAGE_READ_EP_NUM (8) + +/* + * size of DMA packet HAL can accept from Storage API + * HAL will fragment it into smaller chunks that the P port can accept + */ +#define CYASSTORAGE_MAX_XFER_SIZE (2*32768) + +/* + * P port MAX DMA packet size according to interface/ep configurartion + */ +#define HAL_DMA_PKT_SZ 512 + +#define is_storage_e_p(ep) (((ep) == 2) || ((ep) == 4) || \ + ((ep) == 6) || ((ep) == 8)) + +/* + * persistant, stores current GPMC interface cfg mode + */ +static uint8_t pnand_16bit; + +/* + * keep processing new WB DRQ in ISR untill all handled (performance feature) + */ +#define PROCESS_MULTIPLE_DRQ_IN_ISR (1) + + +/* + * ASTORIA PNAND IF COMMANDS, CASDO - READ, CASDI - WRITE + */ +#define CASDO 0x05 +#define CASDI 0x85 +#define RDPAGE_B1 0x00 +#define RDPAGE_B2 0x30 +#define PGMPAGE_B1 0x80 +#define PGMPAGE_B2 0x10 + +/* + * The type of DMA operation, per endpoint + */ +typedef enum cy_as_hal_dma_type { + cy_as_hal_read, + cy_as_hal_write, + cy_as_hal_none +} cy_as_hal_dma_type ; + + +/* + * SG list halpers defined in scaterlist.h +#define sg_is_chain(sg) ((sg)->page_link & 0x01) +#define sg_is_last(sg) ((sg)->page_link & 0x02) +#define sg_chain_ptr(sg) \ + ((struct scatterlist *) ((sg)->page_link & ~0x03)) +*/ +typedef struct cy_as_hal_endpoint_dma { + cy_bool buffer_valid ; + uint8_t *data_p ; + uint32_t size ; + /* + * sg_list_enabled - if true use, r/w DMA transfers use sg list, + * FALSE use pointer to a buffer + * sg_p - pointer to the owner's sg list, of there is such + * (like blockdriver) + * dma_xfer_sz - size of the next dma xfer on P port + * seg_xfer_cnt - counts xfered bytes for in current sg_list + * memory segment + * req_xfer_cnt - total number of bytes transfered so far in + * current request + * req_length - total request length + */ + bool sg_list_enabled; + struct scatterlist *sg_p ; + uint16_t dma_xfer_sz; + uint32_t seg_xfer_cnt; + uint16_t req_xfer_cnt; + uint16_t req_length; + cy_as_hal_dma_type type ; + cy_bool pending ; +} cy_as_hal_endpoint_dma ; + +/* + * The list of OMAP devices (should be one) + */ +static cy_as_omap_dev_kernel *m_omap_list_p; + +/* + * The callback to call after DMA operations are complete + */ +static cy_as_hal_dma_complete_callback callback; + +/* + * Pending data size for the endpoints + */ +static cy_as_hal_endpoint_dma end_points[16] ; + +/* + * Forward declaration + */ +static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p); + +static uint16_t intr_sequence_num; +static uint8_t intr__enable; +spinlock_t int_lock ; + +static u32 iomux_vma; +static u32 csa_phy; + +/* + * gpmc I/O registers VMA + */ +static u32 gpmc_base ; + +/* + * gpmc data VMA associated with CS4 (ASTORIA CS on GPMC) + */ +static u32 gpmc_data_vma; +static u32 ndata_reg_vma; +static u32 ncmd_reg_vma; +static u32 naddr_reg_vma; + +/* + * fwd declarations + */ +static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff); +static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff); +static inline u16 __attribute__((always_inline)) + ast_p_nand_casdo_read(u8 reg_addr8); +static inline void __attribute__((always_inline)) + ast_p_nand_casdi_write(u8 reg_addr8, u16 data); + +/* + * prints given number of omap registers + */ +static void cy_as_hal_print_omap_regs(char *name_prefix, + u8 name_base, u32 virt_base, u16 count) +{ + u32 reg_val, reg_addr; + u16 i; + cy_as_hal_print_message(KERN_INFO "\n"); + for (i = 0; i < count; i++) { + + reg_addr = virt_base + (i*4); + /* use virtual addresses here*/ + reg_val = __raw_readl(reg_addr); + cy_as_hal_print_message(KERN_INFO "%s_%d[%8.8x]=%8.8x\n", + name_prefix, name_base+i, + reg_addr, reg_val); + } +} + +/* + * setMUX function for a pad + additional pad flags + */ +static u16 omap_cfg_reg_L(u32 pad_func_index) +{ + static u8 sanity_check = 1; + + u32 reg_vma; + u16 cur_val, wr_val, rdback_val; + + /* + * do sanity check on the omap_mux_pin_cfg[] table + */ + cy_as_hal_print_message(KERN_INFO" OMAP pins user_pad cfg "); + if (sanity_check) { + if ((omap_mux_pin_cfg[END_OF_TABLE].name[0] == 'E') && + (omap_mux_pin_cfg[END_OF_TABLE].name[1] == 'N') && + (omap_mux_pin_cfg[END_OF_TABLE].name[2] == 'D')) { + + cy_as_hal_print_message(KERN_INFO + "table is good.\n"); + } else { + cy_as_hal_print_message(KERN_WARNING + "table is bad, fix it"); + } + /* + * do it only once + */ + sanity_check = 0; + } + + /* + * get virtual address to the PADCNF_REG + */ + reg_vma = (u32)iomux_vma + omap_mux_pin_cfg[pad_func_index].offset; + + /* + * add additional USER PU/PD/EN flags + */ + wr_val = omap_mux_pin_cfg[pad_func_index].mux_val; + cur_val = IORD16(reg_vma); + + /* + * PADCFG regs 16 bit long, packed into 32 bit regs, + * can also be accessed as u16 + */ + IOWR16(reg_vma, wr_val); + rdback_val = IORD16(reg_vma); + + /* + * in case if the caller wants to save the old value + */ + return wr_val; +} + +#define BLKSZ_4K 0x1000 + +/* + * switch GPMC DATA bus mode + */ +void cy_as_hal_gpmc_enable_16bit_bus(bool dbus16_enabled) +{ + uint32_t tmp32; + + /* + * disable gpmc CS4 operation 1st + */ + tmp32 = gpmc_cs_read_reg(AST_GPMC_CS, + GPMC_CS_CONFIG7) & ~GPMC_CONFIG7_CSVALID; + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32); + + /* + * GPMC NAND data bus can be 8 or 16 bit wide + */ + if (dbus16_enabled) { + DBGPRN("enabling 16 bit bus\n"); + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1, + (GPMC_CONFIG1_DEVICETYPE(2) | + GPMC_CONFIG1_WAIT_PIN_SEL(2) | + GPMC_CONFIG1_DEVICESIZE_16) + ); + } else { + DBGPRN(KERN_INFO "enabling 8 bit bus\n"); + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1, + (GPMC_CONFIG1_DEVICETYPE(2) | + GPMC_CONFIG1_WAIT_PIN_SEL(2)) + ); + } + + /* + * re-enable astoria CS operation on GPMC + */ + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, + (tmp32 | GPMC_CONFIG7_CSVALID)); + + /* + *remember the state + */ + pnand_16bit = dbus16_enabled; +} + +static int cy_as_hal_gpmc_init(void) +{ + u32 tmp32; + int err; + struct gpmc_timings timings; + /* + * get GPMC i/o registers base(already been i/o mapped + * in kernel, no need for separate i/o remap) + */ + gpmc_base = phys_to_virt(OMAP34XX_GPMC_BASE); + DBGPRN(KERN_INFO "kernel has gpmc_base=%x , val@ the base=%x", + gpmc_base, __raw_readl(gpmc_base) + ); + + /* + * these are globals are full VMAs of the gpmc_base above + */ + ncmd_reg_vma = GPMC_VMA(GPMC_NAND_CMD); + naddr_reg_vma = GPMC_VMA(GPMC_NAND_ADDR); + ndata_reg_vma = GPMC_VMA(GPMC_NAND_DATA); + + /* + * request GPMC CS for ASTORIA request + */ + if (gpmc_cs_request(AST_GPMC_CS, SZ_16M, (void *)&csa_phy) < 0) { + cy_as_hal_print_message(KERN_ERR "error failed to request" + "ncs4 for ASTORIA\n"); + return -1; + } else { + DBGPRN(KERN_INFO "got phy_addr:%x for " + "GPMC CS%d GPMC_CFGREG7[CS4]\n", + csa_phy, AST_GPMC_CS); + } + + /* + * request VM region for 4K addr space for chip select 4 phy address + * technically we don't need it for NAND devices, but do it anyway + * so that data read/write bus cycle can be triggered by reading + * or writing this mem region + */ + if (!request_mem_region(csa_phy, BLKSZ_4K, "AST_OMAP_HAL")) { + err = -EBUSY; + cy_as_hal_print_message(KERN_ERR "error MEM region " + "request for phy_addr:%x failed\n", + csa_phy); + goto out_free_cs; + } + + /* + * REMAP mem region associated with our CS + */ + gpmc_data_vma = (u32)ioremap_nocache(csa_phy, BLKSZ_4K); + if (!gpmc_data_vma) { + err = -ENOMEM; + cy_as_hal_print_message(KERN_ERR "error- ioremap()" + "for phy_addr:%x failed", csa_phy); + + goto out_release_mem_region; + } + cy_as_hal_print_message(KERN_INFO "ioremap(%x) returned vma=%x\n", + csa_phy, gpmc_data_vma); + + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1, + (GPMC_CONFIG1_DEVICETYPE(2) | + GPMC_CONFIG1_WAIT_PIN_SEL(2))); + + memset(&timings, 0, sizeof(timings)); + + /* cs timing */ + timings.cs_on = WB_GPMC_CS_t_o_n; + timings.cs_wr_off = WB_GPMC_BUSCYC_t; + timings.cs_rd_off = WB_GPMC_BUSCYC_t; + + /* adv timing */ + timings.adv_on = WB_GPMC_ADV_t_o_n; + timings.adv_rd_off = WB_GPMC_BUSCYC_t; + timings.adv_wr_off = WB_GPMC_BUSCYC_t; + + /* oe timing */ + timings.oe_on = WB_GPMC_OE_t_o_n; + timings.oe_off = WB_GPMC_OE_t_o_f_f; + timings.access = WB_GPMC_RD_t_a_c_c; + timings.rd_cycle = WB_GPMC_BUSCYC_t; + + /* we timing */ + timings.we_on = WB_GPMC_WE_t_o_n; + timings.we_off = WB_GPMC_WE_t_o_f_f; + timings.wr_access = WB_GPMC_WR_t_a_c_c; + timings.wr_cycle = WB_GPMC_BUSCYC_t; + + timings.page_burst_access = WB_GPMC_BUSCYC_t; + timings.wr_data_mux_bus = WB_GPMC_BUSCYC_t; + gpmc_cs_set_timings(AST_GPMC_CS, &timings); + + cy_as_hal_print_omap_regs("GPMC_CONFIG", 1, + GPMC_VMA(GPMC_CFG_REG(1, AST_GPMC_CS)), 7); + + /* + * DISABLE cs4, NOTE GPMC REG7 is already configured + * at this point by gpmc_cs_request + */ + tmp32 = gpmc_cs_read_reg(AST_GPMC_CS, GPMC_CS_CONFIG7) & + ~GPMC_CONFIG7_CSVALID; + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32); + + /* + * PROGRAM chip select Region, (see OMAP3430 TRM PAGE 1088) + */ + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, + (AS_CS_MASK | AS_CS_BADDR)); + + /* + * by default configure GPMC into 8 bit mode + * (to match astoria default mode) + */ + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1, + (GPMC_CONFIG1_DEVICETYPE(2) | + GPMC_CONFIG1_WAIT_PIN_SEL(2))); + + /* + * ENABLE astoria cs operation on GPMC + */ + gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, + (tmp32 | GPMC_CONFIG7_CSVALID)); + + /* + * No method currently exists to write this register through GPMC APIs + * need to change WAIT2 polarity + */ + tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG)); + tmp32 = tmp32 | NAND_FORCE_POSTED_WRITE_B | 0x40; + IOWR32(GPMC_VMA(GPMC_CONFIG_REG), tmp32); + + tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG)); + cy_as_hal_print_message("GPMC_CONFIG_REG=0x%x\n", tmp32); + + return 0; + +out_release_mem_region: + release_mem_region(csa_phy, BLKSZ_4K); + +out_free_cs: + gpmc_cs_free(AST_GPMC_CS); + + return err; +} + +/* + * west bridge astoria ISR (Interrupt handler) + */ +static irqreturn_t cy_astoria_int_handler(int irq, + void *dev_id, struct pt_regs *regs) +{ + cy_as_omap_dev_kernel *dev_p; + uint16_t read_val = 0 ; + uint16_t mask_val = 0 ; + + /* + * debug stuff, counts number of loops per one intr trigger + */ + uint16_t drq_loop_cnt = 0; + uint8_t irq_pin; + /* + * flags to watch + */ + const uint16_t sentinel = (CY_AS_MEM_P0_INTR_REG_MCUINT | + CY_AS_MEM_P0_INTR_REG_MBINT | + CY_AS_MEM_P0_INTR_REG_PMINT | + CY_AS_MEM_P0_INTR_REG_PLLLOCKINT); + + /* + * sample IRQ pin level (just for statistics) + */ + irq_pin = __gpio_get_value(AST_INT); + + /* + * this one just for debugging + */ + intr_sequence_num++ ; + + /* + * astoria device handle + */ + dev_p = dev_id; + + /* + * read Astoria intr register + */ + read_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INTR_REG) ; + + /* + * save current mask value + */ + mask_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INT_MASK_REG) ; + + DBGPRN("<1>HAL__intr__enter:_seq:%d, P0_INTR_REG:%x\n", + intr_sequence_num, read_val); + + /* + * Disable WB interrupt signal generation while we are in ISR + */ + cy_as_hal_write_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INT_MASK_REG, 0x0000) ; + + /* + * this is a DRQ Interrupt + */ + if (read_val & CY_AS_MEM_P0_INTR_REG_DRQINT) { + + do { + /* + * handle DRQ interrupt + */ + drq_loop_cnt++; + + cy_handle_d_r_q_interrupt(dev_p) ; + + /* + * spending to much time in ISR may impact + * average system performance + */ + if (drq_loop_cnt >= MAX_DRQ_LOOPS_IN_ISR) + break; + + /* + * Keep processing if there is another DRQ int flag + */ + } while (cy_as_hal_read_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INTR_REG) & + CY_AS_MEM_P0_INTR_REG_DRQINT); + } + + if (read_val & sentinel) + cy_as_intr_service_interrupt((cy_as_hal_device_tag)dev_p) ; + + DBGPRN("<1>_hal:_intr__exit seq:%d, mask=%4.4x," + "int_pin:%d DRQ_jobs:%d\n", + intr_sequence_num, + mask_val, + irq_pin, + drq_loop_cnt); + + /* + * re-enable WB hw interrupts + */ + cy_as_hal_write_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INT_MASK_REG, mask_val) ; + + return IRQ_HANDLED ; +} + +static int cy_as_hal_configure_interrupts(void *dev_p) +{ + int result; + int irq_pin = AST_INT; + + set_irq_type(OMAP_GPIO_IRQ(irq_pin), IRQ_TYPE_LEVEL_LOW); + + /* + * for shared IRQS must provide non NULL device ptr + * othervise the int won't register + * */ + result = request_irq(OMAP_GPIO_IRQ(irq_pin), + (irq_handler_t)cy_astoria_int_handler, + IRQF_SHARED, "AST_INT#", dev_p); + + if (result == 0) { + /* + * OMAP_GPIO_IRQ(irq_pin) - omap logical IRQ number + * assigned to this interrupt + * OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1) - print status + * of AST_INT GPIO IRQ_ENABLE FLAG + */ + cy_as_hal_print_message(KERN_INFO"AST_INT omap_pin:" + "%d assigned IRQ #%d IRQEN1=%d\n", + irq_pin, + OMAP_GPIO_IRQ(irq_pin), + OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1) + ); + } else { + cy_as_hal_print_message("cyasomaphal: interrupt " + "failed to register\n"); + gpio_free(irq_pin); + cy_as_hal_print_message(KERN_WARNING + "ASTORIA: can't get assigned IRQ" + "%i for INT#\n", OMAP_GPIO_IRQ(irq_pin)); + } + + return result; +} + +/* + * initialize OMAP pads/pins to user defined functions + */ +static void cy_as_hal_init_user_pads(user_pad_cfg_t *pad_cfg_tab) +{ + /* + * browse through the table an dinitiaze the pins + */ + u32 in_level = 0; + u16 tmp16, mux_val; + + while (pad_cfg_tab->name != NULL) { + + if (gpio_request(pad_cfg_tab->pin_num, NULL) == 0) { + + pad_cfg_tab->valid = 1; + mux_val = omap_cfg_reg_L(pad_cfg_tab->mux_func); + + /* + * always set drv level before changing out direction + */ + __gpio_set_value(pad_cfg_tab->pin_num, + pad_cfg_tab->drv); + + /* + * "0" - OUT, "1", input omap_set_gpio_direction + * (pad_cfg_tab->pin_num, pad_cfg_tab->dir); + */ + if (pad_cfg_tab->dir) + gpio_direction_input(pad_cfg_tab->pin_num); + else + gpio_direction_output(pad_cfg_tab->pin_num, + pad_cfg_tab->drv); + + /* sample the pin */ + in_level = __gpio_get_value(pad_cfg_tab->pin_num); + + cy_as_hal_print_message(KERN_INFO "configured %s to " + "OMAP pad_%d, DIR=%d " + "DOUT=%d, DIN=%d\n", + pad_cfg_tab->name, + pad_cfg_tab->pin_num, + pad_cfg_tab->dir, + pad_cfg_tab->drv, + in_level + ); + } else { + /* + * get the pad_mux value to check on the pin_function + */ + cy_as_hal_print_message(KERN_INFO "couldn't cfg pin %d" + "for signal %s, its already taken\n", + pad_cfg_tab->pin_num, + pad_cfg_tab->name); + } + + tmp16 = *(u16 *)PADCFG_VMA + (omap_mux_pin_cfg[pad_cfg_tab->mux_func].offset); + + cy_as_hal_print_message(KERN_INFO "GPIO_%d(PAD_CFG=%x,OE=%d" + "DOUT=%d, DIN=%d IRQEN=%d)\n\n", + pad_cfg_tab->pin_num, tmp16, + OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_OE), + OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_OUT), + OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_IN), + OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_IRQENABLE1) + ); + + /* + * next pad_cfg deriptor + */ + pad_cfg_tab++; + } + + cy_as_hal_print_message(KERN_INFO"pads configured\n"); +} + + +/* + * release gpios taken by the module + */ +static void cy_as_hal_release_user_pads(user_pad_cfg_t *pad_cfg_tab) +{ + while (pad_cfg_tab->name != NULL) { + + if (pad_cfg_tab->valid) { + gpio_free(pad_cfg_tab->pin_num); + pad_cfg_tab->valid = 0; + cy_as_hal_print_message(KERN_INFO "GPIO_%d " + "released from %s\n", + pad_cfg_tab->pin_num, + pad_cfg_tab->name); + } else { + cy_as_hal_print_message(KERN_INFO "no release " + "for %s, GPIO_%d, wasn't acquired\n", + pad_cfg_tab->name, + pad_cfg_tab->pin_num); + } + pad_cfg_tab++; + } +} + +void cy_as_hal_config_c_s_mux(void) +{ + /* + * FORCE the GPMC CS4 pin (it is in use by the zoom system) + */ + omap_cfg_reg_L(T8_OMAP3430_GPMC_n_c_s4); +} +EXPORT_SYMBOL(cy_as_hal_config_c_s_mux); + +/* + * inits all omap h/w + */ +uint32_t cy_as_hal_processor_hw_init(void) +{ + int i, err; + + cy_as_hal_print_message(KERN_INFO "init OMAP3430 hw...\n"); + + iomux_vma = (u32)ioremap_nocache( + (u32)CTLPADCONF_BASE_ADDR, CTLPADCONF_SIZE); + cy_as_hal_print_message(KERN_INFO "PADCONF_VMA=%x val=%x\n", + iomux_vma, IORD32(iomux_vma)); + + /* + * remap gpio banks + */ + for (i = 0; i < 6; i++) { + gpio_vma_tab[i].virt_addr = (u32)ioremap_nocache( + gpio_vma_tab[i].phy_addr, + gpio_vma_tab[i].size); + + cy_as_hal_print_message(KERN_INFO "%s virt_addr=%x\n", + gpio_vma_tab[i].name, + (u32)gpio_vma_tab[i].virt_addr); + }; + + /* + * force OMAP_GPIO_126 to rleased state, + * will be configured to drive reset + */ + gpio_free(AST_RESET); + + /* + *same thing with AStoria CS pin + */ + gpio_free(AST_CS); + + /* + * initialize all the OMAP pads connected to astoria + */ + cy_as_hal_init_user_pads(user_pad_cfg); + + err = cy_as_hal_gpmc_init(); + if (err < 0) + cy_as_hal_print_message(KERN_INFO"gpmc init failed:%d", err); + + cy_as_hal_config_c_s_mux(); + + return gpmc_data_vma; +} +EXPORT_SYMBOL(cy_as_hal_processor_hw_init); + +void cy_as_hal_omap_hardware_deinit(cy_as_omap_dev_kernel *dev_p) +{ + /* + * free omap hw resources + */ + if (gpmc_data_vma != 0) + iounmap((void *)gpmc_data_vma); + + if (csa_phy != 0) + release_mem_region(csa_phy, BLKSZ_4K); + + gpmc_cs_free(AST_GPMC_CS); + + free_irq(OMAP_GPIO_IRQ(AST_INT), dev_p); + + cy_as_hal_release_user_pads(user_pad_cfg); +} + +/* + * These are the functions that are not part of the + * HAL layer, but are required to be called for this HAL + */ + +/* + * Called On AstDevice LKM exit + */ +int stop_o_m_a_p_kernel(const char *pgm, cy_as_hal_device_tag tag) +{ + cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag ; + + /* + * TODO: Need to disable WB interrupt handlere 1st + */ + if (0 == dev_p) + return 1 ; + + cy_as_hal_print_message("<1>_stopping OMAP34xx HAL layer object\n"); + if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG) { + cy_as_hal_print_message("<1>%s: %s: bad HAL tag\n", + pgm, __func__) ; + return 1 ; + } + + /* + * disable interrupt + */ + cy_as_hal_write_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INT_MASK_REG, 0x0000) ; + +#if 0 + if (dev_p->thread_flag == 0) { + dev_p->thread_flag = 1 ; + wait_for_completion(&dev_p->thread_complete) ; + cy_as_hal_print_message("cyasomaphal:" + "done cleaning thread\n"); + cy_as_hal_destroy_sleep_channel(&dev_p->thread_sc) ; + } +#endif + + cy_as_hal_omap_hardware_deinit(dev_p); + + /* + * Rearrange the list + */ + if (m_omap_list_p == dev_p) + m_omap_list_p = dev_p->m_next_p ; + + cy_as_hal_free(dev_p) ; + + cy_as_hal_print_message(KERN_INFO"OMAP_kernel_hal stopped\n"); + return 0; +} + +int omap_start_intr(cy_as_hal_device_tag tag) +{ + cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag ; + int ret = 0 ; + const uint16_t mask = CY_AS_MEM_P0_INTR_REG_DRQINT | + CY_AS_MEM_P0_INTR_REG_MBINT ; + + /* + * register for interrupts + */ + ret = cy_as_hal_configure_interrupts(dev_p) ; + + /* + * enable only MBox & DRQ interrupts for now + */ + cy_as_hal_write_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_INT_MASK_REG, mask) ; + + return 1 ; +} + +/* + * Below are the functions that communicate with the WestBridge device. + * These are system dependent and must be defined by the HAL layer + * for a given system. + */ + +/* + * GPMC NAND command+addr write phase + */ +static inline void nand_cmd_n_addr(u8 cmdb1, u16 col_addr, u32 row_addr) +{ + /* + * byte order on the bus + */ + u32 tmpa32 = ((row_addr << 16) | col_addr); + u8 RA2 = (u8)(row_addr >> 16); + + if (!pnand_16bit) { + /* + * GPMC PNAND 8bit BUS + */ + /* + * CMD1 + */ + IOWR8(ncmd_reg_vma, cmdb1); + + /* + *pnand bus: + */ + IOWR32(naddr_reg_vma, tmpa32); + + /* + * , always zero + */ + IOWR8(naddr_reg_vma, RA2); + + } else { + /* + * GPMC PNAND 16bit BUS , in 16 bit mode CMD + * and ADDR sent on [d7..d0] + */ + uint8_t CA0, CA1, RA0, RA1; + CA0 = tmpa32 & 0x000000ff; + CA1 = (tmpa32 >> 8) & 0x000000ff; + RA0 = (tmpa32 >> 16) & 0x000000ff; + RA1 = (tmpa32 >> 24) & 0x000000ff; + + /* + * can't use 32 bit writes here omap will not serialize + * them to lower half in16 bit mode + */ + + /* + *pnand bus: + */ + IOWR8(ncmd_reg_vma, cmdb1); + IOWR8(naddr_reg_vma, CA0); + IOWR8(naddr_reg_vma, CA1); + IOWR8(naddr_reg_vma, RA0); + IOWR8(naddr_reg_vma, RA1); + IOWR8(naddr_reg_vma, RA2); + } +} + +/* + * spin until r/b goes high + */ +inline int wait_rn_b_high(void) +{ + u32 w_spins = 0; + + /* + * TODO: note R/b may go low here, need to spin until high + * while (omap_get_gpio_datain(AST_RnB) == 0) { + * w_spins++; + * } + * if (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN) == 0) { + * + * while (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN) == 0) { + * w_spins++; + * } + * printk("<1>RnB=0!:%d\n",w_spins); + * } + */ + return w_spins; +} + +#ifdef ENABLE_GPMC_PF_ENGINE +/* #define PFE_READ_DEBUG + * PNAND block read with OMAP PFE enabled + * status: Not tested, NW, broken , etc + */ +static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff) +{ + uint16_t w32cnt; + uint32_t *ptr32; + uint8_t *ptr8; + uint8_t bytes_in_fifo; + + /* debug vars*/ +#ifdef PFE_READ_DEBUG + uint32_t loop_limit; + uint16_t bytes_read = 0; +#endif + + /* + * configure the prefetch engine + */ + uint32_t tmp32; + uint32_t pfe_status; + + /* + * DISABLE GPMC CS4 operation 1st, this is + * in case engine is be already disabled + */ + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x0); + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL); + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count); + +#ifdef PFE_READ_DEBUG + tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG1)); + if (tmp32 != GPMC_PREFETCH_CONFIG1_VAL) { + printk(KERN_INFO "<1> prefetch is CONFIG1 read val:%8.8x, != VAL written:%8.8x\n", + tmp32, GPMC_PREFETCH_CONFIG1_VAL); + tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS)); + printk(KERN_INFO "<1> GPMC_PREFETCH_STATUS : %8.8x\n", tmp32); + } + + /* + *sanity check 2 + */ + tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG2)); + if (tmp32 != (count)) + printk(KERN_INFO "<1> GPMC_PREFETCH_CONFIG2 read val:%d, " + "!= VAL written:%d\n", tmp32, count); +#endif + + /* + * ISSUE PNAND CMD+ADDR, note gpmc puts 32b words + * on the bus least sig. byte 1st + */ + nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr); + + IOWR8(ncmd_reg_vma, RDPAGE_B2); + + /* + * start the prefetch engine + */ + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1); + + ptr32 = buff; + + while (1) { + /* + * GPMC PFE service loop + */ + do { + /* + * spin until PFE fetched some + * PNAND bus words in the FIFO + */ + pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS)); + bytes_in_fifo = (pfe_status >> 24) & 0x7f; + } while (bytes_in_fifo == 0); + + /* whole 32 bit words in fifo */ + w32cnt = bytes_in_fifo >> 2; + +#if 0 + /* + *NOTE: FIFO_PTR indicates number of NAND bus words bytes + * already received in the FIFO and available to be read + * by DMA or MPU whether COUNTVAL indicates number of BUS + * words yet to be read from PNAND bus words + */ + printk(KERN_ERR "<1> got PF_STATUS:%8.8x FIFO_PTR:%d, COUNTVAL:%d, w32cnt:%d\n", + pfe_status, bytes_in_fifo, + (pfe_status & 0x3fff), w32cnt); +#endif + + while (w32cnt--) + *ptr32++ = IORD32(gpmc_data_vma); + + if ((pfe_status & 0x3fff) == 0) { + /* + * PFE acc angine done, there still may be data leftover + * in the FIFO re-read FIFO BYTE counter (check for + * leftovers from 32 bit read accesses above) + */ + bytes_in_fifo = (IORD32( + GPMC_VMA(GPMC_PREFETCH_STATUS)) >> 24) & 0x7f; + + /* + * NOTE we may still have one word left in the fifo + * read it out + */ + ptr8 = ptr32; + switch (bytes_in_fifo) { + + case 0: + /* + * nothing to do we already read the + * FIFO out with 32 bit accesses + */ + break; + case 1: + /* + * this only possible + * for 8 bit pNAND only + */ + *ptr8 = IORD8(gpmc_data_vma); + break; + + case 2: + /* + * this one can occur in either modes + */ + *(uint16_t *)ptr8 = IORD16(gpmc_data_vma); + break; + + case 3: + /* + * this only possible for 8 bit pNAND only + */ + *(uint16_t *)ptr8 = IORD16(gpmc_data_vma); + ptr8 += 2; + *ptr8 = IORD8(gpmc_data_vma); + break; + + case 4: + /* + * shouldn't happen, but has been seen + * in 8 bit mode + */ + *ptr32 = IORD32(gpmc_data_vma); + break; + + default: + printk(KERN_ERR"<1>_error: PFE FIFO bytes leftover is not read:%d\n", + bytes_in_fifo); + break; + } + /* + * read is completed, get out of the while(1) loop + */ + break; + } + } +} +#endif + +#ifdef PFE_LBD_READ_V2 +/* + * PFE engine assisted reads with the 64 byte blocks + */ +static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff) +{ + uint8_t rd_cnt; + uint32_t *ptr32; + uint8_t *ptr8; + uint16_t reminder; + uint32_t pfe_status; + + /* + * ISSUE PNAND CMD+ADDR + * note gpmc puts 32b words on the bus least sig. byte 1st + */ + nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr); + IOWR8(ncmd_reg_vma, RDPAGE_B2); + + /* + * setup PFE block + * count - OMAP number of bytes to access on pnand bus + */ + + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL); + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count); + IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1); + + ptr32 = buff; + + do { + pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS)) ; + rd_cnt = pfe_status >> (24+2); + + while (rd_cnt--) + *ptr32++ = IORD32(gpmc_data_vma); + + } while (pfe_status & 0x3fff); + + /* + * read out the leftover + */ + ptr8 = ptr32; + rd_cnt = (IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS)) >> 24) & 0x7f; + + while (rd_cnt--) + *ptr8++ = IORD8(gpmc_data_vma); +} +#endif + +#ifdef PNAND_LBD_READ_NO_PFE +/* + * Endpoint buffer read w/o OMAP GPMC Prefetch Engine + * the original working code, works at max speed for 8 bit xfers + * for 16 bit the bus diagram has gaps + */ +static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff) +{ + uint16_t w32cnt; + uint32_t *ptr32; + uint16_t *ptr16; + uint16_t remainder; + + DBGPRN("<1> %s(): NO_PFE\n", __func__); + + ptr32 = buff; + /* number of whole 32 bit words in the transfer */ + w32cnt = count >> 2; + + /* remainder, in bytes(0..3) */ + remainder = count & 03; + + /* + * note gpmc puts 32b words on the bus least sig. byte 1st + */ + nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr); + IOWR8(ncmd_reg_vma, RDPAGE_B2); + + /* + * read data by 32 bit chunks + */ + while (w32cnt--) + *ptr32++ = IORD32(ndata_reg_vma); + + /* + * now do the remainder(it can be 0, 1, 2 or 3) + * same code for both 8 & 16 bit bus + * do 1 or 2 MORE words + */ + ptr16 = (uint16_t *)ptr32; + + switch (remainder) { + case 1: + /* read one 16 bit word + * IN 8 BIT WE NEED TO READ even number of bytes + */ + case 2: + *ptr16 = IORD16(ndata_reg_vma); + break; + case 3: + /* + * for 3 bytes read 2 16 bit words + */ + *ptr16++ = IORD16(ndata_reg_vma); + *ptr16 = IORD16(ndata_reg_vma); + break; + default: + /* + * remainder is 0 + */ + break; + } +} +#endif + +/* + * uses LBD mode to write N bytes into astoria + * Status: Working, however there are 150ns idle + * timeafter every 2 (16 bit or 4(8 bit) bus cycles + */ +static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff) +{ + uint16_t w32cnt; + uint16_t remainder; + uint8_t *ptr8; + uint16_t *ptr16; + uint32_t *ptr32; + + remainder = count & 03; + w32cnt = count >> 2; + ptr32 = buff; + ptr8 = buff; + + /* + * send: CMDB1, CA0,CA1,RA0,RA1,RA2 + */ + nand_cmd_n_addr(PGMPAGE_B1, col_addr, row_addr); + + /* + * blast the data out in 32bit chunks + */ + while (w32cnt--) + IOWR32(ndata_reg_vma, *ptr32++); + + /* + * do the reminder if there is one + * same handling for both 8 & 16 bit pnand: mode + */ + ptr16 = (uint16_t *)ptr32; /* do 1 or 2 words */ + + switch (remainder) { + case 1: + /* + * read one 16 bit word + */ + case 2: + IOWR16(ndata_reg_vma, *ptr16); + break; + + case 3: + /* + * for 3 bytes read 2 16 bit words + */ + IOWR16(ndata_reg_vma, *ptr16++); + IOWR16(ndata_reg_vma, *ptr16); + break; + default: + /* + * reminder is 0 + */ + break; + } + /* + * finally issue a PGM cmd + */ + IOWR8(ncmd_reg_vma, PGMPAGE_B2); +} + +/* + * write Astoria register + */ +static inline void ast_p_nand_casdi_write(u8 reg_addr8, u16 data) +{ + unsigned long flags; + u16 addr16; + /* + * throw an error if called from multiple threads + */ + static atomic_t rdreg_usage_cnt = { 0 }; + + /* + * disable interrupts + */ + local_irq_save(flags); + + if (atomic_read(&rdreg_usage_cnt) != 0) { + cy_as_hal_print_message(KERN_ERR "cy_as_omap_hal:" + "* cy_as_hal_write_register usage:%d\n", + atomic_read(&rdreg_usage_cnt)); + } + + atomic_inc(&rdreg_usage_cnt); + + /* + * 2 flavors of GPMC -> PNAND access + */ + if (pnand_16bit) { + /* + * 16 BIT gpmc NAND mode + */ + + /* + * CMD1, CA1, CA2, + */ + IOWR8(ncmd_reg_vma, 0x85); + IOWR8(naddr_reg_vma, reg_addr8); + IOWR8(naddr_reg_vma, 0x0c); + + /* + * this should be sent on the 16 bit bus + */ + IOWR16(ndata_reg_vma, data); + } else { + /* + * 8 bit nand mode GPMC will automatically + * seriallize 16bit or 32 bit writes into + * 8 bit onesto the lower 8 bit in LE order + */ + addr16 = 0x0c00 | reg_addr8; + + /* + * CMD1, CA1, CA2, + */ + IOWR8(ncmd_reg_vma, 0x85); + IOWR16(naddr_reg_vma, addr16); + IOWR16(ndata_reg_vma, data); + } + + /* + * re-enable interrupts + */ + atomic_dec(&rdreg_usage_cnt); + local_irq_restore(flags); +} + + +/* + * read astoria register via pNAND interface + */ +static inline u16 ast_p_nand_casdo_read(u8 reg_addr8) +{ + u16 data; + u16 addr16; + unsigned long flags; + /* + * throw an error if called from multiple threads + */ + static atomic_t wrreg_usage_cnt = { 0 }; + + /* + * disable interrupts + */ + local_irq_save(flags); + + if (atomic_read(&wrreg_usage_cnt) != 0) { + /* + * if it gets here ( from other threads), this function needs + * need spin_lock_irq save() protection + */ + cy_as_hal_print_message(KERN_ERR"cy_as_omap_hal: " + "cy_as_hal_write_register usage:%d\n", + atomic_read(&wrreg_usage_cnt)); + } + atomic_inc(&wrreg_usage_cnt); + + /* + * 2 flavors of GPMC -> PNAND access + */ + if (pnand_16bit) { + /* + * 16 BIT gpmc NAND mode + * CMD1, CA1, CA2, + */ + + IOWR8(ncmd_reg_vma, 0x05); + IOWR8(naddr_reg_vma, reg_addr8); + IOWR8(naddr_reg_vma, 0x0c); + IOWR8(ncmd_reg_vma, 0x00E0); + + udelay(1); + + /* + * much faster through the gPMC Register space + */ + data = IORD16(ndata_reg_vma); + } else { + /* + * 8 BIT gpmc NAND mode + * CMD1, CA1, CA2, CMD2 + */ + addr16 = 0x0c00 | reg_addr8; + IOWR8(ncmd_reg_vma, 0x05); + IOWR16(naddr_reg_vma, addr16); + IOWR8(ncmd_reg_vma, 0xE0); + udelay(1); + data = IORD16(ndata_reg_vma); + } + + /* + * re-enable interrupts + */ + atomic_dec(&wrreg_usage_cnt); + local_irq_restore(flags); + + return data; +} + + +/* + * This function must be defined to write a register within the WestBridge + * device. The addr value is the address of the register to write with + * respect to the base address of the WestBridge device. + */ +void cy_as_hal_write_register( + cy_as_hal_device_tag tag, + uint16_t addr, uint16_t data) +{ + ast_p_nand_casdi_write((u8)addr, data); +} + +/* + * This function must be defined to read a register from the WestBridge + * device. The addr value is the address of the register to read with + * respect to the base address of the WestBridge device. + */ +uint16_t cy_as_hal_read_register(cy_as_hal_device_tag tag, uint16_t addr) +{ + uint16_t data = 0 ; + + /* + * READ ASTORIA REGISTER USING CASDO + */ + data = ast_p_nand_casdo_read((u8)addr); + + return data ; +} + +/* + * preps Ep pointers & data counters for next packet + * (fragment of the request) xfer returns true if + * there is a next transfer, and false if all bytes in + * current request have been xfered + */ +static inline bool prep_for_next_xfer(cy_as_hal_device_tag tag, uint8_t ep) +{ + + if (!end_points[ep].sg_list_enabled) { + /* + * no further transfers for non storage EPs + * (like EP2 during firmware download, done + * in 64 byte chunks) + */ + if (end_points[ep].req_xfer_cnt >= end_points[ep].req_length) { + DBGPRN("<1> %s():RQ sz:%d non-_sg EP:%d completed\n", + __func__, end_points[ep].req_length, ep); + + /* + * no more transfers, we are done with the request + */ + return false; + } + + /* + * calculate size of the next DMA xfer, corner + * case for non-storage EPs where transfer size + * is not egual N * HAL_DMA_PKT_SZ xfers + */ + if ((end_points[ep].req_length - end_points[ep].req_xfer_cnt) + >= HAL_DMA_PKT_SZ) { + end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ; + } else { + /* + * that would be the last chunk less + * than P-port max size + */ + end_points[ep].dma_xfer_sz = end_points[ep].req_length - + end_points[ep].req_xfer_cnt; + } + + return true; + } + + /* + * for SG_list assisted dma xfers + * are we done with current SG ? + */ + if (end_points[ep].seg_xfer_cnt == end_points[ep].sg_p->length) { + /* + * was it the Last SG segment on the list ? + */ + if (sg_is_last(end_points[ep].sg_p)) { + DBGPRN("<1> %s: EP:%d completed," + "%d bytes xfered\n", + __func__, + ep, + end_points[ep].req_xfer_cnt + ); + + return false; + } else { + /* + * There are more SG segments in current + * request's sg list setup new segment + */ + + end_points[ep].seg_xfer_cnt = 0; + end_points[ep].sg_p = sg_next(end_points[ep].sg_p); + /* set data pointer for next DMA sg transfer*/ + end_points[ep].data_p = sg_virt(end_points[ep].sg_p); + DBGPRN("<1> %s new SG:_va:%p\n\n", + __func__, end_points[ep].data_p); + } + + } + + /* + * for sg list xfers it will always be 512 or 1024 + */ + end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ; + + /* + * next transfer is required + */ + + return true; +} + +/* + * Astoria DMA read request, APP_CPU reads from WB ep buffer + */ +static void cy_service_e_p_dma_read_request( + cy_as_omap_dev_kernel *dev_p, uint8_t ep) +{ + cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p ; + uint16_t v, size; + void *dptr; + uint16_t col_addr = 0x0000; + uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep); + uint16_t ep_dma_reg = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2; + + /* + * get the XFER size frtom WB eP DMA REGISTER + */ + v = cy_as_hal_read_register(tag, ep_dma_reg); + + /* + * amount of data in EP buff in bytes + */ + size = v & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK; + + /* + * memory pointer for this DMA packet xfer (sub_segment) + */ + dptr = end_points[ep].data_p; + + DBGPRN("<1>HAL:_svc_dma_read on EP_%d sz:%d, intr_seq:%d, dptr:%p\n", + ep, + size, + intr_sequence_num, + dptr + ); + + cy_as_hal_assert(size != 0); + + if (size) { + /* + * the actual WB-->OMAP memory "soft" DMA xfer + */ + p_nand_lbd_read(col_addr, row_addr, size, dptr); + } + + /* + * clear DMAVALID bit indicating that the data has been read + */ + cy_as_hal_write_register(tag, ep_dma_reg, 0) ; + + end_points[ep].seg_xfer_cnt += size; + end_points[ep].req_xfer_cnt += size; + + /* + * pre-advance data pointer (if it's outside sg + * list it will be reset anyway + */ + end_points[ep].data_p += size; + + if (prep_for_next_xfer(tag, ep)) { + /* + * we have more data to read in this request, + * setup next dma packet due tell WB how much + * data we are going to xfer next + */ + v = end_points[ep].dma_xfer_sz/*HAL_DMA_PKT_SZ*/ | + CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL ; + cy_as_hal_write_register(tag, ep_dma_reg, v); + } else { + end_points[ep].pending = cy_false ; + end_points[ep].type = cy_as_hal_none ; + end_points[ep].buffer_valid = cy_false ; + + /* + * notify the API that we are done with rq on this EP + */ + if (callback) { + DBGPRN("<1>trigg rd_dma completion cb: xfer_sz:%d\n", + end_points[ep].req_xfer_cnt); + callback(tag, ep, + end_points[ep].req_xfer_cnt, + CY_AS_ERROR_SUCCESS); + } + } +} + +/* + * omap_cpu needs to transfer data to ASTORIA EP buffer + */ +static void cy_service_e_p_dma_write_request( + cy_as_omap_dev_kernel *dev_p, uint8_t ep) +{ + uint16_t addr; + uint16_t v = 0; + uint32_t size; + uint16_t col_addr = 0x0000; + uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep); + void *dptr; + + cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p ; + /* + * note: size here its the size of the dma transfer could be + * anything > 0 && < P_PORT packet size + */ + size = end_points[ep].dma_xfer_sz ; + dptr = end_points[ep].data_p ; + + /* + * perform the soft DMA transfer, soft in this case + */ + if (size) + p_nand_lbd_write(col_addr, row_addr, size, dptr); + + end_points[ep].seg_xfer_cnt += size; + end_points[ep].req_xfer_cnt += size; + /* + * pre-advance data pointer + * (if it's outside sg list it will be reset anyway) + */ + end_points[ep].data_p += size; + + /* + * now clear DMAVAL bit to indicate we are done + * transferring data and that the data can now be + * sent via USB to the USB host, sent to storage, + * or used internally. + */ + + addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ; + cy_as_hal_write_register(tag, addr, size) ; + + /* + * finally, tell the USB subsystem that the + * data is gone and we can accept the + * next request if one exists. + */ + if (prep_for_next_xfer(tag, ep)) { + /* + * There is more data to go. Re-init the WestBridge DMA side + */ + v = end_points[ep].dma_xfer_sz | + CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL ; + cy_as_hal_write_register(tag, addr, v) ; + } else { + + end_points[ep].pending = cy_false ; + end_points[ep].type = cy_as_hal_none ; + end_points[ep].buffer_valid = cy_false ; + + /* + * notify the API that we are done with rq on this EP + */ + if (callback) { + /* + * this callback will wake up the process that might be + * sleeping on the EP which data is being transferred + */ + callback(tag, ep, + end_points[ep].req_xfer_cnt, + CY_AS_ERROR_SUCCESS); + } + } +} + +/* + * HANDLE DRQINT from Astoria (called in AS_Intr context + */ +static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p) +{ + uint16_t v ; + static uint8_t service_ep = 2 ; + + /* + * We've got DRQ INT, read DRQ STATUS Register */ + v = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p, + CY_AS_MEM_P0_DRQ) ; + + if (v == 0) { +#ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("stray DRQ interrupt detected\n") ; +#endif + return; + } + + /* + * Now, pick a given DMA request to handle, for now, we just + * go round robin. Each bit position in the service_mask + * represents an endpoint from EP2 to EP15. We rotate through + * each of the endpoints to find one that needs to be serviced. + */ + while ((v & (1 << service_ep)) == 0) { + + if (service_ep == 15) + service_ep = 2 ; + else + service_ep++ ; + } + + if (end_points[service_ep].type == cy_as_hal_write) { + /* + * handle DMA WRITE REQUEST: app_cpu will + * write data into astoria EP buffer + */ + cy_service_e_p_dma_write_request(dev_p, service_ep) ; + } else if (end_points[service_ep].type == cy_as_hal_read) { + /* + * handle DMA READ REQUEST: cpu will + * read EP buffer from Astoria + */ + cy_service_e_p_dma_read_request(dev_p, service_ep) ; + } +#ifndef WESTBRIDGE_NDEBUG + else + cy_as_hal_print_message("cyashalomap:interrupt," + " w/o pending DMA job," + "-check DRQ_MASK logic\n") ; +#endif + + /* + * Now bump the EP ahead, so other endpoints get + * a shot before the one we just serviced + */ + if (end_points[service_ep].type == cy_as_hal_none) { + if (service_ep == 15) + service_ep = 2 ; + else + service_ep++ ; + } + +} + +void cy_as_hal_dma_cancel_request(cy_as_hal_device_tag tag, uint8_t ep) +{ + DBGPRN("cy_as_hal_dma_cancel_request on ep:%d", ep); + if (end_points[ep].pending) + cy_as_hal_write_register(tag, + CY_AS_MEM_P0_EP2_DMA_REG + ep - 2, 0); + + end_points[ep].buffer_valid = cy_false ; + end_points[ep].type = cy_as_hal_none; +} + +/* + * enables/disables SG list assisted DMA xfers for the given EP + * sg_list assisted XFERS can use physical addresses of mem pages in case if the + * xfer is performed by a h/w DMA controller rather then the CPU on P port + */ +void cy_as_hal_set_ep_dma_mode(uint8_t ep, bool sg_xfer_enabled) +{ + end_points[ep].sg_list_enabled = sg_xfer_enabled; + DBGPRN("<1> EP:%d sg_list assisted DMA mode set to = %d\n", + ep, end_points[ep].sg_list_enabled); +} +EXPORT_SYMBOL(cy_as_hal_set_ep_dma_mode); + +/* + * This function must be defined to transfer a block of data to + * the WestBridge device. This function can use the burst write + * (DMA) capabilities of WestBridge to do this, or it can just copy + * the data using writes. + */ +void cy_as_hal_dma_setup_write(cy_as_hal_device_tag tag, + uint8_t ep, void *buf, + uint32_t size, uint16_t maxsize) +{ + uint32_t addr = 0 ; + uint16_t v = 0; + + /* + * Note: "size" is the actual request size + * "maxsize" - is the P port fragment size + * No EP0 or EP1 traffic should get here + */ + cy_as_hal_assert(ep != 0 && ep != 1) ; + + /* + * If this asserts, we have an ordering problem. Another DMA request + * is coming down before the previous one has completed. + */ + cy_as_hal_assert(end_points[ep].buffer_valid == cy_false) ; + end_points[ep].buffer_valid = cy_true ; + end_points[ep].type = cy_as_hal_write ; + end_points[ep].pending = cy_true; + + /* + * total length of the request + */ + end_points[ep].req_length = size; + + if (size >= maxsize) { + /* + * set xfer size for very 1st DMA xfer operation + * port max packet size ( typically 512 or 1024) + */ + end_points[ep].dma_xfer_sz = maxsize; + } else { + /* + * smaller xfers for non-storage EPs + */ + end_points[ep].dma_xfer_sz = size; + } + + /* + * check the EP transfer mode uses sg_list rather then a memory buffer + * block devices pass it to the HAL, so the hAL could get to the real + * physical address for each segment and set up a DMA controller + * hardware ( if there is one) + */ + if (end_points[ep].sg_list_enabled) { + /* + * buf - pointer to the SG list + * data_p - data pointer to the 1st DMA segment + * seg_xfer_cnt - keeps track of N of bytes sent in current + * sg_list segment + * req_xfer_cnt - keeps track of the total N of bytes + * transferred for the request + */ + end_points[ep].sg_p = buf; + end_points[ep].data_p = sg_virt(end_points[ep].sg_p); + end_points[ep].seg_xfer_cnt = 0 ; + end_points[ep].req_xfer_cnt = 0; + +#ifdef DBGPRN_DMA_SETUP_WR + DBGPRN("cyasomaphal:%s: EP:%d, buf:%p, buf_va:%p," + "req_sz:%d, maxsz:%d\n", + __func__, + ep, + buf, + end_points[ep].data_p, + size, + maxsize); +#endif + + } else { + /* + * setup XFER for non sg_list assisted EPs + */ + + #ifdef DBGPRN_DMA_SETUP_WR + DBGPRN("<1>%s non storage or sz < 512:" + "EP:%d, sz:%d\n", __func__, ep, size); + #endif + + end_points[ep].sg_p = NULL; + + /* + * must be a VMA of a membuf in kernel space + */ + end_points[ep].data_p = buf; + + /* + * will keep track No of bytes xferred for the request + */ + end_points[ep].req_xfer_cnt = 0; + } + + /* + * Tell WB we are ready to send data on the given endpoint + */ + v = (end_points[ep].dma_xfer_sz & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) + | CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL ; + + addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ; + + cy_as_hal_write_register(tag, addr, v) ; +} + +/* + * This function must be defined to transfer a block of data from + * the WestBridge device. This function can use the burst read + * (DMA) capabilities of WestBridge to do this, or it can just + * copy the data using reads. + */ +void cy_as_hal_dma_setup_read(cy_as_hal_device_tag tag, + uint8_t ep, void *buf, + uint32_t size, uint16_t maxsize) +{ + uint32_t addr ; + uint16_t v ; + + /* + * Note: "size" is the actual request size + * "maxsize" - is the P port fragment size + * No EP0 or EP1 traffic should get here + */ + cy_as_hal_assert(ep != 0 && ep != 1) ; + + /* + * If this asserts, we have an ordering problem. + * Another DMA request is coming down before the + * previous one has completed. we should not get + * new requests if current is still in process + */ + + cy_as_hal_assert(end_points[ep].buffer_valid == cy_false); + + end_points[ep].buffer_valid = cy_true ; + end_points[ep].type = cy_as_hal_read ; + end_points[ep].pending = cy_true; + end_points[ep].req_xfer_cnt = 0; + end_points[ep].req_length = size; + + if (size >= maxsize) { + /* + * set xfer size for very 1st DMA xfer operation + * port max packet size ( typically 512 or 1024) + */ + end_points[ep].dma_xfer_sz = maxsize; + } else { + /* + * so that we could handle small xfers on in case + * of non-storage EPs + */ + end_points[ep].dma_xfer_sz = size; + } + + addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2 ; + + if (end_points[ep].sg_list_enabled) { + /* + * Handle sg-list assisted EPs + * seg_xfer_cnt - keeps track of N of sent packets + * buf - pointer to the SG list + * data_p - data pointer for the 1st DMA segment + */ + end_points[ep].seg_xfer_cnt = 0 ; + end_points[ep].sg_p = buf; + end_points[ep].data_p = sg_virt(end_points[ep].sg_p); + + #ifdef DBGPRN_DMA_SETUP_RD + DBGPRN("cyasomaphal:DMA_setup_read sg_list EP:%d, " + "buf:%p, buf_va:%p, req_sz:%d, maxsz:%d\n", + ep, + buf, + end_points[ep].data_p, + size, + maxsize); + #endif + v = (end_points[ep].dma_xfer_sz & + CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) | + CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL ; + cy_as_hal_write_register(tag, addr, v); + } else { + /* + * Non sg list EP passed void *buf rather then scatterlist *sg + */ + #ifdef DBGPRN_DMA_SETUP_RD + DBGPRN("%s:non-sg_list EP:%d," + "RQ_sz:%d, maxsz:%d\n", + __func__, ep, size, maxsize); + #endif + + end_points[ep].sg_p = NULL; + + /* + * must be a VMA of a membuf in kernel space + */ + end_points[ep].data_p = buf; + + /* + * Program the EP DMA register for Storage endpoints only. + */ + if (is_storage_e_p(ep)) { + v = (end_points[ep].dma_xfer_sz & + CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) | + CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL ; + cy_as_hal_write_register(tag, addr, v); + } + } +} + +/* + * This function must be defined to allow the WB API to + * register a callback function that is called when a + * DMA transfer is complete. + */ +void cy_as_hal_dma_register_callback(cy_as_hal_device_tag tag, + cy_as_hal_dma_complete_callback cb) +{ + DBGPRN("<1>\n%s: WB API has registered a dma_complete callback:%x\n", + __func__, (uint32_t)cb); + callback = cb ; +} + +/* + * This function must be defined to return the maximum size of + * DMA request that can be handled on the given endpoint. The + * return value should be the maximum size in bytes that the DMA + * module can handle. + */ +uint32_t cy_as_hal_dma_max_request_size(cy_as_hal_device_tag tag, + cy_as_end_point_number_t ep) +{ + /* + * Storage reads and writes are always done in 512 byte blocks. + * So, we do the count handling within the HAL, and save on + * some of the data transfer delay. + */ + if ((ep == CYASSTORAGE_READ_EP_NUM) || + (ep == CYASSTORAGE_WRITE_EP_NUM)) { + /* max DMA request size HAL can handle by itself */ + return CYASSTORAGE_MAX_XFER_SIZE; + } else { + /* + * For the USB - Processor endpoints, the maximum transfer + * size depends on the speed of USB operation. So, we use + * the following constant to indicate to the API that + * splitting of the data into chunks less that or equal to + * the max transfer size should be handled internally. + */ + + /* DEFINED AS 0xffffffff in cyasdma.h */ + return CY_AS_DMA_MAX_SIZE_HW_SIZE; + } +} + +/* + * This function must be defined to set the state of the WAKEUP pin + * on the WestBridge device. Generally this is done via a GPIO of + * some type. + */ +cy_bool cy_as_hal_set_wakeup_pin(cy_as_hal_device_tag tag, cy_bool state) +{ + /* + * Not supported as of now. + */ + return cy_false ; +} + +void cy_as_hal_pll_lock_loss_handler(cy_as_hal_device_tag tag) +{ + cy_as_hal_print_message("error: astoria PLL lock is lost\n") ; + cy_as_hal_print_message("please check the input voltage levels"); + cy_as_hal_print_message("and clock, and restart the system\n") ; +} + +/* + * Below are the functions that must be defined to provide the basic + * operating system services required by the API. + */ + +/* + * This function is required by the API to allocate memory. + * This function is expected to work exactly like malloc(). + */ +void *cy_as_hal_alloc(uint32_t cnt) +{ + void *ret_p ; + + ret_p = kmalloc(cnt, GFP_ATOMIC) ; + return ret_p ; +} + +/* + * This function is required by the API to free memory allocated + * with CyAsHalAlloc(). This function is'expected to work exacly + * like free(). + */ +void cy_as_hal_free(void *mem_p) +{ + kfree(mem_p) ; +} + +/* + * Allocator that can be used in interrupt context. + * We have to ensure that the kmalloc call does not + * sleep in this case. + */ +void *cy_as_hal_c_b_alloc(uint32_t cnt) +{ + void *ret_p ; + + ret_p = kmalloc(cnt, GFP_ATOMIC) ; + return ret_p ; +} + +/* + * This function is required to set a block of memory to a + * specific value. This function is expected to work exactly + * like memset() + */ +void cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt) +{ + memset(ptr, value, cnt) ; +} + +/* + * This function is expected to create a sleep channel. + * The data structure that represents the sleep channel object + * sleep channel (which is Linux "wait_queue_head_t wq" for this paticular HAL) + * passed as a pointer, and allpocated by the caller + * (typically as a local var on the stack) "Create" word should read as + * "SleepOn", this func doesn't actually create anything + */ +cy_bool cy_as_hal_create_sleep_channel(cy_as_hal_sleep_channel *channel) +{ + init_waitqueue_head(&channel->wq) ; + return cy_true ; +} + +/* + * for this particular HAL it doesn't actually destroy anything + * since no actual sleep object is created in CreateSleepChannel() + * sleep channel is given by the pointer in the argument. + */ +cy_bool cy_as_hal_destroy_sleep_channel(cy_as_hal_sleep_channel *channel) +{ + return cy_true ; +} + +/* + * platform specific wakeable Sleep implementation + */ +cy_bool cy_as_hal_sleep_on(cy_as_hal_sleep_channel *channel, uint32_t ms) +{ + wait_event_interruptible_timeout(channel->wq, 0, ((ms * HZ)/1000)) ; + return cy_true ; +} + +/* + * wakes up the process waiting on the CHANNEL + */ +cy_bool cy_as_hal_wake(cy_as_hal_sleep_channel *channel) +{ + wake_up_interruptible_all(&channel->wq); + return cy_true ; +} + +uint32_t cy_as_hal_disable_interrupts() +{ + if (0 == intr__enable) + ; + + intr__enable++ ; + return 0 ; +} + +void cy_as_hal_enable_interrupts(uint32_t val) +{ + intr__enable-- ; + if (0 == intr__enable) + ; +} + +/* + * Sleep atleast 150ns, cpu dependent + */ +void cy_as_hal_sleep150(void) +{ + uint32_t i, j; + + j = 0; + for (i = 0; i < 1000; i++) + j += (~i); +} + +void cy_as_hal_sleep(uint32_t ms) +{ + cy_as_hal_sleep_channel channel; + + cy_as_hal_create_sleep_channel(&channel) ; + cy_as_hal_sleep_on(&channel, ms) ; + cy_as_hal_destroy_sleep_channel(&channel) ; +} + +cy_bool cy_as_hal_is_polling() +{ + return cy_false; +} + +void cy_as_hal_c_b_free(void *ptr) +{ + cy_as_hal_free(ptr); +} + +/* + * suppose to reinstate the astoria registers + * that may be clobbered in sleep mode + */ +void cy_as_hal_init_dev_registers(cy_as_hal_device_tag tag, + cy_bool is_standby_wakeup) +{ + /* specific to SPI, no implementation required */ + (void) tag; + (void) is_standby_wakeup; +} + +void cy_as_hal_read_regs_before_standby(cy_as_hal_device_tag tag) +{ + /* specific to SPI, no implementation required */ + (void) tag; +} + +cy_bool cy_as_hal_sync_device_clocks(cy_as_hal_device_tag tag) +{ + /* + * we are in asynchronous mode. so no need to handle this + */ + return true; +} + +/* + * init OMAP h/w resources + */ +int start_o_m_a_p_kernel(const char *pgm, + cy_as_hal_device_tag *tag, cy_bool debug) +{ + cy_as_omap_dev_kernel *dev_p ; + int i; + u16 data16[4]; + u8 pncfg_reg; + + /* + * No debug mode support through argument as of now + */ + (void)debug; + + DBGPRN(KERN_INFO"starting OMAP34xx HAL...\n"); + + /* + * Initialize the HAL level endpoint DMA data. + */ + for (i = 0 ; i < sizeof(end_points)/sizeof(end_points[0]) ; i++) { + end_points[i].data_p = 0 ; + end_points[i].pending = cy_false ; + end_points[i].size = 0 ; + end_points[i].type = cy_as_hal_none ; + end_points[i].sg_list_enabled = cy_false; + + /* + * by default the DMA transfers to/from the E_ps don't + * use sg_list that implies that the upper devices like + * blockdevice have to enable it for the E_ps in their + * initialization code + */ + } + + /* + * allocate memory for OMAP HAL + */ + dev_p = (cy_as_omap_dev_kernel *)cy_as_hal_alloc( + sizeof(cy_as_omap_dev_kernel)) ; + if (dev_p == 0) { + cy_as_hal_print_message("out of memory allocating OMAP" + "device structure\n") ; + return 0 ; + } + + dev_p->m_sig = CY_AS_OMAP_KERNEL_HAL_SIG; + + /* + * initialize OMAP hardware and StartOMAPKernelall gpio pins + */ + dev_p->m_addr_base = (void *)cy_as_hal_processor_hw_init(); + + /* + * Now perform a hard reset of the device to have + * the new settings take effect + */ + __gpio_set_value(AST_WAKEUP, 1); + + /* + * do Astoria h/w reset + */ + DBGPRN(KERN_INFO"-_-_pulse -> westbridge RST pin\n"); + + /* + * NEGATIVE PULSE on RST pin + */ + __gpio_set_value(AST_RESET, 0); + mdelay(1); + __gpio_set_value(AST_RESET, 1); + mdelay(50); + + /* + * note AFTER reset PNAND interface is 8 bit mode + * so if gpmc Is configured in 8 bit mode upper half will be FF + */ + pncfg_reg = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG); + +#ifdef PNAND_16BIT_MODE + + /* + * switch to 16 bit mode, force NON-LNA LBD mode, 3 RA addr bytes + */ + ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0001); + + /* + * now in order to continue to talk to astoria + * sw OMAP GPMC into 16 bit mode as well + */ + cy_as_hal_gpmc_enable_16bit_bus(cy_true); +#else + /* Astoria and GPMC are already in 8 bit mode, jsut initialize PNAND_CFG */ + ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0000); +#endif + + /* + * NOTE: if you want to capture bus activity on the LA, + * don't use printks in between the activities you want to capture. + * prinks may take milliseconds, and the data of interest + * will fall outside the LA capture window/buffer + */ + data16[0] = ast_p_nand_casdo_read(CY_AS_MEM_CM_WB_CFG_ID); + data16[1] = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG); + + if (data16[0] != 0xA200) { + /* + * astoria device is not found + */ + printk(KERN_ERR "ERROR: astoria device is not found, CY_AS_MEM_CM_WB_CFG_ID "); + printk(KERN_ERR "read returned:%4.4X: CY_AS_MEM_PNAND_CFG:%4.4x !\n", + data16[0], data16[0]); + goto bus_acc_error; + } + + cy_as_hal_print_message(KERN_INFO" register access CASDO test:" + "\n CY_AS_MEM_CM_WB_CFG_ID:%4.4x\n" + "PNAND_CFG after RST:%4.4x\n " + "CY_AS_MEM_PNAND_CFG" + "after cfg_wr:%4.4x\n\n", + data16[0], pncfg_reg, data16[1]); + + dev_p->thread_flag = 1 ; + spin_lock_init(&int_lock) ; + dev_p->m_next_p = m_omap_list_p ; + + m_omap_list_p = dev_p ; + *tag = dev_p; + + cy_as_hal_configure_interrupts((void *)dev_p); + + cy_as_hal_print_message(KERN_INFO"OMAP3430__hal started tag:%p" + ", kernel HZ:%d\n", dev_p, HZ); + + /* + *make processor to storage endpoints SG assisted by default + */ + cy_as_hal_set_ep_dma_mode(4, true); + cy_as_hal_set_ep_dma_mode(8, true); + + return 1 ; + + /* + * there's been a NAND bus access error or + * astoria device is not connected + */ +bus_acc_error: + /* + * at this point hal tag hasn't been set yet + * so the device will not call omap_stop + */ + cy_as_hal_omap_hardware_deinit(dev_p); + cy_as_hal_free(dev_p) ; + return 0; +} + +#else +/* + * Some compilers do not like empty C files, so if the OMAP hal is not being + * compiled, we compile this single function. We do this so that for a + * given target HAL there are not multiple sources for the HAL functions. + */ +void my_o_m_a_p_kernel_hal_dummy_function(void) +{ +} + +#endif diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h new file mode 100644 index 000000000000..6ce78ae6c3bb --- /dev/null +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h @@ -0,0 +1,55 @@ +/* Cypress West Bridge API header file (cyashaldef.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASHALDEF_H_ +#define _INCLUDED_CYASHALDEF_H_ + +/* Summary + * If set to TRUE, the basic numeric types are defined by the + * West Bridge API code + * + * Description + * The West Bridge API relies on some basic integral types to be + * defined. These types include uint8_t, int8_t, uint16_t, + * int16_t, uint32_t, and int32_t. If this macro is defined the + * West Bridge API will define these types based on some basic + * assumptions. If this value is set and the West Bridge API is + * used to set these types, the definition of these types must be + * examined to insure that they are appropriate for the given + * target architecture and compiler. + * + * Notes + * It is preferred that if the basic platform development + * environment defines these types that the CY_DEFINE_BASIC_TYPES + * macro be undefined and the appropriate target system header file + * be added to the file cyashaldef.h. + */ + +#include + + +#if !defined(__doxygen__) +typedef int cy_bool ; +#define cy_true (1) +#define cy_false (0) +#endif + +#endif /* _INCLUDED_CYASHALDEF_H_ */ diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h new file mode 100644 index 000000000000..c40279b29109 --- /dev/null +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h @@ -0,0 +1,319 @@ +/* Cypress Antioch HAL for OMAP KERNEL header file (cyashalomapkernel.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * This file contains the defintion of the hardware abstraction + * layer on OMAP3430 talking to the West Bridge Astoria device + */ + + +#ifndef _INCLUDED_CYASHALOMAP_KERNEL_H_ +#define _INCLUDED_CYASHALOMAP_KERNEL_H_ + +#include +#include +#include +#include +/* include does not seem to work + * moving for patch submission +#include +*/ +#include +typedef struct cy_as_hal_sleep_channel_t { + wait_queue_head_t wq ; +} cy_as_hal_sleep_channel ; + +/* moved to staging location, eventual location + * considered is here +#include +#include +#include +*/ +#include "../cyashaldef.h" +#include "../../../../../../../include/linux/westbridge/cyastypes.h" +#include "../../../../../../../include/linux/westbridge/cyas_cplus_start.h" +#include "cyasomapdev_kernel.h" + +/* + * Below are the data structures that must be defined by the HAL layer + */ + +/* + * The HAL layer must define a TAG for identifying a specific Astoria + * device in the system. In this case the tag is a void * which is + * really an OMAP device pointer + */ +typedef void *cy_as_hal_device_tag ; + + +/* This must be included after the CyAsHalDeviceTag type is defined */ + +/* moved to staging location, eventual location + * considered is here + * #include +*/ +#include "../../../../../../../include/linux/westbridge/cyashalcb.h" +/* + * Below are the functions that communicate with the West Bridge + * device. These are system dependent and must be defined by + * the HAL layer for a given system. + */ + +/* + * This function must be defined to write a register within the Antioch + * device. The addr value is the address of the register to write with + * respect to the base address of the Antioch device. + */ +void +cy_as_hal_write_register(cy_as_hal_device_tag tag, + uint16_t addr, uint16_t data) ; + +/* + * This function must be defined to read a register from + * the west bridge device. The addr value is the address of + * the register to read with respect to the base address + * of the west bridge device. + */ +uint16_t +cy_as_hal_read_register(cy_as_hal_device_tag tag, uint16_t addr) ; + +/* + * This function must be defined to transfer a block of data + * to the west bridge device. This function can use the burst write + * (DMA) capabilities of Antioch to do this, or it can just copy + * the data using writes. + */ +void +cy_as_hal_dma_setup_write(cy_as_hal_device_tag tag, + uint8_t ep, void *buf, uint32_t size, uint16_t maxsize) ; + +/* + * This function must be defined to transfer a block of data + * from the Antioch device. This function can use the burst + * read (DMA) capabilities of Antioch to do this, or it can + * just copy the data using reads. + */ +void +cy_as_hal_dma_setup_read(cy_as_hal_device_tag tag, uint8_t ep, + void *buf, uint32_t size, uint16_t maxsize) ; + +/* + * This function must be defined to cancel any pending DMA request. + */ +void +cy_as_hal_dma_cancel_request(cy_as_hal_device_tag tag, uint8_t ep) ; + +/* + * This function must be defined to allow the Antioch API to + * register a callback function that is called when a DMA transfer + * is complete. + */ +void +cy_as_hal_dma_register_callback(cy_as_hal_device_tag tag, + cy_as_hal_dma_complete_callback cb) ; + +/* + * This function must be defined to return the maximum size of DMA + * request that can be handled on the given endpoint. The return + * value should be the maximum size in bytes that the DMA module can + * handle. + */ +uint32_t +cy_as_hal_dma_max_request_size(cy_as_hal_device_tag tag, + cy_as_end_point_number_t ep) ; + +/* + * This function must be defined to set the state of the WAKEUP pin + * on the Antioch device. Generally this is done via a GPIO of some + * type. + */ +cy_bool +cy_as_hal_set_wakeup_pin(cy_as_hal_device_tag tag, cy_bool state) ; + +/* + * This function is called when the Antioch PLL loses lock, because + * of a problem in the supply voltage or the input clock. + */ +void +cy_as_hal_pll_lock_loss_handler(cy_as_hal_device_tag tag) ; + + +/********************************************************************** + * + * Below are the functions that must be defined to provide the basic + * operating system services required by the API. + * +***********************************************************************/ + +/* + * This function is required by the API to allocate memory. This function + * is expected to work exactly like malloc(). + */ +void * +cy_as_hal_alloc(uint32_t cnt) ; + +/* + * This function is required by the API to free memory allocated with + * CyAsHalAlloc(). This function is expected to work exacly like free(). + */ +void +cy_as_hal_free(void *mem_p) ; + +/* + * This function is required by the API to allocate memory during a + * callback. This function must be able to provide storage at inturupt + * time. + */ +void * +cy_as_hal_c_b_alloc(uint32_t cnt) ; + +/* + * This function is required by the API to free memory allocated with + * CyAsCBHalAlloc(). + */ +void +cy_as_hal_c_b_free(void *ptr) ; + +/* + * This function is required to set a block of memory to a specific + * value. This function is expected to work exactly like memset() + */ +void +cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt) ; + +/* + * This function is expected to create a sleep channel. The data + * structure that represents the sleep channel is given by the + * pointer in the argument. + */ +cy_bool +cy_as_hal_create_sleep_channel(cy_as_hal_sleep_channel *channel) ; + +/* + * This function is expected to destroy a sleep channel. The data + * structure that represents the sleep channel is given by + * the pointer in the argument. + */ + + +cy_bool +cy_as_hal_destroy_sleep_channel(cy_as_hal_sleep_channel *channel) ; + +cy_bool +cy_as_hal_sleep_on(cy_as_hal_sleep_channel *channel, uint32_t ms) ; + +cy_bool +cy_as_hal_wake(cy_as_hal_sleep_channel *channel) ; + +uint32_t +cy_as_hal_disable_interrupts(void) ; + +void +cy_as_hal_enable_interrupts(uint32_t); + +void +cy_as_hal_sleep150(void); + +void +cy_as_hal_sleep(uint32_t ms); + +cy_bool +cy_as_hal_is_polling(void); + +void cy_as_hal_init_dev_registers(cy_as_hal_device_tag tag, + cy_bool is_standby_wakeup); + +/* + * required only in spi mode + */ +cy_bool cy_as_hal_sync_device_clocks(cy_as_hal_device_tag tag); + +void cy_as_hal_read_regs_before_standby(cy_as_hal_device_tag tag); + + +#ifndef NDEBUG +#define cy_as_hal_assert(cond) if (!(cond))\ + printk(KERN_WARNING"assertion failed at %s:%d\n", __FILE__, __LINE__); +#else +#define cy_as_hal_assert(cond) +#endif + +#define cy_as_hal_print_message printk + +/* removable debug printks */ +#ifndef WESTBRIDGE_NDEBUG +#define DBG_PRINT_ENABLED +#endif + +/*#define MBOX_ACCESS_DBG_PRINT_ENABLED*/ + + +#ifdef DBG_PRINT_ENABLED + /* Debug printing enabled */ + + #define DBGPRN(...) printk(__VA_ARGS__) + #define DBGPRN_FUNC_NAME printk("<1> %x:_func: %s\n", \ + current->pid, __func__) + +#else + /** NO DEBUG PRINTING **/ + #define DBGPRN(...) + #define DBGPRN_FUNC_NAME + +#endif + +/* +CyAsMiscSetLogLevel(uint8_t level) +{ + debug_level = level ; +} + +#ifdef CY_AS_LOG_SUPPORT + +void +cy_as_log_debug_message(int level, const char *str) +{ + if (level <= debug_level) + cy_as_hal_print_message("log %d: %s\n", level, str) ; +} +*/ + + +/* + * print buffer helper + */ +void cyashal_prn_buf(void *buf, uint16_t offset, int len); + +/* + * These are the functions that are not part of the HAL layer, + * but are required to be called for this HAL. + */ +int start_o_m_a_p_kernel(const char *pgm, + cy_as_hal_device_tag *tag, cy_bool debug) ; +int stop_o_m_a_p_kernel(const char *pgm, cy_as_hal_device_tag tag) ; +int omap_start_intr(cy_as_hal_device_tag tag) ; +void cy_as_hal_set_ep_dma_mode(uint8_t ep, bool sg_xfer_enabled); + +/* moved to staging location +#include +*/ +#include "../../../../../../../include/linux/westbridge/cyas_cplus_start.h" +#endif diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h new file mode 100644 index 000000000000..4377a34717b8 --- /dev/null +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h @@ -0,0 +1,555 @@ +/* + OMAP3430 ZOOM MDK astoria interface defs(cyasmemmap.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ +/* include does not seem to work + * moving for patch submission +#include +#include +*/ +#include +#include + +#ifndef _INCLUDED_CYASMEMMAP_H_ +#define _INCLUDED_CYASMEMMAP_H_ + +/* defines copied from OMAP kernel branch */ +#define OMAP34XX_MUX_MODE0 0 +#define OMAP34XX_MUX_MODE4 4 +#define OMAP3_INPUT_EN (1 << 8) +#define OMAP34XX_PIN_INPUT_PULLUP (OMAP2_PULL_ENA | OMAP3_INPUT_EN \ + | OMAP2_PULL_UP) + +/* + * for OMAP3430 <-> astoria : ADmux mode, 8 bit data path + * WB Signal- OMAP3430 signal COMMENTS + * --------------------------- -------------------- + * CS_L -GPMC_nCS4_GPIO_53 ZOOM I SOM board + * signal: up_nCS_A_EXT + * AD[7:0]-upD[7:0] buffered on the + * transposer board + * GPMC_ADDR + * [A8:A1]->upD[7:0] + * INT# -GPMC_nWP_GPIO_62 + * DACK -N/C not conected + * WAKEUP-GPIO_167 + * RESET-GPIO_126 + * R/B -GPMC_WAIT2_GPIO_64 + * ------------------------------------------- + * The address range for nCS1B is 0x06000000 - 0x07FF FFFF. +*/ + +/* + *OMAP_ZOOM LEDS + */ +#define LED_0 156 +#define LED_1 128 +#define LED_2 64 +#define LED_3 60 + +#define HIGH 1 +#define LOW 1 + +/* + *omap GPIO number + */ +#define AST_WAKEUP 167 +#define AST_RESET 126 +#define AST__rn_b 64 + +/* + * NOTE THIS PIN IS USED AS WP for OMAP NAND + */ +#define AST_INT 62 + +/* + * as an I/O, it is actually controlled by GPMC + */ +#define AST_CS 55 + + +/* + *GPMC prefetch engine + */ + +/* register and its bit fields */ +#define GPMC_PREFETCH_CONFIG1 0x01E0 + + /*32 bytes for 16 bit pnand mode*/ + #define PFE_THRESHOLD 31 + + /* + * bit fields + * PF_ACCESSMODE - 0 - read mode, 1 - write mode + * PF_DMAMODE - 0 - default only intr line signal will be generated + * PF_SYNCHROMODE - default 0 - engin will start access as soon as + * ctrl re STARTENGINE is set + * PF_WAITPINSEL - FOR synchro mode selects WAIT pin whch edge + * will be monitored + * PF_EN_ENGINE - 1- ENABLES ENGINE, but it needs to be started after + * that C ctrl reg bit 0 + * PF_FIFO_THRESHOLD - FIFO threshhold in number of BUS(8 or 16) words + * PF_WEIGHTED_PRIO - NUM of cycles granted to PFE if RND_ROBIN + * prioritization is enabled + * PF_ROUND_ROBIN - if enabled, gives priority to other CS, but + * reserves NUM of cycles for PFE's turn + * PF_ENGIN_CS_SEL - GPMC CS assotiated with PFE function + */ + #define PF_ACCESSMODE (0 << 0) + #define PF_DMAMODE (0 << 2) + #define PF_SYNCHROMODE (0 << 3) + #define PF_WAITPINSEL (0x0 << 4) + #define PF_EN_ENGINE (1 << 7) + #define PF_FIFO_THRESHOLD (PFE_THRESHOLD << 8) + #define PF_WEIGHTED_PRIO (0x0 << 16) + #define PF_ROUND_ROBIN (0 << 23) + #define PF_ENGIN_CS_SEL (AST_GPMC_CS << 24) + #define PF_EN_OPTIM_ACC (0 << 27) + #define PF_CYCLEOPTIM (0x0 << 28) + +#define GPMC_PREFETCH_CONFIG1_VAL (PF_ACCESSMODE | \ + PF_DMAMODE | PF_SYNCHROMODE | \ + PF_WAITPINSEL | PF_EN_ENGINE | \ + PF_FIFO_THRESHOLD | PF_FIFO_THRESHOLD | \ + PF_WEIGHTED_PRIO | PF_ROUND_ROBIN | \ + PF_ENGIN_CS_SEL | PF_EN_OPTIM_ACC | \ + PF_CYCLEOPTIM) + +/* register and its bit fields */ +#define GPMC_PREFETCH_CONFIG2 0x01E4 + /* + * bit fields + * 14 bit field NOTE this counts is also + * is in number of BUS(8 or 16) words + */ + #define PF_TRANSFERCOUNT (0x000) + + +/* register and its bit fields */ +#define GPMC_PREFETCH_CONTROL 0x01EC + /* + * bit fields , ONLY BIT 0 is implemented + * PFWE engin must be programmed with this bit = 0 + */ + #define PFPW_STARTENGINE (1 << 0) + +/* register and its bit fields */ +#define GPMC_PREFETCH_STATUS 0x01F0 + + /* */ + #define PFE_FIFO_THRESHOLD (1 << 16) + +/* + * GPMC posted write/prefetch engine end + */ + + +/* + * chip select number on GPMC ( 0..7 ) + */ +#define AST_GPMC_CS 4 + +/* + * not connected + */ +#define AST_DACK 00 + + +/* + * Physical address above the NAND flash + * we use CS For mapping in OMAP3430 RAM space use 0x0600 0000 + */ +#define CYAS_DEV_BASE_ADDR (0x20000000) + +#define CYAS_DEV_MAX_ADDR (0xFF) +#define CYAS_DEV_ADDR_RANGE (CYAS_DEV_MAX_ADDR << 1) + +#ifdef p_s_r_a_m_INTERFACE + /* in CRAM or PSRAM mode OMAP A1..An wires-> Astoria, there is no A0 line */ + #define CYAS_DEV_CALC_ADDR(cyas_addr) (cyas_addr << 1) + #define CYAS_DEV_CALC_EP_ADDR(ep) (ep << 1) +#else + /* + * For pNAND interface it depends on NAND emulation mode + * SBD/LBD etc we use NON-LNA_LBD mode, so it goes like this: + * forlbd , + * where CA1 address must have bits 2,3 = "11" + * ep is mapped into RA1 bits {4:0} + */ + #define CYAS_DEV_CALC_ADDR(cyas_addr) (cyas_addr | 0x0c00) + #define CYAS_DEV_CALC_EP_ADDR(ep) ep +#endif + +/* + *OMAP3430 i/o access macros + */ +#define IORD32(addr) (*(volatile u32 *)(addr)) +#define IOWR32(addr, val) (*(volatile u32 *)(addr) = val) + +#define IORD16(addr) (*(volatile u16 *)(addr)) +#define IOWR16(addr, val) (*(volatile u16 *)(addr) = val) + +#define IORD8(addr) (*(volatile u8 *)(addr)) +#define IOWR8(addr, val) (*(volatile u8 *)(addr) = val) + +/* + * local defines for accessing to OMAP GPIO *** + */ +#define CTLPADCONF_BASE_ADDR 0x48002000 +#define CTLPADCONF_SIZE 0x1000 + +#define GPIO1_BASE_ADDR 0x48310000 +#define GPIO2_BASE_ADDR 0x49050000 +#define GPIO3_BASE_ADDR 0x49052000 +#define GPIO4_BASE_ADDR 0x49054000 +#define GPIO5_BASE_ADDR 0x49056000 +#define GPIO6_BASE_ADDR 0x49058000 +#define GPIO_SPACE_SIZE 0x1000 + + +/* + * OMAP3430 GPMC timing for pNAND interface + */ +#define GPMC_BASE 0x6E000000 +#define GPMC_REGION_SIZE 0x1000 +#define GPMC_CONFIG_REG (0x50) + +/* + * bit 0 in the GPMC_CONFIG_REG + */ +#define NAND_FORCE_POSTED_WRITE_B 1 + +/* + * WAIT2STATUS, must be (1 << 10) + */ +#define AS_WAIT_PIN_MASK (1 << 10) + + +/* + * GPMC_CONFIG(reg number [1..7] [for chip sel CS[0..7]) + */ +#define GPMC_CFG_REG(N, CS) ((0x60 + (4*(N-1))) + (0x30*CS)) + +/* + *gpmc nand registers for CS4 + */ +#define GPMC_NAND_CMD (0x7c + (0x30*AST_GPMC_CS)) +#define GPMC_NAND_ADDR (0x80 + (0x30*AST_GPMC_CS)) +#define GPMC_NAND_DATA (0x84 + (0x30*AST_GPMC_CS)) + +#define GPMC_STAT_REG (0x54) +#define GPMC_ERR_TYPE (0x48) + +/* + * we get "gpmc_base" from kernel + */ +#define GPMC_VMA(offset) (gpmc_base + offset) + +/* + * GPMC CS space VMA start address + */ +#define GPMC_CS_VMA(offset) (gpmc_data_vma + offset) + +/* + * PAD_CFG mux space VMA + */ +#define PADCFG_VMA(offset) (iomux_vma + offset) + +/* + * CONFIG1: by default, sngle access, async r/w RD_MULTIPLE[30] + * WR_MULTIPLE[28]; GPMC_FCL_DIV[1:0] + */ +#define GPMC_FCLK_DIV ((0) << 0) + +/* + * ADDITIONAL DIVIDER FOR ALL TIMING PARAMS + */ +#define TIME_GRAN_SCALE ((0) << 4) + +/* + * for use by gpmc_set_timings api, measured in ns, not clocks + */ +#define WB_GPMC_BUSCYC_t (7 * 6) +#define WB_GPMC_CS_t_o_n (0) +#define WB_GPMC_ADV_t_o_n (0) +#define WB_GPMC_OE_t_o_n (0) +#define WB_GPMC_OE_t_o_f_f (5 * 6) +#define WB_GPMC_WE_t_o_n (1 * 6) +#define WB_GPMC_WE_t_o_f_f (5 * 6) +#define WB_GPMC_RDS_ADJ (2 * 6) +#define WB_GPMC_RD_t_a_c_c (WB_GPMC_OE_t_o_f_f + WB_GPMC_RDS_ADJ) +#define WB_GPMC_WR_t_a_c_c (WB_GPMC_BUSCYC_t) + +#define DIR_OUT 0 +#define DIR_INP 1 +#define DRV_HI 1 +#define DRV_LO 0 + +/* + * GPMC_CONFIG7[cs] register bit fields + * AS_CS_MASK - 3 bit mask for A26,A25,A24, + * AS_CS_BADDR - 6 BIT VALUE A29 ...A24 + * CSVALID_B - CSVALID bit on GPMC_CONFIG7[cs] register + */ +#define AS_CS_MASK (0X7 << 8) +#define AS_CS_BADDR 0x02 +#define CSVALID_B (1 << 6) + +/* + * DEFINE OMAP34XX GPIO OFFSETS (should have been defined in kernel /arch + * these are offsets from the BASE_ADDRESS of the GPIO BLOCK + */ +#define GPIO_REVISION 0x000 +#define GPIO_SYSCONFIG 0x010 +#define GPIO_SYSSTATUS1 0x014 +#define GPIO_IRQSTATUS1 0x018 +#define GPIO_IRQENABLE1 0x01C +#define GPIO_IRQSTATUS2 0x028 +#define GPIO_CTRL 0x030 +#define GPIO_OE 0x034 +#define GPIO_DATA_IN 0x038 +#define GPIO_DATA_OUT 0x03C +#define GPIO_LEVELDETECT0 0x040 +#define GPIO_LEVELDETECT1 0x044 +#define GPIO_RISINGDETECT 0x048 +#define GPIO_FALLINGDETECT 0x04c +#define GPIO_CLEAR_DATAOUT 0x090 +#define GPIO_SET_DATAOUT 0x094 + +typedef struct { + char *name; + u32 phy_addr; + u32 virt_addr; + u32 size; +} io2vma_tab_t; + +/* + * GPIO phy to translation VMA table + */ +static io2vma_tab_t gpio_vma_tab[6] = { + {"GPIO1_BASE_ADDR", GPIO1_BASE_ADDR , 0 , GPIO_SPACE_SIZE}, + {"GPIO2_BASE_ADDR", GPIO2_BASE_ADDR , 0 , GPIO_SPACE_SIZE}, + {"GPIO3_BASE_ADDR", GPIO3_BASE_ADDR , 0 , GPIO_SPACE_SIZE}, + {"GPIO4_BASE_ADDR", GPIO4_BASE_ADDR , 0 , GPIO_SPACE_SIZE}, + {"GPIO5_BASE_ADDR", GPIO5_BASE_ADDR , 0 , GPIO_SPACE_SIZE}, + {"GPIO6_BASE_ADDR", GPIO6_BASE_ADDR , 0 , GPIO_SPACE_SIZE} +}; +/* + * name - USER signal name assigned to the pin ( for printks) + * mux_func - enum index NAME for the pad_cfg function + * pin_num - pin_number if mux_func is GPIO, if not a GPIO it is -1 + * mux_ptr - pointer to the corresponding pad_cfg_reg + * (used for pad release ) + * mux_save - preserve here original PAD_CNF value for this + * pin (used for pad release) + * dir - if GPIO: 0 - OUT , 1 - IN + * dir_save - save original pin direction + * drv - initial drive level "0" or "1" + * drv_save - save original pin drive level + * valid - 1 if successfuly configured +*/ +typedef struct { + char *name; + u32 mux_func; + int pin_num; + u16 *mux_ptr; + u16 mux_save; + u8 dir; + u8 dir_save; + u8 drv; + u8 drv_save; + u8 valid; +} user_pad_cfg_t; + +/* + * need to ensure that enums are in sync with the + * omap_mux_pin_cfg table, these enums designate + * functions that OMAP pads can be configured to + */ +enum { + B23_OMAP3430_GPIO_167, + D23_OMAP3430_GPIO_126, + H1_OMAP3430_GPIO_62, + H1_OMAP3430_GPMC_n_w_p, + T8_OMAP3430_GPMC_n_c_s4, + T8_OMAP3430_GPIO_55, + R25_OMAP3430_GPIO_156, + R27_OMAP3430_GPIO_128, + K8_OMAP3430_GPIO_64, + K8_GPMC_WAIT2, + G3_OMAP3430_GPIO_60, + G3_OMAP3430_n_b_e0_CLE, + C6_GPMC_WAIT3, + J1_OMAP3430_GPIO_61, + C6_OMAP3430_GPIO_65, + + END_OF_TABLE +}; + +/* + * number of GPIOS we plan to grab + */ +#define GPIO_SLOTS 8 + +/* + * user_pads_init() reads(and saves) from/to this table + * used in conjunction with omap_3430_mux_t table in .h file + * because the way it's done in the kernel code + * TODO: implement restore of the the original cfg and i/o regs + */ + +static user_pad_cfg_t user_pad_cfg[] = { + /* + * name,pad_func,pin_num, mux_ptr, mux_sav, dir, + * dir_sav, drv, drv_save, valid + */ + {"AST_WAKEUP", B23_OMAP3430_GPIO_167, 167, NULL, 0, + DIR_OUT, 0, DRV_HI, 0, 0}, + {"AST_RESET", D23_OMAP3430_GPIO_126, 126, NULL, 0, + DIR_OUT, 0, DRV_HI, 0, 0}, + {"AST__rn_b", K8_GPMC_WAIT2, 64, NULL, 0, + DIR_INP, 0, 0, 0, 0}, + {"AST_INTR", H1_OMAP3430_GPIO_62, 62, NULL, 0, + DIR_INP, 0, DRV_HI, 0, 0}, + {"AST_CS", T8_OMAP3430_GPMC_n_c_s4, 55, NULL, 0, + DIR_OUT, 0, DRV_HI, 0, 0}, + {"LED_0", R25_OMAP3430_GPIO_156, 156, NULL, 0, + DIR_OUT, 0, DRV_LO, 0, 0}, + {"LED_1", R27_OMAP3430_GPIO_128, 128, NULL, 0, + DIR_OUT, 0, DRV_LO, 0, 0}, + {"AST_CLE", G3_OMAP3430_n_b_e0_CLE , 60, NULL, 0, + DIR_OUT, 0, DRV_LO, 0, 0}, + /* + * Z terminator, must always be present + * for sanity check, don't remove + */ + {NULL} +}; + +#define GPIO_BANK(pin) (pin >> 5) +#define REG_WIDTH 32 +#define GPIO_REG_VMA(pin_num, offset) \ + (gpio_vma_tab[GPIO_BANK(pin_num)].virt_addr + offset) + +/* + * OMAP GPIO_REG 32 BIT MASK for a bit or + * flag in gpio_No[0..191] apply it to a 32 bit + * location to set clear or check on a corresponding + * gpio bit or flag + */ +#define GPIO_REG_MASK(pin_num) (1 << \ + (pin_num - (GPIO_BANK(pin_num) * REG_WIDTH))) + +/* + * OMAP GPIO registers bitwise access macros + */ + +#define OMAP_GPIO_BIT(pin_num, reg) \ + ((*((u32 *)GPIO_REG_VMA(pin_num, reg)) \ + & GPIO_REG_MASK(pin_num)) ? 1 : 0) + +#define RD_OMAP_GPIO_BIT(pin_num, v) OMAP_GPIO_BIT(pin_num, reg) + +/* + *these are superfast set/clr bitbang macro, 48ns cyc tyme + */ +#define OMAP_SET_GPIO(pin_num) \ + (*(u32 *)GPIO_REG_VMA(pin_num, GPIO_SET_DATAOUT) \ + = GPIO_REG_MASK(pin_num)) +#define OMAP_CLR_GPIO(pin_num) \ + (*(u32 *)GPIO_REG_VMA(pin_num, GPIO_CLEAR_DATAOUT) \ + = GPIO_REG_MASK(pin_num)) + +#define WR_OMAP_GPIO_BIT(pin_num, v) \ + (v ? (*(u32 *)GPIO_REG_VMA(pin_num, \ + GPIO_SET_DATAOUT) = GPIO_REG_MASK(pin_num)) \ + : (*(u32 *)GPIO_REG_VMA(pin_num, \ + GPIO_CLEAR_DATAOUT) = GPIO_REG_MASK(pin_num))) + +/* + * Note this pin cfg mimicks similar implementation + * in linux kernel, which unfortunately doesn't allow + * us to dynamically insert new custom GPIO mux + * configurations all REG definitions used in this + * applications. to add a new pad_cfg function, insert + * a new ENUM and new pin_cfg entry in omap_mux_pin_cfg[] + * table below + * + * offset - note this is a word offset since the + * SCM regs are 16 bit packed in one 32 bit word + * mux_val - just enough to describe pins used + */ +typedef struct { + char *name; + u16 offset; + u16 mux_val; +} omap_3430_mux_t; + +/* + * "OUTIN" is configuration when DATA reg drives the + * pin but the level at the pin can be sensed + */ +#define PAD_AS_OUTIN (OMAP34XX_MUX_MODE4 | \ + OMAP34XX_PIN_OUTPUT | OMAP34XX_PIN_INPUT) + +omap_3430_mux_t omap_mux_pin_cfg[] = { + /* + * B23_OMAP3430_GPIO_167 - GPIO func to PAD 167 WB wakeup + * D23_OMAP3430_GPIO_126 - drive GPIO_126 ( AST RESET) + * H1_OMAP3430_GPIO_62 - need a pullup on this pin + * H1_OMAP3430_GPMC_n_w_p - GPMC NAND CTRL n_w_p out + * T8_OMAP3430_GPMC_n_c_s4" - T8 is controlled b_y GPMC NAND ctrl + * R25_OMAP3430_GPIO_156 - OMAPZOOM drive LED_0 + * R27_OMAP3430_GPIO_128 - OMAPZOOM drive LED_1 + * K8_OMAP3430_GPIO_64 - OMAPZOOM drive LED_2 + * K8_GPMC_WAIT2 - GPMC WAIT2 function on PAD K8 + * G3_OMAP3430_GPIO_60 - OMAPZOOM drive LED_3 + * G3_OMAP3430_n_b_e0_CLE -GPMC NAND ctrl CLE signal + */ + + {"B23_OMAP3430_GPIO_167", 0x0130, (OMAP34XX_MUX_MODE4)}, + {"D23_OMAP3430_GPIO_126", 0x0132, (OMAP34XX_MUX_MODE4)}, + {"H1_OMAP3430_GPIO_62", 0x00CA, (OMAP34XX_MUX_MODE4 | + OMAP3_INPUT_EN | OMAP34XX_PIN_INPUT_PULLUP) }, + {"H1_OMAP3430_GPMC_n_w_p", 0x00CA, (OMAP34XX_MUX_MODE0)}, + {"T8_OMAP3430_GPMC_n_c_s4", 0x00B6, (OMAP34XX_MUX_MODE0) }, + {"T8_OMAP3430_GPIO_55", 0x00B6, (OMAP34XX_MUX_MODE4) }, + {"R25_OMAP3430_GPIO_156", 0x018C, (OMAP34XX_MUX_MODE4) }, + {"R27_OMAP3430_GPIO_128", 0x0154, (OMAP34XX_MUX_MODE4) }, + {"K8_OMAP3430_GPIO_64", 0x00d0, (OMAP34XX_MUX_MODE4) }, + {"K8_GPMC_WAIT2", 0x00d0, (OMAP34XX_MUX_MODE0) }, + {"G3_OMAP3430_GPIO_60", 0x00C6, (OMAP34XX_MUX_MODE4 | + OMAP3_INPUT_EN)}, + {"G3_OMAP3430_n_b_e0_CLE", 0x00C6, (OMAP34XX_MUX_MODE0)}, + {"C6_GPMC_WAIT3", 0x00d2, (OMAP34XX_MUX_MODE0)}, + {"C6_OMAP3430_GPIO_65", 0x00d2, (OMAP34XX_MUX_MODE4 | + OMAP3_INPUT_EN)}, + {"J1_OMAP3430_GPIO_61", 0x00C8, (OMAP34XX_MUX_MODE4 | + OMAP3_INPUT_EN | OMAP34XX_PIN_INPUT_PULLUP)}, + /* + * don't remove, used for sanity check. + */ + {"END_OF_TABLE"} +}; + + +#endif /* _INCLUDED_CYASMEMMAP_H_ */ + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h new file mode 100644 index 000000000000..896e23281dba --- /dev/null +++ b/drivers/staging/westbridge/astoria/arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h @@ -0,0 +1,72 @@ +/* Cypress Antioch OMAP KERNEL file (cyanomapdev_kernel.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef __CY_AS_OMAP_DEV_KERNEL_H__ +#define __CY_AS_OMAP_DEV_KERNEL_H__ + + +#include +#include +#include + +/* include does not seem to work + * moving for patch submission +#include +*/ +#include + +/* + * Constants + */ +#define CY_AS_OMAP_KERNEL_HAL_SIG (0x1441) + + +/* + * Data structures + */ +typedef struct cy_as_omap_dev_kernel { + /* This is the signature for this data structure */ + unsigned int m_sig ; + + /* Address base of Antioch Device */ + void *m_addr_base; + + /* This is a pointer to the next Antioch device in the system */ + struct cy_as_omap_dev_kernel *m_next_p; + + /* This is for thread sync */ + struct completion thread_complete; + + /* This is for thread to wait for interrupts */ + cy_as_hal_sleep_channel thread_sc; + + /* This is for thread to exit upon StopOmapKernel */ + int thread_flag; /* set 1 to exit */ + + int dma_ch; + + /* This is for dma sync */ + struct completion dma_complete; +} cy_as_omap_dev_kernel; + +#endif + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/block/Kconfig b/drivers/staging/westbridge/astoria/block/Kconfig new file mode 100644 index 000000000000..851bf96a7b87 --- /dev/null +++ b/drivers/staging/westbridge/astoria/block/Kconfig @@ -0,0 +1,9 @@ +# +# West Bridge block driver configuration +# + +config WESTBRIDGE_BLOCK_DRIVER + tristate "West Bridge Block Driver" + help + Include the West Bridge based block driver + diff --git a/drivers/staging/westbridge/astoria/block/Makefile b/drivers/staging/westbridge/astoria/block/Makefile new file mode 100644 index 000000000000..4a45dd0861e7 --- /dev/null +++ b/drivers/staging/westbridge/astoria/block/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the kernel westbridge block driver +# + +ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y) + EXTRA_CFLAGS += -DWESTBRIDGE_NDEBUG +endif + +obj-$(CONFIG_WESTBRIDGE_BLOCK_DRIVER) += cyasblkdev.o +cyasblkdev-y := cyasblkdev_block.o cyasblkdev_queue.o + diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c new file mode 100644 index 000000000000..58b89b167870 --- /dev/null +++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_block.c @@ -0,0 +1,1628 @@ +/* cyanblkdev_block.c - West Bridge Linux Block Driver source file +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * Linux block driver implementation for Cypress West Bridge. + * Based on the mmc block driver implementation by Andrew Christian + * for the linux 2.6.26 kernel. + * mmc_block.c, 5/28/2002 + */ + +/* + * Block driver for media (i.e., flash cards) + * + * Copyright 2002 Hewlett-Packard Company + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Many thanks to Alessandro Rubini and Jonathan Corbet! + * + * Author: Andrew Christian + * 28 May 2002 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "cyasblkdev_queue.h" + +#define CYASBLKDEV_SHIFT 0 /* Only a single partition. */ +#define CYASBLKDEV_MAX_REQ_LEN (256) +#define CYASBLKDEV_NUM_MINORS (256 >> CYASBLKDEV_SHIFT) +#define CY_AS_TEST_NUM_BLOCKS (64) +#define CYASBLKDEV_MINOR_0 1 +#define CYASBLKDEV_MINOR_1 2 +#define CYASBLKDEV_MINOR_2 3 + +static int major; +module_param(major, int, 0444); +MODULE_PARM_DESC(major, + "specify the major device number for cyasblkdev block driver"); + +/* parameters passed from the user space */ +static int vfat_search; +module_param(vfat_search, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(vfat_search, + "dynamically find the location of the first sector"); + +static int private_partition_bus = -1; +module_param(private_partition_bus, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(private_partition_bus, + "bus number for private partition"); + +static int private_partition_size = -1; +module_param(private_partition_size, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(private_partition_size, + "size of the private partition"); + +/* + * There is one cyasblkdev_blk_data per slot. + */ +struct cyasblkdev_blk_data { + spinlock_t lock; + int media_count[2]; + const struct block_device_operations *blkops; + unsigned int usage; + unsigned int suspended; + + /* handle to the west bridge device this handle, typdefed as *void */ + cy_as_device_handle dev_handle; + + /* our custom structure, in addition to request queue, + * adds lock & semaphore items*/ + struct cyasblkdev_queue queue; + + /* 16 entries is enough given max request size + * 16 * 4K (64 K per request)*/ + struct scatterlist sg[16]; + + /* non-zero enables printk of executed reqests */ + unsigned int dbgprn_flags; + + /*gen_disk for private, system disk */ + struct gendisk *system_disk; + cy_as_media_type system_disk_type; + cy_bool system_disk_read_only; + cy_bool system_disk_bus_num; + + /* sector size for the medium */ + unsigned int system_disk_blk_size; + unsigned int system_disk_first_sector; + unsigned int system_disk_unit_no; + + /*gen_disk for bus 0 */ + struct gendisk *user_disk_0; + cy_as_media_type user_disk_0_type; + cy_bool user_disk_0_read_only; + cy_bool user_disk_0_bus_num; + + /* sector size for the medium */ + unsigned int user_disk_0_blk_size; + unsigned int user_disk_0_first_sector; + unsigned int user_disk_0_unit_no; + + /*gen_disk for bus 1 */ + struct gendisk *user_disk_1; + cy_as_media_type user_disk_1_type; + cy_bool user_disk_1_read_only; + cy_bool user_disk_1_bus_num; + + /* sector size for the medium */ + unsigned int user_disk_1_blk_size; + unsigned int user_disk_1_first_sector; + unsigned int user_disk_1_unit_no; +}; + +/* pointer to west bridge block data device superstructure */ +static struct cyasblkdev_blk_data *gl_bd ; + +static DECLARE_MUTEX(open_lock); + +/* local forwardd declarationss */ +static cy_as_device_handle *cyas_dev_handle; +static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd); + +/*change debug print options */ + #define DBGPRN_RD_RQ (1 < 0) + #define DBGPRN_WR_RQ (1 < 1) + #define DBGPRN_RQ_END (1 < 2) + +int blkdev_ctl_dbgprn( + int prn_flags + ) +{ + int cur_options = gl_bd->dbgprn_flags; + + DBGPRN_FUNC_NAME; + + /* set new debug print options */ + gl_bd->dbgprn_flags = prn_flags; + + /* return previous */ + return cur_options; +} +EXPORT_SYMBOL(blkdev_ctl_dbgprn); + +static struct cyasblkdev_blk_data *cyasblkdev_blk_get( + struct gendisk *disk + ) +{ + struct cyasblkdev_blk_data *bd; + + DBGPRN_FUNC_NAME; + + down(&open_lock); + + bd = disk->private_data; + + if (bd && (bd->usage == 0)) + bd = NULL; + + if (bd) { + bd->usage++; + #ifndef NBDEBUG + cy_as_hal_print_message( + "cyasblkdev_blk_get: usage = %d\n", bd->usage) ; + #endif + } + up(&open_lock); + + return bd; +} + +static void cyasblkdev_blk_put( + struct cyasblkdev_blk_data *bd + ) +{ + DBGPRN_FUNC_NAME; + + down(&open_lock); + + if (bd) { + bd->usage--; + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + " cyasblkdev_blk_put , bd->usage= %d\n", bd->usage); + #endif + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev: blk_put(bd) on bd = NULL!: usage = %d\n", + bd->usage); + #endif + up(&open_lock); + return ; + } + + if (bd->usage == 0) { + put_disk(bd->user_disk_0); + put_disk(bd->user_disk_1); + put_disk(bd->system_disk); + cyasblkdev_cleanup_queue(&bd->queue); + + if (CY_AS_ERROR_SUCCESS != + cy_as_storage_release(bd->dev_handle, 0, 0, 0, 0)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev: cannot release bus 0\n") ; + #endif + } + + if (CY_AS_ERROR_SUCCESS != + cy_as_storage_release(bd->dev_handle, 1, 0, 0, 0)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev: cannot release bus 1\n") ; + #endif + } + + if (CY_AS_ERROR_SUCCESS != + cy_as_storage_stop(bd->dev_handle, 0, 0)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev: cannot stop storage stack\n") ; + #endif + } + + #ifdef __CY_ASTORIA_SCM_KERNEL_HAL__ + /* If the SCM Kernel HAL is being used, disable the use + * of scatter/gather lists at the end of block driver usage. + */ + cy_as_hal_disable_scatter_list(cyasdevice_gethaltag()) ; + #endif + + /*ptr to global struct cyasblkdev_blk_data */ + gl_bd = NULL ; + kfree(bd); + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev (blk_put): usage = %d\n", + bd->usage) ; + #endif + up(&open_lock); +} + +static int cyasblkdev_blk_open( + struct block_device *bdev, + fmode_t mode + ) +{ + struct cyasblkdev_blk_data *bd = cyasblkdev_blk_get(bdev->bd_disk); + int ret = -ENXIO; + + DBGPRN_FUNC_NAME; + + if (bd) { + if (bd->usage == 2) + check_disk_change(bdev); + + ret = 0; + + if (bdev->bd_disk == bd->user_disk_0) { + if ((mode & FMODE_WRITE) && bd->user_disk_0_read_only) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "device marked as readonly " + "and write requested\n"); + #endif + + cyasblkdev_blk_put(bd); + ret = -EROFS; + } + } else if (bdev->bd_disk == bd->user_disk_1) { + if ((mode & FMODE_WRITE) && bd->user_disk_1_read_only) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "device marked as readonly " + "and write requested\n"); + #endif + + cyasblkdev_blk_put(bd); + ret = -EROFS; + } + } else if (bdev->bd_disk == bd->system_disk) { + if ((mode & FMODE_WRITE) && bd->system_disk_read_only) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "device marked as readonly " + "and write requested\n"); + #endif + + cyasblkdev_blk_put(bd); + ret = -EROFS; + } + } + } + + return ret; +} + +static int cyasblkdev_blk_release( + struct gendisk *disk, + fmode_t mode + ) +{ + struct cyasblkdev_blk_data *bd = disk->private_data; + + DBGPRN_FUNC_NAME; + + cyasblkdev_blk_put(bd); + return 0; +} + +static int cyasblkdev_blk_ioctl( + struct block_device *bdev, + fmode_t mode, + unsigned int cmd, + unsigned long arg + ) +{ + DBGPRN_FUNC_NAME; + + if (cmd == HDIO_GETGEO) { + /*for now we only process geometry IOCTL*/ + struct hd_geometry geo; + + memset(&geo, 0, sizeof(struct hd_geometry)); + + geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16); + geo.heads = 4; + geo.sectors = 16; + geo.start = get_start_sect(bdev); + + /* copy to user space */ + return copy_to_user((void __user *)arg, &geo, sizeof(geo)) + ? -EFAULT : 0; + } + + return -ENOTTY; +} + +/* Media_changed block_device opp + * this one is called by kernel to confirm if the media really changed + * as we indicated by issuing check_disk_change() call */ +int cyasblkdev_media_changed(struct gendisk *gd) +{ + struct cyasblkdev_blk_data *bd; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("cyasblkdev_media_changed() is called\n"); + #endif + + if (gd) + bd = gd->private_data; + else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "cyasblkdev_media_changed() is called, " + "but gd is null\n"); + #endif + } + + /* return media change state "1" yes, 0 no */ + return 1; +} + +/* this one called by kernel to give us a chence + * to prep the new media before it starts to rescaning + * of the newlly inserted SD media */ +int cyasblkdev_revalidate_disk(struct gendisk *gd) +{ + /*int (*revalidate_disk) (struct gendisk *); */ + + #ifndef WESTBRIDGE_NDEBUG + if (gd) + cy_as_hal_print_message( + "cyasblkdev_revalidate_disk() is called, " + "(gl_bd->usage:%d)\n", gl_bd->usage); + #endif + + /* 0 means ok, kern can go ahead with partition rescan */ + return 0; +} + + +/*standard block device driver interface */ +static struct block_device_operations cyasblkdev_bdops = { + .open = cyasblkdev_blk_open, + .release = cyasblkdev_blk_release, + .ioctl = cyasblkdev_blk_ioctl, + /* .getgeo = cyasblkdev_blk_getgeo, */ + /* added to support media removal( real and simulated) media */ + .media_changed = cyasblkdev_media_changed, + /* added to support media removal( real and simulated) media */ + .revalidate_disk = cyasblkdev_revalidate_disk, + .owner = THIS_MODULE, +}; + +/* west bridge block device prep request function */ +static int cyasblkdev_blk_prep_rq( + struct cyasblkdev_queue *bq, + struct request *req + ) +{ + struct cyasblkdev_blk_data *bd = bq->data; + int stat = BLKPREP_OK; + + DBGPRN_FUNC_NAME; + + /* If we have no device, we haven't finished initialising. */ + if (!bd || !bd->dev_handle) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message(KERN_ERR + "cyasblkdev %s: killing request - no device/host\n", + req->rq_disk->disk_name); + #endif + stat = BLKPREP_KILL; + } + + if (bd->suspended) { + blk_plug_device(bd->queue.queue); + stat = BLKPREP_DEFER; + } + + /* Check for excessive requests.*/ + if (blk_rq_pos(req) + blk_rq_sectors(req) > get_capacity(req->rq_disk)) { + cy_as_hal_print_message("cyasblkdev: bad request address\n"); + stat = BLKPREP_KILL; + } + + return stat; +} + +/*west bridge storage async api on_completed callback */ +static void cyasblkdev_issuecallback( + /* Handle to the device completing the storage operation */ + cy_as_device_handle handle, + /* The media type completing the operation */ + cy_as_media_type type, + /* The device completing the operation */ + uint32_t device, + /* The unit completing the operation */ + uint32_t unit, + /* The block number of the completed operation */ + uint32_t block_number, + /* The type of operation */ + cy_as_oper_type op, + /* The error status */ + cy_as_return_status_t status + ) +{ + int retry_cnt = 0; + DBGPRN_FUNC_NAME; + + if (status != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: async r/w: op:%d failed with error %d at address %d\n", + __func__, op, status, block_number) ; + #endif + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s calling blk_end_request from issue_callback " + "req=0x%x, status=0x%x, nr_sectors=0x%x\n", + __func__, (unsigned int) gl_bd->queue.req, status, + (unsigned int) blk_rq_sectors(gl_bd->queue.req)) ; + #endif + + /* note: blk_end_request w/o __ prefix should + * not require spinlocks on the queue*/ + while (blk_end_request(gl_bd->queue.req, + status, blk_rq_sectors(gl_bd->queue.req)*512)) { + retry_cnt++; + }; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s blkdev_callback: ended rq on %d sectors, " + "with err:%d, n:%d times\n", __func__, + (int)blk_rq_sectors(gl_bd->queue.req), status, + retry_cnt + ); + #endif + + spin_lock_irq(&gl_bd->lock); + + /*elevate next request, if there is one*/ + if (!blk_queue_plugged(gl_bd->queue.queue)) { + /* queue is not plugged */ + gl_bd->queue.req = blk_fetch_request(gl_bd->queue.queue); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s blkdev_callback: " + "blk_fetch_request():%p\n", + __func__, gl_bd->queue.req); + #endif + } + + if (gl_bd->queue.req) { + spin_unlock_irq(&gl_bd->lock); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s blkdev_callback: about to " + "call issue_fn:%p\n", __func__, gl_bd->queue.req); + #endif + + gl_bd->queue.issue_fn(&gl_bd->queue, gl_bd->queue.req); + } else { + spin_unlock_irq(&gl_bd->lock); + } +} + +/* issue astoria blkdev request (issue_fn) */ +static int cyasblkdev_blk_issue_rq( + struct cyasblkdev_queue *bq, + struct request *req + ) +{ + struct cyasblkdev_blk_data *bd = bq->data; + int index = 0 ; + int ret = CY_AS_ERROR_SUCCESS; + uint32_t req_sector = 0; + uint32_t req_nr_sectors = 0; + int bus_num = 0; + int lcl_unit_no = 0; + + DBGPRN_FUNC_NAME; + + /* + * will construct a scatterlist for the given request; + * the return value is the number of actually used + * entries in the resulting list. Then, this scatterlist + * can be used for the actual DMA prep operation. + */ + spin_lock_irq(&bd->lock); + index = blk_rq_map_sg(bq->queue, req, bd->sg); + + if (req->rq_disk == bd->user_disk_0) { + bus_num = bd->user_disk_0_bus_num; + req_sector = blk_rq_pos(req) + gl_bd->user_disk_0_first_sector; + req_nr_sectors = blk_rq_sectors(req); + lcl_unit_no = gl_bd->user_disk_0_unit_no; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: request made to disk 0 " + "for sector=%d, num_sectors=%d, unit_no=%d\n", + __func__, req_sector, (int) blk_rq_sectors(req), + lcl_unit_no); + #endif + } else if (req->rq_disk == bd->user_disk_1) { + bus_num = bd->user_disk_1_bus_num; + req_sector = blk_rq_pos(req) + gl_bd->user_disk_1_first_sector; + /*SECT_NUM_TRANSLATE(blk_rq_sectors(req));*/ + req_nr_sectors = blk_rq_sectors(req); + lcl_unit_no = gl_bd->user_disk_1_unit_no; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: request made to disk 1 for " + "sector=%d, num_sectors=%d, unit_no=%d\n", __func__, + req_sector, (int) blk_rq_sectors(req), lcl_unit_no); + #endif + } else if (req->rq_disk == bd->system_disk) { + bus_num = bd->system_disk_bus_num; + req_sector = blk_rq_pos(req) + gl_bd->system_disk_first_sector; + req_nr_sectors = blk_rq_sectors(req); + lcl_unit_no = gl_bd->system_disk_unit_no; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: request made to system disk " + "for sector=%d, num_sectors=%d, unit_no=%d\n", __func__, + req_sector, (int) blk_rq_sectors(req), lcl_unit_no); + #endif + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message( + "%s: invalid disk used for request\n", __func__); + } + #endif + + spin_unlock_irq(&bd->lock); + + if (rq_data_dir(req) == READ) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: calling readasync() " + "req_sector=0x%x, req_nr_sectors=0x%x, bd->sg:%x\n\n", + __func__, req_sector, req_nr_sectors, (uint32_t)bd->sg); + #endif + + ret = cy_as_storage_read_async(bd->dev_handle, bus_num, 0, + lcl_unit_no, req_sector, bd->sg, req_nr_sectors, + (cy_as_storage_callback)cyasblkdev_issuecallback); + + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s:readasync() error %d at " + "address %ld, unit no %d\n", __func__, ret, + blk_rq_pos(req), lcl_unit_no); + cy_as_hal_print_message("%s:ending i/o request " + "on reg:%x\n", __func__, (uint32_t)req); + #endif + + while (blk_end_request(req, + (ret == CY_AS_ERROR_SUCCESS), + req_nr_sectors*512)) + ; + + bq->req = NULL ; + } + } else { + ret = cy_as_storage_write_async(bd->dev_handle, bus_num, 0, + lcl_unit_no, req_sector, bd->sg, req_nr_sectors, + (cy_as_storage_callback)cyasblkdev_issuecallback); + + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: write failed with " + "error %d at address %ld, unit no %d\n", + __func__, ret, blk_rq_pos(req), lcl_unit_no); + #endif + + /*end IO op on this request(does both + * end_that_request_... _first & _last) */ + while (blk_end_request(req, + (ret == CY_AS_ERROR_SUCCESS), + req_nr_sectors*512)) + ; + + bq->req = NULL ; + } + } + + return ret; +} + +static unsigned long +dev_use[CYASBLKDEV_NUM_MINORS / (8 * sizeof(unsigned long))]; + + +/* storage event callback (note: called in astoria isr context) */ +static void cyasblkdev_storage_callback( + cy_as_device_handle dev_h, + cy_as_bus_number_t bus, + uint32_t device, + cy_as_storage_event evtype, + void *evdata + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: bus:%d, device:%d, evtype:%d, " + "evdata:%p\n ", __func__, bus, device, evtype, evdata); + #endif + + switch (evtype) { + case cy_as_storage_processor: + break; + + case cy_as_storage_removed: + break; + + case cy_as_storage_inserted: + break; + + default: + break; + } +} + +#define SECTORS_TO_SCAN 4096 + +uint32_t cyasblkdev_get_vfat_offset(int bus_num, int unit_no) +{ + /* + * for sd media, vfat partition boot record is not always + * located at sector it greatly depends on the system and + * software that was used to format the sd however, linux + * fs layer always expects it at sector 0, this function + * finds the offset and then uses it in all media r/w + * operations + */ + int sect_no, stat; + uint8_t *sect_buf; + bool br_found = false; + + DBGPRN_FUNC_NAME; + + sect_buf = kmalloc(1024, GFP_KERNEL); + + /* since HAL layer always uses sg lists instead of the + * buffer (for hw dmas) we need to initialize the sg list + * for local buffer*/ + sg_init_one(gl_bd->sg, sect_buf, 512); + + /* + * Check MPR partition table 1st, then try to scan through + * 1st 384 sectors until BR signature(intel JMP istruction + * code and ,0x55AA) is found + */ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s scanning media for vfat partition...\n", __func__) ; + #endif + + for (sect_no = 0; sect_no < SECTORS_TO_SCAN; sect_no++) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s before cyasstorageread " + "gl_bd->sg addr=0x%x\n", __func__, + (unsigned int) gl_bd->sg); + #endif + + stat = cy_as_storage_read( + /* Handle to the device of interest */ + gl_bd->dev_handle, + /* The bus to access */ + bus_num, + /* The device to access */ + 0, + /* The unit to access */ + unit_no, + /* absolute sector number */ + sect_no, + /* sg structure */ + gl_bd->sg, + /* The number of blocks to be read */ + 1 + ); + + /* try only sectors with boot signature */ + if ((sect_buf[510] == 0x55) && (sect_buf[511] == 0xaa)) { + /* vfat boot record may also be located at + * sector 0, check it first */ + if (sect_buf[0] == 0xEB) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s vfat partition found " + "at sector:%d\n", + __func__, sect_no); + #endif + + br_found = true; + break; + } + } + + if (stat != 0) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s sector scan error\n", + __func__); + #endif + break; + } + } + + kfree(sect_buf); + + if (br_found) { + return sect_no; + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s vfat partition is not found, using 0 offset\n", + __func__); + #endif + return 0; + } +} + +cy_as_storage_query_device_data dev_data = {0} ; + +static int cyasblkdev_add_disks(int bus_num, + struct cyasblkdev_blk_data *bd, + int total_media_count, + int devidx) +{ + int ret = 0; + uint64_t disk_cap; + int lcl_unit_no; + cy_as_storage_query_unit_data unit_data = {0} ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s:query device: " + "type:%d, removable:%d, writable:%d, " + "blksize %d, units:%d, locked:%d, " + "erase_sz:%d\n", + __func__, + dev_data.desc_p.type, + dev_data.desc_p.removable, + dev_data.desc_p.writeable, + dev_data.desc_p.block_size, + dev_data.desc_p.number_units, + dev_data.desc_p.locked, + dev_data.desc_p.erase_unit_size + ); + #endif + + /* make sure that device is not locked */ + if (dev_data.desc_p.locked) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: device is locked\n", __func__); + #endif + ret = cy_as_storage_release( + bd->dev_handle, bus_num, 0, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s cannot release" + " storage\n", __func__) ; + #endif + goto out; + } + goto out; + } + + unit_data.device = 0 ; + unit_data.unit = 0 ; + unit_data.bus = bus_num; + ret = cy_as_storage_query_unit(bd->dev_handle, + &unit_data, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot query " + "%d device unit - reason code %d\n", + __func__, bus_num, ret) ; + #endif + goto out ; + } + + if (private_partition_bus == bus_num) { + if (private_partition_size > 0) { + ret = cy_as_storage_create_p_partition( + bd->dev_handle, bus_num, 0, + private_partition_size, 0, 0); + if ((ret != CY_AS_ERROR_SUCCESS) && + (ret != CY_AS_ERROR_ALREADY_PARTITIONED)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_storage_" + "create_p_partition after size > 0 check " + "failed with error code %d\n", + __func__, ret); + #endif + + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = 0; + + } else if (ret == CY_AS_ERROR_ALREADY_PARTITIONED) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cy_as_storage_create_p_partition " + "indicates memory already partitioned\n", + __func__); + #endif + + /*check to see that partition + * matches size */ + if (unit_data.desc_p.unit_size != + private_partition_size) { + ret = cy_as_storage_remove_p_partition( + bd->dev_handle, + bus_num, 0, 0, 0); + if (ret == CY_AS_ERROR_SUCCESS) { + ret = cy_as_storage_create_p_partition( + bd->dev_handle, bus_num, 0, + private_partition_size, 0, 0); + if (ret == CY_AS_ERROR_SUCCESS) { + unit_data.bus = bus_num ; + unit_data.device = 0 ; + unit_data.unit = 1 ; + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cy_as_storage_create_p_partition " + "after removal unexpectedly failed " + "with error %d\n", __func__, ret) ; + #endif + + /* need to requery bus + * seeing as delete + * successful and create + * failed we have changed + * the disk properties */ + unit_data.bus = bus_num ; + unit_data.device = 0 ; + unit_data.unit = 0 ; + } + + ret = cy_as_storage_query_unit( + bd->dev_handle, + &unit_data, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cannot query %d " + "device unit - reason code %d\n", + __func__, bus_num, ret) ; + #endif + goto out ; + } else { + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = + unit_data.unit; + } + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cy_as_storage_remove_p_partition " + "failed with error %d\n", + __func__, ret); + #endif + + unit_data.bus = bus_num ; + unit_data.device = 0 ; + unit_data.unit = 1 ; + + ret = cy_as_storage_query_unit( + bd->dev_handle, &unit_data, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cannot query %d " + "device unit - reason " + "code %d\n", __func__, + bus_num, ret) ; + #endif + goto out ; + } + + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = + unit_data.unit ; + } + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: partition " + "exists and sizes equal\n", + __func__); + #endif + + /*partition already existed, + * need to query second unit*/ + unit_data.bus = bus_num ; + unit_data.device = 0 ; + unit_data.unit = 1 ; + + ret = cy_as_storage_query_unit( + bd->dev_handle, &unit_data, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cannot query %d " + "device unit " + "- reason code %d\n", + __func__, bus_num, ret) ; + #endif + goto out ; + } else { + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = unit_data.unit ; + } + } + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cy_as_storage_create_p_partition " + "created successfully\n", __func__); + #endif + + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size - + private_partition_size); + + lcl_unit_no = 1; + } + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message( + "%s: invalid partition_size%d\n", __func__, + private_partition_size); + + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = 0; + } + #endif + } else { + disk_cap = (uint64_t) + (unit_data.desc_p.unit_size); + lcl_unit_no = 0; + } + + if ((bus_num == 0) || + (total_media_count == 1)) { + sprintf(bd->user_disk_0->disk_name, + "cyasblkdevblk%d", devidx); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: disk unit_sz:%lu blk_sz:%d, " + "start_blk:%lu, capacity:%llu\n", + __func__, (unsigned long) + unit_data.desc_p.unit_size, + unit_data.desc_p.block_size, + (unsigned long) + unit_data.desc_p.start_block, + (uint64_t)disk_cap + ); + #endif + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: setting gendisk disk " + "capacity to %d\n", __func__, (int) disk_cap); + #endif + + /* initializing bd->queue */ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: init bd->queue\n", + __func__); + #endif + + /* this will create a + * queue kernel thread */ + cyasblkdev_init_queue( + &bd->queue, &bd->lock) ; + + bd->queue.prep_fn = cyasblkdev_blk_prep_rq; + bd->queue.issue_fn = cyasblkdev_blk_issue_rq; + bd->queue.data = bd; + + /*blk_size should always + * be a multiple of 512, + * set to the max to ensure + * that all accesses aligned + * to the greatest multiple, + * can adjust request to + * smaller block sizes + * dynamically*/ + + bd->user_disk_0_read_only = !dev_data.desc_p.writeable; + bd->user_disk_0_blk_size = dev_data.desc_p.block_size; + bd->user_disk_0_type = dev_data.desc_p.type; + bd->user_disk_0_bus_num = bus_num; + bd->user_disk_0->major = major; + bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT; + bd->user_disk_0->minors = 8; + bd->user_disk_0->fops = &cyasblkdev_bdops; + bd->user_disk_0->private_data = bd; + bd->user_disk_0->queue = bd->queue.queue; + bd->dbgprn_flags = DBGPRN_RD_RQ; + bd->user_disk_0_unit_no = lcl_unit_no; + + blk_queue_logical_block_size(bd->queue.queue, + bd->user_disk_0_blk_size); + + set_capacity(bd->user_disk_0, + disk_cap); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: returned from set_capacity %d\n", + __func__, (int) disk_cap); + #endif + + /* need to start search from + * public partition beginning */ + if (vfat_search) { + bd->user_disk_0_first_sector = + cyasblkdev_get_vfat_offset(0, + bd->user_disk_0_unit_no); + } else { + bd->user_disk_0_first_sector = 0; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: set user_disk_0_first " + "sector to %d\n", __func__, + bd->user_disk_0_first_sector); + cy_as_hal_print_message( + "%s: add_disk: disk->major=0x%x\n", + __func__, + bd->user_disk_0->major); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->first_minor=0x%x\n", __func__, + bd->user_disk_0->first_minor); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->minors=0x%x\n", __func__, + bd->user_disk_0->minors); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->disk_name=%s\n", + __func__, + bd->user_disk_0->disk_name); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->part_tbl=0x%x\n", __func__, + (unsigned int) + bd->user_disk_0->part_tbl); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->queue=0x%x\n", __func__, + (unsigned int) + bd->user_disk_0->queue); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->flags=0x%x\n", + __func__, (unsigned int) + bd->user_disk_0->flags); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->driverfs_dev=0x%x\n", + __func__, (unsigned int) + bd->user_disk_0->driverfs_dev); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->slave_dir=0x%x\n", + __func__, (unsigned int) + bd->user_disk_0->slave_dir); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->random=0x%x\n", + __func__, (unsigned int) + bd->user_disk_0->random); + cy_as_hal_print_message( + "%s: add_disk: " + "disk->node_id=0x%x\n", + __func__, (unsigned int) + bd->user_disk_0->node_id); + + #endif + + add_disk(bd->user_disk_0); + + } else if ((bus_num == 1) && + (total_media_count == 2)) { + bd->user_disk_1_read_only = !dev_data.desc_p.writeable; + bd->user_disk_1_blk_size = dev_data.desc_p.block_size; + bd->user_disk_1_type = dev_data.desc_p.type; + bd->user_disk_1_bus_num = bus_num; + bd->user_disk_1->major = major; + bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT; + bd->user_disk_1->minors = 8; + bd->user_disk_1->fops = &cyasblkdev_bdops; + bd->user_disk_1->private_data = bd; + bd->user_disk_1->queue = bd->queue.queue; + bd->dbgprn_flags = DBGPRN_RD_RQ; + bd->user_disk_1_unit_no = lcl_unit_no; + + sprintf(bd->user_disk_1->disk_name, + "cyasblkdevblk%d", (devidx + 1)); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: disk unit_sz:%lu " + "blk_sz:%d, " + "start_blk:%lu, " + "capacity:%llu\n", + __func__, + (unsigned long) + unit_data.desc_p.unit_size, + unit_data.desc_p.block_size, + (unsigned long) + unit_data.desc_p.start_block, + (uint64_t)disk_cap + ); + #endif + + /*blk_size should always be a + * multiple of 512, set to the max + * to ensure that all accesses + * aligned to the greatest multiple, + * can adjust request to smaller + * block sizes dynamically*/ + if (bd->user_disk_0_blk_size > + bd->user_disk_1_blk_size) { + blk_queue_logical_block_size(bd->queue.queue, + bd->user_disk_0_blk_size); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: set hard sect_sz:%d\n", + __func__, + bd->user_disk_0_blk_size); + #endif + } else { + blk_queue_logical_block_size(bd->queue.queue, + bd->user_disk_1_blk_size); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: set hard sect_sz:%d\n", + __func__, + bd->user_disk_1_blk_size); + #endif + } + + set_capacity(bd->user_disk_1, disk_cap); + if (vfat_search) { + bd->user_disk_1_first_sector = + cyasblkdev_get_vfat_offset( + 1, bd->user_disk_1_unit_no); + } else { + bd->user_disk_1_first_sector + = 0; + } + + add_disk(bd->user_disk_1); + } + + if (lcl_unit_no > 0) { + if (bd->system_disk == NULL) { + bd->system_disk = + alloc_disk(CYASBLKDEV_MINOR_2 + << CYASBLKDEV_SHIFT); + if (bd->system_disk == NULL) { + kfree(bd); + bd = ERR_PTR(-ENOMEM); + return bd ; + } + disk_cap = (uint64_t) + (private_partition_size); + + /* set properties of + * system disk */ + bd->system_disk_read_only = !dev_data.desc_p.writeable; + bd->system_disk_blk_size = dev_data.desc_p.block_size; + bd->system_disk_bus_num = bus_num; + bd->system_disk->major = major; + bd->system_disk->first_minor = + (devidx + 2) << CYASBLKDEV_SHIFT; + bd->system_disk->minors = 8; + bd->system_disk->fops = &cyasblkdev_bdops; + bd->system_disk->private_data = bd; + bd->system_disk->queue = bd->queue.queue; + /* don't search for vfat + * with system disk */ + bd->system_disk_first_sector = 0; + sprintf( + bd->system_disk->disk_name, + "cyasblkdevblk%d", (devidx + 2)); + + set_capacity(bd->system_disk, + disk_cap); + + add_disk(bd->system_disk); + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message( + "%s: system disk already allocated %d\n", + __func__, bus_num) ; + } + #endif + } +out: + return ret; +} + +static struct cyasblkdev_blk_data *cyasblkdev_blk_alloc(void) +{ + struct cyasblkdev_blk_data *bd; + int ret = 0 ; + cy_as_return_status_t stat = -1 ; + int bus_num = 0; + int total_media_count = 0; + int devidx = 0; + DBGPRN_FUNC_NAME; + + total_media_count = 0; + devidx = find_first_zero_bit(dev_use, CYASBLKDEV_NUM_MINORS); + if (devidx >= CYASBLKDEV_NUM_MINORS) + return ERR_PTR(-ENOSPC); + + __set_bit(devidx, dev_use); + __set_bit(devidx + 1, dev_use); + + bd = kzalloc(sizeof(struct cyasblkdev_blk_data), GFP_KERNEL); + if (bd) { + gl_bd = bd ; + + spin_lock_init(&bd->lock); + bd->usage = 1; + + /* setup the block_dev_ops pointer*/ + bd->blkops = &cyasblkdev_bdops; + + /* Get the device handle */ + bd->dev_handle = cyasdevice_getdevhandle() ; + if (0 == bd->dev_handle) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: get device failed\n", __func__) ; + #endif + ret = ENODEV ; + goto out ; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s west bridge device handle:%x\n", + __func__, (uint32_t)bd->dev_handle); + #endif + + /* start the storage api and get a handle to the + * device we are interested in. */ + + /* Error code to use if the conditions are not satisfied. */ + ret = ENOMEDIUM ; + + stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_0); + if ((stat != CY_AS_ERROR_SUCCESS) && + (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot release " + "resource bus 0 - reason code %d\n", + __func__, stat) ; + #endif + } + + stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_1); + if ((stat != CY_AS_ERROR_SUCCESS) && + (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot release " + "resource bus 0 - reason code %d\n", + __func__, stat) ; + #endif + } + + /* start storage stack*/ + stat = cy_as_storage_start(bd->dev_handle, 0, 0x101) ; + if (stat != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot start storage " + "stack - reason code %d\n", __func__, stat) ; + #endif + goto out; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: storage started:%d ok\n", + __func__, stat); + #endif + + stat = cy_as_storage_register_callback(bd->dev_handle, + cyasblkdev_storage_callback); + if (stat != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot register callback " + "- reason code %d\n", __func__, stat) ; + #endif + goto out; + } + + for (bus_num = 0; bus_num < 2; bus_num++) { + stat = cy_as_storage_query_bus(bd->dev_handle, + bus_num, &bd->media_count[bus_num], 0, 0) ; + if (stat == CY_AS_ERROR_SUCCESS) { + total_media_count = total_media_count + + bd->media_count[bus_num]; + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cannot query %d, " + "reason code: %d\n", + __func__, bus_num, stat) ; + #endif + goto out; + } + } + + if (total_media_count == 0) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: no storage media was found\n", __func__) ; + #endif + goto out ; + } else if (total_media_count >= 1) { + if (bd->user_disk_0 == NULL) { + + bd->user_disk_0 = + alloc_disk(CYASBLKDEV_MINOR_0 + << CYASBLKDEV_SHIFT); + if (bd->user_disk_0 == NULL) { + kfree(bd); + bd = ERR_PTR(-ENOMEM); + return bd ; + } + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message("%s: no available " + "gen_disk for disk 0, " + "physically inconsistent\n", __func__); + } + #endif + } + + if (total_media_count == 2) { + if (bd->user_disk_1 == NULL) { + bd->user_disk_1 = + alloc_disk(CYASBLKDEV_MINOR_1 + << CYASBLKDEV_SHIFT); + if (bd->user_disk_1 == NULL) { + kfree(bd); + bd = ERR_PTR(-ENOMEM); + return bd ; + } + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message("%s: no available " + "gen_disk for media, " + "physically inconsistent\n", __func__); + } + #endif + } + #ifndef WESTBRIDGE_NDEBUG + else if (total_media_count > 2) { + cy_as_hal_print_message("%s: count corrupted = 0x%d\n", + __func__, total_media_count); + } + #endif + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: %d device(s) found\n", + __func__, total_media_count) ; + #endif + + for (bus_num = 0; bus_num <= 1; bus_num++) { + /*claim storage for cpu */ + stat = cy_as_storage_claim(bd->dev_handle, + bus_num, 0, 0, 0) ; + if (stat != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("%s: cannot claim " + "%d bus - reason code %d\n", + __func__, bus_num, stat) ; + goto out; + } + + dev_data.bus = bus_num ; + dev_data.device = 0 ; + + stat = cy_as_storage_query_device(bd->dev_handle, + &dev_data, 0, 0) ; + if (stat == CY_AS_ERROR_SUCCESS) { + cyasblkdev_add_disks(bus_num, bd, + total_media_count, devidx); + } else if (stat == CY_AS_ERROR_NO_SUCH_DEVICE) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: no device on bus %d\n", + __func__, bus_num) ; + #endif + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cannot query %d device " + "- reason code %d\n", + __func__, bus_num, stat) ; + #endif + goto out ; + } + } /* end for (bus_num = 0; bus_num <= 1; bus_num++)*/ + + return bd ; + } +out: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: bd failed to initialize\n", __func__); + #endif + + kfree(bd); + bd = ERR_PTR(-ret); + return bd; +} + + +/*init west bridge block device */ +static int cyasblkdev_blk_initialize(void) +{ + struct cyasblkdev_blk_data *bd; + int res; + + DBGPRN_FUNC_NAME; + + res = register_blkdev(major, "cyasblkdev"); + + if (res < 0) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message(KERN_WARNING + "%s unable to get major %d for cyasblkdev media: %d\n", + __func__, major, res); + #endif + return res; + } + + if (major == 0) + major = res; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s cyasblkdev registered with major number: %d\n", + __func__, major) ; + #endif + + bd = cyasblkdev_blk_alloc(); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + return 0; +} + +/* start block device */ +static int __init cyasblkdev_blk_init(void) +{ + int res = -ENOMEM; + + DBGPRN_FUNC_NAME; + + /* get the cyasdev handle for future use*/ + cyas_dev_handle = cyasdevice_getdevhandle(); + + if (cyasblkdev_blk_initialize() == 0) + return 0; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("cyasblkdev init error:%d\n", res); + #endif + return res; +} + + +static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd) +{ + DBGPRN_FUNC_NAME; + + if (bd) { + int devidx; + + if (bd->user_disk_0 != NULL) { + del_gendisk(bd->user_disk_0); + devidx = bd->user_disk_0->first_minor + >> CYASBLKDEV_SHIFT; + __clear_bit(devidx, dev_use); + } + + if (bd->user_disk_1 != NULL) { + del_gendisk(bd->user_disk_1); + devidx = bd->user_disk_1->first_minor + >> CYASBLKDEV_SHIFT; + __clear_bit(devidx, dev_use); + } + + if (bd->system_disk != NULL) { + del_gendisk(bd->system_disk); + devidx = bd->system_disk->first_minor + >> CYASBLKDEV_SHIFT; + __clear_bit(devidx, dev_use); + } + + cyasblkdev_blk_put(bd); + } +} + +/* block device exit */ +static void __exit cyasblkdev_blk_exit(void) +{ + DBGPRN_FUNC_NAME; + + cyasblkdev_blk_deinit(gl_bd); + unregister_blkdev(major, "cyasblkdev"); + +} + +module_init(cyasblkdev_blk_init); +module_exit(cyasblkdev_blk_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("antioch (cyasblkdev) block device driver"); +MODULE_AUTHOR("cypress semiconductor"); + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c new file mode 100644 index 000000000000..8dc29bd2891d --- /dev/null +++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.c @@ -0,0 +1,417 @@ +/* cyanblkdev_queue.h - Antioch Linux Block Driver queue source file +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * Request queue handling for Antioch block device driver. + * Based on the mmc queue handling code by Russell King in the + * linux 2.6.10 kernel. + */ + +/* + * linux/drivers/mmc/mmc_queue.c + * + * Copyright (C) 2003 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include + +#include "cyasblkdev_queue.h" + +#define CYASBLKDEV_QUEUE_EXIT (1 << 0) +#define CYASBLKDEV_QUEUE_SUSPENDED (1 << 1) +#define CY_AS_USE_ASYNC_API + + + +/* print flags by name */ +const char *rq_flag_bit_names[] = { + "REQ_RW", /* not set, read. set, write */ + "REQ_FAILFAST", /* no low level driver retries */ + "REQ_SORTED", /* elevator knows about this request */ + "REQ_SOFTBARRIER", /* may not be passed by ioscheduler */ + "REQ_HARDBARRIER", /* may not be passed by drive either */ + "REQ_FUA", /* forced unit access */ + "REQ_NOMERGE", /* don't touch this for merging */ + "REQ_STARTED", /* drive already may have started this one */ + "REQ_DONTPREP", /* don't call prep for this one */ + "REQ_QUEUED", /* uses queueing */ + "REQ_ELVPRIV", /* elevator private data attached */ + "REQ_FAILED", /* set if the request failed */ + "REQ_QUIET", /* don't worry about errors */ + "REQ_PREEMPT", /* set for "ide_preempt" requests */ + "REQ_ORDERED_COLOR",/* is before or after barrier */ + "REQ_RW_SYNC", /* request is sync (O_DIRECT) */ + "REQ_ALLOCED", /* request came from our alloc pool */ + "REQ_RW_META", /* metadata io request */ + "REQ_COPY_USER", /* contains copies of user pages */ + "REQ_NR_BITS", /* stops here */ +}; + +void verbose_rq_flags(int flags) +{ + int i; + uint32_t j; + j = 1; + for (i = 0; i < 32; i++) { + if (flags & j) + DBGPRN("<1>%s", rq_flag_bit_names[i]); + j = j << 1; + } +} + + +/* + * Prepare a -BLK_DEV request. Essentially, this means passing the + * preparation off to the media driver. The media driver will + * create request to CyAsDev. + */ +static int cyasblkdev_prep_request( + struct request_queue *q, struct request *req) +{ + DBGPRN_FUNC_NAME; + + /* we only like normal block requests.*/ + if (!blk_fs_request(req)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s:%x bad request received\n", + __func__, current->pid) ; + #endif + + blk_dump_rq_flags(req, "cyasblkdev bad request"); + return BLKPREP_KILL; + } + + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +} + +/* queue worker thread */ +static int cyasblkdev_queue_thread(void *d) +{ + DECLARE_WAITQUEUE(wait, current); + struct cyasblkdev_queue *bq = d; + struct request_queue *q = bq->queue; + u32 qth_pid; + + DBGPRN_FUNC_NAME; + + /* + * set iothread to ensure that we aren't put to sleep by + * the process freezing. we handle suspension ourselves. + */ + daemonize("cyasblkdev_queue_thread"); + + /* signal to queue_init() so it could contnue */ + complete(&bq->thread_complete); + + down(&bq->thread_sem); + add_wait_queue(&bq->thread_wq, &wait); + + qth_pid = current->pid; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s:%x started, bq:%p, q:%p\n", __func__, qth_pid, bq, q) ; + #endif + + do { + struct request *req = NULL; + + /* the thread wants to be woken up by signals as well */ + set_current_state(TASK_INTERRUPTIBLE); + + spin_lock_irq(q->queue_lock); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: for bq->queue is null\n", __func__); + #endif + + if (!bq->req) { + /* chk if queue is plugged */ + if (!blk_queue_plugged(q)) { + bq->req = req = blk_fetch_request(q); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: blk_fetch_request:%x\n", + __func__, (uint32_t)req); + #endif + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: queue plugged, " + "skip blk_fetch()\n", __func__); + #endif + } + } + spin_unlock_irq(q->queue_lock); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: checking if request queue is null\n", __func__); + #endif + + if (!req) { + if (bq->flags & CYASBLKDEV_QUEUE_EXIT) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s:got QUEUE_EXIT flag\n", __func__); + #endif + + break; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: request queue is null, goto sleep, " + "thread_sem->count=%d\n", + __func__, bq->thread_sem.count); + if (spin_is_locked(q->queue_lock)) { + cy_as_hal_print_message("%s: queue_lock " + "is locked, need to release\n", __func__); + spin_unlock(q->queue_lock); + + if (spin_is_locked(q->queue_lock)) + cy_as_hal_print_message( + "%s: unlock did not work\n", + __func__); + } else { + cy_as_hal_print_message( + "%s: checked lock, is not locked\n", + __func__); + } + #endif + + up(&bq->thread_sem); + + /* yields to the next rdytorun proc, + * then goes back to sleep*/ + schedule(); + down(&bq->thread_sem); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: wake_up,continue\n", + __func__); + #endif + continue; + } + + /* new req recieved, issue it to the driver */ + set_current_state(TASK_RUNNING); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: issued a RQ:%x\n", + __func__, (uint32_t)req); + #endif + + bq->issue_fn(bq, req); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: bq->issue_fn() returned\n", + __func__); + #endif + + + } while (1); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&bq->thread_wq, &wait); + up(&bq->thread_sem); + + complete_and_exit(&bq->thread_complete, 0); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: is finished\n", __func__) ; + #endif + + return 0; +} + +/* + * Generic request handler. it is called for any queue on a + * particular host. When the host is not busy, we look for a request + * on any queue on this host, and attempt to issue it. This may + * not be the queue we were asked to process. + */ +static void cyasblkdev_request(struct request_queue *q) +{ + struct cyasblkdev_queue *bq = q->queuedata; + DBGPRN_FUNC_NAME; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s new request on cyasblkdev_queue_t bq:=%x\n", + __func__, (uint32_t)bq); + #endif + + if (!bq->req) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s wake_up(&bq->thread_wq)\n", + __func__); + #endif + + /* wake up cyasblkdev_queue worker thread*/ + wake_up(&bq->thread_wq); + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: don't wake Q_thr, bq->req:%x\n", + __func__, (uint32_t)bq->req); + #endif + } +} + +/* + * cyasblkdev_init_queue - initialise a queue structure. + * @bq: cyasblkdev queue + * @dev: CyAsDeviceHandle to attach this queue + * @lock: queue lock + * + * Initialise a cyasblkdev_request queue. + */ + +/* MAX NUMBER OF SECTORS PER REQUEST **/ +#define Q_MAX_SECTORS 128 + +/* MAX NUMBER OF PHYS SEGMENTS (entries in the SG list)*/ +#define Q_MAX_SGS 16 + +int cyasblkdev_init_queue(struct cyasblkdev_queue *bq, spinlock_t *lock) +{ + int ret; + + DBGPRN_FUNC_NAME; + + /* 1st param is a function that wakes up the queue thread */ + bq->queue = blk_init_queue(cyasblkdev_request, lock); + if (!bq->queue) + return -ENOMEM; + + blk_queue_prep_rq(bq->queue, cyasblkdev_prep_request); + + blk_queue_bounce_limit(bq->queue, BLK_BOUNCE_ANY); + blk_queue_max_hw_sectors(bq->queue, Q_MAX_SECTORS); + + /* As of now, we have the HAL/driver support to + * merge scattered segments and handle them simultaneously. + * so, setting the max_phys_segments to 8. */ + /*blk_queue_max_phys_segments(bq->queue, Q_MAX_SGS); + blk_queue_max_hw_segments(bq->queue, Q_MAX_SGS);*/ + blk_queue_max_segments(bq->queue, Q_MAX_SGS); + + /* should be < then HAL can handle */ + blk_queue_max_segment_size(bq->queue, 512*Q_MAX_SECTORS); + + bq->queue->queuedata = bq; + bq->req = NULL; + + init_completion(&bq->thread_complete); + init_waitqueue_head(&bq->thread_wq); + init_MUTEX(&bq->thread_sem); + + ret = kernel_thread(cyasblkdev_queue_thread, bq, CLONE_KERNEL); + if (ret >= 0) { + /* wait until the thread is spawned */ + wait_for_completion(&bq->thread_complete); + + /* reinitialize the completion */ + init_completion(&bq->thread_complete); + ret = 0; + goto out; + } + +out: + return ret; +} +EXPORT_SYMBOL(cyasblkdev_init_queue); + +/*called from blk_put() */ +void cyasblkdev_cleanup_queue(struct cyasblkdev_queue *bq) +{ + DBGPRN_FUNC_NAME; + + bq->flags |= CYASBLKDEV_QUEUE_EXIT; + wake_up(&bq->thread_wq); + wait_for_completion(&bq->thread_complete); + + blk_cleanup_queue(bq->queue); +} +EXPORT_SYMBOL(cyasblkdev_cleanup_queue); + + +/** + * cyasblkdev_queue_suspend - suspend a CyAsBlkDev request queue + * @bq: CyAsBlkDev queue to suspend + * + * Stop the block request queue, and wait for our thread to + * complete any outstanding requests. This ensures that we + * won't suspend while a request is being processed. + */ +void cyasblkdev_queue_suspend(struct cyasblkdev_queue *bq) +{ + struct request_queue *q = bq->queue; + unsigned long flags; + + DBGPRN_FUNC_NAME; + + if (!(bq->flags & CYASBLKDEV_QUEUE_SUSPENDED)) { + bq->flags |= CYASBLKDEV_QUEUE_SUSPENDED; + + spin_lock_irqsave(q->queue_lock, flags); + blk_stop_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + + down(&bq->thread_sem); + } +} +EXPORT_SYMBOL(cyasblkdev_queue_suspend); + +/*cyasblkdev_queue_resume - resume a previously suspended + * CyAsBlkDev request queue @bq: CyAsBlkDev queue to resume */ +void cyasblkdev_queue_resume(struct cyasblkdev_queue *bq) +{ + struct request_queue *q = bq->queue; + unsigned long flags; + + DBGPRN_FUNC_NAME; + + if (bq->flags & CYASBLKDEV_QUEUE_SUSPENDED) { + bq->flags &= ~CYASBLKDEV_QUEUE_SUSPENDED; + + up(&bq->thread_sem); + + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } +} +EXPORT_SYMBOL(cyasblkdev_queue_resume); + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h new file mode 100644 index 000000000000..26f9f596506d --- /dev/null +++ b/drivers/staging/westbridge/astoria/block/cyasblkdev_queue.h @@ -0,0 +1,64 @@ +/* cyanblkdev_queue.h - Antioch Linux Block Driver queue header file +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANBLKDEV_QUEUE_H_ +#define _INCLUDED_CYANBLKDEV_QUEUE_H_ + +/* + * may contain various useful MACRO and debug printks + */ + +/* moved to staging location, eventual implementation + * considered is here + * #include + * #include + * */ + +#include "../include/linux/westbridge/cyashal.h" +#include "../include/linux/westbridge/cyastoria.h" + +struct request; +struct task_struct; + +struct cyasblkdev_queue { + struct completion thread_complete; + wait_queue_head_t thread_wq; + struct semaphore thread_sem; + unsigned int flags; + struct request *req; + int (*prep_fn)(struct cyasblkdev_queue *, struct request *); + int (*issue_fn)(struct cyasblkdev_queue *, struct request *); + void *data; + struct request_queue *queue; +}; + +extern int cyasblkdev_init_queue(struct cyasblkdev_queue *, spinlock_t *); +extern void cyasblkdev_cleanup_queue(struct cyasblkdev_queue *); +extern void cyasblkdev_queue_suspend(struct cyasblkdev_queue *); +extern void cyasblkdev_queue_resume(struct cyasblkdev_queue *); + +extern cy_as_device_handle cyasdevice_getdevhandle(void) ; +#define MOD_LOGS 1 +void verbose_rq_flags(int flags); + +#endif /* _INCLUDED_CYANBLKDEV_QUEUE_H_ */ + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/device/Kconfig b/drivers/staging/westbridge/astoria/device/Kconfig new file mode 100644 index 000000000000..cc99658cf3a4 --- /dev/null +++ b/drivers/staging/westbridge/astoria/device/Kconfig @@ -0,0 +1,9 @@ +# +# West Bridge block driver configuration +# + +config WESTBRIDGE_DEVICE_DRIVER + tristate "West Bridge Device Driver" + help + Include the West Bridge based device driver + diff --git a/drivers/staging/westbridge/astoria/device/Makefile b/drivers/staging/westbridge/astoria/device/Makefile new file mode 100644 index 000000000000..7af8b5b0a8f5 --- /dev/null +++ b/drivers/staging/westbridge/astoria/device/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the kernel westbridge device driver +# + +ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y) + EXTRA_CFLAGS += -DWESTBRIDGE_NDEBUG +endif + +obj-$(CONFIG_WESTBRIDGE_DEVICE_DRIVER) += cyasdev.o + + +ifeq ($(CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL),y) +#moved for staging compatbility +#cyasdev-y := ../../../arch/arm/mach-omap2/cyashalomap_kernel.o cyasdevice.o +cyasdev-y := ../arch/arm/mach-omap2/cyashalomap_kernel.o cyasdevice.o \ + ../api/src/cyasdma.o ../api/src/cyasintr.o ../api/src/cyaslep2pep.o \ + ../api/src/cyaslowlevel.o ../api/src/cyasmisc.o ../api/src/cyasmtp.o \ + ../api/src/cyasstorage.o ../api/src/cyasusb.o + +else +# should not get here, need to be built with some hal +cyasdev-y := cyasdevice.o +endif diff --git a/drivers/staging/westbridge/astoria/device/cyandevice_export.h b/drivers/staging/westbridge/astoria/device/cyandevice_export.h new file mode 100644 index 000000000000..fc9dee994f01 --- /dev/null +++ b/drivers/staging/westbridge/astoria/device/cyandevice_export.h @@ -0,0 +1,132 @@ +/* +## cyandevice_export.h - Linux Antioch device driver file +## +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * Export Misc APIs that can be used from the other driver modules. + * The APIs to create a device handle and download firmware are not exported + * because they are expected to be used only by this kernel module. + */ +EXPORT_SYMBOL(cy_as_misc_get_firmware_version) ; +EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register) ; +EXPORT_SYMBOL(cy_as_misc_reset) ; +EXPORT_SYMBOL(cy_as_misc_acquire_resource) ; +EXPORT_SYMBOL(cy_as_misc_release_resource) ; +EXPORT_SYMBOL(cy_as_misc_enter_standby) ; +EXPORT_SYMBOL(cy_as_misc_leave_standby) ; +EXPORT_SYMBOL(cy_as_misc_enter_suspend) ; +EXPORT_SYMBOL(cy_as_misc_leave_suspend) ; +EXPORT_SYMBOL(cy_as_misc_storage_changed) ; +EXPORT_SYMBOL(cy_as_misc_heart_beat_control) ; +EXPORT_SYMBOL(cy_as_misc_get_gpio_value) ; +EXPORT_SYMBOL(cy_as_misc_set_gpio_value) ; +EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq) ; +EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq) ; + +/* + * Export the USB APIs that can be used by the dependent kernel modules. + */ +EXPORT_SYMBOL(cy_as_usb_set_end_point_config) ; +EXPORT_SYMBOL(cy_as_usb_read_data_async) ; +EXPORT_SYMBOL(cy_as_usb_write_data_async) ; +EXPORT_SYMBOL(cy_as_usb_cancel_async) ; +EXPORT_SYMBOL(cy_as_usb_set_stall) ; +EXPORT_SYMBOL(cy_as_usb_clear_stall) ; +EXPORT_SYMBOL(cy_as_usb_connect) ; +EXPORT_SYMBOL(cy_as_usb_disconnect) ; +EXPORT_SYMBOL(cy_as_usb_start) ; +EXPORT_SYMBOL(cy_as_usb_stop) ; +EXPORT_SYMBOL(cy_as_usb_set_enum_config) ; +EXPORT_SYMBOL(cy_as_usb_get_enum_config) ; +EXPORT_SYMBOL(cy_as_usb_set_physical_configuration) ; +EXPORT_SYMBOL(cy_as_usb_register_callback) ; +EXPORT_SYMBOL(cy_as_usb_commit_config) ; +EXPORT_SYMBOL(cy_as_usb_set_descriptor) ; +EXPORT_SYMBOL(cy_as_usb_clear_descriptors) ; +EXPORT_SYMBOL(cy_as_usb_get_descriptor) ; +EXPORT_SYMBOL(cy_as_usb_get_end_point_config) ; +EXPORT_SYMBOL(cy_as_usb_read_data) ; +EXPORT_SYMBOL(cy_as_usb_write_data) ; +EXPORT_SYMBOL(cy_as_usb_get_stall) ; +EXPORT_SYMBOL(cy_as_usb_set_nak) ; +EXPORT_SYMBOL(cy_as_usb_clear_nak) ; +EXPORT_SYMBOL(cy_as_usb_get_nak) ; +EXPORT_SYMBOL(cy_as_usb_signal_remote_wakeup) ; +EXPORT_SYMBOL(cy_as_usb_set_m_s_report_threshold) ; +EXPORT_SYMBOL(cy_as_usb_select_m_s_partitions) ; + +/* + * Export all Storage APIs that can be used by dependent kernel modules. + */ +EXPORT_SYMBOL(cy_as_storage_start) ; +EXPORT_SYMBOL(cy_as_storage_stop) ; +EXPORT_SYMBOL(cy_as_storage_register_callback) ; +EXPORT_SYMBOL(cy_as_storage_query_bus) ; +EXPORT_SYMBOL(cy_as_storage_query_media) ; +EXPORT_SYMBOL(cy_as_storage_query_device) ; +EXPORT_SYMBOL(cy_as_storage_query_unit) ; +EXPORT_SYMBOL(cy_as_storage_device_control) ; +EXPORT_SYMBOL(cy_as_storage_claim) ; +EXPORT_SYMBOL(cy_as_storage_release) ; +EXPORT_SYMBOL(cy_as_storage_read) ; +EXPORT_SYMBOL(cy_as_storage_write) ; +EXPORT_SYMBOL(cy_as_storage_read_async) ; +EXPORT_SYMBOL(cy_as_storage_write_async) ; +EXPORT_SYMBOL(cy_as_storage_cancel_async) ; +EXPORT_SYMBOL(cy_as_storage_sd_register_read) ; +EXPORT_SYMBOL(cy_as_storage_create_p_partition) ; +EXPORT_SYMBOL(cy_as_storage_remove_p_partition) ; +EXPORT_SYMBOL(cy_as_storage_get_transfer_amount) ; +EXPORT_SYMBOL(cy_as_storage_erase) ; + +EXPORT_SYMBOL(cy_as_sdio_query_card); +EXPORT_SYMBOL(cy_as_sdio_init_function); +EXPORT_SYMBOL(cy_as_sdio_set_blocksize); +EXPORT_SYMBOL(cy_as_sdio_direct_read); +EXPORT_SYMBOL(cy_as_sdio_direct_write); +EXPORT_SYMBOL(cy_as_sdio_extended_read); +EXPORT_SYMBOL(cy_as_sdio_extended_write); + +EXPORT_SYMBOL(cy_as_hal_alloc) ; +EXPORT_SYMBOL(cy_as_hal_free) ; +EXPORT_SYMBOL(cy_as_hal_sleep) ; +EXPORT_SYMBOL(cy_as_hal_create_sleep_channel) ; +EXPORT_SYMBOL(cy_as_hal_destroy_sleep_channel) ; +EXPORT_SYMBOL(cy_as_hal_sleep_on) ; +EXPORT_SYMBOL(cy_as_hal_wake) ; +EXPORT_SYMBOL(cy_as_hal_mem_set); + +EXPORT_SYMBOL(cy_as_mtp_storage_only_start); +EXPORT_SYMBOL(cy_as_mtp_storage_only_stop); +EXPORT_SYMBOL(cy_as_mtp_start); +EXPORT_SYMBOL(cy_as_mtp_init_send_object); +EXPORT_SYMBOL(cy_as_mtp_init_get_object); +EXPORT_SYMBOL(cy_as_mtp_cancel_send_object); +EXPORT_SYMBOL(cy_as_mtp_cancel_get_object); + +#ifdef __CY_ASTORIA_SCM_KERNEL_HAL__ +/* Functions in the SCM kernel HAL implementation only. */ +EXPORT_SYMBOL(cy_as_hal_enable_scatter_list) ; +EXPORT_SYMBOL(cy_as_hal_disable_scatter_list) ; +#endif + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/device/cyasdevice.c b/drivers/staging/westbridge/astoria/device/cyasdevice.c new file mode 100644 index 000000000000..cd0f7cbc9b18 --- /dev/null +++ b/drivers/staging/westbridge/astoria/device/cyasdevice.c @@ -0,0 +1,394 @@ +/* +## cyandevice.c - Linux Antioch device driver file +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* moved for staging location + * update/patch submission +#include +#include +#include +*/ + +#include "../include/linux/westbridge/cyastoria.h" +#include "../include/linux/westbridge/cyashal.h" +#include "../include/linux/westbridge/cyasregs.h" + +/* API exports include file */ +#include "cyandevice_export.h" + +typedef struct cyasdevice { + /* Handle to the Antioch device */ + cy_as_device_handle dev_handle; + /* Handle to the HAL */ + cy_as_hal_device_tag hal_tag; +} cyasdevice ; + +/* global ptr to astoria device */ +static cyasdevice *cy_as_device_controller ; +int cy_as_device_init_done; +const char *dev_handle_name = "cy_astoria_dev_handle" ; + +#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL +extern void cy_as_hal_config_c_s_mux(void); +#endif + +static void cyasdevice_deinit(cyasdevice *cy_as_dev) +{ + cy_as_hal_print_message("<1>_cy_as_device deinitialize called\n") ; + if (!cy_as_dev) { + cy_as_hal_print_message("<1>_cy_as_device_deinit: " + "device handle %x is invalid\n", (uint32_t)cy_as_dev) ; + return ; + } + + /* stop west_brige */ + if (cy_as_dev->dev_handle) { + cy_as_hal_print_message("<1>_cy_as_device: " + "cy_as_misc_destroy_device called\n") ; + if (cy_as_misc_destroy_device(cy_as_dev->dev_handle) != + CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message( + "<1>_cy_as_device: destroying failed\n"); + } + } + + if (cy_as_dev->hal_tag) { + + #ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + if (stop_o_m_a_p_kernel(dev_handle_name, + cy_as_dev->hal_tag) != 0) + cy_as_hal_print_message("<1>_cy_as_device: stopping " + "OMAP kernel HAL failed\n"); + + #endif + } + cy_as_hal_print_message("<1>_cy_as_device:HAL layer stopped\n") ; + + kfree(cy_as_dev) ; + cy_as_device_controller = NULL ; + cy_as_hal_print_message("<1>_cy_as_device: deinitialized\n") ; +} + +/*called from src/cyasmisc.c:MyMiscCallback() as a func + * pointer [dev_p->misc_event_cb] which was previously + * registered by CyAsLLRegisterRequestCallback(..., + * MyMiscCallback) ; called from CyAsMiscConfigureDevice() + * which is in turn called from cyasdevice_initialize() in + * this src + */ +static void cy_misc_callback(cy_as_device_handle h, + cy_as_misc_event_type evtype, void *evdata) +{ + (void)h ; + (void)evdata ; + + switch (evtype) { + case cy_as_event_misc_initialized: + cy_as_hal_print_message("<1>_cy_as_device: " + "initialization done callback triggered\n") ; + cy_as_device_init_done = 1 ; + break ; + + case cy_as_event_misc_awake: + cy_as_hal_print_message("<1>_cy_as_device: " + "cy_as_event_misc_awake event callback triggered\n") ; + cy_as_device_init_done = 1 ; + break ; + default: + break ; + } +} + +/* reset astoria and reinit all regs */ + #define PNAND_REG_CFG_INIT_VAL 0x0000 +void hal_reset(cy_as_hal_device_tag tag) +{ + cy_as_hal_print_message("<1> send soft hard rst: " + "MEM_RST_CTRL_REG_HARD...\n"); + cy_as_hal_write_register(tag, CY_AS_MEM_RST_CTRL_REG, + CY_AS_MEM_RST_CTRL_REG_HARD) ; + mdelay(60); + + cy_as_hal_print_message("<1> after RST: si_rev_REG:%x, " + "PNANDCFG_reg:%x\n", + cy_as_hal_read_register(tag, CY_AS_MEM_CM_WB_CFG_ID), + cy_as_hal_read_register(tag, CY_AS_MEM_PNAND_CFG) + ); + + /* set it to LBD */ + cy_as_hal_write_register(tag, CY_AS_MEM_PNAND_CFG, + PNAND_REG_CFG_INIT_VAL) ; +} +EXPORT_SYMBOL(hal_reset); + + +/* below structures and functions primarily + * implemented for firmware loading */ +static struct platform_device *westbridge_pd; + +static int __devinit wb_probe(struct platform_device *devptr) +{ + cy_as_hal_print_message("%s called\n", __func__); + return 0; +} + +static int __devexit wb_remove(struct platform_device *devptr) +{ + cy_as_hal_print_message("%s called\n", __func__); + return 0; +} + +static struct platform_driver west_bridge_driver = { + .probe = wb_probe, + .remove = __devexit_p(wb_remove), + .driver = { + .name = "west_bridge_dev"}, +}; + +/* west bridge device driver main init */ +static int cyasdevice_initialize(void) +{ + cyasdevice *cy_as_dev = 0 ; + int ret = 0 ; + int retval = 0 ; + cy_as_device_config config ; + cy_as_hal_sleep_channel channel ; + cy_as_get_firmware_version_data ver_data = {0}; + const char *str = "" ; + int spin_lim; + const struct firmware *fw_entry; + + cy_as_device_init_done = 0; + + cy_as_misc_set_log_level(8); + + cy_as_hal_print_message("<1>_cy_as_device initialize called\n") ; + + if (cy_as_device_controller != 0) { + cy_as_hal_print_message("<1>_cy_as_device: the device " + "has already been initilaized. ignoring\n") ; + return -EBUSY ; + } + + /* cy_as_dev = CyAsHalAlloc (sizeof(cyasdevice), SLAB_KERNEL); */ + cy_as_dev = cy_as_hal_alloc(sizeof(cyasdevice)); + if (cy_as_dev == NULL) { + cy_as_hal_print_message("<1>_cy_as_device: " + "memmory allocation failed\n") ; + return -ENOMEM; + } + memset(cy_as_dev, 0, sizeof(cyasdevice)); + + + /* Init the HAL & CyAsDeviceHandle */ + + #ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + /* start OMAP HAL init instsnce */ + + if (!start_o_m_a_p_kernel(dev_handle_name, + &(cy_as_dev->hal_tag), cy_false)) { + + cy_as_hal_print_message( + "<1>_cy_as_device: start OMAP34xx HAL failed\n") ; + goto done; + } + #endif + + /* Now create the device */ + if (cy_as_misc_create_device(&(cy_as_dev->dev_handle), + cy_as_dev->hal_tag) != CY_AS_ERROR_SUCCESS) { + + cy_as_hal_print_message( + "<1>_cy_as_device: create device failed\n") ; + goto done ; + } + + memset(&config, 0, sizeof(config)); + config.dmaintr = cy_true; + + ret = cy_as_misc_configure_device(cy_as_dev->dev_handle, &config) ; + if (ret != CY_AS_ERROR_SUCCESS) { + + cy_as_hal_print_message( + "<1>_cy_as_device: configure device " + "failed. reason code: %d\n", ret) ; + goto done; + } + + ret = cy_as_misc_register_callback(cy_as_dev->dev_handle, + cy_misc_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("<1>_cy_as_device: " + "cy_as_misc_register_callback failed. " + "reason code: %d\n", ret) ; + goto done; + } + + ret = platform_driver_register(&west_bridge_driver); + if (unlikely(ret < 0)) + return ret; + westbridge_pd = platform_device_register_simple( + "west_bridge_dev", -1, NULL, 0); + + if (IS_ERR(westbridge_pd)) { + platform_driver_unregister(&west_bridge_driver); + return PTR_ERR(westbridge_pd); + } + /* Load the firmware */ + ret = request_firmware(&fw_entry, + "west bridge fw", &westbridge_pd->dev); + if (ret) { + cy_as_hal_print_message("cy_as_device: " + "request_firmware failed return val = %d\n", ret); + } else { + cy_as_hal_print_message("cy_as_device: " + "got the firmware %d size=0x%x\n", ret, fw_entry->size); + + ret = cy_as_misc_download_firmware( + cy_as_dev->dev_handle, + fw_entry->data, + fw_entry->size , + 0, 0) ; + } + + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("<1>_cy_as_device: cannot download " + "firmware. reason code: %d\n", ret) ; + goto done; + } + + /* spin until the device init is completed */ + /* 50 -MAX wait time for the FW load & init + * to complete is 5sec*/ + spin_lim = 50; + + cy_as_hal_create_sleep_channel(&channel) ; + while (!cy_as_device_init_done) { + + cy_as_hal_sleep_on(&channel, 100) ; + + if (spin_lim-- <= 0) { + cy_as_hal_print_message( + "<1>\n_e_r_r_o_r!: " + "wait for FW init has timed out !!!"); + break; + } + } + cy_as_hal_destroy_sleep_channel(&channel) ; + + if (spin_lim > 0) + cy_as_hal_print_message( + "cy_as_device: astoria firmware is loaded\n") ; + + ret = cy_as_misc_get_firmware_version(cy_as_dev->dev_handle, + &ver_data, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("<1>_cy_as_device: cannot get firmware " + "version. reason code: %d\n", ret) ; + goto done; + } + + if ((ver_data.media_type & 0x01) && (ver_data.media_type & 0x06)) + str = "nand and SD/MMC." ; + else if ((ver_data.media_type & 0x01) && (ver_data.media_type & 0x08)) + str = "nand and CEATA." ; + else if (ver_data.media_type & 0x01) + str = "nand." ; + else if (ver_data.media_type & 0x08) + str = "CEATA." ; + else + str = "SD/MMC." ; + + cy_as_hal_print_message("<1> cy_as_device:_firmware version: %s " + "major=%d minor=%d build=%d,\n_media types supported:%s\n", + ((ver_data.is_debug_mode) ? "debug" : "release"), + ver_data.major, ver_data.minor, ver_data.build, str) ; + + /* done now */ + cy_as_device_controller = cy_as_dev ; + + return 0 ; + +done: + if (cy_as_dev) + cyasdevice_deinit(cy_as_dev) ; + + return -EINVAL ; +} + +cy_as_device_handle cyasdevice_getdevhandle(void) +{ + if (cy_as_device_controller) { + #ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + cy_as_hal_config_c_s_mux(); + #endif + + return cy_as_device_controller->dev_handle ; + } + return NULL; +} +EXPORT_SYMBOL(cyasdevice_getdevhandle) ; + +cy_as_hal_device_tag cyasdevice_gethaltag(void) +{ + if (cy_as_device_controller) + return (cy_as_hal_device_tag) + cy_as_device_controller->hal_tag ; + + return NULL; +} +EXPORT_SYMBOL(cyasdevice_gethaltag) ; + + +/*init Westbridge device driver **/ +static int __init cyasdevice_init(void) +{ + if (cyasdevice_initialize() != 0) + return ENODEV; + + return 0 ; +} + + +static void __exit cyasdevice_cleanup(void) +{ + + cyasdevice_deinit(cy_as_device_controller) ; +} + + +MODULE_DESCRIPTION("west bridge device driver"); +MODULE_AUTHOR("cypress semiconductor"); +MODULE_LICENSE("GPL"); + +module_init(cyasdevice_init); +module_exit(cyasdevice_cleanup); + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/gadget/Kconfig b/drivers/staging/westbridge/astoria/gadget/Kconfig new file mode 100644 index 000000000000..6fbdf2277b03 --- /dev/null +++ b/drivers/staging/westbridge/astoria/gadget/Kconfig @@ -0,0 +1,9 @@ +# +# West Bridge gadget driver configuration +# + +config WESTBRIDGE_GADGET_DRIVER + tristate "West Bridge Gadget Driver" + help + Include the West Bridge based gadget peripheral controller driver + diff --git a/drivers/staging/westbridge/astoria/gadget/Makefile b/drivers/staging/westbridge/astoria/gadget/Makefile new file mode 100644 index 000000000000..a5eef7ee60a4 --- /dev/null +++ b/drivers/staging/westbridge/astoria/gadget/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the kernel westbridge hal +# + +ifneq ($(CONFIG_WESTBRIDGE_DEBUG),y) + EXTRA_CFLAGS += -DWESTBRIDGE_NDEBUG +endif + +obj-$(CONFIG_WESTBRIDGE_GADGET_DRIVER) += cyasgadgetctrl.o +cyasgadgetctrl-y := cyasgadget.o + diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget.c b/drivers/staging/westbridge/astoria/gadget/cyasgadget.c new file mode 100644 index 000000000000..ced239dc3678 --- /dev/null +++ b/drivers/staging/westbridge/astoria/gadget/cyasgadget.c @@ -0,0 +1,2211 @@ +/* cyangadget.c - Linux USB Gadget driver file for the Cypress West Bridge +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * Cypress West Bridge high/full speed usb device controller code + * Based on the Netchip 2280 device controller by David Brownell + * in the linux 2.6.10 kernel + * + * linux/drivers/usb/gadget/net2280.c + */ + +/* + * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330 + * Boston, MA 02111-1307 USA + */ + +#include "cyasgadget.h" + +#define CY_AS_DRIVER_DESC "cypress west bridge usb gadget" +#define CY_AS_DRIVER_VERSION "REV B" +#define DMA_ADDR_INVALID (~(dma_addr_t)0) + +static const char cy_as_driver_name[] = "cy_astoria_gadget"; +static const char cy_as_driver_desc[] = CY_AS_DRIVER_DESC; + +static const char cy_as_ep0name[] = "EP0"; +static const char *cy_as_ep_names[] = { + cy_as_ep0name, "EP1", + "EP2", "EP3", "EP4", "EP5", "EP6", "EP7", "EP8", + "EP9", "EP10", "EP11", "EP12", "EP13", "EP14", "EP15" +}; + +/* forward declarations */ +static void +cyas_ep_reset( + struct cyasgadget_ep *an_ep) ; + +static int +cyasgadget_fifo_status( + struct usb_ep *_ep) ; + +static void +cyasgadget_stallcallback( + cy_as_device_handle h, + cy_as_return_status_t status, + uint32_t tag, + cy_as_funct_c_b_type cbtype, + void *cbdata); + +/* variables */ +static cyasgadget *cy_as_gadget_controller; + +static int append_mtp; +module_param(append_mtp, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(append_mtp, + "west bridge to append descriptors for mtp 0=no 1=yes"); + +static int msc_enum_bus_0; +module_param(msc_enum_bus_0, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(msc_enum_bus_0, + "west bridge to enumerate bus 0 as msc 0=no 1=yes"); + +static int msc_enum_bus_1; +module_param(msc_enum_bus_1, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(msc_enum_bus_1, + "west bridge to enumerate bus 1 as msc 0=no 1=yes"); + +/* all Callbacks are placed in this subsection*/ +static void cy_as_gadget_usb_event_callback( + cy_as_device_handle h, + cy_as_usb_event ev, + void *evdata + ) +{ + cyasgadget *cy_as_dev ; + #ifndef WESTBRIDGE_NDEBUG + struct usb_ctrlrequest *ctrlreq; + #endif + + /* cy_as_dev = container_of(h, cyasgadget, dev_handle); */ + cy_as_dev = cy_as_gadget_controller ; + switch (ev) { + case cy_as_event_usb_suspend: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_suspend received\n") ; + #endif + cy_as_dev->driver->suspend(&cy_as_dev->gadget) ; + break; + + case cy_as_event_usb_resume: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_resume received\n") ; + #endif + cy_as_dev->driver->resume(&cy_as_dev->gadget) ; + break; + + case cy_as_event_usb_reset: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_reset received\n") ; + #endif + break; + + case cy_as_event_usb_speed_change: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_speed_change received\n") ; + #endif + break; + + case cy_as_event_usb_set_config: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_set_config received\n") ; + #endif + break; + + case cy_as_event_usb_setup_packet: + #ifndef WESTBRIDGE_NDEBUG + ctrlreq = (struct usb_ctrlrequest *)evdata; + + cy_as_hal_print_message("<1>_cy_as_event_usb_setup_packet " + "received" + "bRequestType=0x%x," + "bRequest=0x%x," + "wValue=x%x," + "wIndex=0x%x," + "wLength=0x%x,", + ctrlreq->bRequestType, + ctrlreq->bRequest, + ctrlreq->wValue, + ctrlreq->wIndex, + ctrlreq->wLength + ) ; + #endif + cy_as_dev->outsetupreq = 0; + if ((((uint8_t *)evdata)[0] & USB_DIR_IN) == USB_DIR_OUT) + cy_as_dev->outsetupreq = 1; + cy_as_dev->driver->setup(&cy_as_dev->gadget, + (struct usb_ctrlrequest *)evdata) ; + break; + + case cy_as_event_usb_status_packet: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_status_packet received\n") ; + #endif + break; + + case cy_as_event_usb_inquiry_before: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_inquiry_before received\n") ; + #endif + break; + + case cy_as_event_usb_inquiry_after: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_inquiry_after received\n") ; + #endif + break; + + case cy_as_event_usb_start_stop: + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<1>_cy_as_event_usb_start_stop received\n") ; + #endif + break; + + default: + break; + } +} + +static void cy_as_gadget_mtp_event_callback( + cy_as_device_handle handle, + cy_as_mtp_event evtype, + void *evdata + ) +{ + + cyasgadget *dev = cy_as_gadget_controller ; + (void) handle; + + switch (evtype) { + case cy_as_mtp_send_object_complete: + { + cy_as_mtp_send_object_complete_data *send_obj_data = + (cy_as_mtp_send_object_complete_data *) evdata ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<6>MTP EVENT: send_object_complete\n"); + cy_as_hal_print_message( + "<6>_bytes sent = %d\n_send status = %d", + send_obj_data->byte_count, + send_obj_data->status); + #endif + + dev->tmtp_send_complete_data.byte_count = + send_obj_data->byte_count; + dev->tmtp_send_complete_data.status = + send_obj_data->status; + dev->tmtp_send_complete_data.transaction_id = + send_obj_data->transaction_id ; + dev->tmtp_send_complete = cy_true ; + break; + } + case cy_as_mtp_get_object_complete: + { + cy_as_mtp_get_object_complete_data *get_obj_data = + (cy_as_mtp_get_object_complete_data *) evdata ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<6>MTP EVENT: get_object_complete\n"); + cy_as_hal_print_message( + "<6>_bytes got = %d\n_get status = %d", + get_obj_data->byte_count, get_obj_data->status); + #endif + + dev->tmtp_get_complete_data.byte_count = + get_obj_data->byte_count; + dev->tmtp_get_complete_data.status = + get_obj_data->status ; + dev->tmtp_get_complete = cy_true ; + break; + } + case cy_as_mtp_block_table_needed: + { + dev->tmtp_need_new_blk_tbl = cy_true ; + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<6>MTP EVENT: cy_as_mtp_block_table_needed\n"); + #endif + break; + } + default: + break; + } +} + +static void +cyasgadget_setupreadcallback( + cy_as_device_handle h, + cy_as_end_point_number_t ep, + uint32_t count, + void *buf, + cy_as_return_status_t status) +{ + cyasgadget_ep *an_ep; + cyasgadget_req *an_req; + cyasgadget *cy_as_dev ; + unsigned stopped ; + unsigned long flags; + (void)buf ; + + cy_as_dev = cy_as_gadget_controller ; + if (cy_as_dev->driver == NULL) + return; + + an_ep = &cy_as_dev->an_gadget_ep[ep] ; + spin_lock_irqsave(&cy_as_dev->lock, flags); + stopped = an_ep->stopped ; + +#ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: ep=%d, count=%d, " + "status=%d\n", __func__, ep, count, status) ; +#endif + + an_req = list_entry(an_ep->queue.next, + cyasgadget_req, queue) ; + list_del_init(&an_req->queue) ; + + if (status == CY_AS_ERROR_SUCCESS) + an_req->req.status = 0; + else + an_req->req.status = -status; + an_req->req.actual = count ; + an_ep->stopped = 1; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req); + + an_ep->stopped = stopped; + +} +/*called when the write of a setup packet has been completed*/ +static void cyasgadget_setupwritecallback( + cy_as_device_handle h, + cy_as_end_point_number_t ep, + uint32_t count, + void *buf, + cy_as_return_status_t status + ) +{ + cyasgadget_ep *an_ep; + cyasgadget_req *an_req; + cyasgadget *cy_as_dev ; + unsigned stopped ; + unsigned long flags; + + (void)buf ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called status=0x%x\n", + __func__, status); + #endif + + cy_as_dev = cy_as_gadget_controller ; + + if (cy_as_dev->driver == NULL) + return; + + an_ep = &cy_as_dev->an_gadget_ep[ep] ; + + spin_lock_irqsave(&cy_as_dev->lock, flags); + + stopped = an_ep->stopped ; + +#ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("setup_write_callback: ep=%d, " + "count=%d, status=%d\n", ep, count, status) ; +#endif + + an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ; + list_del_init(&an_req->queue) ; + + an_req->req.actual = count ; + an_req->req.status = 0 ; + an_ep->stopped = 1; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req); + + an_ep->stopped = stopped; + +} + +/* called when a read operation has completed.*/ +static void cyasgadget_readcallback( + cy_as_device_handle h, + cy_as_end_point_number_t ep, + uint32_t count, + void *buf, + cy_as_return_status_t status + ) +{ + cyasgadget_ep *an_ep; + cyasgadget_req *an_req; + cyasgadget *cy_as_dev ; + unsigned stopped ; + cy_as_return_status_t ret ; + unsigned long flags; + + (void)h ; + (void)buf ; + + cy_as_dev = cy_as_gadget_controller ; + + if (cy_as_dev->driver == NULL) + return; + + an_ep = &cy_as_dev->an_gadget_ep[ep] ; + stopped = an_ep->stopped ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n", + __func__, ep, count, status) ; + #endif + + if (status == CY_AS_ERROR_CANCELED) + return ; + + spin_lock_irqsave(&cy_as_dev->lock, flags); + + an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ; + list_del_init(&an_req->queue) ; + + if (status == CY_AS_ERROR_SUCCESS) + an_req->req.status = 0 ; + else + an_req->req.status = -status ; + + an_req->complete = 1; + an_req->req.actual = count ; + an_ep->stopped = 1; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req); + + an_ep->stopped = stopped; + + /* We need to call ReadAsync on this end-point + * again, so as to not miss any data packets. */ + if (!an_ep->stopped) { + spin_lock_irqsave(&cy_as_dev->lock, flags); + an_req = 0 ; + if (!list_empty(&an_ep->queue)) + an_req = list_entry(an_ep->queue.next, + cyasgadget_req, queue) ; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + if ((an_req) && (an_req->req.status == -EINPROGRESS)) { + ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle, + an_ep->num, cy_false, an_req->req.length, + an_req->req.buf, cyasgadget_readcallback); + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_read_data_async failed " + "with error code %d\n", ret) ; + else + an_req->req.status = -EALREADY ; + } + } +} + +/* function is called when a usb write operation has completed*/ +static void cyasgadget_writecallback( + cy_as_device_handle h, + cy_as_end_point_number_t ep, + uint32_t count, + void *buf, + cy_as_return_status_t status + ) +{ + cyasgadget_ep *an_ep; + cyasgadget_req *an_req; + cyasgadget *cy_as_dev ; + unsigned stopped = 0; + cy_as_return_status_t ret ; + unsigned long flags; + + (void)h ; + (void)buf ; + + cy_as_dev = cy_as_gadget_controller ; + if (cy_as_dev->driver == NULL) + return; + + an_ep = &cy_as_dev->an_gadget_ep[ep] ; + + if (status == CY_AS_ERROR_CANCELED) + return ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: ep=%d, count=%d, status=%d\n", + __func__, ep, count, status) ; + #endif + + spin_lock_irqsave(&cy_as_dev->lock, flags); + + an_req = list_entry(an_ep->queue.next, cyasgadget_req, queue) ; + list_del_init(&an_req->queue) ; + an_req->req.actual = count ; + + /* Verify the status value before setting req.status to zero */ + if (status == CY_AS_ERROR_SUCCESS) + an_req->req.status = 0 ; + else + an_req->req.status = -status ; + + an_ep->stopped = 1; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req); + an_ep->stopped = stopped; + + /* We need to call WriteAsync on this end-point again, so as to not + miss any data packets. */ + if (!an_ep->stopped) { + spin_lock_irqsave(&cy_as_dev->lock, flags); + an_req = 0 ; + if (!list_empty(&an_ep->queue)) + an_req = list_entry(an_ep->queue.next, + cyasgadget_req, queue) ; + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + if ((an_req) && (an_req->req.status == -EINPROGRESS)) { + ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle, + an_ep->num, an_req->req.length, an_req->req.buf, + cy_false, cyasgadget_writecallback); + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async " + "failed with error code %d\n", ret) ; + else + an_req->req.status = -EALREADY ; + } + } +} + +static void cyasgadget_stallcallback( + cy_as_device_handle h, + cy_as_return_status_t status, + uint32_t tag, + cy_as_funct_c_b_type cbtype, + void *cbdata + ) +{ + #ifndef WESTBRIDGE_NDEBUG + if (status != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_set/_clear stall " + "failed with status %d\n", status) ; + #endif +} + + +/*******************************************************************/ +/* All usb_ep_ops (cyasgadget_ep_ops) are placed in this subsection*/ +/*******************************************************************/ +static int cyasgadget_enable( + struct usb_ep *_ep, + const struct usb_endpoint_descriptor *desc + ) +{ + cyasgadget *an_dev; + cyasgadget_ep *an_ep; + u32 max, tmp; + unsigned long flags; + + an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + if (!_ep || !desc || an_ep->desc || _ep->name == cy_as_ep0name + || desc->bDescriptorType != USB_DT_ENDPOINT) + return -EINVAL; + + an_dev = an_ep->dev; + if (!an_dev->driver || an_dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; + + spin_lock_irqsave(&an_dev->lock, flags); + _ep->maxpacket = max & 0x7ff; + an_ep->desc = desc; + + /* ep_reset() has already been called */ + an_ep->stopped = 0; + an_ep->out_overflow = 0; + + if (an_ep->cyepconfig.enabled != cy_true) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on enabled\n", an_ep->usb_ep_inst.name) ; + #endif + return -EINVAL; + } + + tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + an_ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0; + + spin_unlock_irqrestore(&an_dev->lock, flags); + + switch (tmp) { + case USB_ENDPOINT_XFER_ISOC: + if (an_ep->cyepconfig.type != cy_as_usb_iso) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on type %d %d\n", an_ep->usb_ep_inst.name, + an_ep->cyepconfig.type, cy_as_usb_iso) ; + #endif + return -EINVAL; + } + break; + case USB_ENDPOINT_XFER_INT: + if (an_ep->cyepconfig.type != cy_as_usb_int) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on type %d %d\n", an_ep->usb_ep_inst.name, + an_ep->cyepconfig.type, cy_as_usb_int) ; + #endif + return -EINVAL; + } + break; + default: + if (an_ep->cyepconfig.type != cy_as_usb_bulk) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on type %d %d\n", an_ep->usb_ep_inst.name, + an_ep->cyepconfig.type, cy_as_usb_bulk) ; + #endif + return -EINVAL; + } + break; + } + + tmp = desc->bEndpointAddress; + an_ep->is_in = (tmp & USB_DIR_IN) != 0; + + if ((an_ep->cyepconfig.dir == cy_as_usb_in) && + (!an_ep->is_in)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on dir %d %d\n", an_ep->usb_ep_inst.name, + an_ep->cyepconfig.dir, cy_as_usb_in) ; + #endif + return -EINVAL; + } else if ((an_ep->cyepconfig.dir == cy_as_usb_out) && + (an_ep->is_in)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_end_point_config EP %s mismatch " + "on dir %d %d\n", an_ep->usb_ep_inst.name, + an_ep->cyepconfig.dir, cy_as_usb_out) ; + #endif + return -EINVAL; + } + + cy_as_usb_clear_stall(an_dev->dev_handle, an_ep->num, + cyasgadget_stallcallback, 0); + + cy_as_hal_print_message("%s enabled %s (ep%d-%d) max %04x\n", + __func__, _ep->name, an_ep->num, tmp, max); + + return 0; +} + +static int cyasgadget_disable( + struct usb_ep *_ep + ) +{ + cyasgadget_ep *an_ep; + unsigned long flags; + + an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + if (!_ep || !an_ep->desc || _ep->name == cy_as_ep0name) + return -EINVAL; + + spin_lock_irqsave(&an_ep->dev->lock, flags); + cyas_ep_reset(an_ep); + + spin_unlock_irqrestore(&an_ep->dev->lock, flags); + return 0; +} + +static struct usb_request *cyasgadget_alloc_request( + struct usb_ep *_ep, gfp_t gfp_flags + ) +{ + cyasgadget_ep *an_ep; + cyasgadget_req *an_req; + + if (!_ep) + return NULL; + + an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + + an_req = kzalloc(sizeof(cyasgadget_req), gfp_flags); + if (!an_req) + return NULL; + + an_req->req.dma = DMA_ADDR_INVALID; + INIT_LIST_HEAD(&an_req->queue); + + return &an_req->req; +} + +static void cyasgadget_free_request( + struct usb_ep *_ep, + struct usb_request *_req + ) +{ + cyasgadget_req *an_req ; + + if (!_ep || !_req) + return ; + + an_req = container_of(_req, cyasgadget_req, req) ; + + kfree(an_req); +} + +/* Load a packet into the fifo we use for usb IN transfers. + * works for all endpoints. */ +static int cyasgadget_queue( + struct usb_ep *_ep, + struct usb_request *_req, + gfp_t gfp_flags + ) +{ + cyasgadget_req *as_req; + cyasgadget_ep *as_ep; + cyasgadget *cy_as_dev; + unsigned long flags; + cy_as_return_status_t ret = 0; + + as_req = container_of(_req, cyasgadget_req, req); + if (!_req || !_req->complete || !_req->buf + || !list_empty(&as_req->queue)) + return -EINVAL; + + as_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + + if (!_ep || (!as_ep->desc && (as_ep->num != 0))) + return -EINVAL; + + cy_as_dev = as_ep->dev; + if (!cy_as_dev->driver || + cy_as_dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + spin_lock_irqsave(&cy_as_dev->lock, flags); + + _req->status = -EINPROGRESS; + _req->actual = 0; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + /* Call Async functions */ + if (as_ep->is_in) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async being called " + "on ep %d\n", as_ep->num) ; + #endif + + ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle, + as_ep->num, _req->length, _req->buf, + cy_false, cyasgadget_writecallback) ; + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async failed with " + "error code %d\n", ret) ; + else + _req->status = -EALREADY ; + } else if (as_ep->num == 0) { + /* + ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle, + as_ep->num, _req->length, _req->buf, cy_false, + cyasgadget_setupwritecallback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async failed with error " + "code %d\n", ret) ; + */ + if ((cy_as_dev->outsetupreq) && (_req->length)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_read_data_async " + "being called on ep %d\n", + as_ep->num) ; + #endif + + ret = cy_as_usb_read_data_async ( + cy_as_dev->dev_handle, as_ep->num, + cy_true, _req->length, _req->buf, + cyasgadget_setupreadcallback); + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_read_data_async failed with " + "error code %d\n", ret) ; + + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async " + "being called on ep %d\n", + as_ep->num) ; + #endif + + ret = cy_as_usb_write_data_async(cy_as_dev->dev_handle, + as_ep->num, _req->length, _req->buf, cy_false, + cyasgadget_setupwritecallback) ; + + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_write_data_async failed with " + "error code %d\n", ret) ; + } + + } else if (list_empty(&as_ep->queue)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_read_data_async being called since " + "ep queue empty%d\n", ret) ; + #endif + + ret = cy_as_usb_read_data_async(cy_as_dev->dev_handle, + as_ep->num, cy_false, _req->length, _req->buf, + cyasgadget_readcallback) ; + if (ret != CY_AS_ERROR_SUCCESS) + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_read_data_async failed with error " + "code %d\n", ret) ; + else + _req->status = -EALREADY ; + } + + spin_lock_irqsave(&cy_as_dev->lock, flags); + + if (as_req) + list_add_tail(&as_req->queue, &as_ep->queue); + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + return 0; +} + +/* dequeue request */ +static int cyasgadget_dequeue( + struct usb_ep *_ep, + struct usb_request *_req + ) +{ + cyasgadget_ep *an_ep; + cyasgadget *dev; + an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + dev = an_ep->dev ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + cy_as_usb_cancel_async(dev->dev_handle, an_ep->num); + + return 0; +} + +static int cyasgadget_set_halt( + struct usb_ep *_ep, + int value + ) +{ + cyasgadget_ep *an_ep; + int retval = 0; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + an_ep = container_of(_ep, cyasgadget_ep, usb_ep_inst); + if (!_ep || (!an_ep->desc && an_ep->num != 0)) + return -EINVAL; + + if (!an_ep->dev->driver || an_ep->dev->gadget.speed == + USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + if (an_ep->desc /* not ep0 */ && + (an_ep->desc->bmAttributes & 0x03) == USB_ENDPOINT_XFER_ISOC) + return -EINVAL; + + if (!list_empty(&an_ep->queue)) + retval = -EAGAIN; + else if (an_ep->is_in && value && + cyasgadget_fifo_status(_ep) != 0) + retval = -EAGAIN; + else { + if (value) { + cy_as_usb_set_stall(an_ep->dev->dev_handle, + an_ep->num, cyasgadget_stallcallback, 0) ; + } else { + cy_as_usb_clear_stall(an_ep->dev->dev_handle, + an_ep->num, cyasgadget_stallcallback, 0) ; + } + } + + return retval; +} + +static int cyasgadget_fifo_status( + struct usb_ep *_ep + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + return 0 ; +} + +static void cyasgadget_fifo_flush( + struct usb_ep *_ep + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif +} + +static struct usb_ep_ops cyasgadget_ep_ops = { + .enable = cyasgadget_enable, + .disable = cyasgadget_disable, + .alloc_request = cyasgadget_alloc_request, + .free_request = cyasgadget_free_request, + .queue = cyasgadget_queue, + .dequeue = cyasgadget_dequeue, + .set_halt = cyasgadget_set_halt, + .fifo_status = cyasgadget_fifo_status, + .fifo_flush = cyasgadget_fifo_flush, +}; + +/*************************************************************/ +/*This subsection contains all usb_gadget_ops cyasgadget_ops */ +/*************************************************************/ +static int cyasgadget_get_frame( + struct usb_gadget *_gadget + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + return 0 ; +} + +static int cyasgadget_wakeup( + struct usb_gadget *_gadget + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + return 0; +} + +static int cyasgadget_set_selfpowered( + struct usb_gadget *_gadget, + int value + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + return 0; +} + +static int cyasgadget_pullup( + struct usb_gadget *_gadget, + int is_on + ) +{ + struct cyasgadget *cy_as_dev ; + unsigned long flags; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + if (!_gadget) + return -ENODEV; + + cy_as_dev = container_of(_gadget, cyasgadget, gadget); + + spin_lock_irqsave(&cy_as_dev->lock, flags); + cy_as_dev->softconnect = (is_on != 0); + if (is_on) + cy_as_usb_connect(cy_as_dev->dev_handle, 0, 0) ; + else + cy_as_usb_disconnect(cy_as_dev->dev_handle, 0, 0) ; + + spin_unlock_irqrestore(&cy_as_dev->lock, flags); + + return 0; +} + +static int cyasgadget_ioctl( + struct usb_gadget *_gadget, + unsigned code, + unsigned long param + ) +{ + int err = 0; + int retval = 0; + int ret_stat = 0; + cyasgadget *dev = cy_as_gadget_controller ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called, code=%d, param=%ld\n", + __func__, code, param); + #endif + /* + * extract the type and number bitfields, and don't decode + * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() + */ + if (_IOC_TYPE(code) != CYASGADGET_IOC_MAGIC) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s, bad magic number = 0x%x\n", + __func__, _IOC_TYPE(code)); + #endif + return -ENOTTY; + } + + if (_IOC_NR(code) > CYASGADGET_IOC_MAXNR) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s, bad ioctl code = 0x%x\n", + __func__, _IOC_NR(code)); + #endif + return -ENOTTY; + } + + /* + * the direction is a bitmask, and VERIFY_WRITE catches R/W + * transfers. `Type' is user-oriented, while + * access_ok is kernel-oriented, so the concept of "read" and + * "write" is reversed + */ + if (_IOC_DIR(code) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, + (void __user *)param, _IOC_SIZE(code)); + else if (_IOC_DIR(code) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, + (void __user *)param, _IOC_SIZE(code)); + + if (err) { + cy_as_hal_print_message("%s, bad ioctl dir = 0x%x\n", + __func__, _IOC_DIR(code)); + return -EFAULT; + } + + switch (code) { + case CYASGADGET_GETMTPSTATUS: + { + cy_as_gadget_ioctl_tmtp_status *usr_d = + (cy_as_gadget_ioctl_tmtp_status *)param ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: got CYASGADGET_GETMTPSTATUS\n", + __func__); + #endif + + retval = __put_user(dev->tmtp_send_complete, + (uint32_t __user *)(&(usr_d->tmtp_send_complete))); + retval = __put_user(dev->tmtp_get_complete, + (uint32_t __user *)(&(usr_d->tmtp_get_complete))); + retval = __put_user(dev->tmtp_need_new_blk_tbl, + (uint32_t __user *)(&(usr_d->tmtp_need_new_blk_tbl))); + + if (copy_to_user((&(usr_d->tmtp_send_complete_data)), + (&(dev->tmtp_send_complete_data)), + sizeof(cy_as_gadget_ioctl_send_object))) + return -EFAULT; + + if (copy_to_user((&(usr_d->tmtp_get_complete_data)), + (&(dev->tmtp_get_complete_data)), + sizeof(cy_as_gadget_ioctl_get_object))) + return -EFAULT; + break; + } + case CYASGADGET_CLEARTMTPSTATUS: + { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s got CYASGADGET_CLEARTMTPSTATUS\n", + __func__); + #endif + + dev->tmtp_send_complete = 0 ; + dev->tmtp_get_complete = 0 ; + dev->tmtp_need_new_blk_tbl = 0 ; + + break; + } + case CYASGADGET_INITSOJ: + { + cy_as_gadget_ioctl_i_s_o_j_d k_d ; + cy_as_gadget_ioctl_i_s_o_j_d *usr_d = + (cy_as_gadget_ioctl_i_s_o_j_d *)param ; + cy_as_mtp_block_table blk_table ; + struct scatterlist sg ; + char *alloc_filename; + struct file *file_to_allocate; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s got CYASGADGET_INITSOJ\n", + __func__); + #endif + + memset(&blk_table, 0, sizeof(blk_table)); + + /* Get user argument structure */ + if (copy_from_user(&k_d, usr_d, + sizeof(cy_as_gadget_ioctl_i_s_o_j_d))) + return -EFAULT; + + /* better use fixed size buff*/ + alloc_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL); + + /* get the filename */ + if (copy_from_user(alloc_filename, k_d.file_name, + k_d.name_length + 1)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: CYASGADGET_INITSOJ, " + "copy file name from user space failed\n", + __func__); + #endif + return -EFAULT; + } + + file_to_allocate = filp_open(alloc_filename, O_RDWR, 0); + + if ((int)file_to_allocate != 0xfffffffe) { + + struct address_space *mapping = + file_to_allocate->f_mapping; + const struct address_space_operations *a_ops = + mapping->a_ops; + struct inode *inode = mapping->host; + struct inode *alloc_inode = + file_to_allocate->f_path.dentry->d_inode; + int cluster = 0; + uint32_t num_clusters = 0; + struct buffer_head bh; + struct kstat stat; + struct iattr alloc_iattr; + int nr_pages = 0; + int ret_stat = 0; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: fhandle is OK, " + "calling vfs_getattr\n", __func__); + #endif + + ret_stat = vfs_getattr(file_to_allocate->f_path.mnt, + file_to_allocate->f_path.dentry, &stat); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: returned from " + "vfs_getattr() stat->blksize=0x%lx\n", + __func__, stat.blksize); + #endif + + /* TODO: get this from disk properties + * (from blockdevice)*/ + #define SECTOR_SIZE 512 + if (stat.blksize != 0) { + num_clusters = (k_d.num_bytes) / SECTOR_SIZE; + + if (((k_d.num_bytes) % SECTOR_SIZE) != 0) + num_clusters++; + } else { + goto initsoj_safe_exit; + } + + bh.b_state = 0; + bh.b_blocknr = 0; + /* block size is arbitrary , we'll use sector size*/ + bh.b_size = SECTOR_SIZE ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: getting fat blocks %d " + "size of %d\n", __func__, + num_clusters, bh.b_size); + #endif + for (cluster = 0; cluster < num_clusters; cluster++) { + ret_stat = fat_get_block(inode, + cluster, &bh, 1); + if (ret_stat) { + cy_as_hal_print_message( + "%s: unable to get fat block, " + "ret_stat=0x%d\n", + __func__, ret_stat); + goto initsoj_safe_exit; + } + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: allocated clusters " + "successfully (fat_get_block), check bmap..." + "\n", __func__); + #endif + + alloc_iattr.ia_valid = ATTR_SIZE; + alloc_iattr.ia_size = k_d.num_bytes; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: calling fat_notify_change " + "(ia_valid:%d, ia_size:%d)\n", __func__, + alloc_iattr.ia_valid, + (int)alloc_iattr.ia_size); + #endif + + /* adjust the filesize */ + ret_stat = alloc_inode->i_op->setattr( + file_to_allocate->f_path.dentry, &alloc_iattr); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: fat_setattr() " + "returned 0x%x\n", + __func__, ret_stat); + #endif + + /* clear dirty pages in page cache + * (if were any allocated) */ + nr_pages = (k_d.num_bytes) / (PAGE_CACHE_SIZE); + + if (((k_d.num_bytes) % (PAGE_CACHE_SIZE)) != 0) + nr_pages++; + + #ifndef WESTBRIDGE_NDEBUG + /*check out how many pages where actually allocated */ + if (mapping->nrpages != nr_pages) + cy_as_hal_print_message("%s mpage_cleardirty " + "mapping->nrpages %d != num_pages %d\n", + __func__, (int) mapping->nrpages, + nr_pages); + + cy_as_hal_print_message("%s: calling " + "mpage_cleardirty() " + "for %d pages\n", __func__, nr_pages); + #endif + + ret_stat = mpage_cleardirty(mapping, nr_pages); + + /*fill up the the block table from the addr mapping */ + if (a_ops->bmap) { + int8_t blk_table_idx = -1; + uint32_t file_block_idx = 0; + uint32_t last_blk_addr_map = 0, + curr_blk_addr_map = 0; + + #ifndef WESTBRIDGE_NDEBUG + if (alloc_inode->i_bytes == 0) + cy_as_hal_print_message( + "%s: alloc_inode->ibytes =0\n", + __func__); + #endif + + /* iterate through the list of + * blocks (not clusters)*/ + for (file_block_idx = 0; + file_block_idx < num_clusters + /*inode->i_bytes*/; file_block_idx++) { + + /* returns starting sector number */ + curr_blk_addr_map = + a_ops->bmap(mapping, + file_block_idx); + + /*no valid mapping*/ + if (curr_blk_addr_map == 0) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s:hit invalid " + "mapping\n", __func__); + #endif + break; + } else if (curr_blk_addr_map != + (last_blk_addr_map + 1) || + (blk_table.num_blocks + [blk_table_idx] == 65535)) { + + /* next table entry */ + blk_table_idx++; + /* starting sector of a + * scattered cluster*/ + blk_table.start_blocks + [blk_table_idx] = + curr_blk_addr_map; + /* ++ num of blocks in cur + * table entry*/ + blk_table. + num_blocks[blk_table_idx]++; + + #ifndef WESTBRIDGE_NDEBUG + if (file_block_idx != 0) + cy_as_hal_print_message( + "<*> next table " + "entry:%d required\n", + blk_table_idx); + #endif + } else { + /*add contiguous block*/ + blk_table.num_blocks + [blk_table_idx]++; + } /*if (curr_blk_addr_map == 0)*/ + + last_blk_addr_map = curr_blk_addr_map; + } /* end for (file_block_idx = 0; file_block_idx + < inode->i_bytes;) */ + + #ifndef WESTBRIDGE_NDEBUG + /*print result for verification*/ + { + int i; + cy_as_hal_print_message( + "%s: print block table " + "mapping:\n", + __func__); + for (i = 0; i <= blk_table_idx; i++) { + cy_as_hal_print_message( + "<1> %d 0x%x 0x%x\n", i, + blk_table.start_blocks[i], + blk_table.num_blocks[i]); + } + } + #endif + + /* copy the block table to user + * space (for debug purposes) */ + retval = __put_user( + blk_table.start_blocks[blk_table_idx], + (uint32_t __user *) + (&(usr_d->blk_addr_p))); + + retval = __put_user( + blk_table.num_blocks[blk_table_idx], + (uint32_t __user *) + (&(usr_d->blk_count_p))); + + blk_table_idx++; + retval = __put_user(blk_table_idx, + (uint32_t __user *) + (&(usr_d->item_count))); + + } /*end if (a_ops->bmap)*/ + + filp_close(file_to_allocate, NULL); + + dev->tmtp_send_complete = 0 ; + dev->tmtp_need_new_blk_tbl = 0 ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: calling cy_as_mtp_init_send_object()\n", + __func__); + #endif + sg_init_one(&sg, &blk_table, sizeof(blk_table)); + ret_stat = cy_as_mtp_init_send_object(dev->dev_handle, + (cy_as_mtp_block_table *)&sg, + k_d.num_bytes, 0, 0); + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: returned from " + "cy_as_mtp_init_send_object()\n", __func__); + #endif + + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message( + "%s: failed to allocate the file %s\n", + __func__, alloc_filename); + } /* end if (file_to_allocate)*/ + #endif +initsoj_safe_exit: + ret_stat = 0; + retval = __put_user(ret_stat, + (uint32_t __user *)(&(usr_d->ret_val))); + + break; + } + case CYASGADGET_INITGOJ: + { + cy_as_gadget_ioctl_i_g_o_j_d k_d ; + cy_as_gadget_ioctl_i_g_o_j_d *usr_d = + (cy_as_gadget_ioctl_i_g_o_j_d *)param ; + cy_as_mtp_block_table blk_table ; + struct scatterlist sg ; + char *map_filename; + struct file *file_to_map; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: got CYASGADGET_INITGOJ\n", + __func__); + #endif + + memset(&blk_table, 0, sizeof(blk_table)); + + /* Get user argument sturcutre */ + if (copy_from_user(&k_d, usr_d, + sizeof(cy_as_gadget_ioctl_i_g_o_j_d))) + return -EFAULT; + + map_filename = kmalloc(k_d.name_length + 1, GFP_KERNEL); + if (copy_from_user(map_filename, k_d.file_name, + k_d.name_length + 1)) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: copy file name from " + "user space failed\n", __func__); + #endif + return -EFAULT; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<*>%s: opening %s for kernel " + "mode access map\n", __func__, map_filename); + #endif + file_to_map = filp_open(map_filename, O_RDWR, 0); + if (file_to_map) { + struct address_space *mapping = file_to_map->f_mapping; + const struct address_space_operations + *a_ops = mapping->a_ops; + struct inode *inode = mapping->host; + + int8_t blk_table_idx = -1; + uint32_t file_block_idx = 0; + uint32_t last_blk_addr_map = 0, curr_blk_addr_map = 0; + + /*verify operation exists*/ + if (a_ops->bmap) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<*>%s: bmap found, i_bytes=0x%x, " + "i_size=0x%x, i_blocks=0x%x\n", + __func__, inode->i_bytes, + (unsigned int) inode->i_size, + (unsigned int) inode->i_blocks); + #endif + + k_d.num_bytes = inode->i_size; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "<*>%s: k_d.num_bytes=0x%x\n", + __func__, k_d.num_bytes); + #endif + + for (file_block_idx = 0; + file_block_idx < inode->i_size; + file_block_idx++) { + curr_blk_addr_map = + a_ops->bmap(mapping, + file_block_idx); + + if (curr_blk_addr_map == 0) { + /*no valid mapping*/ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: no valid " + "mapping\n", __func__); + #endif + break; + } else if (curr_blk_addr_map != + (last_blk_addr_map + 1)) { + /*non-contiguous break*/ + blk_table_idx++; + blk_table.start_blocks + [blk_table_idx] = + curr_blk_addr_map; + blk_table.num_blocks + [blk_table_idx]++; + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: found non-" + "contiguous break", + __func__); + #endif + } else { + /*add contiguous block*/ + blk_table.num_blocks + [blk_table_idx]++; + } + last_blk_addr_map = curr_blk_addr_map; + } + + /*print result for verification*/ + #ifndef WESTBRIDGE_NDEBUG + { + int i = 0; + + for (i = 0 ; i <= blk_table_idx; i++) { + cy_as_hal_print_message( + "%s %d 0x%x 0x%x\n", + __func__, i, + blk_table.start_blocks[i], + blk_table.num_blocks[i]); + } + } + #endif + } else { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: could not find " + "a_ops->bmap\n", __func__); + #endif + return -EFAULT; + } + + filp_close(file_to_map, NULL); + + dev->tmtp_get_complete = 0 ; + dev->tmtp_need_new_blk_tbl = 0 ; + + ret_stat = __put_user( + blk_table.start_blocks[blk_table_idx], + (uint32_t __user *)(&(usr_d->blk_addr_p))); + + ret_stat = __put_user( + blk_table.num_blocks[blk_table_idx], + (uint32_t __user *)(&(usr_d->blk_count_p))); + + sg_init_one(&sg, &blk_table, sizeof(blk_table)); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: calling cy_as_mtp_init_get_object() " + "start=0x%x, num =0x%x, tid=0x%x, " + "num_bytes=0x%x\n", + __func__, + blk_table.start_blocks[0], + blk_table.num_blocks[0], + k_d.tid, + k_d.num_bytes); + #endif + + ret_stat = cy_as_mtp_init_get_object( + dev->dev_handle, + (cy_as_mtp_block_table *)&sg, + k_d.num_bytes, k_d.tid, 0, 0); + if (ret_stat != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: cy_as_mtp_init_get_object " + "failed ret_stat=0x%x\n", + __func__, ret_stat); + #endif + } + } + #ifndef WESTBRIDGE_NDEBUG + else { + cy_as_hal_print_message( + "%s: failed to open file %s\n", + __func__, map_filename); + } + #endif + + ret_stat = 0; + retval = __put_user(ret_stat, (uint32_t __user *) + (&(usr_d->ret_val))); + break; + } + case CYASGADGET_CANCELSOJ: + { + cy_as_gadget_ioctl_cancel *usr_d = + (cy_as_gadget_ioctl_cancel *)param ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message( + "%s: got CYASGADGET_CANCELSOJ\n", + __func__); + #endif + + ret_stat = cy_as_mtp_cancel_send_object(dev->dev_handle, 0, 0); + + retval = __put_user(ret_stat, (uint32_t __user *) + (&(usr_d->ret_val))); + break; + } + case CYASGADGET_CANCELGOJ: + { + cy_as_gadget_ioctl_cancel *usr_d = + (cy_as_gadget_ioctl_cancel *)param ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: got CYASGADGET_CANCELGOJ\n", + __func__); + #endif + + ret_stat = cy_as_mtp_cancel_get_object(dev->dev_handle, 0, 0); + + retval = __put_user(ret_stat, + (uint32_t __user *)(&(usr_d->ret_val))); + break; + } + default: + { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: unknown ioctl received: %d\n", + __func__, code); + + cy_as_hal_print_message("%s: known codes:\n" + "CYASGADGET_GETMTPSTATUS=%d\n" + "CYASGADGET_CLEARTMTPSTATUS=%d\n" + "CYASGADGET_INITSOJ=%d\n" + "CYASGADGET_INITGOJ=%d\n" + "CYASGADGET_CANCELSOJ=%d\n" + "CYASGADGET_CANCELGOJ=%d\n", + __func__, + CYASGADGET_GETMTPSTATUS, + CYASGADGET_CLEARTMTPSTATUS, + CYASGADGET_INITSOJ, + CYASGADGET_INITGOJ, + CYASGADGET_CANCELSOJ, + CYASGADGET_CANCELGOJ); + #endif + break; + } + } + + return 0; +} + +static const struct usb_gadget_ops cyasgadget_ops = { + .get_frame = cyasgadget_get_frame, + .wakeup = cyasgadget_wakeup, + .set_selfpowered = cyasgadget_set_selfpowered, + .pullup = cyasgadget_pullup, + .ioctl = cyasgadget_ioctl, +}; + + +/* keeping it simple: + * - one bus driver, initted first; + * - one function driver, initted second + * + * most of the work to support multiple controllers would + * be to associate this gadget driver with all of them, or + * perhaps to bind specific drivers to specific devices. + */ + +static void cyas_ep_reset( + cyasgadget_ep *an_ep + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + an_ep->desc = NULL; + INIT_LIST_HEAD(&an_ep->queue); + + an_ep->stopped = 0 ; + an_ep->is_in = 0 ; + an_ep->is_iso = 0 ; + an_ep->usb_ep_inst.maxpacket = ~0; + an_ep->usb_ep_inst.ops = &cyasgadget_ep_ops; +} + +static void cyas_usb_reset( + cyasgadget *cy_as_dev + ) +{ + cy_as_return_status_t ret; + cy_as_usb_enum_control config ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ; + + cy_as_hal_print_message("<1>%s called mtp_firmware=0x%x\n", + __func__, dev_p->is_mtp_firmware); + #endif + + ret = cy_as_misc_release_resource(cy_as_dev->dev_handle, + cy_as_bus_u_s_b) ; + if (ret != CY_AS_ERROR_SUCCESS && ret != + CY_AS_ERROR_RESOURCE_NOT_OWNED) { + cy_as_hal_print_message("<1>_cy_as_gadget: cannot " + "release usb resource: failed with error code %d\n", + ret) ; + return ; + } + + cy_as_dev->gadget.speed = USB_SPEED_HIGH ; + + ret = cy_as_usb_start(cy_as_dev->dev_handle, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_start failed with error code %d\n", + ret) ; + return ; + } + /* P port will do enumeration, not West Bridge */ + config.antioch_enumeration = cy_false ; + /* 1 2 : 1-BUS_NUM , 2:Storage_device number, SD - is bus 1*/ + + /* TODO: add module param to enumerate mass storage */ + config.mass_storage_interface = 0 ; + + if (append_mtp) { + ret = cy_as_mtp_start(cy_as_dev->dev_handle, + cy_as_gadget_mtp_event_callback, 0, 0); + if (ret == CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("MTP start passed, enumerating " + "MTP interface\n"); + config.mtp_interface = append_mtp ; + /*Do not enumerate NAND storage*/ + config.devices_to_enumerate[0][0] = cy_false; + + /*enumerate SD storage as MTP*/ + config.devices_to_enumerate[1][0] = cy_true; + } + } else { + cy_as_hal_print_message("MTP start not attempted, not " + "enumerating MTP interface\n"); + config.mtp_interface = 0 ; + /* enumerate mass storage based on module parameters */ + config.devices_to_enumerate[0][0] = msc_enum_bus_0; + config.devices_to_enumerate[1][0] = msc_enum_bus_1; + } + + ret = cy_as_usb_set_enum_config(cy_as_dev->dev_handle, + &config, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("<1>_cy_as_gadget: " + "cy_as_usb_set_enum_config failed with error " + "code %d\n", ret) ; + return ; + } + + cy_as_usb_set_physical_configuration(cy_as_dev->dev_handle, 1); + +} + +static void cyas_usb_reinit( + cyasgadget *cy_as_dev + ) +{ + int index = 0; + cyasgadget_ep *an_ep_p; + cy_as_return_status_t ret; + cy_as_device *dev_p = (cy_as_device *)cy_as_dev->dev_handle ; + + INIT_LIST_HEAD(&cy_as_dev->gadget.ep_list); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called, is_mtp_firmware = " + "0x%x\n", __func__, dev_p->is_mtp_firmware); + #endif + + /* Init the end points */ + for (index = 1; index <= 15; index++) { + an_ep_p = &cy_as_dev->an_gadget_ep[index] ; + cyas_ep_reset(an_ep_p) ; + an_ep_p->usb_ep_inst.name = cy_as_ep_names[index] ; + an_ep_p->dev = cy_as_dev ; + an_ep_p->num = index ; + memset(&an_ep_p->cyepconfig, 0, sizeof(an_ep_p->cyepconfig)); + + /* EP0, EPs 2,4,6,8 need not be added */ + if ((index <= 8) && (index % 2 == 0) && + (!dev_p->is_mtp_firmware)) { + /* EP0 is 64 and EPs 2,4,6,8 not allowed */ + cy_as_dev->an_gadget_ep[index].fifo_size = 0 ; + } else { + if (index == 1) + an_ep_p->fifo_size = 64; + else + an_ep_p->fifo_size = 512 ; + list_add_tail(&an_ep_p->usb_ep_inst.ep_list, + &cy_as_dev->gadget.ep_list); + } + } + /* need to setendpointconfig before usb connect, this is not + * quite compatible with gadget methodology (ep_enable called + * by gadget after connect), therefore need to set config in + * initialization and verify compatibility in ep_enable, + * kick up error otherwise*/ + an_ep_p = &cy_as_dev->an_gadget_ep[3] ; + an_ep_p->cyepconfig.enabled = cy_true ; + an_ep_p->cyepconfig.dir = cy_as_usb_out ; + an_ep_p->cyepconfig.type = cy_as_usb_bulk ; + an_ep_p->cyepconfig.size = 0 ; + an_ep_p->cyepconfig.physical = 1 ; + ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle, + 3, &an_ep_p->cyepconfig) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("cy_as_usb_set_end_point_config " + "failed with error code %d\n", ret) ; + } + + cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 3, 0, 0); + + an_ep_p = &cy_as_dev->an_gadget_ep[5] ; + an_ep_p->cyepconfig.enabled = cy_true ; + an_ep_p->cyepconfig.dir = cy_as_usb_in ; + an_ep_p->cyepconfig.type = cy_as_usb_bulk ; + an_ep_p->cyepconfig.size = 0 ; + an_ep_p->cyepconfig.physical = 2 ; + ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle, + 5, &an_ep_p->cyepconfig) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("cy_as_usb_set_end_point_config " + "failed with error code %d\n", ret) ; + } + + cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 5, 0, 0); + + an_ep_p = &cy_as_dev->an_gadget_ep[9] ; + an_ep_p->cyepconfig.enabled = cy_true ; + an_ep_p->cyepconfig.dir = cy_as_usb_in ; + an_ep_p->cyepconfig.type = cy_as_usb_bulk ; + an_ep_p->cyepconfig.size = 0 ; + an_ep_p->cyepconfig.physical = 4 ; + ret = cy_as_usb_set_end_point_config(an_ep_p->dev->dev_handle, + 9, &an_ep_p->cyepconfig) ; + if (ret != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message("cy_as_usb_set_end_point_config " + "failed with error code %d\n", ret) ; + } + + cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 9, 0, 0); + + if (dev_p->mtp_count != 0) { + /* these need to be set for compatibility with + * the gadget_enable logic */ + an_ep_p = &cy_as_dev->an_gadget_ep[2] ; + an_ep_p->cyepconfig.enabled = cy_true ; + an_ep_p->cyepconfig.dir = cy_as_usb_out ; + an_ep_p->cyepconfig.type = cy_as_usb_bulk ; + an_ep_p->cyepconfig.size = 0 ; + an_ep_p->cyepconfig.physical = 0 ; + cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 2, 0, 0); + + an_ep_p = &cy_as_dev->an_gadget_ep[6] ; + an_ep_p->cyepconfig.enabled = cy_true ; + an_ep_p->cyepconfig.dir = cy_as_usb_in ; + an_ep_p->cyepconfig.type = cy_as_usb_bulk ; + an_ep_p->cyepconfig.size = 0 ; + an_ep_p->cyepconfig.physical = 0 ; + cy_as_usb_set_stall(an_ep_p->dev->dev_handle, 6, 0, 0); + } + + cyas_ep_reset(&cy_as_dev->an_gadget_ep[0]) ; + cy_as_dev->an_gadget_ep[0].usb_ep_inst.name = cy_as_ep_names[0] ; + cy_as_dev->an_gadget_ep[0].dev = cy_as_dev ; + cy_as_dev->an_gadget_ep[0].num = 0 ; + cy_as_dev->an_gadget_ep[0].fifo_size = 64 ; + + cy_as_dev->an_gadget_ep[0].usb_ep_inst.maxpacket = 64; + cy_as_dev->gadget.ep0 = &cy_as_dev->an_gadget_ep[0].usb_ep_inst; + cy_as_dev->an_gadget_ep[0].stopped = 0; + INIT_LIST_HEAD(&cy_as_dev->gadget.ep0->ep_list); +} + +static void cyas_ep0_start( + cyasgadget *dev + ) +{ + cy_as_return_status_t ret ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + ret = cy_as_usb_register_callback(dev->dev_handle, + cy_as_gadget_usb_event_callback) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_usb_register_callback " + "failed with error code %d\n", __func__, ret) ; + #endif + return ; + } + + ret = cy_as_usb_commit_config(dev->dev_handle, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_usb_commit_config " + "failed with error code %d\n", __func__, ret) ; + #endif + return ; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_usb_commit_config " + "message sent\n", __func__) ; + #endif + + ret = cy_as_usb_connect(dev->dev_handle, 0, 0) ; + if (ret != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_usb_connect failed " + "with error code %d\n", __func__, ret) ; + #endif + return ; + } + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s: cy_as_usb_connect message " + "sent\n", __func__) ; + #endif +} + +/* + * When a driver is successfully registered, it will receive + * control requests including set_configuration(), which enables + * non-control requests. then usb traffic follows until a + * disconnect is reported. then a host may connect again, or + * the driver might get unbound. + */ +int usb_gadget_register_driver( + struct usb_gadget_driver *driver + ) +{ + cyasgadget *dev = cy_as_gadget_controller ; + int retval; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called driver=0x%x\n", + __func__, (unsigned int) driver); + #endif + + /* insist on high speed support from the driver, since + * "must not be used in normal operation" + */ + if (!driver + || !driver->bind + || !driver->unbind + || !driver->setup) + return -EINVAL; + + if (!dev) + return -ENODEV; + + if (dev->driver) + return -EBUSY; + + /* hook up the driver ... */ + dev->softconnect = 1; + driver->driver.bus = NULL; + dev->driver = driver; + dev->gadget.dev.driver = &driver->driver; + + /* Do the needful */ + cyas_usb_reset(dev) ; /* External usb */ + cyas_usb_reinit(dev) ; /* Internal */ + + retval = driver->bind(&dev->gadget); + if (retval) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("%s bind to driver %s --> %d\n", + __func__, driver->driver.name, retval); + #endif + + dev->driver = NULL; + dev->gadget.dev.driver = NULL; + return retval; + } + + /* ... then enable host detection and ep0; and we're ready + * for set_configuration as well as eventual disconnect. + */ + cyas_ep0_start(dev); + + return 0; +} +EXPORT_SYMBOL(usb_gadget_register_driver); + +static void cyasgadget_nuke( + cyasgadget_ep *an_ep + ) +{ + cyasgadget *dev = cy_as_gadget_controller ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + cy_as_usb_cancel_async(dev->dev_handle, an_ep->num); + an_ep->stopped = 1 ; + + while (!list_empty(&an_ep->queue)) { + cyasgadget_req *an_req = list_entry + (an_ep->queue.next, cyasgadget_req, queue) ; + list_del_init(&an_req->queue) ; + an_req->req.status = -ESHUTDOWN ; + an_req->req.complete(&an_ep->usb_ep_inst, &an_req->req) ; + } +} + +static void cyasgadget_stop_activity( + cyasgadget *dev, + struct usb_gadget_driver *driver + ) +{ + int index ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + /* don't disconnect if it's not connected */ + if (dev->gadget.speed == USB_SPEED_UNKNOWN) + driver = NULL; + + if (spin_is_locked(&dev->lock)) + spin_unlock(&dev->lock); + + /* Stop hardware; prevent new request submissions; + * and kill any outstanding requests. + */ + cy_as_usb_disconnect(dev->dev_handle, 0, 0) ; + + for (index = 3; index <= 7; index += 2) { + cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ; + cyasgadget_nuke(an_ep_p) ; + } + + for (index = 9; index <= 15; index++) { + cyasgadget_ep *an_ep_p = &dev->an_gadget_ep[index] ; + cyasgadget_nuke(an_ep_p) ; + } + + /* report disconnect; the driver is already quiesced */ + if (driver) + driver->disconnect(&dev->gadget); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("cy_as_usb_disconnect returned success"); + #endif + + /* Stop Usb */ + cy_as_usb_stop(dev->dev_handle, 0, 0) ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("cy_as_usb_stop returned success"); + #endif +} + +int usb_gadget_unregister_driver( + struct usb_gadget_driver *driver + ) +{ + cyasgadget *dev = cy_as_gadget_controller ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + if (!dev) + return -ENODEV; + + if (!driver || driver != dev->driver) + return -EINVAL; + + cyasgadget_stop_activity(dev, driver); + + driver->unbind(&dev->gadget); + dev->gadget.dev.driver = NULL; + dev->driver = NULL; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("unregistered driver '%s'\n", + driver->driver.name) ; + #endif + + return 0; +} +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +static void cyas_gadget_release( + struct device *_dev + ) +{ + cyasgadget *dev = dev_get_drvdata(_dev); + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>%s called\n", __func__); + #endif + + kfree(dev); +} + +/* DeInitialize gadget driver */ +static void cyasgadget_deinit( + cyasgadget *cy_as_dev + ) +{ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget deinitialize called\n") ; + #endif + + if (!cy_as_dev) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget_deinit: " + "invalid cyasgadget device\n") ; + #endif + return ; + } + + if (cy_as_dev->driver) { + /* should have been done already by driver model core */ + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1> cy_as_gadget: '%s' " + "is still registered\n", + cy_as_dev->driver->driver.name); + #endif + usb_gadget_unregister_driver(cy_as_dev->driver); + } + + kfree(cy_as_dev) ; + cy_as_gadget_controller = NULL ; +} + +/* Initialize gadget driver */ +static int cyasgadget_initialize(void) +{ + cyasgadget *cy_as_dev = 0 ; + int retval = 0 ; + + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message("<1>_cy_as_gadget [V1.1] initialize called\n") ; + #endif + + if (cy_as_gadget_controller != 0) { + cy_as_hal_print_message("<1> cy_as_gadget: the device has " + "already been initilaized. ignoring\n") ; + return -EBUSY ; + } + + cy_as_dev = kzalloc(sizeof(cyasgadget), GFP_ATOMIC); + if (cy_as_dev == NULL) { + cy_as_hal_print_message("<1> cy_as_gadget: memory " + "allocation failed\n") ; + return -ENOMEM; + } + + spin_lock_init(&cy_as_dev->lock); + cy_as_dev->gadget.ops = &cyasgadget_ops; + cy_as_dev->gadget.is_dualspeed = 1; + + /* the "gadget" abstracts/virtualizes the controller */ + /*strcpy(cy_as_dev->gadget.dev.bus_id, "cyasgadget");*/ + cy_as_dev->gadget.dev.release = cyas_gadget_release; + cy_as_dev->gadget.name = cy_as_driver_name; + + /* Get the device handle */ + cy_as_dev->dev_handle = cyasdevice_getdevhandle() ; + if (0 == cy_as_dev->dev_handle) { + #ifndef NDEBUG + cy_as_hal_print_message("<1> cy_as_gadget: " + "no west bridge device\n") ; + #endif + retval = -EFAULT ; + goto done ; + } + + /* We are done now */ + cy_as_gadget_controller = cy_as_dev ; + return 0 ; + +/* + * in case of an error + */ +done: + if (cy_as_dev) + cyasgadget_deinit(cy_as_dev) ; + + return retval ; +} + +static int __init cyas_init(void) +{ + int init_res = 0; + + init_res = cyasgadget_initialize(); + + if (init_res != 0) { + printk(KERN_WARNING "<1> gadget ctl instance " + "init error:%d\n", init_res); + if (init_res > 0) { + /* force -E/0 linux convention */ + init_res = init_res * -1; + } + } + + return init_res; +} +module_init(cyas_init); + +static void __exit cyas_cleanup(void) +{ + if (cy_as_gadget_controller != NULL) + cyasgadget_deinit(cy_as_gadget_controller); +} +module_exit(cyas_cleanup); + + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(CY_AS_DRIVER_DESC); +MODULE_AUTHOR("cypress semiconductor"); + +/*[]*/ diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget.h b/drivers/staging/westbridge/astoria/gadget/cyasgadget.h new file mode 100644 index 000000000000..d7b72d2720be --- /dev/null +++ b/drivers/staging/westbridge/astoria/gadget/cyasgadget.h @@ -0,0 +1,193 @@ +/* cyangadget.h - Linux USB Gadget driver file for the Cypress West Bridge +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * Cypress West Bridge high/full speed USB device controller code + * Based on the Netchip 2280 device controller by David Brownell + * in the linux 2.6.10 kernel + * + * linux/drivers/usb/gadget/net2280.h + */ + +/* + * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _INCLUDED_CYANGADGET_H_ +#define _INCLUDED_CYANGADGET_H_ + +#include +#include +#include +#include +#include + +#include "../include/linux/westbridge/cyastoria.h" +#include "../include/linux/westbridge/cyashal.h" +#include "../include/linux/westbridge/cyasdevice.h" +#include "cyasgadget_ioctl.h" + +#include +#include + +/*char driver defines, revisit*/ +#include +#include +#include +#include /* everything... */ +#include /* error codes */ +#include /* size_t */ +#include +#include /* O_ACCMODE */ +#include +#include +#include +#include +#include /* vmalloc(), vfree */ +#include /*fat_alloc_cluster*/ +#include +#include /* cli(), *_flags */ +#include /* copy_*_user */ + +extern int mpage_cleardirty(struct address_space *mapping, int num_pages); +extern int fat_get_block(struct inode *, sector_t , struct buffer_head *, int); +extern cy_as_device_handle *cyasdevice_getdevhandle(void) ; + +/* Driver data structures and utilities */ +typedef struct cyasgadget_ep { + struct usb_ep usb_ep_inst; + struct cyasgadget *dev; + + /* analogous to a host-side qh */ + struct list_head queue; + const struct usb_endpoint_descriptor *desc; + unsigned num:8, + fifo_size:12, + in_fifo_validate:1, + out_overflow:1, + stopped:1, + is_in:1, + is_iso:1; + cy_as_usb_end_point_config cyepconfig; +} cyasgadget_ep ; + +typedef struct cyasgadget_req { + struct usb_request req; + struct list_head queue; + int ep_num; + unsigned mapped:1, + valid:1, + complete:1, + ep_stopped:1; +} cyasgadget_req ; + +typedef struct cyasgadget { + /* each device provides one gadget, several endpoints */ + struct usb_gadget gadget; + spinlock_t lock; + struct cyasgadget_ep an_gadget_ep[16]; + struct usb_gadget_driver *driver; + /* Handle to the West Bridge device */ + cy_as_device_handle dev_handle; + unsigned enabled:1, + protocol_stall:1, + softconnect:1, + outsetupreq:1; + struct completion thread_complete; + wait_queue_head_t thread_wq; + struct semaphore thread_sem; + struct list_head thread_queue; + + cy_bool tmtp_send_complete; + cy_bool tmtp_get_complete; + cy_bool tmtp_need_new_blk_tbl; + /* Data member used to store the SendObjectComplete event data */ + cy_as_mtp_send_object_complete_data tmtp_send_complete_data; + /* Data member used to store the GetObjectComplete event data */ + cy_as_mtp_get_object_complete_data tmtp_get_complete_data; + +} cyasgadget ; + +static inline void set_halt(cyasgadget_ep *ep) +{ + return ; +} + +static inline void clear_halt(cyasgadget_ep *ep) +{ + return ; +} + +#define xprintk(dev, level, fmt, args...) \ + printk(level "%s %s: " fmt, driver_name, \ + pci_name(dev->pdev), ## args) + +#ifdef DEBUG +#undef DEBUG +#define DEBUG(dev, fmt, args...) \ + xprintk(dev, KERN_DEBUG, fmt, ## args) +#else +#define DEBUG(dev, fmt, args...) \ + do { } while (0) +#endif /* DEBUG */ + +#ifdef VERBOSE +#define VDEBUG DEBUG +#else +#define VDEBUG(dev, fmt, args...) \ + do { } while (0) +#endif /* VERBOSE */ + +#define ERROR(dev, fmt, args...) \ + xprintk(dev, KERN_ERR, fmt, ## args) +#define GADG_WARN(dev, fmt, args...) \ + xprintk(dev, KERN_WARNING, fmt, ## args) +#define INFO(dev, fmt, args...) \ + xprintk(dev, KERN_INFO, fmt, ## args) + +/*-------------------------------------------------------------------------*/ + +static inline void start_out_naking(struct cyasgadget_ep *ep) +{ + return ; +} + +static inline void stop_out_naking(struct cyasgadget_ep *ep) +{ + return ; +} + +#endif /* _INCLUDED_CYANGADGET_H_ */ diff --git a/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h b/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h new file mode 100644 index 000000000000..e67bfd36f62a --- /dev/null +++ b/drivers/staging/westbridge/astoria/gadget/cyasgadget_ioctl.h @@ -0,0 +1,99 @@ +/* cyasgadget_ioctl.h - Linux USB Gadget driver ioctl file for + * Cypress West Bridge +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef CYASGADGET_IOCTL_H +#define CYASGADGET_IOCTL_H + + +#include +#include + +typedef struct cy_as_gadget_ioctl_send_object { + uint32_t status; + uint32_t byte_count ; + uint32_t transaction_id ; +} cy_as_gadget_ioctl_send_object ; + +typedef struct cy_as_gadget_ioctl_get_object { + uint32_t status; + uint32_t byte_count ; +} cy_as_gadget_ioctl_get_object ; + + +typedef struct cy_as_gadget_ioctl_tmtp_status { + cy_bool tmtp_send_complete; + cy_bool tmtp_get_complete; + cy_bool tmtp_need_new_blk_tbl; + cy_as_gadget_ioctl_send_object tmtp_send_complete_data; + cy_as_gadget_ioctl_get_object tmtp_get_complete_data; + uint32_t t_usec; +} cy_as_gadget_ioctl_tmtp_status ; + +/*Init send object data*/ +typedef struct cy_as_gadget_ioctl_i_s_o_j_d { + uint32_t *blk_addr_p; /* starting sector */ + uint16_t *blk_count_p; /* num of sectors in the block */ + /* number of entries in the blk table */ + uint32_t item_count; + uint32_t num_bytes; + /* in case if more prcise timestamping is done in kernel mode */ + uint32_t t_usec; + uint32_t ret_val ; + char *file_name; + uint32_t name_length; + +} cy_as_gadget_ioctl_i_s_o_j_d; + + +/*Init get object data*/ +typedef struct cy_as_gadget_ioctl_i_g_o_j_d { + uint32_t *blk_addr_p; + uint16_t *blk_count_p; + uint32_t item_count; + uint32_t num_bytes; + uint32_t tid ; + uint32_t ret_val ; + char *file_name; + uint32_t name_length; + +} cy_as_gadget_ioctl_i_g_o_j_d ; + +typedef struct cy_as_gadget_ioctl_cancel { + uint32_t ret_val; +} cy_as_gadget_ioctl_cancel; + +#define CYASGADGET_IOC_MAGIC 0xEF +#define CYASGADGET_GETMTPSTATUS \ + _IOW(CYASGADGET_IOC_MAGIC, 0, cy_as_gadget_ioctl_tmtp_status) +#define CYASGADGET_CLEARTMTPSTATUS \ + _IO(CYASGADGET_IOC_MAGIC, 1) +#define CYASGADGET_INITSOJ \ + _IOW(CYASGADGET_IOC_MAGIC, 2, cy_as_gadget_ioctl_i_s_o_j_d) +#define CYASGADGET_INITGOJ \ + _IOW(CYASGADGET_IOC_MAGIC, 3, cy_as_gadget_ioctl_i_g_o_j_d) +#define CYASGADGET_CANCELSOJ \ + _IOW(CYASGADGET_IOC_MAGIC, 4, cy_as_gadget_ioctl_cancel) +#define CYASGADGET_CANCELGOJ \ + _IOW(CYASGADGET_IOC_MAGIC, 5, cy_as_gadget_ioctl_cancel) +#define CYASGADGET_IOC_MAXNR 6 + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h new file mode 100644 index 000000000000..c7d4ebb020c9 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanerr.h @@ -0,0 +1,418 @@ +/* Cypress West Bridge API header file (cyanerr.h) + ## Symbols for backward compatibility with previous releases of Antioch SDK. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANERR_H_ +#define _INCLUDED_CYANERR_H_ + +#include "cyaserr.h" + +#ifndef __doxygen__ + +/* + * Function completed successfully. + */ +#define CY_AN_ERROR_SUCCESS (CY_AS_ERROR_SUCCESS) + +/* + * A function trying to acquire a resource was unable to do so. + */ +#define CY_AN_ERROR_NOT_ACQUIRED (CY_AS_ERROR_NOT_ACQUIRED) + +/* + * A function trying to acquire a resource was unable to do so. + */ +#define CY_AN_ERROR_NOT_RELEASED (CY_AS_ERROR_NOT_RELEASED) + +/* + * The West Bridge firmware is not loaded. + */ +#define CY_AN_ERROR_NO_FIRMWARE (CY_AS_ERROR_NO_FIRMWARE) + +/* + * A timeout occurred waiting on a response from the West Bridge device + */ +#define CY_AN_ERROR_TIMEOUT (CY_AS_ERROR_TIMEOUT) + +/* + * A request to download firmware was made while not in the CONFIG mode + */ +#define CY_AN_ERROR_NOT_IN_CONFIG_MODE (CY_AS_ERROR_NOT_IN_CONFIG_MODE) + +/* + * This error is returned if the firmware size specified is too invalid. + */ +#define CY_AN_ERROR_INVALID_SIZE (CY_AS_ERROR_INVALID_SIZE) + +/* + * This error is returned if a request is made to acquire a resource that has + * already been acquired. + */ +#define CY_AN_ERROR_RESOURCE_ALREADY_OWNED (CY_AS_ERROR_RESOURCE_ALREADY_OWNED) + +/* + * This error is returned if a request is made to release a resource that has + * not previously been acquired. + */ +#define CY_AN_ERROR_RESOURCE_NOT_OWNED (CY_AS_ERROR_RESOURCE_NOT_OWNED) + +/* + * This error is returned when a request is made for a media that does not + * exist + */ +#define CY_AN_ERROR_NO_SUCH_MEDIA (CY_AS_ERROR_NO_SUCH_MEDIA) + +/* + * This error is returned when a request is made for a device that does + * not exist + */ +#define CY_AN_ERROR_NO_SUCH_DEVICE (CY_AS_ERROR_NO_SUCH_DEVICE) + +/* + * This error is returned when a request is made for a unit that does + * not exist + */ +#define CY_AN_ERROR_NO_SUCH_UNIT (CY_AS_ERROR_NO_SUCH_UNIT) + +/* + * This error is returned when a request is made for a block that does + * not exist + */ +#define CY_AN_ERROR_INVALID_BLOCK (CY_AS_ERROR_INVALID_BLOCK) + +/* + * This error is returned when an invalid trace level is set. + */ +#define CY_AN_ERROR_INVALID_TRACE_LEVEL (CY_AS_ERROR_INVALID_TRACE_LEVEL) + +/* + * This error is returned when West Bridge is already in the standby state + * and an attempt is made to put West Bridge into this state again. + */ +#define CY_AN_ERROR_ALREADY_STANDBY (CY_AS_ERROR_ALREADY_STANDBY) + +/* + * This error is returned when the API needs to set a pin on the + * West Bridge device, but this is not supported by the underlying HAL + * layer. + */ +#define CY_AN_ERROR_SETTING_WAKEUP_PIN (CY_AS_ERROR_SETTING_WAKEUP_PIN) + +/* + * This error is returned when a module is being started that has + * already been started. + */ +#define CY_AN_ERROR_ALREADY_RUNNING (CY_AS_ERROR_ALREADY_RUNNING) + +/* + * This error is returned when a module is being stopped that has + * already been stopped. + */ +#define CY_AN_ERROR_NOT_RUNNING (CY_AS_ERROR_NOT_RUNNING) + +/* + * This error is returned when the caller tries to claim a media that has + * already been claimed. + */ +#define CY_AN_ERROR_MEDIA_ALREADY_CLAIMED (CY_AS_ERROR_MEDIA_ALREADY_CLAIMED) + +/* + * This error is returned when the caller tries to release a media that + * has already been released. + */ +#define CY_AN_ERROR_MEDIA_NOT_CLAIMED (CY_AS_ERROR_MEDIA_NOT_CLAIMED) + +/* + * This error is returned when canceling trying to cancel an asynchronous + * operation when an async operation is not pending. + */ +#define CY_AN_ERROR_NO_OPERATION_PENDING (CY_AS_ERROR_NO_OPERATION_PENDING) + +/* + * This error is returned when an invalid endpoint number is provided + * to an API call. + */ +#define CY_AN_ERROR_INVALID_ENDPOINT (CY_AS_ERROR_INVALID_ENDPOINT) + +/* + * This error is returned when an invalid descriptor type + * is specified in an API call. + */ +#define CY_AN_ERROR_INVALID_DESCRIPTOR (CY_AS_ERROR_INVALID_DESCRIPTOR) + +/* + * This error is returned when an invalid descriptor index + * is specified in an API call. + */ +#define CY_AN_ERROR_BAD_INDEX (CY_AS_ERROR_BAD_INDEX) + +/* + * This error is returned if trying to set a USB descriptor + * when in the P port enumeration mode. + */ +#define CY_AN_ERROR_BAD_ENUMERATION_MODE (CY_AS_ERROR_BAD_ENUMERATION_MODE) + +/* + * This error is returned when the endpoint configuration specified + * is not valid. + */ +#define CY_AN_ERROR_INVALID_CONFIGURATION (CY_AS_ERROR_INVALID_CONFIGURATION) + +/* + * This error is returned when the API cannot verify it is connected + * to an West Bridge device. + */ +#define CY_AN_ERROR_NO_ANTIOCH (CY_AS_ERROR_NO_ANTIOCH) + +/* + * This error is returned when an API function is called and + * CyAnMiscConfigureDevice has not been called to configure West + * Bridge for the current environment. + */ +#define CY_AN_ERROR_NOT_CONFIGURED (CY_AS_ERROR_NOT_CONFIGURED) + +/* + * This error is returned when West Bridge cannot allocate memory required for + * internal API operations. + */ +#define CY_AN_ERROR_OUT_OF_MEMORY (CY_AS_ERROR_OUT_OF_MEMORY) + +/* + * This error is returned when a module is being started that has + * already been started. + */ +#define CY_AN_ERROR_NESTED_SLEEP (CY_AS_ERROR_NESTED_SLEEP) + +/* + * This error is returned when an operation is attempted on an endpoint that has + * been disabled. + */ +#define CY_AN_ERROR_ENDPOINT_DISABLED (CY_AS_ERROR_ENDPOINT_DISABLED) + +/* + * This error is returned when a call is made to an API function when the device + * is in standby. + */ +#define CY_AN_ERROR_IN_STANDBY (CY_AS_ERROR_IN_STANDBY) + +/* + * This error is returned when an API call is made with an invalid handle value. + */ +#define CY_AN_ERROR_INVALID_HANDLE (CY_AS_ERROR_INVALID_HANDLE) + +/* + * This error is returned when an invalid response is returned from the West + * Bridge device. + */ +#define CY_AN_ERROR_INVALID_RESPONSE (CY_AS_ERROR_INVALID_RESPONSE) + +/* + * This error is returned from the callback function for any asynchronous + * read or write request that is canceled. + */ +#define CY_AN_ERROR_CANCELED (CY_AS_ERROR_CANCELED) + +/* + * This error is returned when the call to create sleep channel fails + * in the HAL layer. + */ +#define CY_AN_ERROR_CREATE_SLEEP_CHANNEL_FAILED \ + (CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED) + +/* + * This error is returned when the call to CyAnMiscLeaveStandby + * is made and the device is not in standby. + */ +#define CY_AN_ERROR_NOT_IN_STANDBY (CY_AS_ERROR_NOT_IN_STANDBY) + +/* + * This error is returned when the call to destroy sleep channel fails + * in the HAL layer. + */ +#define CY_AN_ERROR_DESTROY_SLEEP_CHANNEL_FAILED \ + (CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED) + +/* + * This error is returned when an invalid resource is specified to a call + * to CyAnMiscAcquireResource() or CyAnMiscReleaseResource() + */ +#define CY_AN_ERROR_INVALID_RESOURCE (CY_AS_ERROR_INVALID_RESOURCE) + +/* + * This error occurs when an operation is requested on an endpoint that has + * a currently pending async operation. + */ +#define CY_AN_ERROR_ASYNC_PENDING (CY_AS_ERROR_ASYNC_PENDING) + +/* + * This error is returned when a call to CyAnStorageCancelAsync() or + * CyAnUsbCancelAsync() is made when no asynchronous request is pending. + */ +#define CY_AN_ERROR_ASYNC_NOT_PENDING (CY_AS_ERROR_ASYNC_NOT_PENDING) + +/* + * This error is returned when a request is made to put the West Bridge device + * into standby mode while the USB stack is still active. + */ +#define CY_AN_ERROR_USB_RUNNING (CY_AS_ERROR_USB_RUNNING) + +/* + * A request for in the wrong direction was issued on an endpoint. + */ +#define CY_AN_ERROR_USB_BAD_DIRECTION (CY_AS_ERROR_USB_BAD_DIRECTION) + +/* + * An invalid request was received + */ +#define CY_AN_ERROR_INVALID_REQUEST (CY_AS_ERROR_INVALID_REQUEST) + +/* + * An ACK request was requested while no setup packet was pending. + */ +#define CY_AN_ERROR_NO_SETUP_PACKET_PENDING \ + (CY_AS_ERROR_NO_SETUP_PACKET_PENDING) + +/* + * A call was made to a API function that cannot be called from a callback. + */ +#define CY_AN_ERROR_INVALID_IN_CALLBACK (CY_AS_ERROR_INVALID_IN_CALLBACK) + +/* + * A call was made to CyAnUsbSetEndPointConfig() before + * CyAnUsbSetPhysicalConfiguration() was called. + */ +#define CY_AN_ERROR_ENDPOINT_CONFIG_NOT_SET \ + (CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET) + +/* + * The physical endpoint referenced is not valid in the current + * physical configuration + */ +#define CY_AN_ERROR_INVALID_PHYSICAL_ENDPOINT \ + (CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT) + +/* + * The data supplied to the CyAnMiscDownloadFirmware() call is not aligned on a + * WORD (16 bit) boundary. + */ +#define CY_AN_ERROR_ALIGNMENT_ERROR (CY_AS_ERROR_ALIGNMENT_ERROR) + +/* + * A call was made to destroy the West Bridge device, but the USB stack or the + * storage stack was will running. + */ +#define CY_AN_ERROR_STILL_RUNNING (CY_AS_ERROR_STILL_RUNNING) + +/* + * A call was made to the API for a function that is not yet supported. + */ +#define CY_AN_ERROR_NOT_YET_SUPPORTED (CY_AS_ERROR_NOT_YET_SUPPORTED) + +/* + * A NULL callback was provided where a non-NULL callback was required + */ +#define CY_AN_ERROR_NULL_CALLBACK (CY_AS_ERROR_NULL_CALLBACK) + +/* + * This error is returned when a request is made to put the West Bridge device + * into standby mode while the storage stack is still active. + */ +#define CY_AN_ERROR_STORAGE_RUNNING (CY_AS_ERROR_STORAGE_RUNNING) + +/* + * This error is returned when an operation is attempted that cannot be + * completed while the USB stack is connected to a USB host. + */ +#define CY_AN_ERROR_USB_CONNECTED (CY_AS_ERROR_USB_CONNECTED) + +/* + * This error is returned when a USB disconnect is attempted and the + * West Bridge device is not connected. + */ +#define CY_AN_ERROR_USB_NOT_CONNECTED (CY_AS_ERROR_USB_NOT_CONNECTED) + +/* + * This error is returned when an P2S storage operation attempted and + * data could not be read or written to the storage media. + */ +#define CY_AN_ERROR_MEDIA_ACCESS_FAILURE (CY_AS_ERROR_MEDIA_ACCESS_FAILURE) + +/* + * This error is returned when an P2S storage operation attempted and + * the media is write protected. + */ +#define CY_AN_ERROR_MEDIA_WRITE_PROTECTED (CY_AS_ERROR_MEDIA_WRITE_PROTECTED) + +/* + * This error is returned when an attempt is made to cancel a request + * that has already been sent to the West Bridge. + */ +#define CY_AN_ERROR_OPERATION_IN_TRANSIT (CY_AS_ERROR_OPERATION_IN_TRANSIT) + +/* + * This error is returned when an invalid parameter is passed to one of + * the APIs. + */ +#define CY_AN_ERROR_INVALID_PARAMETER (CY_AS_ERROR_INVALID_PARAMETER) + +/* + * This error is returned if an API is not supported by the current + * West Bridge device or the active firmware version. + */ +#define CY_AN_ERROR_NOT_SUPPORTED (CY_AS_ERROR_NOT_SUPPORTED) + +/* + * This error is returned when a call is made to one of the Storage or + * USB APIs while the device is in suspend mode. + */ +#define CY_AN_ERROR_IN_SUSPEND (CY_AS_ERROR_IN_SUSPEND) + +/* + * This error is returned when the call to CyAnMiscLeaveSuspend + * is made and the device is not in suspend mode. + */ +#define CY_AN_ERROR_NOT_IN_SUSPEND (CY_AS_ERROR_NOT_IN_SUSPEND) + +/* + * This error is returned when a command that is disabled by USB is called. + */ +#define CY_AN_ERROR_FEATURE_NOT_ENABLED (CY_AS_ERROR_FEATURE_NOT_ENABLED) + +/* + * This error is returned when an Async storage read or write is called before a + * query device call is issued. + */ +#define CY_AN_ERROR_QUERY_DEVICE_NEEDED (CY_AS_ERROR_QUERY_DEVICE_NEEDED) + +/* + * This error is returned when a call is made to USB or STORAGE Start or + * Stop before a prior Start or Stop has finished. + */ +#define CY_AN_ERROR_STARTSTOP_PENDING (CY_AS_ERROR_STARTSTOP_PENDING) + +/* + * This error is returned when a request is made for a bus that does not exist + */ +#define CY_AN_ERROR_NO_SUCH_BUS (CY_AS_ERROR_NO_SUCH_BUS) + +#endif /* __doxygen__ */ + +#endif /* _INCLUDED_CYANERR_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h new file mode 100644 index 000000000000..be074887f5a3 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmedia.h @@ -0,0 +1,59 @@ +/* Cypress West Bridge API header file (cyanmedia.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANMEDIA_H_ +#define _INCLUDED_CYANMEDIA_H_ + +#include "cyas_cplus_start.h" + +/* Summary + Specifies a specific type of media supported by West Bridge + + Description + The West Bridge device supports five specific types + of media as storage/IO devices attached to it's S-Port. This + type is used to indicate the type of media being referenced in + any API call. +*/ +#include "cyasmedia.h" + +/* Flash NAND memory (may be SLC or MLC) */ +#define cy_an_media_nand cy_as_media_nand + +/* An SD flash memory device */ +#define cy_an_media_sd_flash cy_as_media_sd_flash + +/* An MMC flash memory device */ +#define cy_an_media_mmc_flash cy_as_media_mmc_flash + +/* A CE-ATA disk drive */ +#define cy_an_media_ce_ata cy_as_media_ce_ata + + /* SDIO device. */ +#define cy_an_media_sdio cy_as_media_sdio +#define cy_an_media_max_media_value \ + cy_as_media_max_media_value + +typedef cy_as_media_type cy_an_media_type; + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYANMEDIA_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h new file mode 100644 index 000000000000..34584b798709 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanmisc.h @@ -0,0 +1,614 @@ +/* Cypress West Bridge API header file (cyanmisc.h) + ## Version for backward compatibility with previous Antioch SDK releases. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANMISC_H_ +#define _INCLUDED_CYANMISC_H_ + +#include "cyantypes.h" +#include +#include "cyanmedia.h" +#include "cyas_cplus_start.h" + +#define CY_AN_LEAVE_STANDBY_DELAY_CLOCK \ + (CY_AS_LEAVE_STANDBY_DELAY_CLOCK) +#define CY_AN_RESET_DELAY_CLOCK \ + (CY_AS_RESET_DELAY_CLOCK) + +#define CY_AN_LEAVE_STANDBY_DELAY_CRYSTAL \ + (CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL) + +#define CY_AN_RESET_DELAY_CRYSTAL \ + (CY_AS_RESET_DELAY_CRYSTAL) + +/* Defines to convert the old CyAn names to the new + * CyAs names + */ +typedef cy_as_device_handle cy_an_device_handle; + +#define cy_an_device_dack_ack cy_as_device_dack_ack +#define cy_an_device_dack_eob cy_as_device_dack_eob +typedef cy_as_device_dack_mode cy_an_device_dack_mode; + +typedef cy_as_device_config cy_an_device_config; + +#define cy_an_resource_u_s_b cy_as_bus_u_sB +#define cy_an_resource_sdio_MMC cy_as_bus_1 +#define cy_an_resource_nand cy_as_bus_0 +typedef cy_as_resource_type cy_an_resource_type; + +#define cy_an_reset_soft cy_as_reset_soft +#define cy_an_reset_hard cy_as_reset_hard +typedef cy_as_reset_type cy_an_reset_type; +typedef cy_as_funct_c_b_type cy_an_funct_c_b_type; +typedef cy_as_function_callback cy_an_function_callback; + +#define cy_an_event_misc_initialized \ + cy_as_event_misc_initialized +#define cy_an_event_misc_awake \ + cy_as_event_misc_awake +#define cy_an_event_misc_heart_beat \ + cy_as_event_misc_heart_beat +#define cy_an_event_misc_wakeup \ + cy_as_event_misc_wakeup +#define cy_an_event_misc_device_mismatch \ + cy_as_event_misc_device_mismatch +typedef cy_as_misc_event_type \ + cy_an_misc_event_type; +typedef cy_as_misc_event_callback \ + cy_an_misc_event_callback; + +#define cy_an_misc_gpio_0 cy_as_misc_gpio_0 +#define cy_an_misc_gpio_1 cy_as_misc_gpio_1 +#define cy_an_misc_gpio__nand_CE \ + cy_as_misc_gpio__nand_CE +#define cy_an_misc_gpio__nand_CE2 \ + cy_as_misc_gpio__nand_CE2 +#define cy_an_misc_gpio__nand_WP \ + cy_as_misc_gpio__nand_WP +#define cy_an_misc_gpio__nand_CLE \ + cy_as_misc_gpio__nand_CLE +#define cy_an_misc_gpio__nand_ALE \ + cy_as_misc_gpio__nand_ALE +#define cy_an_misc_gpio_U_valid \ + cy_as_misc_gpio_U_valid +#define cy_an_misc_gpio_SD_POW \ + cy_as_misc_gpio_SD_POW +typedef cy_as_misc_gpio cy_an_misc_gpio; + +#define CY_AN_SD_DEFAULT_FREQ CY_AS_SD_DEFAULT_FREQ +#define CY_AN_SD_RATED_FREQ CY_AS_SD_RATED_FREQ +typedef cy_as_low_speed_sd_freq cy_an_low_speed_sd_freq; + +#define CY_AN_HS_SD_FREQ_48 CY_AS_HS_SD_FREQ_48 +#define CY_AN_HS_SD_FREQ_24 CY_AS_HS_SD_FREQ_24 +typedef cy_as_high_speed_sd_freq \ + cy_an_high_speed_sd_freq; + +#define cy_an_misc_active_high cy_as_misc_active_high +#define cy_an_misc_active_low cy_as_misc_active_low +typedef cy_as_misc_signal_polarity cy_an_misc_signal_polarity; + +typedef cy_as_get_firmware_version_data \ + cy_an_get_firmware_version_data; + +enum { + CYAN_FW_TRACE_LOG_NONE = 0, + CYAN_FW_TRACE_LOG_STATE, + CYAN_FW_TRACE_LOG_CALLS, + CYAN_FW_TRACE_LOG_STACK_TRACE, + CYAN_FW_TRACE_MAX_LEVEL +}; + + +/***********************************/ +/***********************************/ +/* FUNCTIONS */ +/***********************************/ +/***********************************/ + + +EXTERN cy_an_return_status_t +cy_an_misc_create_device( + cy_an_device_handle *handle_p, + cy_an_hal_device_tag tag + ) ; +#define cy_an_misc_create_device(h, tag) \ + cy_as_misc_create_device((cy_as_device_handle *)(h), \ + (cy_as_hal_device_tag)(tag)) + +EXTERN cy_an_return_status_t +cy_an_misc_destroy_device( + cy_an_device_handle handle + ) ; +#define cy_an_misc_destroy_device(h) \ + cy_as_misc_destroy_device((cy_as_device_handle)(h)) + +EXTERN cy_an_return_status_t +cy_an_misc_configure_device( + cy_an_device_handle handle, + cy_an_device_config *config_p + ) ; +#define cy_an_misc_configure_device(h, cfg) \ + cy_as_misc_configure_device((cy_as_device_handle)(h), \ + (cy_as_device_config *)(cfg)) + +EXTERN cy_an_return_status_t +cy_an_misc_in_standby( + cy_an_device_handle handle, + cy_bool *standby + ) ; +#define cy_an_misc_in_standby(h, standby) \ + cy_as_misc_in_standby((cy_as_device_handle)(h), (standby)) + +/* Sync version of Download Firmware */ +EXTERN cy_an_return_status_t +cy_an_misc_download_firmware( + cy_an_device_handle handle, + const void *fw_p, + uint16_t size + ) ; + +#define cy_an_misc_download_firmware(handle, fw_p, size) \ + cy_as_misc_download_firmware((cy_as_device_handle)\ + (handle), (fw_p), (size), 0, 0) + +/* Async version of Download Firmware */ +EXTERN cy_an_return_status_t +cy_an_misc_download_firmware_e_x( + cy_an_device_handle handle, + const void *fw_p, + uint16_t size, + cy_an_function_callback cb, + uint32_t client + ) ; + +#define cy_an_misc_download_firmware_e_x(h, fw_p, size, cb, client) \ + cy_as_misc_download_firmware((cy_as_device_handle)(h), \ + (fw_p), (size), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Get Firmware Version */ +EXTERN cy_an_return_status_t +cy_as_misc_get_firmware_version_dep( + cy_as_device_handle handle, + uint16_t *major, + uint16_t *minor, + uint16_t *build, + uint8_t *media_type, + cy_bool *is_debug_mode); + +#define cy_an_misc_get_firmware_version\ + (h, major, minor, bld, type, mode) \ + cy_as_misc_get_firmware_version_dep((cy_as_device_handle)(h), \ + (major), (minor), (bld), (type), (mode)) + +/* Async version of Get Firmware Version*/ +EXTERN cy_an_return_status_t +cy_an_misc_get_firmware_version_e_x( + cy_an_device_handle handle, + cy_an_get_firmware_version_data *data, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_get_firmware_version_e_x\ + (h, data, cb, client) \ + cy_as_misc_get_firmware_version((cy_as_device_handle)(h), \ + (data), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Read MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_read_m_c_u_register( + cy_an_device_handle handle, + uint16_t address, + uint8_t *value + ) ; + +#define cy_an_misc_read_m_c_u_register(handle, address, value) \ + cy_as_misc_read_m_c_u_register((cy_as_device_handle)(handle), \ + (address), (value), 0, 0) + +/* Async version of Read MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_read_m_c_u_register_e_x( + cy_an_device_handle handle, + uint16_t address, + uint8_t *value, + cy_an_function_callback cb, + uint32_t client + ) ; + +#define cy_an_misc_read_m_c_u_register_e_x\ + (h, addr, val, cb, client) \ + cy_as_misc_read_m_c_u_register((cy_as_device_handle)(h), \ + (addr), (val), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Write MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_write_m_c_u_register( + cy_an_device_handle handle, + uint16_t address, + uint8_t mask, + uint8_t value + ) ; +#define cy_an_misc_write_m_c_u_register\ + (handle, address, mask, value) \ + cy_as_misc_write_m_c_u_register((cy_as_device_handle)(handle), \ + (address), (mask), (value), 0, 0) + +/* Async version of Write MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_write_m_c_u_register_e_x( + cy_an_device_handle handle, + uint16_t address, + uint8_t mask, + uint8_t value, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_write_m_c_u_register_e_x\ + (h, addr, mask, val, cb, client) \ + cy_as_misc_write_m_c_u_register((cy_as_device_handle)(h), \ + (addr), (mask), (val), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Write MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_reset( + cy_an_device_handle handle, + cy_an_reset_type type, + cy_bool flush + ) ; +#define cy_an_misc_reset(handle, type, flush) \ + cy_as_misc_reset((cy_as_device_handle)(handle), \ + (type), (flush), 0, 0) + +/* Async version of Write MCU Register*/ +EXTERN cy_an_return_status_t +cy_an_misc_reset_e_x( + cy_an_device_handle handle, + cy_an_reset_type type, + cy_bool flush, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_reset_e_x(h, type, flush, cb, client) \ + cy_as_misc_reset((cy_as_device_handle)(h), \ + (cy_as_reset_type)(type), (flush), \ + (cy_as_function_callback)(cb), (client)) + +/* Synchronous version of CyAnMiscAcquireResource. */ +EXTERN cy_an_return_status_t +cy_an_misc_acquire_resource( + cy_an_device_handle handle, + cy_an_resource_type type, + cy_bool force + ) ; +#define cy_an_misc_acquire_resource(h, type, force) \ + cy_as_misc_acquire_resource_dep((cy_as_device_handle)(h), \ + (cy_as_resource_type)(type), (force)) + +/* Asynchronous version of CyAnMiscAcquireResource. */ +EXTERN cy_an_return_status_t +cy_an_misc_acquire_resource_e_x( + cy_an_device_handle handle, + cy_an_resource_type *type, + cy_bool force, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_acquire_resource_e_x\ + (h, type_p, force, cb, client) \ + cy_as_misc_acquire_resource((cy_as_device_handle)(h), \ + (cy_as_resource_type *)(type_p), \ + (force), (cy_as_function_callback)(cb), (client)) + +/* The one and only version of Release resource */ +EXTERN cy_an_return_status_t +cy_an_misc_release_resource( + cy_an_device_handle handle, + cy_an_resource_type type + ) ; +#define cy_an_misc_release_resource(h, type)\ + cy_as_misc_release_resource((cy_as_device_handle)(h), \ + (cy_as_resource_type)(type)) + +/* Synchronous version of CyAnMiscSetTraceLevel. */ +EXTERN cy_an_return_status_t +cy_an_misc_set_trace_level( + cy_an_device_handle handle, + uint8_t level, + cy_an_media_type media, + uint32_t device, + uint32_t unit + ) ; + +#define cy_an_misc_set_trace_level\ + (handle, level, media, device, unit) \ + cy_as_misc_set_trace_level_dep((cy_as_device_handle)(handle), \ + (level), (cy_as_media_type)(media), (device), (unit), 0, 0) + +/* Asynchronous version of CyAnMiscSetTraceLevel. */ +EXTERN cy_an_return_status_t +cy_an_misc_set_trace_level_e_x( + cy_an_device_handle handle, + uint8_t level, + cy_an_media_type media, + uint32_t device, + uint32_t unit, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_set_trace_level_e_x\ + (h, level, media, device, unit, cb, client) \ + cy_as_misc_set_trace_level_dep((cy_as_device_handle)(h), \ + (level), (cy_as_media_type)(media), (device), (unit), \ + (cy_as_function_callback)(cb), (client)) + +/* Synchronous version of CyAnMiscEnterStandby. */ +EXTERN cy_an_return_status_t +cy_an_misc_enter_standby( + cy_an_device_handle handle, + cy_bool pin + ) ; +#define cy_an_misc_enter_standby(handle, pin) \ + cy_as_misc_enter_standby(\ + (cy_as_device_handle)(handle), (pin), 0, 0) + +/* Synchronous version of CyAnMiscEnterStandby. */ +EXTERN cy_an_return_status_t +cy_an_misc_enter_standby_e_x( + cy_an_device_handle handle, + cy_bool pin, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_enter_standby_e_x(h, pin, cb, client) \ + cy_as_misc_enter_standby((cy_as_device_handle)(h), \ + (pin), (cy_as_function_callback)(cb), (client)) + +/* Only one version of CyAnMiscLeaveStandby. */ +EXTERN cy_an_return_status_t +cy_an_misc_leave_standby( + cy_an_device_handle handle, + cy_an_resource_type type + ) ; +#define cy_an_misc_leave_standby(h, type) \ + cy_as_misc_leave_standby((cy_as_device_handle)(h), \ + (cy_as_resource_type)(type)) + +/* The one version of Misc Register Callback */ +EXTERN cy_an_return_status_t +cy_an_misc_register_callback( + cy_an_device_handle handle, + cy_an_misc_event_callback callback + ) ; +#define cy_an_misc_register_callback(h, cb) \ + cy_as_misc_register_callback((cy_as_device_handle)(h), \ + (cy_as_misc_event_callback)(cb)) + +/* The only version of SetLogLevel */ +EXTERN void +cy_an_misc_set_log_level( + uint8_t level + ) ; +#define cy_an_misc_set_log_level(level) \ + cy_as_misc_set_log_level(level) + +/* Sync version of Misc Storage Changed */ +EXTERN cy_an_return_status_t +cy_an_misc_storage_changed( + cy_an_device_handle handle + ) ; +#define cy_an_misc_storage_changed(handle) \ + cy_as_misc_storage_changed((cy_as_device_handle)(handle), 0, 0) + +/* Async version of Misc Storage Changed */ +EXTERN cy_an_return_status_t +cy_an_misc_storage_changed_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_storage_changed_e_x(h, cb, client) \ + cy_as_misc_storage_changed((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Heartbeat control */ +EXTERN cy_an_return_status_t +cy_an_misc_heart_beat_control( + cy_an_device_handle handle, + cy_bool enable + ) ; +#define cy_an_misc_heart_beat_control(handle, enable) \ + cy_as_misc_heart_beat_control((cy_as_device_handle)\ + (handle), (enable), 0, 0) + +/* Async version of Heartbeat control */ +EXTERN cy_an_return_status_t +cy_an_misc_heart_beat_control_e_x( + cy_an_device_handle handle, + cy_bool enable, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_heart_beat_control_e_x(h, enable, cb, client) \ + cy_as_misc_heart_beat_control((cy_as_device_handle)(h), \ + (enable), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Get Gpio */ +EXTERN cy_an_return_status_t +cy_an_misc_get_gpio_value( + cy_an_device_handle handle, + cy_an_misc_gpio pin, + uint8_t *value + ) ; +#define cy_an_misc_get_gpio_value(handle, pin, value) \ + cy_as_misc_get_gpio_value((cy_as_device_handle)(handle), \ + (cy_as_misc_gpio)(pin), (value), 0, 0) + +/* Async version of Get Gpio */ +EXTERN cy_an_return_status_t +cy_an_misc_get_gpio_value_e_x( + cy_an_device_handle handle, + cy_an_misc_gpio pin, + uint8_t *value, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_get_gpio_value_e_x(h, pin, value, cb, client) \ + cy_as_misc_get_gpio_value((cy_as_device_handle)(h), \ + (cy_as_misc_gpio)(pin), (value), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Set Gpio */ +EXTERN cy_an_return_status_t +cy_an_misc_set_gpio_value( + cy_an_device_handle handle, + cy_an_misc_gpio pin, + uint8_t value + ) ; +#define cy_an_misc_set_gpio_value(handle, pin, value) \ + cy_as_misc_set_gpio_value((cy_as_device_handle)(handle), \ + (cy_as_misc_gpio)(pin), (value), 0, 0) + +/* Async version of Set Gpio */ +EXTERN cy_an_return_status_t +cy_an_misc_set_gpio_value_e_x( + cy_an_device_handle handle, + cy_an_misc_gpio pin, + uint8_t value, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_set_gpio_value_e_x\ + (h, pin, value, cb, client) \ + cy_as_misc_set_gpio_value((cy_as_device_handle)(h), \ + (cy_as_misc_gpio)(pin), (value), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Enter suspend */ +EXTERN cy_an_return_status_t +cy_an_misc_enter_suspend( + cy_an_device_handle handle, + cy_bool usb_wakeup_en, + cy_bool gpio_wakeup_en + ) ; +#define cy_an_misc_enter_suspend(handle, usb_wakeup_en, \ + gpio_wakeup_en) \ + cy_as_misc_enter_suspend((cy_as_device_handle)(handle), \ + (usb_wakeup_en), (gpio_wakeup_en), 0, 0) + +/* Async version of Enter suspend */ +EXTERN cy_an_return_status_t +cy_an_misc_enter_suspend_e_x( + cy_an_device_handle handle, + cy_bool usb_wakeup_en, + cy_bool gpio_wakeup_en, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_enter_suspend_e_x(h, usb_en, gpio_en, cb, client)\ + cy_as_misc_enter_suspend((cy_as_device_handle)(h), (usb_en), \ + (gpio_en), (cy_as_function_callback)(cb), (client)) + +/* Sync version of Enter suspend */ +EXTERN cy_an_return_status_t +cy_an_misc_leave_suspend( + cy_an_device_handle handle + ) ; +#define cy_an_misc_leave_suspend(handle) \ + cy_as_misc_leave_suspend((cy_as_device_handle)(handle), 0, 0) + +/* Async version of Enter suspend */ +EXTERN cy_an_return_status_t +cy_an_misc_leave_suspend_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; + +#define cy_an_misc_leave_suspend_e_x(h, cb, client) \ + cy_as_misc_leave_suspend((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of SetLowSpeedSDFreq */ +EXTERN cy_an_return_status_t +cy_an_misc_set_low_speed_sd_freq( + cy_an_device_handle handle, + cy_an_low_speed_sd_freq setting + ) ; +#define cy_an_misc_set_low_speed_sd_freq(h, setting) \ + cy_as_misc_set_low_speed_sd_freq((cy_as_device_handle)(h), \ + (cy_as_low_speed_sd_freq)(setting), 0, 0) + +/* Async version of SetLowSpeedSDFreq */ +EXTERN cy_an_return_status_t +cy_an_misc_set_low_speed_sd_freq_e_x( + cy_an_device_handle handle, + cy_an_low_speed_sd_freq setting, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_set_low_speed_sd_freq_e_x\ +(h, setting, cb, client) \ + cy_as_misc_set_low_speed_sd_freq((cy_as_device_handle)(h), \ + (cy_as_low_speed_sd_freq)(setting), \ + (cy_as_function_callback)(cb), (client)) + +/* SetHighSpeedSDFreq */ +EXTERN cy_an_return_status_t +cy_an_misc_set_high_speed_sd_freq( + cy_an_device_handle handle, + cy_an_high_speed_sd_freq setting, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_misc_set_high_speed_sd_freq(h, setting, cb, client) \ + cy_as_misc_set_high_speed_sd_freq((cy_as_device_handle)(h), \ + (cy_as_high_speed_sd_freq)(setting), \ + (cy_as_function_callback)(cb), (client)) + +/* ReserveLNABootArea */ +EXTERN cy_an_return_status_t +cy_an_misc_reserve_l_n_a_boot_area( + cy_an_device_handle handle, + uint8_t numzones, + cy_an_function_callback cb, + uint32_t client); +#define cy_an_misc_reserve_l_n_a_boot_area(h, num, cb, client) \ + cy_as_misc_reserve_l_n_a_boot_area((cy_as_device_handle)(h), \ + num, (cy_as_function_callback)(cb), (client)) + +/* SetSDPowerPolarity */ +EXTERN cy_an_return_status_t +cy_an_misc_set_sd_power_polarity( + cy_an_device_handle handle, + cy_an_misc_signal_polarity polarity, + cy_an_function_callback cb, + uint32_t client); +#define cy_an_misc_set_sd_power_polarity(h, pol, cb, client) \ + cy_as_misc_set_sd_power_polarity((cy_as_device_handle)(h), \ + (cy_as_misc_signal_polarity)(pol), \ + (cy_as_function_callback)(cb), (client)) + +#include "cyas_cplus_end.h" + +#endif + diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h new file mode 100644 index 000000000000..d670291bd24d --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanregs.h @@ -0,0 +1,180 @@ +/* Cypress West Bridge API header file (cyanregs.h) + ## Register and field definitions for the Antioch device. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANREG_H_ +#define _INCLUDED_CYANREG_H_ + +#if !defined(__doxygen__) + +#define CY_AN_MEM_CM_WB_CFG_ID (0x80) +#define CY_AN_MEM_CM_WB_CFG_ID_VER_MASK (0x000F) +#define CY_AN_MEM_CM_WB_CFG_ID_HDID_MASK (0xFFF0) +#define CY_AN_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE (0xA100) +#define CY_AN_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE (0x6800) +#define CY_AN_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE (0xA200) + + +#define CY_AN_MEM_RST_CTRL_REG (0x81) +#define CY_AN_MEM_RST_CTRL_REG_HARD (0x0003) +#define CY_AN_MEM_RST_CTRL_REG_SOFT (0x0001) +#define CY_AN_MEM_RST_RSTCMPT (0x0004) + +#define CY_AN_MEM_P0_ENDIAN (0x82) +#define CY_AN_LITTLE_ENDIAN (0x0000) +#define CY_AN_BIG_ENDIAN (0x0101) + +#define CY_AN_MEM_P0_VM_SET (0x83) +#define CY_AN_MEM_P0_VM_SET_VMTYPE_MASK (0x0007) +#define CY_AN_MEM_P0_VM_SET_VMTYPE_RAM (0x0005) +#define CY_AN_MEM_P0_VM_SET_VMTYPE_VMWIDTH (0x0008) +#define CY_AN_MEM_P0_VM_SET_VMTYPE_FLOWCTRL (0x0010) +#define CY_AN_MEM_P0_VM_SET_IFMODE (0x0020) +#define CY_AN_MEM_P0_VM_SET_CFGMODE (0x0040) +#define CY_AN_MEM_P0_VM_SET_DACKEOB (0x0080) +#define CY_AN_MEM_P0_VM_SET_OVERRIDE (0x0100) +#define CY_AN_MEM_P0_VM_SET_INTOVERD (0x0200) +#define CY_AN_MEM_P0_VM_SET_DRQOVERD (0x0400) +#define CY_AN_MEM_P0_VM_SET_DRQPOL (0x0800) +#define CY_AN_MEM_P0_VM_SET_DACKPOL (0x1000) + + +#define CY_AN_MEM_P0_NV_SET (0x84) +#define CY_AN_MEM_P0_NV_SET_WPSWEN (0x0001) +#define CY_AN_MEM_P0_NV_SET_WPPOLAR (0x0002) + +#define CY_AN_MEM_PMU_UPDATE (0x85) +#define CY_AN_MEM_PMU_UPDATE_UVALID (0x0001) +#define CY_AN_MEM_PMU_UPDATE_USBUPDATE (0x0002) +#define CY_AN_MEM_PMU_UPDATE_SDIOUPDATE (0x0004) + +#define CY_AN_MEM_P0_INTR_REG (0x90) +#define CY_AN_MEM_P0_INTR_REG_MCUINT (0x0020) +#define CY_AN_MEM_P0_INTR_REG_DRQINT (0x0800) +#define CY_AN_MEM_P0_INTR_REG_MBINT (0x1000) +#define CY_AN_MEM_P0_INTR_REG_PMINT (0x2000) +#define CY_AN_MEM_P0_INTR_REG_PLLLOCKINT (0x4000) + +#define CY_AN_MEM_P0_INT_MASK_REG (0x91) +#define CY_AN_MEM_P0_INT_MASK_REG_MMCUINT (0x0020) +#define CY_AN_MEM_P0_INT_MASK_REG_MDRQINT (0x0800) +#define CY_AN_MEM_P0_INT_MASK_REG_MMBINT (0x1000) +#define CY_AN_MEM_P0_INT_MASK_REG_MPMINT (0x2000) +#define CY_AN_MEM_P0_INT_MASK_REG_MPLLLOCKINT (0x4000) + +#define CY_AN_MEM_MCU_MB_STAT (0x92) +#define CY_AN_MEM_P0_MCU_MBNOTRD (0x0001) + +#define CY_AN_MEM_P0_MCU_STAT (0x94) +#define CY_AN_MEM_P0_MCU_STAT_CARDINS (0x0001) +#define CY_AN_MEM_P0_MCU_STAT_CARDREM (0x0002) + +#define CY_AN_MEM_PWR_MAGT_STAT (0x95) +#define CY_AN_MEM_PWR_MAGT_STAT_WAKEUP (0x0001) + +#define CY_AN_MEM_P0_RSE_ALLOCATE (0x98) +#define CY_AN_MEM_P0_RSE_ALLOCATE_SDIOAVI (0x0001) +#define CY_AN_MEM_P0_RSE_ALLOCATE_SDIOALLO (0x0002) +#define CY_AN_MEM_P0_RSE_ALLOCATE_NANDAVI (0x0004) +#define CY_AN_MEM_P0_RSE_ALLOCATE_NANDALLO (0x0008) +#define CY_AN_MEM_P0_RSE_ALLOCATE_USBAVI (0x0010) +#define CY_AN_MEM_P0_RSE_ALLOCATE_USBALLO (0x0020) + +#define CY_AN_MEM_P0_RSE_MASK (0x9A) +#define CY_AN_MEM_P0_RSE_MASK_MSDIOBUS_RW (0x0003) +#define CY_AN_MEM_P0_RSE_MASK_MNANDBUS_RW (0x00C0) +#define CY_AN_MEM_P0_RSE_MASK_MUSBBUS_RW (0x0030) + +#define CY_AN_MEM_P0_DRQ (0xA0) +#define CY_AN_MEM_P0_DRQ_EP2DRQ (0x0004) +#define CY_AN_MEM_P0_DRQ_EP3DRQ (0x0008) +#define CY_AN_MEM_P0_DRQ_EP4DRQ (0x0010) +#define CY_AN_MEM_P0_DRQ_EP5DRQ (0x0020) +#define CY_AN_MEM_P0_DRQ_EP6DRQ (0x0040) +#define CY_AN_MEM_P0_DRQ_EP7DRQ (0x0080) +#define CY_AN_MEM_P0_DRQ_EP8DRQ (0x0100) +#define CY_AN_MEM_P0_DRQ_EP9DRQ (0x0200) +#define CY_AN_MEM_P0_DRQ_EP10DRQ (0x0400) +#define CY_AN_MEM_P0_DRQ_EP11DRQ (0x0800) +#define CY_AN_MEM_P0_DRQ_EP12DRQ (0x1000) +#define CY_AN_MEM_P0_DRQ_EP13DRQ (0x2000) +#define CY_AN_MEM_P0_DRQ_EP14DRQ (0x4000) +#define CY_AN_MEM_P0_DRQ_EP15DRQ (0x8000) + +#define CY_AN_MEM_P0_DRQ_MASK (0xA1) +#define CY_AN_MEM_P0_DRQ_MASK_MEP2DRQ (0x0004) +#define CY_AN_MEM_P0_DRQ_MASK_MEP3DRQ (0x0008) +#define CY_AN_MEM_P0_DRQ_MASK_MEP4DRQ (0x0010) +#define CY_AN_MEM_P0_DRQ_MASK_MEP5DRQ (0x0020) +#define CY_AN_MEM_P0_DRQ_MASK_MEP6DRQ (0x0040) +#define CY_AN_MEM_P0_DRQ_MASK_MEP7DRQ (0x0080) +#define CY_AN_MEM_P0_DRQ_MASK_MEP8DRQ (0x0100) +#define CY_AN_MEM_P0_DRQ_MASK_MEP9DRQ (0x0200) +#define CY_AN_MEM_P0_DRQ_MASK_MEP10DRQ (0x0400) +#define CY_AN_MEM_P0_DRQ_MASK_MEP11DRQ (0x0800) +#define CY_AN_MEM_P0_DRQ_MASK_MEP12DRQ (0x1000) +#define CY_AN_MEM_P0_DRQ_MASK_MEP13DRQ (0x2000) +#define CY_AN_MEM_P0_DRQ_MASK_MEP14DRQ (0x4000) +#define CY_AN_MEM_P0_DRQ_MASK_MEP15DRQ (0x8000) + +#define CY_AN_MEM_P0_EP2_DMA_REG (0xA2) +#define CY_AN_MEM_P0_E_pn_DMA_REG_COUNT_MASK (0x7FF) +#define CY_AN_MEM_P0_E_pn_DMA_REG_DMAVAL (1 << 12) +#define CY_AN_MEM_P0_EP3_DMA_REG (0xA3) +#define CY_AN_MEM_P0_EP4_DMA_REG (0xA4) +#define CY_AN_MEM_P0_EP5_DMA_REG (0xA5) +#define CY_AN_MEM_P0_EP6_DMA_REG (0xA6) +#define CY_AN_MEM_P0_EP7_DMA_REG (0xA7) +#define CY_AN_MEM_P0_EP8_DMA_REG (0xA8) +#define CY_AN_MEM_P0_EP9_DMA_REG (0xA9) +#define CY_AN_MEM_P0_EP10_DMA_REG (0xAA) +#define CY_AN_MEM_P0_EP11_DMA_REG (0xAB) +#define CY_AN_MEM_P0_EP12_DMA_REG (0xAC) +#define CY_AN_MEM_P0_EP13_DMA_REG (0xAD) +#define CY_AN_MEM_P0_EP14_DMA_REG (0xAE) +#define CY_AN_MEM_P0_EP15_DMA_REG (0xAF) + +#define CY_AN_MEM_IROS_IO_CFG (0xC1) +#define CY_AN_MEM_IROS_IO_CFG_GPIODRVST_MASK (0x0003) +#define CY_AN_MEM_IROS_IO_CFG_GPIOSLEW_MASK (0x0004) +#define CY_AN_MEM_IROS_IO_CFG_PPIODRVST_MASK (0x0018) +#define CY_AN_MEM_IROS_IO_CFG_PPIOSLEW_MASK (0x0020) +#define CY_AN_MEM_IROS_IO_CFG_SSIODRVST_MASK (0x0300) +#define CY_AN_MEM_IROS_IO_CFG_SSIOSLEW_MASK (0x0400) +#define CY_AN_MEM_IROS_IO_CFG_SNIODRVST_MASK (0x1800) +#define CY_AN_MEM_IROS_IO_CFG_SNIOSLEW_MASK (0x2000) + +#define CY_AN_MEM_PLL_LOCK_LOSS_STAT (0xC4) +#define CY_AN_MEM_PLL_LOCK_LOSS_STAT_PLLSTAT (0x0800) + +#define CY_AN_MEM_P0_MAILBOX0 (0xF0) +#define CY_AN_MEM_P0_MAILBOX1 (0xF1) +#define CY_AN_MEM_P0_MAILBOX2 (0xF2) +#define CY_AN_MEM_P0_MAILBOX3 (0xF3) + +#define CY_AN_MEM_MCU_MAILBOX0 (0xF8) +#define CY_AN_MEM_MCU_MAILBOX1 (0xF9) +#define CY_AN_MEM_MCU_MAILBOX2 (0xFA) +#define CY_AN_MEM_MCU_MAILBOX3 (0xFB) + +#endif /* !defined(__doxygen__) */ + +#endif /* _INCLUDED_CYANREG_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h new file mode 100644 index 000000000000..ac26b9556dda --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyansdkversion.h @@ -0,0 +1,30 @@ +/* Cypress Antioch Sdk Version file (cyansdkversion.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANSDK_VERSION_H_ +#define _INCLUDED_CYANSDK_VERSION_H_ + +/* Antioch SDK version 1.3.2 */ +#define CYAN_MAJOR_VERSION (1) +#define CYAN_MINOR_VERSION (3) +#define CYAN_BUILD_NUMBER (473) + +#endif /*_INCLUDED_CYANSDK_VERSION_H_*/ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h new file mode 100644 index 000000000000..766f94a9c92b --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanstorage.h @@ -0,0 +1,419 @@ +/* Cypress West Bridge API header file (cyanstorage.h) + ## Header for backward compatibility with previous releases of Antioch SDK. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANSTORAGE_H_ +#define _INCLUDED_CYANSTORAGE_H_ +#ifndef __doxygen__ + +#include "cyanmedia.h" +#include "cyanmisc.h" +#include "cyasstorage.h" +#include "cyas_cplus_start.h" + +#define CY_AN_LUN_PHYSICAL_DEVICE (CY_AS_LUN_PHYSICAL_DEVICE) +#define CY_AN_STORAGE_EP_SIZE (CY_AS_STORAGE_EP_SIZE) + +#define cy_an_storage_antioch cy_as_storage_antioch +#define cy_an_storage_processor cy_as_storage_processor +#define cy_an_storage_removed cy_as_storage_removed +#define cy_an_storage_inserted cy_as_storage_inserted +#define cy_an_sdio_interrupt cy_as_sdio_interrupt +typedef cy_as_storage_event cy_an_storage_event; + +#define cy_an_op_read cy_as_op_read +#define cy_an_op_write cy_as_op_write +typedef cy_as_oper_type cy_an_oper_type; + +typedef cy_as_device_desc cy_an_device_desc; + +typedef cy_as_unit_desc cy_an_unit_desc; + +typedef cy_as_storage_callback_dep \ + cy_an_storage_callback; + +typedef cy_as_storage_event_callback_dep \ + cy_an_storage_event_callback; + +#define cy_an_sd_reg_OCR cy_as_sd_reg_OCR +#define cy_an_sd_reg_CID cy_as_sd_reg_CID +#define cy_an_sd_reg_CSD cy_as_sd_reg_CSD +typedef cy_as_sd_card_reg_type \ + cy_an_sd_card_reg_type; + +typedef cy_as_storage_query_device_data_dep \ + cy_an_storage_query_device_data ; + +typedef cy_as_storage_query_unit_data_dep \ + cy_an_storage_query_unit_data ; + +typedef cy_as_storage_sd_reg_read_data \ + cy_an_storage_sd_reg_read_data; + +#define CY_AN_SD_REG_OCR_LENGTH (CY_AS_SD_REG_OCR_LENGTH) +#define CY_AN_SD_REG_CID_LENGTH (CY_AS_SD_REG_CID_LENGTH) +#define CY_AN_SD_REG_CSD_LENGTH (CY_AS_SD_REG_CSD_LENGTH) +#define CY_AN_SD_REG_MAX_RESP_LENGTH \ + (CY_AS_SD_REG_MAX_RESP_LENGTH) + +/**** API Functions ******/ + +/* Sync version of Storage Start */ +EXTERN cy_an_return_status_t +cy_an_storage_start( + cy_an_device_handle handle + ) ; +#define cy_an_storage_start(handle) \ + cy_as_storage_start((cy_as_device_handle)(handle), 0, 0) + +/* Async version of Storage Start */ +EXTERN cy_an_return_status_t +cy_an_storage_start_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_start_e_x(h, cb, client) \ + cy_as_storage_start((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Storage Stop */ +EXTERN cy_an_return_status_t +cy_an_storage_stop( + cy_an_device_handle handle + ) ; +#define cy_an_storage_stop(handle) \ + cy_as_storage_stop((cy_as_device_handle)(handle), 0, 0) + +/* Async version of Storage Stop */ +EXTERN cy_an_return_status_t +cy_an_storage_stop_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_stop_e_x(h, cb, client) \ + cy_as_storage_stop((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Register Call back api */ +EXTERN cy_an_return_status_t +cy_an_storage_register_callback( + cy_an_device_handle handle, + cy_an_storage_event_callback callback + ) ; +#define cy_an_storage_register_callback(h, cb) \ + cy_as_storage_register_callback_dep((cy_as_device_handle)(h), \ + (cy_as_storage_event_callback_dep)(cb)) + +/* Sync version of Storage Claim */ +EXTERN cy_an_return_status_t +cy_an_storage_claim( + cy_an_device_handle handle, + cy_an_media_type type + ) ; +#define cy_an_storage_claim(h, type) \ + cy_as_storage_claim_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type)) + +/* Async version of Storage Claim */ +EXTERN cy_an_return_status_t +cy_an_storage_claim_e_x( + cy_an_device_handle handle, + cy_an_media_type *type, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_claim_e_x(h, type_p, cb, client) \ + cy_as_storage_claim_dep_EX((cy_as_device_handle)(h), \ + (cy_as_media_type *)(type_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync Version of Storage Release */ +EXTERN cy_an_return_status_t +cy_an_storage_release( + cy_an_device_handle handle, + cy_an_media_type type + ) ; +#define cy_an_storage_release(h, type) \ + cy_as_storage_release_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type)) + +/* Async Version of Storage Release */ +EXTERN cy_an_return_status_t +cy_an_storage_release_e_x( + cy_an_device_handle handle, + cy_an_media_type *type, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_release_e_x(h, type_p, cb, client) \ + cy_as_storage_release_dep_EX((cy_as_device_handle)(h), \ + (cy_as_media_type *)(type_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Query Media */ +EXTERN cy_an_return_status_t +cy_an_storage_query_media( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t *count + ) ; +#define cy_an_storage_query_media(handle, type, count) \ + cy_as_storage_query_media((cy_as_device_handle)(handle), \ + (cy_as_media_type)(type), (count), 0, 0) + +/* Async version of Query Media */ +EXTERN cy_an_return_status_t +cy_an_storage_query_media_e_x( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t *count, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_query_media_e_x(h, type, count, cb, client) \ + cy_as_storage_query_media((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (count), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Query device */ +EXTERN cy_an_return_status_t +cy_an_storage_query_device( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + cy_an_device_desc *desc_p + ) ; +#define cy_an_storage_query_device(h, type, device, desc_p) \ + cy_as_storage_query_device_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), (cy_as_device_desc *)(desc_p)) + +/* Async version of Query device */ +EXTERN cy_an_return_status_t +cy_an_storage_query_device_e_x( + cy_an_device_handle handle, + cy_an_storage_query_device_data *data, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_query_device_e_x(h, data, cb, client) \ + cy_as_storage_query_device_dep_EX((cy_as_device_handle)(h), \ + (cy_as_storage_query_device_data_dep *)(data), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Query Unit */ +EXTERN cy_an_return_status_t +cy_an_storage_query_unit( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + uint32_t unit, + cy_an_unit_desc *desc_p + ) ; +#define cy_an_storage_query_unit(h, type, device, unit, desc_p) \ + cy_as_storage_query_unit_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), \ + (unit), (cy_as_unit_desc *)(desc_p)) + +/* Async version of Query Unit */ +EXTERN cy_an_return_status_t +cy_an_storage_query_unit_e_x( + cy_an_device_handle handle, + cy_an_storage_query_unit_data *data_p, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_query_unit_e_x(h, data_p, cb, client) \ + cy_as_storage_query_unit_dep_EX((cy_as_device_handle)(h), \ + (cy_as_storage_query_unit_data_dep *)(data_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of device control */ +EXTERN cy_an_return_status_t +cy_an_storage_device_control( + cy_an_device_handle handle, + cy_bool card_detect_en, + cy_bool write_prot_en + ) ; +#define cy_an_storage_device_control(handle, \ + card_detect_en, write_prot_en) \ + cy_as_storage_device_control_dep((cy_as_device_handle)(handle), \ + (card_detect_en), (write_prot_en), 0, 0) + +/* Async version of device control */ +EXTERN cy_an_return_status_t +cy_an_storage_device_control_e_x( + cy_an_device_handle handle, + cy_bool card_detect_en, + cy_bool write_prot_en, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_device_control_e_x(h, det_en, prot_en, cb, client) \ + cy_as_storage_device_control_dep((cy_as_device_handle)(h), (det_en), \ + (prot_en), (cy_as_function_callback)(cb), (client)) + +/* Sync Read */ +EXTERN cy_an_return_status_t +cy_an_storage_read( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + uint32_t unit, + uint32_t block, + void *data_p, + uint16_t num_blocks + ) ; +#define cy_an_storage_read(h, type, device, unit, block, data_p, nblks) \ + cy_as_storage_read_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), (unit), \ + (block), (data_p), (nblks)) + +/* Async Read */ +EXTERN cy_an_return_status_t +cy_an_storage_read_async( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + uint32_t unit, + uint32_t block, + void *data_p, + uint16_t num_blocks, + cy_an_storage_callback callback + ) ; +#define cy_an_storage_read_async(h, type, device, unit, \ + block, data_p, nblks, cb) \ + cy_as_storage_read_async_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), (unit), (block), \ + (data_p), (nblks), (cy_as_storage_callback_dep)(cb)) + +/* Sync Write */ +EXTERN cy_an_return_status_t +cy_an_storage_write( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + uint32_t unit, + uint32_t block, + void *data_p, + uint16_t num_blocks + ) ; +#define cy_an_storage_write(h, type, device, unit, \ + block, data_p, nblks) \ + cy_as_storage_write_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), (unit), \ + (block), (data_p), (nblks)) + +/* Async Write */ +EXTERN cy_an_return_status_t +cy_an_storage_write_async( + cy_an_device_handle handle, + cy_an_media_type type, + uint32_t device, + uint32_t unit, + uint32_t block, + void *data_p, + uint16_t num_blocks, + cy_an_storage_callback callback + ) ; +#define cy_an_storage_write_async(h, type, device, unit, \ + block, data_p, nblks, cb) \ + cy_as_storage_write_async_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), (unit), (block), \ + (data_p), (nblks), (cy_as_storage_callback_dep)(cb)) + +/* Cancel Async */ +EXTERN cy_an_return_status_t +cy_an_storage_cancel_async( + cy_an_device_handle handle + ) ; +#define cy_an_storage_cancel_async(h) \ + cy_as_storage_cancel_async((cy_as_device_handle)(h)) + +/* Sync SD Register Read*/ +EXTERN cy_an_return_status_t +cy_an_storage_sd_register_read( + cy_an_device_handle handle, + cy_an_media_type type, + uint8_t device, + cy_an_sd_card_reg_type reg_type, + uint8_t read_len, + uint8_t *data_p + ) ; +#define cy_an_storage_sd_register_read(h, type, device, \ + reg_type, len, data_p) \ + cy_as_storage_sd_register_read_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), \ + (cy_as_sd_card_reg_type)(reg_type), (len), (data_p)) + +/*Async SD Register Read*/ +EXTERN cy_an_return_status_t +cy_an_storage_sd_register_read_e_x( + cy_an_device_handle handle, + cy_an_media_type type, + uint8_t device, + cy_an_sd_card_reg_type reg_type, + cy_an_storage_sd_reg_read_data *data_p, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_storage_sd_register_read_e_x(h, type, device, \ + reg_type, data_p, cb, client) \ + cy_as_storage_sd_register_read_dep_EX((cy_as_device_handle)(h), \ + (cy_as_media_type)(type), (device), \ + (cy_as_sd_card_reg_type)(reg_type), \ + (cy_as_storage_sd_reg_read_data *)(data_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Create partition on storage device */ +EXTERN cy_an_return_status_t +cy_an_storage_create_p_partition( + cy_an_device_handle handle, + cy_an_media_type media, + uint32_t device, + uint32_t size, + cy_an_function_callback cb, + uint32_t client) ; +#define cy_an_storage_create_p_partition(h, media, dev, \ + size, cb, client) \ + cy_as_storage_create_p_partition_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(media), (dev), \ + (size), (cy_as_function_callback)(cb), (client)) + +/* Remove partition on storage device */ +EXTERN cy_an_return_status_t +cy_an_storage_remove_p_partition( + cy_an_device_handle handle, + cy_an_media_type media, + uint32_t device, + cy_an_function_callback cb, + uint32_t client) ; +#define cy_an_storage_remove_p_partition\ +(h, media, dev, cb, client) \ + cy_as_storage_remove_p_partition_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(media), (dev), \ + (cy_as_function_callback)(cb), (client)) + +#include "cyas_cplus_end.h" +#endif /*__doxygen__ */ + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h new file mode 100644 index 000000000000..d65b35a14ae1 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantioch.h @@ -0,0 +1,35 @@ +/* Cypress West Bridge API header file (cyastioch.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANTIOCH_H_ +#define _INCLUDED_CYANTIOCH_H_ + +#if !defined(__doxygen__) + +#include "cyanerr.h" +#include "cyanmisc.h" +#include "cyanstorage.h" +#include "cyanusb.h" +#include "cyanch9.h" + +#endif + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h new file mode 100644 index 000000000000..d6028d64d247 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyantypes.h @@ -0,0 +1,31 @@ +/* Cypress West Bridge API header file (cyantypes.h) +## Type definitions for backward compatibility with previous +## Antioch SDK releases. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANTYPES_H_ +#define _INCLUDED_CYANTYPES_H_ + +#include "cyastypes.h" +typedef cy_as_end_point_number_t cy_an_end_point_number_t ; +typedef cy_as_return_status_t cy_an_return_status_t ; +typedef cy_as_bus_number_t cy_an_bus_number_t ; +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h new file mode 100644 index 000000000000..0777fd457d49 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyanusb.h @@ -0,0 +1,619 @@ +/* Cypress West Bridge API header file (cyanusb.h) + ## Header for backward compatibility with previous Antioch SDK releases. +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYANUSB_H_ +#define _INCLUDED_CYANUSB_H_ + +#if !defined(__doxygen__) + +#include "cyanmisc.h" +#include "cyasusb.h" +#include "cyas_cplus_start.h" + +#define CY_AN_MAX_USB_DESCRIPTOR_SIZE (CY_AS_MAX_USB_DESCRIPTOR_SIZE) + +typedef cy_as_usb_inquiry_data_dep cy_an_usb_inquiry_data; +typedef cy_as_usb_unknown_command_data_dep \ + cy_an_usb_unknown_command_data ; +typedef cy_as_usb_start_stop_data_dep cy_an_usb_start_stop_data ; +typedef cy_as_m_s_c_progress_data cy_an_m_s_c_progress_data ; + +#define cy_an_usb_nand_enum cy_as_usb_nand_enum +#define cy_an_usb_sd_enum cy_as_usb_sd_enum +#define cy_an_usb_mmc_enum cy_as_usb_mmc_enum +#define cy_an_usb_ce_ata_enum cy_as_usb_ce_ata_enum +typedef cy_as_usb_mass_storage_enum cy_an_usb_mass_storage_enum; + +#define cy_an_usb_desc_device cy_as_usb_desc_device +#define cy_an_usb_desc_device_qual cy_as_usb_desc_device_qual +#define cy_an_usb_desc_f_s_configuration \ + cy_as_usb_desc_f_s_configuration +#define cy_an_usb_desc_h_s_configuration \ + cy_as_usb_desc_h_s_configuration +#define cy_an_usb_desc_string cy_as_usb_desc_string +typedef cy_as_usb_desc_type cy_an_usb_desc_type ; + +#define cy_an_usb_in cy_as_usb_in +#define cy_an_usb_out cy_as_usb_out +#define cy_an_usb_in_out cy_as_usb_in_out +typedef cy_as_usb_end_point_dir cy_an_usb_end_point_dir ; + + +#define cy_an_usb_control cy_as_usb_control +#define cy_an_usb_iso cy_as_usb_iso +#define cy_an_usb_bulk cy_as_usb_bulk +#define cy_an_usb_int cy_as_usb_int +typedef cy_as_usb_end_point_type cy_an_usb_end_point_type ; + + +typedef cy_as_usb_enum_control_dep cy_an_usb_enum_control ; +typedef cy_as_usb_end_point_config cy_an_usb_end_point_config ; + +#define cy_an_usb_m_s_unit0 cy_as_usb_m_s_unit0 +#define cy_an_usb_m_s_unit1 cy_as_usb_m_s_unit1 +#define cy_an_usb_m_s_both cy_as_usb_m_s_both +typedef cy_as_usb_m_s_type_t cy_an_usb_m_s_type_t ; + +#define cy_an_event_usb_suspend cy_as_event_usb_suspend +#define cy_an_event_usb_resume cy_as_event_usb_resume +#define cy_an_event_usb_reset cy_as_event_usb_reset +#define cy_an_event_usb_set_config cy_as_event_usb_set_config +#define cy_an_event_usb_speed_change cy_as_event_usb_speed_change +#define cy_an_event_usb_setup_packet cy_as_event_usb_setup_packet +#define cy_an_event_usb_status_packet cy_as_event_usb_status_packet +#define cy_an_event_usb_inquiry_before cy_as_event_usb_inquiry_before +#define cy_an_event_usb_inquiry_after cy_as_event_usb_inquiry_after +#define cy_an_event_usb_start_stop cy_as_event_usb_start_stop +#define cy_an_event_usb_unknown_storage cy_as_event_usb_unknown_storage +#define cy_an_event_usb_m_s_c_progress cy_as_event_usb_m_s_c_progress +typedef cy_as_usb_event cy_an_usb_event; + +typedef cy_as_usb_event_callback_dep cy_an_usb_event_callback ; + +typedef cy_as_usb_io_callback cy_an_usb_io_callback; +typedef cy_as_usb_function_callback cy_an_usb_function_callback; + +/******* USB Functions ********************/ + +/* Sync Usb Start */ +extern cy_an_return_status_t +cy_an_usb_start( + cy_an_device_handle handle + ) ; +#define cy_an_usb_start(handle) \ + cy_as_usb_start((cy_as_device_handle)(handle), 0, 0) + +/*Async Usb Start */ +extern cy_an_return_status_t +cy_an_usb_start_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_start_e_x(h, cb, client) \ + cy_as_usb_start((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync Usb Stop */ +extern cy_an_return_status_t +cy_an_usb_stop( + cy_an_device_handle handle + ) ; +#define cy_an_usb_stop(handle) \ + cy_as_usb_stop((cy_as_device_handle)(handle), 0, 0) + +/*Async Usb Stop */ +extern cy_an_return_status_t +cy_an_usb_stop_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_stop_e_x(h, cb, client) \ + cy_as_usb_stop((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Register USB event callback */ +EXTERN cy_an_return_status_t +cy_an_usb_register_callback( + cy_an_device_handle handle, + cy_an_usb_event_callback callback + ) ; +#define cy_an_usb_register_callback(h, cb) \ + cy_as_usb_register_callback_dep((cy_as_device_handle)(h), \ + (cy_as_usb_event_callback_dep)(cb)) + +/*Sync Usb connect */ +EXTERN cy_an_return_status_t +cy_an_usb_connect( + cy_an_device_handle handle + ) ; +#define cy_an_usb_connect(handle) \ + cy_as_usb_connect((cy_as_device_handle)(handle), 0, 0) + +/*Async Usb connect */ +extern cy_an_return_status_t +cy_an_usb_connect_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_connect_e_x(h, cb, client) \ + cy_as_usb_connect((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/*Sync Usb disconnect */ +EXTERN cy_an_return_status_t +cy_an_usb_disconnect( + cy_an_device_handle handle + ) ; +#define cy_an_usb_disconnect(handle) \ + cy_as_usb_disconnect((cy_as_device_handle)(handle), 0, 0) + +/*Async Usb disconnect */ +extern cy_an_return_status_t +cy_an_usb_disconnect_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_disconnect_e_x(h, cb, client) \ + cy_as_usb_disconnect((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of set enum config */ +EXTERN cy_an_return_status_t +cy_an_usb_set_enum_config( + cy_an_device_handle handle, + cy_an_usb_enum_control *config_p + ) ; +#define cy_an_usb_set_enum_config(handle, config_p) \ + cy_as_usb_set_enum_config_dep((cy_as_device_handle)(handle), \ + (cy_as_usb_enum_control_dep *)(config_p), 0, 0) + +/* Async version of set enum config */ +extern cy_an_return_status_t +cy_an_usb_set_enum_config_e_x( + cy_an_device_handle handle, + cy_an_usb_enum_control *config_p, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_set_enum_config_e_x(h, config_p, cb, client) \ + cy_as_usb_set_enum_config_dep((cy_as_device_handle)(h), \ + (cy_as_usb_enum_control_dep *)(config_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of get enum config */ +EXTERN cy_an_return_status_t +cy_an_usb_get_enum_config( + cy_an_device_handle handle, + cy_an_usb_enum_control *config_p + ) ; +#define cy_an_usb_get_enum_config(handle, config_p) \ + cy_as_usb_get_enum_config_dep((cy_as_device_handle)(handle), \ + (cy_as_usb_enum_control_dep *)(config_p), 0, 0) + +/* Async version of get enum config */ +extern cy_an_return_status_t +cy_an_usb_get_enum_config_e_x( + cy_an_device_handle handle, + cy_an_usb_enum_control *config_p, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_get_enum_config_e_x(h, config_p, cb, client) \ + cy_as_usb_get_enum_config_dep((cy_as_device_handle)(h), \ + (cy_as_usb_enum_control_dep *)(config_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync Version of Set descriptor */ +EXTERN cy_an_return_status_t +cy_an_usb_set_descriptor( + cy_an_device_handle handle, + cy_an_usb_desc_type type, + uint8_t index, + void *desc_p, + uint16_t length + ) ; +#define cy_an_usb_set_descriptor(handle, type, index, desc_p, length) \ + cy_as_usb_set_descriptor((cy_as_device_handle)(handle), \ + (cy_as_usb_desc_type)(type), (index), (desc_p), (length), 0, 0) + +/* Async Version of Set descriptor */ +extern cy_an_return_status_t +cy_an_usb_set_descriptor_e_x( + cy_an_device_handle handle, + cy_an_usb_desc_type type, + uint8_t index, + void *desc_p, + uint16_t length, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_set_descriptor_e_x\ + (h, type, index, desc_p, length, cb, client) \ + cy_as_usb_set_descriptor((cy_as_device_handle)(h), \ + (cy_as_usb_desc_type)(type), (index), (desc_p), (length), \ + (cy_as_function_callback)(cb), (client)) + +/* Only version of clear descriptors */ +EXTERN cy_an_return_status_t +cy_an_usb_clear_descriptors( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_clear_descriptors(h, cb, client) \ + cy_as_usb_clear_descriptors((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of get descriptor*/ +EXTERN cy_an_return_status_t +cy_an_usb_get_descriptor( + cy_an_device_handle handle, + cy_an_usb_desc_type type, + uint8_t index, + void *desc_p, + uint32_t *length_p + ) ; +#define cy_an_usb_get_descriptor(h, type, index, desc_p, length_p) \ + cy_as_usb_get_descriptor_dep((cy_as_device_handle)(h), \ + (cy_as_usb_desc_type)(type), (index), (desc_p), (length_p)) + +typedef cy_as_get_descriptor_data cy_an_get_descriptor_data ; + +/* Async version of get descriptor */ +extern cy_an_return_status_t +cy_an_usb_get_descriptor_e_x( + cy_an_device_handle handle, + cy_an_usb_desc_type type, + uint8_t index, + cy_an_get_descriptor_data *data, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_get_descriptor_e_x\ + (h, type, index, data, cb, client) \ + cy_as_usb_get_descriptor((cy_as_device_handle)(h), \ + (cy_as_usb_desc_type)(type), (index), \ + (cy_as_get_descriptor_data *)(data), \ + (cy_as_function_callback)(cb), (client)) + +EXTERN cy_an_return_status_t +cy_an_usb_set_physical_configuration( + cy_an_device_handle handle, + uint8_t config + ) ; +#define cy_an_usb_set_physical_configuration(h, config) \ + cy_as_usb_set_physical_configuration\ + ((cy_as_device_handle)(h), (config)) + +EXTERN cy_an_return_status_t +cy_an_usb_set_end_point_config( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_end_point_config *config_p + ) ; +#define cy_an_usb_set_end_point_config(h, ep, config_p) \ + cy_as_usb_set_end_point_config((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_end_point_config *)(config_p)) + +EXTERN cy_an_return_status_t +cy_an_usb_get_end_point_config( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_end_point_config *config_p + ) ; +#define cy_an_usb_get_end_point_config(h, ep, config_p) \ + cy_as_usb_get_end_point_config((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_end_point_config *)(config_p)) + +/* Sync version of commit */ +EXTERN cy_an_return_status_t +cy_an_usb_commit_config( + cy_an_device_handle handle + ) ; +#define cy_an_usb_commit_config(handle) \ + cy_as_usb_commit_config((cy_as_device_handle)(handle), 0, 0) + +/* Async version of commit */ +extern cy_an_return_status_t +cy_an_usb_commit_config_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_commit_config_e_x(h, cb, client) \ + cy_as_usb_commit_config((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +EXTERN cy_an_return_status_t +cy_an_usb_read_data( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool pktread, + uint32_t dsize, + uint32_t *dataread, + void *data + ) ; +#define cy_an_usb_read_data(h, ep, pkt, dsize, dataread, data_p) \ + cy_as_usb_read_data((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (pkt), (dsize), \ + (dataread), (data_p)) + +EXTERN cy_an_return_status_t +cy_an_usb_read_data_async( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool pktread, + uint32_t dsize, + void *data, + cy_an_usb_io_callback callback + ) ; +#define cy_an_usb_read_data_async(h, ep, pkt, dsize, data_p, cb) \ + cy_as_usb_read_data_async((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (pkt), (dsize), (data_p), \ + (cy_as_usb_io_callback)(cb)) + +EXTERN cy_an_return_status_t +cy_an_usb_write_data( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + uint32_t dsize, + void *data + ) ; +#define cy_an_usb_write_data(h, ep, dsize, data_p) \ + cy_as_usb_write_data((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (dsize), (data_p)) + +EXTERN cy_an_return_status_t +cy_an_usb_write_data_async( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + uint32_t dsize, + void *data, + cy_bool spacket, + cy_an_usb_io_callback callback + ) ; +#define cy_an_usb_write_data_async(h, ep, dsize, data_p, spacket, cb) \ + cy_as_usb_write_data_async((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (dsize), (data_p), (spacket), \ + (cy_as_usb_io_callback)(cb)) + +EXTERN cy_an_return_status_t +cy_an_usb_cancel_async( + cy_an_device_handle handle, + cy_an_end_point_number_t ep + ) ; +#define cy_an_usb_cancel_async(h, ep) \ + cy_as_usb_cancel_async((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep)) + +/* Sync version of set stall */ +EXTERN cy_an_return_status_t +cy_an_usb_set_stall( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_function_callback cb, + uint32_t client +) ; +#define cy_an_usb_set_stall(h, ep, cb, client) \ + cy_as_usb_set_stall_dep((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_function_callback)(cb), (client)) + +/* Async version of set stall */ +extern cy_an_return_status_t +cy_an_usb_set_stall_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_function_callback cb, + uint32_t client +) ; +#define cy_an_usb_set_stall_e_x(h, ep, cb, client) \ + cy_as_usb_set_stall((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_function_callback)(cb), (client)) + +/*Sync version of clear stall */ +EXTERN cy_an_return_status_t +cy_an_usb_clear_stall( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_clear_stall(h, ep, cb, client) \ + cy_as_usb_clear_stall_dep((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_function_callback)(cb), (client)) + +/*Sync version of clear stall */ +extern cy_an_return_status_t +cy_an_usb_clear_stall_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_clear_stall_e_x(h, ep, cb, client) \ + cy_as_usb_clear_stall((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync get stall */ +EXTERN cy_an_return_status_t +cy_an_usb_get_stall( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool *stall_p + ) ; +#define cy_an_usb_get_stall(handle, ep, stall_p) \ + cy_as_usb_get_stall((cy_as_device_handle)(handle), \ + (cy_as_end_point_number_t)(ep), (stall_p), 0, 0) + +/* Async get stall */ +extern cy_an_return_status_t +cy_an_usb_get_stall_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool *stall_p, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_get_stall_e_x(h, ep, stall_p, cb, client) \ + cy_as_usb_get_stall((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (stall_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of Set Nak */ +EXTERN cy_an_return_status_t +cy_an_usb_set_nak( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_function_callback cb, + uint32_t client +) ; + +#define cy_an_usb_set_nak(h, ep, cb, client) \ + cy_as_usb_set_nak_dep((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_function_callback)(cb), (client)) + +/* Async version of Set Nak */ +extern cy_an_return_status_t +cy_an_usb_set_nak_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_function_callback cb, + uint32_t client +) ; +#define cy_an_usb_set_nak_e_x(h, ep, cb, client) \ + cy_as_usb_set_nak((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync version of clear nak */ +EXTERN cy_an_return_status_t +cy_an_usb_clear_nak( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_usb_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_clear_nak(h, ep, cb, client) \ + cy_as_usb_clear_nak_dep((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_usb_function_callback)(cb), (client)) + +/* Sync version of clear nak */ +extern cy_an_return_status_t +cy_an_usb_clear_nak_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_clear_nak_e_x(h, ep, cb, client) \ + cy_as_usb_clear_nak((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync Get NAK */ +EXTERN cy_an_return_status_t +cy_an_usb_get_nak( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool *nak_p +) ; +#define cy_an_usb_get_nak(handle, ep, nak_p) \ + cy_as_usb_get_nak((cy_as_device_handle)(handle), \ + (cy_as_end_point_number_t)(ep), (nak_p), 0, 0) + +/* Async Get NAK */ +EXTERN cy_an_return_status_t +cy_an_usb_get_nak_e_x( + cy_an_device_handle handle, + cy_an_end_point_number_t ep, + cy_bool *nak_p, + cy_an_function_callback cb, + uint32_t client +) ; +#define cy_an_usb_get_nak_e_x(h, ep, nak_p, cb, client) \ + cy_as_usb_get_nak((cy_as_device_handle)(h), \ + (cy_as_end_point_number_t)(ep), (nak_p), \ + (cy_as_function_callback)(cb), (client)) + +/* Sync remote wakup */ +EXTERN cy_an_return_status_t +cy_an_usb_signal_remote_wakeup( + cy_an_device_handle handle + ) ; +#define cy_an_usb_signal_remote_wakeup(handle) \ + cy_as_usb_signal_remote_wakeup((cy_as_device_handle)(handle), 0, 0) + +/* Async remote wakup */ +EXTERN cy_an_return_status_t +cy_an_usb_signal_remote_wakeup_e_x( + cy_an_device_handle handle, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_signal_remote_wakeup_e_x(h, cb, client) \ + cy_as_usb_signal_remote_wakeup((cy_as_device_handle)(h), \ + (cy_as_function_callback)(cb), (client)) + +/* Only version of SetMSReportThreshold */ +EXTERN cy_an_return_status_t +cy_an_usb_set_m_s_report_threshold( + cy_an_device_handle handle, + uint32_t wr_sectors, + uint32_t rd_sectors, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_set_m_s_report_threshold\ + (h, wr_cnt, rd_cnt, cb, client) \ + cy_as_usb_set_m_s_report_threshold((cy_as_device_handle)(h), \ + wr_cnt, rd_cnt, (cy_as_function_callback)(cb), (client)) + +/* Select storage partitions to be enumerated. */ +EXTERN cy_an_return_status_t +cy_an_usb_select_m_s_partitions( + cy_an_device_handle handle, + cy_an_media_type media, + uint32_t device, + cy_an_usb_m_s_type_t type, + cy_an_function_callback cb, + uint32_t client + ) ; +#define cy_an_usb_select_m_s_partitions(h, media, dev, type, cb, client) \ + cy_as_usb_select_m_s_partitions_dep((cy_as_device_handle)(h), \ + (cy_as_media_type)(media), (dev), \ + (cy_as_usb_m_s_type_t)(type), (cy_as_function_callback)(cb), (client)) + +#include "cyas_cplus_end.h" +#endif /*__doxygen__*/ +#endif /*_INCLUDED_CYANUSB_H_*/ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h new file mode 100644 index 000000000000..ece44ca34f3b --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_end.h @@ -0,0 +1,11 @@ +/* + * This file is included at the end of other include files. + * It basically turns off the C++ specific code words that + * insure this code is seen as C code even within + * a C++ compiler. + * + */ + +#ifdef __cplusplus +} +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h new file mode 100644 index 000000000000..b879cefa9d6b --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyas_cplus_start.h @@ -0,0 +1,11 @@ +/* + * This file is included after all other headers files, but before any other + * definitions in the file. It basically insures that the definitions within + * the file are seen as C defintions even when compiled by a C++ compiler. + */ + +#ifdef __cplusplus + +extern "C" { + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h new file mode 100644 index 000000000000..5f8c852fbb41 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyascast.h @@ -0,0 +1,35 @@ +/* Cypress West Bridge API header file (cyascast.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASCAST_H_ +#define _INCLUDED_CYASCAST_H_ + +#ifndef __doxygen__ + +#ifdef _DEBUG +#define cy_cast_int2U_int16(v) \ + (cy_as_hal_assert(v < 65536), (uint16_t)(v)) +#else /* _DEBUG */ +#define cy_cast_int2U_int16(v) ((uint16_t)(v)) +#endif /* _DEBUG */ + +#endif /* __doxygen__ */ +#endif /* _INCLUDED_CYASCAST_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h new file mode 100644 index 000000000000..b17c985ed0ae --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdevice.h @@ -0,0 +1,1057 @@ +/* Cypress West Bridge API header file (cyasdevice.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +##Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef __INCLUDED_CYASDEVICE_H__ +#define __INCLUDED_CYASDEVICE_H__ + +#include "cyashal.h" +#include "cyasprotocol.h" +#include "cyasusb.h" +#include "cyasstorage.h" +#include "cyasmtp.h" +#include "cyas_cplus_start.h" + +/*********************************** + * West Bridge Constants + ***********************************/ + +/* The endpoints used by West Bridge for the P port to S port path */ +#define CY_AS_P2S_WRITE_ENDPOINT (0x04) +#define CY_AS_P2S_READ_ENDPOINT (0x08) + +/* The endpoint to use for firmware download */ +#define CY_AS_FIRMWARE_ENDPOINT (0x02) + +/* The maximum size of the firmware image West Bridge can accept */ +#define CY_AS_MAXIMUM_FIRMWARE_SIZE (24 * 1024) + +/* The maximum size of a write for EP0 and EP1 */ +#define CY_AS_EP0_MAX_WRITE_SIZE (128) +#define CY_AS_EP1_MAX_WRITE_SIZE (64) + +/* The bitfields for the device state value */ + +/* The device is in StandBy mode */ +#define CY_AS_DEVICE_STATE_PIN_STANDBY (0x00000001) +/* The device has been configured */ +#define CY_AS_DEVICE_STATE_CONFIGURED (0x00000002) +/* The firmware has been loaded into the device */ +#define CY_AS_DEVICE_STATE_FIRMWARE_LOADED (0x00000004) +/* The interrupt module has been initialized */ +#define CY_AS_DEVICE_STATE_LOWLEVEL_MODULE (0x00000008) +/* The DMA module has been initialized */ +#define CY_AS_DEVICE_STATE_DMA_MODULE (0x00000010) +/* The interrupt module has been initialized */ +#define CY_AS_DEVICE_STATE_INTR_MODULE (0x00000020) +/* The storage module has been initialized */ +#define CY_AS_DEVICE_STATE_STORAGE_MODULE (0x00000040) +/* The USB module has been initialized */ +#define CY_AS_DEVICE_STATE_USB_MODULE (0x00000080) +/* If set, the API wants SCSI messages */ +#define CY_AS_DEVICE_STATE_STORAGE_SCSIMSG (0x00000100) +/* If set, an ASYNC storage operation is pending */ +#define CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING (0x00000200) +/* If set, the USB port is connected */ +#define CY_AS_DEVICE_STATE_USB_CONNECTED (0x00000400) +/* If set and USB is connected, it is high speed */ +#define CY_AS_DEVICE_STATE_USB_HIGHSPEED (0x00000800) +/* If set, we are in a callback */ +#define CY_AS_DEVICE_STATE_IN_CALLBACK (0x00001000) +/* If set, we are processing a setup packet */ +#define CY_AS_DEVICE_STATE_IN_SETUP_PACKET (0x00004000) +/* The device was placed in standby via register */ +#define CY_AS_DEVICE_STATE_REGISTER_STANDBY (0x00008000) +/* If set, the device is using a crystal */ +#define CY_AS_DEVICE_STATE_CRYSTAL (0x00010000) +/* If set, wakeup has been called */ +#define CY_AS_DEVICE_STATE_WAKING (0x00020000) +/* If set, EP0 has been stalled. */ +#define CY_AS_DEVICE_STATE_EP0_STALLED (0x00040000) +/* If set, device is in suspend mode. */ +#define CY_AS_DEVICE_STATE_SUSPEND (0x00080000) +/* If set, device is a reset is pending. */ +#define CY_AS_DEVICE_STATE_RESETP (0x00100000) +/* If set, device is a standby is pending. */ +#define CY_AS_DEVICE_STATE_STANDP (0x00200000) +/* If set, device has a storage start or stop pending. */ +#define CY_AS_DEVICE_STATE_SSSP (0x00400000) +/* If set, device has a usb start or stop pending. */ +#define CY_AS_DEVICE_STATE_USSP (0x00800000) +/* If set, device has a mtp start or stop pending. */ +#define CY_AS_DEVICE_STATE_MSSP (0x01000000) +/* If set, P2S DMA transfer can be started. */ +#define CY_AS_DEVICE_STATE_P2SDMA_START (0x02000000) + +/* The bitfields for the endpoint state value */ +/* DMA requests are accepted into the queue */ +#define CY_AS_DMA_ENDPOINT_STATE_ENABLED (0x0001) +/* The endpoint has a sleeping client, waiting on a queue drain */ +#define CY_AS_DMA_ENDPOINT_STATE_SLEEPING (0x0002) +/* The DMA backend to hardware is running */ +#define CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING (0x0004) +/* There is an outstanding DMA entry deployed to the HAL */ +#define CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT (0x0008) +/* 0 = OUT (West Bridge -> P Port), 1 = IN (P Port -> West Bridge) */ +#define CY_AS_DMA_ENDPOINT_STATE_DIRECTION (0x0010) + +/* The state values for the request list */ +/* Mask for getting the state information */ +#define CY_AS_REQUEST_LIST_STATE_MASK (0x0f) +/* The request is queued, nothing further */ +#define CY_AS_REQUEST_LIST_STATE_QUEUED (0x00) +/* The request is sent, waiting for response */ +#define CY_AS_REQUEST_LIST_STATE_WAITING (0x01) +/* The response has been received, processing reponse */ +#define CY_AS_REQUEST_LIST_STATE_RECEIVED (0x02) +/* The request/response is being canceled */ +#define CY_AS_REQUEST_LIST_STATE_CANCELING (0x03) +/* The request is synchronous */ +#define CY_AS_REQUEST_LIST_STATE_SYNC (0x80) + +/* The flag values for a LL RequestResponse */ +/* This request requires an ACK to be sent after it is completed */ +#define CY_AS_REQUEST_RESPONSE_DELAY_ACK (0x01) +/* This request originated from a version V1.1 function call */ +#define CY_AS_REQUEST_RESPONSE_EX (0x02) +/* This request originated from a version V1.2 function call */ +#define CY_AS_REQUEST_RESPONSE_MS (0x04) + + +#define CY_AS_DEVICE_HANDLE_SIGNATURE (0x01211219) + +/* + * This macro returns the endpoint pointer given the + * device pointer and an endpoint number + */ +#define CY_AS_NUM_EP(dev_p, num) ((dev_p)->endp[(num)]) + +/**************************************** + * West Bridge Data Structures + ****************************************/ + +typedef struct cy_as_device cy_as_device ; + +/* Summary + This type defines a callback function that will be called + on completion of a DMA operation. + + Description + This function definition is for a function that is called when + the DMA operation is complete. This function is called with the + endpoint number, operation type, buffer pointer and size. + + See Also + * CyAsDmaOper + * CyAsDmaQueueWrite + */ +typedef void (*cy_as_dma_callback)( + /* The device that completed DMA */ + cy_as_device *dev_p, + /* The endpoint that completed DMA */ + cy_as_end_point_number_t ep, + /* The pointer to the buffer that completed DMA */ + void *mem_p, + /* The amount of data transferred */ + uint32_t size, + /* The error code for this DMA xfer */ + cy_as_return_status_t error + ) ; + +/* Summary + This structure defines a DMA request that is queued + + Description + This structure contains the information about a DMA + request that is queued and is to be sent when possible. +*/ +typedef struct cy_as_dma_queue_entry { + /* Pointer to memory buffer for this request */ + void *buf_p ; + /* Size of the memory buffer for DMA operation */ + uint32_t size ; + /* Offset into memory buffer for next DMA operation */ + uint32_t offset ; + /* If TRUE and IN request */ + cy_bool packet ; + /* If TRUE, this is a read request */ + cy_bool readreq ; + /* Callback function for when DMA is complete */ + cy_as_dma_callback cb ; + /* Pointer to next entry in queue */ + struct cy_as_dma_queue_entry *next_p ; +} cy_as_dma_queue_entry ; + +/* Summary + This structure defines the endpoint data for a given + + Description + This structure defines all of the information required + to manage DMA for a given endpoint. +*/ +typedef struct cy_as_dma_end_point { + /* The endpoint number */ + cy_as_end_point_number_t ep ; + /* The state of this endpoint */ + uint8_t state ; + /* The maximum amount of data accepted in a packet by the hw */ + uint16_t maxhwdata ; + /* The maximum amount of data accepted by the HAL layer */ + uint32_t maxhaldata ; + /* The queue for DMA operations */ + cy_as_dma_queue_entry *queue_p ; + /* The last entry in the DMA queue */ + cy_as_dma_queue_entry *last_p ; + /* This sleep channel is used to wait while the DMA queue + * drains for a given endpoint */ + cy_as_hal_sleep_channel channel ; +} cy_as_dma_end_point ; + +#define cy_as_end_point_number_is_usb(n) \ + ((n) != 2 && (n) != 4 && (n) != 6 && (n) != 8) +#define cy_as_end_point_number_is_storage(n) \ + ((n) == 2 || (n) == 4 || (n) == 6 || (n) == 8) + +#define cy_as_dma_end_point_is_enabled(ep) \ + ((ep)->state & CY_AS_DMA_ENDPOINT_STATE_ENABLED) +#define cy_as_dma_end_point_enable(ep) \ + ((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_ENABLED) +#define cy_as_dma_end_point_disable(ep) \ + ((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_ENABLED) + +#define cy_as_dma_end_point_is_sleeping(ep) \ + ((ep)->state & CY_AS_DMA_ENDPOINT_STATE_SLEEPING) +#define cy_as_dma_end_point_set_sleep_state(ep) \ + ((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_SLEEPING) +#define cy_as_dma_end_point_set_wake_state(ep) \ + ((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_SLEEPING) + +#define cy_as_dma_end_point_is_running(ep) \ + ((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING) +#define cy_as_dma_end_point_set_running(ep) \ + ((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING) +#define cy_as_dma_end_point_set_stopped(ep) \ + ((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_DMA_RUNNING) + +#define cy_as_dma_end_point_in_transit(ep) \ + ((ep)->state & CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT) +#define cy_as_dma_end_point_set_in_transit(ep) \ + ((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT) +#define cy_as_dma_end_point_clear_in_transit(ep) \ + ((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_IN_TRANSIT) + +#define cy_as_dma_end_point_is_direction_in(ep) \ + (((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DIRECTION) == \ + CY_AS_DMA_ENDPOINT_STATE_DIRECTION) +#define cy_as_dma_end_point_is_direction_out(ep) \ + (((ep)->state & CY_AS_DMA_ENDPOINT_STATE_DIRECTION) == 0) +#define cy_as_dma_end_point_set_direction_in(ep) \ + ((ep)->state |= CY_AS_DMA_ENDPOINT_STATE_DIRECTION) +#define cy_as_dma_end_point_set_direction_out(ep) \ + ((ep)->state &= ~CY_AS_DMA_ENDPOINT_STATE_DIRECTION) + +#define cy_as_dma_end_point_is_usb(p) \ + cy_as_end_point_number_is_usb((p)->ep) +#define cy_as_dma_end_point_is_storage(p) \ + cy_as_end_point_number_is_storage((p)->ep) + +typedef struct cy_as_ll_request_response { + /* The mbox[0] contents - see low level comm section of API doc */ + uint16_t box0 ; + /* The amount of data stored in this request/response in bytes */ + uint16_t stored ; + /* Length of this request in words */ + uint16_t length ; + /* Additional status information about the request */ + uint16_t flags ; + /* Note: This is over indexed and contains the request/response data */ + uint16_t data[1] ; +} cy_as_ll_request_response ; + +/* + * The callback function for responses + */ +typedef void (*cy_as_response_callback)( + /* The device that had the response */ + cy_as_device *dev_p, + /* The context receiving a response */ + uint8_t context, + /* The request data */ + cy_as_ll_request_response *rqt, + /* The response data */ + cy_as_ll_request_response *resp, + /* The status of the request */ + cy_as_return_status_t status + ) ; + +typedef struct cy_as_ll_request_list_node { + /* The request to send */ + cy_as_ll_request_response *rqt ; + /* The associated response for the request */ + cy_as_ll_request_response *resp ; + /* Length of the response */ + uint16_t length ; + /* The callback to call when done */ + cy_as_response_callback callback ; + /* The state of the request */ + uint8_t state ; + /* The next request in the list */ + struct cy_as_ll_request_list_node *next ; +} cy_as_ll_request_list_node ; + +#define cy_as_request_get_node_state(node_p) \ + ((node_p)->state & CY_AS_REQUEST_LIST_STATE_MASK) +#define cy_as_request_set_node_state(node_p, st) \ + ((node_p)->state = \ + ((node_p)->state & ~CY_AS_REQUEST_LIST_STATE_MASK) | (st)) + +#define cy_as_request_node_is_sync(node_p) \ + ((node_p)->state & CY_AS_REQUEST_LIST_STATE_SYNC) +#define cy_as_request_node_set_sync(node_p) \ + ((node_p)->state |= CY_AS_REQUEST_LIST_STATE_SYNC) +#define cy_as_request_node_clear_sync(node_p) \ + ((node_p)->state &= ~CY_AS_REQUEST_LIST_STATE_SYNC) + +#ifndef __doxygen__ +typedef enum cy_as_c_b_node_type { + CYAS_INVALID, + CYAS_USB_FUNC_CB, + CYAS_USB_IO_CB, + CYAS_STORAGE_IO_CB, + CYAS_FUNC_CB +} cy_as_c_b_node_type ; + +typedef struct cy_as_func_c_b_node { + cy_as_c_b_node_type node_type ; + cy_as_function_callback cb_p ; + uint32_t client_data ; + cy_as_funct_c_b_type data_type ; + void *data ; + struct cy_as_func_c_b_node *next_p ; +} cy_as_func_c_b_node; + +extern cy_as_func_c_b_node* +cy_as_create_func_c_b_node_data(cy_as_function_callback + cb, uint32_t client, cy_as_funct_c_b_type type, void *data) ; + +extern cy_as_func_c_b_node* +cy_as_create_func_c_b_node(cy_as_function_callback cb, + uint32_t client) ; + +extern void +cy_as_destroy_func_c_b_node(cy_as_func_c_b_node *node) ; + +typedef struct cy_as_mtp_func_c_b_node { + cy_as_c_b_node_type type ; + cy_as_mtp_function_callback cb_p ; + uint32_t client_data; + struct cy_as_mtp_func_c_b_node *next_p ; +} cy_as_mtp_func_c_b_node; + +extern cy_as_mtp_func_c_b_node* +cy_as_create_mtp_func_c_b_node(cy_as_mtp_function_callback cb, + uint32_t client) ; + +extern void +cy_as_destroy_mtp_func_c_b_node(cy_as_mtp_func_c_b_node *node) ; + +typedef struct cy_as_usb_func_c_b_node { + cy_as_c_b_node_type type ; + cy_as_usb_function_callback cb_p ; + uint32_t client_data; + struct cy_as_usb_func_c_b_node *next_p ; +} cy_as_usb_func_c_b_node; + +extern cy_as_usb_func_c_b_node* +cy_as_create_usb_func_c_b_node(cy_as_usb_function_callback cb, + uint32_t client) ; + +extern void +cy_as_destroy_usb_func_c_b_node(cy_as_usb_func_c_b_node *node) ; + +typedef struct cy_as_usb_io_c_b_node { + cy_as_c_b_node_type type ; + cy_as_usb_io_callback cb_p ; + struct cy_as_usb_io_c_b_node *next_p ; +} cy_as_usb_io_c_b_node; + +extern cy_as_usb_io_c_b_node* +cy_as_create_usb_io_c_b_node(cy_as_usb_io_callback cb) ; + +extern void +cy_as_destroy_usb_io_c_b_node(cy_as_usb_io_c_b_node *node) ; + +typedef struct cy_as_storage_io_c_b_node { + cy_as_c_b_node_type type ; + cy_as_storage_callback cb_p ; + /* The media for the currently outstanding async storage request */ + cy_as_media_type media ; + /* The device index for the currently outstanding async storage + * request */ + uint32_t device_index ; + /* The unit index for the currently outstanding async storage + * request */ + uint32_t unit ; + /* The block address for the currently outstanding async storage + * request */ + uint32_t block_addr ; + /* The operation for the currently outstanding async storage + * request */ + cy_as_oper_type oper ; + cy_as_ll_request_response *req_p ; + cy_as_ll_request_response *reply_p ; + struct cy_as_storage_io_c_b_node *next_p ; +} cy_as_storage_io_c_b_node; + +extern cy_as_storage_io_c_b_node* +cy_as_create_storage_io_c_b_node(cy_as_storage_callback cb, + cy_as_media_type media, uint32_t device_index, + uint32_t unit, uint32_t block_addr, cy_as_oper_type oper, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p) ; + +extern void +cy_as_destroy_storage_io_c_b_node(cy_as_storage_io_c_b_node *node) ; + +typedef struct cy_as_c_b_queue { + void *head_p; + void *tail_p; + uint32_t count ; + cy_as_c_b_node_type type ; +} cy_as_c_b_queue ; + +extern cy_as_c_b_queue * +cy_as_create_c_b_queue(cy_as_c_b_node_type type) ; + +extern void +cy_as_destroy_c_b_queue(cy_as_c_b_queue *queue) ; + +/* Allocates a new CyAsCBNode */ +extern void +cy_as_insert_c_b_node(cy_as_c_b_queue *queue_p, void *cbnode) ; + +/* Removes the first CyAsCBNode from the queue and frees it */ +extern void +cy_as_remove_c_b_node(cy_as_c_b_queue *queue_p) ; + +/* Remove the last CyAsCBNode from the queue and frees it */ +extern void +cy_as_remove_c_b_tail_node(cy_as_c_b_queue *queue_p) ; + +/* Removes and frees all pending callbacks */ +extern void +cy_as_clear_c_b_queue(cy_as_c_b_queue *queue_p) ; + +extern cy_as_return_status_t +cy_as_misc_send_request(cy_as_device *dev_p, + cy_as_function_callback cb, + uint32_t client, + cy_as_funct_c_b_type type, + void *data, + cy_as_c_b_queue *queue, + uint16_t req_type, + cy_as_ll_request_response *req_p, + cy_as_ll_request_response *reply_p, + cy_as_response_callback rcb) ; + +extern void +cy_as_misc_cancel_ex_requests(cy_as_device *dev_p) ; + +/* Summary + Free all memory allocated by and zero all + structures initialized by CyAsUsbStart. + */ +extern void +cy_as_usb_cleanup( + cy_as_device *dev_p) ; + +/* Summary + Free all memory allocated and zero all structures initialized + by CyAsStorageStart. + */ +extern void +cy_as_storage_cleanup( + cy_as_device *dev_p) ; +#endif + +/* Summary + This structure defines the data structure to support a + given command context + + Description + All commands send to the West Bridge device via the mailbox + registers are sent via a context.Each context is independent + and there can be a parallel stream of requests and responses on + each context. This structure is used to manage a single context. +*/ +typedef struct cy_as_context { + /* The context number for this context */ + uint8_t number ; + /* This sleep channel is used to sleep while waiting on a + * response from the west bridge device for a request. */ + cy_as_hal_sleep_channel channel ; + /* The buffer for received requests */ + cy_as_ll_request_response *req_p ; + /* The length of the request being received */ + uint16_t request_length ; + /* The callback for the next request received */ + cy_as_response_callback request_callback ; + /* A list of low level requests to go to the firmware */ + cy_as_ll_request_list_node *request_queue_p ; + /* The list node in the request queue */ + cy_as_ll_request_list_node *last_node_p ; + /* Index upto which data is stored. */ + uint16_t queue_index ; + /* Index to the next request in the queue. */ + uint16_t rqt_index ; + /* Queue of data stored */ + uint16_t data_queue[128] ; + +} cy_as_context ; + +#define cy_as_context_is_waiting(ctxt) \ + ((ctxt)->state & CY_AS_CTXT_STATE_WAITING_RESPONSE) +#define cy_as_context_set_waiting(ctxt) \ + ((ctxt)->state |= CY_AS_CTXT_STATE_WAITING_RESPONSE) +#define cy_as_context_clear_waiting(ctxt) \ + ((ctxt)->state &= ~CY_AS_CTXT_STATE_WAITING_RESPONSE) + + + +/* Summary + This data structure stores SDIO function + parameters for a SDIO card + + Description +*/ +typedef struct cy_as_sdio_device { + /* Keeps track of IO functions initialized*/ + uint8_t function_init_map; + uint8_t function_suspended_map; + /* Function 0 (Card Common) properties*/ + cy_as_sdio_card card; + /* Function 1-7 (Mapped to array element 0-6) properties.*/ + cy_as_sdio_func function[7]; + +} cy_as_sdio_device; + +/* Summary +Macros to access the SDIO card properties +*/ + +#define cy_as_sdio_get_function_code(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].function_code) + +#define cy_as_sdio_get_function_ext_code(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].\ + function[i-1].extended_func_code) + +#define cy_as_sdio_get_function_p_s_n(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].card_psn) + +#define cy_as_sdio_get_function_blocksize(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].blocksize) + +#define cy_as_sdio_get_function_max_blocksize(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].maxblocksize) + +#define cy_as_sdio_get_function_csa_support(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].csa_bits) + +#define cy_as_sdio_get_function_wakeup_support(handle, bus, i) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1]. wakeup_support) + +#define cy_as_sdio_set_function_block_size(handle, bus, i, blocksize) \ + (((cy_as_device *)handle)->sdiocard[bus].function[i-1].blocksize = \ + blocksize) + +#define cy_as_sdio_get_card_num_functions(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.num_functions) + +#define cy_as_sdio_get_card_mem_present(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.memory_present) + +#define cy_as_sdio_get_card_manf_id(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.manufacturer__id) + +#define cy_as_sdio_get_card_manf_info(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.manufacturer_info) + +#define cy_as_sdio_get_card_blocksize(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.blocksize) + +#define cy_as_sdio_get_card_max_blocksize(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.maxblocksize) + +#define cy_as_sdio_get_card_sdio_version(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.sdio_version) + +#define cy_as_sdio_get_card_capability(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].card.card_capability) + +#define cy_as_sdio_get_function_init_map(handle, bus) \ + (((cy_as_device *)handle)->sdiocard[bus].function_init_map) + +#define cy_as_sdio_check_function_initialized(handle, bus, i) \ + (((cy_as_sdio_get_function_init_map(handle, bus)) & (0x01<sdiocard[bus].card.blocksize = blocksize) + +#define cy_as_sdio_check_support_bus_suspend(handle, bus) \ + ((cy_as_sdio_get_card_capability(handle, bus) & CY_SDIO_SBS) ? 1 : 0) + +#define cy_as_sdio_check_function_suspended(handle, bus, i) \ + ((((cy_as_device *)handle)->sdiocard[bus].function_suspended_map & \ + (0x01<sdiocard[bus].function_suspended_map) \ + |= (0x01<sdiocard[bus].function_suspended_map) \ + &= (~(0x01<state & CY_AS_DEVICE_STATE_CONFIGURED) +#define cy_as_device_set_configured(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_CONFIGURED) +#define cy_as_device_set_unconfigured(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_CONFIGURED) + +#define cy_as_device_is_dma_running(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_DMA_MODULE) +#define cy_as_device_set_dma_running(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_DMA_MODULE) +#define cy_as_device_set_dma_stopped(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_DMA_MODULE) + +#define cy_as_device_is_low_level_running(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_LOWLEVEL_MODULE) +#define cy_as_device_set_low_level_running(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_LOWLEVEL_MODULE) +#define cy_as_device_set_low_level_stopped(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_LOWLEVEL_MODULE) + +#define cy_as_device_is_intr_running(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_INTR_MODULE) +#define cy_as_device_set_intr_running(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_INTR_MODULE) +#define cy_as_device_set_intr_stopped(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_INTR_MODULE) + +#define cy_as_device_is_firmware_loaded(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_FIRMWARE_LOADED) +#define cy_as_device_set_firmware_loaded(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_FIRMWARE_LOADED) +#define cy_as_device_set_firmware_not_loaded(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_FIRMWARE_LOADED) + +#define cy_as_device_is_storage_running(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_STORAGE_MODULE) +#define cy_as_device_set_storage_running(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_MODULE) +#define cy_as_device_set_storage_stopped(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_MODULE) + +#define cy_as_device_is_usb_running(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_USB_MODULE) +#define cy_as_device_set_usb_running(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_USB_MODULE) +#define cy_as_device_set_usb_stopped(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_USB_MODULE) + +#define cy_as_device_wants_scsi_messages(dp) \ + (((dp)->state & CY_AS_DEVICE_STATE_STORAGE_SCSIMSG) \ + ? cy_true : cy_false) +#define cy_as_device_set_scsi_messages(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_SCSIMSG) +#define cy_as_device_clear_scsi_messages(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_SCSIMSG) + +#define cy_as_device_is_storage_async_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING) +#define cy_as_device_set_storage_async_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING) +#define cy_as_device_clear_storage_async_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_STORAGE_ASYNC_PENDING) + +#define cy_as_device_is_usb_connected(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_USB_CONNECTED) +#define cy_as_device_set_usb_connected(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_USB_CONNECTED) +#define cy_as_device_clear_usb_connected(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_USB_CONNECTED) + +#define cy_as_device_is_usb_high_speed(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_USB_HIGHSPEED) +#define cy_as_device_set_usb_high_speed(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_USB_HIGHSPEED) +#define cy_as_device_clear_usb_high_speed(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_USB_HIGHSPEED) + +#define cy_as_device_is_in_callback(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_IN_CALLBACK) +#define cy_as_device_set_in_callback(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_IN_CALLBACK) +#define cy_as_device_clear_in_callback(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_IN_CALLBACK) + +#define cy_as_device_is_setup_i_o_performed(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED) +#define cy_as_device_set_setup_i_o_performed(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED) +#define cy_as_device_clear_setup_i_o_performed(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_SETUP_IO_PERFORMED) + +#define cy_as_device_is_ack_delayed(dp) \ + ((dp)->usb_delay_ack_count > 0) +#define cy_as_device_set_ack_delayed(dp) \ + ((dp)->usb_delay_ack_count++) +#define cy_as_device_rem_ack_delayed(dp) \ + ((dp)->usb_delay_ack_count--) +#define cy_as_device_clear_ack_delayed(dp) \ + ((dp)->usb_delay_ack_count = 0) + +#define cy_as_device_is_setup_packet(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_IN_SETUP_PACKET) +#define cy_as_device_set_setup_packet(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_IN_SETUP_PACKET) +#define cy_as_device_clear_setup_packet(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_IN_SETUP_PACKET) + +#define cy_as_device_is_ep0_stalled(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_EP0_STALLED) +#define cy_as_device_set_ep0_stalled(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_EP0_STALLED) +#define cy_as_device_clear_ep0_stalled(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_EP0_STALLED) + +#define cy_as_device_is_register_standby(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_REGISTER_STANDBY) +#define cy_as_device_set_register_standby(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_REGISTER_STANDBY) +#define cy_as_device_clear_register_standby(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_REGISTER_STANDBY) + +#define cy_as_device_is_pin_standby(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_PIN_STANDBY) +#define cy_as_device_set_pin_standby(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_PIN_STANDBY) +#define cy_as_device_clear_pin_standby(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_PIN_STANDBY) + +#define cy_as_device_is_crystal(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_CRYSTAL) +#define cy_as_device_is_external_clock(dp) \ + (!((dp)->state & CY_AS_DEVICE_STATE_CRYSTAL)) +#define cy_as_device_set_crystal(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_CRYSTAL) +#define cy_as_device_set_external_clock(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_CRYSTAL) + +#define cy_as_device_is_waking(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_WAKING) +#define cy_as_device_set_waking(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_WAKING) +#define cy_as_device_clear_waking(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_WAKING) + +#define cy_as_device_is_in_suspend_mode(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_SUSPEND) +#define cy_as_device_set_suspend_mode(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_SUSPEND) +#define cy_as_device_clear_suspend_mode(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_SUSPEND) + +#define cy_as_device_is_reset_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_RESETP) +#define cy_as_device_set_reset_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_RESETP) +#define cy_as_device_clear_reset_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_RESETP) + +#define cy_as_device_is_standby_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_STANDP) +#define cy_as_device_set_standby_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_STANDP) +#define cy_as_device_clear_standby_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_STANDP) + +#define cy_as_device_is_s_s_s_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_SSSP) +#define cy_as_device_set_s_s_s_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_SSSP) +#define cy_as_device_clear_s_s_s_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_SSSP) + +#define cy_as_device_is_u_s_s_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_USSP) +#define cy_as_device_set_u_s_s_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_USSP) +#define cy_as_device_clear_u_s_s_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_USSP) + +#define cy_as_device_is_m_s_s_pending(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_MSSP) +#define cy_as_device_set_m_s_s_pending(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_MSSP) +#define cy_as_device_clear_m_s_s_pending(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_MSSP) + +#define cy_as_device_is_p2s_dma_start_recvd(dp) \ + ((dp)->state & CY_AS_DEVICE_STATE_P2SDMA_START) +#define cy_as_device_set_p2s_dma_start_recvd(dp) \ + ((dp)->state |= CY_AS_DEVICE_STATE_P2SDMA_START) +#define cy_as_device_clear_p2s_dma_start_recvd(dp) \ + ((dp)->state &= ~CY_AS_DEVICE_STATE_P2SDMA_START) + +#define cy_as_device_is_usb_async_pending(dp, ep) \ + ((dp)->epasync & (1 << ep)) +#define cy_as_device_set_usb_async_pending(dp, ep) \ + ((dp)->epasync |= (1 << ep)) +#define cy_as_device_clear_usb_async_pending(dp, ep) \ + ((dp)->epasync &= ~(1 << ep)) + +#define cy_as_device_is_nand_storage_supported(dp) \ + ((dp)->media_supported[0] & 1) + +/* Macros to check the type of West Bridge device. */ +#define cy_as_device_is_astoria_dev(dp) \ + (((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE) || \ + ((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE)) +#define cy_as_device_is_antioch_dev(dp) \ + ((dp)->silicon_id == CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE) + +#ifdef CY_AS_LOG_SUPPORT +extern void cy_as_log_debug_message(int value, const char *msg) ; +#else +#define cy_as_log_debug_message(value, msg) +#endif + +/* Summary + This function finds the device object given the HAL tag + + Description + The user associats a device TAG with each West Bridge device + created. This tag is passed from the API functions to and HAL + functions that need to ID a specific West Bridge device. This + tag is also passed in from the user back into the API via + interrupt functions. This function allows the API to find the + device structure associated with a given tag. + + Notes + This function does a simple linear search for the device based + on the TAG. This function is called each time an West Bridge + interrupt handler is called. Therefore this works fine for a + small number of West Bridge devices (e.g. less than five). + Anything more than this and this methodology will need to be + updated. + + Returns + Pointer to a CyAsDevice associated with the tag +*/ +extern cy_as_device * +cy_as_device_find_from_tag( + cy_as_hal_device_tag tag + ) ; + +#include "cyas_cplus_end.h" + +#endif /* __INCLUDED_CYASDEVICE_H__ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h new file mode 100644 index 000000000000..c97f9876fc4c --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h @@ -0,0 +1,375 @@ +/* Cypress West Bridge API header file (cyasdma.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASDMA_H_ +#define _INCLUDED_CYASDMA_H_ + +#include "cyashal.h" +#include "cyasdevice.h" + +#include "cyas_cplus_start.h" + + +/*@@DMA Overview + This module manages the DMA operations to/from the West Bridge + device. The DMA module maintains a DMA queue for each endpoint + so multiple DMA requests may be queued and they will complete + at some future time. + + The DMA module must be started before it can be used. It is + started by calling CyAsDmaStart(). This function intializes + all of the endpoint data structures. + + In order to perform DMA on a particular endpoint, the endpoint + must be enabled by calling CyAsDmaEnableEndPoint(). In addition + to enabling or disabling the endpoint, this function also sets + the direction for a given endpoint. Direction is given in USB + terms. For P port to West Bridge traffic, the endpoint is a + CyAsDirectionIn endpoint. For West Bridge to P port traffic, + the endpoint is a CyAsDirectionOut endpoint. + + Once DMA is started and an endpoint is enabled, DMA requests + are issued by calling CyAsDmaQueueRequest(). This function + queue either a DMA read or DMA write request. The callback + associated with the request is called once the request has been + fulfilled. + + See Also + * CyAsDmaStart + * CyAsDmaEnableEndPoint + * CyAsDmaDirection + * CyAsDmaQueueRequest + */ + +/************************ + * West Bridge Constants + ************************/ +#define CY_AS_DMA_MAX_SIZE_HW_SIZE (0xffffffff) + +/************************ + * West Bridge Data Structures + ************************/ + +/* Summary + This type specifies the direction of an endpoint to the + CyAsDmaEnableEndPoint function. + + Description + When an endpoint is enabled, the direction of the endpoint + can also be set. This type is used to specify the endpoint + type. Note that the direction is specified in USB terms. + Therefore, if the DMA is from the P port to West Bridge, + the direction is IN. + + See Also + * CyAsDmaEnableEndPoint +*/ +typedef enum cy_as_dma_direction { + /* Set the endpoint to type IN (P -> West Bridge) */ + cy_as_direction_in = 0, + /* Set the endpoint to type OUT (West Bridge -> P) */ + cy_as_direction_out = 1, + /* Only valid for EP 0 */ + cy_as_direction_in_out = 2, + /* Do no change the endpoint type */ + cy_as_direction_dont_change = 3 +} cy_as_dma_direction ; + +/********************************* + * West Bridge Functions + *********************************/ + +/* Summary + Initialize the DMA module and ready the module for receiving data + + Description + This function initializes the DMA module by initializing all of + the endpoint data structures associated with the device given. + This function also register a DMA complete callback with the HAL + DMA code. This callback is called whenever the HAL DMA subsystem + completes a requested DMA operation. + + Returns + CY_AS_ERROR_SUCCESS - the module initialized sucessfully + CY_AS_ERROR_OUT_OF_MEMORY - memory allocation failed during + initialization + CY_AS_ERROR_ALREADY_RUNNING - the DMA module was already running + + See Also + * CyAsDmaStop +*/ +extern cy_as_return_status_t +cy_as_dma_start( + /* The device to start */ + cy_as_device *dev_p + ) ; + +/* Summary + Shutdown the DMA module + + Description + This function shuts down the DMA module for this device by + canceling any DMA requests associated with each endpoint and + then freeing the resources associated with each DMA endpoint. + + Returns + CY_AS_ERROR_SUCCESS - the module shutdown sucessfully + CY_AS_ERROR_NOT_RUNNING - the DMA module was not running + + See Also + * CyAsDmaStart + * CyAsDmaCancel +*/ +extern cy_as_return_status_t +cy_as_dma_stop( + /* The device to stop */ + cy_as_device *dev_p + ) ; + +/* Summary + This function cancels all outstanding DMA requests on a given endpoint + + Description + This function cancels any DMA requests outstanding on a given endpoint + by disabling the transfer of DMA requests from the queue to the HAL + layer and then removing any pending DMA requests from the queue. The + callback associated with any DMA requests that are being removed is + called with an error code of CY_AS_ERROR_CANCELED. + + Notes + If a request has already been sent to the HAL layer it will be + completed and not canceled. Only requests that have not been sent to + the HAL layer will be cancelled. + + Returns + CY_AS_ERROR_SUCCESS - the traffic on the endpoint is canceled + sucessfully + + See Also +*/ +extern cy_as_return_status_t +cy_as_dma_cancel( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to cancel */ + cy_as_end_point_number_t ep, + cy_as_return_status_t err + ) ; + +/* Summary + This function enables a single endpoint for DMA operations + + Description + In order to enable the queuing of DMA requests on a given + endpoint, the endpoint must be enabled for DMA. This function + enables a given endpoint. In addition, this function sets the + direction of the DMA operation. + + Returns + * CY_AS_ERROR_INVALID_ENDPOINT - invalid endpoint number + * CY_AS_ERROR_SUCCESS - endpoint was enabled or disabled + * successfully + + See Also + * CyAsDmaQueueRequest +*/ +extern cy_as_return_status_t +cy_as_dma_enable_end_point( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to enable or disable */ + cy_as_end_point_number_t ep, + /* CyTrue to enable, CyFalse to disable */ + cy_bool enable, + /* The direction of the endpoint */ + cy_as_dma_direction dir +) ; + +/* Summary + This function queue a DMA request for a given endpoint + + Description + When an West Bridge API module wishes to do a DMA operation, + this function is called on the associated endpoint to queue + a DMA request. When the DMA request has been fulfilled, the + callback associated with the DMA operation is called. + + Notes + The buffer associated with the DMA request, must remain valid + until after the callback function is calld. + + Returns + * CY_AS_ERROR_SUCCESS - the DMA operation was queued successfully + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint number was invalid + * CY_AS_ERROR_ENDPOINT_DISABLED - the endpoint was disabled + * CY_AS_ERROR_OUT_OF_MEMORY - out of memory processing the request + + See Also + * CyAsDmaEnableEndPoint + * CyAsDmaCancel +*/ +extern cy_as_return_status_t +cy_as_dma_queue_request( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to receive a new request */ + cy_as_end_point_number_t ep, + /* The memory buffer for the DMA request - + * must be valid until after the callback has been called */ + void *mem_p, + /* The size of the DMA request in bytes */ + uint32_t size, + /* If true and a DMA read request, return the next packet + * regardless of size */ + cy_bool packet, + /* If true, this is a read request, + * otherwise it is a write request */ + cy_bool readreq, + /* The callback to call when the DMA request is complete, + * either successfully or via an error */ + cy_as_dma_callback cb + ) ; + +/* Summary + This function waits until all DMA requests on a given endpoint + have been processed and then return + + Description + There are times when a module in the West Bridge API needs to + wait until the DMA operations have been queued. This function + sleeps until all DMA requests have been fulfilled and only then + returns to the caller. + + Notes + I don't think we will need a list of sleeping clients to support + multiple parallel client modules sleeping on a single endpoint, + but if we do instead of having a single sleep channel in the + endpoint, each client will have to supply a sleep channel and we + will have to maintain a list of sleep channels to wake. + + Returns + * CY_AS_ERROR_SUCCESS - the queue has drained sucessfully + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given is not valid + * CY_AS_ERROR_NESTED_SLEEP - CyAsDmaQueueRequest() was requested + * on an endpoint where CyAsDmaQueueRequest was already called +*/ +extern cy_as_return_status_t +cy_as_dma_drain_queue( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to drain */ + cy_as_end_point_number_t ep, + /* If CyTrue, call kickstart to start the DMA process, + if cy_false, west bridge will start the DMA process */ + cy_bool kickstart + ) ; + +/* Summary + Sets the maximum amount of data West Bridge can accept in a single + DMA Operation for the given endpoint + + Description + Depending on the configuration of the West Bridge device endpoint, + the amount of data that can be accepted varies. This function + sets the maximum amount of data West Bridge can accept in a single + DMA operation. The value is stored with the endpoint and passed + to the HAL layer in the CyAsHalDmaSetupWrite() and + CyAsHalDmaSetupRead() functoins. + + Returns + * CY_AS_ERROR_SUCCESS - the value was set sucessfully + * CY_AS_ERROR_INVALID_SIZE - the size value was not valid +*/ +extern cy_as_return_status_t +cy_as_dma_set_max_dma_size( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to change */ + cy_as_end_point_number_t ep, + /* The max size of this endpoint in bytes */ + uint32_t size + ) ; + +/* Summary + This function starts the DMA process on a given channel. + + Description + When transferring data from the P port processor to West + Bridge, the DMA operation must be initiated P Port software + for the first transfer. Subsequent transferrs will be + handled at the interrupt level. + + Returns + * CY_AS_ERROR_SUCCESS +*/ +extern cy_as_return_status_t +cy_as_dma_kick_start( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint to change */ + cy_as_end_point_number_t ep + ) ; + +/* Summary + This function receives endpoint data from a request. + + Description + For endpoint 0 and 1 the endpoint data is transferred from + the West Bridge device to the DMA via a lowlevel + requests (via the mailbox registers). + + Returns + * CY_AS_ERROR_SUCCESS +*/ +extern cy_as_return_status_t +cy_as_dma_received_data( + /* The device of interest */ + cy_as_device *dev_p, + /* The endpoint that received data */ + cy_as_end_point_number_t ep, + /* The data size */ + uint32_t dsize, + /* The data buffer */ + void *data + ); + +/* Summary + This function is called when the DMA operation on + an endpoint has been completed. + + Returns + * void + */ +extern void +cy_as_dma_completed_callback( + /* Tag to HAL completing the DMA operation. */ + cy_as_hal_device_tag tag, + /* Endpoint on which DMA has been completed. */ + cy_as_end_point_number_t ep, + /* Length of data received. */ + uint32_t length, + /* Status of DMA operation. */ + cy_as_return_status_t status + ) ; + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASDMA_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h new file mode 100644 index 000000000000..f78d60270d45 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaserr.h @@ -0,0 +1,1094 @@ +/* Cypress West Bridge API header file (cyaserr.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASERR_H_ +#define _INCLUDED_CYASERR_H_ + +/*@@West Bridge Errors + Summary + This section lists the error codes for West Bridge. + +*/ + +/* Summary + The function completed sucessfully +*/ +#define CY_AS_ERROR_SUCCESS (0) + +/* Summary + A function trying to acquire a resource was unable to do so. + + Description + This code indicates that a resource that the API was trying to claim + could not be claimed. + + See Also + * CyAsMiscAcquireResource + * CyAsStorageClaim +*/ +#define CY_AS_ERROR_NOT_ACQUIRED (1) + +/* Summary + A function trying to acquire a resource was unable to do so. + + Description + The West Bridge API provides the capability to assign the storage media to + either the West Bridge device or the USB port. This error indicates the + P port was trying to release a storage media and was not able to do + so. This generally means it was not owned by the P port processor. + + See Also + * CyAsStorageRelease +*/ +#define CY_AS_ERROR_NOT_RELEASED (2) + +/* Summary + The West Bridge firmware is not loaded. + + Description + Most of the API functions that are part of the West Bridge API rely on + firmware running on the West Bridge device. This error code is + returned when one of these functions is called and the firmware has + not yet been loaded. + + See Also + * CyAsMiscGetFirmwareVersion + * CyAsMiscReset + * CyAsMiscAcquireResource + * CyAsMiscReleaseResource + * CyAsMiscSetTraceLevel + * CyAsStorageStart + * CyAsStorageStop + * CyAsStorageRegisterCallback + * CyAsStorageClaim + * CyAsStorageRelease + * CyAsStorageQueryMedia + * CyAsStorageQueryDevice + * CyAsStorageQueryUnit + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_NO_FIRMWARE (3) + +/* Summary + A timeout occurred waiting on a response from the West Bridge device + + Description + When requests are made of the West Bridge device, a response is expected + within a given timeframe. If a response is not recevied within the + given timeframe, a timeout error occurs. +*/ +#define CY_AS_ERROR_TIMEOUT (4) + +/* Summary + A request to download firmware was made while not in the CONFIG mode + + Description + Firmware is downloaded via the CyAsMiscDownloadFirmware() function. This + function can only be called while in the CONFIG mode. This error indicates + that the CyAsMiscDownloadFirmware() call was made while not in the CONFIG + mode. + + See Also + * CyAsMiscDownloadFirmware +*/ +#define CY_AS_ERROR_NOT_IN_CONFIG_MODE (5) + +/* Summary + This error is returned if the firmware size specified is too invalid. + + Description + If the size of the firmware to be downloaded into West Bridge is + invalid, this error is issued. Invalid firmware sizes are those + greater than 24K or a size of zero. + + See Also + * CyAsMiscDownloadFirmare +*/ +#define CY_AS_ERROR_INVALID_SIZE (6) + +/* Summary + This error is returned if a request is made to acquire a resource that has + already been acquired. + + Description + This error is returned if a request is made to acquire a resource that has + already been acquired. + + See Also + * CyAsMiscAcquireResource + * CyAsMiscReleaseResource +*/ +#define CY_AS_ERROR_RESOURCE_ALREADY_OWNED (7) + +/* Summary + This error is returned if a request is made to release a resource that has + not previously been acquired. + + Description + This error is returned if a request is made to release a resource that has + not previously been acquired. + + See Also + * CyAsMiscAcquireResource + * CyAsMiscReleaseResource +*/ +#define CY_AS_ERROR_RESOURCE_NOT_OWNED (8) + +/* Summary + This error is returned when a request is made for a media that + does not exist + + Description + This error is returned when a request is made that references + a storage media that does not exist. This error is returned + when the storage media is not present in the current system, + or if the media value given is not valid. + + See Also + * CyAsMiscSetTraceLevel + * CyAsStorageClaim + * CyAsStorageRelease + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_NO_SUCH_MEDIA (9) + +/* Summary + This error is returned when a request is made for a device + that does not exist + + Description + This error is returned when a request is made that references a + storage device that does not exist. This error is returned when + the device index is not present in the current system, or if the + device index exceeds 15. + + See Also + * CyAsMiscSetTraceLevel + * CyAsStorageQueryDevice + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_NO_SUCH_DEVICE (10) + +/* Summary + This error is returned when a request is made for a unit that + does not exist + + Description + This error is returned when a request is made that references + a storage unit that does not exist. This error is returned + when the unit index is not present in the current system, or + if the unit index exceeds 255. + + See Also + * CyAsMiscSetTraceLevel + * CyAsStorageQueryDevice + * CyAsStorageQueryUnit + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_NO_SUCH_UNIT (11) + +/* Summary + This error is returned when a request is made for a block that + does not exist + + Description + This error is returned when a request is made that references + a storage block that does not exist. This error is returned + when the block address reference an address beyond the end of + the unit selected. + + See Also + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_INVALID_BLOCK (12) + +/* Summary + This error is returned when an invalid trace level is set. + + Description + This error is returned when the trace level request is greater + than three. + + See Also + * CyAsMiscSetTraceLevel +*/ +#define CY_AS_ERROR_INVALID_TRACE_LEVEL (13) + +/* Summary + This error is returned when West Bridge is already in the standby state + and an attempt is made to put West Bridge into this state again. + + Description + This error is returned when West Bridge is already in the standby state + and an attempt is made to put West Bridge into this state again. + + See Also + * CyAsMiscEnterStandby +*/ +#define CY_AS_ERROR_ALREADY_STANDBY (14) + +/* Summary + This error is returned when the API needs to set a pin on the + West Bridge device, but this is not supported by the underlying HAL + layer. + + Description + This error is returned when the API needs to set a pin on the + West Bridge device, but this is not supported by the underlying HAL + layer. + + See Also + * CyAsMiscEnterStandby + * CyAsMiscLeaveStandby +*/ +#define CY_AS_ERROR_SETTING_WAKEUP_PIN (15) + +/* Summary + This error is returned when a module is being started that has + already been started. + + Description + This error is returned when a module is being started and that module + has already been started. This error does not occur with the + CyAsStorageStart() or CyAsUsbStart() functions as the storage and + USB modules are reference counted. + + Note + At the current time, this error is returned by module internal to + the API but not returned by any of the API functions. +*/ +#define CY_AS_ERROR_ALREADY_RUNNING (16) + +/* Summary + This error is returned when a module is being stopped that has + already been stopped. + + Description + This error is returned when a module is being stopped and that module + has already been stopped. This error does not occur with the + CyAsStorageStop() or CyAsUsbStop() functions as the storage and USB + modules are reference counted. + + Note + At the current time, this error is returned by module internal to + the API but not returned by any of the API functions. +*/ + +#define CY_AS_ERROR_NOT_RUNNING (17) + +/* Summary + This error is returned when the caller tries to claim a media that + has already been claimed. + + Description + This error is returned when the caller tries to claim a media that + has already been claimed. + + See Also + * CyAsStorageClaim +*/ +#define CY_AS_ERROR_MEDIA_ALREADY_CLAIMED (18) + +/* Summary + This error is returned when the caller tries to release a media that has + already been released. + + Description + This error is returned when the caller tries to release a media that has + already been released. + + See Also + * CyAsStorageRelease +*/ +#define CY_AS_ERROR_MEDIA_NOT_CLAIMED (19) + +/* Summary + This error is returned when canceling trying to cancel an asynchronous + operation when an async operation is not pending. + + Description + This error is returned when a call is made to a function to cancel an + asynchronous operation and there is no asynchronous operation pending. + + See Also + * CyAsStorageCancelAsync + * CyAsUsbCancelAsync +*/ +#define CY_AS_ERROR_NO_OPERATION_PENDING (20) + +/* Summary + This error is returned when an invalid endpoint number is provided to + an API call. + + Description + This error is returned when an invalid endpoint number is specified in + an API call. The endpoint number may be invalid because it is greater + than 15, or because it was a reference to an endpoint that is invalid + for West Bridge (2, 4, 6, or 8). + + See Also + * CyAsUsbSetEndPointConfig + * CyAsUsbGetEndPointConfig + * CyAsUsbReadData + * CyAsUsbWriteData + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync + * CyAsUsbSetStall + * CyAsUsbGetStall +*/ +#define CY_AS_ERROR_INVALID_ENDPOINT (21) + +/* Summary + This error is returned when an invalid descriptor type + is specified in an API call. + + Description + This error is returned when an invalid descriptor type + is specified in an API call. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor +*/ +#define CY_AS_ERROR_INVALID_DESCRIPTOR (22) + +/* Summary + This error is returned when an invalid descriptor index + is specified in an API call. + + Description + This error is returned when an invalid descriptor index + is specified in an API call. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor +*/ +#define CY_AS_ERROR_BAD_INDEX (23) + +/* Summary + This error is returned if trying to set a USB descriptor + when in the P port enumeration mode. + + Description + This error is returned if trying to set a USB descriptor + when in the P port enumeration mode. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor +*/ +#define CY_AS_ERROR_BAD_ENUMERATION_MODE (24) + +/* Summary + This error is returned when the endpoint configuration specified + is not valid. + + Description + This error is returned when the endpoint configuration specified + is not valid. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor + * CyAsUsbCommitConfig +*/ +#define CY_AS_ERROR_INVALID_CONFIGURATION (25) + +/* Summary + This error is returned when the API cannot verify it is connected + to an West Bridge device. + + Description + When the API is initialized, the API tries to read the ID register from + the West Bridge device. The value from this ID register should match the + value expected before communications with West Bridge are established. This + error means that the contents of the ID register cannot be verified. + + See Also + * CyAsMiscConfigureDevice +*/ +#define CY_AS_ERROR_NO_ANTIOCH (26) + +/* Summary + This error is returned when an API function is called and + CyAsMiscConfigureDevice has not been called to configure West Bridge + for the current environment. + + Description + This error is returned when an API function is called and + CyAsMiscConfigureDevice has not been called to configure West Bridge for + the current environment. + + See Also + * Almost all API function +*/ +#define CY_AS_ERROR_NOT_CONFIGURED (27) + +/* Summary + This error is returned when West Bridge cannot allocate memory required for + internal API operations. + + Description + This error is returned when West Bridge cannot allocate memory required for + internal API operations. + + See Also + * Almost all API functoins +*/ +#define CY_AS_ERROR_OUT_OF_MEMORY (28) + +/* Summary + This error is returned when a module is being started that has + already been started. + + Description + This error is returned when a module is being started and that module + has already been started. This error does not occur with the + CyAsStorageStart() or CyAsUsbStart() functions as the storage and + USB modules are reference counted. + + Note + At the current time, this error is returned by module internal to the API but + not returned by any of the API functions. +*/ +#define CY_AS_ERROR_NESTED_SLEEP (29) + +/* Summary + This error is returned when an operation is attempted on an endpoint that has + been disabled. + + Description + This error is returned when an operation is attempted on an endpoint that has + been disabled. + + See Also + * CyAsUsbReadData + * CyAsUsbWriteData + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync +*/ +#define CY_AS_ERROR_ENDPOINT_DISABLED (30) + +/* Summary + This error is returned when a call is made to an API function when + the device is in standby. + + Description + When the West Bridge device is in standby, the only two API functions that + can be called are CyAsMiscInStandby() and CyAsMiscLeaveStandby(). + Calling any other API function will result in this error. + + See Also +*/ +#define CY_AS_ERROR_IN_STANDBY (31) + +/* Summary + This error is returned when an API call is made with an invalid handle value. + + Description + This error is returned when an API call is made with an invalid handle value. + + See Also +*/ +#define CY_AS_ERROR_INVALID_HANDLE (32) + +/* Summary + This error is returned when an invalid response is returned from + the West Bridge device. + + Description + Many of the API calls result in requests made to the West Bridge + device. This error occurs when the response from West Bridge is + invalid and generally indicates that the West Bridge device + should be reset. + + See Also +*/ +#define CY_AS_ERROR_INVALID_RESPONSE (33) + +/* Summary + This error is returned from the callback function for any asynchronous + read or write request that is canceled. + + Description + When asynchronous requests are canceled, this error is passed to the + callback function associated with the request to indicate that the + request has been canceled + + See Also + * CyAsStorageReadAsync + * CyAsStorageWriteAsync + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync + * CyAsStorageCancelAsync + * CyAsUsbCancelAsync +*/ +#define CY_AS_ERROR_CANCELED (34) + +/* Summary + This error is returned when the call to create sleep channel fails + in the HAL layer. + + Description + This error is returned when the call to create sleep channel fails + in the HAL layer. + + See Also + * CyAsMiscConfigureDevice +*/ +#define CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED (35) + +/* Summary + This error is returned when the call to CyAsMiscLeaveStandby + is made and the device is not in standby. + + Description + This error is returned when the call to CyAsMiscLeaveStandby + is made and the device is not in standby. + + See Also +*/ +#define CY_AS_ERROR_NOT_IN_STANDBY (36) + +/* Summary + This error is returned when the call to destroy sleep channel fails + in the HAL layer. + + Description + This error is returned when the call to destroy sleep channel fails + in the HAL layer. + + See Also + * CyAsMiscDestroyDevice +*/ +#define CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED (37) + +/* Summary + This error is returned when an invalid resource is specified to a call + to CyAsMiscAcquireResource() or CyAsMiscReleaseResource() + + Description + This error is returned when an invalid resource is specified to a call + to CyAsMiscAcquireResource() or CyAsMiscReleaseResource() + + See Also + * CyAsMiscAcquireResource + * CyAsMiscReleaseResource +*/ +#define CY_AS_ERROR_INVALID_RESOURCE (38) + +/* Summary + This error occurs when an operation is requested on an endpoint that has + a currently pending async operation. + + Description + There can only be a single asynchronous pending operation on a given + endpoint and while the operation is pending on other operation can occur + on the endpoint. In addition, the device cannot enter standby while + any asynchronous operations are pending. + + See Also + * CyAsStorageReadAsync + * CyAsStorageWriteAsync + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync + * CyAsStorageRead + * CyAsStorageWrite + * CyAsUsbReadData + * CyAsUsbWriteData + * CyAsMiscEnterStandby +*/ +#define CY_AS_ERROR_ASYNC_PENDING (39) + +/* Summary + This error is returned when a call to CyAsStorageCancelAsync() or + CyAsUsbCancelAsync() is made when no asynchronous request is pending. + + Description + This error is returned when a call to CyAsStorageCancelAsync() or + CyAsUsbCancelAsync() is made when no asynchronous request is pending. + + See Also + * CyAsStorageCancelAsync + * CyAsUsbCancelAsync +*/ +#define CY_AS_ERROR_ASYNC_NOT_PENDING (40) + +/* Summary + This error is returned when a request is made to put the West Bridge device + into standby mode while the USB stack is still active. + + Description + This error is returned when a request is made to put the West Bridge device + into standby mode while the USB stack is still active. You must call the + function CyAsUsbStop() in order to shut down the USB stack in order to go + into the standby mode. + + See Also + * CyAsMiscEnterStandby +*/ +#define CY_AS_ERROR_USB_RUNNING (41) + +/* Summary + A request for in the wrong direction was issued on an endpoint. + + Description + This error is returned when a write is attempted on an OUT endpoint or + a read is attempted on an IN endpoint. + + See Also + * CyAsUsbReadData + * CyAsUsbWriteData + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync +*/ +#define CY_AS_ERROR_USB_BAD_DIRECTION (42) + +/* Summary + An invalid request was received + + Description + This error is isused if an invalid request is issued. +*/ +#define CY_AS_ERROR_INVALID_REQUEST (43) + +/* Summary + An ACK request was requested while no setup packet was pending. + + Description + This error is issued if CyAsUsbAckSetupPacket() is called when no + setup packet is pending. +*/ +#define CY_AS_ERROR_NO_SETUP_PACKET_PENDING (44) + +/* Summary + A call was made to a API function that cannot be called from a callback. + + Description + Only asynchronous functions can be called from within West Bridge callbacks. + This error results when an invalid function is called from a callback. +*/ +#define CY_AS_ERROR_INVALID_IN_CALLBACK (45) + +/* Summary + A call was made to CyAsUsbSetEndPointConfig() before + CyAsUsbSetPhysicalConfiguration() was called. + + Description + When logical endpoints are configured, you must define the physical + endpoint for the logical endpoint being configured. Therefore + CyAsUsbSetPhysicalConfiguration() must be called to define the + physical endpoints before calling CyAsUsbSetEndPointConfig(). +*/ +#define CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET (46) + +/* Summary + The physical endpoint referenced is not valid in the current physical + configuration + + Description + When logical endpoints are configured, you must define the physical + endpoint for the logical endpoint being configured. Given the + current physical configuration, the physical endpoint referenced + is not valid. +*/ +#define CY_AS_ERROR_INVALID_PHYSICAL_ENDPOINT (47) + +/* Summary + The data supplied to the CyAsMiscDownloadFirmware() call is not + aligned on a WORD (16 bit) boundary. + + Description + Many systems have problems with the transfer of data a word at a + time when the data is not word aligned. For this reason, we + require that the firmware image be aligned on a word boundary and + be an even number of bytes. This error is returned if these + conditions are not met. +*/ +#define CY_AS_ERROR_ALIGNMENT_ERROR (48) + +/* Summary + A call was made to destroy the West Bridge device, but the USB + stack or the storage stack was will running. + + Description + Before calling CyAsMiscDestroyDevice to destroy an West Bridge + device created via a call to CyAsMiscCreateDevice, the USB and + STORAGE stacks much be stopped via calls to CyAsUsbStop and + CyAsStorageStop. This error indicates that one of these two + stacks have not been stopped. +*/ +#define CY_AS_ERROR_STILL_RUNNING (49) + +/* Summary + A call was made to the API for a function that is not yet supported. + + Description + There are calls that are not yet supported that may be called through + the API. This is done to maintain compatibility in the future with + the API. This error is returned if you are asking for a capability + that does not yet exist. +*/ +#define CY_AS_ERROR_NOT_YET_SUPPORTED (50) + +/* Summary + A NULL callback was provided where a non-NULL callback was required + + Description + When async IO function are called, a callback is required to indicate + that the IO has completed. This callback must be non-NULL. +*/ +#define CY_AS_ERROR_NULL_CALLBACK (51) + +/* Summary + This error is returned when a request is made to put the West Bridge device + into standby mode while the storage stack is still active. + + Description + This error is returned when a request is made to put the West Bridge device + into standby mode while the storage stack is still active. You must call the + function CyAsStorageStop() in order to shut down the storage stack in order + to go into the standby mode. + + See Also + * CyAsMiscEnterStandby +*/ +#define CY_AS_ERROR_STORAGE_RUNNING (52) + +/* Summary + This error is returned when an operation is attempted that cannot be + completed while the USB stack is connected to a USB host. + + Description + This error is returned when an operation is attempted that cannot be + completed while the USB stack is connected to a USB host. In order + to sucessfully complete the desired operation, CyAsUsbDisconnect() + must be called to disconnect from the host. +*/ +#define CY_AS_ERROR_USB_CONNECTED (53) + +/* Summary + This error is returned when a USB disconnect is attempted and the + West Bridge device is not connected. + + Description + This error is returned when a USB disconnect is attempted and the + West Bridge device is not connected. +*/ +#define CY_AS_ERROR_USB_NOT_CONNECTED (54) + +/* Summary + This error is returned when an P2S storage operation attempted + and data could not be read or written to the storage media. + + Description + This error is returned when an P2S storage operation attempted + and data could not be read or written to the storage media. If + this error is recevied then a retry can be done. +*/ +#define CY_AS_ERROR_MEDIA_ACCESS_FAILURE (55) + +/* Summary + This error is returned when an P2S storage operation attempted + and the media is write protected. + + Description + This error is returned when an P2S storage operation attempted + and the media is write protected. +*/ +#define CY_AS_ERROR_MEDIA_WRITE_PROTECTED (56) + +/* Summary + This error is returned when an attempt is made to cancel a request + that has already been sent to the West Bridge. + + Description + It is not possible to cancel an asynchronous storage read/write + operation after the actual data transfer with the West Bridge + has started. This error is returned if CyAsStorageCancelAsync + is called to cancel such a request. + */ +#define CY_AS_ERROR_OPERATION_IN_TRANSIT (57) + +/* Summary + This error is returned when an invalid parameter is passed to + one of the APIs. + + Description + Some of the West Bridge APIs are applicable to only specific + media types, devices etc. This error code is returned when a + API is called with an invalid parameter type. + */ +#define CY_AS_ERROR_INVALID_PARAMETER (58) + +/* Summary + This error is returned if an API is not supported in the current setup. + + Description + Some of the West Bridge APIs work only with specific device types + or firmware images. This error is returned when such APIs are called + when the current device or firmware does not support the invoked API + function. + */ +#define CY_AS_ERROR_NOT_SUPPORTED (59) + +/* Summary + This error is returned when a call is made to one of the Storage or + USB APIs while the device is in suspend mode. + + Description + This error is returned when a call is made to one of the storage or + USB APIs while the device is in suspend mode. + */ +#define CY_AS_ERROR_IN_SUSPEND (60) + +/* Summary + This error is returned when the call to CyAsMiscLeaveSuspend + is made and the device is not in suspend mode. + + Description + This error is returned when the call to CyAsMiscLeaveSuspend + is made and the device is not in suspend mode. + */ +#define CY_AS_ERROR_NOT_IN_SUSPEND (61) + +/* Summary + This error is returned when a command that is disabled by USB is called. + + Description + The remote wakeup capability should be exercised only if enabled by the + USB host. This error is returned when the CyAsUsbSignalRemoteWakeup API + is called when the feature has not been enabled by the USB host. + */ +#define CY_AS_ERROR_FEATURE_NOT_ENABLED (62) + +/* Summary + This error is returned when an Async storage read or write is called before a + query device call is issued. + + Description + In order for the SDK to properly set up a DMA the block size of a given media + needs to be known. This is done by making a call to CyAsStorageQueryDevice. + This call only needs to be made once per device. If this call is not issued + before an Async read or write is issued this error code is returned. + */ +#define CY_AS_ERROR_QUERY_DEVICE_NEEDED (63) + +/* Summary + This error is returned when a call is made to USB or STORAGE Start or + Stop before a prior Start or Stop has finished. + + Description + The USB and STORAGE start and stop functions can only be called if a + prior start or stop function call has fully completed. This means when + an async EX call is made you must wait until the callback for that call + has been completed before calling start or stop again. + */ +#define CY_AS_ERROR_STARTSTOP_PENDING (64) + +/* Summary + This error is returned when a request is made for a bus that does not exist + + Description + This error is returned when a request is made that references a bus + number that does not exist. This error is returned when the bus number + is not present in the current system, or if the bus number given is not + valid. + + See Also + * CyAsMiscSetTraceLevel + * CyAsStorageClaim + * CyAsStorageRelease + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageWriteAsync +*/ +#define CY_AS_ERROR_NO_SUCH_BUS (65) + +/* Summary + This error is returned when the bus corresponding to a media type cannot + be resolved. + + Description + In some S-Port configurations, the same media type may be supported on + multiple buses. In this case, it is not possible to resolve the target + address based on the media type. This error indicates that only + bus-based addressing is supported in a particular run-time + configuration. + + See Also + * CyAsMediaType + * CyAsBusNumber_t + */ +#define CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR (66) + +/* Summary + This error is returned when an invalid command is passed to the + CyAsStorageSDIOSync() function. + + Description + This error indiactes an unknown Command type was passed to the SDIO + command handler function. + */ + +#define CY_AS_ERROR_INVALID_COMMAND (67) + + +/* Summary + This error is returned when an invalid function /uninitialized + function is passed to an SDIO function. + + Description + This error indiactes an unknown/uninitialized function number was + passed to a SDIO function. + */ +#define CY_AS_ERROR_INVALID_FUNCTION (68) + +/* Summary + This error is returned when an invalid block size is passed to + CyAsSdioSetBlocksize(). + + Description + This error is returned when an invalid block size (greater than + maximum block size supported) is passed to CyAsSdioSetBlocksize(). + */ + +#define CY_AS_ERROR_INVALID_BLOCKSIZE (69) + +/* Summary + This error is returned when an tuple requested is not found. + + Description + This error is returned when an tuple requested is not found. + */ +#define CY_AS_ERROR_TUPLE_NOT_FOUND (70) + +/* Summary + This error is returned when an extended IO operation to an SDIO function is + Aborted. + Description + This error is returned when an extended IO operation to an SDIO function is + Aborted. */ +#define CY_AS_ERROR_IO_ABORTED (71) + +/* Summary + This error is returned when an extended IO operation to an SDIO function is + Suspended. + Description + This error is returned when an extended IO operation to an SDIO function is + Suspended. */ +#define CY_AS_ERROR_IO_SUSPENDED (72) + +/* Summary + This error is returned when IO is attempted to a Suspended SDIO function. + Description + This error is returned when IO is attempted to a Suspended SDIO function. */ +#define CY_AS_ERROR_FUNCTION_SUSPENDED (73) + +/* Summary + This error is returned if an MTP function is called before MTPStart + has completed. + Description + This error is returned if an MTP function is called before MTPStart + has completed. +*/ +#define CY_AS_ERROR_MTP_NOT_STARTED (74) + +/* Summary + This error is returned by API functions that are not valid in MTP + mode (CyAsStorageClaim for example) + Description + This error is returned by API functions that are not valid in MTP + mode (CyAsStorageClaim for example) +*/ +#define CY_AS_ERROR_NOT_VALID_IN_MTP (75) + +/* Summary + This error is returned when an attempt is made to partition a + storage device that is already partitioned. + + Description + This error is returned when an attempt is made to partition a + storage device that is already partitioned. +*/ +#define CY_AS_ERROR_ALREADY_PARTITIONED (76) + +/* Summary + This error is returned when a call is made to + CyAsUsbSelectMSPartitions after CyAsUsbSetEnumConfig is called. + + Description + This error is returned when a call is made to + CyAsUsbSelectMSPartitions after CyAsUsbSetEnumConfig is called. + */ +#define CY_AS_ERROR_INVALID_CALL_SEQUENCE (77) + +/* Summary + This error is returned when a StorageWrite opperation is attempted + during an ongoing MTP transfer. + Description + This error is returned when a StorageWrite opperation is attempted + during an ongoing MTP transfer. A MTP transfer is initiated by a + call to CyAsMTPInitSendObject or CyAsMTPInitGetObject and is not + finished until the CyAsMTPSendObjectComplete or + CyAsMTPGetObjectComplete event is generated. +*/ +#define CY_AS_ERROR_NOT_VALID_DURING_MTP (78) + +/* Summary + This error is returned when a StorageRead or StorageWrite is + attempted while a UsbRead or UsbWrite on a Turbo endpoint (2 or 6) is + pending, or visa versa. + Description + When there is a pending usb read or write on a turbo endpoint (2 or 6) + a storage read or write call may not be performed. Similarly when there + is a pending storage read or write a usb read or write may not be + performed on a turbo endpoint (2 or 6). +*/ +#define CY_AS_ERROR_STORAGE_EP_TURBO_EP_CONFLICT (79) + +/* Summary + This error is returned when processor requests to reserve greater + number of zones than available for proc booting via lna firmware. + + Description + Astoria does not allocate any nand zones for the processor in this case. +*/ +#define CY_AS_ERROR_EXCEEDED_NUM_ZONES_AVAIL (80) + +#endif /* _INCLUDED_CYASERR_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h new file mode 100644 index 000000000000..b695ba1a9110 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashal.h @@ -0,0 +1,108 @@ +/* Cypress West Bridge API header file (cyashal.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASHAL_H_ +#define _INCLUDED_CYASHAL_H_ + +#if !defined(__doxygen__) + +/* The possible HAL layers defined and implemented by Cypress */ + +#ifdef __CY_ASTORIA_FPGA_HAL__ +#ifdef CY_HAL_DEFINED +#error only one HAL layer can be defined +#endif + +#define CY_HAL_DEFINED + +#include "cyashalfpga.h" +#endif + +/***** SCM User space HAL ****/ +#ifdef __CY_ASTORIA_SCM_HAL__ +#ifdef CY_HAL_DEFINED +#error only one HAL layer can be defined +#endif + +#define CY_HAL_DEFINEDŚŚ + +#include "cyanhalscm.h" +#endif +/***** SCM User space HAL ****/ + +/***** SCM Kernel HAL ****/ +#ifdef __CY_ASTORIA_SCM_KERNEL_HAL__ +#ifdef CY_HAL_DEFINED +#error only one HAL layer can be defined +#endif + +#define CY_HAL_DEFINEDŚ + +#include "cyanhalscm_kernel.h" +#endif +/***** SCM Kernel HAL ****/ + +/***** OMAP5912 Kernel HAL ****/ +#ifdef __CY_ASTORIA_OMAP_5912_KERNEL_HAL__ + #ifdef CY_HAL_DEFINED + #error only one HAL layer can be defined + #endif + + #define CY_HAL_DEFINED + + #include "cyanhalomap_kernel.h" +#endif +/***** eof OMAP5912 Kernel HAL ****/ + + + +/***** OMAP3430 Kernel HAL ****/ +#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL + + #ifdef CY_HAL_DEFINED + #error only one HAL layer can be defined + #endif + + #define CY_HAL_DEFINED +/* moved to staging location, eventual implementation + * considered is here + * #include mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h> +*/ + #include "../../../arch/arm/plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h" + +#endif +/*****************************/ + + +/******/ +#ifdef __CY_ASTORIA_CUSTOMER_HAL__ +#ifdef CY_HAL_DEFINED +#error only one HAL layer can be defined +#endif +br +#define CY_HAL_DEFINED +#include "cyashal_customer.h" + +#endif + +#endif /* __doxygen__ */ + +#endif /* _INCLUDED_CYASHAL_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h new file mode 100644 index 000000000000..d48a7f4b147f --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashalcb.h @@ -0,0 +1,44 @@ +/* Cypress West Bridge API header file (cyashalcb.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASHALCB_H_ +#define _INCLUDED_CYASHALCB_H_ + +/* Summary + This type defines a callback function type called when a + DMA operation has completed. + + Description + + See Also + * CyAsHalDmaRegisterCallback + * CyAsHalDmaSetupWrite + * CyAsHalDmaSetupRead +*/ +typedef void (*cy_as_hal_dma_complete_callback)( + cy_as_hal_device_tag tag, + cy_as_end_point_number_t ep, + uint32_t cnt, + cy_as_return_status_t ret) ; + +typedef cy_as_hal_dma_complete_callback \ + cy_an_hal_dma_complete_callback; +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h new file mode 100644 index 000000000000..2cfe4fb4cf68 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyashaldoc.h @@ -0,0 +1,800 @@ +/* Cypress West Bridge API header file (cyashaldoc.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASHALDOC_H_ +#define _INCLUDED_CYASHALDOC_H_ + +#include "cyashaldef.h" + +/*@@Hardware Abstraction Layer (HAL) + Summary + This software module is supplied by the user of the West Bridge + API. This module contains the software that is specific to the + hardware implementation or operating system of the client + system. + + * Sleep Channels * + A sleep channel is a operating system object that provides that + capability for one thread or process to sleep while waiting on + the completion of some hardware event. The hardware event is + usually processed by a hardware interrupt and the interrupt + handler then wakes the thread or process that is sleeping. + + A sleep channel provides the mechanism for this operation. A + sleep channel is created and initialized during the API + initialization. When the API needs to wait for the hardware, + the API performs a SleepOn() operation on the sleep channel. + When hardware event occurs, an interrupt handler processes the + event and then performs a Wake() operation on the sleep channel + to wake the sleeping process or thread. + + * DMA Model * + When the West Bridge API needs to transfer USB or storage data + to/from the West Bridge device, this is done using a "DMA" + operation. In this context the term DMA is used loosely as the + West Bridge API does not really care if the data is transferred + using a burst read or write operation, or if the data is + transferred using programmed I/O operations. When a "DMA" + operation is needed, the West Bridge API calls either + CyAsHalDmaSetupRead() or CyAsHalDmaSetupWrite() depending on the + direction of the data flow. The West Bridge API expects the + "DMA" operation requested in the call to be completed and the + registered "DMA complete" callback to be called. + + The West Bridge API looks at several factors to determine the + size of the "DMA" request to pass to the HAL layer. First the + West Bridge API calls CyAsHalDmaMaxRequestSize() to determine + the maximum amount of data the HAL layer can accept for a "DMA" + operation on the requested endpoint. The West Bridge API will + never exceed this value in a "DMA" request to the HAL layer. + The West Bridge API also sends the maximum amount of data the + West Bridge device can accept as part of the "DMA" request. If + the amount of data in the "DMA" request to the HAL layer + exceeds the amount of data the West Bridge device can accept, + it is expected that the HAL layer has the ability to break the + request into multiple operations. + + If the HAL implementation requires the API to handle the size + of the "DMA" requests for one or more endpoints, the value + CY_AS_DMA_MAX_SIZE_HW_SIZE can be returned from the + CyAsHalDmaMaxRequestSize() call. In this case, the API assumes + that the maximum size of each "DMA" request should be limited + to the maximum that can be accepted by the endpoint in question. + + Notes + See the /api/hal/scm_kernel/cyashalscm_kernel.c file + for an example of how the DMA request size can be managed by + the HAL implementation. + + * Interrupt Handling * + The HAL implementation is required to handle interrupts arriving + from the West Bridge device, and call the appropriate handlers. + If the interrupt arriving is one of PLLLOCKINT, PMINT, MBINT or + MCUINT, the CyAsIntrServiceInterrupt API should be called to + service the interrupt. If the interrupt arriving is DRQINT, the + HAL should identify the endpoint corresponding to which the DRQ + is being generated and perform the read/write transfer from the + West Bridge. See the /api/hal/scm_kernel/ + cyashalscm_kernel.c or /api/hal/fpga/cyashalfpga.c + reference HAL implementations for examples. + + The HAL implementation can choose to poll the West Bridge + interrupt status register instead of using interrupts. In this + case, the polling has to be performed from a different thread/ + task than the one running the APIs. This is required because + there are API calls that block on the reception of data from the + West Bridge, which is delivered only through the interrupt + handlers. + + * Required Functions * + This section defines the types and functions that must be + supplied in order to provide a complete HAL layer for the + West Bridge API. + + Types that must be supplied: + * CyAsHalSleepChannel + + Hardware functions that must be supplied: + * CyAsHalWriteRegister + * CyAsHalReadRegister + * CyAsHalDmaSetupWrite + * CyAsHalDmaSetupRead + * CyAsHalDmaCancelRequest + * CyAsHalDmaRegisterCallback + * CyAsHalDmaMaxRequestSize + * CyAsHalSetWakeupPin + * CyAsHalSyncDeviceClocks + * CyAsHalInitDevRegisters + * CyAsHalReadRegsBeforeStandby + * CyAsHalRestoreRegsAfterStandby + + Operating system functions that must be supplied: + * CyAsHalAlloc + * CyAsHalFree + * CyAsHalCBAlloc + * CyAsHalCBFree + * CyAsHalMemSet + * CyAsHalCreateSleepChannel + * CyAsHalDestroySleepChannel + * CyAsHalSleepOn + * CyAsHalWake + * CyAsHalDisableInterrupts + * CyAsHalEnableInterrupts + * CyAsHalSleep150 + * CyAsHalSleep + * CyAsHalAssert + * CyAsHalPrintMessage + * CyAsHalIsPolling +*/ + +/* Summary + This is the type that represents a sleep channel + + Description + A sleep channel is an operating system object that, when a + thread of control waits on the sleep channel, the thread + sleeps until another thread signals the sleep object. This + object is generally used when a high level API is called + and must wait for a response that is supplied in an interrupt + handler. The thread calling the API is put into a sleep + state and when the reply arrives via the interrupt handler, + the interrupt handler wakes the sleeping thread to indicate + that the expect reply is available. +*/ +typedef struct cy_as_hal_sleep_channel { + /* This structure is filled in with OS specific information + to implementat a sleep channel */ + int m_channel ; +} cy_as_hal_sleep_channel ; + +/* Summary + This function is called to write a register value + + Description + This function is called to write a specific register to a + specific value. The tag identifies the device of interest. + The address is relative to the base address of the West + Bridge device. + + Returns + Nothing + + See Also + * CyAsHalDeviceTag + * CyAsHalReadRegister +*/ +EXTERN void +cy_as_hal_write_register( +/* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The address we are writing to */ + uint16_t addr, + /* The value to write to the register */ + uint16_t value + ) ; + +/* Summary + This function is called to read a register value + + Description + This function is called to read the contents of a specific + register. The tag identifies the device of interest. The + address is relative to the base address of the West Bridge + device. + + Returns + Contents of the register + + See Also + * CyAsHalDeviceTag + * CyAsHalWriteRegister +*/ +EXTERN uint16_t +cy_as_hal_read_register( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The address we are writing to */ + uint16_t addr + ) ; + +/* Summary + This function initiates a DMA write operation to write + to West Bridge + + Description + This function initiates a DMA write operation. The request + size will not exceed the value the HAL layer returned via + CyAsHalDmaMaxRequestSize(). This request size may exceed + the size of what the West Bridge device will accept as on + packet and the HAL layer may need to divide the request + into multiple hardware DMA operations. + + Returns + None + + See Also + * CyAsHalDmaSetupRead + * CyAsHalDmaMaxRequestSize +*/ +EXTERN void +cy_as_hal_dma_setup_write( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The endpoint we are writing to */ + cy_as_end_point_number_t ep, + /* The data to write via DMA */ + void *buf_p, + /* The size of the data at buf_p */ + uint32_t size, + /* The maximum amount of data that the endpoint + * can accept as one packet */ + uint16_t maxsize + ) ; + +/* Summary + This function initiates a DMA read operation from West Bridge + + Description + This function initiates a DMA read operation. The request + size will not exceed the value the HAL layer returned via + CyAsHalDmaMaxRequestSize(). This request size may exceed + the size of what the Anitoch will accept as one packet and + the HAL layer may need to divide the request into multiple + hardware DMA operations. + + Returns + None + + See Also + * CyAsHalDmaSetupRead + * CyAsHalDmaMaxRequestSize +*/ +EXTERN void +cy_as_hal_dma_setup_read( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The endpoint we are reading from */ + cy_as_end_point_number_t ep, + /* The buffer to read data into */ + void *buf_p, + /* The amount of data to read */ + uint32_t size, + /* The maximum amount of data that the endpoint + * can provide in one DMA operation */ + uint16_t maxsize + ) ; + +/* Summary + This function cancels a pending DMA request + + Description + This function cancels a pending DMA request that has been + passed down to the hardware. The HAL layer can elect to + physically cancel the request if possible, or just ignore + the results of the request if it is not possible. + + Returns + None +*/ +EXTERN void +cy_as_hal_dma_cancel_request( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The endpoint we are reading from */ + cy_as_end_point_number_t ep + ) ; + +/* Summary + This function registers a callback function to be called when + a DMA request is completed + + Description + This function registers a callback that is called when a request + issued via CyAsHalDmaSetupWrite() or CyAsHalDmaSetupRead() has + completed. + + Returns + None + + See Also + * CyAsHalDmaSetupWrite + * CyAsHalDmaSetupRead +*/ +EXTERN void +cy_as_hal_dma_register_callback( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The callback to call when a request has completed */ + cy_as_hal_dma_complete_callback cb + ) ; + +/* Summary + This function returns the maximum size of a DMA request that can + be handled by the HAL. + + Description + When DMA requests are passed to the HAL layer for processing, + the HAL layer may have a limit on the size of the request that + can be handled. This function is called by the DMA manager for + an endpoint when DMA is enabled to get the maximum size of data + the HAL layer can handle. The DMA manager insures that a request + is never sent to the HAL layer that exceeds the size returned by + this function. + + Returns + the maximum size of DMA request the HAL layer can handle +*/ +EXTERN uint32_t +cy_as_hal_dma_max_request_size( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The endpoint of interest */ + cy_as_end_point_number_t ep + ) ; + +/* Summary + This function sets the WAKEUP pin to a specific state on the + West Bridge device. + + Description + In order to enter the standby mode, the WAKEUP pin must be + de-asserted. In order to resume from standby mode, the WAKEUP + pin must be asserted. This function provides the mechanism to + do this. + + Returns + 1 if the pin was changed, 0 if the HAL layer does not support + changing this pin +*/ +EXTERN uint32_t +cy_as_hal_set_wakeup_pin( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* The desired state of the wakeup pin */ + cy_bool state + ) ; + +/* Summary + Synchronise the West Bridge device clocks to re-establish device + connectivity. + + Description + When the Astoria bridge device is working in SPI mode, a long + period of inactivity can cause a loss of serial synchronisation + between the processor and Astoria. This function is called by + the API when it detects such a condition, and is expected to take + the action required to re-establish clock synchronisation between + the devices. + + Returns + CyTrue if the attempt to re-synchronise is successful, + CyFalse if not. + */ +EXTERN cy_bool +cy_as_hal_sync_device_clocks( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + ) ; + +/* Summary + Initialize West Bridge device registers that may have been + modified while the device was in standby. + + Description + The content of some West Bridge registers may be lost when + the device is placed in standby mode. This function restores + these register contents so that the device can continue to + function normally after it wakes up from standby mode. + + This function is required to perform operations only when the + API is being used with the Astoria device in one of the PNAND + modes or in the PSPI mode. It can be a no-operation in all + other cases. + + Returns + None + */ +EXTERN void +cy_as_hal_init_dev_registers( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag, + /* Indicates whether this is a wake-up from standby. */ + cy_bool is_standby_wakeup + ) ; + +/* Summary + This function reads a set of P-port accessible device registers and + stores their value for later use. + + Description + The West Bridge Astoria device silicon has a known problem when + operating in SPI mode on the P-port, where some of the device + registers lose their value when the device goes in and out of + standby mode. The suggested work-around is to reset the Astoria + device as part of the wakeup procedure from standby. + + This requires that the values of some of the P-port accessible + registers be restored to their pre-standby values after it has + been reset. This HAL function can be used to read and store + the values of these registers at the point where the device is + being placed in standby mode. + + Returns + None + + See Also + * CyAsHalRestoreRegsAfterStandby + */ +EXTERN void +cy_as_hal_read_regs_before_standby( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag + ) ; + +/* Summary + This function restores the old values to a set of P-port + accessible device registers. + + Description + This function is part of the work-around to a known West + Bridge Astoria device error when operating in SPI mode on + the P-port. This function is used to restore a set of + P-port accessible registers to the values they had before + the device was placed in standby mode. + + Returns + None + + See Also + * CyAsHalRestoreRegsAfterStandby + */ +EXTERN void +cy_as_hal_restore_regs_after_standby( + /* The tag to ID a specific West Bridge device */ + cy_as_hal_device_tag tag + ) ; + +/* + * The functions below this comment are part of the HAL layer, + * as the HAL layer consists of the abstraction to both the + * hardware platform and the operating system. However; the + * functions below this comment all relate to the operating + * environment and not specifically to the hardware platform + * or specific device. + */ + +/* Summary + This function allocates a block of memory + + Description + This is the HAL layer equivalent of the malloc() function. + + Returns + a pointer to a block of memory + + See Also + * CyAsHalFree +*/ +EXTERN void * +cy_as_hal_alloc( + /* The size of the memory block to allocate */ + uint32_t size + ) ; + +/* Summary + This function frees a previously allocated block of memory + + Description + This is the HAL layer equivalent of the free() function. + + Returns + None + + See Also + * CyAsHalAlloc +*/ +EXTERN void +cy_as_hal_free( + /* Pointer to a memory block to free */ + void *ptr + ) ; + +/* Summary + This function is a malloc equivalent that can be used from an + interrupt context. + + Description + This function is a malloc equivalent that will be called from the + API in callbacks. This function is required to be able to provide + memory in interrupt context. + + Notes + For platforms where it is not possible to allocate memory in interrupt + context, we provide a reference allocator that takes memory during + initialization and implements malloc/free using this memory. + See the /api/hal/fpga/cyashalblkalloc.[ch] files for the + implementation, and the /api/hal/fpga/cyashalfpga.c file + for an example of the use of this allocator. + + Returns + A pointer to the allocated block of memory + + See Also + * CyAsHalCBFree + * CyAsHalAlloc +*/ +EXTERN void * +cy_as_hal_c_b_alloc( + /* The size of the memory block to allocate */ + uint32_t size + ) ; + +/* Summary + This function frees the memory allocated through the CyAsHalCBAlloc + call. + + Description + This function frees memory allocated through the CyAsHalCBAlloc + call, and is also required to support calls from interrupt + context. + + Returns + None + + See Also + * CyAsHalCBAlloc + * CyAsHalFree +*/ +EXTERN void +cy_as_hal_c_b_free( + /* Pointer to the memory block to be freed */ + void *ptr + ) ; + +/* Summary + This function sets a block of memory to a specific value + + Description + This function is the HAL layer equivalent of the memset() function. + + Returns + None +*/ +EXTERN void +cy_as_mem_set( + /* A pointer to a block of memory to set */ + void *ptr, + /* The value to set the memory to */ + uint8_t value, + /* The number of bytes to set */ + uint32_t cnt + ) ; + +/* Summary + This function creates or initializes a sleep channel + + Description + This function creates or initializes a sleep channel. The + sleep channel defined using the HAL data structure + CyAsHalSleepChannel. + + Returns + CyTrue is the initialization was sucessful, and CyFalse otherwise + + See Also + * CyAsHalSleepChannel + * CyAsHalDestroySleepChannel + * CyAsHalSleepOn + * CyAsHalWake +*/ +EXTERN cy_bool +cy_as_hal_create_sleep_channel( + /* Pointer to the sleep channel to create/initialize */ + cy_as_hal_sleep_channel *chan + ) ; + +/* Summary + This function destroys an existing sleep channel + + Description + This function destroys an existing sleep channel. The sleep channel + is of type CyAsHalSleepChannel. + + Returns + CyTrue if the channel was destroyed, and CyFalse otherwise + + See Also + * CyAsHalSleepChannel + * CyAsHalCreateSleepChannel + * CyAsHalSleepOn + * CyAsHalWake +*/ +EXTERN cy_bool +cy_as_hal_destroy_sleep_channel( + /* The sleep channel to destroy */ + cy_as_hal_sleep_channel chan + ) ; + +/* Summary + This function causes the calling process or thread to sleep until + CyAsHalWake() is called + + Description + This function causes the calling process or threadvto sleep. + When CyAsHalWake() is called on the same sleep channel, this + processes or thread is then wakened and allowed to run + + Returns + CyTrue if the thread or process is asleep, and CyFalse otherwise + + See Also + * CyAsHalSleepChannel + * CyAsHalWake +*/ +EXTERN cy_bool +cy_as_hal_sleep_on( + /* The sleep channel to sleep on */ + cy_as_hal_sleep_channel chan, + /* The maximum time to sleep in milli-seconds */ + uint32_t ms + ) ; + +/* Summary + This function casues the process or thread sleeping on the given + sleep channel to wake + + Description + This function causes the process or thread sleeping on the given + sleep channel to wake. The channel + + Returns + CyTrue if the thread or process is awake, and CyFalse otherwise + + See Also + * CyAsHalSleepChannel + * CyAsHalSleepOn +*/ +EXTERN cy_bool +cy_as_hal_wake( + /* The sleep channel to wake */ + cy_as_hal_sleep_channel chan + ) ; + +/* Summary + This function disables interrupts, insuring that short bursts + of code can be run without danger of interrupt handlers running. + + Description + There are cases within the API when lists must be manipulated by + both the API and the associated interrupt handlers. In these + cases, interrupts must be disabled to insure the integrity of the + list during the modification. This function is used to disable + interrupts during the short intervals where these lists are being + changed. + + The HAL must have the ability to nest calls to + CyAsHalDisableInterrupts and CyAsHalEnableInterrupts. + + Returns + Any interrupt related state value which will be passed back into + the subsequent CyAsHalEnableInterrupts call. + + See Also + * CyAsHalEnableInterrupts +*/ +EXTERN uint32_t +cy_as_hal_disable_interrupts() ; + +/* Summary + This function re-enables interrupts after a critical section of + code in the API has been completed. + + Description + There are cases within the API when lists must be manipulated by + both the API and the associated interrupt handlers. In these + cases, interrupts must be disabled to insure the integrity of the + list during the modification. This function is used to enable + interrupts after the short intervals where these lists are being + changed. + + See Also + * CyAsHalDisableInterrupts +*/ +EXTERN void +cy_as_hal_enable_interrupts( + /* Value returned by the previous CyAsHalDisableInterrupts call. */ + uint32_t value + ) ; + +/* Summary + This function sleeps for 150 ns. + + Description + This function sleeps for 150 ns before allowing the calling function + to continue. This function is used for a specific purpose and the + sleep required is at least 150 ns. +*/ +EXTERN void +cy_as_hal_sleep150( + ) ; + +/* Summary + This function sleeps for the given number of milliseconds + + Description + This function sleeps for at least the given number of milliseonds +*/ +EXTERN void +cy_as_hal_sleep( + uint32_t ms + ) ; + +/* Summary + This function asserts when the condition evaluates to zero + + Description + Within the API there are conditions which are checked to insure + the integrity of the code. These conditions are checked only + within a DEBUG build. This function is used to check the condition + and if the result evaluates to zero, it should be considered a + fatal error that should be reported to Cypress. +*/ +EXTERN void +cy_as_hal_assert( + /* The condition to evaluate */ + cy_bool cond + ) ; + +/* Summary + This function prints a message from the API to a human readable device + + Description + There are places within the West Bridge API where printing a message + is useful to the debug process. This function provides the mechanism + to print a message. + + Returns + NONE +*/ +EXTERN void +cy_as_hal_print_message( + /* The message to print */ + const char *fmt_p, + ... /* Variable arguments */ + ) ; + +/* Summary + This function reports whether the HAL implementation uses + polling to service data coming from the West Bridge. + + Description + This function reports whether the HAL implementation uses + polling to service data coming from the West Bridge. + + Returns + CyTrue if the HAL polls the West Bridge Interrupt Status registers + to complete operations, CyFalse if the HAL is interrupt driven. + */ +EXTERN cy_bool +cy_as_hal_is_polling( + void) ; + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h new file mode 100644 index 000000000000..e77aa6ae82bb --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasintr.h @@ -0,0 +1,104 @@ +/* Cypress West Bridge API header file (cyasintr.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASINTR_H_ +#define _INCLUDED_CYASINTR_H_ + +#include "cyasdevice.h" + +#include "cyas_cplus_start.h" + +/* Summary + Initialize the interrupt manager module + + Description + This function is called to initialize the interrupt module. + This module enables interrupts as well as servies West Bridge + related interrupts by determining the source of the interrupt + and calling the appropriate handler function. + + Notes + If the dmaintr parameter is TRUE, the initialization code + initializes the interrupt mask to have the DMA related interrupt + enabled via the general purpose interrupt. However, the interrupt + service function assumes that the DMA interrupt is handled by the + HAL layer before the interrupt module handler function is called. + + Returns + * CY_AS_ERROR_SUCCESS - the interrupt module was initialized + * correctly + * CY_AS_ERROR_ALREADY_RUNNING - the interrupt module was already + * started + + See Also + * CyAsIntrStop + * CyAsServiceInterrupt +*/ +cy_as_return_status_t +cy_as_intr_start( + /* Device being initialized */ + cy_as_device *dev_p, + /* If true, enable the DMA interrupt through the INT signal */ + cy_bool dmaintr + ) ; + +/* Summary + Stop the interrupt manager module + + Description + This function stops the interrupt module and masks all interrupts + from the West Bridge device. + + Returns + * CY_AS_ERROR_SUCCESS - the interrupt module was stopped + * sucessfully + * CY_AS_ERROR_NOT_RUNNING - the interrupt module was not + * running + + See Also + * CyAsIntrStart + * CyAsServiceInterrupt +*/ +cy_as_return_status_t +cy_as_intr_stop( + /* Device bein stopped */ + cy_as_device *dev_p + ) ; + + +/* Summary + The interrupt service routine for West Bridge + + Description + When an interrupt is detected, this function is called to + service the West Bridge interrupt. It is safe and efficient + for this function to be called when no West Bridge interrupt + has occurred. This function will determine it is not an West + Bridge interrupt quickly and return. +*/ +void cy_as_intr_service_interrupt( + /* The USER supplied tag for this device */ + cy_as_hal_device_tag tag + ) ; + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASINTR_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h new file mode 100644 index 000000000000..40497655b7fb --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslep2pep.h @@ -0,0 +1,36 @@ +/* Cypress West Bridge API header file (cyaslep2pep.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASLEP2PEP_H_ +#define _INCLUDED_CYASLEP2PEP_H_ + +#include "cyasdevice.h" + +extern cy_as_return_status_t +cy_as_usb_map_logical2_physical(cy_as_device *dev_p) ; + +extern cy_as_return_status_t +cy_as_usb_setup_dma(cy_as_device *dev_p) ; + +extern cy_as_return_status_t +cy_as_usb_set_dma_sizes(cy_as_device *dev_p) ; + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h new file mode 100644 index 000000000000..6d40aa6eed6c --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyaslowlevel.h @@ -0,0 +1,366 @@ +/* Cypress West Bridge API header file (cyaslowlevel.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASLOWLEVEL_H_ +#define _INCLUDED_CYASLOWLEVEL_H_ + +/*@@Low Level Communications + + Summary + The low level communications module is responsible for + communications between the West Bridge device and the P + port processor. Communications is organized as a series + of requests and subsequent responses. For each request + there is a one and only one response. Requests may go + from the West Bridge device to the P port processor, or + from the P Port processor to the West Bridge device. + + Description + Requests are issued across what is called a context. A + context is a single channel of communications from one + processor to another processor. There can be only a single + request outstanding on a context at a given time. Contexts + are used to identify subsystems that can only process a + single request at a time, but are independent of other + contexts in the system. For instance, there is a context + for communicating storage commands from the P port processor + to the West Bridge device. There is also a context for + communicating USB commands from the P port processor to the + West Bridge device. + + Requests and responses are identical with the exception of + the type bit in the request/response header. If the type + bit is one, the packet is a request. If this bit is zero, + the packet is a response. Also encoded within the header of + the request/response is the code. The code is a command + code for a request, or a response code for a response. For + a request, the code is a function of the context. The code + 0 has one meaning for the storage context and a different + meaning for the USB context. The code is treated differently + in the response. If the code in the response is less than 16, + then the meaning of the response is global across all + contexts. If the response is greater than or equal to 16, + then the response is specific to the associated context. + + Requests and responses are transferred between processors + through the mailbox registers. It may take one or more cycles + to transmit a complete request or response. The context is + encoded into each cycle of the transfer to insure the + receiving processor can route the data to the appropriate + context for processing. In this way, the traffic from multiple + contexts can be multiplexed into a single data stream through + the mailbox registers by the sending processor, and + demultiplexed from the mailbox registers by the receiving + processor. + + * Firmware Assumptions * + The firmware assumes that mailbox contents will be consumed + immediately. Therefore for multi-cycle packets, the data is + sent in a tight polling loop from the firmware. This implies + that the data must be read from the mailbox register on the P + port side and processed immediately or performance of the + firmware will suffer. In order to insure this is the case, + the data from the mailboxes is read and stored immediately + in a per context buffer. This occurs until the entire packet + is received at which time the request packet is processed. + Since the protocol is designed to allow for only one + outstanding packet at a time, the firmware can never be in a + position of waiting on the mailbox registers while the P port + is processing a request. Only after the response to the + previous request is sent will another request be sent. +*/ + +#include "cyashal.h" +#include "cyasdevice.h" + +#include "cyas_cplus_start.h" + +/* + * Constants + */ +#define CY_AS_REQUEST_RESPONSE_CODE_MASK (0x00ff) +#define CY_AS_REQUEST_RESPONSE_CONTEXT_MASK (0x0F00) +#define CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT (8) +#define CY_AS_REQUEST_RESPONSE_TYPE_MASK (0x4000) +#define CY_AS_REQUEST_RESPONSE_LAST_MASK (0x8000) +#define CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG (0x1000) + +/* + * These macros extract the data from a 16 bit value + */ +#define cy_as_mbox_get_code(c) \ + ((uint8_t)((c) & CY_AS_REQUEST_RESPONSE_CODE_MASK)) +#define cy_as_mbox_get_context(c) \ + ((uint8_t)(((c) & CY_AS_REQUEST_RESPONSE_CONTEXT_MASK) \ + >> CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT)) +#define cy_as_mbox_is_last(c) \ + ((c) & CY_AS_REQUEST_RESPONSE_LAST_MASK) +#define cy_as_mbox_is_request(c) \ + (((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) != 0) +#define cy_as_mbox_is_response(c) \ + (((c) & CY_AS_REQUEST_RESPONSE_TYPE_MASK) == 0) + +/* + * These macros (not yet written) pack data into or extract data + * from the m_box0 field of the request or response + */ +#define cy_as_ll_request_response__set_code(req, code) \ + ((req)->box0 = \ + ((req)->box0 & ~CY_AS_REQUEST_RESPONSE_CODE_MASK) | \ + (code & CY_AS_REQUEST_RESPONSE_CODE_MASK)) + +#define cy_as_ll_request_response__get_code(req) \ + cy_as_mbox_get_code((req)->box0) + +#define cy_as_ll_request_response__set_context(req, context) \ + ((req)->box0 |= ((context) << \ + CY_AS_REQUEST_RESPONSE_CONTEXT_SHIFT)) + +#define cy_as_ll_request_response__set_clear_storage_flag(req) \ + ((req)->box0 |= CY_AS_REQUEST_RESPONSE_CLEAR_STR_FLAG) + +#define cy_as_ll_request_response__get_context(req) \ + cy_as_mbox_get_context((req)->box0) + +#define cy_as_ll_request_response__is_last(req) \ + cy_as_mbox_is_last((req)->box0) + +#define CY_an_ll_request_response___set_last(req) \ + ((req)->box0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK) + +#define cy_as_ll_request_response__is_request(req) \ + cy_as_mbox_is_request((req)->box0) + +#define cy_as_ll_request_response__set_request(req) \ + ((req)->box0 |= CY_AS_REQUEST_RESPONSE_TYPE_MASK) + +#define cy_as_ll_request_response__set_response(req) \ + ((req)->box0 &= ~CY_AS_REQUEST_RESPONSE_TYPE_MASK) + +#define cy_as_ll_request_response__is_response(req) \ + cy_as_mbox_is_response((req)->box0) + +#define cy_as_ll_request_response__get_word(req, offset) \ + ((req)->data[(offset)]) + +#define cy_as_ll_request_response__set_word(req, offset, \ + value) ((req)->data[(offset)] = value) + +typedef enum cy_as_remove_request_result_t { + cy_as_remove_request_sucessful, + cy_as_remove_request_in_transit, + cy_as_remove_request_not_found +} cy_as_remove_request_result_t ; + +/* Summary + Start the low level communications module + + Description +*/ +cy_as_return_status_t +cy_as_ll_start( + cy_as_device *dev_p + ) ; + +cy_as_return_status_t +cy_as_ll_stop( + cy_as_device *dev_p + ) ; + + +cy_as_ll_request_response * +cy_as_ll_create_request( + cy_as_device *dev_p, + uint16_t code, + uint8_t context, + /* Length of the request in 16 bit words */ + uint16_t length + ) ; + +void +cy_as_ll_init_request( + cy_as_ll_request_response *req_p, + uint16_t code, + uint16_t context, + uint16_t length) ; + +void +cy_as_ll_init_response( + cy_as_ll_request_response *req_p, + uint16_t length) ; + +void +cy_as_ll_destroy_request( + cy_as_device *dev_p, + cy_as_ll_request_response *) ; + +cy_as_ll_request_response * +cy_as_ll_create_response( + cy_as_device *dev_p, + /* Length of the request in 16 bit words */ + uint16_t length + ) ; + +cy_as_remove_request_result_t +cy_as_ll_remove_request( + cy_as_device *dev_p, + cy_as_context *ctxt_p, + cy_as_ll_request_response *req_p, + cy_bool force + ) ; +void +cy_as_ll_remove_all_requests(cy_as_device *dev_p, + cy_as_context *ctxt_p) ; + +void +cy_as_ll_destroy_response( + cy_as_device *dev_p, + cy_as_ll_request_response *) ; + +cy_as_return_status_t +cy_as_ll_send_request( + /* The West Bridge device */ + cy_as_device *dev_p, + /* The request to send */ + cy_as_ll_request_response *req, + /* Storage for a reply, must be sure it is of sufficient size */ + cy_as_ll_request_response *resp, + /* If true, this is a sync request */ + cy_bool sync, + /* Callback to call when reply is received */ + cy_as_response_callback cb +) ; + +cy_as_return_status_t +cy_as_ll_send_request_wait_reply( + /* The West Bridge device */ + cy_as_device *dev_p, + /* The request to send */ + cy_as_ll_request_response *req, + /* Storage for a reply, must be sure it is of sufficient size */ + cy_as_ll_request_response *resp +) ; + +/* Summary + This function registers a callback function to be called when a + request arrives on a given context. + + Description + + Returns + * CY_AS_ERROR_SUCCESS +*/ +extern cy_as_return_status_t +cy_as_ll_register_request_callback( + cy_as_device *dev_p, + uint8_t context, + cy_as_response_callback cb + ) ; + +/* Summary + This function packs a set of bytes given by the data_p pointer + into a request, reply structure. +*/ +extern void +cy_as_ll_request_response__pack( + /* The destintation request or response */ + cy_as_ll_request_response *req, + /* The offset of where to pack the data */ + uint32_t offset, + /* The length of the data to pack in bytes */ + uint32_t length, + /* The data to pack */ + void *data_p + ) ; + +/* Summary + This function unpacks a set of bytes from a request/reply + structure into a segment of memory given by the data_p pointer. +*/ +extern void +cy_as_ll_request_response__unpack( + /* The source of the data to unpack */ + cy_as_ll_request_response *req, + /* The offset of the data to unpack */ + uint32_t offset, + /* The length of the data to unpack in bytes */ + uint32_t length, + /* The destination of the unpack operation */ + void *data_p + ) ; + +/* Summary + This function sends a status response back to the West Bridge + device in response to a previously send request +*/ +extern cy_as_return_status_t +cy_as_ll_send_status_response( + /* The West Bridge device */ + cy_as_device *dev_p, + /* The context to send the response on */ + uint8_t context, + /* The success/failure code to send */ + uint16_t code, + /* Flag to clear wait on storage context */ + uint8_t clear_storage) ; + +/* Summary + This function sends a response back to the West Bridge device. + + Description + This function sends a response back to the West Bridge device. + The response is sent on the context given by the 'context' + variable. The code for the response is given by the 'code' + argument. The data for the response is given by the data and + length arguments. +*/ +extern cy_as_return_status_t +cy_as_ll_send_data_response( + /* The West Bridge device */ + cy_as_device *dev_p, + /* The context to send the response on */ + uint8_t context, + /* The response code to use */ + uint16_t code, + /* The length of the data for the response */ + uint16_t length, + /* The data for the response */ + void *data +) ; + +/* Summary + This function removes any requests of the given type + from the given context. + + Description + This function removes requests of a given type from the + context given via the context number. +*/ +extern cy_as_return_status_t +cy_as_ll_remove_ep_data_requests( + /* The West Bridge device */ + cy_as_device *dev_p, + cy_as_end_point_number_t ep + ) ; + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASLOWLEVEL_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h new file mode 100644 index 000000000000..e444079cf87c --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmedia.h @@ -0,0 +1,54 @@ +/* Cypress West Bridge API header file (cyasmedia.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASMEDIA_H_ +#define _INCLUDED_CYASMEDIA_H_ + +#include "cyas_cplus_start.h" + + +/* Summary + Specifies a specific type of media supported by West Bridge + + Description + The West Bridge device supports five specific types of media + as storage/IO devices attached to it's S-Port. This type is + used to indicate the type of media being referenced in any + API call. +*/ +typedef enum cy_as_media_type { + /* Flash NAND memory (may be SLC or MLC) */ + cy_as_media_nand = 0x00, + /* An SD flash memory device */ + cy_as_media_sd_flash = 0x01, + /* An MMC flash memory device */ + cy_as_media_mmc_flash = 0x02, + /* A CE-ATA disk drive */ + cy_as_media_ce_ata = 0x03, + /* SDIO device. */ + cy_as_media_sdio = 0x04, + cy_as_media_max_media_value = 0x05 + +} cy_as_media_type ; + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASMEDIA_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h new file mode 100644 index 000000000000..33655bd125cc --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h @@ -0,0 +1,1549 @@ +/* Cypress West Bridge API header file (cyasmisc.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASMISC_H_ +#define _INCLUDED_CYASMISC_H_ + +#include "cyashal.h" +#include "cyastypes.h" +#include "cyasmedia.h" + +#include "cyas_cplus_start.h" + +#define CY_AS_LEAVE_STANDBY_DELAY_CLOCK (1) +#define CY_AS_RESET_DELAY_CLOCK (1) + +#define CY_AS_LEAVE_STANDBY_DELAY_CRYSTAL (5) +#define CY_AS_RESET_DELAY_CRYSTAL (5) + +/* The maximum number of buses supported */ +#define CY_AS_MAX_BUSES (2) + +/* The maximum number of storage devices supported per bus */ +#define CY_AS_MAX_STORAGE_DEVICES (1) + +#define CY_AS_FUNCTCBTYPE_DATA_MASK (0x60000000U) +#define CY_AS_FUNCTCBTYPE_TYPE_MASK (0x1FFFFFFFU) + +#define cy_as_funct_c_b_type_get_type(t) \ + ((cy_as_funct_c_b_type)((t) & CY_AS_FUNCTCBTYPE_TYPE_MASK)) +#define cy_as_funct_c_b_type_contains_data(t) \ + (((cy_as_funct_c_b_type)((t) & \ + CY_AS_FUNCTCBTYPE_DATA_MASK)) == CY_FUNCT_CB_DATA) + +/************************************** + * West Bridge Types + **************************************/ + +/* Summary + Specifies a handle to an West Bridge device + + Description + This type represents an opaque handle to an West Bridge device. + This handle is created via the CyAsMiscCreateDevice() function + and is used in all subsequent calls that communicate to the West + Bridge device. + + See Also + * CyAsMiscCreateDevice + * CyAsMiscDestroyDevice +*/ +typedef void *cy_as_device_handle ; + +/* Summary + This data type gives the mode for the DACK# signal +*/ +typedef enum cy_as_device_dack_mode { + cy_as_device_dack_ack, /* Operate in the ACK mode */ + cy_as_device_dack_eob /* Operate in the EOB mode */ +} cy_as_device_dack_mode ; + +/* Summary + This data structure gives the options for all hardware features. + + Description + This structure contains the information required to initialize the + West Bridge hardware. Any features of the device that can be + configured by the caller are specified here. + + See Also + * CyAsMiscConfigure +*/ +typedef struct cy_as_device_config { + /* If TRUE, the P port is running in SRAM mode. */ + cy_bool srammode ; + /* If TRUE, the P port is synchronous, otherwise async */ + cy_bool sync ; + /* If TRUE, DMA req will be delivered via the interrupt signal */ + cy_bool dmaintr ; + /* Mode for the DACK# signal */ + cy_as_device_dack_mode dackmode ; + /* If TRUE, the DRQ line is active high, otherwise active low */ + cy_bool drqpol ; + /* If TRUE, the DACK line is active high, otherwise active low */ + cy_bool dackpol ; + /* If TRUE, the clock is connected to a crystal, otherwise it is + connected to a clock */ + cy_bool crystal ; +} cy_as_device_config ; + + +/* Summary + Specifies a resource that can be owned by either the West Bridge + device or by the processor. + + Description + This enumerated type identifies a resource that can be owned + either by the West Bridge device, or by the processor attached to + the P port of the West Bridge device. + + See Also + * CyAsMiscAcquireResource + * CyAsMiscReleaseResource +*/ +typedef enum cy_as_resource_type { + cy_as_bus_u_s_b = 0, /* The USB D+ and D- pins */ + cy_as_bus_1 = 1, /* The SDIO bus */ + cy_as_bus_0 = 2 /* The NAND bus (not implemented) */ +} cy_as_resource_type; + +/* Summary + Specifies the reset type for a software reset operation. + + Description + When the West Bridge device is reset, there are two types of + reset that arE possible. This type indicates the type of reset + requested. + + Notes + Both of these reset types are software based resets; and are + distinct from a chip level HARD reset that is applied through + the reset pin on the West Bridge. + + The CyAsResetSoft type resets only the on-chip micro-controller + in the West Bridge. In this case, the previously loaded firmware + will continue running. However, the Storage and USB stack + operations will need to be restarted, as any state relating to + these would have been lost. + + The CyAsResetHard type resets the entire West Bridge chip, and will + need a fresh configuration and firmware download. + + See Also + * + */ + +typedef enum cy_as_reset_type { + /* Just resets the West Bridge micro-controller */ + cy_as_reset_soft, + /* Resets entire device, firmware must be reloaded and + the west bridge device must be re-initialized */ + cy_as_reset_hard +} cy_as_reset_type; + + + +/* Summary + This type specifies the polarity of the SD power pin. + + Description + Sets the SD power pin ( port C, bit 6) to active low or + active high. + +*/ + +typedef enum cy_as_misc_signal_polarity { + cy_as_misc_active_high, + cy_as_misc_active_low + +} cy_as_misc_signal_polarity ; + + + +/* Summary + This type specifies the type of the data returned by a Function + Callback. + + Description + CY_FUNCT_CB_NODATA - This callback does not return any additional + information in the data field. + CY_FUNCT_CB_DATA - The data field is used, and the CyAsFunctCBType + will also contain the type of this data. + + See Also + CyAsFunctionCallback +*/ +typedef enum cy_as_funct_c_b_type { + CY_FUNCT_CB_INVALID = 0x0U, + /* Data from a CyAsMiscGetFirmwareVersion call. */ + CY_FUNCT_CB_MISC_GETFIRMWAREVERSION, + /* Data from a CyAsMiscHeartBeatControl call. */ + CY_FUNCT_CB_MISC_HEARTBEATCONTROL, + /* Data from a CyAsMiscAcquireResource call. */ + CY_FUNCT_CB_MISC_ACQUIRERESOURCE, + /* Data from a CyAsMiscReadMCURegister call. */ + CY_FUNCT_CB_MISC_READMCUREGISTER, + /* Data from a CyAsMiscWriteMCURegister call. */ + CY_FUNCT_CB_MISC_WRITEMCUREGISTER, + /* Data from a CyAsMiscSetTraceLevel call. */ + CY_FUNCT_CB_MISC_SETTRACELEVEL, + /* Data from a CyAsMiscStorageChanged call. */ + CY_FUNCT_CB_MISC_STORAGECHANGED, + /* Data from a CyAsMiscGetGpioValue call. */ + CY_FUNCT_CB_MISC_GETGPIOVALUE, + /* Data from a CyAsMiscSetGpioValue call. */ + CY_FUNCT_CB_MISC_SETGPIOVALUE, + /* Data from a CyAsMiscDownloadFirmware call. */ + CY_FUNCT_CB_MISC_DOWNLOADFIRMWARE, + /* Data from a CyAsMiscEnterStandby call. */ + CY_FUNCT_CB_MISC_ENTERSTANDBY, + /* Data from a CyAsMiscEnterSuspend call. */ + CY_FUNCT_CB_MISC_ENTERSUSPEND, + /* Data from a CyAsMiscLeaveSuspend call. */ + CY_FUNCT_CB_MISC_LEAVESUSPEND, + /* Data from a CyAsMiscReset call. */ + CY_FUNCT_CB_MISC_RESET, + /* Data from a CyAsMiscSetLowSpeedSDFreq or + * CyAsMiscSetHighSpeedSDFreq call. */ + CY_FUNCT_CB_MISC_SETSDFREQ, + /* Data from a CyAsMiscSwitchPnandMode call */ + CY_FUNCT_CB_MISC_RESERVELNABOOTAREA, + /* Data from a CyAsMiscSetSDPowerPolarity call */ + CY_FUNCT_CB_MISC_SETSDPOLARITY, + + /* Data from a CyAsStorageStart call. */ + CY_FUNCT_CB_STOR_START, + /* Data from a CyAsStorageStop call. */ + CY_FUNCT_CB_STOR_STOP, + /* Data from a CyAsStorageClaim call. */ + CY_FUNCT_CB_STOR_CLAIM, + /* Data from a CyAsStorageRelease call. */ + CY_FUNCT_CB_STOR_RELEASE, + /* Data from a CyAsStorageQueryMedia call. */ + CY_FUNCT_CB_STOR_QUERYMEDIA, + /* Data from a CyAsStorageQueryBus call. */ + CY_FUNCT_CB_STOR_QUERYBUS, + /* Data from a CyAsStorageQueryDevice call. */ + CY_FUNCT_CB_STOR_QUERYDEVICE, + /* Data from a CyAsStorageQueryUnit call. */ + CY_FUNCT_CB_STOR_QUERYUNIT, + /* Data from a CyAsStorageDeviceControl call. */ + CY_FUNCT_CB_STOR_DEVICECONTROL, + /* Data from a CyAsStorageSDRegisterRead call. */ + CY_FUNCT_CB_STOR_SDREGISTERREAD, + /* Data from a CyAsStorageCreatePartition call. */ + CY_FUNCT_CB_STOR_PARTITION, + /* Data from a CyAsStorageGetTransferAmount call. */ + CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT, + /* Data from a CyAsStorageErase call. */ + CY_FUNCT_CB_STOR_ERASE, + /* Data from a CyAsStorageCancelAsync call. */ + CY_FUNCT_CB_ABORT_P2S_XFER, + /* Data from a CyAsUsbStart call. */ + CY_FUNCT_CB_USB_START, + /* Data from a CyAsUsbStop call. */ + CY_FUNCT_CB_USB_STOP, + /* Data from a CyAsUsbConnect call. */ + CY_FUNCT_CB_USB_CONNECT, + /* Data from a CyAsUsbDisconnect call. */ + CY_FUNCT_CB_USB_DISCONNECT, + /* Data from a CyAsUsbSetEnumConfig call. */ + CY_FUNCT_CB_USB_SETENUMCONFIG, + /* Data from a CyAsUsbGetEnumConfig call. */ + CY_FUNCT_CB_USB_GETENUMCONFIG, + /* Data from a CyAsUsbSetDescriptor call. */ + CY_FUNCT_CB_USB_SETDESCRIPTOR, + /* Data from a CyAsUsbGetDescriptor call. */ + CY_FUNCT_CB_USB_GETDESCRIPTOR, + /* Data from a CyAsUsbCommitConfig call. */ + CY_FUNCT_CB_USB_COMMITCONFIG, + /* Data from a CyAsUsbGetNak call. */ + CY_FUNCT_CB_USB_GETNAK, + /* Data from a CyAsUsbGetStall call. */ + CY_FUNCT_CB_USB_GETSTALL, + /* Data from a CyAsUsbSignalRemoteWakeup call. */ + CY_FUNCT_CB_USB_SIGNALREMOTEWAKEUP, + /* Data from a CyAnUsbClearDescriptors call. */ + CY_FUNCT_CB_USB_CLEARDESCRIPTORS, + /* Data from a CyAnUsbSetMSReportThreshold call. */ + CY_FUNCT_CB_USB_SET_MSREPORT_THRESHOLD, + /* Data from a CyAsMTPStart call. */ + CY_FUNCT_CB_MTP_START, + /* Data from a CyAsMTPStop call. */ + CY_FUNCT_CB_MTP_STOP, + /* Data from a CyAsMTPInitSendObject call. */ + CY_FUNCT_CB_MTP_INIT_SEND_OBJECT, + /* Data from a CyAsMTPCancelSendObject call. */ + CY_FUNCT_CB_MTP_CANCEL_SEND_OBJECT, + /* Data from a CyAsMTPInitGetObject call. */ + CY_FUNCT_CB_MTP_INIT_GET_OBJECT, + /* Data from a CyAsMTPCancelGetObject call. */ + CY_FUNCT_CB_MTP_CANCEL_GET_OBJECT, + /* Data from a CyAsMTPSendBlockTable call. */ + CY_FUNCT_CB_MTP_SEND_BLOCK_TABLE, + /* Data from a CyAsMTPStopStorageOnly call. */ + CY_FUNCT_CB_MTP_STOP_STORAGE_ONLY, + CY_FUNCT_CB_NODATA = 0x40000000U, + CY_FUNCT_CB_DATA = 0x20000000U +} cy_as_funct_c_b_type ; + +/* Summary + This type specifies the general West Bridge function callback. + + Description + This callback is supplied as an argument to all asynchronous + functions in the API. It iS called after the asynchronous function + has completed. + + See Also + CyAsFunctCBType +*/ +typedef void (*cy_as_function_callback)( + cy_as_device_handle handle, + cy_as_return_status_t status, + uint32_t client, + cy_as_funct_c_b_type type, + void *data) ; + +/* Summary + This type specifies the general West Bridge event that has + occurred. + + Description + This type is used in the West Bridge misc callback function to + indicate the type of callback. + + See Also +*/ +typedef enum cy_as_misc_event_type { + /* This event is sent when West Bridge has finished + initialization and is ready to respond to API calls. */ + cy_as_event_misc_initialized = 0, + + /* This event is sent when West Bridge has left the + standby state and is ready to respond to commands again. */ + cy_as_event_misc_awake, + + /* This event is sent periodically from the firmware + to the processor. */ + cy_as_event_misc_heart_beat, + + /* This event is sent when the West Bridge has left the + suspend mode and is ready to respond to commands + again. */ + cy_as_event_misc_wakeup, + + /* This event is sent when the firmware image downloaded + cannot run on the active west bridge device. */ + cy_as_event_misc_device_mismatch +} cy_as_misc_event_type ; + +/* Summary + This type is the type of a callback function that is called when a + West Bridge misc event occurs. + + Description + At times West Bridge needs to inform the P port processor of events + that have occurred. These events are asynchronous to the thread of + control on the P port processor and as such are generally delivered + via a callback function that is called as part of an interrupt + handler. This type defines the type of function that must be provided + as a callback function for West Bridge misc events. + + See Also + * CyAsMiscEventType +*/ +typedef void (*cy_as_misc_event_callback)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The event type being reported */ + cy_as_misc_event_type ev, + /* The data assocaited with the event being reported */ + void *evdata +) ; + +#ifndef __doxygen__ +/* Summary + This enum provides info of various firmware trace levels. + + Description + + See Also + * CyAsMiscSetTraceLevel +*/ +enum { + CYAS_FW_TRACE_LOG_NONE = 0, /* Log nothing. */ + CYAS_FW_TRACE_LOG_STATE, /* Log state information. */ + CYAS_FW_TRACE_LOG_CALLS, /* Log function calls. */ + CYAS_FW_TRACE_LOG_STACK_TRACE, /* Log function calls with args. */ + CYAS_FW_TRACE_MAX_LEVEL /* Max trace level sentinel. */ +}; +#endif + +/* Summary + This enum lists the controllable GPIOs of the West Bridge device. + + Description + The West Bridge device has GPIOs that can be used for user defined functions. + This enumeration lists the GPIOs that are available on the device. + + Notes + All of the GPIOs except UVALID can only be accessed when using West Bridge + firmware images that support only SD/MMC/MMC+ storage devices. This + functionality is not supported in firmware images that support NAND + storage. + + See Also + * CyAsMiscGetGpioValue + * CyAsMiscSetGpioValue + */ +typedef enum { + cy_as_misc_gpio_0 = 0, /* GPIO[0] pin */ + cy_as_misc_gpio_1, /* GPIO[1] pin */ + cy_as_misc_gpio__nand_CE, /* NAND_CE pin, output only */ + cy_as_misc_gpio__nand_CE2, /* NAND_CE2 pin, output only */ + cy_as_misc_gpio__nand_WP, /* NAND_WP pin, output only */ + cy_as_misc_gpio__nand_CLE, /* NAND_CLE pin, output only */ + cy_as_misc_gpio__nand_ALE, /* NAND_ALE pin, output only */ + /* SD_POW pin, output only, do not drive low while storage is active */ + cy_as_misc_gpio_SD_POW, + cy_as_misc_gpio_U_valid /* UVALID pin */ +} cy_as_misc_gpio; + +/* Summary + This enum lists the set of clock frequencies that are supported for + working with low speed SD media. + + Description + West Bridge firmware uses a clock frequency less than the maximum + possible rate for low speed SD media. This can be changed to a + setting equal to the maximum frequency as desired by the user. This + enumeration lists the different frequency settings that are + supported. + + See Also + * CyAsMiscSetLowSpeedSDFreq + */ +typedef enum cy_as_low_speed_sd_freq { + /* Approx. 21.82 MHz, default value */ + CY_AS_SD_DEFAULT_FREQ = 0, + /* 24 MHz */ + CY_AS_SD_RATED_FREQ +} cy_as_low_speed_sd_freq ; + +/* Summary + This enum lists the set of clock frequencies that are supported + for working with high speed SD media. + + Description + West Bridge firmware uses a 48 MHz clock by default to interface + with high speed SD/MMC media. This can be changed to 24 MHz if + so desired by the user. This enum lists the different frequencies + that are supported. + + See Also + * CyAsMiscSetHighSpeedSDFreq + */ +typedef enum cy_as_high_speed_sd_freq { + CY_AS_HS_SD_FREQ_48, /* 48 MHz, default value */ + CY_AS_HS_SD_FREQ_24 /* 24 MHz */ +} cy_as_high_speed_sd_freq ; + +/* Summary + Struct encapsulating all information returned by the + CyAsMiscGetFirmwareVersion call. + + Description + This struct encapsulates all return values from the asynchronous + CyAsMiscGetFirmwareVersion call, so that a single data argument + can be passed to the user provided callback function. + + See Also + * CyAsMiscGetFirmwareVersion + */ +typedef struct cy_as_get_firmware_version_data { + /* Return value for major version number for the firmware */ + uint16_t major; + /* Return value for minor version number for the firmware */ + uint16_t minor; + /* Return value for build version number for the firmware */ + uint16_t build; + /* Return value for media types supported in the current firmware */ + uint8_t media_type; + /* Return value to indicate the release or debug mode of firmware */ + cy_bool is_debug_mode; +} cy_as_get_firmware_version_data ; + + +/***************************** + * West Bridge Functions + *****************************/ + +/* Summary + This function creates a new West Bridge device and returns a + handle to the device. + + Description + This function initializes the API object that represents the West + Bridge device and returns a handle to this device. This handle is + required for all West Bridge related functions to identify the + specific West Bridge device. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_OUT_OF_MEMORY +*/ +EXTERN cy_as_return_status_t +cy_as_misc_create_device( + /* Return value for handle to created device */ + cy_as_device_handle *handle_p, + /* The HAL specific tag for this device */ + cy_as_hal_device_tag tag + ) ; + +/* Summary + This functions destroys a previously created West Bridge device. + + Description + When an West Bridge device is created, an opaque handle is returned + that represents the device. This function destroys that handle and + frees all resources associated with the handle. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_STILL_RUNNING - The USB or STORAGE stacks are still + * running, they must be stopped before the device can be destroyed + * CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED - the HAL layer failed to + * destroy a sleep channel +*/ +EXTERN cy_as_return_status_t +cy_as_misc_destroy_device( + /* Handle to the device to destroy */ + cy_as_device_handle handle + ) ; + +/* Summary + This function initializes the hardware for basic communication with + West Bridge. + + Description + This function intializes the hardware to establish basic + communication with the West Bridge device. This is always the first + function called to initialize communication with the West Bridge + device. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - the basic initialization was completed + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_IN_STANDBY + * CY_AS_ERROR_ALREADY_RUNNING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_NO_ANTIOCH - cannot find the West Bridge device + * CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED - + * the HAL layer falied to create a sleep channel + + See Also + * CyAsDeviceConfig +*/ +EXTERN cy_as_return_status_t +cy_as_misc_configure_device( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Configuration information */ + cy_as_device_config *config_p + ) ; + +/* Summary + This function returns non-zero if West Bridge is in standby and + zero otherwise. + + Description + West Bridge supports a standby mode. This function is used to + query West Bridge to determine if West Bridge is in a standby + mode. + + * Valid In Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE +*/ +EXTERN cy_as_return_status_t +cy_as_misc_in_standby( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Return value for standby state */ + cy_bool *standby + ) ; + +/* Summary + This function downloads the firmware to West Bridge device. + + Description + This function downloads firmware from a given location and with a + given size to the West Bridge device. After the firmware is + downloaded the West Bridge device is moved out of configuration + mode causing the firmware to be executed. It is an error to call + this function when the device is not in configuration mode. The + device is in configuration mode on power up and may be placed in + configuration mode after power up with a hard reset. + + Notes + The firmware must be on a word align boundary. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the firmware was sucessfully downloaded + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * was not configured + * CY_AS_ERROR_NOT_IN_CONFIG_MODE + * CY_AS_ERROR_INVALID_SIZE - the size of the firmware + * exceeded 32768 bytes + * CY_AS_ERROR_ALIGNMENT_ERROR + * CY_AS_ERROR_IN_STANDBY - trying to download + * while in standby mode + * CY_AS_ERROR_TIMEOUT + + See Also + * CyAsMiscReset +*/ +EXTERN cy_as_return_status_t +cy_as_misc_download_firmware( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Pointer to the firmware to be downloaded */ + const void *fw_p, + /* The size of the firmware in bytes */ + uint16_t size, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + + +/* Summary + This function returns the version number of the firmware running in + the West Bridge device. + + Description + This function queries the West Bridge device and retreives the + firmware version number. If the firmware is not loaded an error is + returned indicated no firmware has been loaded. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the firmware version number was retreived + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been downloaded + * to the device + * CY_AS_ERROR_IN_STANDBY + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response + * from the West Bridge firmware +*/ +EXTERN cy_as_return_status_t +cy_as_misc_get_firmware_version( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Return values indicating the firmware version. */ + cy_as_get_firmware_version_data *data, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +#if !defined(__doxygen__) + +/* Summary + This function reads and returns the contents of an MCU accessible + register on the West Bridge. + + Description + This function requests the firmware to read and return the contents + of an MCU accessible register through the mailboxes. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the register content was retrieved. + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response + * from the West Bridge firmware + * CY_AS_ERROR_INVALID_RESPONSE - the firmware build does not + * support this command. +*/ +EXTERN cy_as_return_status_t +cy_as_misc_read_m_c_u_register( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Address of the register to read */ + uint16_t address, + /* Return value for the MCU register content */ + uint8_t *value, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function writes to an MCU accessible register on the West Bridge. + + Description + This function requests the firmware to write a specified value to an + MCU accessible register through the mailboxes. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + This function is only for internal use by the West Bridge API layer. + Calling this function directly can cause device malfunction. + + Returns + * CY_AS_ERROR_SUCCESS - the register content was updated. + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response + * from the West Bridge firmware + * CY_AS_ERROR_INVALID_RESPONSE - the firmware build does not support + * this command. +*/ +EXTERN cy_as_return_status_t +cy_as_misc_write_m_c_u_register( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Address of the register to write */ + uint16_t address, + /* Mask to be applied on the register contents. */ + uint8_t mask, + /* Data to be ORed with the register contents. */ + uint8_t value, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +#endif + +/* Summary + This function will reset the West Bridge device and software API. + + Description + This function will reset the West Bridge device and software API. + The reset operation can be a hard reset or a soft reset. A hard + reset will reset all aspects of the West Bridge device. The device + will enter the configuration state and the firmware will have to be + reloaded. The device will also have to be re-initialized. A soft + reset just resets the West Bridge micro-controller. + + * Valid In Asynchronous Callback: NO + + Notes + When a hard reset is issued, the firmware that may have been + previously loaded will be lost and any configuration information set + via CyAsMiscConfigureDevice() will be lost. This will be reflected + in the API maintained state of the device. In order to re-establish + communications with the West Bridge device, CyAsMiscConfigureDevice() + and CyAsMiscDownloadFirmware() must be called again. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the device has been reset + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_NOT_YET_SUPPORTED - current soft reset is not supported + * CY_AS_ERROR_ASYNC_PENDING - Reset is unable to flush pending async + * reads/writes in polling mode. + + + See Also + * CyAsMiscReset +*/ +EXTERN cy_as_return_status_t +cy_as_misc_reset( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The type of reset to perform */ + cy_as_reset_type type, + /* If true, flush all pending writes to mass storage + before performing the reset. */ + cy_bool flush, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function acquires a given resource. + + Description + There are resources in the system that are shared between the + West Bridge device and the processor attached to the P port of + the West Bridge device. This API provides a mechanism for the + P port processor to acquire ownership of a resource. + + Notes + The ownership of the resources controlled by CyAsMiscAcquireResource() + and CyAsMiscReleaseResource() defaults to a known state at hardware + reset. After the firmware is loaded and begins execution the state of + these resources may change. At any point if the P Port processor needs + to acquire a resource it should do so explicitly to be sure of + ownership. + + Returns + * CY_AS_ERROR_SUCCESS - the p port sucessfully acquired the + * resource of interest + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_INVALID_RESOURCE + * CY_AS_ERROR_RESOURCE_ALREADY_OWNED - the p port already + * owns this resource + * CY_AS_ERROR_NOT_ACQUIRED - the resource cannot be acquired + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a + * response from the West Bridge firmware + + See Also + * CyAsResourceType +*/ +EXTERN cy_as_return_status_t +cy_as_misc_acquire_resource( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The resource to acquire */ + cy_as_resource_type *resource, + /* If true, force West Bridge to release the resource */ + cy_bool force, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function releases a given resource. + + Description + There are resources in the system that are shared between the + West Bridge device and the processor attached to the P port of + the West Bridge device. This API provides a mechanism for the + P port processor to release a resource that has previously been + acquired via the CyAsMiscAcquireResource() call. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - the p port sucessfully released + * the resource of interest + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_INVALID_RESOURCE + * CY_AS_ERROR_RESOURCE_NOT_OWNED - the p port does not own the + * resource of interest + + See Also + * CyAsResourceType + * CyAsMiscAcquireResource +*/ +EXTERN cy_as_return_status_t +cy_as_misc_release_resource( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The resource to release */ + cy_as_resource_type resource + ) ; + +#ifndef __doxygen__ +/* Summary + This function sets the trace level for the West Bridge firmware. + + Description + The West Bridge firmware has the ability to store information + about the state and execution path of the firmware on a mass storage + device attached to the West Bridge device. This function configures + the specific mass storage device to be used and the type of information + to be stored. This state information is used for debugging purposes + and must be interpreted by a Cypress provided tool. + + *Trace Level* + The trace level indicates the amount of information to output. + * 0 = no trace information is output + * 1 = state information is output + * 2 = function call information is output + * 3 = function call, arguments, and return value information is output + + * Valid In Asynchronous Callback: NO + + Notes + The media device and unit specified in this call will be overwritten + and any data currently stored on this device and unit will be lost. + + * NOT IMPLEMENTED YET + + Returns + * CY_AS_ERROR_SUCCESS - the trace configuration has been + * sucessfully changed + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified does not exist + * CY_AS_ERROR_INVALID_TRACE_LEVEL - the trace level requested + * does not exist + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a + * response from the West Bridge firmware +*/ +EXTERN cy_as_return_status_t +cy_as_misc_set_trace_level( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The trace level */ + uint8_t level, + /* The bus for the output */ + cy_as_bus_number_t bus, + /* The device for the output */ + uint32_t device, + /* The unit for the output */ + uint32_t unit, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; +#endif + +/* Summary + This function places West Bridge into the low power standby mode. + + Description + This function places West Bridge into a low power (sleep) mode, and + cannot be called while the USB stack is active. This function first + instructs the West Bridge firmware that the device is about to be + placed into sleep mode. This allows West Bridge to complete any pending + storage operations. After the West Bridge device has responded that + pending operations are complete, the device is placed in standby mode. + + There are two methods of placing the device in standby mode. If the + WAKEUP pin of the West Bridge is connected to a GPIO on the processor, + the pin is de-asserted (via the HAL layer) and West Bridge enters into + a sleep mode. If the WAKEUP pin is not accessible, the processor can + write into the power management control/status register on the West + Bridge to put the device into sleep mode. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function completed and West Bridge + * is in sleep mode + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_ALREADY_STANDBY - the West Bridge device is already + * in sleep mode + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a response + * from the West Bridge firmware + * CY_AS_ERROR_NOT_SUPPORTED - the HAL layer does not support changing + * the WAKEUP pin + * CY_AS_ERROR_USB_RUNNING - The USB stack is still running when the + * EnterStandby call is made + * CY_AS_ERROR_ASYNC_PENDING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_SETTING_WAKEUP_PIN + * CY_AS_ERROR_ASYNC_PENDING - In polling mode EnterStandby can not + * be called until all pending storage read/write requests have + * finished. + + See Also + * CyAsMiscLeaveStandby +*/ +EXTERN cy_as_return_status_t +cy_as_misc_enter_standby_e_x_u( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* If true, use the wakeup pin, otherwise use the register */ + cy_bool pin, + /* Set true to enable specific usages of the + UVALID signal, please refer to AN xx or ERRATA xx */ + cy_bool uvalid_special, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function is provided for backwards compatibility. + + Description + Calling this function is the same as calling CyAsMiscEnterStandbyEx + with True for the lowpower parameter. + + See Also + * CyAsMiscEnterStandbyEx +*/ +EXTERN cy_as_return_status_t +cy_as_misc_enter_standby(cy_as_device_handle handle, + cy_bool pin, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function brings West Bridge out of sleep mode. + + Description + This function asserts the WAKEUP pin (via the HAL layer). This + brings the West Bridge out of the sleep state and allows the + West Bridge firmware to process the event causing the wakeup. + When all processing associated with the wakeup is complete, a + callback function is called to tell the P port software that + the firmware processing associated with wakeup is complete. + + * Valid In Asynchronous Callback: NO + + Returns: + * CY_AS_ERROR_SUCCESS - the function completed and West Bridge + * is in sleep mode + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_SETTING_WAKEUP_PIN + * CY_AS_ERROR_NOT_IN_STANDBY - the West Bridge device is not in + * the sleep state + * CY_AS_ERROR_TIMEOUT - there was a timeout waiting for a + * response from the West Bridge firmware + * CY_AS_ERROR_NOT_SUPPORTED - the HAL layer does not support + * changing the WAKEUP pin + + See Also + * CyAsMiscEnterStandby +*/ +EXTERN cy_as_return_status_t +cy_as_misc_leave_standby( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The resource causing the wakeup */ + cy_as_resource_type resource + ) ; + +/* Summary + This function registers a callback function to be called when an + asynchronous West Bridge MISC event occurs. + + Description + When asynchronous misc events occur, a callback function can be + called to alert the calling program. This functions allows the + calling program to register a callback. + + * Valid In Asynchronous Callback: NO + + Returns: + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE +*/ +EXTERN cy_as_return_status_t +cy_as_misc_register_callback( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The function to call */ + cy_as_misc_event_callback callback + ) ; + +/* Summary + This function sets the logging level for log messages. + + Description + The API can print messages via the CyAsHalPrintMessage capability. + This function sets the level of detail seen when printing messages + from the API. + + * Valid In Asynchronous Callback:NO +*/ +EXTERN void +cy_as_misc_set_log_level( + /* Level to set, 0 is fewer messages, 255 is all */ + uint8_t level + ) ; + + +/* Summary + This function tells West Bridge that SD or MMC media has been + inserted or removed. + + Description + In some hardware configurations, SD or MMC media detection is + handled outside of the West Bridge device. This function is called + when a change is detected to inform the West Bridge firmware to check + for storage media changes. + + * Valid In Asynchronous Callback: NO + + Returns: + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_IN_STANDBY + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsMiscStorageChanged + +*/ +EXTERN cy_as_return_status_t +cy_as_misc_storage_changed( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function instructs the West Bridge firmware to start/stop + sending periodic heartbeat messages to the processor. + + Description + The West Bridge firmware can send heartbeat messages through the + mailbox register once every 500 ms. This message can be an overhead + as it causes regular Mailbox interrupts to happen, and is turned + off by default. The message can be used to test and verify that the + West Bridge firmware is alive. This API can be used to enable or + disable the heartbeat message. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - the function completed successfully + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured yet + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded to + * the West Bridge device + +*/ +EXTERN cy_as_return_status_t +cy_as_misc_heart_beat_control( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Message enable/disable selection */ + cy_bool enable, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function gets the current state of a GPIO pin on the + West Bridge device. + + Description + The West Bridge device has GPIO pins that can be used for user + defined functions. This function gets the current state of the + specified GPIO pin. Calling this function will configure the + corresponding pin as an input. + + * Valid In Asynchronous Callback: NO + + Notes + Only GPIO[0], GPIO[1] and UVALID pins can be used as GP inputs. + Of these pins, only the UVALID pin is supported by firmware images + that include NAND storage support. + + Returns + * CY_AS_ERROR_SUCCESS - the function completed successfully + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured yet + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded + * to the West Bridge device + * CY_AS_ERROR_BAD_INDEX - an invalid GPIO was specified + * CY_AS_ERROR_NOT_SUPPORTED - this feature is not supported + * by the firmware + + See Also + * CyAsMiscGpio + * CyAsMiscSetGpioValue + */ +EXTERN cy_as_return_status_t +cy_as_misc_get_gpio_value( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Id of the GPIO pin to query */ + cy_as_misc_gpio pin, + /* Current value of the GPIO pin */ + uint8_t *value, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + This function updates the state of a GPIO pin on the West + Bridge device. + + Description + The West Bridge device has GPIO pins that can be used for + user defined functions. This function updates the output + value driven on a specified GPIO pin. Calling this function + will configure the corresponding pin as an output. + + * Valid In Asynchronous Callback: NO + + Notes + All of the pins listed under CyAsMiscGpio can be used as GP + outputs. This feature is note supported by firmware images + that include NAND storage device support. + + Returns + * CY_AS_ERROR_SUCCESS - the function completed successfully + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured yet + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded + * to the West Bridge device + * CY_AS_ERROR_BAD_INDEX - an invalid GPIO was specified + * CY_AS_ERROR_NOT_SUPPORTED - this feature is not supported + * by firmware. + + See Also + * CyAsMiscGpio + * CyAsMiscGetGpioValue + */ +EXTERN cy_as_return_status_t +cy_as_misc_set_gpio_value( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Id of the GPIO pin to set */ + cy_as_misc_gpio pin, + /* Value to be set on the GPIO pin */ + uint8_t value, + /* Callback to call when the operation is complete. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + Set the West Bridge device in the low power suspend mode. + + Description + The West Bridge device has a low power suspend mode where the USB + core and the internal microcontroller are powered down. This + function sets the West Bridge device into this low power mode. + This mode can only be entered when there is no active USB + connection; i.e., when USB has not been connected or is suspended; + and there are no pending USB or storage asynchronous calls. The + device will exit the suspend mode and resume handling USB and + processor requests when any activity is detected on the CE#, D+/D- + or GPIO[0] lines. + + * Valid In Asynchronous Callback: NO + + Notes + The GPIO[0] pin needs to be configured as an input for the gpio + wakeup to work. This flag should not be enabled if the pin is + being used as a GP output. + + Returns + * CY_AS_ERROR_SUCCESS - the device was placed in suspend mode. + * CY_AS_ERROR_INVALID_HANDLE - the West Bridge handle passed + * in is invalid. + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * yet been configured. + * CY_AS_ERROR_NO_FIRMWARE - no firmware has been downloaded + * to the device. + * CY_AS_ERROR_IN_STANDBY - the device is already in sleep mode. + * CY_AS_ERROR_USB_CONNECTED - the USB connection is active. + * CY_AS_ERROR_ASYNC_PENDING - asynchronous storage/USB calls + * are pending. + * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for + * the operation. + * CY_AS_ERROR_INVALID_RESPONSE - command not recognised by + * firmware. + + See Also + * CyAsMiscLeaveSuspend + */ +EXTERN cy_as_return_status_t +cy_as_misc_enter_suspend( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Control the USB wakeup source */ + cy_bool usb_wakeup_en, + /* Control the GPIO[0] wakeup source */ + cy_bool gpio_wakeup_en, + /* Callback to call when suspend mode entry is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + Wake up the West Bridge device from suspend mode. + + Description + This call wakes up the West Bridge device from suspend mode, + and makes it ready for accepting other commands from the API. + A CyAsEventMiscWakeup event will be delivered to the callback + registered with CyAsMiscRegisterCallback to indicate that the + wake up is complete. + + The CyAsEventMiscWakeup event will also be delivered if the + wakeup happens due to USB or GPIO activity. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - the device was woken up from + * suspend mode. + * CY_AS_ERROR_INVALID_HANDLE - invalid device handle + * passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has + * not been configured. + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been + * downloaded to the device. + * CY_AS_ERROR_NOT_IN_SUSPEND - the device is not in + * suspend mode. + * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory + * for the operation. + * CY_AS_ERROR_TIMEOUT - failed to wake up the device. + + See Also + * CyAsMiscEnterSuspend + */ +EXTERN cy_as_return_status_t +cy_as_misc_leave_suspend( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Callback to call when device has resumed operation. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + Reserve first numzones zones of nand device for storing + processor boot image. LNA firmware works on the first + numzones zones of nand to enable the processor to boot. + + Description + This function reserves first numzones zones of nand device + for storing processor boot image. This fonction MUST be + completed before starting the storage stack for the setting + to be taken into account. + + * Valid In Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_SUCCESS- zones are reserved. + +*/ +EXTERN cy_as_return_status_t +cy_as_misc_reserve_l_n_a_boot_area( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* number of nand zones to reserve */ + uint8_t numzones, + /* Callback to call when device has resumed operation. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* Summary + Select the clock frequency to be used when talking to low + speed (non-high speed) SD media. + + Description + West Bridge firmware uses a clock frequency less than the + maximum possible rate for low speed SD media. This function + selects the frequency setting from between the default speed + and the maximum speed. This fonction MUST be completed before + starting the storage stack for the setting to be taken into + account. + + * Valid in Asynchronous Callback: Yes (if cb is non-zero) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the operation completed successfully. + * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been + * configured. + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded + * to the device. + * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for + * the operation. + * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power suspend + * mode. + * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting + * desired. + * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to + * the operation. + * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not support + * the operation. + + See Also + * CyAsLowSpeedSDFreq + */ +EXTERN cy_as_return_status_t +cy_as_misc_set_low_speed_sd_freq( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Frequency setting desired for low speed SD cards */ + cy_as_low_speed_sd_freq setting, + /* Callback to call on completion */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + Select the clock frequency to be used when talking to high speed + SD/MMC media. + + Description + West Bridge firmware uses a 48 MHz clock to interface with high + speed SD/MMC media. This clock rate can be restricted to 24 MHz + if desired. This function selects the frequency setting to be + used. This fonction MUST be completed before starting the storage + stack for the setting to be taken into account. + + * Valid in Asynchronous Callback: Yes (if cb is non-zero) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the operation completed successfully. + * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been + * configured. + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded to + * the device. + * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for the + * operation. + * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power suspend mode. + * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting desired. + * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to the + * operation. + * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not support + * the operation. + + See Also + * CyAsLowSpeedSDFreq + */ +EXTERN cy_as_return_status_t +cy_as_misc_set_high_speed_sd_freq( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Frequency setting desired for high speed SD cards */ + cy_as_high_speed_sd_freq setting, + /* Callback to call on completion */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; +/* Summary + Select the polarity of the SD_POW output driven by West Bridge. + + Description + The SD_POW signal driven by West Bridge can be used to control + the supply of Vcc to the SD/MMC media connected to the device. + This signal is driven as an active high signal by default. This + function can be used to change the polarity of this signal if + required. This fonction MUST be completed before starting the + storage stack for the setting to be taken into account. + + * Valid in Asynchronous Callback: Yes (if cb is non-zero) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the operation completed successfully. + * CY_AS_ERROR_INVALID_HANDLE - invalid device handle passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been + * configured. + * CY_AS_ERROR_NO_FIRMWARE - firmware has not been downloaded + * to the device. + * CY_AS_ERROR_OUT_OF_MEMORY - failed to allocate memory for + * the operation. + * CY_AS_ERROR_IN_SUSPEND - West Bridge is in low power + * suspend mode. + * CY_AS_ERROR_INVALID_PARAMETER - invalid frequency setting + * desired. + * CY_AS_ERROR_TIMEOUT - West Bridge device did not respond to + * the operation. + * CY_AS_ERROR_INVALID_RESPONSE - active firmware does not + * support the operation. + + See Also + * CyAsMiscSignalPolarity + */ +EXTERN cy_as_return_status_t +cy_as_misc_set_sd_power_polarity( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Desired polarity setting to the SD_POW signal. */ + cy_as_misc_signal_polarity polarity, + /* Callback to call on completion. */ + cy_as_function_callback cb, + /* Client data to be passed to the callback. */ + uint32_t client + ) ; + +/* For supporting deprecated functions */ +#include "cyasmisc_dep.h" + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASMISC_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h new file mode 100644 index 000000000000..8b258efc0182 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc_dep.h @@ -0,0 +1,53 @@ +/* Cypress West Bridge API header file (cyasmisc_dep.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* This header will contain Antioch specific declaration + * of the APIs that are deprecated in Astoria SDK. This is + * for maintaining backward compatibility with prior releases + * of the Antioch SDK. + */ +#ifndef __INCLUDED_CYASMISC_DEP_H__ +#define __INCLUDED_CYASMISC_DEP_H__ + +#ifndef __doxygen__ + +EXTERN cy_as_return_status_t +cy_as_misc_acquire_resource_dep(cy_as_device_handle handle, + cy_as_resource_type resource, + cy_bool force); +EXTERN cy_as_return_status_t +cy_as_misc_get_firmware_version_dep(cy_as_device_handle handle, + uint16_t *major, + uint16_t *minor, + uint16_t *build, + uint8_t *media_type, + cy_bool *is_debug_mode); +EXTERN cy_as_return_status_t +cy_as_misc_set_trace_level_dep(cy_as_device_handle handle, + uint8_t level, + cy_as_media_type media, + uint32_t device, + uint32_t unit, + cy_as_function_callback cb, + uint32_t client); +#endif /*__doxygen*/ + +#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h new file mode 100644 index 000000000000..25af22e9a6b7 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmtp.h @@ -0,0 +1,646 @@ +/* Cypress West Bridge API header file (cyasmtp.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASMTP_H_ +#define _INCLUDED_CYASMTP_H_ + +#include "cyasmisc.h" + +#include "cyas_cplus_start.h" + +/*@@Media Transfer Protocol (MTP) Overview + Summary + The MTP API has been designed to allow MTP enabled West Bridge + devices to implement the MTP protocol while maintaining high + performance. West Bridge has the capability to enter into a + Turbo mode during a MTP SendObject or GetObject operation + enabling it to directly stream the data into or out of the + attached SD card with minimal involvement from the Processor. + + Description + The MTP API is designed to act as a pass through implementation + of the MTP protocol for all operations. Each MTP transaction + received from the Host is passed through West Bridge and along + to the Processor. The Processor can then respond to the + transaction and pass data and/or responses back to the Host + through West Bridge. + + The MTP API also allows for a high speed handling of MTP + SendObject and GetObject operations, referred to as Turbo MTP. + During a Turbo MTP operation West Bridge is responsible for + reading or writing the data for the MTP operation directly from + or to the SD card with minimal interaction from the Processor. + The is done by having the Processor transfer a Block Table + to West Bridge which contains the locations on the SD card that + need to be read or written. During the handling of a Turbo + Operation the Processor will then only periodically need to + send a new Block Table to West Bridge when the first is used up. + See the CyAsMTPInitSendObject and CyAsMTPInitGetObject functions + for more details. + + In order to enable the MTP API you must first have a MTP enabled + West Bridge loaded with MTP firmware. You then must start the USB + and Storage APIs before starting the MTP API. See CyAsMTPStart + for more details. +*/ + +/*@@Endpoints + Summary + When using MTP firmware endpoints 2 and 6 are dedicated + to bulk MTP traffic and endpoint 1 is available for MTP + events. + + Description + When using a MTP enabled West Brdige device endpoints 2 and + 6 are made available for use to implement the MTP protocol. + These endpoints have a few special restrictions noted below + but otherwise the existing USB APIs can be used normally with + these endpoints. + + 1. CyAsUsbSetNak, CyAsUsbClearNak, and CyAsUsbGetNak are + disabled for these endpoints + 2. During a turbo operation CyAsUsbSetStall, CyAsUsbClearStall, + and CyAsUsbGetStall are disabled. + +*/ + + +/* Summary + This constants defines the maximum number of + entries in the Block Table used to describe + the locations for Send/GetObject operations. + + See Also + * CyAsMtpSendObject + * CyAsMtpGetObject +*/ +#define CY_AS_MAX_BLOCK_TABLE_ENTRIES 64 + +/* Summary + Endpoint to be used for MTP reads from the USB host. + */ +#define CY_AS_MTP_READ_ENDPOINT (2) + +/* Summary + Endpoint to be used fro MTP writes to the USB host. + */ +#define CY_AS_MTP_WRITE_ENDPOINT (6) + +/****************************************** + * MTP Types + ******************************************/ + +/* Summary + The BlockTable used for turbo operations. + + Description + This struct is used to specify the blocks + to be used for both read/write and send/getObject + operations. + + The start block is a starting Logical Block Address + and num block is the number of blocks in that contiguous + region. + + start_blocks[i]->[-------] <- start_blocks[i] + num_blocks[i] + + If you need fewer than CY_AS_MAX_BLOCK_TABLE_ENTRIES + the remainder should be left empty. Empty is defined + as num_blocks equal to 0. + + See Also + * CyAsMTPInitSendObject + * CyAsMTPInitGetObject + +*/ +typedef struct cy_as_mtp_block_table { + uint32_t start_blocks[CY_AS_MAX_BLOCK_TABLE_ENTRIES] ; + uint16_t num_blocks[CY_AS_MAX_BLOCK_TABLE_ENTRIES] ; +} cy_as_mtp_block_table ; + +/* Summary + This type specifies the type of MTP event that has occurred. + + Description + MTP events are used to communicate that West Bridge has + either finished the handling of the given operation, or + that it requires additional data to complete the operation. + + In no case does West Bridge send any MTP protocol responses, + this always remain the responsibility of the client. + + See Also + * CyAsMTPInitSendObject + * CyAsMTPInitGetObject + * CyAsMTPSendBlockTable + +*/ +typedef enum cy_as_mtp_event { + /* This event is sent when West Bridge + has finished writing the data from a + send_object. west bridge will -not- send + the MTP response. */ + cy_as_mtp_send_object_complete, + + /* This event is sent when West Bridge + has finished sending the data for a + get_object operation. west bridge will + -not- send the MTP response. */ + cy_as_mtp_get_object_complete, + + /* This event is called when West Bridge + needs a new block_table. this is only a + notification, to transfer a block_table + to west bridge the cy_as_mtp_send_block_table + use the function. while west bridge is waiting + for a block_table during a send_object it + may need to NAK the endpoint. it is important + that the cy_as_mtp_send_block_table call is made + in a timely manner as eventually a delay + will result in an USB reset. this event has + no data */ + cy_as_mtp_block_table_needed +} cy_as_mtp_event ; + +/* Summary + Data for the CyAsMTPSendObjectComplete event. + + Description + Notification that a SendObject operation has been + completed. The status of the operation is given + (to distinguish between a cancelled and a success + for example) as well as the block count. The blocks + are used in order based on the current block table. + If more than one block table was used for a given + SendObject the count will include the total number + of blocks written. + + This callback will be made only once per SendObject + operation and it will only be called after all of + the data has been committed to the SD card. + + See Also + * CyAsMTPEvent + + */ +typedef struct cy_as_mtp_send_object_complete_data { + cy_as_return_status_t status ; + uint32_t byte_count ; + uint32_t transaction_id ; +} cy_as_mtp_send_object_complete_data ; + +/* Summary + Data for the CyAsMTPGetObjectComplete event. + + Description + Notification that a GetObject has finished. This + event allows the P side to know when to send the MTP + response for the GetObject operation. + + See Also + * CyAsMTPEvent + +*/ +typedef struct cy_as_mtp_get_object_complete_data { + cy_as_return_status_t status ; + uint32_t byte_count ; +} cy_as_mtp_get_object_complete_data ; + +/* Summary + MTP Event callback. + + Description + Callback used to communicate that a SendObject + operation has finished. + + See Also + * CyAsMTPEvent +*/ +typedef void (*cy_as_mtp_event_callback)( + cy_as_device_handle handle, + cy_as_mtp_event evtype, + void *evdata + ) ; + +/* Summary + This is the callback function called after asynchronous API + functions have completed. + + Description + When calling API functions from callback routines (interrupt + handlers usually) the async version of these functions must + be used. This callback is called when an asynchronous API + function has completed. +*/ +typedef void (*cy_as_mtp_function_callback)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The error status of the operation */ + cy_as_return_status_t status, + /* A client supplied 32 bit tag */ + uint32_t client +) ; + +/************************************** + * MTP Functions + **************************************/ + +/* Summary + This function starts the MTP stack. + + Description + Initializes West Bridge for MTP activity and registers the MTP + event callback. + + Before calling CyAsMTPStart, CyAsUsbStart and CyAsStorageStart must be + called (in either order). + + MTPStart must be called before the device is enumerated. Please + see the documentation for CyAsUsbSetEnumConfig and CyAsUsbEnumControl + for details on enumerating a device for MTP. + + Calling MTPStart will not affect any ongoing P<->S traffic. + + This requires a MTP firmware image to be loaded on West Bridge. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_IN_SUSPEND + * CY_AS_ERROR_INVALID_IN_CALLBACK + * CY_AS_ERROR_STARTSTOP_PENDING + * CY_AS_ERROR_NOT_RUNNING - CyAsUsbStart or CyAsStorageStart + * have not been called + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + + See Also + * CyAsMTPStop + * CyAsUsbStart + * CyAsStorageStart + * CyAsUsbSetEnumConfig + * CyAsUsbEnumControl +*/ +cy_as_return_status_t +cy_as_mtp_start( + cy_as_device_handle handle, + cy_as_mtp_event_callback event_c_b, + cy_as_function_callback cb, + uint32_t client + ) ; + + +/* Summary + This function stops the MTP stack. + + Description + Stops all MTP activity. Any ongoing transfers are + canceled. + + This will not cause a UsbDisconnect but all + MTP activity (both pass through and turbo) will + stop. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_IN_SUSPEND + * CY_AS_ERROR_INVALID_IN_CALLBACK + * CY_AS_ERROR_STARTSTOP_PENDING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + + See Also + * CyAsMTPStart +*/ +cy_as_return_status_t +cy_as_mtp_stop( + cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function sets up a Turbo SendObject operation. + + Description + Calling this function will setup West Bridge to + enable Tubo handling of the next SendObject + operation received. This will pass down the initial + block table to the firmware and setup a direct u->s + write for the SendObject operation. + + If this function is not called before a SendObject + operation is seen the SendObject operation and data + will be passed along to the P port like any other MTP + command. It would then be the responsibility of the + client to perform a normal StorageWrite call to + store the data on the SD card. N.B. This will be + very slow compared with the Turbo handling. + + The completion of this function only signals that + West Bridge has been set up to receive the next SendObject + operation. When the SendObject operation has been fully + handled and the data written to the SD card a separate + event will be triggered. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_IN_SUSPEND + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_ASYNC_PENDING + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + + See Also + * CyAsMTPCancelSendObject + * CyAsMTPInitGetObject + * CyAsMTPEvent + * CyAsMTPSendBlockTable +*/ +cy_as_return_status_t +cy_as_mtp_init_send_object( + cy_as_device_handle handle, + cy_as_mtp_block_table *blk_table, + uint32_t num_bytes, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function cancels an ongoing MTP operation. + + Description + Causes West Bridge to cancel an ongoing SendObject + operation. Note this is only a cancel to West Bridge, + the MTP operation still needs to be canceled by + sending a response. + + West Bridge will automatically set a Stall on the endpoint + when the cancel is received. + + This function is only valid after CyAsMTPInitSendObject + has been called, but before the CyAsMTPSendObjectComplete + event has been sent. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + * CY_AS_ERROR_NO_OPERATION_PENDING + + See Also + * CyAsMTPInitSendObject +*/ +cy_as_return_status_t +cy_as_mtp_cancel_send_object( + cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function sets up a turbo GetObject operation. + + Description + Called by the P in response to a GetObject + operation. This provides West Bridge with the block + addresses for the Object data that needs to be + transferred. + + It is the responsibility of the Processor to send the MTP + operation before calling CyAsMTPInitGetObject. West Bridge + will then send the data phase of the transaction, + automatically creating the required container for Data. + Once all of the Data has been transferred a callback will + be issued to inform the Processor that the Data phase has + completed allowing it to send the required MTP response. + + If an entire Block Table is used then after the + last block is transferred the CyAsMTPBtCallback + will be called to allow an additional Block Table(s) + to be specified. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_IN_SUSPEND + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_ASYNC_PENDING + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + + See Also + * CyAsMTPInitSendObject + * CyAsMTPCancelGetObject + * CyAsMTPEvent + * CyAsMTPSendBlockTable +*/ +cy_as_return_status_t +cy_as_mtp_init_get_object( + cy_as_device_handle handle, + cy_as_mtp_block_table *table_p, + uint32_t num_bytes, + uint32_t transaction_id, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function cancels an ongoing turbo GetObject + operation. + + Description + Causes West Bridge to cancel an ongoing GetObject + operation. Note this is only a cancel to West Bridge, + the MTP operation still needs to be canceled by + sending a response. + + This function is only valid after CyAsMTPGetSendObject + has been called, but before the CyAsMTPGetObjectComplete + event has been sent. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + * CY_AS_ERROR_NO_OPERATION_PENDING + + See Also + * CyAsMTPInitGetObject +*/ +cy_as_return_status_t +cy_as_mtp_cancel_get_object( + cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function is used to transfer a BlockTable as part of + an ongoing MTP operation. + + Description + This function is called in response to the + CyAsMTPBlockTableNeeded event. This allows the client to + pass in a BlockTable structure to West Bridge. + + The memory associated with the table will be copied and + can be safely disposed of when the function returns if + called synchronously, or when the callback is made if + called asynchronously. + + This function is used for both SendObject and GetObject + as both can generate the CyAsMTPBlockTableNeeded event. + + Returns + * CY_AS_ERROR_SUCCESS + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_NOT_CONFIGURED + * CY_AS_ERROR_NO_FIRMWARE + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_IN_SUSPEND + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_ASYNC_PENDING + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_SUPPORTED - West Bridge is not running + * firmware with MTP support + + See Also + * CyAsMTPInitSendObject + * CyAsMTPInitGetObject +*/ +cy_as_return_status_t +cy_as_mtp_send_block_table( + cy_as_device_handle handle, + cy_as_mtp_block_table *table, + cy_as_function_callback cb, + uint32_t client + ) ; + +/* Summary + This function is used to mark the start of a storage + read/write burst from the P port processor. + + Description + This function is used to mark the start of a storage + read/write burst from the processor. All USB host access + into the mass storage / MTP endpoints will be blocked + while the read/write burst is ongoing, and will be allowed + to resume only after CyAsMTPStorageOnlyStop is called. + The burst mode is used to reduce the firmware overhead + due to configuring the internal data paths repeatedly, + and can help improve performance when a sequence of + read/writes is performed in a burst. + + This function will not generate a special mailbox request, + it will only set a flag on the next Storage Read/Write + operation. Until such a call is made West Bridge will + continue to accept incoming packets from the Host. + + * Valid in Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device + * handle was passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not + * been configured. + * CY_AS_ERROR_NO_FIRMWARE - Firmware is not active on West + * Bridge device. + * CY_AS_ERROR_NOT_RUNNING - Storage stack is not running. + * CY_AS_ERROR_SUCCESS - Burst mode has been started. + + See Also + * CyAsStorageReadWriteBurstStop + */ +cy_as_return_status_t +cy_as_mtp_storage_only_start( + /* Handle to the West Bridge device. */ + cy_as_device_handle handle + ); + +/* Summary + This function is used to mark the end of a storage read/write + burst from the P port processor. + + Description + This function is used to mark the end of a storage read/write + burst from the processor. At this point, USB access to the + mass storage / MTP endpoints on the West Bridge device will be + re-enabled. + + * Valid in Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device handle + * was passed in. + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not been + * configured. + * CY_AS_ERROR_NO_FIRMWARE - Firmware is not active on West Bridge + * device. + * CY_AS_ERROR_NOT_RUNNING - Storage stack is not running. + * CY_AS_ERROR_INVALID_IN_CALLBACK - This API cannot be called + * from a callback. + * CY_AS_ERROR_OUT_OF_MEMORY - Failed to allocate memory to + * process the request. + * CY_AS_ERROR_TIMEOUT - Failed to send request to firmware. + * CY_AS_ERROR_SUCCESS - Burst mode has been stopped. + + See Also + * CyAsStorageReadWriteBurstStart + */ +cy_as_return_status_t +cy_as_mtp_storage_only_stop( + /* Handle to the West Bridge device. */ + cy_as_device_handle handle, + cy_as_function_callback cb, + uint32_t client + ); + +#include "cyas_cplus_end.h" + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h new file mode 100644 index 000000000000..317805fc4ff4 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasprotocol.h @@ -0,0 +1,3838 @@ +/* Cypress West Bridge API header file (cyasprotocol.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASPROTOCOL_H_ +#define _INCLUDED_CYASPROTOCOL_H_ + +/* + * Constants defining the per context buffer sizes + */ +#ifndef __doxygen__ +#define CY_CTX_GEN_MAX_DATA_SIZE (8) +#define CY_CTX_RES_MAX_DATA_SIZE (8) +#define CY_CTX_STR_MAX_DATA_SIZE (64) +#define CY_CTX_USB_MAX_DATA_SIZE (130 + 23) +#define CY_CTX_TUR_MAX_DATA_SIZE (12) +#endif + +/* Summary + This response indicates a command has been processed + and returned a status. + + Direction + West Bridge -> P Port Processor + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = all + * Response Code = 0 + + D0 + * 0 = success (CY_AS_ERROR_SUCCESS) + * non-zero = error code + + Description + This response indicates that a request was processed + and no data was generated as a result of the request + beyond a single 16 bit status value. This response + contains the 16 bit data value. + */ +#define CY_RESP_SUCCESS_FAILURE (0) + +/* Summary + This response indicates an invalid request was sent + + Direction + West Bridge -> P Port Processor + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = all + * Response Code = 1 + + D0 + * Mailbox contents for invalid request + + Description + This response is returned when a request is sent + that contains an invalid + context or request code. +*/ +#define CY_RESP_INVALID_REQUEST (1) + +/* Summary + This response indicates a request of invalid length was sent + + Direction + West Bridge -> P Port Processor + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = all + * Response Code = 2 + + D0 + * Mailbox contenxt for invalid request + * Length for invalid request + + Description + The software API and firmware sends requests across the + P Port to West Bridge interface on different contexts. + Each contexts has a maximum size of the request packet + that can be received. The size of a request can be + determined during the first cycle of a request transfer. + If the request is larger than can be handled by the + receiving context this response is returned. Note that + the complete request is received before this response is + sent, but that the request is dropped after this response + is sent. +*/ +#define CY_RESP_INVALID_LENGTH (2) + + +/* Summary + This response indicates a request was made to an + invalid storage address. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = all + * Response Code = 0 + + D0 + Bits 15 - 12 : Media Type + * 0 = NAND + * 1 = SD Flash + * 2 = MMC Flash + * 3 = CE-ATA + + Bits 11 - 8 : Zero based device index + + Bits 7 - 0 : Zero based unit index + + D1 + Upper 16 bits of block address + + D2 + Lower 16 bits of block address + + D3 + Portion of address that is invalid + * 0 = Media Type + * 1 = Device Index + * 2 = Unit Index + * 3 = Block Address + + Description + This response indicates a request to an invalid storage media + address + */ +#define CY_RESP_NO_SUCH_ADDRESS (3) + + +/******************************************************/ + +/*@@General requests + Summary + The general requests include: + * CY_RQT_GET_FIRMWARE_VERSION + * CY_RQT_SET_TRACE_LEVEL + * CY_RQT_INITIALIZATION_COMPLETE + * CY_RQT_READ_MCU_REGISTER + * CY_RQT_WRITE_MCU_REGISTER + * CY_RQT_STORAGE_MEDIA_CHANGED + * CY_RQT_CONTROL_ANTIOCH_HEARTBEAT + * CY_RQT_PREPARE_FOR_STANDBY + * CY_RQT_ENTER_SUSPEND_MODE + * CY_RQT_OUT_OF_SUSPEND + * CY_RQT_GET_GPIO_STATE + * CY_RQT_SET_GPIO_STATE + * CY_RQT_SET_SD_CLOCK_FREQ + * CY_RQT_WB_DEVICE_MISMATCH + * CY_RQT_BOOTLOAD_NO_FIRMWARE + * CY_RQT_RESERVE_LNA_BOOT_AREA + * CY_RQT_ABORT_P2S_XFER + */ + +#ifndef __doxygen__ +#define CY_RQT_GENERAL_RQT_CONTEXT (0) +#endif + +/* Summary + This command returns the firmware version number, + media types supported and debug/release mode information. + + Direction + P Port Processor-> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request Code = 0 + + Description + The response contains the 16-bit major version, the + 16-bit minor version, the 16 bit build number, media + types supported and release/debug mode information. + + Responses + * CY_RESP_FIRMWARE_VERSION + */ +#define CY_RQT_GET_FIRMWARE_VERSION (0) + + +/* Summary + This command changes the trace level and trace information + destination within the West Bridge firmware. + + Direction + P Port Processor-> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request Code = 1 + + D0 + Trace Level + * 0 = no trace information + * 1 = state information + * 2 = function call + * 3 = function call with args/return value + + D1 + Bits 12 - 15 : MediaType + * 0 = NAND + * 1 = SDIO Flash + * 2 = MMC Flash + * 3 = CE-ATA + + Bits 8 - 11 : Zero based device index + + Bits 0 - 7 : Zero based unit index + + Description + The West Bridge firmware contains debugging facilities that can + be used to trace the execution of the firmware. This request + sets the level of tracing information that is stored and the + location where it is stored. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_SET_TRACE_LEVEL (1) + +/* Summary + This command indicates that the firmware is up and ready + for communications with the P port processor. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 0 + * Request Code = 3 + + D0 + Major Version + + D1 + Minor Version + + D2 + Build Number + + D3 + Bits 15-8: Media types supported on Bus 1. + Bits 7-0: Media types supported on Bus 0. + Bits 8, 0: NAND support. + * 0: NAND is not supported. + * 1: NAND is supported. + Bits 9, 1: SD memory card support. + * 0: SD memory card is not supported. + * 1: SD memory card is supported. + Bits 10, 2: MMC card support. + * 0: MMC card is not supported. + * 1: MMC card is supported. + Bits 11, 3: CEATA drive support + * 0: CEATA drive is not supported. + * 1: CEATA drive is supported. + Bits 12, 4: SD IO card support. + * 0: SD IO card is not supported. + * 1: SD IO card is supported. + + D4 + Bits 15 - 8 : MTP information + * 0 : MTP not supported in firmware + * 1 : MTP supported in firmware + Bits 7 - 0 : Debug/Release mode information. + * 0 : Release mode + * 1 : Debug mode + + Description + When the West Bridge firmware is loaded it being by performing + initialization. Initialization must be complete before West + Bridge is ready to accept requests from the P port processor. + This request is sent from West Bridge to the P port processor + to indicate that initialization is complete. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_INITIALIZATION_COMPLETE (3) + +/* Summary + This command requests the firmware to read and return the contents + of a MCU accessible + register. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 4 + + D0 + Address of register to read + + Description + This debug command allows the processor to read the contents of + a MCU accessible register. + + Responses + * CY_RESP_MCU_REGISTER_DATA + */ +#define CY_RQT_READ_MCU_REGISTER (4) + +/* Summary + This command requests the firmware to write to an MCU + accessible register. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 5 + + D0 + Address of register to be written + + D1 + Bits 15 - 8 : Mask to be applied to existing data. + Bits 7 - 0 : Data to be ORed with masked data. + + Description + This debug command allows the processor to write to an MCU + accessible register. + Note: This has to be used with caution, and is supported by + the firmware only in special debug builds. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_WRITE_MCU_REGISTER (5) + +/* Summary + This command tells the West Bridge firmware that a change in + storage media has been detected. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 6 + + Description + If the insertion or removal of SD or MMC cards is detected by + hardware external to West Bridge, this command is used to tell + the West Bridge firmware to re-initialize the storage controlled + by the device. + + Responses + * CY_RESP_SUCCESS_FAILURE +*/ +#define CY_RQT_STORAGE_MEDIA_CHANGED (6) + +/* Summary + This command enables/disables the periodic heartbeat message + from the West Bridge firmware to the processor. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 7 + + Description + This command enables/disables the periodic heartbeat message + from the West Bridge firmware to the processor. The heartbeat + message is left enabled by default, and can lead to a loss + in performance on the P port interface. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_CONTROL_ANTIOCH_HEARTBEAT (7) + +/* Summary + This command requests the West Bridge firmware to prepare for + the device going into standby + mode. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 8 + + Description + This command is sent by the processor to the West Bridge as + preparation for going into standby mode. The request allows the + firmware to complete any pending/cached storage operations before + going into the low power state. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_PREPARE_FOR_STANDBY (8) + +/* Summary + Requests the firmware to go into suspend mode. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 9 + + D0 + Bits 7-0: Wakeup control information. + + Description + This command is sent by the processor to the West Bridge to + request the device to be placed in suspend mode. The firmware + will complete any pending/cached storage operations before + going into the low power state. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_ENTER_SUSPEND_MODE (9) + +/* Summary + Indicates that the device has left suspend mode. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 10 + + Description + This message is sent by the West Bridge to the Processor + to indicate that the device has woken up from suspend mode, + and is ready to accept new requests. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_OUT_OF_SUSPEND (10) + +/* Summary + Request to get the current state of an West Bridge GPIO pin. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 11 + + D0 + Bits 15 - 8 : GPIO pin identifier + + Responses + * CY_RESP_GPIO_STATE + + Description + Request from the processor to get the current state of + an West Bridge GPIO pin. + */ +#define CY_RQT_GET_GPIO_STATE (11) + +/* Summary + Request to update the output value on an West Bridge + GPIO pin. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 12 + + D0 + Bits 15 - 8 : GPIO pin identifier + Bit 0 : Desired output state + + Responses + * CY_RESP_SUCCESS_FAILURE + + Description + Request from the processor to update the output value on + an West Bridge GPIO pin. + */ +#define CY_RQT_SET_GPIO_STATE (12) + +/* Summary + Set the clock frequency on the SD interface of the West + Bridge device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 13 + + D0 + Bit 8: Type of SD/MMC media + 0 = low speed media + 1 = high speed media + Bit 0: Clock frequency selection + 0 = Default frequency + 1 = Alternate frequency (24 MHz in both cases) + + Description + This request is sent by the processor to set the operating clock + frequency used on the SD interface of the device. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_SET_SD_CLOCK_FREQ (13) + +/* Summary + Indicates the firmware downloaded to West Bridge cannot + run on the active device. + + Direction + West Bridge -> P Port processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 14 + + Description + Some versions of West Bridge firmware can only run on specific + types/versions of the West Bridge device. This error is + returned when a firmware image is downloaded onto a device that + does not support it. + + Responses + * None + */ +#define CY_RQT_WB_DEVICE_MISMATCH (14) + +/* Summary + This command is indicates that no firmware was found in the + storage media. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 0 + * Request code = 15 + + Description + The command is received only in case of silicon with bootloader + ROM. The device sends the request if there is no firmware image + found in the storage media or the image is corrupted. The + device is waiting for P port to download a valid firmware image. + + Responses + * None + */ +#define CY_RQT_BOOTLOAD_NO_FIRMWARE (15) + +/* Summary + This command reserves first numzones zones of nand device for + storing processor boot image. + + Direction + P Port Processor-> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request Code = 16 + + D0 + Bits 7-0: numzones + + Description + The first numzones zones in nand device will be used for storing + proc boot image. LNA firmware in Astoria will work on this nand + area and boots the processor which will then use the remaining + nand for usual purposes. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_RESERVE_LNA_BOOT_AREA (16) + +/* Summary + This command cancels the processing of a P2S operation in + firmware. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request Code = 17 + + Responses + * CY_RESP_SUCCESS_FAILURE +*/ +#define CY_RQT_ABORT_P2S_XFER (17) + +/* + * Used for debugging, ignore for normal operations + */ +#ifndef __doxygen__ +#define CY_RQT_DEBUG_MESSAGE (127) +#endif + +/******************************************************/ + +/*@@General responses + Summary + The general responses include: + * CY_RESP_FIRMWARE_VERSION + * CY_RESP_MCU_REGISTER_DATA + * CY_RESP_GPIO_STATE + */ + + +/* Summary + This response indicates success and contains the firmware + version number, media types supported by the firmware and + release/debug mode information. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + MailBox0 + * Context = 0 + * Response Code = 16 + + D0 + Major Version + + D1 + Minor Version + + D2 + Build Number + + D3 + Bits 15-8: Media types supported on Bus 1. + Bits 7-0: Media types supported on Bus 0. + Bits 8, 0: NAND support. + * 0: NAND is not supported. + * 1: NAND is supported. + Bits 9, 1: SD memory card support. + * 0: SD memory card is not supported. + * 1: SD memory card is supported. + Bits 10, 2: MMC card support. + * 0: MMC card is not supported. + * 1: MMC card is supported. + Bits 11, 3: CEATA drive support + * 0: CEATA drive is not supported. + * 1: CEATA drive is supported. + Bits 12, 4: SD IO card support. + * 0: SD IO card is not supported. + * 1: SD IO card is supported. + + D4 + Bits 15 - 8 : MTP information + * 0 : MTP not supported in firmware + * 1 : MTP supported in firmware + Bits 7 - 0 : Debug/Release mode information. + * 0 : Release mode + * 1 : Debug mode + + Description + This reponse is sent to return the firmware version + number to the requestor. + */ +#define CY_RESP_FIRMWARE_VERSION (16) + +/* Summary + This response returns the contents of a MCU accessible + register to the processor. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Response code = 17 + + D0 + Bits 7 - 0 : MCU register contents + + Description + This response is sent by the firmware in response to the + CY_RQT_READ_MCU_REGISTER + command. + */ +#define CY_RESP_MCU_REGISTER_DATA (17) + +/* Summary + Reports the current state of an West Bridge GPIO pin. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request code = 18 + + D0 + Bit 0: Current state of the GP input pin + + Description + This response is sent by the West Bridge to report the + current state observed on a general purpose input pin. + */ +#define CY_RESP_GPIO_STATE (18) + + +/* Summary + This command notifies West Bridge the polarity of the + SD power pin + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 0 + * Request Code = 19 + D0: CyAnMiscActivehigh / CyAnMiscActivelow + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + + */ + +#define CY_RQT_SDPOLARITY (19) + +/******************************/ + +/*@@Resource requests + Summary + + The resource requests include: + * CY_RQT_ACQUIRE_RESOURCE + * CY_RQT_RELEASE_RESOURCE + */ + + + + + +#ifndef __doxygen__ +#define CY_RQT_RESOURCE_RQT_CONTEXT (1) +#endif + + +/* Summary + This command is a request from the P port processor + for ownership of a resource. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 1 + * Request Code = 0 + + D0 + Resource + * 0 = USB + * 1 = SDIO/MMC + * 2 = NAND + + D1 + Force Flag + * 0 = Normal + * 1 = Force + + Description + The resource may be the USB pins, the SDIO/MMC bus, + or the NAND bus. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_RELEASED + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_RESOURCE + */ +#define CY_RQT_ACQUIRE_RESOURCE (0) + + +/* Summary + This command is a request from the P port processor + to release ownership of a resource. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 1 + * Request Code = 1 + + D0 + Resource + * 0 = USB + * 1 = SDIO/MMC + * 2 = NAND + + Description + The resource may be the USB pins, the SDIO/MMC bus, or + the NAND bus. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_OWNER + */ +#define CY_RQT_RELEASE_RESOURCE (1) + + +/****************************/ + +/*@@Storage requests + Summary + The storage commands include: + * CY_RQT_START_STORAGE + * CY_RQT_STOP_STORAGE + * CY_RQT_CLAIM_STORAGE + * CY_RQT_RELEASE_STORAGE + * CY_RQT_QUERY_MEDIA + * CY_RQT_QUERY_DEVICE + * CY_RQT_QUERY_UNIT + * CY_RQT_READ_BLOCK + * CY_RQT_WRITE_BLOCK + * CY_RQT_MEDIA_CHANGED + * CY_RQT_ANTIOCH_CLAIM + * CY_RQT_ANTIOCH_RELEASE + * CY_RQT_SD_INTERFACE_CONTROL + * CY_RQT_SD_REGISTER_READ + * CY_RQT_CHECK_CARD_LOCK + * CY_RQT_QUERY_BUS + * CY_RQT_PARTITION_STORAGE + * CY_RQT_PARTITION_ERASE + * CY_RQT_GET_TRANSFER_AMOUNT + * CY_RQT_ERASE + * CY_RQT_SDIO_READ_DIRECT + * CY_RQT_SDIO_WRITE_DIRECT + * CY_RQT_SDIO_READ_EXTENDED + * CY_RQT_SDIO_WRITE_EXTENDED + * CY_RQT_SDIO_INIT_FUNCTION + * CY_RQT_SDIO_QUERY_CARD + * CY_RQT_SDIO_GET_TUPLE + * CY_RQT_SDIO_ABORT_IO + * CY_RQT_SDIO_INTR + * CY_RQT_SDIO_SUSPEND + * CY_RQT_SDIO_RESUME + * CY_RQT_SDIO_RESET_DEV + * CY_RQT_P2S_DMA_START + */ +#ifndef __doxygen__ +#define CY_RQT_STORAGE_RQT_CONTEXT (2) +#endif + +/* Summary + This command requests initialization of the storage stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 0 + + Description + This command is required before any other storage related command + can be send to the West Bridge firmware. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_ALREADY_RUNNING + */ +#define CY_RQT_START_STORAGE (0) + + +/* Summary + This command requests shutdown of the storage stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 1 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_NOT_RUNNING + */ +#define CY_RQT_STOP_STORAGE (1) + + +/* Summary + This command requests ownership of the given media + type by the P port processor. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 2 + + D0 + Bits 12 - 15 : Bus Index + Bits 8 - 11 : Zero based device index + + Responses + * CY_RESP_MEDIA_CLAIMED_RELEASED + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_CLAIM_STORAGE (2) + + +/* Summary + This command releases ownership of a given media type + by the P port processor. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 3 + + D0 + Bits 12 - 15 : Bus Index + Bits 8 - 11 : Zero based device index + + Responses + * CY_RESP_MEDIA_CLAIMED_RELEASED + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_RELEASE_STORAGE (3) + + +/* Summary + This command returns the total number of logical devices + of the given type of media. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 4 + + D0 + Bits 12 - 15 : MediaType + * 0 = NAND + * 1 = SDIO Flash + * 2 = MMC Flash + * 3 = CE-ATA + + Bits 8 - 11 : Not Used + + Bits 0 - 7 : Not Used + + Responses + * CY_RESP_MEDIA_DESCRIPTOR + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_QUERY_MEDIA (4) + + +/* Summary + This command queries a given device to determine + information about the number of logical units on + the given device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 5 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Not Used + + Responses + * CY_RESP_DEVICE_DESCRIPTOR + * CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_PARTITION_TABLE + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_QUERY_DEVICE (5) + + +/* Summary + This command queries a given device to determine + information about the size and location of a logical unit + located on a physical device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 6 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + Responses + * CY_RESP_UNIT_DESCRIPTOR + * CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_PARTITION_TABLE + * CY_RESP_NO_SUCH_ADDRESS + */ +#define CY_RQT_QUERY_UNIT (6) + + +/* Summary + This command initiates the read of a specific block + from the given media, + device and unit. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 2 + * Request Code = 7 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + D1 + Upper 16 bits of block address + + D2 + Lower 16 bits of block address + + D3 + BIT 8 - 15 : Upper 8 bits of Number of blocks + + BIT 0 - 7 : Reserved + + * D4 * + BITS 8 - 15 : Lower 8 bits of Number of blocks + BITS 1 - 7 : Not Used + BIT 0 : Indicates whether this command is a + part of a P2S only burst. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_ANTIOCH_DEFERRED_ERROR + */ +#define CY_RQT_READ_BLOCK (7) + + +/* Summary + This command initiates the write of a specific block + from the given media, device and unit. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 2 + * Request Code = 8 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + D1 + Upper 16 bits of block address + + D2 + Lower 16 bits of block address + + D3 + BIT 8 - 15 : Upper 8 bits of Number of blocks + + BIT 0 - 7 : Reserved + + * D4 * + BITS 8 - 15 : Lower 8 bits of Number of blocks + BITS 1 - 7 : Not Used + BIT 0 : Indicates whether this command is a + part of a P2S only burst. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_ANTIOCH_DEFERRED_ERROR + */ +#define CY_RQT_WRITE_BLOCK (8) + +/* Summary + This request is sent when the West Bridge device detects + a change in the status of the media. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request Code = 9 + + D0 + Bits 12 - 15 : Bus index + Bits 0 - 7 : Media type + + D1 + Bit 0 : Action + * 0 = Inserted + * 1 = Removed + + Description + When the media manager detects the insertion or removal + of a media from the West Bridge port, this request is sent + from the West Bridge device to the P Port processor to + inform the processor of the change in status of the media. + This request is sent for both an insert operation and a + removal operation. + + Responses + * CY_RESPO_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_MEDIA_CHANGED (9) + +/* Summary + This request is sent when the USB module wishes to claim + storage media. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request Code = 10 + + D0 + Bit 0: + * 0 = do not release NAND + * 1 = release NAND + + Bit 1: + * 0 = do not release SD Flash + * 1 = release SD Flash + + Bit 2: + * 0 = do not release MMC flash + * 1 = release MMC flash + + Bit 3: + * 0 = do not release CE-ATA storage + * 1 = release CE-ATA storage + + Bit 8: + * 0 = do not release storage on bus 0 + * 1 = release storage on bus 0 + + Bit 9: + * 0 = do not release storage on bus 1 + * 1 = release storage on bus 1 + + Description + When the USB cable is attached to the West Bridge device, + West Bridge will enumerate the storage devices per the USB + initialization of West Bridge. In order for West Bridge to + respond to requests received via USB for the mass storage + devices, the USB module must claim the storeage. This + request is a request to the P port processor to release the + storage medium. The medium will not be visible on the USB + host, until it has been released by the processor. +*/ +#define CY_RQT_ANTIOCH_CLAIM (10) + +/* Summary + This request is sent when the P port has asked West Bridge to + release storage media, and the West Bridge device has + completed this. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request Code = 11 + + D0 + Bit 0: + * 0 = No change in ownership of NAND storage + * 1 = NAND ownership has been given to processor + + Bit 1: + * 0 = No change in ownership of SD storage + * 1 = SD ownership has been given to processor + + Bit 2: + * 0 = No change in ownership of MMC storage + * 1 = MMC ownership has been given to processor + + Bit 3: + * 0 = No change in ownership of CE-ATA storage + * 1 = CE-ATA ownership has been given to processor + + Bit 4: + * 0 = No change in ownership of SD IO device + * 1 = SD IO device ownership has been given to processor + + Bit 8: + * 0 = No change in ownership of storage on bus 0 + * 1 = Bus 0 ownership has been given to processor + + Bit 9: + * 0 = No change in ownership of storage on bus 1 + * 1 = Bus 1 ownership has been given to processor + + Description + When the P port asks for control of a particular media, West + Bridge may be able to release the media immediately. West + Bridge may also need to complete the flush of buffers before + releasing the media. In the later case, West Bridge will + indicated a release is not possible immediately and West Bridge + will send this request to the P port when the release has been + completed. +*/ +#define CY_RQT_ANTIOCH_RELEASE (11) + +/* Summary + This request is sent by the Processor to enable/disable the + handling of SD card detection and SD card write protection + by the firmware. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 12 + + D0 + Bit 8: Enable/disable handling of card detection. + Bit 1: SDAT_3 = 0, GIPO_0 = 1 + Bit 0: Enable/disable handling of write protection. + + Description + This request is sent by the Processor to enable/disable + the handling of SD card detection and SD card write + protection by the firmware. + */ +#define CY_RQT_SD_INTERFACE_CONTROL (12) + +/* Summary + Request from the processor to read a register on the SD + card, and return the contents. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 13 + + D0 + Bits 12 - 15 : MediaType + * 0 = Reserved + * 1 = SDIO Flash + * 2 = MMC Flash + * 3 = Reserved + + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Type of register to read + + Description + This request is sent by the processor to instruct the + West Bridge to read a register on the SD/MMC card, and + send the contents back through the CY_RESP_SD_REGISTER_DATA + response. + */ +#define CY_RQT_SD_REGISTER_READ (13) + +/* Summary + Check if the SD/MMC card connected to West Bridge is + password locked. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 14 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + + Description + This request is sent by the processor to check if the + SD/MMC connected to the West Bridge is locked with a + password. + */ +#define CY_RQT_CHECK_CARD_LOCK (14) + +/* Summary + This command returns the total number of logical devices on the + given bus + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 15 + + D0 + Bits 12 - 15 : Bus Number + + Bits 0 - 11: Not Used + + Responses + * CY_RESP_BUS_DESCRIPTOR + * CY_RESP_NO_SUCH_BUS + */ +#define CY_RQT_QUERY_BUS (15) + +/* Summary + Divide a storage device into two partitions. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request code = 16 + + D0 + Bits 12 - 15 : Bus number + Bits 8 - 11 : Device number + Bits 0 - 7 : Not used + + D1 + Size of partition 0 (MS word) + + D2 + Size of partition 0 (LS word) + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_PARTITION_STORAGE (16) + +/* Summary + Remove the partition table and unify all partitions on + a storage device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request code = 17 + + D0 + Bits 12 - 15 : Bus number + Bits 8 - 11 : Device number + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_PARTITION_ERASE (17) + +/* Summary + Requests the current transfer amount. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request code = 18 + + D0 + Bits 12 - 15 : Bus number + Bits 8 - 11 : Device number + + Responses + * CY_RESP_TRANSFER_COUNT + */ +#define CY_RQT_GET_TRANSFER_AMOUNT (18) + +/* Summary + Erases. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 2 + * Request code = 19 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + D1 + Upper 16 bits of erase unit + + D2 + Lower 16 bits of erase unit + + D3 + BIT 8 - 15 : Upper 8 bits of Number of erase units + BIT 0 - 7 : Reserved + + * D4 * + BIT 8 - 15 : Lower 8 bits of Number of erase units + BIT 0 - 7 : Not Used + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + */ +#define CY_RQT_ERASE (19) + +/* Summary + This command reads 1 byte from an SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 23 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + D1 + Bits 8 - 15 : 0 + Bit 7 : 0 to indicate a read + Bits 4 - 6 : Function number + Bit 3 : 0 + Bit 2 : 1 if SDIO interrupt needs to be re-enabled. + Bits 0 - 1 : Two Most significant bits of Read address + + D2 + Bits 1 - 15 : 15 Least significant bits of Read address + Bit 0 : 0 + + + Responses + * CY_RESP_SUCCESS_FAILURE + * CY_RESP_SDIO_DIRECT +*/ +#define CY_RQT_SDIO_READ_DIRECT (23) + +/* Summary + This command writes 1 byte to an SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 24 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + D1 + Bits 8 - 15 : Data to write + Bit 7 : 1 to indicate a write + Bits 4 - 6 : Function number + Bit 3 : 1 if Read after write is enabled + Bit 2 : 1 if SDIO interrupt needs to be re-enabled. + Bits 0 - 1 : Two Most significant bits of write address + + D2 + Bits 1 - 15 : 15 Least significant bits of write address + Bit 0 : 0 + + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SDIO_DIRECT +*/ +#define CY_RQT_SDIO_WRITE_DIRECT (24) + +/* Summary + This command reads performs a multi block/byte read from + an SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 25 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + D1 + Bit 15 : 0 to indicate a read + Bit 12 - 14 : Function Number + Bit 11 : Block Mode + Bit 10 : OpCode + Bits 0 - 9 : 10 Most significant bits of Read address + + D2 + Bits 9 - 15 : 7 Least significant bits of address + Bits 0 - 8 : Block/Byte Count + + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SDIO_EXT +*/ +#define CY_RQT_SDIO_READ_EXTENDED (25) + +/* Summary + This command reads performs a multi block/byte write + to an SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 26 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + D1 + Bit 15 : 1 to indicate a write + Bit 12 - 14 : Function Number + Bit 11 : Block Mode + Bit 10 : OpCode + Bits 0 - 9 : 10 Most significant bits of Read address + + D2 + Bits 9 - 15 : 7 Least significant bits of address + Bits 0 - 8 : Block/Byte Count + + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SDIO_EXT +*/ +#define CY_RQT_SDIO_WRITE_EXTENDED (26) + +/* Summary + This command initialises an IO function on the SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 27 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SDIO_INIT_FUNCTION (27) + +/* Summary + This command gets properties of the SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 28 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_QUERY_CARD +*/ +#define CY_RQT_SDIO_QUERY_CARD (28) + +/* Summary + This command reads a tuple from the CIS of an SDIO card. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 29 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + D1 + Bits 8 - 15 : Tuple ID to read + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SDIO_GET_TUPLE +*/ +#define CY_RQT_SDIO_GET_TUPLE (29) + +/* Summary + This command Aborts an IO operation. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 30 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SDIO_ABORT_IO (30) + +/* Summary + SDIO Interrupt request sent to the processor from the West Bridge device. + + Direction + West Bridge ->P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 31 + + D0 + Bits 0 - 7 : Bus Index + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SDIO_INTR (31) + +/* Summary + This command Suspends an IO operation. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 32 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SDIO_SUSPEND (32) + +/* Summary + This command resumes a suspended operation. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 33 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based function number + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SDIO_RESUME +*/ +#define CY_RQT_SDIO_RESUME (33) + +/* Summary + This command resets an SDIO device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request Code = 34 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : 0 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SDIO_RESET_DEV (34) + +/* Summary + This command asks the API to start the DMA transfer + for a P2S operation. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Request code = 35 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_P2S_DMA_START (35) + +/******************************************************/ + +/*@@Storage responses + Summary + The storage responses include: + * CY_RESP_MEDIA_CLAIMED_RELEASED + * CY_RESP_MEDIA_DESCRIPTOR + * CY_RESP_DEVICE_DESCRIPTOR + * CY_RESP_UNIT_DESCRIPTOR + * CY_RESP_ANTIOCH_DEFERRED_ERROR + * CY_RESP_SD_REGISTER_DATA + * CY_RESP_SD_LOCK_STATUS + * CY_RESP_BUS_DESCRIPTOR + * CY_RESP_TRANSFER_COUNT + * CY_RESP_SDIO_EXT + * CY_RESP_SDIO_INIT_FUNCTION + * CY_RESP_SDIO_QUERY_CARD + * CY_RESP_SDIO_GET_TUPLE + * CY_RESP_SDIO_DIRECT + * CY_RESP_SDIO_INVALID_FUNCTION + * CY_RESP_SDIO_RESUME + */ + +/* Summary + Based on the request sent, the state of a given media was + changed as indicated by this response. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Response Code = 16 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + + D1 + State of Media + * 0 = released + * 1 = claimed + */ +#define CY_RESP_MEDIA_CLAIMED_RELEASED (16) + + +/* Summary + This response gives the number of physical devices + associated with a given media type. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Response Code = 17 + + D0 + Media Type + Bits 12 - 15 + * 0 = NAND + * 1 = SDIO Flash + * 2 = MMC Flash + * 3 = CE-ATA + + D1 + Number of devices + */ +#define CY_RESP_MEDIA_DESCRIPTOR (17) + + +/* Summary + This response gives description of a physical device. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + MailBox0 + * Context = 2 + * Response Code = 18 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Type of media present on bus + + D1 + Block Size in bytes + + D2 + Bit 15 : Is device removable + Bit 9 : Is device password locked + Bit 8 : Is device writeable + Bits 0 - 7 : Number Of Units + + D3 + ERASE_UNIT_SIZE high 16 bits + + D4 + ERASE_UNIT_SIZE low 16 bits + + */ +#define CY_RESP_DEVICE_DESCRIPTOR (18) + + +/* Summary + This response gives description of a unit on a + physical device. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 6 + + MailBox0 + * Context = 2 + * Response Code = 19 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + D1 + Bits 0 - 7 : Media type + * 1 = NAND + * 2 = SD FLASH + * 4 = MMC FLASH + * 8 = CEATA + * 16 = SD IO + + D2 + Block Size in bytes + + D3 + Start Block Low 16 bits + + D4 + Start Block High 16 bits + + D5 + Unit Size Low 16 bits + + D6 + Unit Size High 16 bits + */ +#define CY_RESP_UNIT_DESCRIPTOR (19) + + +/* Summary + This response is sent as error status for P2S + Storage operation. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 2 + * Request Code = 20 + + D0 + Bit 8 : Type of operation (Read / Write) + Bits 7 - 0 : Error code + + D1 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Zero based unit index + + *D2 - D3* + Address where the error occurred. + + D4 + Length of the operation in blocks. + + Description + This error is returned by the West Bridge to the + processor if a storage operation fails due to a + medium error. +*/ +#define CY_RESP_ANTIOCH_DEFERRED_ERROR (20) + +/* Summary + Contents of a register on the SD/MMC card connected to + West Bridge. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + Variable + + Mailbox0 + * Context = 2 + * Request code = 21 + + D0 + Length of data in bytes + + D1 - Dn + The register contents + + Description + This is the response to a CY_RQT_SD_REGISTER_READ + request. +*/ +#define CY_RESP_SD_REGISTER_DATA (21) + +/* Summary + Status of whether the SD card is password locked. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 22 + + D0 + Bit 0 : The card's lock status + + Description + Status of whether the SD card is password locked. +*/ +#define CY_RESP_SD_LOCK_STATUS (22) + + +/* Summary + This response gives the types of physical devices + attached to a given bus. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 2 + * Response Code = 23 + + D0 + Bus Number + Bits 12 - 15 + + D1 + Media present on addressed bus + */ +#define CY_RESP_BUS_DESCRIPTOR (23) + +/* Summary + Amount of data read/written through the USB mass + storage/MTP device. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + MailBox0 + * Context = 2 + * Request code = 24 + + D0 + MS 16 bits of number of sectors written + + D1 + LS 16 bits of number of sectors written + + D2 + MS 16 bits of number of sectors read + + D3 + LS 16 bits of number of sectors read + + Description + This is the response to the CY_RQT_GET_TRANSFER_AMOUNT + request, and represents the number of sectors of data + that has been written to or read from the storage device + through the USB Mass storage or MTP interface. + */ +#define CY_RESP_TRANSFER_COUNT (24) + +/* Summary + Status of SDIO Extended read/write operation. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 34 + + D0 + Bit 8 : 1 if Read response, 0 if write response + Bits 0-7: Error Status + + Description + Status of SDIO Extended read write operation. +*/ + +#define CY_RESP_SDIO_EXT (34) + +/* Summary + Status of SDIO operation to Initialize a function + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 2 + * Request code = 35 + + + D0 + Bits 8-15 : Function Interface Code + Bits 0-7: Extended Function Interface Code + + D1 + Bits 0-15 : Function Block Size + + D2 + Bits 0-15 : Most significant Word of Function PSN + + D3 + Bits 0-15 : Least significant Word of Function PSN + + D4 + Bit 15 : CSA Enabled Status + Bit 14 : CSA Support Status + Bit 9 : CSA No Format Status + Bit 8 : CSA Write Protect Status + Bit 0 : Function Wake Up Support status + + Description + Status of SDIO Function Initialization operation. +*/ +#define CY_RESP_SDIO_INIT_FUNCTION (35) + +/* Summary + Status of SDIO operation to query the Card + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 2 + * Request code = 36 + + + D0 + Bits 8-15 : Number of IO functions present + Bit 0: 1 if memory is present + + D1 + Bits 0-15 : Card Manufacturer ID + + D2 + Bits 0-15 : Card Manufacturer Additional Information + + D3 + Bits 0-15 : Function 0 Block Size + + D4 + Bits 8-15 :SDIO Card Capability register + Bits 0-7: SDIO Version + + + Description + Status of SDIO Card Query operation. + */ +#define CY_RESP_SDIO_QUERY_CARD (36) +/* Summary + Status of SDIO CIS read operation + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 37 + + D0 + Bit 8 : 1 + Bits 0-7: Error Status + + D1 + Bits 0 - 7 : Size of data read. + + Description + Status of SDIO Get Tuple Read operation. + */ +#define CY_RESP_SDIO_GET_TUPLE (37) + +/* Summary + Status of SDIO Direct read/write operation. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 38 + + D0 + Bit 8 : Error Status + Bits 0-7: Data Read(If any) + + Description + Status of SDIO Direct read write operation. + +*/ +#define CY_RESP_SDIO_DIRECT (38) + +/* Summary + Indicates an un-initialized function has been used for IO + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 39 + + Description + Indicates an IO request on an uninitialized function. +*/ +#define CY_RESP_SDIO_INVALID_FUNCTION (39) + +/* Summary + Response to a Resume request + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 2 + * Request code = 40 + + D0 + Bits 8-15 : Error Status + Bit 0: 1 if data is available. 0 otherwise. + + Description + Response to a Resume request. Indicates if data is + available after resum or not. +*/ +#define CY_RESP_SDIO_RESUME (40) + +/******************************************************/ + +/*@@USB requests + Summary + The USB requests include: + * CY_RQT_START_USB + * CY_RQT_STOP_USB + * CY_RQT_SET_CONNECT_STATE + * CY_RQT_GET_CONNECT_STATE + * CY_RQT_SET_USB_CONFIG + * CY_RQT_GET_USB_CONFIG + * CY_RQT_STALL_ENDPOINT + * CY_RQT_GET_STALL + * CY_RQT_SET_DESCRIPTOR + * CY_RQT_GET_DESCRIPTOR + * CY_RQT_SET_USB_CONFIG_REGISTERS + * CY_RQT_USB_EVENT + * CY_RQT_USB_EP_DATA + * CY_RQT_ENDPOINT_SET_NAK + * CY_RQT_GET_ENDPOINT_NAK + * CY_RQT_ACK_SETUP_PACKET + * CY_RQT_SCSI_INQUIRY_COMMAND + * CY_RQT_SCSI_START_STOP_COMMAND + * CY_RQT_SCSI_UNKNOWN_COMMAND + * CY_RQT_USB_REMOTE_WAKEUP + * CY_RQT_CLEAR_DESCRIPTORS + * CY_RQT_USB_STORAGE_MONITOR + * CY_RQT_USB_ACTIVITY_UPDATE + * CY_RQT_MS_PARTITION_SELECT + */ +#ifndef __doxygen__ +#define CY_RQT_USB_RQT_CONTEXT (3) +#endif + +/* Summary + This command requests initialization of the USB stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 0 + + Description + This command is required before any other USB related command can be + sent to the West Bridge firmware. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_ALREADY_RUNNING + */ +#define CY_RQT_START_USB (0) + + +/* Summary + This command requests shutdown of the USB stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 1 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_STOP_USB (1) + + +/* Summary + This command requests that the USB pins be connected + or disconnected to/from the West Bridge device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 2 + + D0 + Desired Connect State + * 0 = DISCONNECTED + * 1 = CONNECTED + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_SET_CONNECT_STATE (2) + + +/* Summary + This command requests the connection state of the + West Bridge USB pins. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 3 + + Responses + * CY_RESP_CONNECT_STATE + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_GET_CONNECT_STATE (3) + + +/* Summary + This request configures the USB subsystem. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 3 + * Request Code = 4 + + D0 + Bits 8 - 15: Media to enumerate (bit mask) + Bits 0 - 7: Enumerate Mass Storage (bit mask) + * 1 = Enumerate device on bus 0 + * 2 = Enumerate device on bus 1 + + D1 + Enumeration Methodology + * 1 = West Bridge enumeration + * 0 = P Port enumeration + + D2 + Mass storage interface number - Interface number to + be used for the mass storage interface + + D3 + Mass storage callbacks + * 1 = relay to P port + * 0 = completely handle in firmware + + Description + This indicates how enumeration should be handled. + Enumeration can be handled by the West Bridge device + or by the P port processor. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_MASK + * CY_RESP_SUCCESS_FAILURE:CY_ERR_INVALID_STORAGE_MEDIA + */ +#define CY_RQT_SET_USB_CONFIG (4) + + +/* Summary + This request retrieves the current USB configuration from + the West Bridge device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 5 + + Responses + * CY_RESP_USB_CONFIG + */ +#define CY_RQT_GET_USB_CONFIG (5) + + +/* Summary + This request stalls the given endpoint. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 6 + + D0 + Endpoint Number + + D1 + * 1 = Stall Endpoint + * 0 = Clear Stall + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT + */ +#define CY_RQT_STALL_ENDPOINT (6) + + +/* Summary + This request retrieves the stall status of the + requested endpoint. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 7 + + D0 + Endpoint number + + Responses + * CY_RESP_ENDPOINT_STALL + * CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT + */ +#define CY_RQT_GET_STALL (7) + + +/* Summary + This command sets the contents of a descriptor. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 8 + + D0 + Bit 15 - Bit 8 + Descriptor Index + + Bit 7 - Bit 0 + Descriptor Type + * Device = 1 + * Device Qualifier = 2 + * Full Speed Configuration = 3 + * High Speed Configuration = 4 + + * D1 - DN * + Actual data for the descriptor + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_TYPE + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_INDEX + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_LENGTH + */ +#define CY_RQT_SET_DESCRIPTOR (8) + +/* Summary + This command gets the contents of a descriptor. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 9 + + D0 + Bit 15 - Bit 8 + Descriptor Index + + Bit 7 - Bit 0 + Descriptor Type + * Device = 1 + * Device Qualifier = 2 + * Full Speed Configuration = 3 + * High Speed Configuration = 4 + + Responses + * CY_RESP_USB_DESCRIPTOR + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_TYPE + * CY_RESP_SUCCESS_FAILURE:CY_ERR_BAD_INDEX + */ +#define CY_RQT_GET_DESCRIPTOR (9) + +/* Summary + This request is sent from the P port processor to the + West Bridge device to physically configure the endpoints + in the device. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 3 + + MailBox0 + * Context = 3 + * Request Code = 10 + + D0 + Bit 15 - Bit 8 + EP1OUTCFG register value + Bit 7 - Bit 0 + EP1INCFG register value + + * D1 - D2 * + PEPxCFS register values where x = 3, 5, 7, 9 + + * D3 - D7 * + LEPxCFG register values where x = 3, 5, 7, 9, 10, + 11, 12, 13, 14, 15 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_SET_USB_CONFIG_REGISTERS (10) + +/* Summary + This request is sent to the P port processor when a + USB event occurs and needs to be relayed to the + P port. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Request Code = 11 + + D0 + Event Type + * 0 = Reserved + * 1 = Reserved + * 2 = USB Suspend + * 3 = USB Resume + * 4 = USB Reset + * 5 = USB Set Configuration + * 6 = USB Speed change + + D1 + If EventTYpe is USB Speed change + * 0 = Full Speed + * 1 = High Speed + + If EventType is USB Set Configuration + * The number of the configuration to use + * (may be zero to unconfigure) + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_USB_EVENT (11) + +/* Summary + This request is sent in both directions to transfer + endpoint data for endpoints 0 and 1. + + Direction + West Bridge -> P Port Processor + P Port Processor -> West Bridge + + Length (in transfers) + Variable + + Mailbox0 + * Context = 3 + * Request Code = 12 + + D0 + Bit 15 - 14 Data Type + * 0 = Setup (payload should be the 8 byte setup packet) + * 1 = Data + * 2 = Status (payload should be empty) + + Bit 13 Endpoint Number (only 0 and 1 supported) + Bit 12 First Packet (only supported for Host -> + West Bridge traffic) + Bit 11 Last Packet (only supported for Host -> + West Bridge traffic) + + Bit 9 - 0 Data Length (real max data length is 64 bytes + for EP0 and EP1) + + *D1-Dn* + Endpoint data +*/ +#define CY_RQT_USB_EP_DATA (12) + + +/* Summary + This request sets the NAK bit on an endpoint. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 13 + + D0 + Endpoint Number + + D1 + * 1 = NAK Endpoint + * 0 = Clear NAK + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT + */ +#define CY_RQT_ENDPOINT_SET_NAK (13) + + +/* Summary + This request retrieves the NAK config status of the + requested endpoint. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Request Code = 14 + + D0 + Endpoint number + + Responses + * CY_RESP_ENDPOINT_NAK + * CY_RESP_SUCCESS_FAILURE:CY_RESP_INVALID_ENDPOINT + */ +#define CY_RQT_GET_ENDPOINT_NAK (14) + +/* Summary + This request acknowledges a setup packet that does not + require any data transfer. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox + * Context = 3 + * Request Code = 15 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_ACK_SETUP_PACKET (15) + +/* Summary + This request is sent when the USB storage driver within + West Bridge receives an Inquiry request. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + x - variable + + Mailbox0 + * Context = 3 + * Request Code = 16 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Media type being addressed + + D1 + Bits 8 : EVPD bit from request + Bits 0 - 7 : Codepage from the inquiry request + + D2 + Length of the inquiry response in bytes + + * D3 - Dn * + The inquiry response + + Description + When the West Bridge firmware receives an SCSI Inquiry + request from the USB host, the response to this mass + storage command is created by West Bridge and forwarded to + the P port processor. The P port processor may change + this response before it is returned to the USB host. This + request is the method by which this may happen. +*/ +#define CY_RQT_SCSI_INQUIRY_COMMAND (16) + +/* Summary + This request is sent when the USB storage driver within + West Bridge receives a Start/Stop request. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Request Code = 17 + + D0 + Bits 12 - 15 : Bus index + Bits 8 - 11 : Zero based device index + Bits 0 - 7 : Media type being addressed + + D1 + Bit 1 + * LoEj Bit (See SCSI-3 specification) + + Bit 0 + * Start Bit (See SCSI-3 specification) + + Description + When the West Bridge firmware received a SCSI Start/Stop + request from the USB host, this request is relayed to the + P port processor. This request is used to relay the command. + The USB firmware will not response to the USB command until + the response to this request is recevied by the firmware. +*/ +#define CY_RQT_SCSI_START_STOP_COMMAND (17) + +/* Summary + This request is sent when the USB storage driver + receives an unknown CBW on mass storage. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 4 + + Mailbox0 + * Context = 3 + * Request Code = 18 + + D0 + Bits 12 - 15 : MediaType + * 0 = NAND + * 1 = SDIO Flash + * 2 = MMC Flash + * 3 = CE-ATA + + D1 + The length of the request in bytes + + D2 - Dn + CBW command block from the SCSI host controller. + + Description + When the firmware recevies a SCSI request that is not + understood, this request is relayed to the + P port processor. +*/ +#define CY_RQT_SCSI_UNKNOWN_COMMAND (18) + +/* Summary + Request the West Bridge to signal remote wakeup + to the USB host. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Request code = 19 + + Description + Request from the processor to West Bridge, to signal + remote wakeup to the USB host. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_USB_REMOTE_WAKEUP (19) + +/* Summary + Request the West Bridge to clear all descriptors tha + were set previously + using the Set Descriptor calls. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Request code = 20 + + Description + Request from the processor to West Bridge, to clear + all descriptor information that was previously stored + on the West Bridge using CyAnUsbSetDescriptor calls. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_CLEAR_DESCRIPTORS (20) + +/* Summary + Request the West Bridge to monitor USB to storage activity + and send periodic updates. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + Mailbox0 + * Context = 3 + * Request code = 21 + + D0 + Upper 16 bits of write threshold + + D1 + Lower 16 bits of write threshold + + D2 + Upper 16 bits of read threshold + + D3 + Lower 16 bits of read threshold + + Description + Request from the processor to West Bridge, to start + monitoring the level of read/write activity on the + USB mass storage drive and to set the threshold + level at which progress reports are sent. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_USB_STORAGE_MONITOR (21) + +/* Summary + Event from the West Bridge showing that U2S activity + since the last event has crossed the threshold. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 3 + * Request code = 22 + + D0 + Upper 16 bits of sectors written since last event. + + D1 + Lower 16 bits of sectors written since last event. + + D2 + Upper 16 bits of sectors read since last event. + + D3 + Lower 16 bits of sectors read since last event. + + Description + Event notification from the West Bridge indicating + that the number of read/writes on the USB mass + storage device have crossed a pre-defined threshold + level. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_USB_ACTIVITY_UPDATE (22) + +/* Summary + Request to select the partitions to be enumerated on a + storage device with partitions. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Request code = 23 + + D0 + Bits 8-15 : Bus index + Bits 0- 7 : Device index + + D1 + Bits 8-15 : Control whether to enumerate partition 1. + Bits 0- 7 : Control whether to enumerate partition 0. + + Responses + * CY_RESP_SUCCESS_FAILURE + */ +#define CY_RQT_MS_PARTITION_SELECT (23) + +/************/ + +/*@@USB responses + Summary + The USB responses include: + * CY_RESP_USB_CONFIG + * CY_RESP_ENDPOINT_CONFIG + * CY_RESP_ENDPOINT_STALL + * CY_RESP_CONNECT_STATE + * CY_RESP_USB_DESCRIPTOR + * CY_RESP_USB_INVALID_EVENT + * CY_RESP_ENDPOINT_NAK + * CY_RESP_INQUIRY_DATA + * CY_RESP_UNKNOWN_SCSI_COMMAND + */ + +/* Summary + This response contains the enumeration configuration + information for the USB module. + + Direction + 8051->P + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Response Code = 32 + + D0 + Bits 8 - 15: Media to enumerate (bit mask) + Bits 0 - 7: Buses to enumerate (bit mask) + * 1 = Bus 0 + * 2 = Bus 1 + + D1 + Enumeration Methodology + * 0 = West Bridge enumeration + * 1 = P Port enumeration + + D2 + Bits 7 - 0 : Interface Count - the number of interfaces + Bits 15 - 8 : Mass storage callbacks + + */ +#define CY_RESP_USB_CONFIG (32) + + +/* Summary + This response contains the configuration information + for the specified endpoint. + + Direction + 8051->P + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Response Code = 33 + + D0 + Bits 15 - 12 : Endpoint Number (0 - 15) + + Bits 11 - 10 : Endpoint Type + * 0 = Control + * 1 = Bulk + * 2 = Interrupt + * 3 = Isochronous + + Bits 9 : Endpoint Size + * 0 = 512 + * 1 = 1024 + + Bits 8 - 7 : Buffering + * 0 = Double + * 1 = Triple + * 2 = Quad + + Bits 6 : Bit Direction + * 0 = Input + * 1 = Output + */ +#define CY_RESP_ENDPOINT_CONFIG (33) + + +/* Summary + This response contains the stall status for + the specified endpoint. + + Direction + 8051->P + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Response Code = 34 + + D0 + Stall status + * 0 = Active + * 1 = Stalled + */ +#define CY_RESP_ENDPOINT_STALL (34) + + +/* Summary + This response contains the connected/disconnected + state of the West Bridge USB pins. + + Direction + 8051->P + + Length (in transfers) + 1 + + MailBox0 + * Context = 3 + * Response Code = 35 + + D0 + Connect state + * 0 = Disconnected + * 1 = Connected + */ +#define CY_RESP_CONNECT_STATE (35) + +/* Summary + This response contains the information + about the USB configuration + + Direction + West Bridge -> P Port Processor + + Length + x bytes + + Mailbox0 + * Context = 3 + * Response Code = 36 + + D0 + Length in bytes of the descriptor + + * D1 - DN * + Descriptor contents +*/ +#define CY_RESP_USB_DESCRIPTOR (36) + +/* Summary + This response is sent in response to a bad USB event code + + Direction + P Port Processor -> West Bridge + + Length + 1 word (2 bytes) + + Mailbox0 + * Context = 3 + * Response Code = 37 + + D0 + The invalid event code in the request +*/ +#define CY_RESP_USB_INVALID_EVENT (37) + +/* Summary + This response contains the current NAK status of + a USB endpoint. + + Direction + West Bridge -> P port processor + + Length + 1 transfer + + Mailbox0 + * Context = 3 + * Response Code = 38 + + D0 + The NAK status of the endpoint + 1 : NAK bit set + 0 : NAK bit clear +*/ +#define CY_RESP_ENDPOINT_NAK (38) + +/* Summary + This response gives the contents of the inquiry + data back to West Bridge to returns to the USB host. + + Direction + West Bridge -> P Port Processor + + Length + Variable + + MailBox0 + * Context = 3 + * Response Code = 39 + + D0 + Length of the inquiry response + + *D1 - Dn* + Inquiry data +*/ +#define CY_RESP_INQUIRY_DATA (39) + +/* Summary + This response gives the status of an unknown SCSI command. + This also gives three bytes of sense information. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 3 + * Response Code = 40 + + D0 + The length of the reply in bytes + + D1 + * Status of the command + * Sense Key + + D2 + * Additional Sense Code (ASC) + * Additional Sense Code Qualifier (ASCQ) +*/ +#define CY_RESP_UNKNOWN_SCSI_COMMAND (40) +/*******************************************************/ + +/*@@Turbo requests + Summary + The Turbo requests include: + * CY_RQT_START_MTP + * CY_RQT_STOP_MTP + * CY_RQT_INIT_SEND_OBJECT + * CY_RQT_CANCEL_SEND_OBJECT + * CY_RQT_INIT_GET_OBJECT + * CY_RQT_CANCEL_GET_OBJECT + * CY_RQT_SEND_BLOCK_TABLE + * CY_RQT_MTP_EVENT + * CY_RQT_TURBO_CMD_FROM_HOST + * CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST + * CY_RQT_TURBO_SWITCH_ENDPOINT + * CY_RQT_TURBO_START_WRITE_DMA + * CY_RQT_ENABLE_USB_PATH + * CY_RQT_CANCEL_ASYNC_TRANSFER + */ +#ifndef __doxygen__ +#define CY_RQT_TUR_RQT_CONTEXT (4) +#endif + +/* Summary + This command requests initialization of the MTP stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 0 + + Description + This command is required before any other MTP related + command can be sent to the West Bridge firmware. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_ALREADY_RUNNING + */ +#define CY_RQT_START_MTP (0) + +/* Summary + This command requests shutdown of the MTP stack. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 1 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_STOP_MTP (1) + +/* Summary + This command sets up an MTP SendObject operation. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 2 + + D0 + Total bytes for send object Low 16 bits + + D1 + Total bytes for send object High 16 bits + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_INIT_SEND_OBJECT (2) + +/* Summary + This command cancels West Bridges handling of + an ongoing MTP SendObject operation. This + does NOT send an MTP response. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 3 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_NO_OPERATION_PENDING + */ +#define CY_RQT_CANCEL_SEND_OBJECT (3) + +/* Summary + This command sets up an MTP GetObject operation. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 4 + * Request Code = 4 + + D0 + Total bytes for get object Low 16 bits + + D1 + Total bytes for get object High 16 bits + + D2 + Transaction Id for get object Low 16 bits + + D3 + Transaction Id for get object High 16 bits + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_INIT_GET_OBJECT (4) + +/* Summary + This command notifies West Bridge of a new + BlockTable transfer. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 5 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_SEND_BLOCK_TABLE (5) + +/* Summary + This request is sent to the P port processor when a MTP event occurs + and needs to be relayed to the P port. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 2 + + Mailbox0 + * Context = 4 + * Request Code = 6 + + D0 + Bits 15 - 8 : Return Status for GetObject/SendObject + Bits 7 - 0 : Event Type + * 0 = MTP SendObject Complete + * 1 = MTP GetObject Complete + * 2 = BlockTable Needed + + D1 + Lower 16 bits of the length of the data that got transferred + in the Turbo Endpoint.(Applicable to "MTP SendObject Complete" + and "MTP GetObject Complete" events) + + D2 + Upper 16 bits of the length of the data that got transferred + in the Turbo Endpoint. (Applicable to "MTP SendObject Complete" + and "MTP GetObject Complete" events) + + D3 + Lower 16 bits of the Transaction Id of the MTP_SEND_OBJECT + command. (Applicable to "MTP SendObject Complete" event) + + D4 + Upper 16 bits of the Transaction Id of the MTP_SEND_OBJECT + command. (Applicable to "MTP SendObject Complete" event) + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_MTP_EVENT (6) + +/* Summary + This request is sent to the P port processor when a command + is received from Host in a Turbo Endpoint. Upon receiving + this event, P port should read the data from the endpoint as + soon as possible. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + Mailbox0 + * Context = 4 + * Request Code = 7 + + D0 + This contains the EP number. (This will be always two now). + + D1 + Length of the data available in the Turbo Endpoint. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_TURBO_CMD_FROM_HOST (7) + +/* Summary + This request is sent to the West Bridge when the P port + needs to send data to the Host in a Turbo Endpoint. + Upon receiving this event, Firmware will make the end point + avilable for the P port. If the length is zero, then + firmware will send a zero length packet. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + Mailbox0 + * Context = 4 + * Request Code = 8 + + D0 + This contains the EP number. (This will be always six now). + + D1 + Lower 16 bits of the length of the data that needs to be + sent in the Turbo Endpoint. + + D2 + Upper 16 bits of the length of the data that needs to be + sent in the Turbo Endpoint. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS +*/ +#define CY_RQT_TURBO_SEND_RESP_DATA_TO_HOST (8) + +/* Summary + This command cancels West Bridges handling of + an ongoing MTP GetObject operation. This + does NOT send an MTP response. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 9 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_NO_OPERATION_PENDING + */ +#define CY_RQT_CANCEL_GET_OBJECT (9) + +/* Summary + This command switches a Turbo endpoint + from the U port to the P port. If no data + is in the endpoint the endpoint is + primed to switch as soon as data is placed + in the endpoint. The endpoint will continue + to switch until all data has been transferd. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 2 + + MailBox0 + * Context = 4 + * Request Code = 10 + + D0 + Whether the read is a packet read. + + D1 + Lower 16 bits of the length of the data to switch + the Turbo Endpoint for. + + D2 + Upper 16 bits of the length of the data to switch + the Turbo Endpoint for. + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + * CY_RESP_SUCCESS_FAILURE:CY_RESP_NOT_RUNNING + */ +#define CY_RQT_TURBO_SWITCH_ENDPOINT (10) + +/* Summary + This command requests the API to start the DMA + transfer of a packet of MTP data to the Antioch. + + Direction + West Bridge -> P Port Processor + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request Code = 11 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + */ +#define CY_RQT_TURBO_START_WRITE_DMA (11) + +/* Summary + This command requests the firmware to switch the + internal data paths to enable USB access to the + Mass storage / MTP endpoints. + + Direction + P Port Processor -> West Bridge + + Length (in transfers) + 1 + + MailBox0 + * Context = 4 + * Request code = 12 + + Responses + * CY_RESP_SUCCESS_FAILURE:CY_AS_ERROR_SUCCESS + */ +#define CY_RQT_ENABLE_USB_PATH (12) + +/* Summary + Request to cancel an asynchronous MTP write from + the processor side. + + Direction + P Port processor -> West Bridge + + Length (in transfers) + 1 + + Mailbox0 + * Context = 4 + * Request code = 13 + + D0 + * EP number + + Description + This is a request to the firmware to update internal + state so that a pending write on the MTP endpoint + can be cancelled. + */ +#define CY_RQT_CANCEL_ASYNC_TRANSFER (13) + +/******************************************************/ + +/*@@Turbo responses + Summary + The Turbo responses include: + * CY_RESP_MTP_INVALID_EVENT + */ + +/* Summary + This response is sent in response to a bad MTP event code + + Direction + P Port Processor -> West Bridge + + Length + 1 word (2 bytes) + + Mailbox0 + * Context = 4 + * Response Code = 16 + + D0 + The invalid event code in the request +*/ +#define CY_RESP_MTP_INVALID_EVENT (16) + +#ifndef __doxygen__ +#define CY_RQT_CONTEXT_COUNT (5) +#endif + +#endif /* _INCLUDED_CYASPROTOCOL_H_ */ + diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h new file mode 100644 index 000000000000..f049d7e32a4b --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasregs.h @@ -0,0 +1,201 @@ +/* Cypress West Bridge API header file (cyasregs.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASREG_H_ +#define _INCLUDED_CYASREG_H_ + +#if !defined(__doxygen__) + +#define CY_AS_MEM_CM_WB_CFG_ID (0x80) +#define CY_AS_MEM_CM_WB_CFG_ID_VER_MASK (0x000F) +#define CY_AS_MEM_CM_WB_CFG_ID_HDID_MASK (0xFFF0) +#define CY_AS_MEM_CM_WB_CFG_ID_HDID_ANTIOCH_VALUE (0xA100) +#define CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_FPGA_VALUE (0x6800) +#define CY_AS_MEM_CM_WB_CFG_ID_HDID_ASTORIA_VALUE (0xA200) + + +#define CY_AS_MEM_RST_CTRL_REG (0x81) +#define CY_AS_MEM_RST_CTRL_REG_HARD (0x0003) +#define CY_AS_MEM_RST_CTRL_REG_SOFT (0x0001) +#define CY_AS_MEM_RST_RSTCMPT (0x0004) + +#define CY_AS_MEM_P0_ENDIAN (0x82) +#define CY_AS_LITTLE_ENDIAN (0x0000) +#define CY_AS_BIG_ENDIAN (0x0101) + +#define CY_AS_MEM_P0_VM_SET (0x83) +#define CY_AS_MEM_P0_VM_SET_VMTYPE_MASK (0x0007) +#define CY_AS_MEM_P0_VM_SET_VMTYPE_RAM (0x0005) +#define CY_AS_MEM_P0_VM_SET_VMTYPE_SRAM (0x0007) +#define CY_AS_MEM_P0_VM_SET_VMTYPE_VMWIDTH (0x0008) +#define CY_AS_MEM_P0_VM_SET_VMTYPE_FLOWCTRL (0x0010) +#define CY_AS_MEM_P0_VM_SET_IFMODE (0x0020) +#define CY_AS_MEM_P0_VM_SET_CFGMODE (0x0040) +#define CY_AS_MEM_P0_VM_SET_DACKEOB (0x0080) +#define CY_AS_MEM_P0_VM_SET_OVERRIDE (0x0100) +#define CY_AS_MEM_P0_VM_SET_INTOVERD (0x0200) +#define CY_AS_MEM_P0_VM_SET_DRQOVERD (0x0400) +#define CY_AS_MEM_P0_VM_SET_DRQPOL (0x0800) +#define CY_AS_MEM_P0_VM_SET_DACKPOL (0x1000) + + +#define CY_AS_MEM_P0_NV_SET (0x84) +#define CY_AS_MEM_P0_NV_SET_WPSWEN (0x0001) +#define CY_AS_MEM_P0_NV_SET_WPPOLAR (0x0002) + +#define CY_AS_MEM_PMU_UPDATE (0x85) +#define CY_AS_MEM_PMU_UPDATE_UVALID (0x0001) +#define CY_AS_MEM_PMU_UPDATE_USBUPDATE (0x0002) +#define CY_AS_MEM_PMU_UPDATE_SDIOUPDATE (0x0004) + +#define CY_AS_MEM_P0_INTR_REG (0x90) +#define CY_AS_MEM_P0_INTR_REG_MCUINT (0x0020) +#define CY_AS_MEM_P0_INTR_REG_DRQINT (0x0800) +#define CY_AS_MEM_P0_INTR_REG_MBINT (0x1000) +#define CY_AS_MEM_P0_INTR_REG_PMINT (0x2000) +#define CY_AS_MEM_P0_INTR_REG_PLLLOCKINT (0x4000) + +#define CY_AS_MEM_P0_INT_MASK_REG (0x91) +#define CY_AS_MEM_P0_INT_MASK_REG_MMCUINT (0x0020) +#define CY_AS_MEM_P0_INT_MASK_REG_MDRQINT (0x0800) +#define CY_AS_MEM_P0_INT_MASK_REG_MMBINT (0x1000) +#define CY_AS_MEM_P0_INT_MASK_REG_MPMINT (0x2000) +#define CY_AS_MEM_P0_INT_MASK_REG_MPLLLOCKINT (0x4000) + +#define CY_AS_MEM_MCU_MB_STAT (0x92) +#define CY_AS_MEM_P0_MCU_MBNOTRD (0x0001) + +#define CY_AS_MEM_P0_MCU_STAT (0x94) +#define CY_AS_MEM_P0_MCU_STAT_CARDINS (0x0001) +#define CY_AS_MEM_P0_MCU_STAT_CARDREM (0x0002) + +#define CY_AS_MEM_PWR_MAGT_STAT (0x95) +#define CY_AS_MEM_PWR_MAGT_STAT_WAKEUP (0x0001) + +#define CY_AS_MEM_P0_RSE_ALLOCATE (0x98) +#define CY_AS_MEM_P0_RSE_ALLOCATE_SDIOAVI (0x0001) +#define CY_AS_MEM_P0_RSE_ALLOCATE_SDIOALLO (0x0002) +#define CY_AS_MEM_P0_RSE_ALLOCATE_NANDAVI (0x0004) +#define CY_AS_MEM_P0_RSE_ALLOCATE_NANDALLO (0x0008) +#define CY_AS_MEM_P0_RSE_ALLOCATE_USBAVI (0x0010) +#define CY_AS_MEM_P0_RSE_ALLOCATE_USBALLO (0x0020) + +#define CY_AS_MEM_P0_RSE_MASK (0x9A) +#define CY_AS_MEM_P0_RSE_MASK_MSDIOBUS_RW (0x0003) +#define CY_AS_MEM_P0_RSE_MASK_MNANDBUS_RW (0x00C0) +#define CY_AS_MEM_P0_RSE_MASK_MUSBBUS_RW (0x0030) + +#define CY_AS_MEM_P0_DRQ (0xA0) +#define CY_AS_MEM_P0_DRQ_EP2DRQ (0x0004) +#define CY_AS_MEM_P0_DRQ_EP3DRQ (0x0008) +#define CY_AS_MEM_P0_DRQ_EP4DRQ (0x0010) +#define CY_AS_MEM_P0_DRQ_EP5DRQ (0x0020) +#define CY_AS_MEM_P0_DRQ_EP6DRQ (0x0040) +#define CY_AS_MEM_P0_DRQ_EP7DRQ (0x0080) +#define CY_AS_MEM_P0_DRQ_EP8DRQ (0x0100) +#define CY_AS_MEM_P0_DRQ_EP9DRQ (0x0200) +#define CY_AS_MEM_P0_DRQ_EP10DRQ (0x0400) +#define CY_AS_MEM_P0_DRQ_EP11DRQ (0x0800) +#define CY_AS_MEM_P0_DRQ_EP12DRQ (0x1000) +#define CY_AS_MEM_P0_DRQ_EP13DRQ (0x2000) +#define CY_AS_MEM_P0_DRQ_EP14DRQ (0x4000) +#define CY_AS_MEM_P0_DRQ_EP15DRQ (0x8000) + +#define CY_AS_MEM_P0_DRQ_MASK (0xA1) +#define CY_AS_MEM_P0_DRQ_MASK_MEP2DRQ (0x0004) +#define CY_AS_MEM_P0_DRQ_MASK_MEP3DRQ (0x0008) +#define CY_AS_MEM_P0_DRQ_MASK_MEP4DRQ (0x0010) +#define CY_AS_MEM_P0_DRQ_MASK_MEP5DRQ (0x0020) +#define CY_AS_MEM_P0_DRQ_MASK_MEP6DRQ (0x0040) +#define CY_AS_MEM_P0_DRQ_MASK_MEP7DRQ (0x0080) +#define CY_AS_MEM_P0_DRQ_MASK_MEP8DRQ (0x0100) +#define CY_AS_MEM_P0_DRQ_MASK_MEP9DRQ (0x0200) +#define CY_AS_MEM_P0_DRQ_MASK_MEP10DRQ (0x0400) +#define CY_AS_MEM_P0_DRQ_MASK_MEP11DRQ (0x0800) +#define CY_AS_MEM_P0_DRQ_MASK_MEP12DRQ (0x1000) +#define CY_AS_MEM_P0_DRQ_MASK_MEP13DRQ (0x2000) +#define CY_AS_MEM_P0_DRQ_MASK_MEP14DRQ (0x4000) +#define CY_AS_MEM_P0_DRQ_MASK_MEP15DRQ (0x8000) + +#define CY_AS_MEM_P0_EP2_DMA_REG (0xA2) +#define CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK (0x7FF) +#define CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL (1 << 12) +#define CY_AS_MEM_P0_EP3_DMA_REG (0xA3) +#define CY_AS_MEM_P0_EP4_DMA_REG (0xA4) +#define CY_AS_MEM_P0_EP5_DMA_REG (0xA5) +#define CY_AS_MEM_P0_EP6_DMA_REG (0xA6) +#define CY_AS_MEM_P0_EP7_DMA_REG (0xA7) +#define CY_AS_MEM_P0_EP8_DMA_REG (0xA8) +#define CY_AS_MEM_P0_EP9_DMA_REG (0xA9) +#define CY_AS_MEM_P0_EP10_DMA_REG (0xAA) +#define CY_AS_MEM_P0_EP11_DMA_REG (0xAB) +#define CY_AS_MEM_P0_EP12_DMA_REG (0xAC) +#define CY_AS_MEM_P0_EP13_DMA_REG (0xAD) +#define CY_AS_MEM_P0_EP14_DMA_REG (0xAE) +#define CY_AS_MEM_P0_EP15_DMA_REG (0xAF) + +#define CY_AS_MEM_IROS_SLB_DATARET (0xC0) + +#define CY_AS_MEM_IROS_IO_CFG (0xC1) +#define CY_AS_MEM_IROS_IO_CFG_GPIODRVST_MASK (0x0003) +#define CY_AS_MEM_IROS_IO_CFG_GPIOSLEW_MASK (0x0004) +#define CY_AS_MEM_IROS_IO_CFG_PPIODRVST_MASK (0x0018) +#define CY_AS_MEM_IROS_IO_CFG_PPIOSLEW_MASK (0x0020) +#define CY_AS_MEM_IROS_IO_CFG_SSIODRVST_MASK (0x0300) +#define CY_AS_MEM_IROS_IO_CFG_SSIOSLEW_MASK (0x0400) +#define CY_AS_MEM_IROS_IO_CFG_SNIODRVST_MASK (0x1800) +#define CY_AS_MEM_IROS_IO_CFG_SNIOSLEW_MASK (0x2000) + +#define CY_AS_MEM_IROS_PLL_CFG (0xC2) + +#define CY_AS_MEM_IROS_PXB_DATARET (0xC3) + +#define CY_AS_MEM_PLL_LOCK_LOSS_STAT (0xC4) +#define CY_AS_MEM_PLL_LOCK_LOSS_STAT_PLLSTAT (0x0800) + +#define CY_AS_MEM_IROS_SLEEP_CFG (0xC5) + +#define CY_AS_MEM_PNAND_CFG (0xDA) +#define CY_AS_MEM_PNAND_CFG_IOWIDTH_MASK (0x0001) +#define CY_AS_MEM_PNAND_CFG_IOWIDTH_8BIT (0x0000) +#define CY_AS_MEM_PNAND_CFG_IOWIDTH_16BIT (0x0001) +#define CY_AS_MEM_PNAND_CFG_BLKTYPE_MASK (0x0002) +#define CY_AS_MEM_PNAND_CFG_BLKTYPE_SMALL (0x0002) +#define CY_AS_MEM_PNAND_CFG_BLKTYPE_LARGE (0x0000) +#define CY_AS_MEM_PNAND_CFG_EPABYTE_POS (4) +#define CY_AS_MEM_PNAND_CFG_EPABYTE_MASK (0x0030) +#define CY_AS_MEM_PNAND_CFG_EPABIT_POS (6) +#define CY_AS_MEM_PNAND_CFG_EPABIT_MASK (0x00C0) +#define CY_AS_MEM_PNAND_CFG_LNAEN_MASK (0x0100) + +#define CY_AS_MEM_P0_MAILBOX0 (0xF0) +#define CY_AS_MEM_P0_MAILBOX1 (0xF1) +#define CY_AS_MEM_P0_MAILBOX2 (0xF2) +#define CY_AS_MEM_P0_MAILBOX3 (0xF3) + +#define CY_AS_MEM_MCU_MAILBOX0 (0xF8) +#define CY_AS_MEM_MCU_MAILBOX1 (0xF9) +#define CY_AS_MEM_MCU_MAILBOX2 (0xFA) +#define CY_AS_MEM_MCU_MAILBOX3 (0xFB) + +#endif /* !defined(__doxygen__) */ + +#endif /* _INCLUDED_CYASREG_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h new file mode 100644 index 000000000000..52d3d688a47c --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage.h @@ -0,0 +1,2759 @@ +/* Cypress West Bridge API header file (cyasstorage.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASSTORAGE_H_ +#define _INCLUDED_CYASSTORAGE_H_ + +#include "cyasmedia.h" +#include "cyasmisc.h" +#include "cyas_cplus_start.h" + + +/*@@Storage APIs + Summary + This section documents the storage APIs supported by the + West Bridge API. + + Description + The storage API is based on some specific concepts which + are referenced here. + * + * Addressing + * Ownership + * +*/ + +/*@@Storage API Overview + Summary + Storage devices are identified by media type. Each media + type is considered a single logical device. + + Description + Each media type has a consistent block size and consists + of a set of logical blocks numbered from 0 to N - 1 where + N is the size of the + media type in blocks. The mass storage APIs defined below + provide the + capability to query for devices that are present, and + read/write data to/from + these devices. +*/ + +/*@@Addressing + Summary + Blocks within a storage device are address by a hierarchal + block address. This + address consists of the bus number, physical device, + logical unit, and finally + block address. + + Description + While currently only a single device of each media type + is supported, the address + space reserves space in the future for multiple devices + of each type. Therefore + the second element of the address is the specific device + being addressed within + a given device type. For this release of the software, + this value will always be + zero to address the first device. + + The third element of the address is the logical unit. + A device being managed + by West Bridge can be partitioned into multiple logical + units. This partition + information is stored on each device itself. Currently, + one of the storage devices + managed by West Bridge can be partitioned into two + logical units. + + Finally a logical block address is given within the + logical unit to address an + individual block. +*/ + +/*@@Ownership + Summary + While West Bridge supports concurrent block level + operations from both the USB port and + the processor port, this is not desirable in most + situations as the file system + contained on the storage media cannot be accessed + concurrently. To insure access + by only one of USB and the processor, the West Bridge + API provides for ownership of storage + devices based on media type. + + Description + The processor requests ownership of a given media type + by calling CyAsStorageClaim(). + The firmware in West Bridge releases control of the + media and signals the processor through + the event callback registered with + CyAsStorageRegisterCallback(). The specific event is + the CyAsStorageProcessor. The processor can later + release the media via a call to + CyAsStorageRelease(). This call is immediate and + no callback is required. + + If the processor has claimed storage and the USB port + is connected, West Bridge will need to + claim the storage to manage the mass storage device. + West Bridge requests the storage through + the event callback registered with + CyAsStorageRegisterCallback(). The specific event is + CyAsStorageAntioch and is named as such to reflect + the USB view of storage. This callback + is a request for the processor to release storage. + The storage is not actually released + until the processor calls CyAsStorageRelease(). + + Note that the CyAsStorageAntioch is only sent when the + USB storage device is enumerated and + NOT at every USB operation. The ownership of a given + storage media type is assumed to belong + to the processor until the USB connection is established. + At that point, the storage ownership + is transferred to West Bridge. After the USB connection + is broken, ownership can be transferred + back to the processor. +*/ + +/*@@Asynchronous Versus Synchronous Operation + Summary + When read or write operations are performed to the + storage devices, these operations may be + synchronous or asynchronous. A synchronous operation + is an operation where the read or write + operation is requested and the function does not return + until the operation is complete. This + type of function is the easiest to use but does not + provide for optimal usage of the P port processor time. + + Description + An asynchronous operation is one where the function returns + as soon as the request is started. + The specific read and write request will complete at some + time in the future and the P port + processor will be notified via a callback function. While + asynchronous functions provide for + much better usage of the CPU, these function have more + stringent requirements for use. First, + any buffer use for data transfer must be valid from the + function call to request the operation + through when the callback function is called. This basically + implies that stack based buffers + are not acceptable for asynchronous calls. Second, error + handling must be deferred until the + callback function is called indicating any kind of error + that may have occurred. +*/ + +/*@@Partitioning + Summary + West Bridge API and firmware support the creation of up to + two logical partitions on one + of the storage devices that are managed by West Bridge. The + partitions are managed through + the CyAsStorageCreatePPartition and CyAsStorageRemovePPartition + APIs. + + Description + The CyAsStorageCreatePPartition API is used to divide the total + storage on a storage + device into two logical units or partitions. Since the partition + information is stored + on the storage device in a custom format, partitions should + only be created on fixed + storage devices (i.e., no removable SD/MMC cards). Any data + stored on the device + before the creation of the partition, is liable to be lost when + a partition is created. + + The CyAsStorageRemovePPartition API is used to remove the + stored partition information, + so that all of the device's capacity is treated as a single + partition again. + + When a storage device with two partitions (units) is being + enumerated as a mass storage + device through the West Bridge, it is possible to select the + partitions to be made + visible to the USB host. This is done through the + CyAsUsbSelectMSPartitions API. +*/ + +/********************************* + * West Bridge Constants + **********************************/ + +/* Summary + This constants indicates a raw device access to the read/write + functions + + Description + When performing reading and writing operations on the + storage devices attached + to West Bridge, there are cases where writes need to + happen to raw devices, versus + the units contained within a device. This is + specifically required to manage + the partitions within physical devices. This constant + is used in calls to + CyAsStorageRead(), CyAsStorageReadAsync(), + CyAsStorageWrite() and + CyAsStorageWriteAsync(), to indicate that the raw + physical device is being + accessed and not any specific unit on the device. + + See Also + * CyAsStorageRead + * CyAsStorageReadAsync + * CyAsStorageWrite + * CyAsStorageWriteAsync +*/ +#define CY_AS_LUN_PHYSICAL_DEVICE (0xffffffff) + +/* Summary + This constant represents the maximum DMA burst length + supported on a storage endpoint + + Description + West Bridge reserves separate endpoints for accessing + storage media through the + CyAsStorageRead() and CyAsStorageWrite() calls. The + maximum size of these + endpoints is always 512 bytes, regardless of status + and speed of the USB + connection. +*/ +#define CY_AS_STORAGE_EP_SIZE (512) + +/******************************** + * West Bridge Types + *******************************/ + +/* Summary + This type indicates the type of event in an event + callback from West Bridge + + Description + At times West Bridge needs to inform the P port + processor of events that have + occurred. These events are asynchronous to the + thread of control on the P + port processor and as such are generally delivered + via a callback function that + is called as part of an interrupt handler. This + type indicates the resonse for + the call to the callback function. + + See Also + * CyAsStorageEventCallback + * CyAsStorageRegisterCallback +*/ +typedef enum cy_as_storage_event { + /* This event occurs when the West Bridge device has + detected a USB connect and has enumerated the + storage controlled by west bridge to the USB port. + this event is the signal that the processor + needs to release the storage media. west bridge will + not have control of the storage media until the + processor calls cy_as_release_storage() to release + the specific media. */ + cy_as_storage_antioch, + + /* This event occurs when the processor has requested + ownership of a given media type and west bridge has + released the media. this event is an indicator + that the transfer of ownership is complete and the + processor now owns the given media type. */ + cy_as_storage_processor, + + /* This event occurs when a removable media type has + been removed. */ + cy_as_storage_removed, + + /* This event occurs when a removable media type has + been inserted. */ + cy_as_storage_inserted, + + /* This event occurs when the West Bridge device + * percieves an interrrupt from an SDIO card */ + cy_as_sdio_interrupt + +} cy_as_storage_event ; + +/* Summary + This type gives the type of the operation in a storage + operation callback + + Description + This type is used in the callback function for asynchronous + operation. This type indicates whether it is a + CyAsStorageRead() or CyAsStorageWrite() operation that + has completed. + + See Also + * + * CyAsStorageRead + * CyAsStorageWrite +*/ +typedef enum cy_as_oper_type { + /* A data read operation */ + cy_as_op_read, + /* A data write operation */ + cy_as_op_write +} cy_as_oper_type ; + +/* Summary + This data structure describes a specific type of media + + Description + This data structure is the return value from the + CyAsStorageQueryDevice function. This structure provides + information about the specific storage device being queried. + + See Also + * CyAsStorageQueryDevice +*/ +typedef struct cy_as_device_desc { + /* Type of device */ + cy_as_media_type type ; + /* Is the device removable */ + cy_bool removable ; + /* Is the device writeable */ + cy_bool writeable ; + /* Basic block size for device */ + uint16_t block_size ; + /* Number of LUNs on the device */ + uint32_t number_units ; + /* Is the device password locked */ + cy_bool locked ; + /* Size in bytes of an Erase Unit. Block erase operation + is only supported for SD storage, and the erase_unit_size + is invalid for all other kinds of storage. */ + uint32_t erase_unit_size ; +} cy_as_device_desc ; + +/* Summary + This data structure describes a specific unit on a + specific type of media + + Description + This data structure is the return value from the + CyAsStorageQueryUnit function. This structure provides + information about the specific unit. + + See Also + * CyAsStorageQueryUnit +*/ +typedef struct cy_as_unit_desc { + /* Type of device */ + cy_as_media_type type ; + /* Basic block size for device */ + uint16_t block_size ; + /* Physical start block for LUN */ + uint32_t start_block ; + /* Number of blocks in the LUN */ + uint32_t unit_size ; +} cy_as_unit_desc ; + +/* Summary + This function type defines a callback to be called after an + asynchronous operation + + Description + This function type defines a callback function that is called + at the completion of any asynchronous read or write operation. + + See Also + * CyAsStorageReadAsync() + * CyAsStorageWriteAsync() +*/ +typedef void (*cy_as_storage_callback)( + /* Handle to the device completing the storage operation */ + cy_as_device_handle handle, + /* The bus completing the operation */ + cy_as_bus_number_t bus, + /* The device completing the operation */ + uint32_t device, + /* The unit completing the operation */ + uint32_t unit, + /* The block number of the completed operation */ + uint32_t block_number, + /* The type of operation */ + cy_as_oper_type op, + /* The error status */ + cy_as_return_status_t status + ) ; + +/* Summary + This function type defines a callback to be called in the + event of a storage related event + + Description + At times West Bridge needs to inform the P port processor + of events that have + occurred. These events are asynchronous to the thread of + control on the P + port processor and as such are generally delivered via a + callback function that + is called as part of an interrupt handler. This type + defines the type of function + that must be provided as a callback function. + + See Also + * CyAsStorageEvent + * CyAsStorageRegisterCallback +*/ +typedef void (*cy_as_storage_event_callback)( + /* Handle to the device sending the event notification */ + cy_as_device_handle handle, + /* The bus where the event happened */ + cy_as_bus_number_t bus, + /* The device where the event happened */ + uint32_t device, + /* The event type */ + cy_as_storage_event evtype, + /* Event related data */ + void *evdata + ) ; + +/* Summary + This function type defines a callback to be called after + an asynchronous sdio operation + + Description + The Callback function is called at the completion of an + asynchronous sdio read or write operation. + + See Also + * CyAsSdioExtendedRead() + * CyAsSdioExtendedWrite() +*/ +typedef void (*cy_as_sdio_callback)( + /* Handle to the device completing the storage operation */ + cy_as_device_handle handle, + /* The bus completing the operation */ + cy_as_bus_number_t bus, + /* The device completing the operation */ + uint32_t device, + /* The function number of the completing the operation. + if the status of the operation is either CY_AS_ERROR_IO_ABORTED + or CY_AS_IO_SUSPENDED then the most significant word parameter will + contain the number of blocks still pending. */ + uint32_t function, + /* The base address of the completed operation */ + uint32_t address, + /* The type of operation */ + cy_as_oper_type op, + /* The status of the operation */ + cy_as_return_status_t status + ) ; + +/* Summary + Enumeration of SD/MMC card registers that can be read + through the API. + + Description + Some of the registers on the SD/MMC card(s) attached to the + West Bridge can be read through the API layers. This type + enumerates the registers that can be read. + + See Also + * CyAsStorageSDRegisterRead + */ +typedef enum cy_as_sd_card_reg_type { + cy_as_sd_reg_OCR = 0, + cy_as_sd_reg_CID, + cy_as_sd_reg_CSD +} cy_as_sd_card_reg_type ; + +/* Summary + Struct encapsulating parameters and return values for a + CyAsStorageQueryDevice call. + + Description + This struct holds the input parameters and the return values + for an asynchronous CyAsStorageQueryDevice call. + + See Also + * CyAsStorageQueryDevice + */ +typedef struct cy_as_storage_query_device_data { + /* The bus with the device to query */ + cy_as_bus_number_t bus ; + /* The logical device number to query */ + uint32_t device ; + /* The return value for the device descriptor */ + cy_as_device_desc desc_p ; +} cy_as_storage_query_device_data ; + + +/* Summary + Struct encapsulating parameters and return values + for a CyAsStorageQueryUnit call. + + Description + This struct holds the input parameters and the return + values for an asynchronous CyAsStorageQueryUnit call. + + See Also + * CyAsStorageQueryUnit + */ +typedef struct cy_as_storage_query_unit_data { + /* The bus with the device to query */ + cy_as_bus_number_t bus ; + /* The logical device number to query */ + uint32_t device ; + /* The unit to query on the device */ + uint32_t unit ; + /* The return value for the unit descriptor */ + cy_as_unit_desc desc_p ; +} cy_as_storage_query_unit_data ; + +/* Summary + Struct encapsulating the input parameter and return + values for a CyAsStorageSDRegisterRead call. + + Description + This struct holds the input parameter and return + values for an asynchronous CyAsStorageSDRegisterRead + call. + + See Also + * CyAsStorageSDRegisterRead + */ +typedef struct cy_as_storage_sd_reg_read_data { + /* Pointer to the result buffer. */ + uint8_t *buf_p; + /* Length of data to be copied in bytes. */ + uint8_t length; +} cy_as_storage_sd_reg_read_data ; + +/* Summary + Controls which pins are used for card detection + + Description + When a StorageDeviceControl call is made to enable or + disable card detection this enum is passed in to + control which pin is used for the detection. + + See Also + * CyAsStorageDeviceControl +*/ +typedef enum cy_as_storage_card_detect { + cy_as_storage_detect_GPIO, + cy_as_storage_detect_SDAT_3 +} cy_as_storage_card_detect ; + +#ifndef __doxygen__ +#define cy_as_storage_detect_GPIO_0 cy_as_storage_detect_GPIO + +/* Length of OCR value in bytes. */ +#define CY_AS_SD_REG_OCR_LENGTH (4) +/* Length of CID value in bytes. */ +#define CY_AS_SD_REG_CID_LENGTH (16) +/* Length of CSD value in bytes. */ +#define CY_AS_SD_REG_CSD_LENGTH (16) +/* Max. length of register response in words. */ +#define CY_AS_SD_REG_MAX_RESP_LENGTH (10) + +#endif + +/* Summary + This data structure is the data passed via the evdata + paramater on a usb event callback for the mass storage + device progress event. + + Description + This data structure reports the number of sectors that have + been written and read on the USB mass storage device since + the last event report. The corresponding event is only sent + when either the number of writes, or the number of reads has + crossed a pre-set threshold. + + See Also + * CyAsUsbEventCallback + * CyAsUsbRegisterCallback +*/ +typedef struct cy_as_m_s_c_progress_data { + /* Number of sectors written since the last event. */ + uint32_t wr_count; + /* Number of sectors read since the last event. */ + uint32_t rd_count; +} cy_as_m_s_c_progress_data ; + +/* Summary +Flag to set Direct Write operation to read back from the +address written to. + + + See Also + *CyAsSdioDirectWrite() +*/ +#define CY_SDIO_RAW (0x01) + + +/* Summary +Flag to set Extended Read and Write to perform IO +using a FIFO i.e. read or write from the specified +address only. + + See Also + *CyAsSdioExtendedRead() + *CyAsSdioExtendedWrite() +*/ +#define CY_SDIO_OP_FIFO (0x00) + +/* Summary +Flag to set Extended Read and Write to perform incremental +IO using the address provided as the base address. + + + See Also + *CyAsSdioExtendedRead() + *CyAsSdioExtendedWrite() +*/ +#define CY_SDIO_OP_INCR (0x02) + +/* Summary +Flag to set Extended Read and Write to Block Mode operation + + See Also + *CyAsSdioExtendedRead() + *CyAsSdioExtendedWrite() +*/ +#define CY_SDIO_BLOCKMODE (0x04) + +/* Summary +Flag to set Extended Read and Write to Byte Mode operation + + See Also + *CyAsSdioExtendedRead() + *CyAsSdioExtendedWrite() +*/ +#define CY_SDIO_BYTEMODE (0x00) + +/* Summary +Flag to force re/initialization of a function. + +Description +If not set a call to CyAsSdioInitFunction() +will not initialize a function that has been previously +initialized. + See Also + *CyAsSdioInitFunction() + */ +#define CY_SDIO_FORCE_INIT (0x40) + +/* Summary +Flag to re-enable the SDIO interrupts. + +Description +Used with a direct read or direct write +after the Interrupt triggerred by SDIO has been serviced +and cleared to reset the West Bridge Sdio Interrupt. + See Also + *CyAsSdioDirectRead() + *CyAsSdioDirectWrite() +*/ + +#define CY_SDIO_REARM_INT (0x80) + + +/* Summary + Flag to check if 4 bit support is enabled on a + low speed card + See Also + */ +#define CY_SDIO_4BLS (0x80) + +/* Summary + Flag to check if card is a low speed card + See Also + */ +#define CY_SDIO_LSC (0x40) + +/* Summary + Flag to check if interrupt during multiblock data + transfer is enabled + See Also + */ +#define CY_SDIO_E4MI (0x20) + +/* Summary + Flag to check if interrupt during multiblock data + transfer is supported + See Also + */ +#define CY_SDIO_S4MI (0x10) + +/* Summary + Flag to check if card supports function suspending. + See Also + */ +#define CY_SDIO_SBS (0x08) + +/* Summary + Flag to check if card supports SDIO Read-Wait + See Also + */ +#define CY_SDIO_SRW (0x04) + +/* Summary + Flag to check if card supports multi-block transfers + See Also + */ +#define CY_SDIO_SMB (0x02) + +/* Summary + Flag to check if card supports Direct IO commands + during execution of an Extended + IO function + See Also + */ +#define CY_SDIO_SDC (0x01) + +/* Summary + Flag to check if function has a CSA area. + See Also + */ +#define CY_SDIO_CSA_SUP (0x40) + +/* Summary + Flag to check if CSA access is enabled. + See Also + */ +#define CY_SDIO_CSA_EN (0x80) + +/* Summary + Flag to check if CSA is Write protected. + See Also + */ +#define CY_SDIO_CSA_WP (0x01) + +/* Summary + Flag to check if CSA formatting is prohibited. + See Also + */ +#define CY_SDIO_CSA_NF (0x02) + +/* Summary + Flag to check if the function allows wake-up from low + power mode using some vendor specific method. + See Also + */ +#define CY_SDIO_FN_WUS (0x01) + + +/* Summary + This data structure stores SDIO function 0 + parameters for a SDIO card +*/ +typedef struct cy_as_sdio_card { + /* Number of functions present on the card. */ + uint8_t num_functions; + /* Memory present(Combo card) or not */ + uint8_t memory_present; + /* 16 bit manufacturer ID */ + uint16_t manufacturer__id; + /* Additional vendor specific info */ + uint16_t manufacturer_info; + /* Max Block size for function 0 */ + uint16_t maxblocksize; + /* Block size used for function 0 */ + uint16_t blocksize; + /* SDIO version supported by the card */ + uint8_t sdio_version; + /* Card capability flags */ + uint8_t card_capability; +} cy_as_sdio_card; + +/* Summary + This data structure stores SDIO function 1-7 parameters + for a SDIO card +*/ +typedef struct cy_as_sdio_func { + /* SDIO function code. 0 if non standard function */ + uint8_t function_code; + /* Extended function type code for non-standard function */ + uint8_t extended_func_code; + /* Max IO Blocksize supported by the function */ + uint16_t maxblocksize; + /* IO Blocksize used by the function */ + uint16_t blocksize; + /* 32 bit product serial number for the function */ + uint32_t card_psn; + /* Code storage area variables */ + uint8_t csa_bits; + /* Function wake-up support */ + uint8_t wakeup_support; +} cy_as_sdio_func; + +/*********************************** + * West Bridge Functions + ************************************/ + +/* Summary + This function starts the West Bridge storage module. + + Description + This function initializes the West Bridge storage software + stack and readies this module to service storage related + requests. If the stack is already running, the reference + count for the stack is incremented. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_SUCCESS - the module started sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsStorageStop +*/ +EXTERN cy_as_return_status_t +cy_as_storage_start( + /* Handle to the device */ + cy_as_device_handle handle, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function stops the West Bridge storage module. + + Description + This function decrements the reference count for the + storage stack and if this count is zero, the storage + stack is shut down. The shutdown frees all resources + associated with the storage stack. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + While all resources associated with the storage stack + will be freed is a shutdown occurs, + resources associated with underlying layers of the + software will not be freed if they + are shared by the USB stack and the USB stack is + active. Specifically the DMA manager, + the interrupt manager, and the West Bridge + communications module are all shared by both the + USB stack and the storage stack. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge + * device has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not + * been loaded into West Bridge + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - this module was shut + * down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING + * CY_AS_ERROR_ASYNC_PENDING + * CY_AS_ERROR_OUT_OF_MEMORY + + See Also + * CyAsStorageStart +*/ +EXTERN cy_as_return_status_t +cy_as_storage_stop( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function is used to register a callback function + for the storage API. + + Description + At times West Bridge needs to inform the P port processor + of events that have occurred. These events are asynchronous + to the thread of control on the P + port processor and as such are generally delivered via a + callback function that + is called as part of an interrupt handler. This function + registers the callback + function that is called when an event occurs. Each call + to this function + replaces any old callback function with a new callback + function supplied on + the most recent call. This function can also be called + with a callback function + of NULL in order to remove any existing callback function + + * Valid In Asynchronous Callback:YES + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has + * not been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle + * was passed in + * CY_AS_ERROR_SUCCESS - the function was registered + * sucessfully + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + + See Also + * CyAsStorageEventCallback + * CyAsStorageEvent +*/ +EXTERN cy_as_return_status_t +cy_as_storage_register_callback( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The callback function to call for async storage events */ + cy_as_storage_event_callback callback + ) ; + +/* Summary + This function claims a given media type. + + Description + This function communicates to West Bridge that the + processor wants control of the + given storage media type. Each media type can be + claimed or released by the + processor independently. As the processor is the + master for the storage, + West Bridge should release control of the requested + media as soon as possible and + signal the processor via the CyAsStorageProcessor event. + + * Valid In Asynchronous Callback: NO + + Notes + This function just notifies West Bridge that the storage + is desired. The storage + has not actually been released by West Bridge until the + registered callback function + is called with the CyAsStorageProcessor event + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - this request was sucessfully + * transmitted to the West Bridge device + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_MEDIA + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_ACQUIRED + + See Also: + * CyAsStorageClaim + * CyAsStorageRelease +*/ +EXTERN cy_as_return_status_t +cy_as_storage_claim( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to claim */ + cy_as_bus_number_t bus, + /* The device to claim */ + uint32_t device, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function releases a given media type. + + Description + This function communicates to West Bridge that the + processor has released control of + the given storage media type. Each media type can + be claimed or released by the + processor independently. As the processor is the + master for the storage, West Bridge + can now assume ownership of the media type. No callback + or event is generated. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle + * was passed in + * CY_AS_ERROR_SUCCESS - the media was sucessfully + * released + * CY_AS_ERROR_MEDIA_NOT_CLAIMED - the media was not + * claimed by the P port + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_MEDIA + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsStorageClaim +*/ +EXTERN cy_as_return_status_t +cy_as_storage_release( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to release */ + cy_as_bus_number_t bus, + /* The device to release */ + uint32_t device, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function information about the number of devices present + on a given bus + + Description + This function retrieves information about how many devices on + on the given + West Bridge bus. + + * Valid In Asynchronous Callback: NO + + Notes + While the current implementation of West Bridge only + supports one of logical device of + each media type, future versions WestBridge/Antioch may + support multiple devices. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsStorageQueryDevice + * CyAsStorageQueryUnit +*/ +EXTERN cy_as_return_status_t +cy_as_storage_query_bus( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to query */ + cy_as_bus_number_t bus, + /* The return value containing the number of + devices present for this media type */ + uint32_t *count, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function information about the number of devices + present for a given media type + + Description + This function retrieves information about how many + devices of a given media type are attached to West Bridge. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + While the current implementation of West Bridge only + supports one of logical device of each media type, future + versions West Bridge may support multiple devices. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsStorageQueryMedia + * CyAsMediaType + * CyAsStorageQueryDevice + * CyAsStorageQueryUnit +*/ +EXTERN cy_as_return_status_t +cy_as_storage_query_media( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to query */ + cy_as_media_type type, + /* The return value containing the number of + devices present for this media type */ + uint32_t *count, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function returns information about a given device + of a specific media type + + Description + This function retrieves information about a device of a + given type of media. The function is called with a given + media type and device and a pointer to a media descriptor + (CyAsDeviceDesc). This function fills in the data in the + media descriptor to provide information about the + attributes of the device of the given device. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + Currently this API only supports a single logical device + of each media type. Therefore the only acceptable value + for the parameter device is zero (0). + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_NO_SUCH_MEDIA + * CY_AS_ERROR_NO_SUCH_DEVICE + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsMediaType + * CyAsStorageQueryMedia + * CyAsStorageQueryUnit + * CyAsDeviceDesc +*/ +EXTERN cy_as_return_status_t +cy_as_storage_query_device( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Parameters and return value for the query call */ + cy_as_storage_query_device_data *data, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function returns information about a given unit on a + specific device + + Description + This function retrieves information about a device of a + given logical unit. The function is called with a given + media type, device address, unit address, and a pointer + to a unit descriptor (CyAsUnitDesc). This function fills + in the data in the unit descriptor to provide information + about the attributes of the device of the given logical + unit. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_NO_SUCH_DEVICE + * CY_AS_ERROR_NO_SUCH_UNIT + * CY_AS_ERROR_INVALID_RESPONSE + + + See Also + * CyAsMediaType + * CyAsStorageQueryMedia + * CyAsStorageQueryDevice + * CyAsUnitDesc +*/ +EXTERN cy_as_return_status_t +cy_as_storage_query_unit( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Parameters and return value for the query call */ + cy_as_storage_query_unit_data *data_p, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function enables/disables the handling of SD/MMC card + detection and SD/MMC write protection in West Bridge Firmware. + + Description + If the detection of SD/MMC card insertion or removal is being + done by the Processor directly, the West Bridge firmware needs + to be instructed to disable the card detect feature. Also, if + the hardware design does not use the SD_WP GPIO of the West + Bridge to handle SD card's write protect notch, the handling + of write protection if firmware should be disabled. This API + is used to enable/disable the card detect and write protect + support in West Bridge firmware. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the feature controls were + * set successfully + * CY_AS_ERROR_NO_SUCH_BUS - the specified bus is invalid + * CY_AS_ERROR_NOT_SUPPORTED - function not supported on + * the device in the specified bus + * CY_AS_ERROR_IN_SUSPEND - the West Brdige device is in + * suspended mode + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + +*/ +EXTERN cy_as_return_status_t +cy_as_storage_device_control( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The bus to control */ + cy_as_bus_number_t bus, + /* The device to control */ + uint32_t device, + /* Enable/disable control for card detection */ + cy_bool card_detect_en, + /* Enable/disable control for write protect handling */ + cy_bool write_prot_en, + /* Control which pin is used for card detection */ + cy_as_storage_card_detect config_detect, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +/* Summary + This function reads one or more blocks of data from + the storage system. + + Description + This function synchronously reads one or more blocks + of data from the given media + type/device and places the data into the data buffer + given. This function does not + return until the data is read and placed into the buffer. + + * Valid In Asynchronous Callback: NO + + Notes + If the Samsung CEATA drive is the target for a + read/write operation, the maximum + number of sectors that can be accessed through a + single API call is limited to 2047. + Longer accesses addressed to a Samsung CEATA drive + can result in time-out errors. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle + * was passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified + * does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified + * media/device pair does not exist + * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified + * does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation + * is pending + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was + * error in reading from the media + * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is + * write protected + * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater + * than 4095 logic blocks are not allowed + + See Also + * CyAsStorageReadAsync + * CyAsStorageWrite + * CyAsStorageWriteAsync + * CyAsStorageCancelAsync + * +*/ +EXTERN cy_as_return_status_t +cy_as_storage_read( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to access */ + cy_as_bus_number_t bus, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where data will be placed */ + void *data_p, + /* The number of blocks to be read */ + uint16_t num_blocks + ) ; + +/* Summary + This function asynchronously reads one or more blocks of data + from the storage system. + + Description + This function asynchronously reads one or more blocks of + data from the given media + type/device and places the data into the data buffer given. + This function returns + as soon as the request is transmitted to the West Bridge + device but before the data is + available. When the read is complete, the callback function + is called to indicate the + data has been placed into the data buffer. Note that the + data buffer must remain + valid from when the read is requested until the callback + function is called. + + * Valid In Asynchronous Callback: YES + + Notes + If the Samsung CEATA drive is the target for a read/write + operation, the maximum + number of sectors that can be accessed through a single API + call is limited to 2047. + Longer accesses addressed to a Samsung CEATA drive can + result in time-out errors. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle + * was passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_ASYNC_PENDING - an async operation + * is pending + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error + * in reading from the media + * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is + * write protected + * CY_AS_ERROR_QUERY_DEVICE_NEEDED - Before an + * asynchronous read can be issue a call to + * CyAsStorageQueryDevice must be made + * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater + * than 4095 logic blocks are not allowed + + See Also + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageWriteAsync + * CyAsStorageCancelAsync + * CyAsStorageQueryDevice + * +*/ +EXTERN cy_as_return_status_t +cy_as_storage_read_async( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to access */ + cy_as_bus_number_t bus, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where data will be placed */ + void *data_p, + /* The number of blocks to be read */ + uint16_t num_blocks, + /* The function to call when the read is complete + or an error occurs */ + cy_as_storage_callback callback + ) ; + +/* Summary + This function writes one or more blocks of data + to the storage system. + + Description + This function synchronously writes one or more blocks of + data to the given media/device. + This function does not return until the data is written + into the media. + + * Valid In Asynchronous Callback: NO + + Notes + If the Samsung CEATA drive is the target for a read/write + operation, the maximum + number of sectors that can be accessed through a single + API call is limited to 2047. + Longer accesses addressed to a Samsung CEATA drive can + result in time-out errors. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does + * not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified + * media/device pair does not exist + * CY_AS_ERROR_NO_SUCH_UNIT - the unit specified + * does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation + * is pending + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error + * in reading from the media + * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is + * write protected + * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater + * than 4095 logic blocks are not allowed + + See Also + * CyAsStorageRead + * CyAsStorageReadAsync + * CyAsStorageWriteAsync + * CyAsStorageCancelAsync + * +*/ +EXTERN cy_as_return_status_t +cy_as_storage_write( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to access */ + cy_as_bus_number_t bus, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer containing the data to be written */ + void *data_p, + /* The number of blocks to be written */ + uint16_t num_blocks + ) ; + +/* Summary + This function asynchronously writes one or more blocks + of data to the storage system + + Description + This function asynchronously writes one or more blocks of + data to the given media type/device. + This function returns as soon as the request is transmitted + to the West Bridge device + but before the data is actually written. When the write is + complete, the callback + function is called to indicate the data has been physically + written into the media. + + * Valid In Asynchronous Callback: YES + + Notes + If the Samsung CEATA drive is the target for a read/write + operation, the maximum + number of sectors that can be accessed through a single API + call is limited to 2047. + Longer accesses addressed to a Samsung CEATA drive can + result in time-out errors. + + Notes + The data buffer must remain valid from when the write is + requested until the callback function is called. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has + * not been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_ASYNC_PENDING - an async operation is + * pending + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is write + * protected + * CY_AS_ERROR_QUERY_DEVICE_NEEDED - A query device call is + * required before async writes are allowed + * CY_AS_ERROR_INVALID_PARAMETER - Reads/Writes greater + * than 4095 logic blocks are not allowed + + See Also + * CyAsStorageRead + * CyAsStorageWrite + * CyAsStorageReadAsync + * CyAsStorageCancelAsync + * CyAsStorageQueryDevice + * +*/ +EXTERN cy_as_return_status_t +cy_as_storage_write_async( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The bus to access */ + cy_as_bus_number_t bus, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where the data to be written is stored */ + void *data_p, + /* The number of blocks to be written */ + uint16_t num_blocks, + /* The function to call when the write is complete + or an error occurs */ + cy_as_storage_callback callback + ) ; + +/* Summary + This function aborts any outstanding asynchronous operation + + Description + This function aborts any asynchronous block read or block + write operation. As only a single asynchronous block read + or write operation is possible at one time, this aborts + the single operation in progress. + + * Valid In Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_OPERATION_PENDING - no asynchronous + * operation is pending + + See Also + * CyAsStorageRead + * CyAsStorageReadAsync + * CyAsStorageWrite + * CyAsStorageWriteAsync + * +*/ +EXTERN cy_as_return_status_t +cy_as_storage_cancel_async( + /* Handle to the device with outstanding async request */ + cy_as_device_handle handle + ) ; + +/* Summary + This function is used to read the content of SD registers + + Description + This function is used to read the contents of CSD, CID and + CSD registers of the SD Card. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the read operation was successful + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in + * suspend mode + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair + * does not exist + * CY_AS_ERROR_INVALID_PARAMETER - The register type is invalid + * or the media is not supported on the bus + * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to process + * request + * CY_AS_ERROR_INVALID_RESPONSE - communication failure with + * West Bridge firmware + + See Also + * CyAsStorageSDRegReadData + */ +EXTERN cy_as_return_status_t +cy_as_storage_sd_register_read( + /* Handle to the West Bridge device. */ + cy_as_device_handle handle, + /* The bus to query */ + cy_as_bus_number_t bus, + /* The device to query */ + uint8_t device, + /* The type of register to read. */ + cy_as_sd_card_reg_type reg_type, + /* Output data buffer and length. */ + cy_as_storage_sd_reg_read_data *data_p, + /* Callback function to call when done. */ + cy_as_function_callback cb, + /* Call context to send to the cb function. */ + uint32_t client + ) ; + +/* Summary + Creates a partition starting at the given block and using the + remaining blocks on the card. + + Description + Storage devices attached to West Bridge can be partitioned + into two units. + The visibility of these units through the mass storage + interface can be + individually controlled. This API is used to partition + a device into two. + + * Valid in Asynchronous Callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the partition was successfully created + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in + * suspend mode + * CY_AS_ERROR_USB_RUNNING - Partition cannot be created while + * USB stack is active + * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to + * process request + * CY_AS_ERROR_INVALID_REQUEST - feature not supported by + * active device or firmware + * CY_AS_ERROR_INVALID_RESPONSE - communication failure with + * West Bridge firmware + * CY_AS_ERROR_ALREADY_PARTITIONED - the storage device already + * has been partitioned + * CY_AS_ERROR_INVALID_BLOCK - Size specified for the partition + * exceeds the actual device capacity + + See Also + * + * CyAsStorageRemovePPartition + */ +EXTERN cy_as_return_status_t +cy_as_storage_create_p_partition( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Bus on which the device to be partitioned is connected */ + cy_as_bus_number_t bus, + /* Device number to be partitioned */ + uint32_t device, + /* Size of partition number 0 in blocks */ + uint32_t size, + /* Callback in case of async call */ + cy_as_function_callback cb, + /* Client context to pass to the callback */ + uint32_t client + ); + +/* Summary + Removes the partition table on a storage device connected + to the West Bridge. + + Description + Storage devices attached to West Bridge can be partitioned + into two units.This partition information is stored on the + device and is non-volatile. This API is used to remove the + stored partition information and make the entire device + visible as a single partition (unit). + + * Valid in Asynchronous Callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the partition was successfully + * deleted + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_IN_SUSPEND - The West Bridge device is in + * suspend mode + * CY_AS_ERROR_USB_RUNNING - Partition cannot be created + * while USB stack is active + * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to + * process request + * CY_AS_ERROR_INVALID_REQUEST - operation not supported + * by active device/firmware + * CY_AS_ERROR_NO_SUCH_UNIT - the addressed device is + * not partitioned + + See Also + * + * CyAsStorageCreatePPartition + */ +EXTERN cy_as_return_status_t +cy_as_storage_remove_p_partition( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Bus on which device of interest is connected */ + cy_as_bus_number_t bus, + /* Device number of interest */ + uint32_t device, + /* Callback in case of async call */ + cy_as_function_callback cb, + /* Client context to pass to the callback */ + uint32_t client + ); + +/* Summary + Returns the amount of data read/written to the given + device from the USB host. + + Description + + * Valid in Asynchronous Callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - API call completed successfully + * CY_AS_ERROR_INVALID_HANDLE - Invalid West Bridge device + * handle + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - No firmware image has been + * loaded on West Bridge device + * CY_AS_ERROR_NOT_RUNNING - Storage stack has not been + * started + * CY_AS_ERROR_NOT_SUPPORTED - This function is not + * supported by active firmware version + * CY_AS_ERROR_OUT_OF_MEMORY - Failed to get memory to + * process the request + * CY_AS_ERROR_TIMEOUT - West Bridge firmware did not + * respond to request + * CY_AS_ERROR_INVALID_RESPONSE - Unexpected reply from + * West Bridge firmware + + See Also + * CyAsUsbSetMSReportThreshold +*/ +EXTERN cy_as_return_status_t +cy_as_storage_get_transfer_amount( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Bus on which device of interest is connected */ + cy_as_bus_number_t bus, + /* Device number of interest */ + uint32_t device, + /* Return value containing read/write sector counts. */ + cy_as_m_s_c_progress_data *data_p, + /* Callback in case of async call */ + cy_as_function_callback cb, + /* Client context to pass to the callback */ + uint32_t client + ) ; + +/* Summary + Performs a Sector Erase on an attached SD Card + + Description + This allows you to erase an attached SD card. The area to erase + is specified in terms of a starting Erase Unit and a number of + Erase Units. The size of each Erase Unit is defined in the + DeviceDesc returned from a StorageQueryDevice call and it can + differ between SD cards. + + A large erase can take a while to complete depending on the SD + card. In such a case it is reccomended that an async call is made. + + Returns + * CY_AS_ERROR_SUCCESS - API call completed successfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed in + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_MEDIA_WRITE_PROTECTED - the media is write protected + * CY_AS_ERROR_QUERY_DEVICE_NEEDED - A query device call is + * required before erase is allowed + * CY_AS_ERROR_NO_SUCH_BUS + * CY_AS_ERROR_NO_SUCH_DEVICE + * CY_AS_ERROR_NOT_SUPPORTED - Erase is currenly only supported + * on SD and using SD only firmware + * CY_AS_ERROR_OUT_OF_MEMORY + + See Also + * CyAsStorageSDRegisterRead +*/ +EXTERN cy_as_return_status_t +cy_as_storage_erase( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Bus on which device of interest is connected */ + cy_as_bus_number_t bus, + /* Device number of interest */ + uint32_t device, + /* Erase Unit to start the erase */ + uint32_t erase_unit, + /* Number of Erase Units to erase */ + uint16_t num_erase_units, + /* Callback in case of async call */ + cy_as_function_callback cb, + /* Client context to pass to the callback */ + uint32_t client + ) ; + +/* Summary + This function is used to read a Tuple from the SDIO CIS area. + + Description + This function is used to read a Tuple from the SDIO CIS area. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device + * is in suspend mode + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending + * CY_AS_ERROR_INVALID_REQUEST - an invalid IO request + * type was made + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to + * an invalid function + * CY_AS_ERROR_INVALID_ENDPOINT - A DMA request was made to + * an invalid endpoint + * CY_AS_ERROR_ENDPOINT_DISABLED - A DMA request was made to + * a disabled endpoint + +*/ +cy_as_return_status_t +cy_as_sdio_get_c_i_s_info( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Id of tuple to be fetched */ + uint16_t tuple_id, + /* Buffer to hold tuple read from card. + should be at least 256 bytes in size */ + uint8_t *data_p + ); + + +/* Summary + This function is used to read properties of the SDIO card. + + Description + This function is used to read properties of the SDIO card + into a CyAsSDIOCard structure. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_SUCCESS - the card information was returned + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + +*/ +cy_as_return_status_t +cy_as_sdio_query_card( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* Buffer to store card properties */ + cy_as_sdio_card *data_p + ); + +/* Summary + This function is used to reset a SDIO card. + + Description + This function is used to reset a SDIO card by writing to + the reset bit in the CCCR and reinitializing the card. This + function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + */ +cy_as_return_status_t +cy_as_sdio_reset_card( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device + ); + +/* Summary + This function performs a Synchronous 1 byte read from the sdio + device function. + + Description + This function is used to perform a synchronous 1 byte read + from an SDIO card function. This function is to be used only + for IO to an SDIO card as other media will not respond to the + SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed + * in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair + * does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in reading + * from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to an + * invalid function + * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which read + * was attempted is in suspend +*/ +cy_as_return_status_t +cy_as_sdio_direct_read( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Address for IO */ + uint32_t address, + /* Set to CY_SDIO_REARM_INT to reinitialize SDIO interrupt */ + uint8_t misc_buf, + /* Buffer to hold byte read from card */ + uint8_t *data_p + ); + +/* Summary + This function performs a Synchronous 1 byte write to the + sdio device function. + + Description + This function is used to perform a synchronous 1 byte write + to an SDIO card function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to + * an invalid function + * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which + * write was attempted is in suspend +*/ +cy_as_return_status_t +cy_as_sdio_direct_write( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Address for IO */ + uint32_t address, + /* Set to CY_SDIO_REARM_INT to reinitialize SDIO interrupt, + set to CY_SDIO_RAW for read after write */ + uint8_t misc_buf, + /* Byte to write */ + uint16_t argument, + /* Buffer to hold byte read from card in Read after write mode */ + uint8_t *data_p + ); + +/* Summary + This function is used to set the blocksize of an SDIO function. + + Description + This function is used to set the blocksize of an SDIO function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory + * available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function + * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize + * was passed to the function. + * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which + * write was attempted is in suspend +*/ +cy_as_return_status_t +cy_as_sdio_set_blocksize( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Block size to set. */ + uint16_t blocksize + ); + +/* Summary + This function is used to read Multibyte/Block data from a + IO function. + + Description + This function is used to read Multibyte/Block data from a + IO function. This function is to be used only for IO to an + SDIO card as other media will not respond to the SDIO + command set. + + * Valid in Asynchronous Callback: YES + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was recieved + * from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made to + * an invalid function + * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize or + * block count was passed to the function. + * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which + * write was attempted is in suspend + * CY_AS_ERROR_IO_ABORTED - The IO operation was aborted + * CY_AS_ERROR_IO_SUSPENDED - The IO operation was suspended + * CY_AS_ERROR_INVALID_REQUEST - An invalid request was + * passed to the card. + +*/ +cy_as_return_status_t +cy_as_sdio_extended_read( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Base Address for IO */ + uint32_t address, + /* Set to CY_SDIO_BLOCKMODE for block IO, + CY_SDIO_BYTEMODE for multibyte IO, + CY_SDIO_OP_FIFO to read multiple bytes from the + same address, CY_SDIO_OP_INCR to read bytes from + the incrementing addresses */ + uint8_t misc_buf, + /* Block/Byte count to read */ + uint16_t argument, + /* Buffer to hold data read from card */ + uint8_t *data_p, + /* Callback in case of Asyncronous call. 0 if Synchronous */ + cy_as_sdio_callback callback + ); + +/* Summary + This function is used to write Multibyte/Block data + to a IO function. + + Description + This function is used to write Multibyte/Block data + to a IO function. This function is to be used only + for IO to an SDIO card as other media will not respond + to the SDIO command set. + + * Valid in Asynchronous Callback: YES + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation is pending + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function + * CY_AS_ERROR_INVALID_BLOCKSIZE - An incorrect blocksize or + * block count was passed to the function. + * CY_AS_ERROR_FUNCTION_SUSPENDED - The function to which + * write was attempted is in suspend + * CY_AS_ERROR_IO_ABORTED - The IO operation was aborted + * CY_AS_ERROR_IO_SUSPENDED - The IO operation was suspended + * CY_AS_ERROR_INVALID_REQUEST - An invalid request was + * passed to the card. +*/ +cy_as_return_status_t +cy_as_sdio_extended_write( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Base Address for IO */ + uint32_t address, + /* Set to CY_SDIO_BLOCKMODE for block IO, + CY_SDIO_BYTEMODE for multibyte IO, + CY_SDIO_OP_FIFO to write multiple bytes to the same address, + CY_SDIO_OP_INCR to write multiple bytes to incrementing + addresses */ + uint8_t misc_buf, + /* Block/Byte count to write + in case of byte mode the count should not exceed the block size + or 512, whichever is smaller. + in case of block mode, maximum number of blocks is 511. */ + uint16_t argument, + /* Buffer to hold data to be written to card. */ + uint8_t *data_p, + /* Callback in case of Asyncronous call. 0 if Synchronous */ + cy_as_sdio_callback callback + ); + +/* Summary + This function is used to initialize a SDIO card function. + + Description + This function is used to initialize a SDIO card function + (1 - 7). This function is to be used only for IO to an + SDIO card as other media will not respond to the SDIO + command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed + * in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error in + * reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function +*/ +cy_as_return_status_t +cy_as_sdio_init_function( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Set to CY_SDIO_FORCE_INIT to reinitialize function */ + uint8_t misc_buf + ); + +/* Summary + This function is used to get properties of a SDIO card function. + + Description + This function is used to get properties of a SDIO card functio + (1 - 7) into a CyAsSDIOFunc structure. This function is to be + used only for IO to an SDIO card as other media will not respond + to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not been + * started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was passed + * in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the media specified does + * not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device pair + * does not exist + * CY_AS_ERROR_INVALID_FUNCTION - An IO request was made to + * an invalid function +*/ +cy_as_return_status_t +cy_as_sdio_query_function( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Buffer to store function properties */ + cy_as_sdio_func *data_p + ); + +/* Summary + This function is used to Abort the current IO function. + + Description + This function is used to Abort the current IO function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified + * media/device pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory + * available + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function +*/ +cy_as_return_status_t +cy_as_sdio_abort_function( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no + ); + +/* Summary + This function is used to Disable IO to an SDIO function. + + Description + This function is used to Disable IO to an SDIO function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is + * in suspend mode + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified media/device + * pair does not exist + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function +*/ +cy_as_return_status_t +cy_as_sdio_de_init_function( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no + ); + +/* Summary + This function is used to Suspend the current IO function. + + Description + This function is used to Suspend the current IO function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has + * not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is in + * suspend mode + * CY_AS_ERROR_SUCCESS - the media information was returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified does not + * exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified + * media/device pair does not exist + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory + * available + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was made + * to an invalid function +*/ +cy_as_return_status_t +cy_as_sdio_suspend( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no + ); + +/* Summary + This function is used to resume a Suspended IO function. + + Description + This function is used to resume a Suspended IO function. + This function is to be used only for IO to an SDIO card as + other media will not respond to the SDIO command set. + + * Valid in Asynchronous Callback: NO + * Valid on Antioch device: NO + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device + * has not been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been + * loaded into West Bridge + * CY_AS_ERROR_NOT_RUNNING - the storage stack has not + * been started + * CY_AS_ERROR_INVALID_HANDLE - an invalid handle was + * passed in + * CY_AS_ERROR_IN_SUSPEND - the West Bridge device is + * in suspend mode + * CY_AS_ERROR_SUCCESS - the media information was + * returned + * CY_AS_ERROR_TIMEOUT - a timeout occurred + * communicating with the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the stack is not running + * CY_AS_ERROR_NO_SUCH_BUS - the bus specified + * does not exist + * CY_AS_ERROR_NO_SUCH_DEVICE - the specified + * media/device pair does not exist + * CY_AS_ERROR_ASYNC_PENDING - an async operation + * is pending + * CY_AS_ERROR_OUT_OF_MEMORY - insufficient memory + * available + * CY_AS_ERROR_INVALID_RESPONSE - an error message was + * recieved from the firmware + * CY_AS_ERROR_MEDIA_ACCESS_FAILURE - there was error + * in reading from the media + * CY_AS_ERROR_INVALID_FUNCTION - An IO attempt was + * made to an invalid function + * CY_AS_ERROR_IO_ABORTED - The IO operation was + * aborted + * CY_AS_ERROR_IO_SUSPENDED - The IO operation was + * suspended + * CY_AS_ERROR_INVALID_REQUEST - An invalid request was + * passed to the card. + +*/ +cy_as_return_status_t +cy_as_sdio_resume( + /* Handle to the Westbridge device */ + cy_as_device_handle handle, + /* Bus to use */ + cy_as_bus_number_t bus, + /* Device number */ + uint32_t device, + /* IO function Number */ + uint8_t n_function_no, + /* Operation to resume (Read or Write) */ + cy_as_oper_type op, + /* Micellaneous buffer same as for Extended read and Write */ + uint8_t misc_buf, + /* Number of pending blocks for IO. Should be less + than or equal to the maximum defined for extended + read and write */ + uint16_t pendingblockcount, + /* Buffer to continue the Suspended IO operation */ + uint8_t *data_p + ); + + + +/* For supporting deprecated functions */ +#include "cyasstorage_dep.h" + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASSTORAGE_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h new file mode 100644 index 000000000000..172fa85731bb --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasstorage_dep.h @@ -0,0 +1,309 @@ +/* Cypress West Bridge API header file (cyanstorage_dep.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* This header will contain Antioch specific declaration + * of the APIs that are deprecated in Astoria SDK. This is + * for maintaining backward compatibility + */ +#ifndef __INCLUDED_CYANSTORAGE_DEP_H__ +#define __INCLUDED_CYANSTORAGE_DEP_H__ + +#ifndef __doxygen__ + +typedef void (*cy_as_storage_callback_dep)( +/* Handle to the device completing the storage operation */ + cy_as_device_handle handle, + /* The media type completing the operation */ + cy_as_media_type type, + /* The device completing the operation */ + uint32_t device, + /* The unit completing the operation */ + uint32_t unit, + /* The block number of the completed operation */ + uint32_t block_number, + /* The type of operation */ + cy_as_oper_type op, + /* The error status */ + cy_as_return_status_t status + ) ; + +typedef void (*cy_as_storage_event_callback_dep)( + /* Handle to the device sending the event notification */ + cy_as_device_handle handle, + /* The media type */ + cy_as_media_type type, + /* The event type */ + cy_as_storage_event evtype, + /* Event related data */ + void *evdata + ) ; + +typedef struct cy_as_storage_query_device_data_dep { + /* The type of media to query */ + cy_as_media_type type ; + /* The logical device number to query */ + uint32_t device ; + /* The return value for the device descriptor */ + cy_as_device_desc desc_p ; +} cy_as_storage_query_device_data_dep ; + +typedef struct cy_as_storage_query_unit_data_dep { + /* The type of media to query */ + cy_as_media_type type ; + /* The logical device number to query */ + uint32_t device ; + /* The unit to query on the device */ + uint32_t unit ; + /* The return value for the unit descriptor */ + cy_as_unit_desc desc_p ; +} cy_as_storage_query_unit_data_dep ; + + +/************ FUNCTIONS *********************/ + +EXTERN cy_as_return_status_t +cy_as_storage_register_callback_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The callback function to call for async storage events */ + cy_as_storage_event_callback_dep callback + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_claim_dep(cy_as_device_handle handle, + cy_as_media_type type + ); + +EXTERN cy_as_return_status_t +cy_as_storage_claim_dep_EX( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to claim */ + cy_as_media_type *type, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_release_dep(cy_as_device_handle handle, + cy_as_media_type type + ); + +EXTERN cy_as_return_status_t +cy_as_storage_release_dep_EX( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Handle to the device of interest */ + cy_as_media_type *type, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_query_device_dep( + cy_as_device_handle handle, + cy_as_media_type media, + uint32_t device, + cy_as_device_desc *desc_p + ); + +EXTERN cy_as_return_status_t +cy_as_storage_query_device_dep_EX( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Parameters and return value for the query call */ + cy_as_storage_query_device_data_dep *data, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_query_unit_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to query */ + cy_as_media_type type, + /* The logical device number to query */ + uint32_t device, + /* The unit to query on the device */ + uint32_t unit, + /* The return value for the unit descriptor */ + cy_as_unit_desc *unit_p + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_query_unit_dep_EX( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* Parameters and return value for the query call */ + cy_as_storage_query_unit_data_dep *data_p, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_device_control_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Enable/disable control for card detection */ + cy_bool card_detect_en, + /* Enable/disable control for write protect handling */ + cy_bool write_prot_en, + /* Callback to be called when the operation is complete */ + cy_as_function_callback cb, + /* Client data to be passed to the callback */ + uint32_t client + ) ; + + +EXTERN cy_as_return_status_t +cy_as_storage_read_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to access */ + cy_as_media_type type, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where data will be placed */ + void *data_p, + /* The number of blocks to be read */ + uint16_t num_blocks + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_read_async_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to access */ + cy_as_media_type type, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where data will be placed */ + void *data_p, + /* The number of blocks to be read */ + uint16_t num_blocks, + /* The function to call when the read is complete + or an error occurs */ + cy_as_storage_callback_dep callback + ) ; +EXTERN cy_as_return_status_t +cy_as_storage_write_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to access */ + cy_as_media_type type, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer containing the data to be written */ + void *data_p, + /* The number of blocks to be written */ + uint16_t num_blocks + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_write_async_dep( + /* Handle to the device of interest */ + cy_as_device_handle handle, + /* The type of media to access */ + cy_as_media_type type, + /* The device to access */ + uint32_t device, + /* The unit to access */ + uint32_t unit, + /* The first block to access */ + uint32_t block, + /* The buffer where the data to be written is stored */ + void *data_p, + /* The number of blocks to be written */ + uint16_t num_blocks, + /* The function to call when the write is complete + or an error occurs */ + cy_as_storage_callback_dep callback + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_sd_register_read_dep( + cy_as_device_handle handle, + cy_as_media_type type, + uint8_t device, + cy_as_sd_card_reg_type reg_type, + uint8_t read_len, + uint8_t *data_p + ); + +EXTERN cy_as_return_status_t +cy_as_storage_sd_register_read_dep_EX( + /* Handle to the West Bridge device. */ + cy_as_device_handle handle, + /* The type of media to query */ + cy_as_media_type type, + /* The device to query */ + uint8_t device, + /* The type of register to read. */ + cy_as_sd_card_reg_type reg_type, + /* Output data buffer and length. */ + cy_as_storage_sd_reg_read_data *data_p, + /* Callback function to call when done. */ + cy_as_function_callback cb, + /* Call context to send to the cb function. */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_storage_create_p_partition_dep( + cy_as_device_handle handle, + cy_as_media_type media, + uint32_t device, + uint32_t size, + cy_as_function_callback cb, + uint32_t client) ; + +EXTERN cy_as_return_status_t +cy_as_storage_remove_p_partition_dep( + cy_as_device_handle handle, + cy_as_media_type media, + uint32_t device, + cy_as_function_callback cb, + uint32_t client) ; + +#endif /*__doxygen*/ + +#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h new file mode 100644 index 000000000000..b1b18d0685e4 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastoria.h @@ -0,0 +1,36 @@ +/* Cypress West Bridge API header file (cyastioch.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASTORIA_H_ +#define _INCLUDED_CYASTORIA_H_ + +#if !defined(__doxygen__) + +#include "cyaserr.h" +#include "cyasmisc.h" +#include "cyasstorage.h" +#include "cyasusb.h" +#include "cyasmtp.h" + +#endif + +#endif + diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h new file mode 100644 index 000000000000..a3c10aa559e2 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastsdkversion.h @@ -0,0 +1,30 @@ +/* Cypress Astoria Sdk Version file (cyastsdkversion.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASTSDK_VERSION_H_ +#define _INCLUDED_CYASTSDK_VERSION_H_ + +/* Astoria SDK version 1.2.1 */ +#define CYAS_MAJOR_VERSION (1) +#define CYAS_MINOR_VERSION (2) +#define CYAS_BUILD_NUMBER (197) + +#endif /*_INCLUDED_CYASTSDK_VERSION_H_*/ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h new file mode 100644 index 000000000000..2ccccf746a10 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyastypes.h @@ -0,0 +1,71 @@ +/* Cypress West Bridge API header file (cyastypes.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASTYPES_H_ +#define _INCLUDED_CYASTYPES_H_ +/* moved to staging location, eventual implementation + * considered is here +#include +*/ + #include "../../../arch/arm/plat-omap/include/mach/westbridge/cyashaldef.h" + +/* Types that are not available on specific platforms. + * These are used only in the reference HAL implementations and + * are not required for using the API. + */ +#ifdef __unix__ +typedef unsigned long DWORD; +typedef void *LPVOID; +#define WINAPI +#define INFINITE (0xFFFFFFFF) +#define ptr_to_uint(ptr) ((unsigned int)(ptr)) +#endif + +/* Basic types used by the entire API */ + +/* Summary + This type represents an endpoint number +*/ +typedef uint8_t cy_as_end_point_number_t ; + +/* Summary + This type is used to return status information from + an API call. +*/ +typedef uint16_t cy_as_return_status_t ; + +/* Summary + This type represents a bus number +*/ +typedef uint32_t cy_as_bus_number_t ; + +/* Summary + All APIs provided with this release are marked extern + through this definition. This definition can be changed + to meet the scope changes required in the user build + environment. + + For example, this can be changed to __declspec(exportdll) + to enable exporting the API from a DLL. + */ +#define EXTERN extern + +#endif diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h new file mode 100644 index 000000000000..f066848cb7a9 --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h @@ -0,0 +1,1862 @@ +/* Cypress West Bridge API header file (cyasusb.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +#ifndef _INCLUDED_CYASUSB_H_ +#define _INCLUDED_CYASUSB_H_ + +#include "cyasmisc.h" + +#include "cyas_cplus_start.h" + +/*@@Enumeration Model + Summary + The USB enumeration process is the process of communicating + to the USB host information + about the capabilities of the connected device. This + process is completed by servicing + requests for various types of descriptors. In the software + APIs described below, this + process is controlled in one of two ways. + + Description + There are advantages to either type of enumeration + and this is why both models are supported. + P Port processor based enumeraton gives the P port + processor maximum control and flexibility + for providing USB configuration information. However, + this does require (near) real time data + responses from the P port processor during the enumeration + process. West Bridge based enumeration + requires no real time information from the P port processor, + ensuring the fastest possible + enumeration times. + + * P Port Based Enumeration * + The first method for handling USB enumeration is for the + processor client to handle all + endpoint zero requests for descriptors. This mode is + configured by indicating to the API + that the processor wants to handle all endpoint zero + requests. This is done by setting + bit 0 in the end_point_mask to a 1. The processor uses + CyAsUsbReadDataAsync() to read the request and + CyAsUsbWriteDataAsync() to write the response. + + * West Bridge Based Enumeration * + The second method for handling USB enumeration is the + configuration information method. + Before enabling a connection from the West Bridge device + to the USB connector, the P Port + processor sends information about the USB configuration to + West Bridge through the configuration + APIs. This information is stored within the West Bridge + device. When a USB cable is attached, + the West Bridge device then handles all descriptor requests + based on the stored information. + Note that this method of enumeration only supports a single + USB configuration. + + In either model of enumeration, the processor client is + responsible for ensuring that + the system meets USB Chapter 9 compliance requirements. This + can be done by providing spec + compliant descriptors, and handling any setup packets that + are sent to the client + appropriately. + + Mass storage class compliance will be ensured by the West + Bridge firmware when the mass + storage functionality is enabled. +*/ + +/*@@Endpoint Configuration + Summary + The West Bridge device has one 64-byte control endpoint, one + 64-byte low bandwidth endpoint, four bulk + endpoints dedicated for mass storage usage, and up to ten + bulk/interrupt/isochronous + endpoints that can be used for USB-to-Processor communication. + + Description + The four storage endpoints (Endpoints 2, 4, 6 and 8) are + reserved for accessing storage + devices attached to West Bridge and are not available for use + by the processor. These are + used implicitly when using the storage API to read/write to + the storage media. + + Endpoint 0 is the standard USB control pipe used for all + enumeration activity. Though + the endpoint buffer is not directly accessible from the + processor, read/write activity + can be performed on this endpoint through the API layers. + This endpoint is always + configured as a bi-directional control endpoint. + + Endpoint 1 is a 64-byte endpoint that can be used for low + bandwidth bulk/interrupt + activity. The physical buffer is not accessible from the + processor, but can be read/written + through the API. As the data coming to this endpoint is + being handled through the + software layers, there can be loss of data if a read call + is not waiting when an OUT + packet arrives. + + Endpoints 3, 5, 7, 9, 10, 11, 12, 13, 14 and 15 are ten + configurable endpoints + mapped to parts of a total 4 KB FIFO buffer space on the + West Bridge device. This 4 KB + physical buffer space is divided into up to four endpoints + called PEP1, PEP2, PEP3 and PEP4 + in this software document. There are multiple configurations + in which this buffer space + can be used, and the size and number of buffers available to + each physical endpoint + vary between these configurations. See the West Bridge PDD + for details on the buffer + orientation corresponding to each configuration. + + * Note * + PEPs 1, 2, 3 and 4 are called Physical EP 3, 5, 7 and 9 in the + West Bridge PDD. The + sequential number scheme is used in the software to disambiguate + these from the logical + endpoint numbers, and also for convenience of array indexing. +*/ + +#if !defined(__doxygen__) + + +#endif + +/* Summary + This constants defines the maximum size of a USB descriptor + when referenced via the CyAsUsbSetDescriptor or + CyAsUsbGetDescriptor functions. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor +*/ +#define CY_AS_MAX_USB_DESCRIPTOR_SIZE (128) + +/*************************************** + * West Bridge Types + ***************************************/ + + +/* Summary + This data structure is the data passed via the evdata paramater + on a usb event callback for the inquiry request. + + Description + When a SCSI inquiry request arrives via the USB connection and + the P Port has asked + to receive inquiry requests, this request is forwarded to the + client via the USB + callback. This callback is called twice, once before the + inquiry data is forwarded + to the host (CyAsEventUsbInquiryBefore) and once after the + inquiry has been sent to the + USB host (CyAsEventUsbInquiryAfter). The evdata parameter + is a pointer to this data + structure. + + *CyAsEventUsbInquiryBefore* + If the client just wishes to see the inquiry request and + associated data, then a simple + return from the callback will forward the inquiry response + to the USB host. If the + client wishes to change the data returned to the USB host, + the updated parameter must + be set to CyTrue and the memory area address by the data + parameter should be updated. + The data pointer can be changed to point to a new memory + area and the length field + changed to change the amount of data returned from the + inquiry request. Note that the + data area pointed to by the data parameter must remain + valid and the contents must + remain consistent until after the CyAsEventUsbInquiryAfter + event has occurred. THE LENGTH + MUST BE LESS THAN 192 BYTES OR THE CUSTOM INQUIRY RESPONSE + WILL NOT BE RETURNED. If the + length is too long, the default inquiry response will be + returned. + + *CyAsEventUsbInquiryAfter* + If the client needs to free any data, this event signals that + the data associated with the inquiry is no longer needed. + + See Also + * CyAsUsbEventCallback + * CyAsUsbRegisterCallback +*/ +typedef struct cy_as_usb_inquiry_data { + /* The bus for the event */ + cy_as_bus_number_t bus ; + /* The device the event */ + uint32_t device ; + /* The EVPD bit from the SCSI INQUIRY request */ + uint8_t evpd ; + /* The codepage in the inquiry request */ + uint8_t codepage ; + /* This bool must be set to CyTrue indicate that the inquiry + data was changed */ + cy_bool updated ; + /* The length of the data */ + uint16_t length ; + /* The inquiry data */ + void *data ; +} cy_as_usb_inquiry_data ; + + +/* Summary + This data structure is the data passed via the evdata + parameter on a usb event + callback for the unknown mass storage request. + + Description + When a SCSI request is made that the mass storage + firmware in West Bridge does not + know how to process, this request is passed to the + processor for handling via + the usb callback. This data structure is used to + pass the request and the + associated response. The user may set the status + to indicate the status of the + request. The status value is the bCSWStatus value + from the USB mass storage + Command Status Wrapper (0 = command passed, 1 = + command failed). If the status + is set to command failed (1), the sense information + should be set as well. For + more information about sense information, see the + USB mass storage specification + as well as the SCSI specifications for block devices. + By default the status is + initialized to 1 (failure) with a sense information + of 05h/20h/00h which + indicates INVALID COMMAND. +*/ +typedef struct cy_as_usb_unknown_command_data { + /* The bus for the event */ + cy_as_bus_number_t bus ; + /* The device for the event */ + uint32_t device ; + + uint16_t reqlen ; + /* The request */ + void *request ; + + /* The returned status value for the command */ + uint8_t status ; + /* If status is failed, the sense key */ + uint8_t key ; + /* If status is failed, the additional sense code */ + uint8_t asc ; + /* If status if failed, the additional sense code qualifier */ + uint8_t ascq ; +} cy_as_usb_unknown_command_data ; + + +/* Summary + This data structure is the data passed via the evdata + paramater on a usb event callback for the start/stop request. + + Description + When a SCSI start stop request arrives via the USB connection + and the P Port has asked + + See Also + * CyAsUsbEventCallback + * CyAsUsbRegisterCallback +*/ +typedef struct cy_as_usb_start_stop_data { + /* The bus for the event */ + cy_as_bus_number_t bus ; + /* The device for the event */ + uint32_t device ; + /* CyTrue means start request, CyFalse means stop request */ + cy_bool start ; + /* CyTrue means LoEj bit set, otherwise false */ + cy_bool loej ; +} cy_as_usb_start_stop_data ; + +/* Summary + This data type is used to indicate which mass storage devices + are enumerated. + + Description + + See Also + * CyAsUsbEnumControl + * CyAsUsbSetEnumConfig +*/ +typedef enum cy_as_usb_mass_storage_enum { + cy_as_usb_nand_enum = 0x01, + cy_as_usb_sd_enum = 0x02, + cy_as_usb_mmc_enum = 0x04, + cy_as_usb_ce_ata_enum = 0x08 +} cy_as_usb_mass_storage_enum ; + +/* Summary + This data type specifies the type of descriptor to transfer + to the West Bridge device + + Description + During enumeration, if West Bridge is handling enumeration, + the West Bridge device needs to USB descriptors + to complete the enumeration. The function CyAsUsbSetDescriptor() + is used to transfer the descriptors + to the West Bridge device. This type is an argument to that + function and specifies which descriptor + is being transferred. + + See Also + * CyAsUsbSetDescriptor + * CyAsUsbGetDescriptor +*/ +typedef enum cy_as_usb_desc_type { + /* A device descriptor - See USB 2.0 specification Chapter 9 */ + cy_as_usb_desc_device = 1, + /* A device descriptor qualifier - + * See USB 2.0 specification Chapter 9 */ + cy_as_usb_desc_device_qual = 2, + /* A configuration descriptor for FS operation - + * See USB 2.0 specification Chapter 9 */ + cy_as_usb_desc_f_s_configuration = 3, + /* A configuration descriptor for HS operation - + * See USB 2.0 specification Chapter 9 */ + cy_as_usb_desc_h_s_configuration = 4, + cy_as_usb_desc_string = 5 +} cy_as_usb_desc_type ; + +/* Summary + This type specifies the direction of an endpoint + + Description + This type is used when configuring the endpoint hardware + to specify the direction + of the endpoint. + + See Also + * CyAsUsbEndPointConfig + * CyAsUsbSetEndPointConfig + * CyAsUsbGetEndPointConfig +*/ +typedef enum cy_as_usb_end_point_dir { + /* The endpoint direction is IN (West Bridge -> USB Host) */ + cy_as_usb_in = 0, + /* The endpoint direction is OUT (USB Host -> West Bridge) */ + cy_as_usb_out = 1, + /* The endpoint direction is IN/OUT (valid only for EP 0 & 1) */ + cy_as_usb_in_out = 2 +} cy_as_usb_end_point_dir ; + +/* Summary + This type specifies the type of an endpoint + + Description + This type is used when configuring the endpoint hardware + to specify the type of endpoint. + + See Also + * CyAsUsbEndPointConfig + * CyAsUsbSetEndPointConfig + * CyAsUsbGetEndPointConfig +*/ +typedef enum cy_as_usb_end_point_type { + cy_as_usb_control, + cy_as_usb_iso, + cy_as_usb_bulk, + cy_as_usb_int +} cy_as_usb_end_point_type ; + +/* Summary + This type is a structure used to indicate the top level + configuration of the USB stack + + Description + In order to configure the USB stack, the CyAsUsbSetEnumConfig() + function is called to indicate + how mass storage is to be handled, the specific number of + interfaces to be supported if + West Bridge is handling enumeration, and the end points of + specifi interest. This structure + contains this information. + + See Also + * CyAsUsbSetConfig + * CyAsUsbGetConfig + * +*/ +typedef struct cy_as_usb_enum_control { + /* Designate which devices on which buses to enumerate */ + cy_bool devices_to_enumerate[CY_AS_MAX_BUSES] + [CY_AS_MAX_STORAGE_DEVICES]; + /* If true, West Bridge will control enumeration. If this + * is false the P port controls enumeration. if the P port + * is controlling enumeration, traffic will be received via + * endpoint zero. */ + cy_bool antioch_enumeration ; + /* This is the interface # to use for the mass storage + * interface, if mass storage is enumerated. if mass + * storage is not enumerated this value should be zero. */ + uint8_t mass_storage_interface ; + /* This is the interface # to use for the MTP interface, + * if MTP is enumerated. if MTP is not enumerated + * this value should be zero. */ + uint8_t mtp_interface ; + /* If true, Inquiry, START/STOP, and unknown mass storage + * requests cause a callback to occur for handling by the + * baseband processor. */ + cy_bool mass_storage_callbacks ; +} cy_as_usb_enum_control ; + + +/* Summary + This structure is used to configure a single endpoint + + Description + This data structure contains all of the information required + to configure the West Bridge hardware + associated with a given endpoint. + + See Also + * CyAsUsbSetEndPointConfig + * CyAsUsbGetEndPointConfig +*/ +typedef struct cy_as_usb_end_point_config { + /* If true, this endpoint is enabled */ + cy_bool enabled ; + /* The direction of this endpoint */ + cy_as_usb_end_point_dir dir ; + /* The type of endpoint */ + cy_as_usb_end_point_type type ; + /* The physical endpoint #, 1, 2, 3, 4 */ + cy_as_end_point_number_t physical ; + /* The size of the endpoint in bytes */ + uint16_t size ; +} cy_as_usb_end_point_config ; + +/* Summary + List of partition enumeration combinations that can + be selected on a partitioned storage device. + + Description + West Bridge firmware supports creating upto two + partitions on mass storage devices connected to + West Bridge. When there are two partitions on a device, + the user can choose which of these partitions should be + made visible to a USB host through the mass storage + interface. This enumeration lists the various enumeration + selections that can be made. + + See Also + * CyAsStorageCreatePPartition + * CyAsStorageRemovePPartition + * CyAsUsbSelectMSPartitions + */ +typedef enum cy_as_usb_m_s_type_t { + /* Enumerate only partition 0 as CD (autorun) device */ + cy_as_usb_m_s_unit0 = 0, + /* Enumerate only partition 1 as MS device (default setting) */ + cy_as_usb_m_s_unit1, + /* Enumerate both units */ + cy_as_usb_m_s_both +} cy_as_usb_m_s_type_t ; + +/* Summary + This type specifies the type of USB event that has occurred + + Description + This type is used in the USB event callback function to + indicate the type of USB event that has occurred. The callback + function includes both this reasons for the callback and a data + parameter associated with the reason. The data parameter is used + in a reason specific way and is documented below with each reason. + + See Also + * CyAsUsbIoCallback +*/ +typedef enum cy_as_usb_event { + /* This event is sent when West Bridge is put into the suspend + state by the USB host. the data parameter is not used and + will be zero. */ + cy_as_event_usb_suspend, + /* This event is sent when West Bridge is taken out of the + suspend state by the USB host. the data parameter is not + used and will be zero. */ + cy_as_event_usb_resume, + /* This event is sent when a USB reset request is received + by the west bridge device. the data parameter is not used and + will be zero. */ + cy_as_event_usb_reset, + /* This event is sent when a USB set configuration request is made. + the data parameter is a pointer to a uint16_t that contains the + configuration number. the configuration number may be zero to + indicate an unconfigure operation. */ + cy_as_event_usb_set_config, + /* This event is sent when the USB connection changes speed. This is + generally a transition from full speed to high speed. the parameter + to this event is a pointer to uint16_t that gives the speed of the + USB connection. zero indicates full speed, one indicates high speed */ + cy_as_event_usb_speed_change, + /* This event is sent when a setup packet is received. + * The data parameter is a pointer to the eight bytes of setup data. */ + cy_as_event_usb_setup_packet, + /* This event is sent when a status packet is received. The data + parameter is not used. */ + cy_as_event_usb_status_packet, + /* This event is sent when mass storage receives an inquiry + request and we have asked to see these requests. */ + cy_as_event_usb_inquiry_before, + /* This event is sent when mass storage has finished processing an + inquiry request and any data associated with the request is no longer + required. */ + cy_as_event_usb_inquiry_after, + /* This event is sent when mass storage receives a start/stop + * request and we have asked to see these requests */ + cy_as_event_usb_start_stop, + /* This event is sent when a Clear Feature request is received. + * The data parameter is the endpoint number. */ + cy_as_event_usb_clear_feature, + /* This event is sent when mass storage receives a request + * that is not known and we have asked to see these requests */ + cy_as_event_usb_unknown_storage, + /* This event is sent when the read/write activity on the USB mass + storage has crossed a pre-set level */ + cy_as_event_usb_m_s_c_progress +} cy_as_usb_event; + +/* Summary + This type is the type of a callback function that is + called when a USB event occurs + + Description + At times West Bridge needs to inform the P port processor + of events that have + occurred. These events are asynchronous to the thread of + control on the P + port processor and as such are generally delivered via a + callback function that + is called as part of an interrupt handler. This type + defines the type of function + that must be provided as a callback function for USB events. + + See Also + * CyAsUsbEvent +*/ +typedef void (*cy_as_usb_event_callback)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The event type being reported */ + cy_as_usb_event ev, + /* The data assocaited with the event being reported */ + void *evdata +) ; + + +/* Summary + This type is the callback function called after an + asynchronous USB read/write operation + + Description + This function type defines a callback function that is + called at the completion of any + asynchronous read or write operation. + + See Also + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync + * CY_AS_ERROR_CANCELED +*/ +typedef void (*cy_as_usb_io_callback)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The endpoint that has completed an operation */ + cy_as_end_point_number_t ep, + /* THe amount of data transferred to/from USB */ + uint32_t count, + /* The data buffer for the operation */ + void *buffer, + /* The error status of the operation */ + cy_as_return_status_t status +) ; + +/* Summary + This type is the callback function called after asynchronous + API functions have completed. + + Description + When calling API functions from callback routines (interrupt + handlers usually) the async version of + these functions must be used. This callback is called when an + asynchronous API function has completed. +*/ +typedef void (*cy_as_usb_function_callback)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The error status of the operation */ + cy_as_return_status_t status, + /* A client supplied 32 bit tag */ + uint32_t client +) ; + + +/******************************************** + * West Bridge Functions + ********************************************/ + +/* Summary + This function starts the USB stack + + Description + This function initializes the West Bridge USB software + stack if it has not yet been stared. + This initializes any required data structures and powers + up any USB specific portions of + the West Bridge hardware. If the stack had already been + started, the USB stack reference count + is incremented. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + This function cannot be called from any type of West Bridge + callback. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_SUCCESS - the stack initialized and is ready + * for use + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating + * with the West Bridge device + + See Also + * CyAsUsbStop +*/ +EXTERN cy_as_return_status_t +cy_as_usb_start( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function stops the USB stack + + Description + This function decrements the reference count for + the USB stack and if this count + is zero, the USB stack is shut down. The shutdown + frees all resources associated + with the USB stack. + + * Valid In Asynchronous Callback: NO + + Notes + While all resources associated with the USB stack will + be freed is a shutdown occurs, + resources associated with underlying layers of the software + will not be freed if they + are shared by the storage stack and the storage stack is active. + Specifically the DMA manager, + the interrupt manager, and the West Bridge communications module + are all shared by both the + USB stack and the storage stack. + + Returns + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + + See Also + * CyAsUsbStart +*/ +EXTERN cy_as_return_status_t +cy_as_usb_stop( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function registers a callback function to be called when an + asynchronous USB event occurs + + Description + When asynchronous USB events occur, a callback function can be + called to alert the calling program. This + functions allows the calling program to register a callback. + + * Valid In Asynchronous Callback: YES +*/ +EXTERN cy_as_return_status_t +cy_as_usb_register_callback( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The function to call */ + cy_as_usb_event_callback callback + ) ; + + +/* Summary + This function connects the West Bridge device D+ and D- signals + physically to the USB host. + + Description + The West Bridge device has the ability to programmatically + disconnect the USB pins on the device + from the USB host. This feature allows for re-enumeration of + the West Bridge device as a different + device when necessary. This function connects the D+ and D- + signal physically to the USB host + if they have been previously disconnnected. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + + See Also + * CyAsUsbDisconnect +*/ +EXTERN cy_as_return_status_t +cy_as_usb_connect( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function disconnects the West Bridge device D+ and D- + signals physically from the USB host. + + Description + The West Bridge device has the ability to programmatically + disconnect the USB pins on the device + from the USB host. This feature allows for re-enumeration + of the West Bridge device as a different + device when necessary. This function disconnects the D+ + and D- signal physically from the USB host + if they have been previously connected. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + + See Also + * CyAsUsbConnect +*/ +EXTERN cy_as_return_status_t +cy_as_usb_disconnect( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function configures the USB stack + + Description + This function is used to configure the USB stack. It is + used to indicate which endpoints are going to + be used, and how to deal with the mass storage USB device + within West Bridge. + + * Valid In Asynchronous Callback: Yes (if cb supplied) + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + + See Also + * CyAsUsbGetEnumConfig + * CyAsUsbEnumControl + */ +EXTERN cy_as_return_status_t +cy_as_usb_set_enum_config( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The USB configuration information */ + cy_as_usb_enum_control *config_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function retreives the current configuration of + the USB stack + + Description + This function sends a request to West Bridge to retreive + the current configuration + + * Valid In Asynchronous Callback: Yes (if cb supplied) + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + + See Also + * CyAsUsbSetConfig + * CyAsUsbConfig + */ +EXTERN cy_as_return_status_t +cy_as_usb_get_enum_config( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The return value for USB congifuration information */ + cy_as_usb_enum_control *config_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function sets the USB descriptor + + Description + This function is used to set the various descriptors + assocaited with the USB enumeration + process. This function should only be called when the + West Bridge enumeration model is selected. + Descriptors set using this function can be cleared by + stopping the USB stack, or by calling + the CyAsUsbClearDescriptors function. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + These descriptors are described in the USB 2.0 specification, + Chapter 9. + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_DESCRIPTOR - the descriptor passed is + * not valid + * CY_AS_ERROR_BAD_INDEX - a bad index was given for the type + * of descriptor given + * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be + * called if the P port processor doing enumeration + + See Also + * CyAsUsbGetDescriptor + * CyAsUsbClearDescriptors + * +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_descriptor( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The type of descriptor */ + cy_as_usb_desc_type type, + /* Only valid for string descriptors */ + uint8_t index, + /* The descriptor to be transferred */ + void *desc_p, + /* The length of the descriptor in bytes */ + uint16_t length, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function clears all user descriptors stored + on the West Bridge. + + Description + This function is used to clear all descriptors that + were previously + stored on the West Bridge through CyAsUsbSetDescriptor + calls, and go back + to the default descriptor setup in the firmware. This + function should + only be called when the Antioch enumeration model is + selected. + + * Valid In Asynchronous Callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - all descriptors cleared successfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be + * called if the P port processor is doing enumeration + + See Also + * CyAsUsbSetDescriptor + * +*/ +EXTERN cy_as_return_status_t +cy_as_usb_clear_descriptors( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; +/* Summary + This structure contains the descriptor buffer to be + filled by CyAsUsbGetDescriptor API. + + Description + This data structure the buffer to hold the descriptor + data, and an in/out parameter ti indicate the + lenght of the buffer and descriptor data in bytes. + + See Also + * CyAsUsbGetDescriptor +*/ +typedef struct cy_as_get_descriptor_data { + /* The buffer to hold the returned descriptor */ + void *desc_p; + /* This is an input and output parameter. + * Before the code this pointer points to a uint32_t + * that contains the length of the buffer. after + * the call, this value contains the amount of data + * actually returned. */ + uint32_t length; + +} cy_as_get_descriptor_data ; + +/* Summary + This function retreives a given descriptor from the + West Bridge device + + Description + This function retreives a USB descriptor from the West + Bridge device. This function should only be called when the + West Bridge enumeration model is selected. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Notes + These descriptors are described in the USB 2.0 specification, + Chapter 9. + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_BAD_INDEX - a bad index was given for the type of + * descriptor given + * CY_AS_ERROR_BAD_ENUMERATION_MODE - this function cannot be + * called if the P port processor doing enumeration + + See Also + * CyAsUsbSetDescriptor + * +*/ + +EXTERN cy_as_return_status_t +cy_as_usb_get_descriptor( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The type of descriptor */ + cy_as_usb_desc_type type, + /* Index for string descriptor */ + uint8_t index, + /* Parameters and return value for the get descriptor call */ + cy_as_get_descriptor_data *data, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function sets the configuration of the physical + endpoints into one of the twelve supported configuration + + Description + USB endpoints are mapped onto one of four physical + endpoints in the device. Therefore + USB endpoints are known as logical endpoints and these + logical endpoints are mapped to + one of four physical endpoints. In support of these + four physical endpoints there is + four kilo-bytes of buffer spaces that can be used as + buffers for these physical endpoints. + This 4K of buffer space can be configured in one of + twelve ways. This function sets the + buffer configuration for the physical endpoints. + + * Config 1: PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (2 * 512), PEP4 (2 * 512) + * Config 2: PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (4 * 512), PEP4 (N/A) + * Config 3: PEP1 (2 * 512), PEP2 (2 * 512), + * PEP3 (2 * 1024), PEP4(N/A) + * Config 4: PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (2 * 512), PEP4 (2 * 512) + * Config 5: PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (4 * 512), PEP4 (N/A) + * Config 6: PEP1 (4 * 512), PEP2 (N/A), + * PEP3 (2 * 1024), PEP4 (N/A) + * Config 7: PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (2 * 512), PEP4 (2 * 512) + * Config 8: PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (4 * 512), PEP4 (N/A) + * Config 9: PEP1 (2 * 1024), PEP2 (N/A), + * PEP3 (2 * 1024), PEP4 (N/A) + * Config 10: PEP1 (3 * 512), PEP2 (N/A), + * PEP3 (3 * 512), PEP4 (2 * 512) + * Config 11: PEP1 (3 * 1024), PEP2 (N/A), + * PEP3 (N/A), PEP4 (2 * 512) + * Config 12: PEP1 (4 * 1024), PEP2 (N/A), + * PEP3 (N/A), PEP4 (N/A) + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_CONFIGURATION - the configuration given + * is not between 1 and 12 +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_physical_configuration( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The physical endpoint configuration number */ + uint8_t config + ) ; + +/* Summary + This function sets the hardware configuration for a given endpoint + + Description + This function sets the hardware configuration for a given endpoint. + This is the method to set the direction of the endpoint, the type + of endpoint, the size of the endpoint buffer, and the buffering + style for the endpoint. + + * Valid In Asynchronous Callback: NO + + Notes + Add documentation about endpoint configuration limitations + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is invalid + * CY_AS_ERROR_INVALID_CONFIGURATION - the endpoint configuration + * given is not valid + * CY_AS_ERROR_ENDPOINT_CONFIG_NOT_SET - the physical endpoint + * configuration is not set + + See Also + * CyAsUsbGetEndPointConfig + * CyAsUsbEndPointConfig +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_end_point_config( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The configuration information for the endpoint */ + cy_as_usb_end_point_config *config_p + ) ; + +/* Summary + This function retreives the hardware configuration for + a given endpoint + + Description + This function gets the hardware configuration for the given + endpoint. This include information about the direction of + the endpoint, the type of endpoint, the size of the endpoint + buffer, and the buffering style for the endpoint. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is + * invalid + + See Also + * CyAsUsbSetEndPointConfig + * CyAsUsbEndPointConfig +*/ +EXTERN cy_as_return_status_t +cy_as_usb_get_end_point_config( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest*/ + cy_as_end_point_number_t ep, + /* The return value containing the endpoint config + * information */ + cy_as_usb_end_point_config *config_p + ) ; + +/* Summary + This function commits the configuration information that + has previously been set. + + Description + The initialization process involves calling CyAsUsbSetEnumConfig() + and CyAsUsbSetEndPointConfig(). These + functions do not actually send the configuration information to + the West Bridge device. Instead, these + functions store away the configuration information and this + CyAsUsbCommitConfig() actually finds the + best hardware configuration based on the requested endpoint + configuration and sends thsi optimal + confiuration down to the West Bridge device. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - a configuration was found and sent + * to West Bridge + * CY_AS_ERROR_NOT_CONFIGURED - the West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - the firmware has not been loaded + * into West Bridge + * CY_AS_ERROR_INVALID_CONFIGURATION - the configuration requested + * is not possible + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + + See Also + * CyAsUsbSetEndPointConfig + * CyAsUsbSetEnumConfig +*/ + +EXTERN cy_as_return_status_t +cy_as_usb_commit_config( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function reads data from a USB endpoint. + + Description + This function reads data from an OUT. This function blocks + until the read is complete. + If this is a packet read, a single received USB packet will + complete the read. If this + is not a packet read, this function will block until all of + the data requested has been + recevied. + + * Valid In Asynchronous Callback: NO + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is + * invalid + + See Also + * CyAsUsbReadDataAsync + * CyAsUsbWriteData + * CyAsUsbWriteDataAsync +*/ +EXTERN cy_as_return_status_t +cy_as_usb_read_data( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* If CyTrue, this is a packet read */ + cy_bool pktread, + /* The amount of data to read */ + uint32_t dsize, + /* The amount of data read */ + uint32_t *dataread, + /* The buffer to hold the data read */ + void *data + ) ; + +/* Summary + This function reads data from a USB endpoint + + Description + This function reads data from an OUT endpoint. This + function will return immediately and the callback + provided will be called when the read is complete. + If this is a packet read, then the callback will be + called on the next received packet. If this is not a + packet read, the callback will be called when the + requested data is received. + + * Valid In Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is + * invalid + + See Also + * CyAsUsbReadData + * CyAsUsbWriteData + * CyAsUsbWriteDataAsync +*/ +EXTERN cy_as_return_status_t +cy_as_usb_read_data_async( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* If CyTrue, this is a packet read */ + cy_bool pktread, + /* The amount of data to read */ + uint32_t dsize, + /* The buffer for storing the data */ + void *data, + /* The callback function to call when the data is read */ + cy_as_usb_io_callback callback + ) ; + +/* Summary + This function writes data to a USB endpoint + + Description + This function writes data to an IN endpoint data buffer. + Multiple USB packets may be sent until all data requeste + has been sent. This function blocks until all of the data + has been sent. + + * Valid In Asynchronous Callback: NO + + Notes + Calling this function with a dsize of zero will result in + a zero length packet transmitted to the USB host. + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is + * invalid + + See Also + * CyAsUsbReadData + * CyAsUsbReadDataAsync + * CyAsUsbWriteDataAsync +*/ +EXTERN cy_as_return_status_t +cy_as_usb_write_data( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint to write data to */ + cy_as_end_point_number_t ep, + /* The size of the data to write */ + uint32_t dsize, + /* The data buffer */ + void *data + ) ; + +/* Summary + This function writes data to a USB endpoint + + Description + This function writes data to an IN endpoint data buffer. + This function returns immediately and when the write + completes, or if an error occurs, the callback function + is called to indicate completion of the write operation. + + * Valid In Asynchronous Callback: YES + + Notes + Calling this function with a dsize of zero will result + in a zero length packet transmitted to the USB host. + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down sucessfully + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint parameter is + * invalid + + See Also + * CyAsUsbReadData + * CyAsUsbReadDataAsync + * CyAsUsbWriteData +*/ +EXTERN cy_as_return_status_t +cy_as_usb_write_data_async( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint to write data to */ + cy_as_end_point_number_t ep, + /* The size of the data */ + uint32_t dsize, + /* The buffer containing the data */ + void *data, + /* If true, send a short packet to terminate data */ + cy_bool spacket, + /* The callback to call when the data is written */ + cy_as_usb_io_callback callback + ) ; + +/* Summary + This function aborts an outstanding asynchronous + operation on a given endpoint + + Description + This function aborts any outstanding operation that is + pending on the given endpoint. + + * Valid In Asynchronous Callback: YES + + Returns + * CY_AS_ERROR_SUCCESS - this module was shut down + * sucessfully + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not + * running + * CY_AS_ERROR_ASYNC_NOT_PENDING - no asynchronous USB + * operation was pending + + See Also + * CyAsUsbReadData + * CyAsUsbReadDataAsync + * CyAsUsbWriteData + * CyAsUsbWriteDataAsync +*/ +EXTERN cy_as_return_status_t +cy_as_usb_cancel_async( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep + ) ; + +/* Summary + This function sets a stall condition on a given endpoint + + Description + This function sets a stall condition on the given endpoint. + If the callback function is not zero, the function is + executed asynchronously and the callback is called when + the function is completed. If the callback function is + zero, this function executes synchronously and will not + return until the function has completed. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid, + * or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied) + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbGetStall + * CyAsUsbClearStall +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_stall( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client +) ; + +/* Summary + This function clears a stall condition on a given endpoint + + Description + This function clears a stall condition on the given endpoint. + If the callback function is not zero, the function is + executed asynchronously and the callback is called when the + function is completed. If the callback function is zero, this + function executes synchronously and will not return until the + function has completed. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid, + * or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied) + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbGetStall + * CyAsUsbSetStall +*/ + +EXTERN cy_as_return_status_t +cy_as_usb_clear_stall( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + + +/* Summary + This function returns the stall status for a given endpoint + + Description + This function returns the stall status for a given endpoint + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid, + * or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbGetStall + * CyAsUsbSetStall + * CyAsUsbClearStall +*/ + +EXTERN cy_as_return_status_t +cy_as_usb_get_stall( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The return value for the stall state */ + cy_bool *stall_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function sets a NAK condition on a given endpoint + + Description + This function sets a NAK condition on the given endpoint. + If the callback function is not zero, the function is + executed asynchronously and the callback is called when + the function is completed. If the callback function is + zero, this function executes synchronously and will not + return until the function has completed. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was + * invalid, or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied) + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbGetNak + * CyAsUsbClearNak +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_nak( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client +) ; + +/* Summary + This function clears a NAK condition on a given endpoint + + Description + This function clears a NAK condition on the given endpoint. + If the callback function is not zero, the function is + executed asynchronously and the callback is called when the + function is completed. If the callback function is zero, + this function executes synchronously and will not return + until the function has completed. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid, + * or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK (only if no cb supplied) + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbGetNak + * CyAsUsbSetNak +*/ +EXTERN cy_as_return_status_t +cy_as_usb_clear_nak( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function returns the NAK status for a given endpoint + + Description + This function returns the NAK status for a given endpoint + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_INVALID_ENDPOINT - the endpoint given was invalid, + * or was not configured as an OUT endpoint + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + + See Also + * CyAsUsbSetNak + * CyAsUsbClearNak +*/ +EXTERN cy_as_return_status_t +cy_as_usb_get_nak( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The return value for the stall state */ + cy_bool *nak_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client +) ; + +/* Summary + This function triggers a USB remote wakeup from the Processor + API + + Description + When there is a Suspend condition on the USB bus, this function + programmatically takes the USB bus out of thi suspend state. + + * Valid In Asynchronous Callback: YES (if cb supplied) + * Nestable: YES + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE + * CY_AS_ERROR_INVALID_IN_CALLBACK + * CY_AS_ERROR_OUT_OF_MEMORY + * CY_AS_ERROR_INVALID_RESPONSE + * CY_AS_ERROR_NOT_IN_SUSPEND + +*/ +EXTERN cy_as_return_status_t +cy_as_usb_signal_remote_wakeup( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + This function sets the threshold levels for mass storage progress + reports from the West Bridge. + + Description + The West Bridge firmware can be configured to track the amount of + read/write activity on the mass storage device, and send progress + reports when the activity level has crossed a threshold level. + This function sets the threshold levels for the progress reports. + Set wr_sectors and rd_sectors to 0, if the progress reports are to + be turned off. + + * Valid In Asynchronous Callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - the function succeeded + * CY_AS_ERROR_NOT_RUNNING - the USB stack is not running + * CY_AS_ERROR_TIMEOUT - a timeout occurred communicating with + * the West Bridge device + * CY_AS_ERROR_INVALID_HANDLE - Bad handle + * CY_AS_ERROR_INVALID_IN_CALLBACK - Synchronous call made + * while in callback + * CY_AS_ERROR_OUT_OF_MEMORY - Failed allocating memory for + * request processing + * CY_AS_ERROR_NOT_SUPPORTED - Firmware version does not support + * mass storage progress tracking + * CY_AS_ERROR_INVALID_RESPONSE - Unexpected response from + * Firmware + + See Also + * CyAsUsbMSCProgressData + * CyAsEventUsbMSCProgress +*/ +EXTERN cy_as_return_status_t +cy_as_usb_set_m_s_report_threshold( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Number of sectors written before report is sent */ + uint32_t wr_sectors, + /* Number of sectors read before report is sent */ + uint32_t rd_sectors, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +/* Summary + Specify which of the partitions on a partitioned mass storage + device should be made visible to USB. + + Description + West Bridge firmware supports the creation of upto two + partitions on mass storage devices connected to the West Bridge + device. When there are two partitions on a device, the user can + choose which of these partitions should be made visible to the + USB host through the USB mass storage interface. This function + allows the user to configure the partitions that should be + enumerated. At least one partition should be selected through + this API. If neither partition needs to be enumerated, use + CyAsUsbSetEnumConfig to control this. + + * Valid in Asynchronous callback: Yes (if cb supplied) + * Nestable: Yes + + Returns + * CY_AS_ERROR_SUCCESS - operation completed successfully + * CY_AS_ERROR_INVALID_HANDLE - invalid handle to the West + * Bridge device + * CY_AS_ERROR_NOT_CONFIGURED - West Bridge device has not + * been configured + * CY_AS_ERROR_NO_FIRMWARE - no firmware running on West + * Bridge device + * CY_AS_ERROR_NOT_RUNNING - USB stack has not been started + * CY_AS_ERROR_IN_SUSPEND - West Bridge device is in + * suspend mode + * CY_AS_ERROR_INVALID_CALL_SEQUENCE - this API has to be + * called before CyAsUsbSetEnumConfig + * CY_AS_ERROR_OUT_OF_MEMORY - failed to get memory to + * process the request + * CY_AS_ERROR_NO_SUCH_UNIT - Storage device addressed has + * not been partitioned + * CY_AS_ERROR_NOT_SUPPORTED - operation is not supported by + * active device/firmware. + + See Also + * CyAsStorageCreatePPartition + * CyAsStorageRemovePPartition + * CyAsUsbMsType_t + */ +EXTERN cy_as_return_status_t +cy_as_usb_select_m_s_partitions( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* Bus index of the device being addressed */ + cy_as_bus_number_t bus, + /* Device id of the device being addressed */ + uint32_t device, + /* Selection of partitions to be enumerated */ + cy_as_usb_m_s_type_t type, + /* The callback, if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ); + +extern cy_as_media_type +cy_as_storage_get_media_from_address(uint16_t v) ; + +extern cy_as_bus_number_t +cy_as_storage_get_bus_from_address(uint16_t v) ; + +extern uint32_t +cy_as_storage_get_device_from_address(uint16_t v) ; + +/* For supporting deprecated functions */ +#include "cyasusb_dep.h" + +#include "cyas_cplus_end.h" + +#endif /* _INCLUDED_CYASUSB_H_ */ diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h new file mode 100644 index 000000000000..0ee18e8ba1bd --- /dev/null +++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb_dep.h @@ -0,0 +1,224 @@ +/* Cypress West Bridge API header file (cyasusb_dep.h) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street +## Fifth Floor, Boston, MA 02110-1301, USA. +## =========================== +*/ + +/* + * This header will contain Antioch specific declaration + * of the APIs that are deprecated in Astoria SDK. This is + * for maintaining backward compatibility. + */ + +#ifndef __INCLUDED_CYASUSB_DEP_H__ +#define __INCLUDED_CYASUSB_DEP_H__ + +#ifndef __doxygen__ + +/* + This data structure is the data passed via the evdata + paramater on a usb event callback for the inquiry request. +*/ + +typedef struct cy_as_usb_inquiry_data_dep { + /* The media for the event */ + cy_as_media_type media ; + /* The EVPD bit from the SCSI INQUIRY request */ + uint8_t evpd ; + /* The codepage in the inquiry request */ + uint8_t codepage ; + /* This bool must be set to CyTrue indicate + * that the inquiry data was changed */ + cy_bool updated ; + /* The length of the data */ + uint16_t length ; + /* The inquiry data */ + void *data ; +} cy_as_usb_inquiry_data_dep ; + + +typedef struct cy_as_usb_unknown_command_data_dep { + /* The media for the event */ + cy_as_media_type media ; + /* The length of the requst (should be 16 bytes) */ + uint16_t reqlen ; + /* The request */ + void *request ; + /* The returned status value for the command */ + uint8_t status ; + /* If status is failed, the sense key */ + uint8_t key ; + /* If status is failed, the additional sense code */ + uint8_t asc ; + /* If status if failed, the additional sense code qualifier */ + uint8_t ascq ; +} cy_as_usb_unknown_command_data_dep ; + + +typedef struct cy_as_usb_start_stop_data_dep { + /* The media type for the event */ + cy_as_media_type media ; + /* CyTrue means start request, CyFalse means stop request */ + cy_bool start ; + /* CyTrue means LoEj bit set, otherwise false */ + cy_bool loej ; +} cy_as_usb_start_stop_data_dep ; + + +typedef struct cy_as_usb_enum_control_dep { + /* The bits in this member determine which mass storage devices + are enumerated. see cy_as_usb_mass_storage_enum for more details. */ + uint8_t enum_mass_storage ; + /* If true, West Bridge will control enumeration. If this is false the + pport controls enumeration. if the P port is controlling + enumeration, traffic will be received via endpoint zero. */ + cy_bool antioch_enumeration ; + /* This is the interface # to use for the mass storage interface, + if mass storage is enumerated. if mass storage is not enumerated + this value should be zero. */ + uint8_t mass_storage_interface ; + /* If true, Inquiry, START/STOP, and unknown mass storage + requests cause a callback to occur for handling by the + baseband processor. */ + cy_bool mass_storage_callbacks ; +} cy_as_usb_enum_control_dep ; + + +typedef void (*cy_as_usb_event_callback_dep)( + /* Handle to the device to configure */ + cy_as_device_handle handle, + /* The event type being reported */ + cy_as_usb_event ev, + /* The data assocaited with the event being reported */ + void *evdata +) ; + + + +/* Register Callback api */ +EXTERN cy_as_return_status_t +cy_as_usb_register_callback_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The function to call */ + cy_as_usb_event_callback_dep callback + ) ; + + +extern cy_as_return_status_t +cy_as_usb_set_enum_config_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The USB configuration information */ + cy_as_usb_enum_control_dep *config_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + + +extern cy_as_return_status_t +cy_as_usb_get_enum_config_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The return value for USB congifuration information */ + cy_as_usb_enum_control_dep *config_p, + /* The callback if async call */ + cy_as_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +extern cy_as_return_status_t +cy_as_usb_get_descriptor_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The type of descriptor */ + cy_as_usb_desc_type type, + /* Index for string descriptor */ + uint8_t index, + /* The buffer to hold the returned descriptor */ + void *desc_p, + /* This is an input and output parameter. Before the code this pointer + points to a uint32_t that contains the length of the buffer. after + the call, this value contains the amount of data actually returned. */ + uint32_t *length_p + ) ; + +extern cy_as_return_status_t +cy_as_usb_set_stall_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_usb_function_callback cb, + /* Client supplied data */ + uint32_t client +) ; + +EXTERN cy_as_return_status_t +cy_as_usb_clear_stall_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_usb_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_usb_set_nak_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_usb_function_callback cb, + /* Client supplied data */ + uint32_t client +) ; + +EXTERN cy_as_return_status_t +cy_as_usb_clear_nak_dep( + /* Handle to the West Bridge device */ + cy_as_device_handle handle, + /* The endpoint of interest */ + cy_as_end_point_number_t ep, + /* The callback if async call */ + cy_as_usb_function_callback cb, + /* Client supplied data */ + uint32_t client + ) ; + +EXTERN cy_as_return_status_t +cy_as_usb_select_m_s_partitions_dep( + cy_as_device_handle handle, + cy_as_media_type media, + uint32_t device, + cy_as_usb_m_s_type_t type, + cy_as_function_callback cb, + uint32_t client + ) ; + +#endif /*__doxygen*/ + +#endif /*__INCLUDED_CYANSTORAGE_DEP_H__*/