static void msvdx_release_mtx_control_from_dash(struct drm_psb_private *dev_priv)
{
	struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;

	/* restore access control */
	PSB_WMSVDX32(msvdx_priv->psb_dash_access_ctrl, MTX_RAM_ACCESS_CONTROL_OFFSET);
	/* release bus */
	PSB_WMSVDX32(0x4, MSVDX_MTX_DEBUG_OFFSET);
}
示例#2
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;
}
示例#3
0
文件: psb_irq.c 项目: gregkh/psb-kmp
void psb_irq_uninstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);

	dev_priv->sgx_irq_mask = 0x00000000;
	dev_priv->sgx2_irq_mask = 0x00000000;
	dev_priv->vdc_irq_mask = 0x00000000;

	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
	PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
	PSB_WSGX32(dev_priv->sgx_irq_mask, PSB_CR_EVENT_HOST_ENABLE);
	PSB_WSGX32(dev_priv->sgx2_irq_mask, PSB_CR_EVENT_HOST_ENABLE2);
	wmb();
	PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
	PSB_WSGX32(PSB_RSGX32(PSB_CR_EVENT_STATUS), PSB_CR_EVENT_HOST_CLEAR);
	PSB_WSGX32(PSB_RSGX32(PSB_CR_EVENT_STATUS2), PSB_CR_EVENT_HOST_CLEAR2);

	/****MSVDX IRQ Setup...*****/
	/* Clear interrupt enabled flag */
	PSB_WMSVDX32(0, MSVDX_HOST_INTERRUPT_ENABLE);

	dev_priv->irq_enabled = 0;
	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);

}
示例#4
0
文件: psb_irq.c 项目: gregkh/psb-kmp
void psb_irq_postinstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;
	unsigned long irqflags;

	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
	PSB_WSGX32(dev_priv->sgx2_irq_mask, PSB_CR_EVENT_HOST_ENABLE2);
	PSB_WSGX32(dev_priv->sgx_irq_mask, PSB_CR_EVENT_HOST_ENABLE);
	(void)PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);
	/****MSVDX IRQ Setup...*****/
	/* Enable Mtx Interupt to host */
	{
		unsigned long enables = 0;
		PSB_DEBUG_GENERAL("Setting up MSVDX IRQs.....\n");
		REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS,
				       CR_MTX_IRQ, 1);
		PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE);
	}
	dev_priv->irq_enabled = 1;
 
	uint32_t hotplug_stat = PSB_RVDC32(PORT_HOTPLUG_ENABLE_REG);
	PSB_WVDC32(hotplug_stat | SDVOB_HOTPLUG_DETECT_ENABLE, PORT_HOTPLUG_ENABLE_REG);

	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
}
示例#5
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);
	}
示例#7
0
文件: psb_irq.c 项目: gregkh/psb-kmp
void psb_msvdx_irq_postinstall(struct drm_psb_private *dev_priv)
{
	/* Enable Mtx Interupt to host */
	unsigned long enables = 0;
	PSB_DEBUG_GENERAL("Setting up MSVDX IRQs.....\n");
	REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1);
	PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE);
}
示例#8
0
文件: psb_irq.c 项目: gregkh/psb-kmp
void psb_msvdx_irq_preinstall(struct drm_psb_private *dev_priv)
{
	unsigned long mtx_int = 0;
	dev_priv->vdc_irq_mask |= _PSB_IRQ_MSVDX_FLAG;

	/*Clear MTX interrupt */
	REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1);
	PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
}
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);
}
示例#10
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);
}
示例#11
0
文件: psb_irq.c 项目: gregkh/psb-kmp
/*
 * MSVDX interrupt.
 */
static void psb_msvdx_interrupt(struct drm_device *dev, uint32_t msvdx_stat)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;

	if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK) {
		/*Ideally we should we should never get to this */
		PSB_DEBUG_GENERAL
		    ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MMU FAULT)\n",
		     msvdx_stat, dev_priv->fence2_irq_on);

		/* Pause MMU */
		PSB_WMSVDX32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
			     MSVDX_MMU_CONTROL0);
		DRM_WRITEMEMORYBARRIER();

		/* Clear this interupt bit only */
		PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK,
			     MSVDX_INTERRUPT_CLEAR);
		PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
		DRM_READMEMORYBARRIER();

		dev_priv->msvdx_needs_reset = 1;
	} else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
		PSB_DEBUG_GENERAL
		    ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MTX)\n",
		     msvdx_stat, dev_priv->fence2_irq_on);

		/* Clear all interupt bits */
		PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR);
		PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
		DRM_READMEMORYBARRIER();

		psb_msvdx_mtx_interrupt(dev);
	}
}
static void msvdx_get_mtx_control_from_dash(struct drm_psb_private *dev_priv)
{
	struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
	int count = 0;
	uint32_t reg_val = 0;

	REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_IS_SLAVE, 1);
	REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_GPIO_IN, 0x02);
	PSB_WMSVDX32(reg_val, MSVDX_MTX_DEBUG_OFFSET);

	do {
		reg_val = PSB_RMSVDX32(MSVDX_MTX_DEBUG_OFFSET);
		count++;
	} while (((reg_val & 0x18) != 0) && count < 50000);

	if (count >= 50000)
		PSB_DEBUG_GENERAL("MAVDX: timeout in get_mtx_control_from_dash\n");

	/* Save the access control register...*/
	msvdx_priv->psb_dash_access_ctrl = PSB_RMSVDX32(MTX_RAM_ACCESS_CONTROL_OFFSET);
}
示例#13
0
文件: psb_irq.c 项目: gregkh/psb-kmp
void psb_irq_preinstall(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv =
	    (struct drm_psb_private *)dev->dev_private;
	spin_lock(&dev_priv->irqmask_lock);
	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
	PSB_WVDC32(0x00000000, PSB_INT_MASK_R);
	PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
	PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
	(void)PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);

	dev_priv->sgx_irq_mask = _PSB_CE_PIXELBE_END_RENDER |
	    _PSB_CE_DPM_3D_MEM_FREE |
	    _PSB_CE_TA_FINISHED |
	    _PSB_CE_DPM_REACHED_MEM_THRESH |
	    _PSB_CE_DPM_OUT_OF_MEMORY_GBL |
	    _PSB_CE_DPM_OUT_OF_MEMORY_MT |
	    _PSB_CE_TA_TERMINATE | _PSB_CE_SW_EVENT;

	dev_priv->sgx2_irq_mask = _PSB_CE2_BIF_REQUESTER_FAULT;

	dev_priv->vdc_irq_mask = _PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG | _PSB_HOTPLUG_INTERRUPT_ENABLE;

	if (!drm_psb_disable_vsync || drm_psb_detear)
		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG |
		    _PSB_VSYNC_PIPEB_FLAG;

	/*Clear MTX interrupt */
	{
		unsigned long mtx_int = 0;
		REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS,
				       CR_MTX_IRQ, 1);
		PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
	}
	spin_unlock(&dev_priv->irqmask_lock);
}
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");
}