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) ; }
/* 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: " "memory 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); spin_lock_init(&cy_as_dev->common_lock); /* done now */ cy_as_device_controller = cy_as_dev; return 0; done: if (cy_as_dev) cyasdevice_deinit(cy_as_dev); return -EINVAL; }
/* * 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 = 200 ; 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) * 100) ; } 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 ; } } printk(KERN_ERR"cyasdevice:timeout 0xA0 = 0x%x\n",cy_as_hal_read_register(dev_p->tag,0xA0)); printk(KERN_ERR"cyasdevice:timeout 0xA1 = 0x%x\n",cy_as_hal_read_register(dev_p->tag,0xA1)); printk(KERN_ERR"cyasdevice:timeout 0xA2 = 0x%x\n",cy_as_hal_read_register(dev_p->tag,0xA2)); printk(KERN_ERR"cyasdevice:timeout 0x90 = 0x%x\n",cy_as_hal_read_register(dev_p->tag,0x90)); printk(KERN_ERR"cyasdevice:timeout 0x91 = 0x%x\n",cy_as_hal_read_register(dev_p->tag,0x91)); /* * 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 ; }