0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/init.h>
0014 #include <linux/spinlock.h>
0015 #include <linux/pps_kernel.h>
0016
0017 #include "kc.h"
0018
0019
0020
0021
0022
0023
0024 static DEFINE_SPINLOCK(pps_kc_hardpps_lock);
0025
0026 static struct pps_device *pps_kc_hardpps_dev;
0027 static int pps_kc_hardpps_mode;
0028
0029
0030
0031
0032
0033
0034
0035
0036 int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
0037 {
0038
0039 spin_lock_irq(&pps_kc_hardpps_lock);
0040
0041 if (bind_args->edge == 0)
0042 if (pps_kc_hardpps_dev == pps) {
0043 pps_kc_hardpps_mode = 0;
0044 pps_kc_hardpps_dev = NULL;
0045 spin_unlock_irq(&pps_kc_hardpps_lock);
0046 dev_info(pps->dev, "unbound kernel"
0047 " consumer\n");
0048 } else {
0049 spin_unlock_irq(&pps_kc_hardpps_lock);
0050 dev_err(pps->dev, "selected kernel consumer"
0051 " is not bound\n");
0052 return -EINVAL;
0053 }
0054 else
0055 if (pps_kc_hardpps_dev == NULL ||
0056 pps_kc_hardpps_dev == pps) {
0057 pps_kc_hardpps_mode = bind_args->edge;
0058 pps_kc_hardpps_dev = pps;
0059 spin_unlock_irq(&pps_kc_hardpps_lock);
0060 dev_info(pps->dev, "bound kernel consumer: "
0061 "edge=0x%x\n", bind_args->edge);
0062 } else {
0063 spin_unlock_irq(&pps_kc_hardpps_lock);
0064 dev_err(pps->dev, "another kernel consumer"
0065 " is already bound\n");
0066 return -EINVAL;
0067 }
0068
0069 return 0;
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079 void pps_kc_remove(struct pps_device *pps)
0080 {
0081 spin_lock_irq(&pps_kc_hardpps_lock);
0082 if (pps == pps_kc_hardpps_dev) {
0083 pps_kc_hardpps_mode = 0;
0084 pps_kc_hardpps_dev = NULL;
0085 spin_unlock_irq(&pps_kc_hardpps_lock);
0086 dev_info(pps->dev, "unbound kernel consumer"
0087 " on device removal\n");
0088 } else
0089 spin_unlock_irq(&pps_kc_hardpps_lock);
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099 void pps_kc_event(struct pps_device *pps, struct pps_event_time *ts,
0100 int event)
0101 {
0102 unsigned long flags;
0103
0104
0105 spin_lock_irqsave(&pps_kc_hardpps_lock, flags);
0106 if (pps == pps_kc_hardpps_dev && event & pps_kc_hardpps_mode)
0107 hardpps(&ts->ts_real, &ts->ts_raw);
0108 spin_unlock_irqrestore(&pps_kc_hardpps_lock, flags);
0109 }