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