AnsweredAssumed Answered

MPU read problem in iMX28

Question asked by Cheng Shi on Sep 25, 2013
Latest reply on Oct 30, 2013 by Cheng Shi

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;

}

Outcomes