Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Greybus Vibrator protocol driver.
0004  *
0005  * Copyright 2014 Google Inc.
0006  * Copyright 2014 Linaro Ltd.
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/slab.h>
0012 #include <linux/device.h>
0013 #include <linux/kdev_t.h>
0014 #include <linux/idr.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/greybus.h>
0017 
0018 struct gb_vibrator_device {
0019     struct gb_connection    *connection;
0020     struct device       *dev;
0021     int         minor;      /* vibrator minor number */
0022     struct delayed_work     delayed_work;
0023 };
0024 
0025 /* Greybus Vibrator operation types */
0026 #define GB_VIBRATOR_TYPE_ON         0x02
0027 #define GB_VIBRATOR_TYPE_OFF            0x03
0028 
0029 static int turn_off(struct gb_vibrator_device *vib)
0030 {
0031     struct gb_bundle *bundle = vib->connection->bundle;
0032     int ret;
0033 
0034     ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
0035                 NULL, 0, NULL, 0);
0036 
0037     gb_pm_runtime_put_autosuspend(bundle);
0038 
0039     return ret;
0040 }
0041 
0042 static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
0043 {
0044     struct gb_bundle *bundle = vib->connection->bundle;
0045     int ret;
0046 
0047     ret = gb_pm_runtime_get_sync(bundle);
0048     if (ret)
0049         return ret;
0050 
0051     /* Vibrator was switched ON earlier */
0052     if (cancel_delayed_work_sync(&vib->delayed_work))
0053         turn_off(vib);
0054 
0055     ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
0056                 NULL, 0, NULL, 0);
0057     if (ret) {
0058         gb_pm_runtime_put_autosuspend(bundle);
0059         return ret;
0060     }
0061 
0062     schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms));
0063 
0064     return 0;
0065 }
0066 
0067 static void gb_vibrator_worker(struct work_struct *work)
0068 {
0069     struct delayed_work *delayed_work = to_delayed_work(work);
0070     struct gb_vibrator_device *vib =
0071         container_of(delayed_work,
0072                  struct gb_vibrator_device,
0073                  delayed_work);
0074 
0075     turn_off(vib);
0076 }
0077 
0078 static ssize_t timeout_store(struct device *dev, struct device_attribute *attr,
0079                  const char *buf, size_t count)
0080 {
0081     struct gb_vibrator_device *vib = dev_get_drvdata(dev);
0082     unsigned long val;
0083     int retval;
0084 
0085     retval = kstrtoul(buf, 10, &val);
0086     if (retval < 0) {
0087         dev_err(dev, "could not parse timeout value %d\n", retval);
0088         return retval;
0089     }
0090 
0091     if (val)
0092         retval = turn_on(vib, (u16)val);
0093     else
0094         retval = turn_off(vib);
0095     if (retval)
0096         return retval;
0097 
0098     return count;
0099 }
0100 static DEVICE_ATTR_WO(timeout);
0101 
0102 static struct attribute *vibrator_attrs[] = {
0103     &dev_attr_timeout.attr,
0104     NULL,
0105 };
0106 ATTRIBUTE_GROUPS(vibrator);
0107 
0108 static struct class vibrator_class = {
0109     .name       = "vibrator",
0110     .owner      = THIS_MODULE,
0111     .dev_groups = vibrator_groups,
0112 };
0113 
0114 static DEFINE_IDA(minors);
0115 
0116 static int gb_vibrator_probe(struct gb_bundle *bundle,
0117                  const struct greybus_bundle_id *id)
0118 {
0119     struct greybus_descriptor_cport *cport_desc;
0120     struct gb_connection *connection;
0121     struct gb_vibrator_device *vib;
0122     struct device *dev;
0123     int retval;
0124 
0125     if (bundle->num_cports != 1)
0126         return -ENODEV;
0127 
0128     cport_desc = &bundle->cport_desc[0];
0129     if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
0130         return -ENODEV;
0131 
0132     vib = kzalloc(sizeof(*vib), GFP_KERNEL);
0133     if (!vib)
0134         return -ENOMEM;
0135 
0136     connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
0137                       NULL);
0138     if (IS_ERR(connection)) {
0139         retval = PTR_ERR(connection);
0140         goto err_free_vib;
0141     }
0142     gb_connection_set_data(connection, vib);
0143 
0144     vib->connection = connection;
0145 
0146     greybus_set_drvdata(bundle, vib);
0147 
0148     retval = gb_connection_enable(connection);
0149     if (retval)
0150         goto err_connection_destroy;
0151 
0152     /*
0153      * For now we create a device in sysfs for the vibrator, but odds are
0154      * there is a "real" device somewhere in the kernel for this, but I
0155      * can't find it at the moment...
0156      */
0157     vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
0158     if (vib->minor < 0) {
0159         retval = vib->minor;
0160         goto err_connection_disable;
0161     }
0162     dev = device_create(&vibrator_class, &bundle->dev,
0163                 MKDEV(0, 0), vib, "vibrator%d", vib->minor);
0164     if (IS_ERR(dev)) {
0165         retval = -EINVAL;
0166         goto err_ida_remove;
0167     }
0168     vib->dev = dev;
0169 
0170     INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker);
0171 
0172     gb_pm_runtime_put_autosuspend(bundle);
0173 
0174     return 0;
0175 
0176 err_ida_remove:
0177     ida_simple_remove(&minors, vib->minor);
0178 err_connection_disable:
0179     gb_connection_disable(connection);
0180 err_connection_destroy:
0181     gb_connection_destroy(connection);
0182 err_free_vib:
0183     kfree(vib);
0184 
0185     return retval;
0186 }
0187 
0188 static void gb_vibrator_disconnect(struct gb_bundle *bundle)
0189 {
0190     struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
0191     int ret;
0192 
0193     ret = gb_pm_runtime_get_sync(bundle);
0194     if (ret)
0195         gb_pm_runtime_get_noresume(bundle);
0196 
0197     if (cancel_delayed_work_sync(&vib->delayed_work))
0198         turn_off(vib);
0199 
0200     device_unregister(vib->dev);
0201     ida_simple_remove(&minors, vib->minor);
0202     gb_connection_disable(vib->connection);
0203     gb_connection_destroy(vib->connection);
0204     kfree(vib);
0205 }
0206 
0207 static const struct greybus_bundle_id gb_vibrator_id_table[] = {
0208     { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
0209     { }
0210 };
0211 MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
0212 
0213 static struct greybus_driver gb_vibrator_driver = {
0214     .name       = "vibrator",
0215     .probe      = gb_vibrator_probe,
0216     .disconnect = gb_vibrator_disconnect,
0217     .id_table   = gb_vibrator_id_table,
0218 };
0219 
0220 static __init int gb_vibrator_init(void)
0221 {
0222     int retval;
0223 
0224     retval = class_register(&vibrator_class);
0225     if (retval)
0226         return retval;
0227 
0228     retval = greybus_register(&gb_vibrator_driver);
0229     if (retval)
0230         goto err_class_unregister;
0231 
0232     return 0;
0233 
0234 err_class_unregister:
0235     class_unregister(&vibrator_class);
0236 
0237     return retval;
0238 }
0239 module_init(gb_vibrator_init);
0240 
0241 static __exit void gb_vibrator_exit(void)
0242 {
0243     greybus_deregister(&gb_vibrator_driver);
0244     class_unregister(&vibrator_class);
0245     ida_destroy(&minors);
0246 }
0247 module_exit(gb_vibrator_exit);
0248 
0249 MODULE_LICENSE("GPL v2");