1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * pps_parport.c -- kernel parallel port PPS client 4 * 5 * Copyright (C) 2009 Alexander Gordeev <lasaine@lvk.cs.msu.su> 6 */ 7 8 9 /* 10 * TODO: 11 * implement echo over SEL pin 12 */ 13 14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/init.h> 19 #include <linux/irqnr.h> 20 #include <linux/time.h> 21 #include <linux/slab.h> 22 #include <linux/parport.h> 23 #include <linux/pps_kernel.h> 24 25 #define DRVDESC "parallel port PPS client" 26 27 /* module parameters */ 28 29 #define CLEAR_WAIT_MAX 100 30 #define CLEAR_WAIT_MAX_ERRORS 5 31 32 static unsigned int clear_wait = 100; 33 MODULE_PARM_DESC(clear_wait, 34 "Maximum number of port reads when polling for signal clear," 35 " zero turns clear edge capture off entirely"); 36 module_param(clear_wait, uint, 0); 37 38 static DEFINE_IDA(pps_client_index); 39 40 /* internal per port structure */ 41 struct pps_client_pp { 42 struct pardevice *pardev; /* parport device */ 43 struct pps_device *pps; /* PPS device */ 44 unsigned int cw; /* port clear timeout */ 45 unsigned int cw_err; /* number of timeouts */ 46 int index; /* device number */ 47 }; 48 49 static inline int signal_is_set(struct parport *port) 50 { 51 return (port->ops->read_status(port) & PARPORT_STATUS_ACK) != 0; 52 } 53 54 /* parport interrupt handler */ 55 static void parport_irq(void *handle) 56 { 57 struct pps_event_time ts_assert, ts_clear; 58 struct pps_client_pp *dev = handle; 59 struct parport *port = dev->pardev->port; 60 unsigned int i; 61 unsigned long flags; 62 63 /* first of all we get the time stamp... */ 64 pps_get_ts(&ts_assert); 65 66 if (dev->cw == 0) 67 /* clear edge capture disabled */ 68 goto out_assert; 69 70 /* try capture the clear edge */ 71 72 /* We have to disable interrupts here. The idea is to prevent 73 * other interrupts on the same processor to introduce random 74 * lags while polling the port. Reading from IO port is known 75 * to take approximately 1us while other interrupt handlers can 76 * take much more potentially. 77 * 78 * Interrupts won't be disabled for a long time because the 79 * number of polls is limited by clear_wait parameter which is 80 * kept rather low. So it should never be an issue. 81 */ 82 local_irq_save(flags); 83 /* check the signal (no signal means the pulse is lost this time) */ 84 if (!signal_is_set(port)) { 85 local_irq_restore(flags); 86 dev_err(dev->pps->dev, "lost the signal\n"); 87 goto out_assert; 88 } 89 90 /* poll the port until the signal is unset */ 91 for (i = dev->cw; i; i--) 92 if (!signal_is_set(port)) { 93 pps_get_ts(&ts_clear); 94 local_irq_restore(flags); 95 dev->cw_err = 0; 96 goto out_both; 97 } 98 local_irq_restore(flags); 99 100 /* timeout */ 101 dev->cw_err++; 102 if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) { 103 dev_err(dev->pps->dev, "disabled clear edge capture after %d" 104 " timeouts\n", dev->cw_err); 105 dev->cw = 0; 106 dev->cw_err = 0; 107 } 108 109 out_assert: 110 /* fire assert event */ 111 pps_event(dev->pps, &ts_assert, 112 PPS_CAPTUREASSERT, NULL); 113 return; 114 115 out_both: 116 /* fire assert event */ 117 pps_event(dev->pps, &ts_assert, 118 PPS_CAPTUREASSERT, NULL); 119 /* fire clear event */ 120 pps_event(dev->pps, &ts_clear, 121 PPS_CAPTURECLEAR, NULL); 122 return; 123 } 124 125 static void parport_attach(struct parport *port) 126 { 127 struct pardev_cb pps_client_cb; 128 int index; 129 struct pps_client_pp *device; 130 struct pps_source_info info = { 131 .name = KBUILD_MODNAME, 132 .path = "", 133 .mode = PPS_CAPTUREBOTH | \ 134 PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ 135 PPS_ECHOASSERT | PPS_ECHOCLEAR | \ 136 PPS_CANWAIT | PPS_TSFMT_TSPEC, 137 .owner = THIS_MODULE, 138 .dev = NULL 139 }; 140 141 device = kzalloc(sizeof(struct pps_client_pp), GFP_KERNEL); 142 if (!device) { 143 pr_err("memory allocation failed, not attaching\n"); 144 return; 145 } 146 147 index = ida_simple_get(&pps_client_index, 0, 0, GFP_KERNEL); 148 memset(&pps_client_cb, 0, sizeof(pps_client_cb)); 149 pps_client_cb.private = device; 150 pps_client_cb.irq_func = parport_irq; 151 pps_client_cb.flags = PARPORT_FLAG_EXCL; 152 device->pardev = parport_register_dev_model(port, 153 KBUILD_MODNAME, 154 &pps_client_cb, 155 index); 156 if (!device->pardev) { 157 pr_err("couldn't register with %s\n", port->name); 158 goto err_free; 159 } 160 161 if (parport_claim_or_block(device->pardev) < 0) { 162 pr_err("couldn't claim %s\n", port->name); 163 goto err_unregister_dev; 164 } 165 166 device->pps = pps_register_source(&info, 167 PPS_CAPTUREBOTH | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); 168 if (IS_ERR(device->pps)) { 169 pr_err("couldn't register PPS source\n"); 170 goto err_release_dev; 171 } 172 173 device->cw = clear_wait; 174 175 port->ops->enable_irq(port); 176 device->index = index; 177 178 pr_info("attached to %s\n", port->name); 179 180 return; 181 182 err_release_dev: 183 parport_release(device->pardev); 184 err_unregister_dev: 185 parport_unregister_device(device->pardev); 186 err_free: 187 ida_simple_remove(&pps_client_index, index); 188 kfree(device); 189 } 190 191 static void parport_detach(struct parport *port) 192 { 193 struct pardevice *pardev = port->cad; 194 struct pps_client_pp *device; 195 196 /* FIXME: oooh, this is ugly! */ 197 if (!pardev || strcmp(pardev->name, KBUILD_MODNAME)) 198 /* not our port */ 199 return; 200 201 device = pardev->private; 202 203 port->ops->disable_irq(port); 204 pps_unregister_source(device->pps); 205 parport_release(pardev); 206 parport_unregister_device(pardev); 207 ida_simple_remove(&pps_client_index, device->index); 208 kfree(device); 209 } 210 211 static struct parport_driver pps_parport_driver = { 212 .name = KBUILD_MODNAME, 213 .match_port = parport_attach, 214 .detach = parport_detach, 215 .devmodel = true, 216 }; 217 218 /* module staff */ 219 220 static int __init pps_parport_init(void) 221 { 222 int ret; 223 224 pr_info(DRVDESC "\n"); 225 226 if (clear_wait > CLEAR_WAIT_MAX) { 227 pr_err("clear_wait value should be not greater" 228 " then %d\n", CLEAR_WAIT_MAX); 229 return -EINVAL; 230 } 231 232 ret = parport_register_driver(&pps_parport_driver); 233 if (ret) { 234 pr_err("unable to register with parport\n"); 235 return ret; 236 } 237 238 return 0; 239 } 240 241 static void __exit pps_parport_exit(void) 242 { 243 parport_unregister_driver(&pps_parport_driver); 244 } 245 246 module_init(pps_parport_init); 247 module_exit(pps_parport_exit); 248 249 MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>"); 250 MODULE_DESCRIPTION(DRVDESC); 251 MODULE_LICENSE("GPL"); 252