1 /*- 2 * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/kernel.h> 34 #include <sys/limits.h> 35 #include <sys/lock.h> 36 #include <sys/module.h> 37 #include <sys/mutex.h> 38 #include <sys/resource.h> 39 #include <sys/rman.h> 40 41 #include <machine/bus.h> 42 43 #include <dev/ofw/openfirm.h> 44 #include <dev/ofw/ofw_bus.h> 45 #include <dev/ofw/ofw_bus_subr.h> 46 47 #include <dev/pwm/pwmc.h> 48 49 #include "pwmbus_if.h" 50 51 #include "am335x_pwm.h" 52 53 /******************************************************************************* 54 * Enhanced resolution PWM driver. Many of the advanced featues of the hardware 55 * are not supported by this driver. What is implemented here is simple 56 * variable-duty-cycle PWM output. 57 ******************************************************************************/ 58 59 /* In ticks */ 60 #define DEFAULT_PWM_PERIOD 1000 61 #define PWM_CLOCK 100000000UL 62 63 #define NS_PER_SEC 1000000000 64 65 #define PWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 66 #define PWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 67 #define PWM_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) 68 #define PWM_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \ 69 device_get_nameunit(_sc->sc_dev), "am335x_ehrpwm softc", MTX_DEF) 70 #define PWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) 71 72 #define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res, reg) 73 #define EPWM_WRITE2(_sc, reg, value) \ 74 bus_write_2((_sc)->sc_mem_res, reg, value) 75 76 #define EPWM_TBCTL 0x00 77 /* see 15.2.2.11 for the first two, used in debug situations */ 78 #define TBCTL_FREERUN_STOP_NEXT_TBC_INCREMENT (0 << 14) 79 #define TBCTL_FREERUN_STOP_COMPLETE_CYCLE (1 << 14) 80 /* ignore suspend control signal */ 81 #define TBCTL_FREERUN (2 << 14) 82 83 #define TBCTL_PHDIR_UP (1 << 13) 84 #define TBCTL_PHDIR_DOWN (0 << 13) 85 #define TBCTL_CLKDIV(x) ((x) << 10) 86 #define TBCTL_CLKDIV_MASK (7 << 10) 87 #define TBCTL_HSPCLKDIV(x) ((x) << 7) 88 #define TBCTL_HSPCLKDIV_MASK (7 << 7) 89 #define TBCTL_SYNCOSEL_DISABLED (3 << 4) 90 #define TBCTL_PRDLD_SHADOW (0 << 3) 91 #define TBCTL_PRDLD_IMMEDIATE (1 << 3) 92 #define TBCTL_PHSEN_DISABLED (0 << 2) 93 #define TBCTL_PHSEN_ENABLED (1 << 2) 94 #define TBCTL_CTRMODE_MASK (3) 95 #define TBCTL_CTRMODE_UP (0 << 0) 96 #define TBCTL_CTRMODE_DOWN (1 << 0) 97 #define TBCTL_CTRMODE_UPDOWN (2 << 0) 98 #define TBCTL_CTRMODE_FREEZE (3 << 0) 99 100 #define EPWM_TBSTS 0x02 101 #define EPWM_TBPHSHR 0x04 102 #define EPWM_TBPHS 0x06 103 #define EPWM_TBCNT 0x08 104 #define EPWM_TBPRD 0x0a 105 /* Counter-compare */ 106 #define EPWM_CMPCTL 0x0e 107 #define CMPCTL_SHDWBMODE_SHADOW (1 << 6) 108 #define CMPCTL_SHDWBMODE_IMMEDIATE (0 << 6) 109 #define CMPCTL_SHDWAMODE_SHADOW (1 << 4) 110 #define CMPCTL_SHDWAMODE_IMMEDIATE (0 << 4) 111 #define CMPCTL_LOADBMODE_ZERO (0 << 2) 112 #define CMPCTL_LOADBMODE_PRD (1 << 2) 113 #define CMPCTL_LOADBMODE_EITHER (2 << 2) 114 #define CMPCTL_LOADBMODE_FREEZE (3 << 2) 115 #define CMPCTL_LOADAMODE_ZERO (0 << 0) 116 #define CMPCTL_LOADAMODE_PRD (1 << 0) 117 #define CMPCTL_LOADAMODE_EITHER (2 << 0) 118 #define CMPCTL_LOADAMODE_FREEZE (3 << 0) 119 #define EPWM_CMPAHR 0x10 120 #define EPWM_CMPA 0x12 121 #define EPWM_CMPB 0x14 122 /* CMPCTL_LOADAMODE_ZERO */ 123 #define EPWM_AQCTLA 0x16 124 #define EPWM_AQCTLB 0x18 125 #define AQCTL_CBU_NONE (0 << 8) 126 #define AQCTL_CBU_CLEAR (1 << 8) 127 #define AQCTL_CBU_SET (2 << 8) 128 #define AQCTL_CBU_TOGGLE (3 << 8) 129 #define AQCTL_CAU_NONE (0 << 4) 130 #define AQCTL_CAU_CLEAR (1 << 4) 131 #define AQCTL_CAU_SET (2 << 4) 132 #define AQCTL_CAU_TOGGLE (3 << 4) 133 #define AQCTL_ZRO_NONE (0 << 0) 134 #define AQCTL_ZRO_CLEAR (1 << 0) 135 #define AQCTL_ZRO_SET (2 << 0) 136 #define AQCTL_ZRO_TOGGLE (3 << 0) 137 #define EPWM_AQSFRC 0x1a 138 #define EPWM_AQCSFRC 0x1c 139 #define AQCSFRC_OFF 0 140 #define AQCSFRC_LO 1 141 #define AQCSFRC_HI 2 142 #define AQCSFRC_MASK 3 143 #define AQCSFRC(chan, hilo) ((hilo) << (2 * chan)) 144 145 /* Trip-Zone module */ 146 #define EPWM_TZSEL 0x24 147 #define EPWM_TZCTL 0x28 148 #define EPWM_TZFLG 0x2C 149 150 /* Dead band */ 151 #define EPWM_DBCTL 0x1E 152 #define DBCTL_MASK (3 << 0) 153 #define DBCTL_BYPASS 0 154 #define DBCTL_RISING_EDGE 1 155 #define DBCTL_FALLING_EDGE 2 156 #define DBCTL_BOTH_EDGE 3 157 158 /* PWM-chopper */ 159 #define EPWM_PCCTL 0x3C 160 #define PCCTL_CHPEN_MASK (1 << 0) 161 #define PCCTL_CHPEN_DISABLE 0 162 #define PCCTL_CHPEN_ENABLE 1 163 164 /* High-Resolution PWM */ 165 #define EPWM_HRCTL 0x40 166 #define HRCTL_DELMODE_BOTH 3 167 #define HRCTL_DELMODE_FALL 2 168 #define HRCTL_DELMODE_RISE 1 169 170 static device_probe_t am335x_ehrpwm_probe; 171 static device_attach_t am335x_ehrpwm_attach; 172 static device_detach_t am335x_ehrpwm_detach; 173 174 struct ehrpwm_channel { 175 u_int duty; /* on duration, in ns */ 176 bool enabled; /* channel enabled? */ 177 bool inverted; /* signal inverted? */ 178 }; 179 #define NUM_CHANNELS 2 180 181 struct am335x_ehrpwm_softc { 182 device_t sc_dev; 183 device_t sc_busdev; 184 struct mtx sc_mtx; 185 struct resource *sc_mem_res; 186 int sc_mem_rid; 187 188 /* Things used for configuration via pwm(9) api. */ 189 u_int sc_clkfreq; /* frequency in Hz */ 190 u_int sc_clktick; /* duration in ns */ 191 u_int sc_period; /* duration in ns */ 192 struct ehrpwm_channel sc_channels[NUM_CHANNELS]; 193 }; 194 195 static struct ofw_compat_data compat_data[] = { 196 {"ti,am3352-ehrpwm", true}, 197 {"ti,am33xx-ehrpwm", true}, 198 {NULL, false}, 199 }; 200 SIMPLEBUS_PNP_INFO(compat_data); 201 202 static void 203 am335x_ehrpwm_cfg_duty(struct am335x_ehrpwm_softc *sc, u_int chan, u_int duty) 204 { 205 u_int tbcmp; 206 207 if (duty == 0) 208 tbcmp = 0; 209 else 210 tbcmp = max(1, duty / sc->sc_clktick); 211 212 sc->sc_channels[chan].duty = tbcmp * sc->sc_clktick; 213 214 PWM_LOCK_ASSERT(sc); 215 EPWM_WRITE2(sc, (chan == 0) ? EPWM_CMPA : EPWM_CMPB, tbcmp); 216 } 217 218 static void 219 am335x_ehrpwm_cfg_enable(struct am335x_ehrpwm_softc *sc, u_int chan, bool enable) 220 { 221 uint16_t regval; 222 223 sc->sc_channels[chan].enabled = enable; 224 225 /* 226 * Turn off any existing software-force of the channel, then force 227 * it in the right direction (high or low) if it's not being enabled. 228 */ 229 PWM_LOCK_ASSERT(sc); 230 regval = EPWM_READ2(sc, EPWM_AQCSFRC); 231 regval &= ~AQCSFRC(chan, AQCSFRC_MASK); 232 if (!sc->sc_channels[chan].enabled) { 233 if (sc->sc_channels[chan].inverted) 234 regval |= AQCSFRC(chan, AQCSFRC_HI); 235 else 236 regval |= AQCSFRC(chan, AQCSFRC_LO); 237 } 238 EPWM_WRITE2(sc, EPWM_AQCSFRC, regval); 239 } 240 241 static bool 242 am335x_ehrpwm_cfg_period(struct am335x_ehrpwm_softc *sc, u_int period) 243 { 244 uint16_t regval; 245 u_int clkdiv, hspclkdiv, pwmclk, pwmtick, tbprd; 246 247 /* Can't do a period shorter than 2 clock ticks. */ 248 if (period < 2 * NS_PER_SEC / PWM_CLOCK) { 249 sc->sc_clkfreq = 0; 250 sc->sc_clktick = 0; 251 sc->sc_period = 0; 252 return (false); 253 } 254 255 /* 256 * Figure out how much we have to divide down the base 100MHz clock so 257 * that we can express the requested period as a 16-bit tick count. 258 */ 259 tbprd = 0; 260 for (clkdiv = 0; clkdiv < 8; ++clkdiv) { 261 const u_int cd = 1 << clkdiv; 262 for (hspclkdiv = 0; hspclkdiv < 8; ++hspclkdiv) { 263 const u_int cdhs = max(1, hspclkdiv * 2); 264 pwmclk = PWM_CLOCK / (cd * cdhs); 265 pwmtick = NS_PER_SEC / pwmclk; 266 if (period / pwmtick < 65536) { 267 tbprd = period / pwmtick; 268 break; 269 } 270 } 271 if (tbprd != 0) 272 break; 273 } 274 275 /* Handle requested period too long for available clock divisors. */ 276 if (tbprd == 0) 277 return (false); 278 279 /* 280 * If anything has changed from the current settings, reprogram the 281 * clock divisors and period register. 282 */ 283 if (sc->sc_clkfreq != pwmclk || sc->sc_clktick != pwmtick || 284 sc->sc_period != tbprd * pwmtick) { 285 sc->sc_clkfreq = pwmclk; 286 sc->sc_clktick = pwmtick; 287 sc->sc_period = tbprd * pwmtick; 288 289 PWM_LOCK_ASSERT(sc); 290 regval = EPWM_READ2(sc, EPWM_TBCTL); 291 regval &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK); 292 regval |= TBCTL_CLKDIV(clkdiv) | TBCTL_HSPCLKDIV(hspclkdiv); 293 EPWM_WRITE2(sc, EPWM_TBCTL, regval); 294 EPWM_WRITE2(sc, EPWM_TBPRD, tbprd - 1); 295 #if 0 296 device_printf(sc->sc_dev, "clkdiv %u hspclkdiv %u tbprd %u " 297 "clkfreq %u Hz clktick %u ns period got %u requested %u\n", 298 clkdiv, hspclkdiv, tbprd - 1, 299 sc->sc_clkfreq, sc->sc_clktick, sc->sc_period, period); 300 #endif 301 /* 302 * If the period changed, that invalidates the current CMP 303 * registers (duty values), just zero them out. 304 */ 305 am335x_ehrpwm_cfg_duty(sc, 0, 0); 306 am335x_ehrpwm_cfg_duty(sc, 1, 0); 307 } 308 309 return (true); 310 } 311 312 static int 313 am335x_ehrpwm_channel_count(device_t dev, u_int *nchannel) 314 { 315 316 *nchannel = NUM_CHANNELS; 317 318 return (0); 319 } 320 321 static int 322 am335x_ehrpwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty) 323 { 324 struct am335x_ehrpwm_softc *sc; 325 bool status; 326 327 if (channel >= NUM_CHANNELS) 328 return (EINVAL); 329 330 sc = device_get_softc(dev); 331 332 PWM_LOCK(sc); 333 status = am335x_ehrpwm_cfg_period(sc, period); 334 if (status) 335 am335x_ehrpwm_cfg_duty(sc, channel, duty); 336 PWM_UNLOCK(sc); 337 338 return (status ? 0 : EINVAL); 339 } 340 341 static int 342 am335x_ehrpwm_channel_get_config(device_t dev, u_int channel, 343 u_int *period, u_int *duty) 344 { 345 struct am335x_ehrpwm_softc *sc; 346 347 if (channel >= NUM_CHANNELS) 348 return (EINVAL); 349 350 sc = device_get_softc(dev); 351 *period = sc->sc_period; 352 *duty = sc->sc_channels[channel].duty; 353 return (0); 354 } 355 356 static int 357 am335x_ehrpwm_channel_set_flags(device_t dev, u_int channel, 358 uint32_t flags) 359 { 360 struct am335x_ehrpwm_softc *sc; 361 362 if (channel >= NUM_CHANNELS) 363 return (EINVAL); 364 365 sc = device_get_softc(dev); 366 367 PWM_LOCK(sc); 368 if (flags & PWM_POLARITY_INVERTED) { 369 sc->sc_channels[channel].inverted = true; 370 /* Action-Qualifier 15.2.2.5 */ 371 if (channel == 0) 372 EPWM_WRITE2(sc, EPWM_AQCTLA, 373 (AQCTL_ZRO_CLEAR | AQCTL_CAU_SET)); 374 else 375 EPWM_WRITE2(sc, EPWM_AQCTLB, 376 (AQCTL_ZRO_CLEAR | AQCTL_CBU_SET)); 377 } else { 378 sc->sc_channels[channel].inverted = false; 379 if (channel == 0) 380 EPWM_WRITE2(sc, EPWM_AQCTLA, 381 (AQCTL_ZRO_SET | AQCTL_CAU_CLEAR)); 382 else 383 EPWM_WRITE2(sc, EPWM_AQCTLB, 384 (AQCTL_ZRO_SET | AQCTL_CBU_CLEAR)); 385 } 386 PWM_UNLOCK(sc); 387 388 return (0); 389 } 390 391 static int 392 am335x_ehrpwm_channel_get_flags(device_t dev, u_int channel, 393 uint32_t *flags) 394 { 395 struct am335x_ehrpwm_softc *sc; 396 if (channel >= NUM_CHANNELS) 397 return (EINVAL); 398 399 sc = device_get_softc(dev); 400 401 if (sc->sc_channels[channel].inverted == true) 402 *flags = PWM_POLARITY_INVERTED; 403 else 404 *flags = 0; 405 406 return (0); 407 } 408 409 410 static int 411 am335x_ehrpwm_channel_enable(device_t dev, u_int channel, bool enable) 412 { 413 struct am335x_ehrpwm_softc *sc; 414 415 if (channel >= NUM_CHANNELS) 416 return (EINVAL); 417 418 sc = device_get_softc(dev); 419 420 PWM_LOCK(sc); 421 am335x_ehrpwm_cfg_enable(sc, channel, enable); 422 PWM_UNLOCK(sc); 423 424 return (0); 425 } 426 427 static int 428 am335x_ehrpwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled) 429 { 430 struct am335x_ehrpwm_softc *sc; 431 432 if (channel >= NUM_CHANNELS) 433 return (EINVAL); 434 435 sc = device_get_softc(dev); 436 437 *enabled = sc->sc_channels[channel].enabled; 438 439 return (0); 440 } 441 442 static int 443 am335x_ehrpwm_probe(device_t dev) 444 { 445 446 if (!ofw_bus_status_okay(dev)) 447 return (ENXIO); 448 449 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 450 return (ENXIO); 451 452 device_set_desc(dev, "AM335x EHRPWM"); 453 454 return (BUS_PROBE_DEFAULT); 455 } 456 457 static int 458 am335x_ehrpwm_attach(device_t dev) 459 { 460 struct am335x_ehrpwm_softc *sc; 461 uint16_t reg; 462 463 sc = device_get_softc(dev); 464 sc->sc_dev = dev; 465 466 PWM_LOCK_INIT(sc); 467 468 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 469 &sc->sc_mem_rid, RF_ACTIVE); 470 if (sc->sc_mem_res == NULL) { 471 device_printf(dev, "cannot allocate memory resources\n"); 472 goto fail; 473 } 474 475 /* CONFIGURE EPWM */ 476 reg = EPWM_READ2(sc, EPWM_TBCTL); 477 reg &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK); 478 EPWM_WRITE2(sc, EPWM_TBCTL, reg); 479 480 EPWM_WRITE2(sc, EPWM_TBPRD, DEFAULT_PWM_PERIOD - 1); 481 EPWM_WRITE2(sc, EPWM_CMPA, 0); 482 EPWM_WRITE2(sc, EPWM_CMPB, 0); 483 484 /* Action-Qualifier 15.2.2.5 */ 485 EPWM_WRITE2(sc, EPWM_AQCTLA, (AQCTL_ZRO_SET | AQCTL_CAU_CLEAR)); 486 EPWM_WRITE2(sc, EPWM_AQCTLB, (AQCTL_ZRO_SET | AQCTL_CBU_CLEAR)); 487 488 /* Dead band 15.2.2.6 */ 489 reg = EPWM_READ2(sc, EPWM_DBCTL); 490 reg &= ~DBCTL_MASK; 491 reg |= DBCTL_BYPASS; 492 EPWM_WRITE2(sc, EPWM_DBCTL, reg); 493 494 /* PWM-chopper described in 15.2.2.7 */ 495 /* Acc. TRM used in pulse transformerbased gate drivers 496 * to control the power switching-elements 497 */ 498 reg = EPWM_READ2(sc, EPWM_PCCTL); 499 reg &= ~PCCTL_CHPEN_MASK; 500 reg |= PCCTL_CHPEN_DISABLE; 501 EPWM_WRITE2(sc, EPWM_PCCTL, PCCTL_CHPEN_DISABLE); 502 503 /* Trip zone are described in 15.2.2.8. 504 * Essential its used to detect faults and can be configured 505 * to react on such faults.. 506 */ 507 /* disable TZn as one-shot / CVC trip source 15.2.4.18 */ 508 EPWM_WRITE2(sc, EPWM_TZSEL, 0x0); 509 /* reg described in 15.2.4.19 */ 510 EPWM_WRITE2(sc, EPWM_TZCTL, 0xf); 511 reg = EPWM_READ2(sc, EPWM_TZFLG); 512 513 /* START EPWM */ 514 reg &= ~TBCTL_CTRMODE_MASK; 515 reg |= TBCTL_CTRMODE_UP | TBCTL_FREERUN; 516 EPWM_WRITE2(sc, EPWM_TBCTL, reg); 517 518 if ((sc->sc_busdev = device_add_child(dev, "pwmbus", -1)) == NULL) { 519 device_printf(dev, "Cannot add child pwmbus\n"); 520 // This driver can still do things even without the bus child. 521 } 522 523 bus_generic_probe(dev); 524 return (bus_generic_attach(dev)); 525 fail: 526 PWM_LOCK_DESTROY(sc); 527 if (sc->sc_mem_res) 528 bus_release_resource(dev, SYS_RES_MEMORY, 529 sc->sc_mem_rid, sc->sc_mem_res); 530 531 return(ENXIO); 532 } 533 534 static int 535 am335x_ehrpwm_detach(device_t dev) 536 { 537 struct am335x_ehrpwm_softc *sc; 538 int error; 539 540 sc = device_get_softc(dev); 541 542 if ((error = bus_generic_detach(sc->sc_dev)) != 0) 543 return (error); 544 545 PWM_LOCK(sc); 546 547 if (sc->sc_busdev != NULL) 548 device_delete_child(dev, sc->sc_busdev); 549 550 if (sc->sc_mem_res) 551 bus_release_resource(dev, SYS_RES_MEMORY, 552 sc->sc_mem_rid, sc->sc_mem_res); 553 554 PWM_UNLOCK(sc); 555 556 PWM_LOCK_DESTROY(sc); 557 558 return (0); 559 } 560 561 static phandle_t 562 am335x_ehrpwm_get_node(device_t bus, device_t dev) 563 { 564 565 /* 566 * Share our controller node with our pwmbus child; it instantiates 567 * devices by walking the children contained within our node. 568 */ 569 return ofw_bus_get_node(bus); 570 } 571 572 static device_method_t am335x_ehrpwm_methods[] = { 573 DEVMETHOD(device_probe, am335x_ehrpwm_probe), 574 DEVMETHOD(device_attach, am335x_ehrpwm_attach), 575 DEVMETHOD(device_detach, am335x_ehrpwm_detach), 576 577 /* ofw_bus_if */ 578 DEVMETHOD(ofw_bus_get_node, am335x_ehrpwm_get_node), 579 580 /* pwm interface */ 581 DEVMETHOD(pwmbus_channel_count, am335x_ehrpwm_channel_count), 582 DEVMETHOD(pwmbus_channel_config, am335x_ehrpwm_channel_config), 583 DEVMETHOD(pwmbus_channel_get_config, am335x_ehrpwm_channel_get_config), 584 DEVMETHOD(pwmbus_channel_set_flags, am335x_ehrpwm_channel_set_flags), 585 DEVMETHOD(pwmbus_channel_get_flags, am335x_ehrpwm_channel_get_flags), 586 DEVMETHOD(pwmbus_channel_enable, am335x_ehrpwm_channel_enable), 587 DEVMETHOD(pwmbus_channel_is_enabled, am335x_ehrpwm_channel_is_enabled), 588 589 DEVMETHOD_END 590 }; 591 592 static driver_t am335x_ehrpwm_driver = { 593 "pwm", 594 am335x_ehrpwm_methods, 595 sizeof(struct am335x_ehrpwm_softc), 596 }; 597 598 DRIVER_MODULE(am335x_ehrpwm, am335x_pwmss, am335x_ehrpwm_driver, 0, 0); 599 MODULE_VERSION(am335x_ehrpwm, 1); 600 MODULE_DEPEND(am335x_ehrpwm, am335x_pwmss, 1, 1, 1); 601 MODULE_DEPEND(am335x_ehrpwm, pwmbus, 1, 1, 1); 602