Hi, All
In my driver of LCDIF as MPU read/write bus in imx28, the read operation with following implement can correctly run 8 times, then no read bus cycle anymore.
static unsigned int mpu_data_read(struct em9287_isa_dev *devp)
{
unsigned int i;
u32 value;
/* wait until RUN bit => 0 if necessary */
if (readl(devp->base + LCDC_CTRL) & CTRL_RUN)
{
while (readl(devp->base + LCDC_CTRL) & CTRL_RUN) ;
}
// disable master mode
writel(CTRL_MASTER, devp->base + LCDC_CTRL + REG_CLR);
// set READ_WRITEB bit -> read mode
writel(CTRL_READ_WRITEB, devp->base + LCDC_CTRL + REG_SET);
// setup transfer count
value = (1 << 16) | devp->dat_len;
writel(value, devp->base + LCDC_TRANSFER_COUNT);
/* setup physical address */
writel(devp->read_dma_addr, devp->base + LCDC_CUR_BUF);
/* set RUN bit */
writel(CTRL_RUN, devp->base + LCDC_CTRL + REG_SET);
i = devp->dat_len;
devp->dat_len = 0;
return i;
}
Please let me know how to setup a right procedure to read if anybody has similar experience. Thanks!
BTW, the following is write operation which is always right.
static void mpu_data_write(struct em9287_isa_dev *devp)
{
u32 value;
/* wait until RUN bit => 0 if necessary */
if (readl(devp->base + LCDC_CTRL) & CTRL_RUN)
{
while (readl(devp->base + LCDC_CTRL) & CTRL_RUN) ;
}
// enable master mode
writel(CTRL_MASTER, devp->base + LCDC_CTRL + REG_SET);
// clear READ_WRITEB bit -> write mode
writel(CTRL_READ_WRITEB, devp->base + LCDC_CTRL + REG_CLR);
// setup transfer count
value = (1 << 16) | devp->dat_len;
writel(value, devp->base + LCDC_TRANSFER_COUNT);
/* setup physical address */
writel(devp->write_dma_addr, devp->base + LCDC_CUR_BUF);
/* set RUN bit */
writel(CTRL_RUN, devp->base + LCDC_CTRL + REG_SET);
// wait until RUN => 0
while (readl(devp->base + LCDC_CTRL) & CTRL_RUN) ;
}
init LCDIF:
static int lcdif_mpu_init(struct em9287_isa_dev *devp)
{
unsigned int clock_rate, clock_period;
u32 value;
clk_prepare_enable(devp->clk);
clk_set_rate(devp->clk, ISA_BUS_CLOCK);
clock_rate = clk_get_rate(devp->clk);
clock_period = DIV_NUM(1000000000U, clock_rate);
pr_info("%s: lcdif clock = %d Hz -> %d ns\n", __func__, clock_rate, clock_period);
/* reset LCDIF controller */
mxs_reset_block(devp->base);
/* dump version number */
value = readl(devp->base + LCDC_VERSION);
pr_info("LCDIF version %d.%d.%d\n", (value >> 24) & 0xff, (value >> 16) & 0xff, value & 0xffff);
// stop running
writel(CTRL_RUN, devp->base + LCDC_CTRL + REG_CLR);
// select 8080 mode: Pins LCD_WR_RWn and LCD_RD_E function as active low WR and active low RD signals respectively.
writel(CTRL1_MODE86, devp->base + LCDC_CTRL1 + REG_CLR);
// busy disabled: The busy signal from the LCD controller will be ignored.
writel(CTRL1_BUSY_ENABLE, devp->base + LCDC_CTRL1 + REG_CLR);
// setup data format
writel(CTRL2_READ_MODE_NUM_PACKED_SUBWORDS(2), devp->base + LCDC_CTRL2); /* 2 for 16-bit databus */
value = CTRL_WORD_LENGTH(WORD_LENGTH_16_BIT)
| CTRL_BUS_WIDTH(LCD_DATABUS_WIDTH_16_BIT)
| CTRL_CSC_DATA_SWIZZLE(CSC_DATA_SWIZZLE_NO_SWAP)
| CTRL_INPUT_DATA_SWIZZLE(INPUT_DATA_SWIZZLE_NO_SWAP)
| CTRL_SHIFT_NUM_BITS(0);
writel(value, devp->base + LCDC_CTRL);
// setup bus timing
value = (DIV_NUM(ISA_RW_STROBE, clock_period) & 0xFF) /* -> DATA_SETUP */
| ((DIV_NUM(ISA_DATA_HOLD, clock_period) & 0xFF) << 8) /* -> DATA_HOLD */
| ((DIV_NUM(ISA_CS_SETUP, clock_period) & 0xFF) << 16) /* -> CMD_SETUP */
| ((DIV_NUM(ISA_BUS_HOLD, clock_period) & 0xFF) << 24); /* -> CMD_HOLD */
writel(value, devp->base + LCDC_TIMING);
// enable master mode
writel(CTRL_MASTER, devp->base + LCDC_CTRL + REG_SET);
//only use 2 low bytes
writel(CTRL1_BYTE_PACKAGING(0x3), devp->base + LCDC_CTRL1);
// disable DVI mode
writel(CTRL_DVI_MODE, devp->base + LCDC_CTRL + REG_CLR);
writel(CTRL_BYPASS_COUNT, devp->base + LCDC_CTRL + REG_CLR);
// disable dotclock mode
writel(CTRL_DOTCLK_MODE, devp->base + LCDC_CTRL + REG_CLR);
// disable vsync mode
writel(CTRL_VSYNC_MODE, devp->base + LCDC_CTRL + REG_CLR);
// now, we are in MPU mode
devp->enabled = 1;
//pr_info("%s: LCDIF_CTRL = 0x%08x\n", __func__, readl(devp->base + LCDC_CTRL));
//pr_info("%s: LCDIF_CTRL1 = 0x%08x\n", __func__, readl(devp->base + LCDC_CTRL1));
//pr_info("%s: LCDIF_CTRL2 = 0x%08x\n", __func__, readl(devp->base + LCDC_CTRL2));
return 0;
}
Solved! Go to Solution.
LCDIF is work as MPU interface, both read and write. :-)
Cheng Shi
emtronix
LCDIF is work as MPU interface, both read and write. :-)
Cheng Shi
emtronix
I think I got confused by AXI Master which can only be used for outputing data from frame buffer to LCD. As my understanding, data can be read from register HW_LCDIF_DATA in either DMA or CPU, but how to start a MPU read bus cycle shown in Figure 33-12 before reading the data register. Another question is about the definition of HW_LCDIF_STAT, no information about RXFIFO contains in this register. As I guess, both LFIFO_FULL and LFIFO_EMPTY refers RXFIFO instead of latency FIFO in write datapath, is that right?
It's appreciated for any comments, thanks!
BR
Cheng Shi
emtronix