1*3a29355aSViresh Kumar // SPDX-License-Identifier: GPL-2.0+ 2*3a29355aSViresh Kumar /* 3*3a29355aSViresh Kumar * GPIO driver for virtio-based virtual GPIO controllers 4*3a29355aSViresh Kumar * 5*3a29355aSViresh Kumar * Copyright (C) 2021 metux IT consult 6*3a29355aSViresh Kumar * Enrico Weigelt, metux IT consult <info@metux.net> 7*3a29355aSViresh Kumar * 8*3a29355aSViresh Kumar * Copyright (C) 2021 Linaro. 9*3a29355aSViresh Kumar * Viresh Kumar <viresh.kumar@linaro.org> 10*3a29355aSViresh Kumar */ 11*3a29355aSViresh Kumar 12*3a29355aSViresh Kumar #include <linux/completion.h> 13*3a29355aSViresh Kumar #include <linux/err.h> 14*3a29355aSViresh Kumar #include <linux/gpio/driver.h> 15*3a29355aSViresh Kumar #include <linux/io.h> 16*3a29355aSViresh Kumar #include <linux/kernel.h> 17*3a29355aSViresh Kumar #include <linux/module.h> 18*3a29355aSViresh Kumar #include <linux/mutex.h> 19*3a29355aSViresh Kumar #include <linux/virtio_config.h> 20*3a29355aSViresh Kumar #include <uapi/linux/virtio_gpio.h> 21*3a29355aSViresh Kumar #include <uapi/linux/virtio_ids.h> 22*3a29355aSViresh Kumar 23*3a29355aSViresh Kumar struct virtio_gpio_line { 24*3a29355aSViresh Kumar struct mutex lock; /* Protects line operation */ 25*3a29355aSViresh Kumar struct completion completion; 26*3a29355aSViresh Kumar struct virtio_gpio_request req ____cacheline_aligned; 27*3a29355aSViresh Kumar struct virtio_gpio_response res ____cacheline_aligned; 28*3a29355aSViresh Kumar unsigned int rxlen; 29*3a29355aSViresh Kumar }; 30*3a29355aSViresh Kumar 31*3a29355aSViresh Kumar struct virtio_gpio { 32*3a29355aSViresh Kumar struct virtio_device *vdev; 33*3a29355aSViresh Kumar struct mutex lock; /* Protects virtqueue operation */ 34*3a29355aSViresh Kumar struct gpio_chip gc; 35*3a29355aSViresh Kumar struct virtio_gpio_config config; 36*3a29355aSViresh Kumar struct virtio_gpio_line *lines; 37*3a29355aSViresh Kumar struct virtqueue *request_vq; 38*3a29355aSViresh Kumar }; 39*3a29355aSViresh Kumar 40*3a29355aSViresh Kumar static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio, 41*3a29355aSViresh Kumar u8 txvalue, u8 *rxvalue, void *response, u32 rxlen) 42*3a29355aSViresh Kumar { 43*3a29355aSViresh Kumar struct virtio_gpio_line *line = &vgpio->lines[gpio]; 44*3a29355aSViresh Kumar struct virtio_gpio_request *req = &line->req; 45*3a29355aSViresh Kumar struct virtio_gpio_response *res = response; 46*3a29355aSViresh Kumar struct scatterlist *sgs[2], req_sg, res_sg; 47*3a29355aSViresh Kumar struct device *dev = &vgpio->vdev->dev; 48*3a29355aSViresh Kumar int ret; 49*3a29355aSViresh Kumar 50*3a29355aSViresh Kumar /* 51*3a29355aSViresh Kumar * Prevent concurrent requests for the same line since we have 52*3a29355aSViresh Kumar * pre-allocated request/response buffers for each GPIO line. Moreover 53*3a29355aSViresh Kumar * Linux always accesses a GPIO line sequentially, so this locking shall 54*3a29355aSViresh Kumar * always go through without any delays. 55*3a29355aSViresh Kumar */ 56*3a29355aSViresh Kumar mutex_lock(&line->lock); 57*3a29355aSViresh Kumar 58*3a29355aSViresh Kumar req->type = cpu_to_le16(type); 59*3a29355aSViresh Kumar req->gpio = cpu_to_le16(gpio); 60*3a29355aSViresh Kumar req->value = txvalue; 61*3a29355aSViresh Kumar 62*3a29355aSViresh Kumar sg_init_one(&req_sg, req, sizeof(*req)); 63*3a29355aSViresh Kumar sg_init_one(&res_sg, res, rxlen); 64*3a29355aSViresh Kumar sgs[0] = &req_sg; 65*3a29355aSViresh Kumar sgs[1] = &res_sg; 66*3a29355aSViresh Kumar 67*3a29355aSViresh Kumar line->rxlen = 0; 68*3a29355aSViresh Kumar reinit_completion(&line->completion); 69*3a29355aSViresh Kumar 70*3a29355aSViresh Kumar /* 71*3a29355aSViresh Kumar * Virtqueue callers need to ensure they don't call its APIs with other 72*3a29355aSViresh Kumar * virtqueue operations at the same time. 73*3a29355aSViresh Kumar */ 74*3a29355aSViresh Kumar mutex_lock(&vgpio->lock); 75*3a29355aSViresh Kumar ret = virtqueue_add_sgs(vgpio->request_vq, sgs, 1, 1, line, GFP_KERNEL); 76*3a29355aSViresh Kumar if (ret) { 77*3a29355aSViresh Kumar dev_err(dev, "failed to add request to vq\n"); 78*3a29355aSViresh Kumar mutex_unlock(&vgpio->lock); 79*3a29355aSViresh Kumar goto out; 80*3a29355aSViresh Kumar } 81*3a29355aSViresh Kumar 82*3a29355aSViresh Kumar virtqueue_kick(vgpio->request_vq); 83*3a29355aSViresh Kumar mutex_unlock(&vgpio->lock); 84*3a29355aSViresh Kumar 85*3a29355aSViresh Kumar if (!wait_for_completion_timeout(&line->completion, HZ)) { 86*3a29355aSViresh Kumar dev_err(dev, "GPIO operation timed out\n"); 87*3a29355aSViresh Kumar ret = -ETIMEDOUT; 88*3a29355aSViresh Kumar goto out; 89*3a29355aSViresh Kumar } 90*3a29355aSViresh Kumar 91*3a29355aSViresh Kumar if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) { 92*3a29355aSViresh Kumar dev_err(dev, "GPIO request failed: %d\n", gpio); 93*3a29355aSViresh Kumar ret = -EINVAL; 94*3a29355aSViresh Kumar goto out; 95*3a29355aSViresh Kumar } 96*3a29355aSViresh Kumar 97*3a29355aSViresh Kumar if (unlikely(line->rxlen != rxlen)) { 98*3a29355aSViresh Kumar dev_err(dev, "GPIO operation returned incorrect len (%u : %u)\n", 99*3a29355aSViresh Kumar rxlen, line->rxlen); 100*3a29355aSViresh Kumar ret = -EINVAL; 101*3a29355aSViresh Kumar goto out; 102*3a29355aSViresh Kumar } 103*3a29355aSViresh Kumar 104*3a29355aSViresh Kumar if (rxvalue) 105*3a29355aSViresh Kumar *rxvalue = res->value; 106*3a29355aSViresh Kumar 107*3a29355aSViresh Kumar out: 108*3a29355aSViresh Kumar mutex_unlock(&line->lock); 109*3a29355aSViresh Kumar return ret; 110*3a29355aSViresh Kumar } 111*3a29355aSViresh Kumar 112*3a29355aSViresh Kumar static int virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio, 113*3a29355aSViresh Kumar u8 txvalue, u8 *rxvalue) 114*3a29355aSViresh Kumar { 115*3a29355aSViresh Kumar struct virtio_gpio_line *line = &vgpio->lines[gpio]; 116*3a29355aSViresh Kumar struct virtio_gpio_response *res = &line->res; 117*3a29355aSViresh Kumar 118*3a29355aSViresh Kumar return _virtio_gpio_req(vgpio, type, gpio, txvalue, rxvalue, res, 119*3a29355aSViresh Kumar sizeof(*res)); 120*3a29355aSViresh Kumar } 121*3a29355aSViresh Kumar 122*3a29355aSViresh Kumar static void virtio_gpio_free(struct gpio_chip *gc, unsigned int gpio) 123*3a29355aSViresh Kumar { 124*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 125*3a29355aSViresh Kumar 126*3a29355aSViresh Kumar virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio, 127*3a29355aSViresh Kumar VIRTIO_GPIO_DIRECTION_NONE, NULL); 128*3a29355aSViresh Kumar } 129*3a29355aSViresh Kumar 130*3a29355aSViresh Kumar static int virtio_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) 131*3a29355aSViresh Kumar { 132*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 133*3a29355aSViresh Kumar u8 direction; 134*3a29355aSViresh Kumar int ret; 135*3a29355aSViresh Kumar 136*3a29355aSViresh Kumar ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_DIRECTION, gpio, 0, 137*3a29355aSViresh Kumar &direction); 138*3a29355aSViresh Kumar if (ret) 139*3a29355aSViresh Kumar return ret; 140*3a29355aSViresh Kumar 141*3a29355aSViresh Kumar switch (direction) { 142*3a29355aSViresh Kumar case VIRTIO_GPIO_DIRECTION_IN: 143*3a29355aSViresh Kumar return GPIO_LINE_DIRECTION_IN; 144*3a29355aSViresh Kumar case VIRTIO_GPIO_DIRECTION_OUT: 145*3a29355aSViresh Kumar return GPIO_LINE_DIRECTION_OUT; 146*3a29355aSViresh Kumar default: 147*3a29355aSViresh Kumar return -EINVAL; 148*3a29355aSViresh Kumar } 149*3a29355aSViresh Kumar } 150*3a29355aSViresh Kumar 151*3a29355aSViresh Kumar static int virtio_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) 152*3a29355aSViresh Kumar { 153*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 154*3a29355aSViresh Kumar 155*3a29355aSViresh Kumar return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio, 156*3a29355aSViresh Kumar VIRTIO_GPIO_DIRECTION_IN, NULL); 157*3a29355aSViresh Kumar } 158*3a29355aSViresh Kumar 159*3a29355aSViresh Kumar static int virtio_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, 160*3a29355aSViresh Kumar int value) 161*3a29355aSViresh Kumar { 162*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 163*3a29355aSViresh Kumar int ret; 164*3a29355aSViresh Kumar 165*3a29355aSViresh Kumar ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL); 166*3a29355aSViresh Kumar if (ret) 167*3a29355aSViresh Kumar return ret; 168*3a29355aSViresh Kumar 169*3a29355aSViresh Kumar return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio, 170*3a29355aSViresh Kumar VIRTIO_GPIO_DIRECTION_OUT, NULL); 171*3a29355aSViresh Kumar } 172*3a29355aSViresh Kumar 173*3a29355aSViresh Kumar static int virtio_gpio_get(struct gpio_chip *gc, unsigned int gpio) 174*3a29355aSViresh Kumar { 175*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 176*3a29355aSViresh Kumar u8 value; 177*3a29355aSViresh Kumar int ret; 178*3a29355aSViresh Kumar 179*3a29355aSViresh Kumar ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_VALUE, gpio, 0, &value); 180*3a29355aSViresh Kumar return ret ? ret : value; 181*3a29355aSViresh Kumar } 182*3a29355aSViresh Kumar 183*3a29355aSViresh Kumar static void virtio_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value) 184*3a29355aSViresh Kumar { 185*3a29355aSViresh Kumar struct virtio_gpio *vgpio = gpiochip_get_data(gc); 186*3a29355aSViresh Kumar 187*3a29355aSViresh Kumar virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL); 188*3a29355aSViresh Kumar } 189*3a29355aSViresh Kumar 190*3a29355aSViresh Kumar static void virtio_gpio_request_vq(struct virtqueue *vq) 191*3a29355aSViresh Kumar { 192*3a29355aSViresh Kumar struct virtio_gpio_line *line; 193*3a29355aSViresh Kumar unsigned int len; 194*3a29355aSViresh Kumar 195*3a29355aSViresh Kumar do { 196*3a29355aSViresh Kumar line = virtqueue_get_buf(vq, &len); 197*3a29355aSViresh Kumar if (!line) 198*3a29355aSViresh Kumar return; 199*3a29355aSViresh Kumar 200*3a29355aSViresh Kumar line->rxlen = len; 201*3a29355aSViresh Kumar complete(&line->completion); 202*3a29355aSViresh Kumar } while (1); 203*3a29355aSViresh Kumar } 204*3a29355aSViresh Kumar 205*3a29355aSViresh Kumar static void virtio_gpio_free_vqs(struct virtio_device *vdev) 206*3a29355aSViresh Kumar { 207*3a29355aSViresh Kumar vdev->config->reset(vdev); 208*3a29355aSViresh Kumar vdev->config->del_vqs(vdev); 209*3a29355aSViresh Kumar } 210*3a29355aSViresh Kumar 211*3a29355aSViresh Kumar static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio, 212*3a29355aSViresh Kumar struct virtio_device *vdev) 213*3a29355aSViresh Kumar { 214*3a29355aSViresh Kumar const char * const names[] = { "requestq" }; 215*3a29355aSViresh Kumar vq_callback_t *cbs[] = { 216*3a29355aSViresh Kumar virtio_gpio_request_vq, 217*3a29355aSViresh Kumar }; 218*3a29355aSViresh Kumar struct virtqueue *vqs[1] = { NULL }; 219*3a29355aSViresh Kumar int ret; 220*3a29355aSViresh Kumar 221*3a29355aSViresh Kumar ret = virtio_find_vqs(vdev, 1, vqs, cbs, names, NULL); 222*3a29355aSViresh Kumar if (ret) { 223*3a29355aSViresh Kumar dev_err(&vdev->dev, "failed to find vqs: %d\n", ret); 224*3a29355aSViresh Kumar return ret; 225*3a29355aSViresh Kumar } 226*3a29355aSViresh Kumar 227*3a29355aSViresh Kumar if (!vqs[0]) { 228*3a29355aSViresh Kumar dev_err(&vdev->dev, "failed to find requestq vq\n"); 229*3a29355aSViresh Kumar return -ENODEV; 230*3a29355aSViresh Kumar } 231*3a29355aSViresh Kumar vgpio->request_vq = vqs[0]; 232*3a29355aSViresh Kumar 233*3a29355aSViresh Kumar return 0; 234*3a29355aSViresh Kumar } 235*3a29355aSViresh Kumar 236*3a29355aSViresh Kumar static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio) 237*3a29355aSViresh Kumar { 238*3a29355aSViresh Kumar struct virtio_gpio_config *config = &vgpio->config; 239*3a29355aSViresh Kumar struct virtio_gpio_response_get_names *res; 240*3a29355aSViresh Kumar struct device *dev = &vgpio->vdev->dev; 241*3a29355aSViresh Kumar u8 *gpio_names, *str; 242*3a29355aSViresh Kumar const char **names; 243*3a29355aSViresh Kumar int i, ret, len; 244*3a29355aSViresh Kumar 245*3a29355aSViresh Kumar if (!config->gpio_names_size) 246*3a29355aSViresh Kumar return NULL; 247*3a29355aSViresh Kumar 248*3a29355aSViresh Kumar len = sizeof(*res) + config->gpio_names_size; 249*3a29355aSViresh Kumar res = devm_kzalloc(dev, len, GFP_KERNEL); 250*3a29355aSViresh Kumar if (!res) 251*3a29355aSViresh Kumar return NULL; 252*3a29355aSViresh Kumar gpio_names = res->value; 253*3a29355aSViresh Kumar 254*3a29355aSViresh Kumar ret = _virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_NAMES, 0, 0, NULL, 255*3a29355aSViresh Kumar res, len); 256*3a29355aSViresh Kumar if (ret) { 257*3a29355aSViresh Kumar dev_err(dev, "Failed to get GPIO names: %d\n", ret); 258*3a29355aSViresh Kumar return NULL; 259*3a29355aSViresh Kumar } 260*3a29355aSViresh Kumar 261*3a29355aSViresh Kumar names = devm_kcalloc(dev, config->ngpio, sizeof(*names), GFP_KERNEL); 262*3a29355aSViresh Kumar if (!names) 263*3a29355aSViresh Kumar return NULL; 264*3a29355aSViresh Kumar 265*3a29355aSViresh Kumar /* NULL terminate the string instead of checking it */ 266*3a29355aSViresh Kumar gpio_names[config->gpio_names_size - 1] = '\0'; 267*3a29355aSViresh Kumar 268*3a29355aSViresh Kumar for (i = 0, str = gpio_names; i < config->ngpio; i++) { 269*3a29355aSViresh Kumar names[i] = str; 270*3a29355aSViresh Kumar str += strlen(str) + 1; /* zero-length strings are allowed */ 271*3a29355aSViresh Kumar 272*3a29355aSViresh Kumar if (str > gpio_names + config->gpio_names_size) { 273*3a29355aSViresh Kumar dev_err(dev, "gpio_names block is too short (%d)\n", i); 274*3a29355aSViresh Kumar return NULL; 275*3a29355aSViresh Kumar } 276*3a29355aSViresh Kumar } 277*3a29355aSViresh Kumar 278*3a29355aSViresh Kumar return names; 279*3a29355aSViresh Kumar } 280*3a29355aSViresh Kumar 281*3a29355aSViresh Kumar static int virtio_gpio_probe(struct virtio_device *vdev) 282*3a29355aSViresh Kumar { 283*3a29355aSViresh Kumar struct virtio_gpio_config *config; 284*3a29355aSViresh Kumar struct device *dev = &vdev->dev; 285*3a29355aSViresh Kumar struct virtio_gpio *vgpio; 286*3a29355aSViresh Kumar int ret, i; 287*3a29355aSViresh Kumar 288*3a29355aSViresh Kumar vgpio = devm_kzalloc(dev, sizeof(*vgpio), GFP_KERNEL); 289*3a29355aSViresh Kumar if (!vgpio) 290*3a29355aSViresh Kumar return -ENOMEM; 291*3a29355aSViresh Kumar 292*3a29355aSViresh Kumar config = &vgpio->config; 293*3a29355aSViresh Kumar 294*3a29355aSViresh Kumar /* Read configuration */ 295*3a29355aSViresh Kumar virtio_cread_bytes(vdev, 0, config, sizeof(*config)); 296*3a29355aSViresh Kumar config->gpio_names_size = le32_to_cpu(config->gpio_names_size); 297*3a29355aSViresh Kumar config->ngpio = le16_to_cpu(config->ngpio); 298*3a29355aSViresh Kumar if (!config->ngpio) { 299*3a29355aSViresh Kumar dev_err(dev, "Number of GPIOs can't be zero\n"); 300*3a29355aSViresh Kumar return -EINVAL; 301*3a29355aSViresh Kumar } 302*3a29355aSViresh Kumar 303*3a29355aSViresh Kumar vgpio->lines = devm_kcalloc(dev, config->ngpio, sizeof(*vgpio->lines), GFP_KERNEL); 304*3a29355aSViresh Kumar if (!vgpio->lines) 305*3a29355aSViresh Kumar return -ENOMEM; 306*3a29355aSViresh Kumar 307*3a29355aSViresh Kumar for (i = 0; i < config->ngpio; i++) { 308*3a29355aSViresh Kumar mutex_init(&vgpio->lines[i].lock); 309*3a29355aSViresh Kumar init_completion(&vgpio->lines[i].completion); 310*3a29355aSViresh Kumar } 311*3a29355aSViresh Kumar 312*3a29355aSViresh Kumar mutex_init(&vgpio->lock); 313*3a29355aSViresh Kumar vdev->priv = vgpio; 314*3a29355aSViresh Kumar 315*3a29355aSViresh Kumar vgpio->vdev = vdev; 316*3a29355aSViresh Kumar vgpio->gc.free = virtio_gpio_free; 317*3a29355aSViresh Kumar vgpio->gc.get_direction = virtio_gpio_get_direction; 318*3a29355aSViresh Kumar vgpio->gc.direction_input = virtio_gpio_direction_input; 319*3a29355aSViresh Kumar vgpio->gc.direction_output = virtio_gpio_direction_output; 320*3a29355aSViresh Kumar vgpio->gc.get = virtio_gpio_get; 321*3a29355aSViresh Kumar vgpio->gc.set = virtio_gpio_set; 322*3a29355aSViresh Kumar vgpio->gc.ngpio = config->ngpio; 323*3a29355aSViresh Kumar vgpio->gc.base = -1; /* Allocate base dynamically */ 324*3a29355aSViresh Kumar vgpio->gc.label = dev_name(dev); 325*3a29355aSViresh Kumar vgpio->gc.parent = dev; 326*3a29355aSViresh Kumar vgpio->gc.owner = THIS_MODULE; 327*3a29355aSViresh Kumar vgpio->gc.can_sleep = true; 328*3a29355aSViresh Kumar 329*3a29355aSViresh Kumar ret = virtio_gpio_alloc_vqs(vgpio, vdev); 330*3a29355aSViresh Kumar if (ret) 331*3a29355aSViresh Kumar return ret; 332*3a29355aSViresh Kumar 333*3a29355aSViresh Kumar /* Mark the device ready to perform operations from within probe() */ 334*3a29355aSViresh Kumar virtio_device_ready(vdev); 335*3a29355aSViresh Kumar 336*3a29355aSViresh Kumar vgpio->gc.names = virtio_gpio_get_names(vgpio); 337*3a29355aSViresh Kumar 338*3a29355aSViresh Kumar ret = gpiochip_add_data(&vgpio->gc, vgpio); 339*3a29355aSViresh Kumar if (ret) { 340*3a29355aSViresh Kumar virtio_gpio_free_vqs(vdev); 341*3a29355aSViresh Kumar dev_err(dev, "Failed to add virtio-gpio controller\n"); 342*3a29355aSViresh Kumar } 343*3a29355aSViresh Kumar 344*3a29355aSViresh Kumar return ret; 345*3a29355aSViresh Kumar } 346*3a29355aSViresh Kumar 347*3a29355aSViresh Kumar static void virtio_gpio_remove(struct virtio_device *vdev) 348*3a29355aSViresh Kumar { 349*3a29355aSViresh Kumar struct virtio_gpio *vgpio = vdev->priv; 350*3a29355aSViresh Kumar 351*3a29355aSViresh Kumar gpiochip_remove(&vgpio->gc); 352*3a29355aSViresh Kumar virtio_gpio_free_vqs(vdev); 353*3a29355aSViresh Kumar } 354*3a29355aSViresh Kumar 355*3a29355aSViresh Kumar static const struct virtio_device_id id_table[] = { 356*3a29355aSViresh Kumar { VIRTIO_ID_GPIO, VIRTIO_DEV_ANY_ID }, 357*3a29355aSViresh Kumar {}, 358*3a29355aSViresh Kumar }; 359*3a29355aSViresh Kumar MODULE_DEVICE_TABLE(virtio, id_table); 360*3a29355aSViresh Kumar 361*3a29355aSViresh Kumar static struct virtio_driver virtio_gpio_driver = { 362*3a29355aSViresh Kumar .id_table = id_table, 363*3a29355aSViresh Kumar .probe = virtio_gpio_probe, 364*3a29355aSViresh Kumar .remove = virtio_gpio_remove, 365*3a29355aSViresh Kumar .driver = { 366*3a29355aSViresh Kumar .name = KBUILD_MODNAME, 367*3a29355aSViresh Kumar .owner = THIS_MODULE, 368*3a29355aSViresh Kumar }, 369*3a29355aSViresh Kumar }; 370*3a29355aSViresh Kumar module_virtio_driver(virtio_gpio_driver); 371*3a29355aSViresh Kumar 372*3a29355aSViresh Kumar MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>"); 373*3a29355aSViresh Kumar MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); 374*3a29355aSViresh Kumar MODULE_DESCRIPTION("VirtIO GPIO driver"); 375*3a29355aSViresh Kumar MODULE_LICENSE("GPL"); 376