1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2017 Poul-Henning Kamp <phk@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/rman.h> 37 #include <sys/lock.h> 38 #include <sys/sysctl.h> 39 40 #include <machine/bus.h> 41 #include <machine/resource.h> 42 43 #include <dev/ofw/ofw_bus.h> 44 #include <dev/ofw/ofw_bus_subr.h> 45 46 #include <arm/broadcom/bcm2835/bcm2835_clkman.h> 47 48 static struct ofw_compat_data compat_data[] = { 49 {"broadcom,bcm2835-pwm", 1}, 50 {"brcm,bcm2835-pwm", 1}, 51 {NULL, 0} 52 }; 53 54 struct bcm_pwm_softc { 55 device_t sc_dev; 56 57 struct resource * sc_mem_res; 58 bus_space_tag_t sc_m_bst; 59 bus_space_handle_t sc_m_bsh; 60 61 device_t clkman; 62 63 uint32_t freq; /* shared between channels 1 and 2 */ 64 uint32_t period; /* channel 1 */ 65 uint32_t ratio; 66 uint32_t mode; 67 uint32_t period2; /* channel 2 */ 68 uint32_t ratio2; 69 uint32_t mode2; 70 }; 71 72 #define BCM_PWM_MEM_WRITE(_sc, _off, _val) \ 73 bus_space_write_4(_sc->sc_m_bst, _sc->sc_m_bsh, _off, _val) 74 #define BCM_PWM_MEM_READ(_sc, _off) \ 75 bus_space_read_4(_sc->sc_m_bst, _sc->sc_m_bsh, _off) 76 #define BCM_PWM_CLK_WRITE(_sc, _off, _val) \ 77 bus_space_write_4(_sc->sc_c_bst, _sc->sc_c_bsh, _off, _val) 78 #define BCM_PWM_CLK_READ(_sc, _off) \ 79 bus_space_read_4(_sc->sc_c_bst, _sc->sc_c_bsh, _off) 80 81 #define W_CTL(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x00, _val) 82 #define R_CTL(_sc) BCM_PWM_MEM_READ(_sc, 0x00) 83 #define W_STA(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x04, _val) 84 #define R_STA(_sc) BCM_PWM_MEM_READ(_sc, 0x04) 85 #define W_RNG(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x10, _val) 86 #define R_RNG(_sc) BCM_PWM_MEM_READ(_sc, 0x10) 87 #define W_DAT(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x14, _val) 88 #define R_DAT(_sc) BCM_PWM_MEM_READ(_sc, 0x14) 89 #define W_RNG2(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x20, _val) 90 #define R_RNG2(_sc) BCM_PWM_MEM_READ(_sc, 0x20) 91 #define W_DAT2(_sc, _val) BCM_PWM_MEM_WRITE(_sc, 0x24, _val) 92 #define R_DAT2(_sc) BCM_PWM_MEM_READ(_sc, 0x24) 93 94 static int 95 bcm_pwm_reconf(struct bcm_pwm_softc *sc) 96 { 97 uint32_t u, ctlr; 98 99 /* Disable PWM */ 100 W_CTL(sc, 0); 101 102 /* Stop PWM clock */ 103 (void)bcm2835_clkman_set_frequency(sc->clkman, BCM_PWM_CLKSRC, 0); 104 105 ctlr = 0; /* pre-assign zero, enable bits, write to CTL at end */ 106 107 if (sc->mode == 0 && sc->mode2 == 0) /* both modes are zero */ 108 return 0; /* device is now off - return */ 109 110 /* set the PWM clock frequency */ 111 /* TODO: should I only do this if it changes and not stop it first? */ 112 u = bcm2835_clkman_set_frequency(sc->clkman, BCM_PWM_CLKSRC, sc->freq); 113 if (u == 0) 114 return (EINVAL); 115 sc->freq = u; 116 117 /* control register CTL bits: 118 * (from BCM2835 ARM Peripherals manual, section 9.6) 119 * 120 * 15 MSEN2 chan 2 M/S enable; 0 for PWM algo, 1 for M/S transmission 121 * 14 unused; always reads as 0 122 * 13 USEF2 chan 2 use FIFO (0 uses data; 1 uses FIFO) 123 * 12 POLA2 chan 2 invert polarity (0 normal, 1 inverted polarity) 124 * 11 SBIT2 chan 2 'Silence' bit (when not transmitting data) 125 * 10 RPTL2 chan 2 FIFO repeat last data (1 repeats, 0 interrupts) 126 * 9 MODE2 chan 2 PWM/Serializer mode (0 PWM, 1 Serializer) 127 * 8 PWEN2 chan 2 enable (0 disable, 1 enable) 128 * 7 MSEN1 chan 1 M/S enable; 0 for PWM algo, 1 for M/S transmission 129 * 6 CLRF1 chan 1 clear FIFO (set 1 to clear; always reads as 0) 130 * 5 USEF1 chan 1 use FIFO (0 uses data; 1 uses FIFO) 131 * 4 POLA1 chan 1 invert polarity (0 normal, 1 inverted polarity) 132 * 3 SBIT1 chan 1 'Silence' bit (when not transmitting data) 133 * 2 RTPL1 chan 1 FIFO repeat last data (1 repeats, 0 interrupts) 134 * 1 MODE1 chan 1 PWM/Serializer mode (0 PWM, 1 Serializer) 135 * 0 PWMEN1 chan 1 enable (0 disable, 1 enable) 136 * 137 * Notes on M/S enable: when this bit is '1', a simple M/S ratio is used. In short, 138 * the value of 'ratio' is the number of 'on' bits, and the total length of the data is 139 * defined by 'period'. So if 'ratio' is 2500 and 'period' is 10000, then the output 140 * remains 'on' for 2500 clocks, and goes 'off' for the remaining 7500 clocks. 141 * When the M/S enable is '0', a more complicated algorithm effectively 'dithers' the 142 * pulses in order to obtain the desired ratio. For details, see section 9.3 of the 143 * BCM2835 ARM Peripherals manual. 144 */ 145 146 if (sc->mode != 0) { 147 /* Config PWM Channel 1 */ 148 W_RNG(sc, sc->period); 149 if (sc->ratio > sc->period) 150 sc->ratio = sc->period; 151 W_DAT(sc, sc->ratio); 152 153 /* Start PWM Channel 1 */ 154 if (sc->mode == 1) 155 ctlr |= 0x81; /* chan 1 enable + chan 1 M/S enable */ 156 else 157 ctlr |= 0x1; /* chan 1 enable */ 158 } 159 160 if (sc->mode2 != 0) { 161 /* Config PWM Channel 2 */ 162 W_RNG2(sc, sc->period2); 163 if (sc->ratio2 > sc->period2) 164 sc->ratio2 = sc->period2; 165 W_DAT2(sc, sc->ratio2); 166 167 /* Start PWM Channel 2 */ 168 if (sc->mode2 == 1) 169 ctlr |= 0x8100; /* chan 2 enable + chan 2 M/S enable */ 170 else 171 ctlr |= 0x100; /* chan 2 enable */ 172 } 173 174 /* write CTL register with updated value */ 175 W_CTL(sc, ctlr); 176 177 return (0); 178 } 179 180 static int 181 bcm_pwm_pwm_freq_proc(SYSCTL_HANDLER_ARGS) 182 { 183 struct bcm_pwm_softc *sc; 184 uint32_t r; 185 int error; 186 187 sc = (struct bcm_pwm_softc *)arg1; 188 if (sc->mode == 1) 189 r = sc->freq / sc->period; 190 else 191 r = 0; 192 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 193 return (error); 194 } 195 196 static int 197 bcm_pwm_mode_proc(SYSCTL_HANDLER_ARGS) 198 { 199 struct bcm_pwm_softc *sc; 200 uint32_t r; 201 int error; 202 203 sc = (struct bcm_pwm_softc *)arg1; 204 r = sc->mode; 205 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 206 if (error != 0 || req->newptr == NULL) 207 return (error); 208 if (r > 2) 209 return (EINVAL); 210 sc->mode = r; 211 return (bcm_pwm_reconf(sc)); 212 } 213 214 static int 215 bcm_pwm_freq_proc(SYSCTL_HANDLER_ARGS) 216 { 217 struct bcm_pwm_softc *sc; 218 uint32_t r; 219 int error; 220 221 sc = (struct bcm_pwm_softc *)arg1; 222 r = sc->freq; 223 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 224 if (error != 0 || req->newptr == NULL) 225 return (error); 226 if (r > 125000000) 227 return (EINVAL); 228 sc->freq = r; 229 return (bcm_pwm_reconf(sc)); 230 } 231 232 static int 233 bcm_pwm_period_proc(SYSCTL_HANDLER_ARGS) 234 { 235 struct bcm_pwm_softc *sc; 236 int error; 237 238 sc = (struct bcm_pwm_softc *)arg1; 239 error = sysctl_handle_int(oidp, &sc->period, sizeof(sc->period), req); 240 if (error != 0 || req->newptr == NULL) 241 return (error); 242 return (bcm_pwm_reconf(sc)); 243 } 244 245 static int 246 bcm_pwm_ratio_proc(SYSCTL_HANDLER_ARGS) 247 { 248 struct bcm_pwm_softc *sc; 249 uint32_t r; 250 int error; 251 252 sc = (struct bcm_pwm_softc *)arg1; 253 r = sc->ratio; 254 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 255 if (error != 0 || req->newptr == NULL) 256 return (error); 257 if (r > sc->period) // XXX >= ? 258 return (EINVAL); 259 sc->ratio = r; 260 W_DAT(sc, sc->ratio); 261 return (0); 262 } 263 264 static int 265 bcm_pwm_pwm_freq2_proc(SYSCTL_HANDLER_ARGS) 266 { 267 struct bcm_pwm_softc *sc; 268 uint32_t r; 269 int error; 270 271 sc = (struct bcm_pwm_softc *)arg1; 272 if (sc->mode2 == 1) 273 r = sc->freq / sc->period2; 274 else 275 r = 0; 276 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 277 return (error); 278 } 279 280 static int 281 bcm_pwm_mode2_proc(SYSCTL_HANDLER_ARGS) 282 { 283 struct bcm_pwm_softc *sc; 284 uint32_t r; 285 int error; 286 287 sc = (struct bcm_pwm_softc *)arg1; 288 r = sc->mode2; 289 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 290 if (error != 0 || req->newptr == NULL) 291 return (error); 292 if (r > 2) 293 return (EINVAL); 294 sc->mode2 = r; 295 return (bcm_pwm_reconf(sc)); 296 } 297 298 static int 299 bcm_pwm_period2_proc(SYSCTL_HANDLER_ARGS) 300 { 301 struct bcm_pwm_softc *sc; 302 int error; 303 304 sc = (struct bcm_pwm_softc *)arg1; 305 error = sysctl_handle_int(oidp, &sc->period2, sizeof(sc->period2), req); 306 if (error != 0 || req->newptr == NULL) 307 return (error); 308 return (bcm_pwm_reconf(sc)); 309 } 310 311 static int 312 bcm_pwm_ratio2_proc(SYSCTL_HANDLER_ARGS) 313 { 314 struct bcm_pwm_softc *sc; 315 uint32_t r; 316 int error; 317 318 sc = (struct bcm_pwm_softc *)arg1; 319 r = sc->ratio2; 320 error = sysctl_handle_int(oidp, &r, sizeof(r), req); 321 if (error != 0 || req->newptr == NULL) 322 return (error); 323 if (r > sc->period2) // XXX >= ? 324 return (EINVAL); 325 sc->ratio2 = r; 326 W_DAT(sc, sc->ratio2); 327 return (0); 328 } 329 330 static int 331 bcm_pwm_reg_proc(SYSCTL_HANDLER_ARGS) 332 { 333 struct bcm_pwm_softc *sc; 334 uint32_t reg; 335 int error; 336 337 sc = (struct bcm_pwm_softc *)arg1; 338 reg = BCM_PWM_MEM_READ(sc, arg2 & 0xff); 339 340 error = sysctl_handle_int(oidp, ®, sizeof(reg), req); 341 if (error != 0 || req->newptr == NULL) 342 return (error); 343 344 BCM_PWM_MEM_WRITE(sc, arg2, reg); 345 return (0); 346 } 347 348 static void 349 bcm_pwm_sysctl_init(struct bcm_pwm_softc *sc) 350 { 351 struct sysctl_ctx_list *ctx; 352 struct sysctl_oid *tree_node; 353 struct sysctl_oid_list *tree; 354 355 /* 356 * Add system sysctl tree/handlers. 357 */ 358 ctx = device_get_sysctl_ctx(sc->sc_dev); 359 tree_node = device_get_sysctl_tree(sc->sc_dev); 360 tree = SYSCTL_CHILDREN(tree_node); 361 if (bootverbose) { 362 #define RR(x,y) \ 363 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, y, \ 364 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, \ 365 sc, 0x##x, \ 366 bcm_pwm_reg_proc, "IU", "Register 0x" #x " " y); 367 368 RR(24, "DAT2") 369 RR(20, "RNG2") 370 RR(18, "FIF1") 371 RR(14, "DAT1") 372 RR(10, "RNG1") 373 RR(08, "DMAC") 374 RR(04, "STA") 375 RR(00, "CTL") 376 #undef RR 377 } 378 379 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "pwm_freq", 380 CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 381 bcm_pwm_pwm_freq_proc, "IU", "PWM frequency ch 1 (Hz)"); 382 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "period", 383 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 384 bcm_pwm_period_proc, "IU", "PWM period ch 1 (#clocks)"); 385 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "ratio", 386 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 387 bcm_pwm_ratio_proc, "IU", "PWM ratio ch 1 (0...period)"); 388 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "freq", 389 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 390 bcm_pwm_freq_proc, "IU", "PWM clock (Hz)"); 391 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "mode", 392 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 393 bcm_pwm_mode_proc, "IU", "PWM mode ch 1 (0=off, 1=pwm, 2=dither)"); 394 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "pwm_freq2", 395 CTLFLAG_RD | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 396 bcm_pwm_pwm_freq2_proc, "IU", "PWM frequency ch 2 (Hz)"); 397 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "period2", 398 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 399 bcm_pwm_period2_proc, "IU", "PWM period ch 2 (#clocks)"); 400 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "ratio2", 401 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 402 bcm_pwm_ratio2_proc, "IU", "PWM ratio ch 2 (0...period)"); 403 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "mode2", 404 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT, sc, 0, 405 bcm_pwm_mode2_proc, "IU", "PWM mode ch 2 (0=off, 1=pwm, 2=dither)"); 406 } 407 408 static int 409 bcm_pwm_probe(device_t dev) 410 { 411 412 if (!ofw_bus_status_okay(dev)) 413 return (ENXIO); 414 415 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 416 return (ENXIO); 417 418 device_set_desc(dev, "BCM2708/2835 PWM controller"); 419 420 return (BUS_PROBE_DEFAULT); 421 } 422 423 static int 424 bcm_pwm_attach(device_t dev) 425 { 426 struct bcm_pwm_softc *sc; 427 int rid; 428 429 if (device_get_unit(dev) != 0) { 430 device_printf(dev, "only one PWM controller supported\n"); 431 return (ENXIO); 432 } 433 434 sc = device_get_softc(dev); 435 sc->sc_dev = dev; 436 437 sc->clkman = devclass_get_device(devclass_find("bcm2835_clkman"), 0); 438 if (sc->clkman == NULL) { 439 device_printf(dev, "cannot find Clock Manager\n"); 440 return (ENXIO); 441 } 442 443 rid = 0; 444 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 445 RF_ACTIVE); 446 if (!sc->sc_mem_res) { 447 device_printf(dev, "cannot allocate memory window\n"); 448 return (ENXIO); 449 } 450 451 sc->sc_m_bst = rman_get_bustag(sc->sc_mem_res); 452 sc->sc_m_bsh = rman_get_bushandle(sc->sc_mem_res); 453 454 /* Add sysctl nodes. */ 455 bcm_pwm_sysctl_init(sc); 456 457 sc->freq = 125000000; /* 125 Mhz */ 458 sc->period = 10000; /* 12.5 khz */ 459 sc->ratio = 2500; /* 25% */ 460 sc->period2 = 10000; /* 12.5 khz */ 461 sc->ratio2 = 2500; /* 25% */ 462 463 bus_attach_children(dev); 464 return (0); 465 } 466 467 static int 468 bcm_pwm_detach(device_t dev) 469 { 470 struct bcm_pwm_softc *sc; 471 472 bus_generic_detach(dev); 473 474 sc = device_get_softc(dev); 475 sc->mode = 0; 476 sc->mode2 = 0; 477 (void)bcm_pwm_reconf(sc); 478 if (sc->sc_mem_res) 479 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 480 481 return (0); 482 } 483 484 static phandle_t 485 bcm_pwm_get_node(device_t bus, device_t dev) 486 { 487 488 return (ofw_bus_get_node(bus)); 489 } 490 491 static device_method_t bcm_pwm_methods[] = { 492 /* Device interface */ 493 DEVMETHOD(device_probe, bcm_pwm_probe), 494 DEVMETHOD(device_attach, bcm_pwm_attach), 495 DEVMETHOD(device_detach, bcm_pwm_detach), 496 DEVMETHOD(ofw_bus_get_node, bcm_pwm_get_node), 497 498 DEVMETHOD_END 499 }; 500 501 static driver_t bcm_pwm_driver = { 502 "pwm", 503 bcm_pwm_methods, 504 sizeof(struct bcm_pwm_softc), 505 }; 506 507 DRIVER_MODULE(bcm2835_pwm, simplebus, bcm_pwm_driver, 0, 0); 508 MODULE_DEPEND(bcm2835_pwm, bcm2835_clkman, 1, 1, 1); 509