static void gpiochip_setup_devs(void) { struct gpio_device *gdev; int err;
list_for_each_entry(gdev, &gpio_devices, list) { err = gpiochip_setup_dev(gdev); if (err) pr_err("%s: Failed to initialize gpio device (%d)\n", dev_name(&gdev->dev), err); } }
static const struct file_operations gpio_fileops = {
.release = gpio_chrdev_release,
.open = gpio_chrdev_open,
.owner = THIS_MODULE,
.llseek = noop_llseek,
.unlocked_ioctl = gpio_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = gpio_ioctl_compat,
#endif
};
static int gpiochip_setup_dev(struct gpio_device *gdev) { int status;
cdev_init(&gdev->chrdev, &gpio_fileops); gdev->chrdev.owner = THIS_MODULE; gdev->chrdev.kobj.parent = &gdev->dev.kobj; gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id); status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1); if (status < 0) chip_warn(gdev->chip, "failed to add char device %d:%d\n", MAJOR(gpio_devt), gdev->id); else chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n", MAJOR(gpio_devt), gdev->id); status = device_add(&gdev->dev); if (status) goto err_remove_chardev;
status = gpiochip_sysfs_register(gdev); if (status) goto err_remove_device;
/* From this point, the .release() function cleans up gpio_device */ gdev->dev.release = gpiodevice_release; pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", __func__, gdev->base, gdev->base + gdev->ngpio - 1, dev_name(&gdev->dev), gdev->chip->label ? : "generic");
return 0;
err_remove_device: device_del(&gdev->dev); err_remove_chardev: cdev_del(&gdev->chrdev); return status; }