1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org> 5 * Copyright (c) 2019 Brandon Bergren <git@bdragon.rtk0.net> 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * 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 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/bus.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/rman.h> 35 #include <sys/resource.h> 36 #include <machine/bus.h> 37 38 #include <dev/ofw/ofw_bus.h> 39 #include <dev/ofw/ofw_bus_subr.h> 40 41 #include <dev/clk/clk.h> 42 43 #include "pwmbus_if.h" 44 45 /* Register offsets. */ 46 #define RK_PWM_COUNTER 0x00 47 #define RK_PWM_PERIOD 0x04 48 #define RK_PWM_DUTY 0x08 49 #define RK_PWM_CTRL 0x0c 50 51 #define SET(reg,mask,val) reg = ((reg & ~mask) | val) 52 53 #define RK_PWM_CTRL_ENABLE_MASK (1 << 0) 54 #define RK_PWM_CTRL_ENABLED (1 << 0) 55 #define RK_PWM_CTRL_DISABLED (0) 56 57 #define RK_PWM_CTRL_MODE_MASK (3 << 1) 58 #define RK_PWM_CTRL_MODE_ONESHOT (0) 59 #define RK_PWM_CTRL_MODE_CONTINUOUS (1 << 1) 60 #define RK_PWM_CTRL_MODE_CAPTURE (1 << 2) 61 62 #define RK_PWM_CTRL_DUTY_MASK (1 << 3) 63 #define RK_PWM_CTRL_DUTY_POSITIVE (1 << 3) 64 #define RK_PWM_CTRL_DUTY_NEGATIVE (0) 65 66 #define RK_PWM_CTRL_INACTIVE_MASK (1 << 4) 67 #define RK_PWM_CTRL_INACTIVE_POSITIVE (1 << 4) 68 #define RK_PWM_CTRL_INACTIVE_NEGATIVE (0) 69 70 /* PWM Output Alignment */ 71 #define RK_PWM_CTRL_ALIGN_MASK (1 << 5) 72 #define RK_PWM_CTRL_ALIGN_CENTER (1 << 5) 73 #define RK_PWM_CTRL_ALIGN_LEFT (0) 74 75 /* Low power mode: disable prescaler when inactive */ 76 #define RK_PWM_CTRL_LP_MASK (1 << 8) 77 #define RK_PWM_CTRL_LP_ENABLE (1 << 8) 78 #define RK_PWM_CTRL_LP_DISABLE (0) 79 80 /* Clock source: bypass the scaler or not */ 81 #define RK_PWM_CTRL_CLOCKSRC_MASK (1 << 9) 82 #define RK_PWM_CTRL_CLOCKSRC_NONSCALED (0) 83 #define RK_PWM_CTRL_CLOCKSRC_SCALED (1 << 9) 84 85 #define RK_PWM_CTRL_PRESCALE_MASK (7 << 12) 86 #define RK_PWM_CTRL_PRESCALE_SHIFT 12 87 88 #define RK_PWM_CTRL_SCALE_MASK (0xFF << 16) 89 #define RK_PWM_CTRL_SCALE_SHIFT 16 90 91 #define RK_PWM_CTRL_REPEAT_MASK (0xFF << 24) 92 #define RK_PWM_CTRL_REPEAT_SHIFT 24 93 94 #define NS_PER_SEC 1000000000 95 96 static struct ofw_compat_data compat_data[] = { 97 { "rockchip,rk3288-pwm", 1 }, 98 { "rockchip,rk3399-pwm", 1 }, 99 { NULL, 0 } 100 }; 101 102 static struct resource_spec rk_pwm_spec[] = { 103 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 104 { -1, 0 } 105 }; 106 107 struct rk_pwm_softc { 108 device_t dev; 109 device_t busdev; 110 clk_t clk; 111 struct resource *res; 112 113 uint64_t clk_freq; 114 unsigned int period; 115 unsigned int duty; 116 uint32_t flags; 117 uint8_t prescaler; 118 uint8_t scaler; 119 bool using_scaler; 120 bool enabled; 121 }; 122 123 #define RK_PWM_READ(sc, reg) bus_read_4((sc)->res, (reg)) 124 #define RK_PWM_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) 125 126 static int rk_pwm_probe(device_t dev); 127 static int rk_pwm_attach(device_t dev); 128 static int rk_pwm_detach(device_t dev); 129 130 static int 131 rk_pwm_probe(device_t dev) 132 { 133 if (!ofw_bus_status_okay(dev)) 134 return (ENXIO); 135 136 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 137 return (ENXIO); 138 139 device_set_desc(dev, "Rockchip PWM"); 140 return (BUS_PROBE_DEFAULT); 141 } 142 143 static int 144 rk_pwm_attach(device_t dev) 145 { 146 struct rk_pwm_softc *sc; 147 phandle_t node; 148 uint64_t clk_freq; 149 uint32_t reg; 150 int error; 151 152 sc = device_get_softc(dev); 153 sc->dev = dev; 154 155 error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); 156 if (error != 0) { 157 device_printf(dev, "cannot get clock\n"); 158 goto fail; 159 } 160 error = clk_enable(sc->clk); 161 if (error != 0) { 162 device_printf(dev, "cannot enable clock\n"); 163 goto fail; 164 } 165 error = clk_get_freq(sc->clk, &sc->clk_freq); 166 if (error != 0) { 167 device_printf(dev, "cannot get base frequency\n"); 168 goto fail; 169 } 170 171 if (bus_alloc_resources(dev, rk_pwm_spec, &sc->res) != 0) { 172 device_printf(dev, "cannot allocate resources for device\n"); 173 error = ENXIO; 174 goto fail; 175 } 176 177 /* Read the configuration left by U-Boot */ 178 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 179 if ((reg & RK_PWM_CTRL_ENABLE_MASK) == RK_PWM_CTRL_ENABLED) 180 sc->enabled = true; 181 182 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 183 reg &= RK_PWM_CTRL_PRESCALE_MASK; 184 sc->prescaler = reg >> RK_PWM_CTRL_PRESCALE_SHIFT; 185 186 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 187 reg &= RK_PWM_CTRL_SCALE_MASK; 188 sc->scaler = reg >> RK_PWM_CTRL_SCALE_SHIFT; 189 190 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 191 if ((reg & RK_PWM_CTRL_CLOCKSRC_MASK) == RK_PWM_CTRL_CLOCKSRC_SCALED) 192 sc->using_scaler = true; 193 else 194 sc->using_scaler = false; 195 196 clk_freq = sc->clk_freq / (2 ^ sc->prescaler); 197 198 if (sc->using_scaler) { 199 if (sc->scaler == 0) 200 clk_freq /= 512; 201 else 202 clk_freq /= (sc->scaler * 2); 203 } 204 205 reg = RK_PWM_READ(sc, RK_PWM_PERIOD); 206 sc->period = NS_PER_SEC / 207 (clk_freq / reg); 208 reg = RK_PWM_READ(sc, RK_PWM_DUTY); 209 sc->duty = NS_PER_SEC / 210 (clk_freq / reg); 211 212 node = ofw_bus_get_node(dev); 213 OF_device_register_xref(OF_xref_from_node(node), dev); 214 215 sc->busdev = device_add_child(dev, "pwmbus", DEVICE_UNIT_ANY); 216 217 bus_attach_children(dev); 218 return (0); 219 220 fail: 221 rk_pwm_detach(dev); 222 return (error); 223 } 224 225 static int 226 rk_pwm_detach(device_t dev) 227 { 228 struct rk_pwm_softc *sc; 229 230 sc = device_get_softc(dev); 231 232 bus_generic_detach(sc->dev); 233 234 bus_release_resources(dev, rk_pwm_spec, &sc->res); 235 236 return (0); 237 } 238 239 static phandle_t 240 aw_pwm_get_node(device_t bus, device_t dev) 241 { 242 243 /* 244 * Share our controller node with our pwmbus child; it instantiates 245 * devices by walking the children contained within our node. 246 */ 247 return ofw_bus_get_node(bus); 248 } 249 250 static int 251 rk_pwm_channel_count(device_t dev, u_int *nchannel) 252 { 253 /* The device supports 4 channels, but attaches multiple times in the 254 * device tree. This interferes with advanced usage though, as 255 * the interrupt capability and channel 3 FIFO register offsets 256 * don't work right in this situation. 257 * But since we don't support those yet, pretend we are singlechannel. 258 */ 259 *nchannel = 1; 260 261 return (0); 262 } 263 264 static int 265 rk_pwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty) 266 { 267 struct rk_pwm_softc *sc; 268 uint64_t period_freq, duty_freq; 269 uint32_t reg; 270 uint32_t period_out; 271 uint32_t duty_out; 272 uint8_t prescaler; 273 uint8_t scaler; 274 bool using_scaler; 275 276 sc = device_get_softc(dev); 277 278 period_freq = NS_PER_SEC / period; 279 /* Datasheet doesn't define, so use Nyquist frequency. */ 280 if (period_freq > (sc->clk_freq / 2)) 281 return (EINVAL); 282 duty_freq = NS_PER_SEC / duty; 283 if (duty_freq < period_freq) { 284 device_printf(sc->dev, "duty < period\n"); 285 return (EINVAL); 286 } 287 288 /* Assuming 24 MHz reference, we should never actually have 289 to use the divider due to pwm API limitations. */ 290 prescaler = 0; 291 scaler = 0; 292 using_scaler = false; 293 294 /* XXX Expand API to allow for 64 bit period/duty. */ 295 period_out = (sc->clk_freq * period) / NS_PER_SEC; 296 duty_out = (sc->clk_freq * duty) / NS_PER_SEC; 297 298 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 299 300 if ((reg & RK_PWM_CTRL_MODE_MASK) != RK_PWM_CTRL_MODE_CONTINUOUS) { 301 /* Switching modes, disable just in case. */ 302 SET(reg, RK_PWM_CTRL_ENABLE_MASK, RK_PWM_CTRL_DISABLED); 303 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 304 } 305 306 RK_PWM_WRITE(sc, RK_PWM_PERIOD, period_out); 307 RK_PWM_WRITE(sc, RK_PWM_DUTY, duty_out); 308 309 SET(reg, RK_PWM_CTRL_ENABLE_MASK, RK_PWM_CTRL_ENABLED); 310 SET(reg, RK_PWM_CTRL_MODE_MASK, RK_PWM_CTRL_MODE_CONTINUOUS); 311 SET(reg, RK_PWM_CTRL_ALIGN_MASK, RK_PWM_CTRL_ALIGN_LEFT); 312 SET(reg, RK_PWM_CTRL_CLOCKSRC_MASK, using_scaler); 313 SET(reg, RK_PWM_CTRL_PRESCALE_MASK, 314 prescaler << RK_PWM_CTRL_PRESCALE_SHIFT); 315 SET(reg, RK_PWM_CTRL_SCALE_MASK, 316 scaler << RK_PWM_CTRL_SCALE_SHIFT); 317 318 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 319 320 sc->period = period; 321 sc->duty = duty; 322 323 return (0); 324 } 325 326 static int 327 rk_pwm_channel_get_config(device_t dev, u_int channel, u_int *period, u_int *duty) 328 { 329 struct rk_pwm_softc *sc; 330 331 sc = device_get_softc(dev); 332 333 *period = sc->period; 334 *duty = sc->duty; 335 336 return (0); 337 } 338 339 static int 340 rk_pwm_channel_enable(device_t dev, u_int channel, bool enable) 341 { 342 struct rk_pwm_softc *sc; 343 uint32_t reg; 344 345 sc = device_get_softc(dev); 346 347 if (enable && sc->enabled) 348 return (0); 349 350 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 351 SET(reg, RK_PWM_CTRL_ENABLE_MASK, enable); 352 353 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 354 355 sc->enabled = enable; 356 357 return (0); 358 } 359 360 static int 361 rk_pwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled) 362 { 363 struct rk_pwm_softc *sc; 364 365 sc = device_get_softc(dev); 366 367 *enabled = sc->enabled; 368 369 return (0); 370 } 371 372 static device_method_t rk_pwm_methods[] = { 373 /* Device interface */ 374 DEVMETHOD(device_probe, rk_pwm_probe), 375 DEVMETHOD(device_attach, rk_pwm_attach), 376 DEVMETHOD(device_detach, rk_pwm_detach), 377 378 /* ofw_bus interface */ 379 DEVMETHOD(ofw_bus_get_node, aw_pwm_get_node), 380 381 /* pwm interface */ 382 DEVMETHOD(pwmbus_channel_count, rk_pwm_channel_count), 383 DEVMETHOD(pwmbus_channel_config, rk_pwm_channel_config), 384 DEVMETHOD(pwmbus_channel_get_config, rk_pwm_channel_get_config), 385 DEVMETHOD(pwmbus_channel_enable, rk_pwm_channel_enable), 386 DEVMETHOD(pwmbus_channel_is_enabled, rk_pwm_channel_is_enabled), 387 388 DEVMETHOD_END 389 }; 390 391 static driver_t rk_pwm_driver = { 392 "pwm", 393 rk_pwm_methods, 394 sizeof(struct rk_pwm_softc), 395 }; 396 397 DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, 0, 0); 398 SIMPLEBUS_PNP_INFO(compat_data); 399