Esempio n. 1
0
/**
 * mic_x100_ack_interrupt - Read the interrupt sources register and
 * clear it. This function will be called in the MSI/INTx case.
 * @mdev: Pointer to mic_device instance.
 *
 * Returns: bitmask of interrupt sources triggered.
 */
static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
{
	u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
	u32 reg = mic_mmio_read(&mdev->mmio, sicr0);
	mic_mmio_write(&mdev->mmio, reg, sicr0);
	return reg;
}
Esempio n. 2
0
/**
 * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
 * @mdev: pointer to mic_device instance
 * @idx: index to the mapping register, 0 based
 *
 * This function allows reading of the 32bit MSI mapping register.
 *
 * RETURNS: The value in the register.
 */
static u32
mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
{
	return mic_mmio_read(&mdev->mmio,
		MIC_X100_SBOX_BASE_ADDRESS +
		MIC_X100_SBOX_MXAR0 + idx * 4);
}
Esempio n. 3
0
/**
 * mic_ack_interrupt - Device specific interrupt handling.
 * @mdev: pointer to mic_device instance
 *
 * Returns: bitmask of doorbell events triggered.
 */
static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
{
	u32 reg = 0;
	struct mic_mw *mw = &mdev->mmio;
	u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;

	/* Clear pending bit array. */
	if (MIC_A0_STEP == mdev->stepping)
		mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
			MIC_X100_SBOX_MSIXPBACR);

	if (mdev->irq_info.num_vectors <= 1) {
		reg = mic_mmio_read(mw, sicr0);

		if (unlikely(!reg))
			goto done;

		mic_mmio_write(mw, reg, sicr0);
	}

	if (mdev->stepping >= MIC_B0_STEP)
		mdev->intr_ops->enable_interrupts(mdev);
done:
	return reg;
}
Esempio n. 4
0
/**
 * mic_x100_disable_interrupts - Disable interrupts.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_disable_interrupts(struct mic_device *mdev)
{
	u32 reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
	u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;

	reg = mic_mmio_read(mw, sice0);
	mic_mmio_write(mw, reg, sicc0);

	if (mdev->irq_info.num_vectors > 1) {
		reg = mic_mmio_read(mw, siac0);
		reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
			MIC_X100_SBOX_DMA_BITS(0xff));
		mic_mmio_write(mw, reg, siac0);
	}
}
Esempio n. 5
0
/**
 * mic_x100_read_spad - read from the scratchpad register
 * @mdev: pointer to mic_device instance
 * @idx: index to scratchpad register, 0 based
 *
 * This function allows reading of the 32bit scratchpad register.
 *
 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
 */
static u32
mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
{
	u32 val = mic_mmio_read(&mdev->mmio,
		MIC_X100_SBOX_BASE_ADDRESS +
		MIC_X100_SBOX_SPAD0 + idx * 4);

	dev_dbg(mdev->sdev->parent,
		"Reading 0x%x from scratch pad index %d\n", val, idx);
	return val;
}
Esempio n. 6
0
/**
 * mic_x100_enable_interrupts - Enable interrupts.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_enable_interrupts(struct mic_device *mdev)
{
	u32 reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;

	reg = mic_mmio_read(mw, sice0);
	reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
	mic_mmio_write(mw, reg, sice0);

	/*
	 * Enable auto-clear when enabling interrupts. Applicable only for
	 * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
	 */
	if (mdev->irq_info.num_vectors > 1) {
		reg = mic_mmio_read(mw, siac0);
		reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
			MIC_X100_SBOX_DMA_BITS(0xff);
		mic_mmio_write(mw, reg, siac0);
	}
}
Esempio n. 7
0
/**
 * mic_x100_program_msi_to_src_map - program the MSI mapping registers
 * @mdev: pointer to mic_device instance
 * @idx: index to the mapping register, 0 based
 * @offset: The bit offset in the register that needs to be updated.
 * @set: boolean specifying if the bit in the specified offset needs
 * to be set or cleared.
 *
 * RETURNS: None.
 */
static void
mic_x100_program_msi_to_src_map(struct mic_device *mdev,
				int idx, int offset, bool set)
{
	unsigned long reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
		MIC_X100_SBOX_MXAR0 + idx * 4;

	reg = mic_mmio_read(mw, mxar);
	if (set)
		__set_bit(offset, &reg);
	else
		__clear_bit(offset, &reg);
	mic_mmio_write(mw, reg, mxar);
}
Esempio n. 8
0
/**
 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_send_sbox_intr(struct mic_device *mdev,
			int doorbell)
{
	struct mic_mw *mw = &mdev->mmio;
	u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
	u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
					apic_icr_offset);

	/* for MIC we need to make sure we "hit" the send_icr bit (13) */
	apicicr_low = (apicicr_low | (1 << 13));

	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
	wmb();
	mic_mmio_write(mw, apicicr_low,
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}
Esempio n. 9
0
/**
 * mic_x100_hw_reset - Reset the MIC device.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_hw_reset(struct mic_device *mdev)
{
	u32 reset_reg;
	u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
	struct mic_mw *mw = &mdev->mmio;

	/* Ensure that the reset is ordered w.r.t. previous loads and stores */
	mb();
	/* Trigger reset */
	reset_reg = mic_mmio_read(mw, rgcr);
	reset_reg |= 0x1;
	mic_mmio_write(mw, reset_reg, rgcr);
	/*
	 * It seems we really want to delay at least 1 second
	 * after touching reset to prevent a lot of problems.
	 */
	msleep(1000);
}
Esempio n. 10
0
/*
 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
 */
static void mic_x100_send_sbox_intr(struct mic_mw *mw, int doorbell)
{
	u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
	u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
					apic_icr_offset);

	/* for MIC we need to make sure we "hit" the send_icr bit (13) */
	apicicr_low = (apicicr_low | (1 << 13));
	/*
	 * Ensure that the interrupt is ordered w.r.t. previous stores
	 * to main memory. Fence instructions are not implemented in X100
	 * since execution is in order but a compiler barrier is still
	 * required.
	 */
	wmb();
	mic_mmio_write(mw, apicicr_low,
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}
Esempio n. 11
0
/**
 * mic_x100_get_postcode - Get postcode status from firmware.
 * @mdev: pointer to mic_device instance
 *
 * RETURNS: postcode.
 */
static u32 mic_x100_get_postcode(struct mic_device *mdev)
{
	return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
}
Esempio n. 12
0
/**
 * mic_read_spad - read from the scratchpad register
 * @mdev: pointer to mic_device instance
 * @idx: index to scratchpad register, 0 based
 *
 * This function allows reading of the 32bit scratchpad register.
 *
 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
 */
u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
{
	return mic_mmio_read(&mdev->mmio,
		MIC_X100_SBOX_BASE_ADDRESS +
		MIC_X100_SBOX_SPAD0 + idx * 4);
}