1 /*- 2 * SPDX-License-Identifier: Beerware 3 * 4 * ---------------------------------------------------------------------------- 5 * "THE BEER-WARE LICENSE" (Revision 42): 6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 7 * can do whatever you want with this stuff. If we meet some day, and you think 8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 9 * ---------------------------------------------------------------------------- 10 * 11 * 12 * This driver implements a draft-mogul-pps-api-02.txt PPS source. 13 * 14 * The input pin is pin#10 15 * The echo output pin is pin#14 16 * 17 */ 18 19 #include <sys/cdefs.h> 20 __FBSDID("$FreeBSD$"); 21 22 #include <sys/param.h> 23 #include <sys/lock.h> 24 #include <sys/kernel.h> 25 #include <sys/systm.h> 26 #include <sys/module.h> 27 #include <sys/sx.h> 28 #include <sys/bus.h> 29 #include <sys/conf.h> 30 #include <sys/timepps.h> 31 #include <machine/bus.h> 32 #include <machine/resource.h> 33 #include <sys/rman.h> 34 35 #include <dev/ppbus/ppbconf.h> 36 #include "ppbus_if.h" 37 #include <dev/ppbus/ppbio.h> 38 39 #define PPS_NAME "pps" /* our official name */ 40 41 #define PRVERBOSE(fmt, arg...) if (bootverbose) printf(fmt, ##arg); 42 43 struct pps_data { 44 struct ppb_device pps_dev; 45 struct pps_state pps[9]; 46 struct cdev *devs[9]; 47 device_t ppsdev; 48 device_t ppbus; 49 int busy; 50 struct callout timeout; 51 int lastdata; 52 53 struct sx lock; 54 struct resource *intr_resource; /* interrupt resource */ 55 void *intr_cookie; /* interrupt registration cookie */ 56 }; 57 58 static void ppsintr(void *arg); 59 static void ppshcpoll(void *arg); 60 61 #define DEVTOSOFTC(dev) \ 62 ((struct pps_data *)device_get_softc(dev)) 63 64 static devclass_t pps_devclass; 65 66 static d_open_t ppsopen; 67 static d_close_t ppsclose; 68 static d_ioctl_t ppsioctl; 69 70 static struct cdevsw pps_cdevsw = { 71 .d_version = D_VERSION, 72 .d_open = ppsopen, 73 .d_close = ppsclose, 74 .d_ioctl = ppsioctl, 75 .d_name = PPS_NAME, 76 }; 77 78 static void 79 ppsidentify(driver_t *driver, device_t parent) 80 { 81 82 device_t dev; 83 84 dev = device_find_child(parent, PPS_NAME, -1); 85 if (!dev) 86 BUS_ADD_CHILD(parent, 0, PPS_NAME, -1); 87 } 88 89 static int 90 ppstry(device_t ppbus, int send, int expect) 91 { 92 int i; 93 94 ppb_wdtr(ppbus, send); 95 i = ppb_rdtr(ppbus); 96 PRVERBOSE("S: %02x E: %02x G: %02x\n", send, expect, i); 97 return (i != expect); 98 } 99 100 static int 101 ppsprobe(device_t ppsdev) 102 { 103 device_set_desc(ppsdev, "Pulse per second Timing Interface"); 104 105 return (0); 106 } 107 108 static int 109 ppsattach(device_t dev) 110 { 111 struct pps_data *sc = DEVTOSOFTC(dev); 112 device_t ppbus = device_get_parent(dev); 113 struct cdev *d; 114 int error, i, unit, rid = 0; 115 116 /* declare our interrupt handler */ 117 sc->intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 118 RF_SHAREABLE); 119 120 /* interrupts seem mandatory */ 121 if (sc->intr_resource == NULL) { 122 device_printf(dev, "Unable to allocate interrupt resource\n"); 123 return (ENXIO); 124 } 125 126 error = bus_setup_intr(dev, sc->intr_resource, 127 INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppsintr, 128 sc, &sc->intr_cookie); 129 if (error) { 130 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intr_resource); 131 device_printf(dev, "Unable to register interrupt handler\n"); 132 return (error); 133 } 134 135 sx_init(&sc->lock, "pps"); 136 ppb_init_callout(ppbus, &sc->timeout, 0); 137 sc->ppsdev = dev; 138 sc->ppbus = ppbus; 139 unit = device_get_unit(ppbus); 140 d = make_dev(&pps_cdevsw, unit, 141 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", unit); 142 sc->devs[0] = d; 143 sc->pps[0].ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 144 sc->pps[0].driver_abi = PPS_ABI_VERSION; 145 sc->pps[0].driver_mtx = ppb_get_lock(ppbus); 146 d->si_drv1 = sc; 147 d->si_drv2 = (void*)0; 148 pps_init_abi(&sc->pps[0]); 149 150 ppb_lock(ppbus); 151 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { 152 ppb_unlock(ppbus); 153 return (0); 154 } 155 156 do { 157 i = ppb_set_mode(sc->ppbus, PPB_EPP); 158 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 159 if (i == -1) 160 break; 161 i = 0; 162 ppb_wctr(ppbus, i); 163 if (ppstry(ppbus, 0x00, 0x00)) 164 break; 165 if (ppstry(ppbus, 0x55, 0x55)) 166 break; 167 if (ppstry(ppbus, 0xaa, 0xaa)) 168 break; 169 if (ppstry(ppbus, 0xff, 0xff)) 170 break; 171 172 i = IRQENABLE | PCD | STROBE | nINIT | SELECTIN; 173 ppb_wctr(ppbus, i); 174 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 175 if (ppstry(ppbus, 0x00, 0x00)) 176 break; 177 if (ppstry(ppbus, 0x55, 0x00)) 178 break; 179 if (ppstry(ppbus, 0xaa, 0x00)) 180 break; 181 if (ppstry(ppbus, 0xff, 0x00)) 182 break; 183 184 i = IRQENABLE | PCD | nINIT | SELECTIN; 185 ppb_wctr(ppbus, i); 186 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 187 ppstry(ppbus, 0x00, 0xff); 188 ppstry(ppbus, 0x55, 0xff); 189 ppstry(ppbus, 0xaa, 0xff); 190 ppstry(ppbus, 0xff, 0xff); 191 ppb_unlock(ppbus); 192 193 for (i = 1; i < 9; i++) { 194 d = make_dev(&pps_cdevsw, unit + 0x10000 * i, 195 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%db%d", unit, i - 1); 196 sc->devs[i] = d; 197 sc->pps[i].ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 198 sc->pps[i].driver_abi = PPS_ABI_VERSION; 199 sc->pps[i].driver_mtx = ppb_get_lock(ppbus); 200 d->si_drv1 = sc; 201 d->si_drv2 = (void *)(intptr_t)i; 202 pps_init_abi(&sc->pps[i]); 203 } 204 ppb_lock(ppbus); 205 } while (0); 206 i = ppb_set_mode(sc->ppbus, PPB_COMPATIBLE); 207 ppb_release_bus(ppbus, dev); 208 ppb_unlock(ppbus); 209 210 return (0); 211 } 212 213 static int 214 ppsopen(struct cdev *dev, int flags, int fmt, struct thread *td) 215 { 216 struct pps_data *sc = dev->si_drv1; 217 device_t ppbus = sc->ppbus; 218 int subdev = (intptr_t)dev->si_drv2; 219 int i; 220 221 /* 222 * The sx lock is here solely to serialize open()'s to close 223 * the race of concurrent open()'s when pps(4) doesn't own the 224 * ppbus. 225 */ 226 sx_xlock(&sc->lock); 227 ppb_lock(ppbus); 228 if (!sc->busy) { 229 device_t ppsdev = sc->ppsdev; 230 231 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) { 232 ppb_unlock(ppbus); 233 sx_xunlock(&sc->lock); 234 return (EINTR); 235 } 236 237 i = ppb_set_mode(sc->ppbus, PPB_PS2); 238 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 239 240 i = IRQENABLE | PCD | nINIT | SELECTIN; 241 ppb_wctr(ppbus, i); 242 } 243 if (subdev > 0 && !(sc->busy & ~1)) { 244 /* XXX: Timeout of 1? hz/100 instead perhaps? */ 245 callout_reset(&sc->timeout, 1, ppshcpoll, sc); 246 sc->lastdata = ppb_rdtr(sc->ppbus); 247 } 248 sc->busy |= (1 << subdev); 249 ppb_unlock(ppbus); 250 sx_xunlock(&sc->lock); 251 return(0); 252 } 253 254 static int 255 ppsclose(struct cdev *dev, int flags, int fmt, struct thread *td) 256 { 257 struct pps_data *sc = dev->si_drv1; 258 int subdev = (intptr_t)dev->si_drv2; 259 260 sx_xlock(&sc->lock); 261 sc->pps[subdev].ppsparam.mode = 0; /* PHK ??? */ 262 ppb_lock(sc->ppbus); 263 sc->busy &= ~(1 << subdev); 264 if (subdev > 0 && !(sc->busy & ~1)) 265 callout_stop(&sc->timeout); 266 if (!sc->busy) { 267 device_t ppsdev = sc->ppsdev; 268 device_t ppbus = sc->ppbus; 269 270 ppb_wdtr(ppbus, 0); 271 ppb_wctr(ppbus, 0); 272 273 ppb_set_mode(ppbus, PPB_COMPATIBLE); 274 ppb_release_bus(ppbus, ppsdev); 275 } 276 ppb_unlock(sc->ppbus); 277 sx_xunlock(&sc->lock); 278 return(0); 279 } 280 281 static void 282 ppshcpoll(void *arg) 283 { 284 struct pps_data *sc = arg; 285 int i, j, k, l; 286 287 KASSERT(sc->busy & ~1, ("pps polling w/o opened devices")); 288 i = ppb_rdtr(sc->ppbus); 289 if (i == sc->lastdata) 290 return; 291 l = sc->lastdata ^ i; 292 k = 1; 293 for (j = 1; j < 9; j ++) { 294 if (l & k) { 295 pps_capture(&sc->pps[j]); 296 pps_event(&sc->pps[j], 297 i & k ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 298 } 299 k += k; 300 } 301 sc->lastdata = i; 302 callout_reset(&sc->timeout, 1, ppshcpoll, sc); 303 } 304 305 static void 306 ppsintr(void *arg) 307 { 308 struct pps_data *sc = (struct pps_data *)arg; 309 310 ppb_assert_locked(sc->ppbus); 311 pps_capture(&sc->pps[0]); 312 if (!(ppb_rstr(sc->ppbus) & nACK)) 313 return; 314 315 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 316 ppb_wctr(sc->ppbus, IRQENABLE | AUTOFEED); 317 pps_event(&sc->pps[0], PPS_CAPTUREASSERT); 318 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 319 ppb_wctr(sc->ppbus, IRQENABLE); 320 } 321 322 static int 323 ppsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) 324 { 325 struct pps_data *sc = dev->si_drv1; 326 int subdev = (intptr_t)dev->si_drv2; 327 int err; 328 329 ppb_lock(sc->ppbus); 330 err = pps_ioctl(cmd, data, &sc->pps[subdev]); 331 ppb_unlock(sc->ppbus); 332 return (err); 333 } 334 335 static device_method_t pps_methods[] = { 336 /* device interface */ 337 DEVMETHOD(device_identify, ppsidentify), 338 DEVMETHOD(device_probe, ppsprobe), 339 DEVMETHOD(device_attach, ppsattach), 340 { 0, 0 } 341 }; 342 343 static driver_t pps_driver = { 344 PPS_NAME, 345 pps_methods, 346 sizeof(struct pps_data), 347 }; 348 DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, 0, 0); 349 MODULE_DEPEND(pps, ppbus, 1, 1, 1); 350