xref: /linux/drivers/gpio/gpio-virtio.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
13a29355aSViresh Kumar // SPDX-License-Identifier: GPL-2.0+
23a29355aSViresh Kumar /*
33a29355aSViresh Kumar  * GPIO driver for virtio-based virtual GPIO controllers
43a29355aSViresh Kumar  *
53a29355aSViresh Kumar  * Copyright (C) 2021 metux IT consult
63a29355aSViresh Kumar  * Enrico Weigelt, metux IT consult <info@metux.net>
73a29355aSViresh Kumar  *
83a29355aSViresh Kumar  * Copyright (C) 2021 Linaro.
93a29355aSViresh Kumar  * Viresh Kumar <viresh.kumar@linaro.org>
103a29355aSViresh Kumar  */
113a29355aSViresh Kumar 
123a29355aSViresh Kumar #include <linux/completion.h>
133a29355aSViresh Kumar #include <linux/err.h>
143a29355aSViresh Kumar #include <linux/gpio/driver.h>
153a29355aSViresh Kumar #include <linux/io.h>
163a29355aSViresh Kumar #include <linux/kernel.h>
173a29355aSViresh Kumar #include <linux/module.h>
183a29355aSViresh Kumar #include <linux/mutex.h>
19eff5cdd7SViresh Kumar #include <linux/spinlock.h>
203a29355aSViresh Kumar #include <linux/virtio_config.h>
213a29355aSViresh Kumar #include <uapi/linux/virtio_gpio.h>
223a29355aSViresh Kumar #include <uapi/linux/virtio_ids.h>
233a29355aSViresh Kumar 
243a29355aSViresh Kumar struct virtio_gpio_line {
253a29355aSViresh Kumar 	struct mutex lock; /* Protects line operation */
263a29355aSViresh Kumar 	struct completion completion;
273a29355aSViresh Kumar 	struct virtio_gpio_request req ____cacheline_aligned;
283a29355aSViresh Kumar 	struct virtio_gpio_response res ____cacheline_aligned;
293a29355aSViresh Kumar 	unsigned int rxlen;
303a29355aSViresh Kumar };
313a29355aSViresh Kumar 
32eff5cdd7SViresh Kumar struct vgpio_irq_line {
33eff5cdd7SViresh Kumar 	u8 type;
34eff5cdd7SViresh Kumar 	bool disabled;
35eff5cdd7SViresh Kumar 	bool masked;
36eff5cdd7SViresh Kumar 	bool queued;
37eff5cdd7SViresh Kumar 	bool update_pending;
38eff5cdd7SViresh Kumar 	bool queue_pending;
39eff5cdd7SViresh Kumar 
40eff5cdd7SViresh Kumar 	struct virtio_gpio_irq_request ireq ____cacheline_aligned;
41eff5cdd7SViresh Kumar 	struct virtio_gpio_irq_response ires ____cacheline_aligned;
42eff5cdd7SViresh Kumar };
43eff5cdd7SViresh Kumar 
443a29355aSViresh Kumar struct virtio_gpio {
453a29355aSViresh Kumar 	struct virtio_device *vdev;
463a29355aSViresh Kumar 	struct mutex lock; /* Protects virtqueue operation */
473a29355aSViresh Kumar 	struct gpio_chip gc;
483a29355aSViresh Kumar 	struct virtio_gpio_line *lines;
493a29355aSViresh Kumar 	struct virtqueue *request_vq;
50eff5cdd7SViresh Kumar 
51eff5cdd7SViresh Kumar 	/* irq support */
52eff5cdd7SViresh Kumar 	struct virtqueue *event_vq;
53eff5cdd7SViresh Kumar 	struct mutex irq_lock; /* Protects irq operation */
54eff5cdd7SViresh Kumar 	raw_spinlock_t eventq_lock; /* Protects queuing of the buffer */
55eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_lines;
563a29355aSViresh Kumar };
573a29355aSViresh Kumar 
_virtio_gpio_req(struct virtio_gpio * vgpio,u16 type,u16 gpio,u8 txvalue,u8 * rxvalue,void * response,u32 rxlen)583a29355aSViresh Kumar static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
593a29355aSViresh Kumar 			    u8 txvalue, u8 *rxvalue, void *response, u32 rxlen)
603a29355aSViresh Kumar {
613a29355aSViresh Kumar 	struct virtio_gpio_line *line = &vgpio->lines[gpio];
623a29355aSViresh Kumar 	struct virtio_gpio_request *req = &line->req;
633a29355aSViresh Kumar 	struct virtio_gpio_response *res = response;
643a29355aSViresh Kumar 	struct scatterlist *sgs[2], req_sg, res_sg;
653a29355aSViresh Kumar 	struct device *dev = &vgpio->vdev->dev;
663a29355aSViresh Kumar 	int ret;
673a29355aSViresh Kumar 
683a29355aSViresh Kumar 	/*
693a29355aSViresh Kumar 	 * Prevent concurrent requests for the same line since we have
703a29355aSViresh Kumar 	 * pre-allocated request/response buffers for each GPIO line. Moreover
713a29355aSViresh Kumar 	 * Linux always accesses a GPIO line sequentially, so this locking shall
723a29355aSViresh Kumar 	 * always go through without any delays.
733a29355aSViresh Kumar 	 */
743a29355aSViresh Kumar 	mutex_lock(&line->lock);
753a29355aSViresh Kumar 
763a29355aSViresh Kumar 	req->type = cpu_to_le16(type);
773a29355aSViresh Kumar 	req->gpio = cpu_to_le16(gpio);
7817395d77SViresh Kumar 	req->value = cpu_to_le32(txvalue);
793a29355aSViresh Kumar 
803a29355aSViresh Kumar 	sg_init_one(&req_sg, req, sizeof(*req));
813a29355aSViresh Kumar 	sg_init_one(&res_sg, res, rxlen);
823a29355aSViresh Kumar 	sgs[0] = &req_sg;
833a29355aSViresh Kumar 	sgs[1] = &res_sg;
843a29355aSViresh Kumar 
853a29355aSViresh Kumar 	line->rxlen = 0;
863a29355aSViresh Kumar 	reinit_completion(&line->completion);
873a29355aSViresh Kumar 
883a29355aSViresh Kumar 	/*
893a29355aSViresh Kumar 	 * Virtqueue callers need to ensure they don't call its APIs with other
903a29355aSViresh Kumar 	 * virtqueue operations at the same time.
913a29355aSViresh Kumar 	 */
923a29355aSViresh Kumar 	mutex_lock(&vgpio->lock);
933a29355aSViresh Kumar 	ret = virtqueue_add_sgs(vgpio->request_vq, sgs, 1, 1, line, GFP_KERNEL);
943a29355aSViresh Kumar 	if (ret) {
953a29355aSViresh Kumar 		dev_err(dev, "failed to add request to vq\n");
963a29355aSViresh Kumar 		mutex_unlock(&vgpio->lock);
973a29355aSViresh Kumar 		goto out;
983a29355aSViresh Kumar 	}
993a29355aSViresh Kumar 
1003a29355aSViresh Kumar 	virtqueue_kick(vgpio->request_vq);
1013a29355aSViresh Kumar 	mutex_unlock(&vgpio->lock);
1023a29355aSViresh Kumar 
1033e4d9a48SVincent Whitchurch 	wait_for_completion(&line->completion);
1043a29355aSViresh Kumar 
1053a29355aSViresh Kumar 	if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) {
1063a29355aSViresh Kumar 		dev_err(dev, "GPIO request failed: %d\n", gpio);
1073a29355aSViresh Kumar 		ret = -EINVAL;
1083a29355aSViresh Kumar 		goto out;
1093a29355aSViresh Kumar 	}
1103a29355aSViresh Kumar 
1113a29355aSViresh Kumar 	if (unlikely(line->rxlen != rxlen)) {
1123a29355aSViresh Kumar 		dev_err(dev, "GPIO operation returned incorrect len (%u : %u)\n",
1133a29355aSViresh Kumar 			rxlen, line->rxlen);
1143a29355aSViresh Kumar 		ret = -EINVAL;
1153a29355aSViresh Kumar 		goto out;
1163a29355aSViresh Kumar 	}
1173a29355aSViresh Kumar 
1183a29355aSViresh Kumar 	if (rxvalue)
1193a29355aSViresh Kumar 		*rxvalue = res->value;
1203a29355aSViresh Kumar 
1213a29355aSViresh Kumar out:
1223a29355aSViresh Kumar 	mutex_unlock(&line->lock);
1233a29355aSViresh Kumar 	return ret;
1243a29355aSViresh Kumar }
1253a29355aSViresh Kumar 
virtio_gpio_req(struct virtio_gpio * vgpio,u16 type,u16 gpio,u8 txvalue,u8 * rxvalue)1263a29355aSViresh Kumar static int virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
1273a29355aSViresh Kumar 			   u8 txvalue, u8 *rxvalue)
1283a29355aSViresh Kumar {
1293a29355aSViresh Kumar 	struct virtio_gpio_line *line = &vgpio->lines[gpio];
1303a29355aSViresh Kumar 	struct virtio_gpio_response *res = &line->res;
1313a29355aSViresh Kumar 
1323a29355aSViresh Kumar 	return _virtio_gpio_req(vgpio, type, gpio, txvalue, rxvalue, res,
1333a29355aSViresh Kumar 				sizeof(*res));
1343a29355aSViresh Kumar }
1353a29355aSViresh Kumar 
virtio_gpio_free(struct gpio_chip * gc,unsigned int gpio)1363a29355aSViresh Kumar static void virtio_gpio_free(struct gpio_chip *gc, unsigned int gpio)
1373a29355aSViresh Kumar {
1383a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
1393a29355aSViresh Kumar 
1403a29355aSViresh Kumar 	virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
1413a29355aSViresh Kumar 			VIRTIO_GPIO_DIRECTION_NONE, NULL);
1423a29355aSViresh Kumar }
1433a29355aSViresh Kumar 
virtio_gpio_get_direction(struct gpio_chip * gc,unsigned int gpio)1443a29355aSViresh Kumar static int virtio_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
1453a29355aSViresh Kumar {
1463a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
1473a29355aSViresh Kumar 	u8 direction;
1483a29355aSViresh Kumar 	int ret;
1493a29355aSViresh Kumar 
1503a29355aSViresh Kumar 	ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_DIRECTION, gpio, 0,
1513a29355aSViresh Kumar 			      &direction);
1523a29355aSViresh Kumar 	if (ret)
1533a29355aSViresh Kumar 		return ret;
1543a29355aSViresh Kumar 
1553a29355aSViresh Kumar 	switch (direction) {
1563a29355aSViresh Kumar 	case VIRTIO_GPIO_DIRECTION_IN:
1573a29355aSViresh Kumar 		return GPIO_LINE_DIRECTION_IN;
1583a29355aSViresh Kumar 	case VIRTIO_GPIO_DIRECTION_OUT:
1593a29355aSViresh Kumar 		return GPIO_LINE_DIRECTION_OUT;
1603a29355aSViresh Kumar 	default:
1613a29355aSViresh Kumar 		return -EINVAL;
1623a29355aSViresh Kumar 	}
1633a29355aSViresh Kumar }
1643a29355aSViresh Kumar 
virtio_gpio_direction_input(struct gpio_chip * gc,unsigned int gpio)1653a29355aSViresh Kumar static int virtio_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
1663a29355aSViresh Kumar {
1673a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
1683a29355aSViresh Kumar 
1693a29355aSViresh Kumar 	return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
1703a29355aSViresh Kumar 			       VIRTIO_GPIO_DIRECTION_IN, NULL);
1713a29355aSViresh Kumar }
1723a29355aSViresh Kumar 
virtio_gpio_direction_output(struct gpio_chip * gc,unsigned int gpio,int value)1733a29355aSViresh Kumar static int virtio_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
1743a29355aSViresh Kumar 					int value)
1753a29355aSViresh Kumar {
1763a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
1773a29355aSViresh Kumar 	int ret;
1783a29355aSViresh Kumar 
1793a29355aSViresh Kumar 	ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
1803a29355aSViresh Kumar 	if (ret)
1813a29355aSViresh Kumar 		return ret;
1823a29355aSViresh Kumar 
1833a29355aSViresh Kumar 	return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
1843a29355aSViresh Kumar 			       VIRTIO_GPIO_DIRECTION_OUT, NULL);
1853a29355aSViresh Kumar }
1863a29355aSViresh Kumar 
virtio_gpio_get(struct gpio_chip * gc,unsigned int gpio)1873a29355aSViresh Kumar static int virtio_gpio_get(struct gpio_chip *gc, unsigned int gpio)
1883a29355aSViresh Kumar {
1893a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
1903a29355aSViresh Kumar 	u8 value;
1913a29355aSViresh Kumar 	int ret;
1923a29355aSViresh Kumar 
1933a29355aSViresh Kumar 	ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_VALUE, gpio, 0, &value);
1943a29355aSViresh Kumar 	return ret ? ret : value;
1953a29355aSViresh Kumar }
1963a29355aSViresh Kumar 
virtio_gpio_set(struct gpio_chip * gc,unsigned int gpio,int value)1973a29355aSViresh Kumar static void virtio_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
1983a29355aSViresh Kumar {
1993a29355aSViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
2003a29355aSViresh Kumar 
2013a29355aSViresh Kumar 	virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
2023a29355aSViresh Kumar }
2033a29355aSViresh Kumar 
204eff5cdd7SViresh Kumar /* Interrupt handling */
virtio_gpio_irq_prepare(struct virtio_gpio * vgpio,u16 gpio)205eff5cdd7SViresh Kumar static void virtio_gpio_irq_prepare(struct virtio_gpio *vgpio, u16 gpio)
206eff5cdd7SViresh Kumar {
207eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[gpio];
208eff5cdd7SViresh Kumar 	struct virtio_gpio_irq_request *ireq = &irq_line->ireq;
209eff5cdd7SViresh Kumar 	struct virtio_gpio_irq_response *ires = &irq_line->ires;
210eff5cdd7SViresh Kumar 	struct scatterlist *sgs[2], req_sg, res_sg;
211eff5cdd7SViresh Kumar 	int ret;
212eff5cdd7SViresh Kumar 
213eff5cdd7SViresh Kumar 	if (WARN_ON(irq_line->queued || irq_line->masked || irq_line->disabled))
214eff5cdd7SViresh Kumar 		return;
215eff5cdd7SViresh Kumar 
216eff5cdd7SViresh Kumar 	ireq->gpio = cpu_to_le16(gpio);
217eff5cdd7SViresh Kumar 	sg_init_one(&req_sg, ireq, sizeof(*ireq));
218eff5cdd7SViresh Kumar 	sg_init_one(&res_sg, ires, sizeof(*ires));
219eff5cdd7SViresh Kumar 	sgs[0] = &req_sg;
220eff5cdd7SViresh Kumar 	sgs[1] = &res_sg;
221eff5cdd7SViresh Kumar 
222eff5cdd7SViresh Kumar 	ret = virtqueue_add_sgs(vgpio->event_vq, sgs, 1, 1, irq_line, GFP_ATOMIC);
223eff5cdd7SViresh Kumar 	if (ret) {
224eff5cdd7SViresh Kumar 		dev_err(&vgpio->vdev->dev, "failed to add request to eventq\n");
225eff5cdd7SViresh Kumar 		return;
226eff5cdd7SViresh Kumar 	}
227eff5cdd7SViresh Kumar 
228eff5cdd7SViresh Kumar 	irq_line->queued = true;
229eff5cdd7SViresh Kumar 	virtqueue_kick(vgpio->event_vq);
230eff5cdd7SViresh Kumar }
231eff5cdd7SViresh Kumar 
virtio_gpio_irq_enable(struct irq_data * d)232eff5cdd7SViresh Kumar static void virtio_gpio_irq_enable(struct irq_data *d)
233eff5cdd7SViresh Kumar {
234eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
235eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
236eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
237eff5cdd7SViresh Kumar 
238eff5cdd7SViresh Kumar 	raw_spin_lock(&vgpio->eventq_lock);
239eff5cdd7SViresh Kumar 	irq_line->disabled = false;
240eff5cdd7SViresh Kumar 	irq_line->masked = false;
241eff5cdd7SViresh Kumar 	irq_line->queue_pending = true;
242eff5cdd7SViresh Kumar 	raw_spin_unlock(&vgpio->eventq_lock);
243eff5cdd7SViresh Kumar 
244eff5cdd7SViresh Kumar 	irq_line->update_pending = true;
245eff5cdd7SViresh Kumar }
246eff5cdd7SViresh Kumar 
virtio_gpio_irq_disable(struct irq_data * d)247eff5cdd7SViresh Kumar static void virtio_gpio_irq_disable(struct irq_data *d)
248eff5cdd7SViresh Kumar {
249eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
250eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
251eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
252eff5cdd7SViresh Kumar 
253eff5cdd7SViresh Kumar 	raw_spin_lock(&vgpio->eventq_lock);
254eff5cdd7SViresh Kumar 	irq_line->disabled = true;
255eff5cdd7SViresh Kumar 	irq_line->masked = true;
256eff5cdd7SViresh Kumar 	irq_line->queue_pending = false;
257eff5cdd7SViresh Kumar 	raw_spin_unlock(&vgpio->eventq_lock);
258eff5cdd7SViresh Kumar 
259eff5cdd7SViresh Kumar 	irq_line->update_pending = true;
260eff5cdd7SViresh Kumar }
261eff5cdd7SViresh Kumar 
virtio_gpio_irq_mask(struct irq_data * d)262eff5cdd7SViresh Kumar static void virtio_gpio_irq_mask(struct irq_data *d)
263eff5cdd7SViresh Kumar {
264eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
265eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
266eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
267eff5cdd7SViresh Kumar 
268eff5cdd7SViresh Kumar 	raw_spin_lock(&vgpio->eventq_lock);
269eff5cdd7SViresh Kumar 	irq_line->masked = true;
270eff5cdd7SViresh Kumar 	raw_spin_unlock(&vgpio->eventq_lock);
271eff5cdd7SViresh Kumar }
272eff5cdd7SViresh Kumar 
virtio_gpio_irq_unmask(struct irq_data * d)273eff5cdd7SViresh Kumar static void virtio_gpio_irq_unmask(struct irq_data *d)
274eff5cdd7SViresh Kumar {
275eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
276eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
277eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
278eff5cdd7SViresh Kumar 
279eff5cdd7SViresh Kumar 	raw_spin_lock(&vgpio->eventq_lock);
280eff5cdd7SViresh Kumar 	irq_line->masked = false;
281eff5cdd7SViresh Kumar 
282eff5cdd7SViresh Kumar 	/* Queue the buffer unconditionally on unmask */
283eff5cdd7SViresh Kumar 	virtio_gpio_irq_prepare(vgpio, d->hwirq);
284eff5cdd7SViresh Kumar 	raw_spin_unlock(&vgpio->eventq_lock);
285eff5cdd7SViresh Kumar }
286eff5cdd7SViresh Kumar 
virtio_gpio_irq_set_type(struct irq_data * d,unsigned int type)287eff5cdd7SViresh Kumar static int virtio_gpio_irq_set_type(struct irq_data *d, unsigned int type)
288eff5cdd7SViresh Kumar {
289eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
290eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
291eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
292eff5cdd7SViresh Kumar 
293eff5cdd7SViresh Kumar 	switch (type) {
294eff5cdd7SViresh Kumar 	case IRQ_TYPE_EDGE_RISING:
295eff5cdd7SViresh Kumar 		type = VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING;
296eff5cdd7SViresh Kumar 		break;
297eff5cdd7SViresh Kumar 	case IRQ_TYPE_EDGE_FALLING:
298eff5cdd7SViresh Kumar 		type = VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING;
299eff5cdd7SViresh Kumar 		break;
300eff5cdd7SViresh Kumar 	case IRQ_TYPE_EDGE_BOTH:
301eff5cdd7SViresh Kumar 		type = VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH;
302eff5cdd7SViresh Kumar 		break;
303eff5cdd7SViresh Kumar 	case IRQ_TYPE_LEVEL_LOW:
304eff5cdd7SViresh Kumar 		type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW;
305eff5cdd7SViresh Kumar 		break;
306eff5cdd7SViresh Kumar 	case IRQ_TYPE_LEVEL_HIGH:
307eff5cdd7SViresh Kumar 		type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH;
308eff5cdd7SViresh Kumar 		break;
309eff5cdd7SViresh Kumar 	default:
310eff5cdd7SViresh Kumar 		dev_err(&vgpio->vdev->dev, "unsupported irq type: %u\n", type);
311eff5cdd7SViresh Kumar 		return -EINVAL;
312eff5cdd7SViresh Kumar 	}
313eff5cdd7SViresh Kumar 
314eff5cdd7SViresh Kumar 	irq_line->type = type;
315eff5cdd7SViresh Kumar 	irq_line->update_pending = true;
316eff5cdd7SViresh Kumar 
317eff5cdd7SViresh Kumar 	return 0;
318eff5cdd7SViresh Kumar }
319eff5cdd7SViresh Kumar 
virtio_gpio_irq_bus_lock(struct irq_data * d)320eff5cdd7SViresh Kumar static void virtio_gpio_irq_bus_lock(struct irq_data *d)
321eff5cdd7SViresh Kumar {
322eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
323eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
324eff5cdd7SViresh Kumar 
325eff5cdd7SViresh Kumar 	mutex_lock(&vgpio->irq_lock);
326eff5cdd7SViresh Kumar }
327eff5cdd7SViresh Kumar 
virtio_gpio_irq_bus_sync_unlock(struct irq_data * d)328eff5cdd7SViresh Kumar static void virtio_gpio_irq_bus_sync_unlock(struct irq_data *d)
329eff5cdd7SViresh Kumar {
330eff5cdd7SViresh Kumar 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
331eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = gpiochip_get_data(gc);
332eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
333eff5cdd7SViresh Kumar 	u8 type = irq_line->disabled ? VIRTIO_GPIO_IRQ_TYPE_NONE : irq_line->type;
334eff5cdd7SViresh Kumar 	unsigned long flags;
335eff5cdd7SViresh Kumar 
336eff5cdd7SViresh Kumar 	if (irq_line->update_pending) {
337eff5cdd7SViresh Kumar 		irq_line->update_pending = false;
338eff5cdd7SViresh Kumar 		virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_IRQ_TYPE, d->hwirq, type,
339eff5cdd7SViresh Kumar 				NULL);
340eff5cdd7SViresh Kumar 
341eff5cdd7SViresh Kumar 		/* Queue the buffer only after interrupt is enabled */
342eff5cdd7SViresh Kumar 		raw_spin_lock_irqsave(&vgpio->eventq_lock, flags);
343eff5cdd7SViresh Kumar 		if (irq_line->queue_pending) {
344eff5cdd7SViresh Kumar 			irq_line->queue_pending = false;
345eff5cdd7SViresh Kumar 			virtio_gpio_irq_prepare(vgpio, d->hwirq);
346eff5cdd7SViresh Kumar 		}
347eff5cdd7SViresh Kumar 		raw_spin_unlock_irqrestore(&vgpio->eventq_lock, flags);
348eff5cdd7SViresh Kumar 	}
349eff5cdd7SViresh Kumar 
350eff5cdd7SViresh Kumar 	mutex_unlock(&vgpio->irq_lock);
351eff5cdd7SViresh Kumar }
352eff5cdd7SViresh Kumar 
353eff5cdd7SViresh Kumar static struct irq_chip vgpio_irq_chip = {
354eff5cdd7SViresh Kumar 	.name			= "virtio-gpio",
355eff5cdd7SViresh Kumar 	.irq_enable		= virtio_gpio_irq_enable,
356eff5cdd7SViresh Kumar 	.irq_disable		= virtio_gpio_irq_disable,
357eff5cdd7SViresh Kumar 	.irq_mask		= virtio_gpio_irq_mask,
358eff5cdd7SViresh Kumar 	.irq_unmask		= virtio_gpio_irq_unmask,
359eff5cdd7SViresh Kumar 	.irq_set_type		= virtio_gpio_irq_set_type,
360eff5cdd7SViresh Kumar 
361eff5cdd7SViresh Kumar 	/* These are required to implement irqchip for slow busses */
362eff5cdd7SViresh Kumar 	.irq_bus_lock		= virtio_gpio_irq_bus_lock,
363eff5cdd7SViresh Kumar 	.irq_bus_sync_unlock	= virtio_gpio_irq_bus_sync_unlock,
364eff5cdd7SViresh Kumar };
365eff5cdd7SViresh Kumar 
ignore_irq(struct virtio_gpio * vgpio,int gpio,struct vgpio_irq_line * irq_line)366eff5cdd7SViresh Kumar static bool ignore_irq(struct virtio_gpio *vgpio, int gpio,
367eff5cdd7SViresh Kumar 		       struct vgpio_irq_line *irq_line)
368eff5cdd7SViresh Kumar {
369eff5cdd7SViresh Kumar 	bool ignore = false;
370eff5cdd7SViresh Kumar 
371eff5cdd7SViresh Kumar 	raw_spin_lock(&vgpio->eventq_lock);
372eff5cdd7SViresh Kumar 	irq_line->queued = false;
373eff5cdd7SViresh Kumar 
374eff5cdd7SViresh Kumar 	/* Interrupt is disabled currently */
375eff5cdd7SViresh Kumar 	if (irq_line->masked || irq_line->disabled) {
376eff5cdd7SViresh Kumar 		ignore = true;
377eff5cdd7SViresh Kumar 		goto unlock;
378eff5cdd7SViresh Kumar 	}
379eff5cdd7SViresh Kumar 
380eff5cdd7SViresh Kumar 	/*
381eff5cdd7SViresh Kumar 	 * Buffer is returned as the interrupt was disabled earlier, but is
382eff5cdd7SViresh Kumar 	 * enabled again now. Requeue the buffers.
383eff5cdd7SViresh Kumar 	 */
384eff5cdd7SViresh Kumar 	if (irq_line->ires.status == VIRTIO_GPIO_IRQ_STATUS_INVALID) {
385eff5cdd7SViresh Kumar 		virtio_gpio_irq_prepare(vgpio, gpio);
386eff5cdd7SViresh Kumar 		ignore = true;
387eff5cdd7SViresh Kumar 		goto unlock;
388eff5cdd7SViresh Kumar 	}
389eff5cdd7SViresh Kumar 
390eff5cdd7SViresh Kumar 	if (WARN_ON(irq_line->ires.status != VIRTIO_GPIO_IRQ_STATUS_VALID))
391eff5cdd7SViresh Kumar 		ignore = true;
392eff5cdd7SViresh Kumar 
393eff5cdd7SViresh Kumar unlock:
394eff5cdd7SViresh Kumar 	raw_spin_unlock(&vgpio->eventq_lock);
395eff5cdd7SViresh Kumar 
396eff5cdd7SViresh Kumar 	return ignore;
397eff5cdd7SViresh Kumar }
398eff5cdd7SViresh Kumar 
virtio_gpio_event_vq(struct virtqueue * vq)399eff5cdd7SViresh Kumar static void virtio_gpio_event_vq(struct virtqueue *vq)
400eff5cdd7SViresh Kumar {
401eff5cdd7SViresh Kumar 	struct virtio_gpio *vgpio = vq->vdev->priv;
402eff5cdd7SViresh Kumar 	struct device *dev = &vgpio->vdev->dev;
403eff5cdd7SViresh Kumar 	struct vgpio_irq_line *irq_line;
404eff5cdd7SViresh Kumar 	int gpio, ret;
405eff5cdd7SViresh Kumar 	unsigned int len;
406eff5cdd7SViresh Kumar 
407eff5cdd7SViresh Kumar 	while (true) {
408eff5cdd7SViresh Kumar 		irq_line = virtqueue_get_buf(vgpio->event_vq, &len);
409eff5cdd7SViresh Kumar 		if (!irq_line)
410eff5cdd7SViresh Kumar 			break;
411eff5cdd7SViresh Kumar 
412eff5cdd7SViresh Kumar 		if (len != sizeof(irq_line->ires)) {
413eff5cdd7SViresh Kumar 			dev_err(dev, "irq with incorrect length (%u : %u)\n",
414eff5cdd7SViresh Kumar 				len, (unsigned int)sizeof(irq_line->ires));
415eff5cdd7SViresh Kumar 			continue;
416eff5cdd7SViresh Kumar 		}
417eff5cdd7SViresh Kumar 
418eff5cdd7SViresh Kumar 		/*
419eff5cdd7SViresh Kumar 		 * Find GPIO line number from the offset of irq_line within the
420eff5cdd7SViresh Kumar 		 * irq_lines block. We can also get GPIO number from
421eff5cdd7SViresh Kumar 		 * irq-request, but better not to rely on a buffer returned by
422eff5cdd7SViresh Kumar 		 * remote.
423eff5cdd7SViresh Kumar 		 */
424eff5cdd7SViresh Kumar 		gpio = irq_line - vgpio->irq_lines;
425eff5cdd7SViresh Kumar 		WARN_ON(gpio >= vgpio->gc.ngpio);
426eff5cdd7SViresh Kumar 
427eff5cdd7SViresh Kumar 		if (unlikely(ignore_irq(vgpio, gpio, irq_line)))
428eff5cdd7SViresh Kumar 			continue;
429eff5cdd7SViresh Kumar 
430eff5cdd7SViresh Kumar 		ret = generic_handle_domain_irq(vgpio->gc.irq.domain, gpio);
431eff5cdd7SViresh Kumar 		if (ret)
432eff5cdd7SViresh Kumar 			dev_err(dev, "failed to handle interrupt: %d\n", ret);
433f7715b3aSYang Li 	}
434eff5cdd7SViresh Kumar }
435eff5cdd7SViresh Kumar 
virtio_gpio_request_vq(struct virtqueue * vq)4363a29355aSViresh Kumar static void virtio_gpio_request_vq(struct virtqueue *vq)
4373a29355aSViresh Kumar {
4383a29355aSViresh Kumar 	struct virtio_gpio_line *line;
4393a29355aSViresh Kumar 	unsigned int len;
4403a29355aSViresh Kumar 
4413a29355aSViresh Kumar 	do {
4423a29355aSViresh Kumar 		line = virtqueue_get_buf(vq, &len);
4433a29355aSViresh Kumar 		if (!line)
4443a29355aSViresh Kumar 			return;
4453a29355aSViresh Kumar 
4463a29355aSViresh Kumar 		line->rxlen = len;
4473a29355aSViresh Kumar 		complete(&line->completion);
4483a29355aSViresh Kumar 	} while (1);
4493a29355aSViresh Kumar }
4503a29355aSViresh Kumar 
virtio_gpio_free_vqs(struct virtio_device * vdev)4513a29355aSViresh Kumar static void virtio_gpio_free_vqs(struct virtio_device *vdev)
4523a29355aSViresh Kumar {
453d9679d00SMichael S. Tsirkin 	virtio_reset_device(vdev);
4543a29355aSViresh Kumar 	vdev->config->del_vqs(vdev);
4553a29355aSViresh Kumar }
4563a29355aSViresh Kumar 
virtio_gpio_alloc_vqs(struct virtio_gpio * vgpio,struct virtio_device * vdev)4573a29355aSViresh Kumar static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio,
4583a29355aSViresh Kumar 				 struct virtio_device *vdev)
4593a29355aSViresh Kumar {
460c95e67baSJiri Pirko 	struct virtqueue_info vqs_info[] = {
461c95e67baSJiri Pirko 		{ "requestq", virtio_gpio_request_vq },
462c95e67baSJiri Pirko 		{ "eventq", virtio_gpio_event_vq },
4633a29355aSViresh Kumar 	};
464eff5cdd7SViresh Kumar 	struct virtqueue *vqs[2] = { NULL, NULL };
4653a29355aSViresh Kumar 	int ret;
4663a29355aSViresh Kumar 
467*6c85d6b6SJiri Pirko 	ret = virtio_find_vqs(vdev, vgpio->irq_lines ? 2 : 1, vqs,
468c95e67baSJiri Pirko 			      vqs_info, NULL);
4693a29355aSViresh Kumar 	if (ret) {
4703a29355aSViresh Kumar 		dev_err(&vdev->dev, "failed to find vqs: %d\n", ret);
4713a29355aSViresh Kumar 		return ret;
4723a29355aSViresh Kumar 	}
4733a29355aSViresh Kumar 
4743a29355aSViresh Kumar 	if (!vqs[0]) {
4753a29355aSViresh Kumar 		dev_err(&vdev->dev, "failed to find requestq vq\n");
476eff5cdd7SViresh Kumar 		goto out;
4773a29355aSViresh Kumar 	}
4783a29355aSViresh Kumar 	vgpio->request_vq = vqs[0];
4793a29355aSViresh Kumar 
480eff5cdd7SViresh Kumar 	if (vgpio->irq_lines && !vqs[1]) {
481eff5cdd7SViresh Kumar 		dev_err(&vdev->dev, "failed to find eventq vq\n");
482eff5cdd7SViresh Kumar 		goto out;
483eff5cdd7SViresh Kumar 	}
484eff5cdd7SViresh Kumar 	vgpio->event_vq = vqs[1];
485eff5cdd7SViresh Kumar 
4863a29355aSViresh Kumar 	return 0;
487eff5cdd7SViresh Kumar 
488eff5cdd7SViresh Kumar out:
489eff5cdd7SViresh Kumar 	if (vqs[0] || vqs[1])
490eff5cdd7SViresh Kumar 		virtio_gpio_free_vqs(vdev);
491eff5cdd7SViresh Kumar 
492eff5cdd7SViresh Kumar 	return -ENODEV;
4933a29355aSViresh Kumar }
4943a29355aSViresh Kumar 
virtio_gpio_get_names(struct virtio_gpio * vgpio,u32 gpio_names_size,u16 ngpio)49517395d77SViresh Kumar static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
49617395d77SViresh Kumar 					  u32 gpio_names_size, u16 ngpio)
4973a29355aSViresh Kumar {
4983a29355aSViresh Kumar 	struct virtio_gpio_response_get_names *res;
4993a29355aSViresh Kumar 	struct device *dev = &vgpio->vdev->dev;
5003a29355aSViresh Kumar 	u8 *gpio_names, *str;
5013a29355aSViresh Kumar 	const char **names;
5023a29355aSViresh Kumar 	int i, ret, len;
5033a29355aSViresh Kumar 
50417395d77SViresh Kumar 	if (!gpio_names_size)
5053a29355aSViresh Kumar 		return NULL;
5063a29355aSViresh Kumar 
50717395d77SViresh Kumar 	len = sizeof(*res) + gpio_names_size;
5083a29355aSViresh Kumar 	res = devm_kzalloc(dev, len, GFP_KERNEL);
5093a29355aSViresh Kumar 	if (!res)
5103a29355aSViresh Kumar 		return NULL;
5113a29355aSViresh Kumar 	gpio_names = res->value;
5123a29355aSViresh Kumar 
5133a29355aSViresh Kumar 	ret = _virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_NAMES, 0, 0, NULL,
5143a29355aSViresh Kumar 			       res, len);
5153a29355aSViresh Kumar 	if (ret) {
5163a29355aSViresh Kumar 		dev_err(dev, "Failed to get GPIO names: %d\n", ret);
5173a29355aSViresh Kumar 		return NULL;
5183a29355aSViresh Kumar 	}
5193a29355aSViresh Kumar 
52017395d77SViresh Kumar 	names = devm_kcalloc(dev, ngpio, sizeof(*names), GFP_KERNEL);
5213a29355aSViresh Kumar 	if (!names)
5223a29355aSViresh Kumar 		return NULL;
5233a29355aSViresh Kumar 
5243a29355aSViresh Kumar 	/* NULL terminate the string instead of checking it */
52517395d77SViresh Kumar 	gpio_names[gpio_names_size - 1] = '\0';
5263a29355aSViresh Kumar 
52717395d77SViresh Kumar 	for (i = 0, str = gpio_names; i < ngpio; i++) {
5283a29355aSViresh Kumar 		names[i] = str;
5293a29355aSViresh Kumar 		str += strlen(str) + 1; /* zero-length strings are allowed */
5303a29355aSViresh Kumar 
53117395d77SViresh Kumar 		if (str > gpio_names + gpio_names_size) {
5323a29355aSViresh Kumar 			dev_err(dev, "gpio_names block is too short (%d)\n", i);
5333a29355aSViresh Kumar 			return NULL;
5343a29355aSViresh Kumar 		}
5353a29355aSViresh Kumar 	}
5363a29355aSViresh Kumar 
5373a29355aSViresh Kumar 	return names;
5383a29355aSViresh Kumar }
5393a29355aSViresh Kumar 
virtio_gpio_probe(struct virtio_device * vdev)5403a29355aSViresh Kumar static int virtio_gpio_probe(struct virtio_device *vdev)
5413a29355aSViresh Kumar {
54217395d77SViresh Kumar 	struct virtio_gpio_config config;
5433a29355aSViresh Kumar 	struct device *dev = &vdev->dev;
5443a29355aSViresh Kumar 	struct virtio_gpio *vgpio;
54517395d77SViresh Kumar 	u32 gpio_names_size;
54617395d77SViresh Kumar 	u16 ngpio;
5473a29355aSViresh Kumar 	int ret, i;
5483a29355aSViresh Kumar 
5493a29355aSViresh Kumar 	vgpio = devm_kzalloc(dev, sizeof(*vgpio), GFP_KERNEL);
5503a29355aSViresh Kumar 	if (!vgpio)
5513a29355aSViresh Kumar 		return -ENOMEM;
5523a29355aSViresh Kumar 
5533a29355aSViresh Kumar 	/* Read configuration */
55417395d77SViresh Kumar 	virtio_cread_bytes(vdev, 0, &config, sizeof(config));
55517395d77SViresh Kumar 	gpio_names_size = le32_to_cpu(config.gpio_names_size);
55617395d77SViresh Kumar 	ngpio = le16_to_cpu(config.ngpio);
55717395d77SViresh Kumar 	if (!ngpio) {
5583a29355aSViresh Kumar 		dev_err(dev, "Number of GPIOs can't be zero\n");
5593a29355aSViresh Kumar 		return -EINVAL;
5603a29355aSViresh Kumar 	}
5613a29355aSViresh Kumar 
56217395d77SViresh Kumar 	vgpio->lines = devm_kcalloc(dev, ngpio, sizeof(*vgpio->lines), GFP_KERNEL);
5633a29355aSViresh Kumar 	if (!vgpio->lines)
5643a29355aSViresh Kumar 		return -ENOMEM;
5653a29355aSViresh Kumar 
56617395d77SViresh Kumar 	for (i = 0; i < ngpio; i++) {
5673a29355aSViresh Kumar 		mutex_init(&vgpio->lines[i].lock);
5683a29355aSViresh Kumar 		init_completion(&vgpio->lines[i].completion);
5693a29355aSViresh Kumar 	}
5703a29355aSViresh Kumar 
5713a29355aSViresh Kumar 	mutex_init(&vgpio->lock);
5723a29355aSViresh Kumar 	vdev->priv = vgpio;
5733a29355aSViresh Kumar 
5743a29355aSViresh Kumar 	vgpio->vdev			= vdev;
5753a29355aSViresh Kumar 	vgpio->gc.free			= virtio_gpio_free;
5763a29355aSViresh Kumar 	vgpio->gc.get_direction		= virtio_gpio_get_direction;
5773a29355aSViresh Kumar 	vgpio->gc.direction_input	= virtio_gpio_direction_input;
5783a29355aSViresh Kumar 	vgpio->gc.direction_output	= virtio_gpio_direction_output;
5793a29355aSViresh Kumar 	vgpio->gc.get			= virtio_gpio_get;
5803a29355aSViresh Kumar 	vgpio->gc.set			= virtio_gpio_set;
58117395d77SViresh Kumar 	vgpio->gc.ngpio			= ngpio;
5823a29355aSViresh Kumar 	vgpio->gc.base			= -1; /* Allocate base dynamically */
5833a29355aSViresh Kumar 	vgpio->gc.label			= dev_name(dev);
5843a29355aSViresh Kumar 	vgpio->gc.parent		= dev;
5853a29355aSViresh Kumar 	vgpio->gc.owner			= THIS_MODULE;
5863a29355aSViresh Kumar 	vgpio->gc.can_sleep		= true;
5873a29355aSViresh Kumar 
588eff5cdd7SViresh Kumar 	/* Interrupt support */
589eff5cdd7SViresh Kumar 	if (virtio_has_feature(vdev, VIRTIO_GPIO_F_IRQ)) {
590eff5cdd7SViresh Kumar 		vgpio->irq_lines = devm_kcalloc(dev, ngpio, sizeof(*vgpio->irq_lines), GFP_KERNEL);
591eff5cdd7SViresh Kumar 		if (!vgpio->irq_lines)
592eff5cdd7SViresh Kumar 			return -ENOMEM;
593eff5cdd7SViresh Kumar 
594eff5cdd7SViresh Kumar 		/* The event comes from the outside so no parent handler */
595eff5cdd7SViresh Kumar 		vgpio->gc.irq.parent_handler	= NULL;
596eff5cdd7SViresh Kumar 		vgpio->gc.irq.num_parents	= 0;
597eff5cdd7SViresh Kumar 		vgpio->gc.irq.parents		= NULL;
598eff5cdd7SViresh Kumar 		vgpio->gc.irq.default_type	= IRQ_TYPE_NONE;
599eff5cdd7SViresh Kumar 		vgpio->gc.irq.handler		= handle_level_irq;
600eff5cdd7SViresh Kumar 		vgpio->gc.irq.chip		= &vgpio_irq_chip;
601eff5cdd7SViresh Kumar 
602eff5cdd7SViresh Kumar 		for (i = 0; i < ngpio; i++) {
603eff5cdd7SViresh Kumar 			vgpio->irq_lines[i].type = VIRTIO_GPIO_IRQ_TYPE_NONE;
604eff5cdd7SViresh Kumar 			vgpio->irq_lines[i].disabled = true;
605eff5cdd7SViresh Kumar 			vgpio->irq_lines[i].masked = true;
606eff5cdd7SViresh Kumar 		}
607eff5cdd7SViresh Kumar 
608eff5cdd7SViresh Kumar 		mutex_init(&vgpio->irq_lock);
609eff5cdd7SViresh Kumar 		raw_spin_lock_init(&vgpio->eventq_lock);
610eff5cdd7SViresh Kumar 	}
611eff5cdd7SViresh Kumar 
6123a29355aSViresh Kumar 	ret = virtio_gpio_alloc_vqs(vgpio, vdev);
6133a29355aSViresh Kumar 	if (ret)
6143a29355aSViresh Kumar 		return ret;
6153a29355aSViresh Kumar 
6163a29355aSViresh Kumar 	/* Mark the device ready to perform operations from within probe() */
6173a29355aSViresh Kumar 	virtio_device_ready(vdev);
6183a29355aSViresh Kumar 
61917395d77SViresh Kumar 	vgpio->gc.names = virtio_gpio_get_names(vgpio, gpio_names_size, ngpio);
6203a29355aSViresh Kumar 
6213a29355aSViresh Kumar 	ret = gpiochip_add_data(&vgpio->gc, vgpio);
6223a29355aSViresh Kumar 	if (ret) {
6233a29355aSViresh Kumar 		virtio_gpio_free_vqs(vdev);
6243a29355aSViresh Kumar 		dev_err(dev, "Failed to add virtio-gpio controller\n");
6253a29355aSViresh Kumar 	}
6263a29355aSViresh Kumar 
6273a29355aSViresh Kumar 	return ret;
6283a29355aSViresh Kumar }
6293a29355aSViresh Kumar 
virtio_gpio_remove(struct virtio_device * vdev)6303a29355aSViresh Kumar static void virtio_gpio_remove(struct virtio_device *vdev)
6313a29355aSViresh Kumar {
6323a29355aSViresh Kumar 	struct virtio_gpio *vgpio = vdev->priv;
6333a29355aSViresh Kumar 
6343a29355aSViresh Kumar 	gpiochip_remove(&vgpio->gc);
6353a29355aSViresh Kumar 	virtio_gpio_free_vqs(vdev);
6363a29355aSViresh Kumar }
6373a29355aSViresh Kumar 
6383a29355aSViresh Kumar static const struct virtio_device_id id_table[] = {
6393a29355aSViresh Kumar 	{ VIRTIO_ID_GPIO, VIRTIO_DEV_ANY_ID },
6403a29355aSViresh Kumar 	{},
6413a29355aSViresh Kumar };
6423a29355aSViresh Kumar MODULE_DEVICE_TABLE(virtio, id_table);
6433a29355aSViresh Kumar 
644eff5cdd7SViresh Kumar static const unsigned int features[] = {
645eff5cdd7SViresh Kumar 	VIRTIO_GPIO_F_IRQ,
646eff5cdd7SViresh Kumar };
647eff5cdd7SViresh Kumar 
6483a29355aSViresh Kumar static struct virtio_driver virtio_gpio_driver = {
649eff5cdd7SViresh Kumar 	.feature_table		= features,
650eff5cdd7SViresh Kumar 	.feature_table_size	= ARRAY_SIZE(features),
6513a29355aSViresh Kumar 	.id_table		= id_table,
6523a29355aSViresh Kumar 	.probe			= virtio_gpio_probe,
6533a29355aSViresh Kumar 	.remove			= virtio_gpio_remove,
6543a29355aSViresh Kumar 	.driver			= {
6553a29355aSViresh Kumar 		.name		= KBUILD_MODNAME,
6563a29355aSViresh Kumar 	},
6573a29355aSViresh Kumar };
6583a29355aSViresh Kumar module_virtio_driver(virtio_gpio_driver);
6593a29355aSViresh Kumar 
6603a29355aSViresh Kumar MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
6613a29355aSViresh Kumar MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
6623a29355aSViresh Kumar MODULE_DESCRIPTION("VirtIO GPIO driver");
6633a29355aSViresh Kumar MODULE_LICENSE("GPL");
664