Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f2a7d5e authored by Felipe Balbi's avatar Felipe Balbi Committed by Samuel Ortiz
Browse files

mfd: Drop twl4030-irq's edge_work



... and do all the synchronization with the
hardware during bus_sync_unlock. We can now
remove all the workqueues.

Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
Reviewed-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 84868424
Loading
Loading
Loading
Loading
+52 −72
Original line number Diff line number Diff line
@@ -422,8 +422,6 @@ static inline void activate_irq(int irq)

/*----------------------------------------------------------------------*/

static struct workqueue_struct *wq;

struct sih_agent {
	int			irq_base;
	const struct sih	*sih;
@@ -432,68 +430,10 @@ struct sih_agent {
	bool			imr_change_pending;

	u32			edge_change;
	struct work_struct	edge_work;

	struct mutex		irq_lock;
};

static void twl4030_sih_do_edge(struct work_struct *work)
{
	struct sih_agent	*agent;
	const struct sih	*sih;
	u8			bytes[6];
	u32			edge_change;
	int			status;

	agent = container_of(work, struct sih_agent, edge_work);

	/* see what work we have */
	edge_change = agent->edge_change;
	agent->edge_change = 0;
	sih = edge_change ? agent->sih : NULL;
	if (!sih)
		return;

	/* Read, reserving first byte for write scratch.  Yes, this
	 * could be cached for some speedup ... but be careful about
	 * any processor on the other IRQ line, EDR registers are
	 * shared.
	 */
	status = twl_i2c_read(sih->module, bytes + 1,
			sih->edr_offset, sih->bytes_edr);
	if (status) {
		pr_err("twl4030: %s, %s --> %d\n", __func__,
				"read", status);
		return;
	}

	/* Modify only the bits we know must change */
	while (edge_change) {
		int		i = fls(edge_change) - 1;
		struct irq_data	*idata = irq_get_irq_data(i + agent->irq_base);
		int		byte = 1 + (i >> 2);
		int		off = (i & 0x3) * 2;
		unsigned int	type;

		bytes[byte] &= ~(0x03 << off);

		type = irqd_get_trigger_type(idata);
		if (type & IRQ_TYPE_EDGE_RISING)
			bytes[byte] |= BIT(off + 1);
		if (type & IRQ_TYPE_EDGE_FALLING)
			bytes[byte] |= BIT(off + 0);

		edge_change &= ~BIT(i);
	}

	/* Write */
	status = twl_i2c_write(sih->module, bytes,
			sih->edr_offset, sih->bytes_edr);
	if (status)
		pr_err("twl4030: %s, %s --> %d\n", __func__,
				"write", status);
}

/*----------------------------------------------------------------------*/

/*
@@ -526,10 +466,8 @@ static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
		return -EINVAL;

	if (irqd_get_trigger_type(data) != trigger) {
	if (irqd_get_trigger_type(data) != trigger)
		agent->edge_change |= BIT(data->irq - agent->irq_base);
		queue_work(wq, &agent->edge_work);
	}

	return 0;
}
@@ -566,6 +504,56 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
					"write", status);
	}

	if (agent->edge_change) {
		u32		edge_change;
		u8		bytes[6];

		edge_change = agent->edge_change;
		agent->edge_change = 0;

		/*
		 * Read, reserving first byte for write scratch.  Yes, this
		 * could be cached for some speedup ... but be careful about
		 * any processor on the other IRQ line, EDR registers are
		 * shared.
		 */
		status = twl_i2c_read(sih->module, bytes + 1,
				sih->edr_offset, sih->bytes_edr);
		if (status) {
			pr_err("twl4030: %s, %s --> %d\n", __func__,
					"read", status);
			return;
		}

		/* Modify only the bits we know must change */
		while (edge_change) {
			int		i = fls(edge_change) - 1;
			struct irq_data	*idata;
			int		byte = 1 + (i >> 2);
			int		off = (i & 0x3) * 2;
			unsigned int	type;

			idata = irq_get_irq_data(i + agent->irq_base);

			bytes[byte] &= ~(0x03 << off);

			type = irqd_get_trigger_type(idata);
			if (type & IRQ_TYPE_EDGE_RISING)
				bytes[byte] |= BIT(off + 1);
			if (type & IRQ_TYPE_EDGE_FALLING)
				bytes[byte] |= BIT(off + 0);

			edge_change &= ~BIT(i);
		}

		/* Write */
		status = twl_i2c_write(sih->module, bytes,
				sih->edr_offset, sih->bytes_edr);
		if (status)
			pr_err("twl4030: %s, %s --> %d\n", __func__,
					"write", status);
	}

	mutex_unlock(&agent->irq_lock);
}

@@ -672,7 +660,6 @@ int twl4030_sih_setup(int module)
	agent->sih = sih;
	agent->imr = ~0;
	mutex_init(&agent->irq_lock);
	INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);

	for (i = 0; i < sih->bits; i++) {
		irq = irq_base + i;
@@ -720,12 +707,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
	if (status < 0)
		return status;

	wq = create_singlethread_workqueue("twl4030-irqchip");
	if (!wq) {
		pr_err("twl4030: workqueue FAIL\n");
		return -ESRCH;
	}

	twl4030_irq_base = irq_base;

	/* install an irq handler for each of the SIH modules;
@@ -766,8 +747,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
fail:
	for (i = irq_base; i < irq_end; i++)
		irq_set_chip_and_handler(i, NULL, NULL);
	destroy_workqueue(wq);
	wq = NULL;

	return status;
}