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