示例#1
0
/**
 * prcmu_abb_read() - Read register value(s) from the ABB.
 * @slave:	The I2C slave address.
 * @reg:	The (start) register address.
 * @value:	The read out value(s).
 * @size:	The number of registers to read.
 *
 * Reads register value(s) from the ABB.
 * @size has to be 1 for the current firmware version.
 */
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
	int r;

	if (size != 1)
		return -EINVAL;

	r = mutex_lock_interruptible(&mb5_transfer.lock);
	if (r)
		return r;

	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
		cpu_relax();

	writeb(I2C_READ(slave), REQ_MB5_I2C_SLAVE_OP);
	writeb(I2C_STOP_EN, REQ_MB5_I2C_HW_BITS);
	writeb(reg, REQ_MB5_I2C_REG);

	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
	if (!wait_for_completion_timeout(&mb5_transfer.work,
			msecs_to_jiffies(500))) {
		pr_err("prcmu: prcmu_abb_read timed out.\n");
		r = -EIO;
		goto unlock_and_return;
	}
	r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
	if (!r)
		*value = mb5_transfer.ack.value;

unlock_and_return:
	mutex_unlock(&mb5_transfer.lock);
	return r;
}
int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
{
	int r;

	if ((size < 1) || (4 < size))
		return -EINVAL;

	mutex_lock(&mb5_transfer.lock);

	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
		cpu_relax();
	writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
	writeb(reg, PRCM_REQ_MB5_I2C_REG);
	writeb(size, PRCM_REQ_MB5_I2C_SIZE);
	memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size);
	writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER);

	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
	wait_for_completion(&mb5_transfer.work);

	if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) &&
		(mb5_transfer.ack.status == RC_SUCCESS))
		r = 0;
	else
		r = -EIO;

	mutex_unlock(&mb5_transfer.lock);

	return r;
}
static void ack_dbb_wakeup(void)
{
	unsigned long flags;

	spin_lock_irqsave(&mb0_transfer.lock, flags);

	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
		cpu_relax();

	writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);

	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
}
示例#4
0
static void read_mailbox_5(void)
{
	mb5_transfer.ack.status = readb(ACK_MB5_I2C_STATUS);
	mb5_transfer.ack.value = readb(ACK_MB5_I2C_VAL);
	complete(&mb5_transfer.work);
	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
}
示例#5
0
static irqreturn_t prcmu_irq_handler(int irq, void *data)
{
	u32 bits;
	u8 n;

	bits = (readl(PRCM_ARM_IT1_VAL) & (MBOX_BIT(NUM_MBOX) - 1));
	if (unlikely(!bits))
		return IRQ_NONE;

	for (n = 0; bits; n++) {
		if (bits & MBOX_BIT(n)) {
			bits -= MBOX_BIT(n);
			read_mailbox[n]();
		}
	}
	return IRQ_HANDLED;
}
示例#6
0
static int __init prcmu_init(void)
{
	mutex_init(&mb5_transfer.lock);
	init_completion(&mb5_transfer.work);

	/* Clean up the mailbox interrupts after pre-kernel code. */
	writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR);

	return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL);
}
static irqreturn_t prcmu_irq_handler(int irq, void *data)
{
	u32 bits;
	u8 n;
	irqreturn_t r;

	bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
	if (unlikely(!bits))
		return IRQ_NONE;

	r = IRQ_HANDLED;
	for (n = 0; bits; n++) {
		if (bits & MBOX_BIT(n)) {
			bits -= MBOX_BIT(n);
			if (read_mailbox[n]())
				r = IRQ_WAKE_THREAD;
		}
	}
	return r;
}
static bool read_mailbox_0(void)
{
	bool r;
	u8 header;

	header = readb(PRCM_ACK_MB0_HEADER);
	switch (header) {
	case AMB0H_WAKE_UP:
		r = true;
		break;
	default:
		print_unknown_header_warning(0, header);
		r = false;
		break;
	}
	writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
	return r;
}
static bool read_mailbox_5(void)
{
	u8 header;

	header = readb(PRCM_ACK_MB5_HEADER);
	switch (header) {
	case MB5H_I2C_READ:
		memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4);
	case MB5H_I2C_WRITE:
		mb5_transfer.ack.header = header;
		mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE);
		complete(&mb5_transfer.work);
		break;
	default:
		print_unknown_header_warning(5, header);
		break;
	}
	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
	return false;
}
static bool read_mailbox_7(void)
{
	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
	return false;
}
示例#11
0
static bool read_mailbox_6(void)
{
	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
	return false;
}
示例#12
0
static void read_mailbox_7(void)
{
	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
}