예제 #1
0
int psb_poll_mtx_irq(struct drm_psb_private *dev_priv)
{
	int ret = 0;
	uint32_t mtx_int = 0;

	REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
			       1);

	ret = psb_wait_for_register(dev_priv, MSVDX_INTERRUPT_STATUS,
				    /* Required value */
				    mtx_int,
				    /* Enabled bits */
				    mtx_int, 10000, 100);

	if (ret) {
		DRM_ERROR("MSVDX: Error Mtx did not return"
			  " int within a resonable time\n");
		return ret;
	}

	PSB_DEBUG_IRQ("MSVDX: Got MTX Int\n");

	/* Got it so clear the bit */
	PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);

	return ret;
}
예제 #2
0
void
psb_upload_fw (struct drm_psb_private *dev_priv, const uint32_t ui32DataMem,
	       uint32_t ui32RamBankSize, uint32_t ui32Address,
	       const unsigned int uiWords, const uint32_t * const pui32Data)
{
  uint32_t ui32Loop, ui32Ctrl, ui32RamId, ui32Addr, ui32CurrBank =
    (uint32_t) ~ 0;
  uint32_t ui32AccessControl;

  /* Save the access control register... */
  ui32AccessControl = PSB_RMSVDX32 (MSVDX_MTX_RAM_ACCESS_CONTROL);

  /* Wait for MCMSTAT to become be idle 1 */
  psb_wait_for_register (dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS, 1,	/* Required Value */
			 0xffffffff /* Enables */ );

  for (ui32Loop = 0; ui32Loop < uiWords; ui32Loop++)
    {
      ui32RamId = ui32DataMem + (ui32Address / ui32RamBankSize);

      if (ui32RamId != ui32CurrBank)
	{
	  ui32Addr = ui32Address >> 2;

	  ui32Ctrl = 0;

	  REGIO_WRITE_FIELD_LITE (ui32Ctrl,
				  MSVDX_MTX_RAM_ACCESS_CONTROL,
				  MTX_MCMID, ui32RamId);
	  REGIO_WRITE_FIELD_LITE (ui32Ctrl,
				  MSVDX_MTX_RAM_ACCESS_CONTROL,
				  MTX_MCM_ADDR, ui32Addr);
	  REGIO_WRITE_FIELD_LITE (ui32Ctrl,
				  MSVDX_MTX_RAM_ACCESS_CONTROL, MTX_MCMAI, 1);

	  PSB_WMSVDX32 (ui32Ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);

	  ui32CurrBank = ui32RamId;
	}
      ui32Address += 4;

      PSB_WMSVDX32 (pui32Data[ui32Loop], MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);

      /* Wait for MCMSTAT to become be idle 1 */
      psb_wait_for_register (dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS, 1,	/* Required Value */
			     0xffffffff /* Enables */ );
    }
static void msvdx_upload_fw(struct drm_psb_private *dev_priv,
			  const uint32_t data_mem, uint32_t ram_bank_size,
			  uint32_t address, const unsigned int words,
			  const uint32_t * const data)
{
	uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0;
	uint32_t access_ctrl;

	PSB_DEBUG_GENERAL("MSVDX: Upload firmware by register interface\n");
	/* Save the access control register... */
	access_ctrl = PSB_RMSVDX32(MTX_RAM_ACCESS_CONTROL_OFFSET);

	/* Wait for MCMSTAT to become be idle 1 */
	psb_wait_for_register(dev_priv, MTX_RAM_ACCESS_STATUS_OFFSET,
			      1,	/* Required Value */
			      0xffffffff, /* Enables */
			      2000000, 5);

	for (loop = 0; loop < words; loop++) {
		ram_id = data_mem + (address / ram_bank_size);
		if (ram_id != cur_bank) {
			addr = address >> 2;
			ctrl = 0;
			REGIO_WRITE_FIELD_LITE(ctrl,
					       MTX_RAM_ACCESS_CONTROL,
					       MTX_MCMID, ram_id);
			REGIO_WRITE_FIELD_LITE(ctrl,
					       MTX_RAM_ACCESS_CONTROL,
					       MTX_MCM_ADDR, addr);
			REGIO_WRITE_FIELD_LITE(ctrl,
					       MTX_RAM_ACCESS_CONTROL,
					       MTX_MCMAI, 1);
			PSB_WMSVDX32(ctrl, MTX_RAM_ACCESS_CONTROL_OFFSET);
			cur_bank = ram_id;
		}
		address += 4;

		PSB_WMSVDX32(data[loop],
			     MTX_RAM_ACCESS_DATA_TRANSFER_OFFSET);

		/* Wait for MCMSTAT to become be idle 1 */
		psb_wait_for_register(dev_priv, MTX_RAM_ACCESS_STATUS_OFFSET,
				      1,	/* Required Value */
				      0xffffffff, /* Enables */
				      2000000, 5);
	}
void psb_write_mtx_core_reg(struct drm_psb_private *dev_priv,
			    const uint32_t core_reg, const uint32_t val)
{
	uint32_t reg = 0;

	/* Put data in MTX_RW_DATA */
	PSB_WMSVDX32(val, MSVDX_MTX_REGISTER_READ_WRITE_DATA);

	/* DREADY is set to 0 and request a write */
	reg = core_reg;
	REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
			       MTX_RNW, 0);
	REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
			       MTX_DREADY, 0);
	PSB_WMSVDX32(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);

	psb_wait_for_register(dev_priv,
			      MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
			      MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
			      MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
}
예제 #5
0
void
psb_write_mtx_core_reg (struct drm_psb_private *dev_priv,
			const uint32_t ui32CoreRegister,
			const uint32_t ui32Val)
{
  uint32_t ui32Reg = 0;

  /* Put data in MTX_RW_DATA */
  PSB_WMSVDX32 (ui32Val, MSVDX_MTX_REGISTER_READ_WRITE_DATA);

  /* DREADY is set to 0 and request a write */
  ui32Reg = ui32CoreRegister;
  REGIO_WRITE_FIELD_LITE (ui32Reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
			  MTX_RNW, 0);
  REGIO_WRITE_FIELD_LITE (ui32Reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
			  MTX_DREADY, 0);
  PSB_WMSVDX32 (ui32Reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);

  psb_wait_for_register (dev_priv, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,	/* Required Value */
			 MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
}
static void msvdx_upload_fw(struct drm_psb_private *dev_priv,
			  uint32_t address, const unsigned int words, int fw_sel)
{
	uint32_t reg_val = 0;
	uint32_t cmd;
	uint32_t uCountReg, offset, mmu_ptd;
	uint32_t size = (words * 4); /* byte count */
	uint32_t dma_channel = 0; /* Setup a Simple DMA for Ch0 */
	struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;

	PSB_DEBUG_GENERAL("MSVDX: Upload firmware by DMA\n");
	msvdx_get_mtx_control_from_dash(dev_priv);

	/* dma transfers to/from the mtx have to be 32-bit aligned and in multiples of 32 bits */
	PSB_WMSVDX32(address, MTX_SYSC_CDMAA_OFFSET);

	REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, BURSTSIZE,	4); /* burst size in multiples of 64 bits (allowed values are 2 or 4) */
	REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, RNW, 0);	/* false means write to mtx mem, true means read from mtx mem */
	REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, ENABLE,	1);				/* begin transfer */
	REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, LENGTH,	words);		/* This specifies the transfer size of the DMA operation in terms of 32-bit words */
	PSB_WMSVDX32(reg_val, MTX_SYSC_CDMAC_OFFSET);

	/* toggle channel 0 usage between mtx and other msvdx peripherals */
	{
		reg_val = PSB_RMSVDX32(MSVDX_CONTROL_OFFSET);
		REGIO_WRITE_FIELD(reg_val, MSVDX_CONTROL, DMAC_CH0_SELECT,  0);
		PSB_WMSVDX32(reg_val, MSVDX_CONTROL_OFFSET);
	}


	/* Clear the DMAC Stats */
	PSB_WMSVDX32(0 , DMAC_DMAC_IRQ_STAT_OFFSET + dma_channel);

	offset = msvdx_priv->fw->offset;

	if (fw_sel)
		offset += ((msvdx_priv->mtx_mem_size + 8192) & ~0xfff);

	/* use bank 0 */
	cmd = 0;
	PSB_WMSVDX32(cmd, MSVDX_MMU_BANK_INDEX_OFFSET);

	/* Write PTD to mmu base 0*/
	mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
	PSB_WMSVDX32(mmu_ptd, MSVDX_MMU_DIR_LIST_BASE_OFFSET + 0);

	/* Invalidate */
	reg_val = PSB_RMSVDX32(MSVDX_MMU_CONTROL0_OFFSET);
	reg_val &= ~0xf;
	REGIO_WRITE_FIELD(reg_val, MSVDX_MMU_CONTROL0, MMU_INVALDC, 1);
	PSB_WMSVDX32(reg_val, MSVDX_MMU_CONTROL0_OFFSET);

	PSB_WMSVDX32(offset, DMAC_DMAC_SETUP_OFFSET + dma_channel);

	/* Only use a single dma - assert that this is valid */
	if ((size / 4) >= (1 << 15)) {
		DRM_ERROR("psb: DMA size beyond limited, aboart firmware uploading\n");
		return;
	}

	uCountReg = PSB_DMAC_VALUE_COUNT(PSB_DMAC_BSWAP_NO_SWAP,
					 0,  /* 32 bits */
					 PSB_DMAC_DIR_MEM_TO_PERIPH,
					 0,
					 (size / 4));
	/* Set the number of bytes to dma*/
	PSB_WMSVDX32(uCountReg, DMAC_DMAC_COUNT_OFFSET + dma_channel);

	cmd = PSB_DMAC_VALUE_PERIPH_PARAM(PSB_DMAC_ACC_DEL_0, PSB_DMAC_INCR_OFF, PSB_DMAC_BURST_2);
	PSB_WMSVDX32(cmd, DMAC_DMAC_PERIPH_OFFSET + dma_channel);

	/* Set destination port for dma */
	cmd = 0;
	REGIO_WRITE_FIELD(cmd, DMAC_DMAC_PERIPHERAL_ADDR, ADDR, MTX_SYSC_CDMAT_OFFSET);
	PSB_WMSVDX32(cmd, DMAC_DMAC_PERIPHERAL_ADDR_OFFSET + dma_channel);


	/* Finally, rewrite the count register with the enable bit set*/
	PSB_WMSVDX32(uCountReg | DMAC_DMAC_COUNT_EN_MASK, DMAC_DMAC_COUNT_OFFSET + dma_channel);

	/* Wait for all to be done */
	if (psb_wait_for_register(dev_priv,
				  DMAC_DMAC_IRQ_STAT_OFFSET + dma_channel,
				  DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK,
				  DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK,
				  2000000, 5)) {
		psb_setup_fw_dump(dev_priv, dma_channel);
		msvdx_release_mtx_control_from_dash(dev_priv);
		return;
	}

	/* Assert that the MTX DMA port is all done aswell */
	if (psb_wait_for_register(dev_priv,
			MTX_SYSC_CDMAS0_OFFSET,
			1, 1, 2000000, 5)) {
		msvdx_release_mtx_control_from_dash(dev_priv);
		return;
	}

	msvdx_release_mtx_control_from_dash(dev_priv);

	PSB_DEBUG_GENERAL("MSVDX: Upload done\n");
}