static void omap24xxcam_dmahw_transfer_chain(void __iomem *base, int dmach, int free_dmach) { int prev_dmach, ch; if (dmach == 0) prev_dmach = NUM_CAMDMA_CHANNELS - 1; else prev_dmach = dmach - 1; omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach), CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach); /* Did we chain the DMA transfer before the previous one * finished? */ ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS; while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch)) & CAMDMA_CCR_ENABLE)) { if (ch == dmach) { /* The previous transfer has ended and this one * hasn't started, so we must not have chained * to the previous one in time. We'll have to * start it now. */ omap24xxcam_dmahw_transfer_start(base, dmach); break; } else ch = (ch + 1) % NUM_CAMDMA_CHANNELS; } }
/* * Reset camera block to power-on state. */ static void omap24xxcam_poweron_reset(struct omap24xxcam_device *cam) { int max_loop = RESET_TIMEOUT_NS; /* Reset whole camera subsystem */ omap24xxcam_reg_out(cam->mmio_base, CAM_SYSCONFIG, CAM_SYSCONFIG_SOFTRESET); /* Wait till it's finished */ while (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS) & CAM_SYSSTATUS_RESETDONE) && --max_loop) { ndelay(1); } if (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS) & CAM_SYSSTATUS_RESETDONE)) dev_err(cam->dev, "camera soft reset timeout\n"); }
/* Ack dmach on CSR and IRQSTATUS_L0 */ static u32 omap24xxcam_dmahw_ack_ch(void __iomem *base, int dmach) { u32 csr; csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach)); /* ack interrupt in CSR */ omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr); /* ack interrupt in IRQSTATUS */ omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach)); return csr; }
/* Ack all interrupt on CSR and IRQSTATUS_L0 */ static void omap24xxcam_dmahw_ack_all(void __iomem *base) { u32 csr; int i; for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) { csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i)); /* ack interrupt in CSR */ omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr); } omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf); }
static u32 omap24xxcam_dmahw_ack_ch(unsigned long base, int dmach) { u32 csr; csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach)); omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr); omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach)); return csr; }
static void omap24xxcam_dmahw_ack_all(unsigned long base) { u32 csr; int i; for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) { csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i)); omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr); } omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf); }
/* Interrupt service routine for camera core interrupts. */ static void omap24xxcam_core_isr(struct omap24xxcam_device *cam) { u32 cc_irqstatus; const u32 cc_irqstatus_err = CC_IRQSTATUS_FW_ERR_IRQ | CC_IRQSTATUS_FSC_ERR_IRQ | CC_IRQSTATUS_SSC_ERR_IRQ | CC_IRQSTATUS_FIFO_UF_IRQ | CC_IRQSTATUS_FIFO_OF_IRQ; cc_irqstatus = omap24xxcam_reg_in(cam->mmio_base + CC_REG_OFFSET, CC_IRQSTATUS); omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQSTATUS, cc_irqstatus); if (cc_irqstatus & cc_irqstatus_err && !atomic_read(&cam->in_reset)) { dev_dbg(cam->dev, "resetting camera, cc_irqstatus 0x%x\n", cc_irqstatus); omap24xxcam_reset(cam); } }
/* * The main interrupt handler. */ static irqreturn_t omap24xxcam_isr(int irq, void *arg) { struct omap24xxcam_device *cam = (struct omap24xxcam_device *)arg; u32 irqstatus; unsigned int irqhandled = 0; irqstatus = omap24xxcam_reg_in(cam->mmio_base, CAM_IRQSTATUS); if (irqstatus & (CAM_IRQSTATUS_DMA_IRQ2 | CAM_IRQSTATUS_DMA_IRQ1 | CAM_IRQSTATUS_DMA_IRQ0)) { omap24xxcam_dma_isr(&cam->sgdma.dma); irqhandled = 1; } if (irqstatus & CAM_IRQSTATUS_CC_IRQ) { omap24xxcam_core_isr(cam); irqhandled = 1; } if (irqstatus & CAM_IRQSTATUS_MMU_IRQ) dev_err(cam->dev, "unhandled camera MMU interrupt!\n"); return IRQ_RETVAL(irqhandled); }
static void omap24xxcam_dmahw_transfer_chain(unsigned long base, int dmach, int free_dmach) { int prev_dmach, ch; if (dmach == 0) prev_dmach = NUM_CAMDMA_CHANNELS - 1; else prev_dmach = dmach - 1; omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach), CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach); ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS; while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch)) & CAMDMA_CCR_ENABLE)) { if (ch == dmach) { omap24xxcam_dmahw_transfer_start(base, dmach); break; } else ch = (ch + 1) % NUM_CAMDMA_CHANNELS; } }
static int omap24xxcam_dmahw_running(void __iomem *base, int dmach) { return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE; }
static int omap24xxcam_dmahw_running(unsigned long base, int dmach) { return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE; }