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/extres/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", -1); 216 217 return (bus_generic_attach(dev)); 218 219 fail: 220 rk_pwm_detach(dev); 221 return (error); 222 } 223 224 static int 225 rk_pwm_detach(device_t dev) 226 { 227 struct rk_pwm_softc *sc; 228 229 sc = device_get_softc(dev); 230 231 bus_generic_detach(sc->dev); 232 233 bus_release_resources(dev, rk_pwm_spec, &sc->res); 234 235 return (0); 236 } 237 238 static phandle_t 239 aw_pwm_get_node(device_t bus, device_t dev) 240 { 241 242 /* 243 * Share our controller node with our pwmbus child; it instantiates 244 * devices by walking the children contained within our node. 245 */ 246 return ofw_bus_get_node(bus); 247 } 248 249 static int 250 rk_pwm_channel_count(device_t dev, u_int *nchannel) 251 { 252 /* The device supports 4 channels, but attaches multiple times in the 253 * device tree. This interferes with advanced usage though, as 254 * the interrupt capability and channel 3 FIFO register offsets 255 * don't work right in this situation. 256 * But since we don't support those yet, pretend we are singlechannel. 257 */ 258 *nchannel = 1; 259 260 return (0); 261 } 262 263 static int 264 rk_pwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty) 265 { 266 struct rk_pwm_softc *sc; 267 uint64_t period_freq, duty_freq; 268 uint32_t reg; 269 uint32_t period_out; 270 uint32_t duty_out; 271 uint8_t prescaler; 272 uint8_t scaler; 273 bool using_scaler; 274 275 sc = device_get_softc(dev); 276 277 period_freq = NS_PER_SEC / period; 278 /* Datasheet doesn't define, so use Nyquist frequency. */ 279 if (period_freq > (sc->clk_freq / 2)) 280 return (EINVAL); 281 duty_freq = NS_PER_SEC / duty; 282 if (duty_freq < period_freq) { 283 device_printf(sc->dev, "duty < period\n"); 284 return (EINVAL); 285 } 286 287 /* Assuming 24 MHz reference, we should never actually have 288 to use the divider due to pwm API limitations. */ 289 prescaler = 0; 290 scaler = 0; 291 using_scaler = false; 292 293 /* XXX Expand API to allow for 64 bit period/duty. */ 294 period_out = (sc->clk_freq * period) / NS_PER_SEC; 295 duty_out = (sc->clk_freq * duty) / NS_PER_SEC; 296 297 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 298 299 if ((reg & RK_PWM_CTRL_MODE_MASK) != RK_PWM_CTRL_MODE_CONTINUOUS) { 300 /* Switching modes, disable just in case. */ 301 SET(reg, RK_PWM_CTRL_ENABLE_MASK, RK_PWM_CTRL_DISABLED); 302 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 303 } 304 305 RK_PWM_WRITE(sc, RK_PWM_PERIOD, period_out); 306 RK_PWM_WRITE(sc, RK_PWM_DUTY, duty_out); 307 308 SET(reg, RK_PWM_CTRL_ENABLE_MASK, RK_PWM_CTRL_ENABLED); 309 SET(reg, RK_PWM_CTRL_MODE_MASK, RK_PWM_CTRL_MODE_CONTINUOUS); 310 SET(reg, RK_PWM_CTRL_ALIGN_MASK, RK_PWM_CTRL_ALIGN_LEFT); 311 SET(reg, RK_PWM_CTRL_CLOCKSRC_MASK, using_scaler); 312 SET(reg, RK_PWM_CTRL_PRESCALE_MASK, 313 prescaler << RK_PWM_CTRL_PRESCALE_SHIFT); 314 SET(reg, RK_PWM_CTRL_SCALE_MASK, 315 scaler << RK_PWM_CTRL_SCALE_SHIFT); 316 317 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 318 319 sc->period = period; 320 sc->duty = duty; 321 322 return (0); 323 } 324 325 static int 326 rk_pwm_channel_get_config(device_t dev, u_int channel, u_int *period, u_int *duty) 327 { 328 struct rk_pwm_softc *sc; 329 330 sc = device_get_softc(dev); 331 332 *period = sc->period; 333 *duty = sc->duty; 334 335 return (0); 336 } 337 338 static int 339 rk_pwm_channel_enable(device_t dev, u_int channel, bool enable) 340 { 341 struct rk_pwm_softc *sc; 342 uint32_t reg; 343 344 sc = device_get_softc(dev); 345 346 if (enable && sc->enabled) 347 return (0); 348 349 reg = RK_PWM_READ(sc, RK_PWM_CTRL); 350 SET(reg, RK_PWM_CTRL_ENABLE_MASK, enable); 351 352 RK_PWM_WRITE(sc, RK_PWM_CTRL, reg); 353 354 sc->enabled = enable; 355 356 return (0); 357 } 358 359 static int 360 rk_pwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled) 361 { 362 struct rk_pwm_softc *sc; 363 364 sc = device_get_softc(dev); 365 366 *enabled = sc->enabled; 367 368 return (0); 369 } 370 371 static device_method_t rk_pwm_methods[] = { 372 /* Device interface */ 373 DEVMETHOD(device_probe, rk_pwm_probe), 374 DEVMETHOD(device_attach, rk_pwm_attach), 375 DEVMETHOD(device_detach, rk_pwm_detach), 376 377 /* ofw_bus interface */ 378 DEVMETHOD(ofw_bus_get_node, aw_pwm_get_node), 379 380 /* pwm interface */ 381 DEVMETHOD(pwmbus_channel_count, rk_pwm_channel_count), 382 DEVMETHOD(pwmbus_channel_config, rk_pwm_channel_config), 383 DEVMETHOD(pwmbus_channel_get_config, rk_pwm_channel_get_config), 384 DEVMETHOD(pwmbus_channel_enable, rk_pwm_channel_enable), 385 DEVMETHOD(pwmbus_channel_is_enabled, rk_pwm_channel_is_enabled), 386 387 DEVMETHOD_END 388 }; 389 390 static driver_t rk_pwm_driver = { 391 "pwm", 392 rk_pwm_methods, 393 sizeof(struct rk_pwm_softc), 394 }; 395 396 DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, 0, 0); 397 SIMPLEBUS_PNP_INFO(compat_data); 398