Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * pps_parport.c -- kernel parallel port PPS client
0004  *
0005  * Copyright (C) 2009   Alexander Gordeev <lasaine@lvk.cs.msu.su>
0006  */
0007 
0008 
0009 /*
0010  * TODO:
0011  * implement echo over SEL pin
0012  */
0013 
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/init.h>
0019 #include <linux/irqnr.h>
0020 #include <linux/time.h>
0021 #include <linux/slab.h>
0022 #include <linux/parport.h>
0023 #include <linux/pps_kernel.h>
0024 
0025 /* module parameters */
0026 
0027 #define CLEAR_WAIT_MAX      100
0028 #define CLEAR_WAIT_MAX_ERRORS   5
0029 
0030 static unsigned int clear_wait = 100;
0031 MODULE_PARM_DESC(clear_wait,
0032     "Maximum number of port reads when polling for signal clear,"
0033     " zero turns clear edge capture off entirely");
0034 module_param(clear_wait, uint, 0);
0035 
0036 static DEFINE_IDA(pps_client_index);
0037 
0038 /* internal per port structure */
0039 struct pps_client_pp {
0040     struct pardevice *pardev;   /* parport device */
0041     struct pps_device *pps;     /* PPS device */
0042     unsigned int cw;        /* port clear timeout */
0043     unsigned int cw_err;        /* number of timeouts */
0044     int index;          /* device number */
0045 };
0046 
0047 static inline int signal_is_set(struct parport *port)
0048 {
0049     return (port->ops->read_status(port) & PARPORT_STATUS_ACK) != 0;
0050 }
0051 
0052 /* parport interrupt handler */
0053 static void parport_irq(void *handle)
0054 {
0055     struct pps_event_time ts_assert, ts_clear;
0056     struct pps_client_pp *dev = handle;
0057     struct parport *port = dev->pardev->port;
0058     unsigned int i;
0059     unsigned long flags;
0060 
0061     /* first of all we get the time stamp... */
0062     pps_get_ts(&ts_assert);
0063 
0064     if (dev->cw == 0)
0065         /* clear edge capture disabled */
0066         goto out_assert;
0067 
0068     /* try capture the clear edge */
0069 
0070     /* We have to disable interrupts here. The idea is to prevent
0071      * other interrupts on the same processor to introduce random
0072      * lags while polling the port. Reading from IO port is known
0073      * to take approximately 1us while other interrupt handlers can
0074      * take much more potentially.
0075      *
0076      * Interrupts won't be disabled for a long time because the
0077      * number of polls is limited by clear_wait parameter which is
0078      * kept rather low. So it should never be an issue.
0079      */
0080     local_irq_save(flags);
0081     /* check the signal (no signal means the pulse is lost this time) */
0082     if (!signal_is_set(port)) {
0083         local_irq_restore(flags);
0084         dev_err(dev->pps->dev, "lost the signal\n");
0085         goto out_assert;
0086     }
0087 
0088     /* poll the port until the signal is unset */
0089     for (i = dev->cw; i; i--)
0090         if (!signal_is_set(port)) {
0091             pps_get_ts(&ts_clear);
0092             local_irq_restore(flags);
0093             dev->cw_err = 0;
0094             goto out_both;
0095         }
0096     local_irq_restore(flags);
0097 
0098     /* timeout */
0099     dev->cw_err++;
0100     if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) {
0101         dev_err(dev->pps->dev, "disabled clear edge capture after %d"
0102                 " timeouts\n", dev->cw_err);
0103         dev->cw = 0;
0104         dev->cw_err = 0;
0105     }
0106 
0107 out_assert:
0108     /* fire assert event */
0109     pps_event(dev->pps, &ts_assert,
0110             PPS_CAPTUREASSERT, NULL);
0111     return;
0112 
0113 out_both:
0114     /* fire assert event */
0115     pps_event(dev->pps, &ts_assert,
0116             PPS_CAPTUREASSERT, NULL);
0117     /* fire clear event */
0118     pps_event(dev->pps, &ts_clear,
0119             PPS_CAPTURECLEAR, NULL);
0120     return;
0121 }
0122 
0123 static void parport_attach(struct parport *port)
0124 {
0125     struct pardev_cb pps_client_cb;
0126     int index;
0127     struct pps_client_pp *device;
0128     struct pps_source_info info = {
0129         .name       = KBUILD_MODNAME,
0130         .path       = "",
0131         .mode       = PPS_CAPTUREBOTH | \
0132                   PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
0133                   PPS_ECHOASSERT | PPS_ECHOCLEAR | \
0134                   PPS_CANWAIT | PPS_TSFMT_TSPEC,
0135         .owner      = THIS_MODULE,
0136         .dev        = NULL
0137     };
0138 
0139     if (clear_wait > CLEAR_WAIT_MAX) {
0140         pr_err("clear_wait value should be not greater then %d\n",
0141                CLEAR_WAIT_MAX);
0142         return;
0143     }
0144 
0145     device = kzalloc(sizeof(struct pps_client_pp), GFP_KERNEL);
0146     if (!device) {
0147         pr_err("memory allocation failed, not attaching\n");
0148         return;
0149     }
0150 
0151     index = ida_simple_get(&pps_client_index, 0, 0, GFP_KERNEL);
0152     memset(&pps_client_cb, 0, sizeof(pps_client_cb));
0153     pps_client_cb.private = device;
0154     pps_client_cb.irq_func = parport_irq;
0155     pps_client_cb.flags = PARPORT_FLAG_EXCL;
0156     device->pardev = parport_register_dev_model(port,
0157                             KBUILD_MODNAME,
0158                             &pps_client_cb,
0159                             index);
0160     if (!device->pardev) {
0161         pr_err("couldn't register with %s\n", port->name);
0162         goto err_free;
0163     }
0164 
0165     if (parport_claim_or_block(device->pardev) < 0) {
0166         pr_err("couldn't claim %s\n", port->name);
0167         goto err_unregister_dev;
0168     }
0169 
0170     device->pps = pps_register_source(&info,
0171             PPS_CAPTUREBOTH | PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
0172     if (IS_ERR(device->pps)) {
0173         pr_err("couldn't register PPS source\n");
0174         goto err_release_dev;
0175     }
0176 
0177     device->cw = clear_wait;
0178 
0179     port->ops->enable_irq(port);
0180     device->index = index;
0181 
0182     pr_info("attached to %s\n", port->name);
0183 
0184     return;
0185 
0186 err_release_dev:
0187     parport_release(device->pardev);
0188 err_unregister_dev:
0189     parport_unregister_device(device->pardev);
0190 err_free:
0191     ida_simple_remove(&pps_client_index, index);
0192     kfree(device);
0193 }
0194 
0195 static void parport_detach(struct parport *port)
0196 {
0197     struct pardevice *pardev = port->cad;
0198     struct pps_client_pp *device;
0199 
0200     /* FIXME: oooh, this is ugly! */
0201     if (!pardev || strcmp(pardev->name, KBUILD_MODNAME))
0202         /* not our port */
0203         return;
0204 
0205     device = pardev->private;
0206 
0207     port->ops->disable_irq(port);
0208     pps_unregister_source(device->pps);
0209     parport_release(pardev);
0210     parport_unregister_device(pardev);
0211     ida_simple_remove(&pps_client_index, device->index);
0212     kfree(device);
0213 }
0214 
0215 static struct parport_driver pps_parport_driver = {
0216     .name = KBUILD_MODNAME,
0217     .match_port = parport_attach,
0218     .detach = parport_detach,
0219     .devmodel = true,
0220 };
0221 module_parport_driver(pps_parport_driver);
0222 
0223 MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>");
0224 MODULE_DESCRIPTION("parallel port PPS client");
0225 MODULE_LICENSE("GPL");