diff options
Diffstat (limited to 'drivers/staging/westbridge/astoria/device/cyasdiagnostics.c')
-rw-r--r-- | drivers/staging/westbridge/astoria/device/cyasdiagnostics.c | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/drivers/staging/westbridge/astoria/device/cyasdiagnostics.c b/drivers/staging/westbridge/astoria/device/cyasdiagnostics.c new file mode 100644 index 0000000..378eb06 --- /dev/null +++ b/drivers/staging/westbridge/astoria/device/cyasdiagnostics.c @@ -0,0 +1,359 @@ +/* +## cyasdiagnostics.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 <linux/fs.h> +#include <linux/ioport.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/scatterlist.h> +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <asm/io.h> +#include <linux/clk.h> + +#include <linux/device.h> +#include <linux/sched.h> +#include "cyasdiagnostics.h" + +#include "../include/linux/westbridge/cyashal.h" +#include "../include/linux/westbridge/cyastoria.h" + + +extern uint32_t cy_as_hal_storage_test(cy_as_device_handle dev_p, uint32_t loop_max); + +extern cy_as_device_handle cyasdevice_getdevhandle(void); +extern cy_as_hal_device_tag cyasdevice_gethaltag(void); +extern int cyasdevice_enter_standby(void); +extern int cyasdevice_leave_standby(void); + +extern int CyAsAPIUsbInit(void); +extern int CyAsAPIUsbExit(void); +extern int cyasdevice_reload_firmware(int mtp_mode); + +extern int cyasblkdev_blk_init(int fmajor, int fsearch); +extern void cyasblkdev_blk_exit(void); +extern int cy_as_gadget_init(int fmtp); +extern void cy_as_gadget_cleanup(void); + +#define CYASSTORAGE_MAX_XFER_SIZE (2*32768) +#define MAX_DRQ_LOOPS_IN_ISR 128 + +uint8_t *actdata ; +uint8_t *expdata ; + +uint32_t start_unit; + +int cy_as_diagnostics(cy_as_diag_cmd_type mode, char *result) +{ + uint32_t retVal = 0; +#ifdef __CYAS_SYSFS_FOR_DIAGNOSTICS__ + cy_as_device_handle cyas_hd = cyasdevice_getdevhandle(); + + switch (mode) { + case CY_AS_DIAG_GET_VERSION: + { + cy_as_get_firmware_version_data ver_data = {0}; + const char *str = "" ; + cyasdevice_leave_standby(); + retVal = cy_as_misc_get_firmware_version(cyas_hd, &ver_data, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message( + "cy_as_diagnostics: cannot get firmware version. reason code: %d\n", + retVal) ; + sprintf(result, "fail - %d", retVal); + return retVal; + } + + 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." ; + + cyasdevice_enter_standby(); + 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) ; + sprintf(result, "%d.%d.%d", ver_data.major, ver_data.minor, ver_data.build); + } + break; + + case CY_AS_DIAG_DISABLE_MSM_SDIO: + break; + case CY_AS_DIAG_ENABLE_MSM_SDIO: + break; + case CY_AS_DIAG_ENTER_STANDBY: + cyasdevice_enter_standby(); + break; + case CY_AS_DIAG_LEAVE_STANDBY: + cyasdevice_leave_standby(); + break; + case CY_AS_DIAG_CREATE_BLKDEV: + retVal = cyasblkdev_blk_init(0, 0); + break; + case CY_AS_DIAG_DESTROY_BLKDEV: + cyasblkdev_blk_exit(); + break; + case CY_AS_DIAG_SD_MOUNT: + { + int i; + uint32_t count = 0 ; + int bus = 1 ; + cy_as_storage_query_device_data dev_data ; + cy_as_storage_query_unit_data unit_data = {0} ; + cyasdevice_leave_standby(); + actdata = (uint8_t *)cy_as_hal_alloc(CYASSTORAGE_MAX_XFER_SIZE); + expdata = (uint8_t *)cy_as_hal_alloc(CYASSTORAGE_MAX_XFER_SIZE); + cy_as_hal_mem_set(actdata, 0, CYASSTORAGE_MAX_XFER_SIZE); + cy_as_hal_mem_set(expdata, 0, CYASSTORAGE_MAX_XFER_SIZE); + retVal = cy_as_storage_device_control(cyas_hd, bus, + 0, cy_true, cy_false, cy_as_storage_detect_SDAT_3, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR + "ERROR: Cannot set Device control - Reason code %d\n", retVal) ; + return retVal; + } + + /* Start the storage API and get a handle to the device we are interested in. */ + retVal = cy_as_storage_start(cyas_hd, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR + "ERROR: Cannot start storage stack - Reason code %d\n", retVal) ; + return retVal; + } + retVal = cy_as_storage_query_media(cyas_hd, cy_as_media_sd_flash, &count, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR + "ERROR: Cannot query SD device count - Reason code %d\n", retVal) ; + return retVal; + } + if (!count) { + cy_as_hal_print_message(KERN_ERR"ERROR: SD storage media was not found\n") ; + return retVal; + } else { + cy_as_hal_print_message(KERN_ERR + "SUCCESS: %d SD device(s) found. SD_CLK, SD_CMD, and SD_D0 connected\n", + count) ; + dev_data.bus = 1 ; + dev_data.device = 0 ; + retVal = cy_as_storage_query_device(cyas_hd, &dev_data, 0, 0); + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR + "ERROR: Cannot query SD device count - Reason code %d\n", retVal) ; + return retVal; + } else { + #if 1 /* skkm */ + retVal = cy_as_storage_change_sd_frequency(cyas_hd, bus, 0x11, 24, 0, 0); + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message( + "%s: Cannot control cy_as_storage_change_sd_frequency - reason [%d]\n", __func__, retVal) ; + } + #endif + cy_as_hal_print_message(KERN_ERR"Checking for SD_WP Connectivity:\n"); + if (dev_data.desc_p.writeable) + cy_as_hal_print_message(KERN_ERR" SD media is not write protected\n") ; + else + cy_as_hal_print_message(KERN_ERR" SD media is write protected %d\n", retVal) ; + unit_data.device = 0 ; + unit_data.unit = 0 ; + unit_data.bus = bus; + retVal = cy_as_storage_query_unit(cyas_hd, &unit_data, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + #ifndef WESTBRIDGE_NDEBUG + cy_as_hal_print_message(KERN_INFO + "%s: cannot query %d device unit - reason code %d\n", + __func__, unit_data.bus, retVal) ; + #endif + return retVal; + } + } + } + cy_as_hal_set_ep_dma_mode(4, false); + cy_as_hal_set_ep_dma_mode(8, false); + start_unit = unit_data.desc_p.unit_size - MAX_DRQ_LOOPS_IN_ISR*2; + for (i = 0 ; i < CYASSTORAGE_MAX_XFER_SIZE ; i++) + expdata[i] = i; + } + break; + + case CY_AS_DIAG_SD_READ: + { + int i; + int bus = 1 ; + struct timespec mStartTime, mEndTime; + long second, nano; + long mDelta; + + mStartTime = CURRENT_TIME; + retVal = cy_as_storage_read( + cyas_hd, bus, 0, 0, start_unit, + actdata, MAX_DRQ_LOOPS_IN_ISR) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR + "ERROR: cannot read from block device - code %d\n", + retVal) ; + break; + } + + mEndTime = CURRENT_TIME; + second = mEndTime.tv_sec - mStartTime.tv_sec; + nano = mEndTime.tv_nsec - mStartTime.tv_nsec; + mDelta = (second*1000000) + nano/1000; + cy_as_hal_print_message("<1>%s: reading speed = %d KByte/s\n", + __func__, + (int)((CYASSTORAGE_MAX_XFER_SIZE*1000)/mDelta)) ; + if (memcmp(expdata, actdata, 2048) != 0) { + int errCnt = 0 ; + cy_as_hal_print_message(KERN_ERR + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n") ; + for (i = 0 ; i < 2048 ; i++) { + if (expdata[i] != actdata[i]) { + cy_as_hal_print_message(KERN_ERR "EXP[%d]: 0x%02x\n", i, expdata[i]); + cy_as_hal_print_message(KERN_ERR "ACT[%d]: 0x%02x\n", i, actdata[i]); + errCnt++ ; + if (errCnt > 10) + break; + } + } + cy_as_hal_print_message(KERN_ERR + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n") ; + retVal = CY_AS_ERROR_INVALID_RESPONSE; + break; + } else + cy_as_hal_print_message(KERN_ERR "success : storage test\n") ; + + } + break; + case CY_AS_DIAG_SD_WRITE: + { + int i; + int bus = 1 ; + struct timespec mStartTime, mEndTime; + long second, nano; + long mDelta; + for (i = 0 ; i < CYASSTORAGE_MAX_XFER_SIZE ; i++) + expdata[i] = i; + mStartTime = CURRENT_TIME; + retVal = cy_as_storage_write(cyas_hd, bus, 0, 0, start_unit, expdata, MAX_DRQ_LOOPS_IN_ISR) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR "ERROR: cannot write to block device - code %d\n", retVal) ; + break; + } + mEndTime = CURRENT_TIME; + second = mEndTime.tv_sec - mStartTime.tv_sec; + nano = mEndTime.tv_nsec - mStartTime.tv_nsec; + mDelta = (second*1000000) + nano/1000; + cy_as_hal_print_message("<1>%s: writing speed = %d KByte/s\n", + __func__, + (int)((CYASSTORAGE_MAX_XFER_SIZE*1000)/mDelta)) ; + } + break; + case CY_AS_DIAG_SD_UNMOUNT: + cy_as_hal_set_ep_dma_mode(4, true); + cy_as_hal_set_ep_dma_mode(8, true); + + /* Start the storage API and get a handle to the device we are interested in. */ + retVal = cy_as_storage_stop(cyas_hd, 0, 0) ; + if (retVal != CY_AS_ERROR_SUCCESS) { + cy_as_hal_print_message(KERN_ERR"ERROR: Cannot stop storage stack - Reason code %d\n", retVal) ; + return retVal; + } + cy_as_hal_free(actdata); + cy_as_hal_free(expdata); + cyasdevice_enter_standby(); + break; +#if 0 + case CY_AS_DIAG_CONNECT_UMS: + cyasdevice_leave_standby(); + /* cyasblkdev_blk_exit(); */ + + cyasdevice_reload_firmware(0); + /* CyAsHalSelUSBSwitch(1); */ + retVal = CyAsAPIUsbInit(); + if (retVal) { + cy_as_hal_print_message("%s: USB test failed.\n", __func__) ; + return 0; + } else { + msleep(1000); + cy_as_hal_print_message("%s: USB connected.\n", __func__) ; + } + cy_as_hal_print_message("%s: UMS MODE init done\n", __func__) ; + break; + + case CY_AS_DIAG_DISCONNECT_UMS: + + CyAsAPIUsbExit(); + /* CyAsHalSelUSBSwitch(0); */ + cy_as_hal_print_message("%s: UMS mode - close done\n", __func__) ; + + cyasdevice_reload_firmware(1); + /* cyasblkdev_blk_init(0, 0); */ + cyasdevice_enter_standby(); + cy_as_hal_print_message("%s: reload F/W - close done\n", __func__) ; + break; + case CY_AS_DIAG_CONNECT_MTP: + cyasdevice_leave_standby(); + /* CyAsHalSelUSBSwitch(1); */ + cyasblkdev_blk_init(0, 0); + retVal = cy_as_gadget_init(1); + if (retVal) + cy_as_hal_print_message("%s: cy_as_gadget_init failed.\n", __func__) ; + else + cy_as_hal_print_message("%s: cy_as_gadget_init success\n", __func__) ; + cy_as_hal_print_message("%s: Start cy_as_gadget driver - init done\n", __func__) ; + break; + case CY_AS_DIAG_DISCONNECT_MTP: + cyasblkdev_blk_exit(); + cy_as_gadget_cleanup(); + /* CyAsHalSelUSBSwitch(0); */ + cyasdevice_enter_standby(); + cy_as_hal_print_message("%s: cy_as_gadget driver - close done\n", __func__) ; + break; +#endif + case CY_AS_DIAG_TEST_RESET_LOW: + /* cy_as_hal_set_reset_pin(0); */ + cy_as_hal_print_message("%s: cy_as_hal_set_reset_pin - set LOW\n", __func__) ; + break; + + case CY_AS_DIAG_TEST_RESET_HIGH: + /* cy_as_hal_set_reset_pin(1); */ + cy_as_hal_print_message("%s: cy_as_hal_set_reset_pin - set HIGH\n", __func__) ; + break; + default: + cy_as_hal_print_message("%s: unkown mode\n", __func__) ; + break; + + } +#endif + return retVal; +} +EXPORT_SYMBOL(cy_as_diagnostics); + + +/*[]*/ |