📄 iic.c
字号:
return; }void ci_set_fifo(unsigned int timeout, CI_FIFO_THRESHOLD threshold, int fifo1_enable, int fifo2_enable){ unsigned int value; // write citor CITOR = timeout; // write cifr: always enable fifo 0! also reset input fifo value = CIFR; value &= ~(CI_CIFR_FEN0 | CI_CIFR_FEN1 | CI_CIFR_FEN2 | CI_CIFR_RESETF | CI_CIFR_THL_0_SMASK<<CI_CIFR_THL_0_SHIFT); value |= (unsigned int)threshold << CI_CIFR_THL_0_SHIFT; value |= (fifo1_enable) ? CI_CIFR_FEN1 : 0; value |= (fifo2_enable) ? CI_CIFR_FEN2 : 0; value |= CI_CIFR_RESETF | CI_CIFR_FEN0; CIFR = value; return; }void ci_reset_fifo(){ unsigned int value; value = CIFR; value |= CI_CIFR_RESETF; CIFR = value;}void ci_set_int_mask(unsigned int mask){ unsigned int value; // write mask in cicr0 value = CICR0; value &= ~CI_CICR0_INTERRUPT_MASK; value |= (mask & CI_CICR0_INTERRUPT_MASK); CICR0 = value; return; }unsigned int ci_get_int_mask(){ unsigned int value; // write mask in cicr0 value = CICR0; return (value & CI_CICR0_INTERRUPT_MASK);}void ci_clear_int_status(unsigned int status){ // write 1 to clear CISR = status;}unsigned int ci_get_int_status(){ int value; value = CISR; return value;}void ci_set_reg_value(unsigned int reg_offset, unsigned int value){ CI_REG((u32)(ci_regs_base) + reg_offset) = value;}int ci_get_reg_value(unsigned int reg_offset){ int value; value = CI_REG((u32)(ci_regs_base) + reg_offset); return value;}//-------------------------------------------------------------------------------------------------------// Control APIs//-------------------------------------------------------------------------------------------------------int ci_init(){ // clear all CI registers CICR0 = 0x3FF; // disable all interrupts CICR1 = 0; CICR2 = 0; CICR3 = 0; CICR4 = 0; CISR = ~0; CIFR = 0; CITOR = 0; // enable CI clock CKEN |= CKEN24_CAMERA; return 0;}void ci_deinit(){ // disable CI clock CKEN &= ~CKEN24_CAMERA;}void ci_enable(int dma_en){ unsigned int value; // write mask in cicr0 value = CICR0; value |= CI_CICR0_ENB; if (dma_en) { value |= CI_CICR0_DMA_EN; } CICR0 = value; udelay(100); GPSR0 |= 0x00000800; udelay(100); return; }int ci_disable(int quick){ volatile unsigned int value, mask; int retry; // write control bit in cicr0 value = CICR0; if (quick) { value &= ~CI_CICR0_ENB; mask = CI_CISR_CQD; } else { value |= CI_CICR0_DIS; mask = CI_CISR_CDD; } CICR0 = value; // wait shutdown complete retry = 50; while ( retry-- > 0 ) { value = CISR; if ( value & mask ) { CISR = mask; return 0; } mdelay(10); } return -1; }void ci_slave_capture_enable(){ unsigned int value; // write mask in cicr0 value = CICR0; value |= CI_CICR0_SL_CAP_EN; CICR0 = value; return; }void ci_slave_capture_disable(){ unsigned int value; // write mask in cicr0 value = CICR0; value &= ~CI_CICR0_SL_CAP_EN; CICR0 = value; return; }void pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs){ int dcsr; static int dma_repeated = 0; camera_context_t *cam_ctx = g_camera_context; dcsr = DCSR(channel); DCSR(channel) = dcsr & ~DCSR_STOPIRQEN; if (still_image_mode == 1) { if (task_waiting == 1) { wake_up_interruptible (&camera_wait_q); task_waiting = 0; } else { still_image_rdy = 1; } } else if (dma_repeated == 0 && (cam_ctx->block_tail == ((cam_ctx->block_header + 2) % cam_ctx->block_number))) { dma_repeated = 1; pxa_dma_repeat(cam_ctx); cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number; } else if (dma_repeated == 1 && (cam_ctx->block_tail != ((cam_ctx->block_header + 1) % cam_ctx->block_number)) && (cam_ctx->block_tail != ((cam_ctx->block_header + 2) % cam_ctx->block_number))) { pxa_dma_continue(cam_ctx); dma_repeated = 0; } else if (dma_repeated == 0) { cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number; } if (task_waiting == 1 && !(cam_ctx->block_header == cam_ctx->block_tail)) { wake_up_interruptible (&camera_wait_q); task_waiting = 0; }}void pxa_ci_dma_irq_cb(int channel, void *data, struct pt_regs *regs){ return;}void pxa_ci_dma_irq_cr(int channel, void *data, struct pt_regs *regs){ return;} inline static void pxa_ci_dma_stop(camera_context_t *cam_ctx){ int ch0, ch1, ch2; ch0 = cam_ctx->dma_channels[0]; ch1 = cam_ctx->dma_channels[1]; ch2 = cam_ctx->dma_channels[2]; DCSR(ch0) &= ~DCSR_RUN; DCSR(ch1) &= ~DCSR_RUN; DCSR(ch2) &= ~DCSR_RUN;} void pxa_dma_start(camera_context_t *cam_ctx){ unsigned char cnt_blk; pxa_dma_desc *cnt_desc; cam_ctx->block_header = (cam_ctx->block_header + 1) % cam_ctx->block_number; cnt_blk = (unsigned char)cam_ctx->block_header; cnt_desc = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_physical + cnt_blk * cam_ctx->fifo0_num_descriptors; DDADR(cam_ctx->dma_channels[0]) = cnt_desc; DCSR(cam_ctx->dma_channels[0]) |= DCSR_RUN; if (cam_ctx->fifo1_num_descriptors) { cnt_desc = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_physical + cnt_blk * cam_ctx->fifo1_num_descriptors; DDADR(cam_ctx->dma_channels[1]) = cnt_desc; DCSR(cam_ctx->dma_channels[1]) |= DCSR_RUN; } if (cam_ctx->fifo2_num_descriptors) { cnt_desc = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_physical + cnt_blk * cam_ctx->fifo2_num_descriptors; DDADR(cam_ctx->dma_channels[2]) = cnt_desc; DCSR(cam_ctx->dma_channels[2]) |= DCSR_RUN; } return;}void pxa_camera_irq(int irq, void *dev_id, struct pt_regs *regs){ int cisr; static int dma_started=0; disable_irq(IRQ_CAMERA); cisr = CISR; if (cisr & CI_CISR_SOF) { if (dma_started == 0) { dma_started = 1; } CISR |= CI_CISR_SOF; } if (cisr & CI_CISR_EOF) { CISR |= CI_CISR_EOF; } enable_irq(IRQ_CAMERA);}void pxa_dma_repeat(camera_context_t *cam_ctx){ pxa_dma_desc *cnt_head, *cnt_tail; int cnt_block; cnt_block = (cam_ctx->block_header + 1) % cam_ctx->block_number;// FIFO0 (pxa_dma_desc *)cnt_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + cnt_block * cam_ctx->fifo0_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo0_num_descriptors - 1; cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);// FIFO1 if (cam_ctx->fifo1_transfer_size) { cnt_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + cnt_block * cam_ctx->fifo1_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo1_num_descriptors - 1; cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc); }// FIFO2 if (cam_ctx->fifo2_transfer_size) { cnt_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + cnt_block * cam_ctx->fifo2_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo2_num_descriptors - 1; cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc); } return;}void pxa_dma_continue(camera_context_t *cam_ctx){ pxa_dma_desc *cnt_head, *cnt_tail; pxa_dma_desc *next_head; int cnt_block, next_block; cnt_block = cam_ctx->block_header; next_block = (cnt_block + 1) % cam_ctx->block_number;// FIFO0 cnt_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + cnt_block * cam_ctx->fifo0_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo0_num_descriptors - 1; next_head = (pxa_dma_desc *)cam_ctx->fifo0_descriptors_virtual + next_block * cam_ctx->fifo0_num_descriptors; cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);// FIFO1 if (cam_ctx->fifo1_transfer_size) { cnt_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + cnt_block * cam_ctx->fifo1_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo1_num_descriptors - 1; next_head = (pxa_dma_desc *)cam_ctx->fifo1_descriptors_virtual + next_block * cam_ctx->fifo1_num_descriptors; cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc); }// FIFO2 if (cam_ctx->fifo2_transfer_size) { cnt_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + cnt_block * cam_ctx->fifo2_num_descriptors; cnt_tail = cnt_head + cam_ctx->fifo2_num_descriptors - 1; next_head = (pxa_dma_desc *)cam_ctx->fifo2_descriptors_virtual + next_block * cam_ctx->fifo2_num_descriptors; cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc); } return; }static int iic_init(){ printk("iic init here\n"); CKEN |= CKEN14_I2C; set_GPIO_mode(117 | GPIO_ALT_FN_1_IN); set_GPIO_mode(118 | GPIO_ALT_FN_1_IN); ICR |= ICR_UR; udelay(1000); ICR &= ~ICR_UR; udelay(1000); ICR &= ~ICR_IUE; ISAR = 0xff; ISR = 0; ICR = ICR_IUE | ICR_SCLE | ICR_GCD; udelay(100); return 0;}static int iic_read(unsigned char dev_addr,unsigned char reg_addr){ int i; unsigned char data1 = 0; unsigned char data2 = 0; printk("dev_addr = 0x%x, reg_addr = 0x%x\n",dev_addr,reg_addr); //send start signal and device addr here IDBR = (unsigned int)dev_addr; ICR &= ~(ICR_STOP | ICR_ALDIE | ICR_TB); ICR |= ICR_START | ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); printk("IDBR = 0x%x\n",IDBR); printk("ICR = 0x%x\n",ICR); printk("ISR = 0x%x\n",ISR); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send slaveaddr here IDBR = (unsigned int)reg_addr; ICR &= ~(ICR_TB | ICR_START | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); printk("IDBR = 0x%x\n",IDBR); printk("ICR = 0x%x\n",ICR); printk("ISR = 0x%x\n",ISR); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //send start signal and dev_addr read IDBR = (unsigned int)dev_addr | 0x01; ICR &= ~(ICR_TB | ICR_STOP | ICR_ALDIE); ICR |= ICR_TB | ICR_START; for(i=0;i<0x100000;i++) { if((ISR & ISR_ITE) == ISR_ITE) break; } if(i >= 0x100000) { printk("time out at dev_addr\n"); printk("IDBR = 0x%x\n",IDBR); printk("ICR = 0x%x\n",ICR); printk("ISR = 0x%x\n",ISR); } //while((ISR & ISR_ITE) == 0); ISR &= ISR_ITE; while(ISR & ISR_ACKNAK); udelay(2); //init read ICR &= ~(ICR_START | ICR_STOP | ICR_TB | ICR_ACKNAK | ICR_ALDIE); ICR |= ICR_TB; for(i=0;i<0x100000;i++) { if((ISR & ISR_IRF) == ISR_IRF) break; } if(i >= 0x100000) { printk("time out at dev_addr\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -