From 852aaf411c5cc8ebf08fb2d8ff7562933e789a1f Mon Sep 17 00:00:00 2001 From: ddl Date: Fri, 17 Aug 2012 12:24:33 +0800 Subject: [PATCH 1/3] camera rk29: add support zoom by arm, version update to v0.x.11 --- arch/arm/mach-rk29/include/mach/rk29_camera.h | 19 + arch/arm/plat-rk/include/plat/rk_camera.h | 7 + drivers/media/video/rk29_camera_oneframe.c | 327 ++++++++++++++++-- 3 files changed, 318 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-rk29/include/mach/rk29_camera.h b/arch/arm/mach-rk29/include/mach/rk29_camera.h index 66c9f68b5b60..1e4fc5fad006 100755 --- a/arch/arm/mach-rk29/include/mach/rk29_camera.h +++ b/arch/arm/mach-rk29/include/mach/rk29_camera.h @@ -25,4 +25,23 @@ #include + +#define CONFIG_CAMERA_SCALE_CROP_MACHINE RK_CAM_SCALE_CROP_IPP + +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_ARM) + #define CAMERA_SCALE_CROP_MACHINE "arm" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_IPP) + #define CAMERA_SCALE_CROP_MACHINE "ipp" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_RGA) + #define CAMERA_SCALE_CROP_MACHINE "rga" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_PP) + #define CAMERA_SCALE_CROP_MACHINE "pp" +#endif + +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) + #define CAMERA_VIDEOBUF_ARM_ACCESS 1 +#else + #define CAMERA_VIDEOBUF_ARM_ACCESS 0 +#endif + #endif diff --git a/arch/arm/plat-rk/include/plat/rk_camera.h b/arch/arm/plat-rk/include/plat/rk_camera.h index d4659d3f4708..729f87c74149 100755 --- a/arch/arm/plat-rk/include/plat/rk_camera.h +++ b/arch/arm/plat-rk/include/plat/rk_camera.h @@ -154,6 +154,12 @@ #define RK29_CAM_FLASHACTIVE_H (0x01< #include #include - +#include static int debug; module_param(debug, int, S_IRUGO|S_IWUSR|S_IWGRP); @@ -160,8 +160,9 @@ module_param(debug, int, S_IRUGO|S_IWUSR|S_IWGRP); *v0.x.c : fix work queue havn't been finished after close device; *v0.x.d : fix error when calculate crop left-top point coordinate; *v0.x.f : fix struct rk29_camera_work may be reentrant. +*v0.x.11: add support zoom by arm; */ -#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0xf) +#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0x11) /* limit to rk29 hardware capabilities */ #define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\ @@ -238,6 +239,14 @@ struct rk29_camera_zoominfo struct v4l2_crop a; int zoom_rate; }; +#if CAMERA_VIDEOBUF_ARM_ACCESS +struct rk29_camera_vbinfo +{ + unsigned int phy_addr; + void __iomem *vir_addr; + unsigned int size; +}; +#endif struct rk29_camera_dev { struct soc_camera_host soc_host; @@ -270,8 +279,13 @@ struct rk29_camera_dev unsigned long frame_interval; unsigned int pixfmt; unsigned int vipmem_phybase; + void __iomem *vipmem_virbase; unsigned int vipmem_size; unsigned int vipmem_bsize; +#if CAMERA_VIDEOBUF_ARM_ACCESS + struct rk29_camera_vbinfo *vbinfo; + unsigned int vbinfo_count; +#endif int host_width; int host_height; int icd_width; @@ -378,6 +392,22 @@ static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, } pcdev->camera_work_count = (*count); } +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) { + kfree(pcdev->vbinfo); + pcdev->vbinfo = NULL; + pcdev->vbinfo_count = 0x00; + } + + if (pcdev->vbinfo == NULL) { + pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL); + if (pcdev->vbinfo == NULL) { + RK29CAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__); + BUG(); + } + pcdev->vbinfo_count = *count; + } +#endif } RK29CAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count); @@ -498,7 +528,8 @@ static void rk29_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk29_camera_dev *pcdev = ici->priv; - + struct rk29_camera_vbinfo *vb_info; + dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); @@ -512,6 +543,31 @@ static void rk29_videobuf_queue(struct videobuf_queue *vq, else BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */ } +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo+vb->i; + if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) { + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + vb_info->vir_addr = NULL; + vb_info->phy_addr = 0x00; + vb_info->size = 0x00; + } + + if (request_mem_region(vb->boff,vb->bsize,"rk29_camera_vb")) { + vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize); + } + + if (vb_info->vir_addr) { + vb_info->size = vb->bsize; + vb_info->phy_addr = vb->boff; + } else { + RK29CAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i); + } + } + } +#endif if (!pcdev->active) { pcdev->active = vb; rk29_videobuf_capture(vb); @@ -541,7 +597,8 @@ static int rk29_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt) rk29_pixfmt2ippfmt_err: return -1; } -static void rk29_camera_capture_process(struct work_struct *work) +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP) +static int rk29_camera_scale_crop_ipp(struct work_struct *work) { struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work); struct videobuf_buffer *vb = camera_work->vb; @@ -550,7 +607,8 @@ static void rk29_camera_capture_process(struct work_struct *work) unsigned long int flags; int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size; int scale_times,w,h,vipdata_base; - + int ret = 0; + /* *ddl@rock-chips.com: * IPP Dest image resolution is 2047x1088, so scale operation break up some times @@ -564,8 +622,6 @@ static void rk29_camera_capture_process(struct work_struct *work) memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); - down(&pcdev->zoominfo.sem); - ipp_req.timeout = 100; ipp_req.flag = IPP_ROT_0; ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times; @@ -614,21 +670,170 @@ static void rk29_camera_capture_process(struct work_struct *work) RK29CAMERA_TR("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); RK29CAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag); - goto do_ipp_err; + goto rk29_camera_scale_crop_ipp_end; } } } + +rk29_camera_scale_crop_ipp_end: + return ret; +} +#endif +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) +static int rk29_camera_scale_crop_arm(struct work_struct *work) +{ + struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk29_camera_dev *pcdev = camera_work->pcdev; + struct rk29_camera_vbinfo *vb_info; + unsigned char *psY,*pdY,*psUV,*pdUV; + unsigned char *src,*dst; + unsigned long src_phy,dst_phy; + int srcW,srcH,cropW,cropH,dstW,dstH; + long zoomindstxIntInv,zoomindstyIntInv; + long x,y; + long yCoeff00,yCoeff01,xCoeff00,xCoeff01; + long sX,sY; + long r0,r1,a,b,c,d; + int ret = 0; + - if (pcdev->icd_cb.sensor_cb) - (pcdev->icd_cb.sensor_cb)(vb); - -do_ipp_err: - up(&pcdev->zoominfo.sem); - wake_up(&(camera_work->vb->done)); - spin_lock_irqsave(&pcdev->camera_work_lock, flags); - list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); - spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); - return; + src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; + src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize); + psUV = psY + pcdev->host_width*pcdev->host_height; + srcW = pcdev->host_width; + srcH = pcdev->host_height; + cropW = pcdev->zoominfo.a.c.width; + cropH = pcdev->zoominfo.a.c.height; + psY = psY + pcdev->host_width - pcdev->zoominfo.a.c.width; + psUV = psUV + pcdev->host_width - pcdev->zoominfo.a.c.width; + + vb_info = pcdev->vbinfo+vb->i; + dst_phy = vb_info->phy_addr; + dst = pdY = (unsigned char*)vb_info->vir_addr; + pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height; + dstW = pcdev->icd->user_width; + dstH = pcdev->icd->user_height; + + zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1; + zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1; + + //y + //for(y = 0; y> 16); + + for(x = 0; x> 16); + + a = psY[sY*srcW + sX]; + b = psY[sY*srcW + sX + 1]; + c = psY[(sY+1)*srcW + sX]; + d = psY[(sY+1)*srcW + sX + 1]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdY[x] = r0; + } + pdY += dstW; + } + + dstW /= 2; + dstH /= 2; + srcW /= 2; + srcH /= 2; + + //UV + //for(y = 0; y> 16); + + for(x = 0; x> 16); + + //U + a = psUV[(sY*srcW + sX)*2]; + b = psUV[(sY*srcW + sX + 1)*2]; + c = psUV[((sY+1)*srcW + sX)*2]; + d = psUV[((sY+1)*srcW + sX + 1)*2]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdUV[x*2] = r0; + + //V + a = psUV[(sY*srcW + sX)*2 + 1]; + b = psUV[(sY*srcW + sX + 1)*2 + 1]; + c = psUV[((sY+1)*srcW + sX)*2 + 1]; + d = psUV[((sY+1)*srcW + sX + 1)*2 + 1]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdUV[x*2 + 1] = r0; + } + pdUV += dstW*2; + } + +rk29_camera_scale_crop_arm_end: + + dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize)); + outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize)); + + dmac_flush_range((void*)dst,(void*)(dst+vb_info->size)); + outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size)); + + return ret; +} +#endif + +static void rk29_camera_capture_process(struct work_struct *work) +{ + struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk29_camera_dev *pcdev = camera_work->pcdev; + //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code; + unsigned long flags = 0; + int err = 0; + + if (!CAM_WORKQUEUE_IS_EN()) + goto rk29_camera_capture_process_end; + + down(&pcdev->zoominfo.sem); + if (pcdev->icd_cb.scale_crop_cb) + err = (pcdev->icd_cb.scale_crop_cb)(work); + up(&pcdev->zoominfo.sem); + + if (pcdev->icd_cb.sensor_cb) + (pcdev->icd_cb.sensor_cb)(vb); + +rk29_camera_capture_process_end: + if (err) { + vb->state = VIDEOBUF_ERROR; + } else { + if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { + vb->state = VIDEOBUF_DONE; + vb->field_count++; + } + } + wake_up(&(camera_work->vb->done)); + spin_lock_irqsave(&pcdev->camera_work_lock, flags); + list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); + spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); + return; } static irqreturn_t rk29_camera_irq(int irq, void *data) { @@ -680,13 +885,8 @@ static irqreturn_t rk29_camera_irq(int irq, void *data) if (pcdev->active == NULL) { RK29CAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__); } - - if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { - vb->state = VIDEOBUF_DONE; - do_gettimeofday(&vb->ts); - vb->field_count++; - } - + + do_gettimeofday(&vb->ts); if (CAM_WORKQUEUE_IS_EN()) { if (!list_empty(&pcdev->camera_work_queue)) { wk = list_entry(pcdev->camera_work_queue.next, struct rk29_camera_work, queue); @@ -697,6 +897,10 @@ static irqreturn_t rk29_camera_irq(int irq, void *data) queue_work(pcdev->camera_wq, &(wk->work)); } } else { + if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { + vb->state = VIDEOBUF_DONE; + vb->field_count++; + } wake_up(&vb->done); } } @@ -713,6 +917,8 @@ static void rk29_videobuf_release(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk29_camera_dev *pcdev = ici->priv; + struct rk29_camera_vbinfo *vb_info =NULL; + #ifdef DEBUG dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -732,17 +938,26 @@ static void rk29_videobuf_release(struct videobuf_queue *vq, dev_dbg(&icd->dev, "%s (unknown)\n", __func__); break; } -#endif - if(vb->i == 0){ - flush_workqueue(pcdev->camera_wq); - } - +#endif if (vb == pcdev->active) { RK29CAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb); interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500)); - flush_workqueue(pcdev->camera_wq); RK29CAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb); } + + flush_workqueue(pcdev->camera_wq); +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo + vb->i; + + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); + } + + } +#endif rk29_videobuf_free(vq, buf); } @@ -961,7 +1176,9 @@ static void rk29_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk29_camera_dev *pcdev = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - + struct rk29_camera_vbinfo *vb_info; + unsigned int i; + mutex_lock(&camera_lock); BUG_ON(icd != pcdev->icd); @@ -982,7 +1199,22 @@ static void rk29_camera_remove_device(struct soc_camera_device *icd) pcdev->camera_work_count = 0; INIT_LIST_HEAD(&pcdev->camera_work_queue); } - +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo; + for (i=0; ivbinfo_count; i++) { + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); + } + vb_info++; + } + kfree(pcdev->vbinfo); + pcdev->vbinfo = NULL; + pcdev->vbinfo_count = 0; + } +#endif pcdev->active = NULL; pcdev->icd = NULL; pcdev->icd_cb.sensor_cb = NULL; @@ -2053,8 +2285,8 @@ static int rk29_camera_probe(struct platform_device *pdev) int irq,i; int err = 0; - RK29CAMERA_TR("RK29 Camera driver version: v%d.%d.%d\n",(RK29_CAM_VERSION_CODE&0xff0000)>>16, - (RK29_CAM_VERSION_CODE&0xff00)>>8,RK29_CAM_VERSION_CODE&0xff); + RK29CAMERA_TR("RK29 Camera driver version: v%d.%d.%d Zoom by %s\n",(RK29_CAM_VERSION_CODE&0xff0000)>>16, + (RK29_CAM_VERSION_CODE&0xff00)>>8,RK29_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); @@ -2117,11 +2349,24 @@ static int rk29_camera_probe(struct platform_device *pdev) if (pcdev->pdata && (strcmp(pcdev->pdata->meminfo.name,"camera_ipp_mem")==0)) { pcdev->vipmem_phybase = pcdev->pdata->meminfo.start; pcdev->vipmem_size = pcdev->pdata->meminfo.size; + + if (!request_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size,"rk29_vipmem")) { + err = -EBUSY; + goto exit_ioremap_vipmem; + } + pcdev->vipmem_virbase = ioremap_cached(pcdev->vipmem_phybase,pcdev->vipmem_size); + if (pcdev->vipmem_virbase == NULL) { + dev_err(pcdev->dev, "ioremap() of vip internal memory(Ex:IPP process/raw process) failed\n"); + err = -ENXIO; + goto exit_ioremap_vipmem; + } + RK29CAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); } else { RK29CAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__); pcdev->vipmem_phybase = 0; pcdev->vipmem_size = 0; + pcdev->vipmem_virbase = 0; } #endif INIT_LIST_HEAD(&pcdev->capture); @@ -2183,6 +2428,11 @@ static int rk29_camera_probe(struct platform_device *pdev) pcdev->fps_timer.function = rk29_camera_fps_func; pcdev->icd_cb.sensor_cb = NULL; +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP) + pcdev->icd_cb.scale_crop_cb = rk29_camera_scale_crop_ipp; +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) + pcdev->icd_cb.scale_crop_cb = rk29_camera_scale_crop_arm; +#endif RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__); return 0; @@ -2207,6 +2457,10 @@ exit_reqirq: iounmap(pcdev->base); exit_ioremap: release_mem_region(res->start, res->end - res->start + 1); +exit_ioremap_vipmem: + if (pcdev->vipmem_virbase) + iounmap(pcdev->vipmem_virbase); + release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size); exit_reqmem: if (pcdev->aclk_ddr_lcdc) { clk_put(pcdev->aclk_ddr_lcdc); @@ -2277,6 +2531,9 @@ static int __devexit rk29_camera_remove(struct platform_device *pdev) soc_camera_host_unregister(&pcdev->soc_host); + iounmap((void __iomem*)pcdev->vipmem_phybase); + release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size); + res = pcdev->res; release_mem_region(res->start, res->end - res->start + 1); From 3fd8816a56e3ed45b8eb6799acd7cb2c49da29b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=99=B4?= Date: Fri, 17 Aug 2012 14:30:45 +0800 Subject: [PATCH 2/3] rk30:sdk:support wm8326 early suspend and modify dcdc or ldo mode when in early suspend --- arch/arm/mach-rk30/board-rk30-sdk-wm8326.c | 133 ++++++++++++++++++--- drivers/mfd/wm831x-core.c | 17 ++- drivers/regulator/wm831x-ldo.c | 2 +- 3 files changed, 135 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-rk30/board-rk30-sdk-wm8326.c b/arch/arm/mach-rk30/board-rk30-sdk-wm8326.c index fbba1ea0aeb3..ac7108154434 100755 --- a/arch/arm/mach-rk30/board-rk30-sdk-wm8326.c +++ b/arch/arm/mach-rk30/board-rk30-sdk-wm8326.c @@ -5,6 +5,7 @@ #include #include +#include #define cru_readl(offset) readl_relaxed(RK30_CRU_BASE + offset) #define cru_writel(v, offset) do { writel_relaxed(v, RK30_CRU_BASE + offset); dsb(); } while (0) @@ -498,7 +499,8 @@ struct regulator_init_data wm831x_regulator_init_dcdc[WM831X_MAX_DCDC] = { .min_uV = 600000, .max_uV = 1800000, //0.6-1.8V .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST | REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(dcdc1_consumers), .consumer_supplies = dcdc1_consumers, @@ -509,7 +511,8 @@ struct regulator_init_data wm831x_regulator_init_dcdc[WM831X_MAX_DCDC] = { .min_uV = 600000, .max_uV = 1800000, //0.6-1.8V .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST | REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(dcdc2_consumers), .consumer_supplies = dcdc2_consumers, @@ -520,7 +523,8 @@ struct regulator_init_data wm831x_regulator_init_dcdc[WM831X_MAX_DCDC] = { .min_uV = 850000, .max_uV = 3400000, //0.85-3.4V .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST | REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(dcdc3_consumers), .consumer_supplies = dcdc3_consumers, @@ -531,7 +535,8 @@ struct regulator_init_data wm831x_regulator_init_dcdc[WM831X_MAX_DCDC] = { .min_uV = 850000, .max_uV = 3400000, //0.85-3.4V .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_STANDBY | REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST | REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(dcdc4_consumers), .consumer_supplies = dcdc4_consumers, @@ -572,7 +577,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo1_consumers), .consumer_supplies = ldo1_consumers, @@ -583,7 +589,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo2_consumers), .consumer_supplies = ldo2_consumers, @@ -594,7 +601,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo3_consumers), .consumer_supplies = ldo3_consumers, @@ -605,7 +613,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo4_consumers), .consumer_supplies = ldo4_consumers, @@ -616,7 +625,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo5_consumers), .consumer_supplies = ldo5_consumers, @@ -627,7 +637,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 900000, .max_uV = 3300000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo6_consumers), .consumer_supplies = ldo6_consumers, @@ -638,7 +649,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 1000000, .max_uV = 3500000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo7_consumers), .consumer_supplies = ldo7_consumers, @@ -649,7 +661,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 1000000, .max_uV = 3500000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo8_consumers), .consumer_supplies = ldo8_consumers, @@ -660,7 +673,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 1000000, .max_uV = 3500000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo9_consumers), .consumer_supplies = ldo9_consumers, @@ -671,7 +685,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 1000000, .max_uV = 3500000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo10_consumers), .consumer_supplies = ldo10_consumers, @@ -682,7 +697,8 @@ struct regulator_init_data wm831x_regulator_init_ldo[WM831X_MAX_LDO] = { .min_uV = 800000, .max_uV = 1550000, .apply_uV = true, - .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_IDLE | REGULATOR_MODE_NORMAL, }, .num_consumer_supplies = ARRAY_SIZE(ldo11_consumers), .consumer_supplies = ldo11_consumers, @@ -777,6 +793,93 @@ out: return 0; } +#ifdef CONFIG_HAS_EARLYSUSPEND +void wm831x_pmu_early_suspend(struct regulator_dev *rdev) +{ + struct regulator *dcdc; + struct regulator *ldo; + printk("%s\n", __func__); + + dcdc = regulator_get(NULL, "dcdc4"); //vcc_io + regulator_set_voltage(dcdc, 2800000, 2800000); + regulator_set_mode(dcdc, REGULATOR_MODE_STANDBY); + regulator_enable(dcdc); + printk("%s set dcdc4 vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc)); + regulator_put(dcdc); + udelay(100); + + ldo = regulator_get(NULL, "ldo1"); // + regulator_set_mode(ldo, REGULATOR_MODE_IDLE); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo4"); + regulator_set_mode(ldo, REGULATOR_MODE_IDLE); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo6"); + regulator_set_mode(ldo, REGULATOR_MODE_IDLE); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo8"); + regulator_set_mode(ldo, REGULATOR_MODE_IDLE); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + +} +void wm831x_pmu_early_resume(struct regulator_dev *rdev) +{ + struct regulator *dcdc; + struct regulator *ldo; + printk("%s\n", __func__); + + dcdc = regulator_get(NULL, "dcdc4"); //vcc_io + regulator_set_voltage(dcdc, 3000000, 3000000); + regulator_set_mode(dcdc, REGULATOR_MODE_FAST); + regulator_enable(dcdc); + printk("%s set dcdc4 vcc_io=%dmV end\n", __func__, regulator_get_voltage(dcdc)); + regulator_put(dcdc); + udelay(100); + + ldo = regulator_get(NULL, "ldo1"); // + regulator_set_mode(ldo, REGULATOR_MODE_NORMAL); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo4"); + regulator_set_mode(ldo, REGULATOR_MODE_NORMAL); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo6"); + regulator_set_mode(ldo, REGULATOR_MODE_NORMAL); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); + + ldo = regulator_get(NULL, "ldo8"); + regulator_set_mode(ldo, REGULATOR_MODE_NORMAL); + regulator_enable(ldo); + regulator_put(ldo); + udelay(100); +} +#else +void wm831x_pmu_early_suspend(struct regulator_dev *rdev) +{ +} +void wm831x_pmu_early_resume(struct regulator_dev *rdev) +{ +} +#endif + void __sramfunc board_pmu_wm8326_suspend(void) { cru_writel(CRU_CLKGATE5_GRFCLK_ON,CRU_CLKGATE5_CON_ADDR); //open grf clk diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 504314e87de1..6ff1849eba14 100755 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -29,6 +29,11 @@ #include #include +#include + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend wm831x_early_suspend; +#endif /* Current settings - values are 2*2^(reg_val/4) microamps. These are * exported since they are used by multiple drivers. @@ -1465,6 +1470,10 @@ static struct mfd_cell backlight_devs[] = { /* * Instantiate the generic non-control parts of the device. */ + +__weak void wm831x_pmu_early_suspend(struct regulator_dev *rdev) {} +__weak void wm831x_pmu_early_resume(struct regulator_dev *rdev) {} + int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) { struct wm831x_pdata *pdata = wm831x->dev->platform_data; @@ -1729,7 +1738,13 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) goto err_irq; } } - + #ifdef CONFIG_HAS_EARLYSUSPEND + wm831x_early_suspend.level = 0xffff; + wm831x_early_suspend.suspend = wm831x_pmu_early_suspend; + wm831x_early_suspend.resume = wm831x_pmu_early_resume; + register_early_suspend(&wm831x_early_suspend); + #endif + return 0; err_irq: diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index a5fc30d8b3ca..aff55c8e08b0 100755 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -206,7 +206,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; int ret; - printk("%s base=%x,mode=%x\n", __FUNCTION__,ldo->base,mode); +// printk("%s base=%x,mode=%x\n", __FUNCTION__,ldo->base,mode); switch (mode) { case REGULATOR_MODE_NORMAL: ret = wm831x_set_bits(wm831x, on_reg, From 92fcf2abad9b3d48d5f0aadc429cf6194305a5dc Mon Sep 17 00:00:00 2001 From: yangkai Date: Fri, 17 Aug 2012 16:20:17 +0800 Subject: [PATCH 3/3] merge rk2928 usb --- drivers/usb/dwc_otg/dwc_otg_cil.c | 10 ++ drivers/usb/dwc_otg/dwc_otg_driver.c | 99 +++++++++++++-- drivers/usb/dwc_otg/dwc_otg_hcd.c | 56 ++++++++- drivers/usb/dwc_otg/dwc_otg_pcd.c | 147 ++++++++++++++++++++++- drivers/usb/dwc_otg/linux/dwc_otg_plat.h | 9 ++ 5 files changed, 303 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.c b/drivers/usb/dwc_otg/dwc_otg_cil.c index 9f44adc2796f..406aad103928 100755 --- a/drivers/usb/dwc_otg/dwc_otg_cil.c +++ b/drivers/usb/dwc_otg/dwc_otg_cil.c @@ -731,6 +731,16 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t *_core_if) dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo +#endif +#ifdef CONFIG_ARCH_RK2928 //@lyz the same with RK30 + /* Configure data FIFO sizes, RK30 otg has 0x3cc dwords total */ + dwc_write_reg32( &global_regs->grxfsiz, 0x00000120 ); + dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100120 ); //ep0 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000130 ); //ep1 tx fifo 256*4Byte + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00800230 ); //ep3 tx fifo 128*4Byte + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo 128*4Byte + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo 128*4Byte + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo 16*4Byte #endif if(_core_if->en_multiple_tx_fifo && _core_if->dma_enable) { diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c index 5efdecdd4705..e7bdd6d2d970 100755 --- a/drivers/usb/dwc_otg/dwc_otg_driver.c +++ b/drivers/usb/dwc_otg/dwc_otg_driver.c @@ -1203,6 +1203,9 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_RK30 unsigned int * otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON2); #endif +#ifdef CONFIG_ARCH_RK2928 + unsigned int * otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON5); +#endif #ifdef CONFIG_ARCH_RK29 regval = * otg_phy_con1; @@ -1291,6 +1294,35 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) clk_disable(phyclk); clk_disable(ahbclk); #endif +#endif +//need to be checked @wlf +#ifdef CONFIG_ARCH_RK2928 +#ifndef CONFIG_USB20_HOST + otg_phy_con = (unsigned int*)(USBGRF_UOC1_CON5); + /* + * disable usb host 2.0 phy if not support + */ + phyclk = clk_get(NULL, "otgphy1"); + if (IS_ERR(phyclk)) { + retval = PTR_ERR(phyclk); + DWC_ERROR("can't get USBPHY1 clock\n"); + goto fail; + } + clk_enable(phyclk); + + ahbclk = clk_get(NULL, "hclk_otg1"); + if (IS_ERR(ahbclk)) { + retval = PTR_ERR(ahbclk); + DWC_ERROR("can't get USBOTG1 ahb bus clock\n"); + goto fail; + } + clk_enable(ahbclk); + + *otg_phy_con = ((0x01<<0)|(0x00<<1)|(0x05<<4))|(((0x01<<0)|(0x01<<1)|(0x07<<4))<<16); // enter suspend. + udelay(3); + clk_disable(phyclk); + clk_disable(ahbclk); +#endif #endif dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL); @@ -1385,6 +1417,42 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) dwc_otg_device->phyclk = phyclk; dwc_otg_device->ahbclk = ahbclk; #endif +//need to be checked @wlf +#if 0//def CONFIG_ARCH_RK2928 + otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON5); + cru_set_soft_reset(SOFT_RST_USBPHY0, true); + cru_set_soft_reset(SOFT_RST_OTGC0, true); + cru_set_soft_reset(SOFT_RST_USBOTG0, true); + udelay(1); + + cru_set_soft_reset(SOFT_RST_USBOTG0, false); + cru_set_soft_reset(SOFT_RST_OTGC0, false); + cru_set_soft_reset(SOFT_RST_USBPHY0, false); + + phyclk = clk_get(NULL, "otgphy0"); + if (IS_ERR(phyclk)) { + retval = PTR_ERR(phyclk); + DWC_ERROR("can't get USBPHY0 clock\n"); + goto fail; + } + clk_enable(phyclk); + + ahbclk = clk_get(NULL, "hclk_otg0"); + if (IS_ERR(ahbclk)) { + retval = PTR_ERR(ahbclk); + DWC_ERROR("can't get USB otg0 ahb bus clock\n"); + goto fail; + } + clk_enable(ahbclk); + + /* + * Enable usb phy 0 + */ + *otg_phy_con = (0x01<<16); + + dwc_otg_device->phyclk = phyclk; + dwc_otg_device->ahbclk = ahbclk; +#endif /* * Map the DWC_otg Core memory into virtual address space. */ @@ -1519,6 +1587,9 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) #endif #ifdef CONFIG_ARCH_RK30 USB_IOMUX_INIT(GPIO0A5_OTGDRVVBUS_NAME, GPIO0A_OTG_DRV_VBUS); +#endif +#ifdef CONFIG_ARCH_RK2928 + USB_IOMUX_INIT(GPIO3C1_OTG_DRVVBUS_NAME, GPIO3C_OTG_DRVVBUS); #endif /* * Initialize the HCD @@ -2057,7 +2128,10 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2); *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. #endif - +#ifdef CONFIG_ARCH_RK2928 + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON5); + *otg_phy_con1 = (0x01<<16); // exit suspend. +#endif #if 0 *otg_phy_con1 |= (0x01<<2); *otg_phy_con1 |= (0x01<<3); // exit suspend. @@ -2084,6 +2158,9 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_RK30 *(unsigned int*)(USBGRF_UOC1_CON2+4) = ((1<<5)|((1<<5)<<16)); #endif +#ifdef CONFIG_ARCH_RK2928 + *(unsigned int*)(USBGRF_UOC1_CON5-4) = ((1<<5)|((1<<5)<<16)); +#endif if (dwc_otg_device == 0) { dev_err(dev, "kmalloc of dwc_otg_device failed\n"); @@ -2108,6 +2185,9 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_RK30 ahbclk = clk_get(NULL, "hclk_otg1"); #endif +#ifdef CONFIG_ARCH_RK2928 + ahbclk = clk_get(NULL, "hclk_otg1"); //need to be checked @wlf +#endif if (IS_ERR(ahbclk)) { retval = PTR_ERR(ahbclk); DWC_ERROR("can't get USBOTG1 ahb bus clock\n"); @@ -2213,15 +2293,6 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) #endif #ifdef CONFIG_ARCH_RK30 USB_IOMUX_INIT(GPIO0A6_HOSTDRVVBUS_NAME, GPIO0A_HOST_DRV_VBUS); -#ifdef CONFIG_MACH_RK30_DS1001B - USB_IOMUX_INIT(GPIO0A5_OTGDRVVBUS_NAME, GPIO0A_GPIO0A5); - if(gpio_request(RK30_PIN0_PA5,"host_drv")<0){ - DWC_ERROR("request of host power control failed\n"); - gpio_free(RK30_PIN0_PA5); - } - gpio_direction_output(RK30_PIN0_PA5, GPIO_HIGH); - gpio_set_value(RK30_PIN0_PA5, GPIO_HIGH); -#endif #endif /* * Initialize the DWC_otg core. @@ -2246,9 +2317,15 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) #ifndef CONFIG_USB20_HOST_EN clk_disable(phyclk); clk_disable(ahbclk); +#if defined(CONFIG_ARCH_RK29) otgreg &= ~(0x01<<14); // suspend. - otgreg |= (0x01<<13); // software control + otgreg |= (0x01<<13); // software control enable *otg_phy_con1 = otgreg; +#elif defined(CONFIG_ARCH_RK30) + *otg_phy_con1 = ((0x01<<2)|(0x00<<3)|(0x05<<6))|(((0x01<<2)|(0x01<<3)|(0x07<<6))<<16); // enter suspend. +#elif defined(CONFIG_ARCH_RK2928) + *otg_phy_con1 = ((0x01<<0)|(0x00<<1)|(0x05<<4))|(((0x01<<0)|(0x01<<1)|(0x07<<4))<<16); // enter suspend. +#endif #endif return 0; diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.c b/drivers/usb/dwc_otg/dwc_otg_hcd.c index bef6e0db01d9..b2fb7519f5b6 100755 --- a/drivers/usb/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/dwc_otg/dwc_otg_hcd.c @@ -69,8 +69,10 @@ static int dwc_otg_hcd_suspend(struct usb_hcd *hcd) return 0; } hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); +#ifdef CONFIG_USB_SUSPEND if((!dwc_otg_hcd->host_enabled)||(!hprt0.b.prtena)) return 0; +#endif DWC_PRINT("%s suspend, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32); if(hprt0.b.prtconnsts) // usb device connected { @@ -128,8 +130,10 @@ static int dwc_otg_hcd_resume(struct usb_hcd *hcd) DWC_PRINT("%s, usb device mode\n", __func__); return 0; } +#ifdef CONFIG_USB_SUSPEND if(!dwc_otg_hcd->host_enabled) return 0; +#endif #ifndef CONFIG_DWC_REMOTE_WAKEUP clk_enable(core_if->otg_dev->phyclk); clk_enable(core_if->otg_dev->ahbclk); @@ -149,8 +153,10 @@ static int dwc_otg_hcd_resume(struct usb_hcd *hcd) dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32); hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); +#ifdef CONFIG_USB_SUSPEND if(!hprt0.b.prtena) return 0; +#endif DWC_PRINT("%s resume, HPRT0:0x%x\n",hcd->self.bus_name,hprt0.d32); if(hprt0.b.prtconnsts) { @@ -617,6 +623,24 @@ static int32_t dwc_otg_phy_suspend_cb( void *_p, int suspend) udelay(3); DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); } +#endif +#if 0//def CONFIG_ARCH_RK2928 + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5); + if(exitsuspend && (pcd->phy_suspend == 1)) { + clk_enable(pcd->otg_dev->ahbclk); + clk_enable(pcd->otg_dev->phyclk); + pcd->phy_suspend = 0; + *otg_phy_con1 = (0x01<<16); // exit suspend. + DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n"); + } + if( !exitsuspend && (pcd->phy_suspend == 0)) { + pcd->phy_suspend = 1; + *otg_phy_con1 = 0x55 |(0x7f<<16); // enter suspend. + udelay(3); + clk_disable(pcd->otg_dev->phyclk); + clk_disable(pcd->otg_dev->ahbclk); + DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); + } #endif return suspend; } @@ -663,7 +687,7 @@ static struct tasklet_struct reset_tasklet = { .func = reset_tasklet_func, .data = 0, }; -#ifdef CONFIG_ARCH_RK30 +#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928) static void dwc_otg_hcd_enable(struct work_struct *work) { dwc_otg_hcd_t *dwc_otg_hcd; @@ -721,7 +745,11 @@ static void dwc_otg_hcd_connect_detect(unsigned long pdata) local_irq_save(flags); // DWC_PRINT("%s hprt %x, grfstatus 0x%x\n", __func__, dwc_read_reg32(core_if->host_if->hprt0), usbgrf_status& (7<<22)); +#ifdef CONFIG_ARCH_RK30 if(usbgrf_status & (7<<22)){ +#else //CONFIG_ARCH_RK2928 + if(usbgrf_status & (7<<12)){ +#endif // usb device connected dwc_otg_hcd->host_setenable = 1; } @@ -732,7 +760,11 @@ static void dwc_otg_hcd_connect_detect(unsigned long pdata) } if(dwc_otg_hcd->host_setenable != dwc_otg_hcd->host_enabled){ - DWC_PRINT("%s schedule delaywork \n", __func__, dwc_read_reg32(core_if->host_if->hprt0), usbgrf_status& (7<<22)); +#ifdef CONFIG_ARCH_RK30 + DWC_PRINT("%s schedule delaywork 0x%x, 0x%x\n", __func__, dwc_read_reg32(core_if->host_if->hprt0), usbgrf_status& (7<<22)); +#else //CONFIG_ARCH_RK2928 + DWC_PRINT("%s schedule delaywork \n", __func__, dwc_read_reg32(core_if->host_if->hprt0), usbgrf_status& (7<<12)); +#endif schedule_delayed_work(&dwc_otg_hcd->host_enable_work, 8); } // dwc_otg_hcd->connect_detect_timer.expires = jiffies + (HZ<<1); /* 1 s */ @@ -1116,6 +1148,24 @@ static int32_t host20_phy_suspend_cb( void *_p, int suspend) udelay(3); DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); } +#endif +#if 0//def CONFIG_ARCH_RK2928 + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5); + if(exitsuspend && (pcd->phy_suspend == 1)) { + clk_enable(pcd->otg_dev->ahbclk); + clk_enable(pcd->otg_dev->phyclk); + pcd->phy_suspend = 0; + *otg_phy_con1 = (0x01<<16); // exit suspend. + DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n"); + } + if( !exitsuspend && (pcd->phy_suspend == 0)) { + pcd->phy_suspend = 1; + *otg_phy_con1 = 0x55 |(0x7f<<16); // enter suspend. + udelay(3); + clk_disable(pcd->otg_dev->phyclk); + clk_disable(pcd->otg_dev->ahbclk); + DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); + } #endif return suspend; } @@ -1266,7 +1316,7 @@ int __devinit host20_hcd_init(struct device *dev) goto error3; } -#ifdef CONFIG_ARCH_RK30 +#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928) dwc_otg_hcd->host_setenable = 1; dwc_otg_hcd->connect_detect_timer.function = dwc_otg_hcd_connect_detect; dwc_otg_hcd->connect_detect_timer.data = (unsigned long)(dwc_otg_hcd); diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd.c b/drivers/usb/dwc_otg/dwc_otg_pcd.c index 6f6d975e09c6..81456fd70dbd 100755 --- a/drivers/usb/dwc_otg/dwc_otg_pcd.c +++ b/drivers/usb/dwc_otg/dwc_otg_pcd.c @@ -189,7 +189,7 @@ void request_nuke( dwc_otg_pcd_ep_t *_ep ) * This function assigns periodic Tx FIFO to an periodic EP * in shared Tx FIFO mode */ - #ifdef CONFIG_ARCH_RK30 + #if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK2928) //@lyz static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t *core_if) { uint32_t PerTxMsk = 1; @@ -218,7 +218,7 @@ static void release_perio_tx_fifo(dwc_otg_core_if_t *core_if, uint32_t fifo_num) * This function assigns periodic Tx FIFO to an periodic EP * in Dedicated FIFOs mode */ -#ifdef CONFIG_ARCH_RK30 +#if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK2928) //@lyz static uint32_t assign_tx_fifo(dwc_otg_core_if_t *core_if) { uint32_t TxMsk = 1; @@ -304,7 +304,7 @@ static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep, if(ep->dwc_ep.is_in) { -#ifndef CONFIG_ARCH_RK29 +#if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK2928) //@lyz if(!pcd->otg_dev->core_if->en_multiple_tx_fifo) { ep->dwc_ep.tx_fifo_num = 0; @@ -1497,6 +1497,10 @@ void dwc_otg_pcd_reinit(dwc_otg_pcd_t *_pcd) * EP8&EP9 of rk30 are IN&OUT ep, we use ep8 as OUT EP default */ #ifdef CONFIG_ARCH_RK30 + if(i == 8) + continue; + #endif + #ifdef CONFIG_ARCH_RK2928 //@lyz the same with rk30 if(i == 8) continue; #endif @@ -1558,6 +1562,10 @@ void dwc_otg_pcd_reinit(dwc_otg_pcd_t *_pcd) * EP8&EP9 of rk30 are IN&OUT ep, we use ep9 as IN EP default */ #ifdef CONFIG_ARCH_RK30 + if(i == 9) + continue; + #endif + #ifdef CONFIG_ARCH_RK2928 //@lyz the same with rk30 if(i == 9) continue; #endif @@ -1663,7 +1671,25 @@ int dwc_otg20phy_suspend( int exitsuspend ) DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); } #endif - +#ifdef CONFIG_ARCH_RK2928 + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5); + if(exitsuspend && (pcd->phy_suspend == 1)) { + clk_enable(pcd->otg_dev->ahbclk); + clk_enable(pcd->otg_dev->phyclk); + pcd->phy_suspend = 0; + *otg_phy_con1 = (0x01<<16); // exit suspend. + DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n"); + } + if( !exitsuspend && (pcd->phy_suspend == 0)) { + pcd->phy_suspend = 1; + *otg_phy_con1 = 0x55 |(0x7f<<16); // enter suspend. + // *otg_phy_con1 = 0x1D5 |(0x1ff<<16); // enter suspend. enable dm,dp debug_wlf @2012.8.10 + udelay(3); + clk_disable(pcd->otg_dev->phyclk); + clk_disable(pcd->otg_dev->ahbclk); + DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); + } +#endif return pcd->phy_suspend; } @@ -1873,6 +1899,69 @@ connect: return; } +#endif +#ifdef CONFIG_ARCH_RK2928 +static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata ) +{ + dwc_otg_pcd_t * _pcd = (dwc_otg_pcd_t *)pdata; + unsigned long flags; + unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);//@lyz USBGRF_SOC_STATUS0结构有变 + + local_irq_save(flags); + _pcd->check_vbus_timer.expires = jiffies + (HZ); /* 1 s */ + if((usbgrf_status &(1<<10)) == 0){ // id low //@lyz SOC_STATUS0[10] represents id_dig + + if( _pcd->phy_suspend) + dwc_otg20phy_suspend( 1 ); + } + else if(usbgrf_status & (1<<7)){ //@lyz SOC_STATUS0[7] represents bvalid + /* if usb not connect before ,then start connect */ + if( _pcd->vbus_status == 0 ) { + DWC_PRINT("********vbus detect*********************************************\n"); + dwc_otg_msc_lock(_pcd); + _pcd->vbus_status = 1; + if(_pcd->conn_en) + goto connect; + else + dwc_otg20phy_suspend( 0 ); + } + else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3)){ + DWC_PRINT("********soft reconnect******************************************\n"); + goto connect; + } + else if(_pcd->conn_status ==3){ + //*连接不上时释放锁,允许系统进入二级睡眠,yk@rk,20100331*// + dwc_otg_msc_unlock(_pcd); + _pcd->conn_status++; + if((dwc_read_reg32((uint32_t*)((uint8_t *)_pcd->otg_dev->base + DWC_OTG_HOST_PORT_REGS_OFFSET))&0xc00) == 0xc00) + _pcd->vbus_status = 2; + } + }else { + _pcd->vbus_status = 0; + if(_pcd->conn_status) + { + _pcd->conn_status = 0; + dwc_otg_msc_unlock(_pcd); + } + /* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */ + if( _pcd->phy_suspend == 0 ) + /* no vbus detect here , close usb phy */ + dwc_otg20phy_suspend( 0 ); + } + add_timer(&_pcd->check_vbus_timer); + local_irq_restore(flags); + return; + +connect: + if( _pcd->phy_suspend == 1 ) + dwc_otg20phy_suspend( 1 ); + schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */ + _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */ + add_timer(&_pcd->check_vbus_timer); + local_irq_restore(flags); + return; +} + #endif #ifdef CONFIG_ARCH_RK29 /* @@ -1980,6 +2069,56 @@ out: return bus_status; } +EXPORT_SYMBOL(dwc_otg_check_dpdm); +#endif +#ifdef CONFIG_ARCH_RK2928 +int dwc_otg_check_dpdm(void) +{ + static uint8_t * reg_base = 0; + volatile unsigned int * otg_dctl; + volatile unsigned int * otg_gotgctl; + volatile unsigned int * otg_hprt0; + int bus_status = 0; + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5);//@lyz modify UOC0_CON2 to CON5 + + // softreset & clockgate //@lyz modify RK2928_CRU_BASE + *(unsigned int*)(RK2928_CRU_BASE+0x120) = ((7<<5)<<16)|(7<<5); // otg0 phy clkgate + udelay(3); + *(unsigned int*)(RK2928_CRU_BASE+0x120) = ((7<<5)<<16)|(0<<5); // otg0 phy clkgate + dsb(); + *(unsigned int*)(RK2928_CRU_BASE+0xd4) = ((1<<5)<<16); // otg0 phy clkgate + *(unsigned int*)(RK2928_CRU_BASE+0xe4) = ((1<<13)<<16); // otg0 hclk clkgate + *(unsigned int*)(RK2928_CRU_BASE+0xf4) = ((3<<10)<<16); // hclk usb clkgate//@lyz to be check + + // exit phy suspend + *otg_phy_con1 = ((0x01<<0)<<16); // exit suspend.@lyz + + // soft connect + if(reg_base == 0){ + reg_base = ioremap(RK2928_USBOTG20_PHYS,USBOTG_SIZE);//@lyz + if(!reg_base){ + bus_status = -1; + goto out; + } + } + mdelay(105); + printk("regbase %p 0x%x, otg_phy_con%p, 0x%x\n", + reg_base, *(reg_base), otg_phy_con1, *otg_phy_con1); + otg_dctl = (unsigned int * )(reg_base+0x804); + otg_gotgctl = (unsigned int * )(reg_base); + otg_hprt0 = (unsigned int * )(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); + if(*otg_gotgctl &(1<<19)){ + bus_status = 1; + *otg_dctl &= ~(0x01<<1);//@lyz exit soft-disconnect mode + mdelay(50); // delay about 10ms + // check dp,dm + if((*otg_hprt0 & 0xc00)==0xc00)//@lyz check hprt[11:10] + bus_status = 2; + } +out: + return bus_status; +} + EXPORT_SYMBOL(dwc_otg_check_dpdm); #endif void dwc_otg_pcd_start_vbus_timer( dwc_otg_pcd_t * _pcd ) diff --git a/drivers/usb/dwc_otg/linux/dwc_otg_plat.h b/drivers/usb/dwc_otg/linux/dwc_otg_plat.h index e3f7d6e99640..1fa1f5c886a6 100755 --- a/drivers/usb/dwc_otg/linux/dwc_otg_plat.h +++ b/drivers/usb/dwc_otg/linux/dwc_otg_plat.h @@ -67,6 +67,15 @@ #define USB_IOMUX_INIT(a,b) rk30_mux_api_set(a,b) #endif +#ifdef CONFIG_ARCH_RK2928 +#include +#define GRF_REG_BASE RK2928_GRF_BASE +#define USBOTG_SIZE RK2928_USBOTG20_SIZE +#define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0x14c) +#define USBGRF_UOC0_CON5 (GRF_REG_BASE+0x17c) +#define USBGRF_UOC1_CON5 (GRF_REG_BASE+0x194) +#define USB_IOMUX_INIT(a,b) rk30_mux_api_set(a,b) +#endif /** * @file *