MPU read problem in iMX28

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MPU read problem in iMX28

Jump to solution
1,347 Views
x10
Contributor V

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;

}

Labels (2)
0 Kudos
Reply
1 Solution
1,020 Views
x10
Contributor V

LCDIF is work as MPU interface, both read and write. :-)

Cheng Shi

emtronix

View solution in original post

0 Kudos
Reply
2 Replies
1,021 Views
x10
Contributor V

LCDIF is work as MPU interface, both read and write. :-)

Cheng Shi

emtronix

0 Kudos
Reply
1,020 Views
x10
Contributor V

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

0 Kudos
Reply