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