From: David Cross Date: Sat, 7 Aug 2010 00:29:03 +0000 (-0700) Subject: Staging: add West Bridge Astoria Driver X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=81eb669b9516b85a2acf4c342db2322bed37d70c;p=openwrt%2Fstaging%2Fblogic.git Staging: add West Bridge Astoria Driver This is a driver for the Cypress West Bridge companion chip. Its function is analogous to the North/South Bridges of PC environments applied to embedded devices, in that it expands I/O and storage capabilities of an embedded processor. The Astoria version, which this driver applies to, functions as a USB, embedded memory and SDIO controller. The kernel that this patch was applied to is linux-2.6.35, although it was tested using the android kernel 2.6.29 running on the Zoom 2 platform. In this system, it was used primarily as a sideloading accelerator enabling direct data transfers between a USB host PC and embedded memory without system overheads. Minor modifications were also made to the kernel for this patch. These include changes such as EXPORTing of fat_get_block in the kernel code. Another function, mpage_cleardirty was also added to the memory management code. This function is used to clear the dirty pages from a specific inode. This allows for direct, file based DMA. None of these changes are believed to have any negative impact on the kernel and may provide additional benefit for other developers and drivers. The driver, as submitted, was placed into the drivers/staging/westbridge folder as the directory structure it will eventually reside in is not yet defined. The driver, as placed in staging is divided into four parts: 1) gadget - this implements a gadget peripheral controller and includes IOCTLs for MTP transfers 2) block -this implements a generic block device driver to enable access to embedded memory 3) api -this is the Cypress SDK, and includes USB and Storage specific functions. In addition, it includes common code for low level routines such as message passing and common data transfer routines 4) hal - this should likely be included in the arch directory as it needs to be modified for a given platform. The directory structure in the staging area is meant to reflect the eventual location of where this code likely should be. It is platform specific. In this case, the HAL included is for the Android Zoom 2 platform. Here, West Bridge is connected to the GPMC (general purpose memory controller) of the OMAP3. Specific timing needs to be enabled to ensure reliable communication. Many thanks to Greg KH for conducting initial reviews and providing pointers. Please contact david.cross@cypress.com for questions, concerns or feedback. Signed-off-by: David Cross Signed-off-by: Greg Kroah-Hartman --- 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__*/