1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/bus.h> 31 #include <sys/kernel.h> 32 #include <sys/module.h> 33 #include <sys/rman.h> 34 #include <sys/resource.h> 35 #include <machine/bus.h> 36 37 #include <dev/ofw/ofw_bus.h> 38 #include <dev/ofw/ofw_bus_subr.h> 39 40 #include <dev/clk/clk.h> 41 42 #include "pwmbus_if.h" 43 44 #define AW_PWM_CTRL 0x00 45 #define AW_PWM_CTRL_PRESCALE_MASK 0xF 46 #define AW_PWM_CTRL_EN (1 << 4) 47 #define AW_PWM_CTRL_ACTIVE_LEVEL_HIGH (1 << 5) 48 #define AW_PWM_CTRL_GATE (1 << 6) 49 #define AW_PWM_CTRL_MODE_MASK 0x80 50 #define AW_PWM_CTRL_PULSE_MODE (1 << 7) 51 #define AW_PWM_CTRL_CYCLE_MODE (0 << 7) 52 #define AW_PWM_CTRL_PULSE_START (1 << 8) 53 #define AW_PWM_CTRL_CLK_BYPASS (1 << 9) 54 #define AW_PWM_CTRL_PERIOD_BUSY (1 << 28) 55 56 #define AW_PWM_PERIOD 0x04 57 #define AW_PWM_PERIOD_TOTAL_MASK 0xFFFF 58 #define AW_PWM_PERIOD_TOTAL_SHIFT 16 59 #define AW_PWM_PERIOD_ACTIVE_MASK 0xFFFF 60 #define AW_PWM_PERIOD_ACTIVE_SHIFT 0 61 62 #define AW_PWM_MAX_FREQ 24000000 63 64 #define NS_PER_SEC 1000000000 65 66 static struct ofw_compat_data compat_data[] = { 67 { "allwinner,sun5i-a13-pwm", 1 }, 68 { "allwinner,sun8i-h3-pwm", 1 }, 69 { NULL, 0 } 70 }; 71 72 static struct resource_spec aw_pwm_spec[] = { 73 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 74 { -1, 0 } 75 }; 76 77 struct aw_pwm_softc { 78 device_t dev; 79 device_t busdev; 80 clk_t clk; 81 struct resource *res; 82 83 uint64_t clk_freq; 84 unsigned int period; 85 unsigned int duty; 86 uint32_t flags; 87 bool enabled; 88 }; 89 90 static uint32_t aw_pwm_clk_prescaler[] = { 91 120, 92 180, 93 240, 94 360, 95 480, 96 0, 97 0, 98 0, 99 12000, 100 24000, 101 36000, 102 48000, 103 72000, 104 0, 105 0, 106 1, 107 }; 108 109 #define AW_PWM_READ(sc, reg) bus_read_4((sc)->res, (reg)) 110 #define AW_PWM_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) 111 112 static int aw_pwm_probe(device_t dev); 113 static int aw_pwm_attach(device_t dev); 114 static int aw_pwm_detach(device_t dev); 115 116 static int 117 aw_pwm_probe(device_t dev) 118 { 119 if (!ofw_bus_status_okay(dev)) 120 return (ENXIO); 121 122 if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 123 return (ENXIO); 124 125 device_set_desc(dev, "Allwinner PWM"); 126 return (BUS_PROBE_DEFAULT); 127 } 128 129 static int 130 aw_pwm_attach(device_t dev) 131 { 132 struct aw_pwm_softc *sc; 133 uint64_t clk_freq; 134 uint32_t reg; 135 phandle_t node; 136 int error; 137 138 sc = device_get_softc(dev); 139 sc->dev = dev; 140 141 error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); 142 if (error != 0) { 143 device_printf(dev, "cannot get clock\n"); 144 goto fail; 145 } 146 error = clk_enable(sc->clk); 147 if (error != 0) { 148 device_printf(dev, "cannot enable clock\n"); 149 goto fail; 150 } 151 152 error = clk_get_freq(sc->clk, &sc->clk_freq); 153 if (error != 0) { 154 device_printf(dev, "cannot get clock frequency\n"); 155 goto fail; 156 } 157 158 if (bus_alloc_resources(dev, aw_pwm_spec, &sc->res) != 0) { 159 device_printf(dev, "cannot allocate resources for device\n"); 160 error = ENXIO; 161 goto fail; 162 } 163 164 /* Read the configuration left by U-Boot */ 165 reg = AW_PWM_READ(sc, AW_PWM_CTRL); 166 if (reg & (AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN)) 167 sc->enabled = true; 168 169 reg = AW_PWM_READ(sc, AW_PWM_CTRL); 170 reg &= AW_PWM_CTRL_PRESCALE_MASK; 171 if (reg > nitems(aw_pwm_clk_prescaler)) { 172 device_printf(dev, "Bad prescaler %x, cannot guess current settings\n", reg); 173 goto skipcfg; 174 } 175 clk_freq = sc->clk_freq / aw_pwm_clk_prescaler[reg]; 176 177 reg = AW_PWM_READ(sc, AW_PWM_PERIOD); 178 sc->period = NS_PER_SEC / 179 (clk_freq / ((reg >> AW_PWM_PERIOD_TOTAL_SHIFT) & AW_PWM_PERIOD_TOTAL_MASK)); 180 sc->duty = NS_PER_SEC / 181 (clk_freq / ((reg >> AW_PWM_PERIOD_ACTIVE_SHIFT) & AW_PWM_PERIOD_ACTIVE_MASK)); 182 183 skipcfg: 184 /* 185 * Note that we don't check for failure to attach pwmbus -- even without 186 * it we can still service clients who connect via fdt xref data. 187 */ 188 node = ofw_bus_get_node(dev); 189 OF_device_register_xref(OF_xref_from_node(node), dev); 190 191 sc->busdev = device_add_child(dev, "pwmbus", DEVICE_UNIT_ANY); 192 193 return (bus_generic_attach(dev)); 194 195 fail: 196 aw_pwm_detach(dev); 197 return (error); 198 } 199 200 static int 201 aw_pwm_detach(device_t dev) 202 { 203 struct aw_pwm_softc *sc; 204 int error; 205 206 sc = device_get_softc(dev); 207 208 if ((error = bus_generic_detach(sc->dev)) != 0) { 209 device_printf(sc->dev, "cannot detach child devices\n"); 210 return (error); 211 } 212 213 if (sc->busdev != NULL) 214 device_delete_child(dev, sc->busdev); 215 216 if (sc->res != NULL) 217 bus_release_resources(dev, aw_pwm_spec, &sc->res); 218 219 return (0); 220 } 221 222 static phandle_t 223 aw_pwm_get_node(device_t bus, device_t dev) 224 { 225 226 /* 227 * Share our controller node with our pwmbus child; it instantiates 228 * devices by walking the children contained within our node. 229 */ 230 return ofw_bus_get_node(bus); 231 } 232 233 static int 234 aw_pwm_channel_count(device_t dev, u_int *nchannel) 235 { 236 237 *nchannel = 1; 238 239 return (0); 240 } 241 242 static int 243 aw_pwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty) 244 { 245 struct aw_pwm_softc *sc; 246 uint64_t period_freq, duty_freq; 247 uint64_t clk_rate, div; 248 uint32_t reg; 249 int prescaler; 250 int i; 251 252 sc = device_get_softc(dev); 253 254 period_freq = NS_PER_SEC / period; 255 if (period_freq > AW_PWM_MAX_FREQ) 256 return (EINVAL); 257 258 /* 259 * FIXME. The hardware is capable of sub-Hz frequencies, that is, 260 * periods longer than a second. But the current code cannot deal 261 * with those properly. 262 */ 263 if (period_freq == 0) 264 return (EINVAL); 265 266 /* 267 * FIXME. There is a great loss of precision when the period and the 268 * duty are near 1 second. In some cases period_freq and duty_freq can 269 * be equal even if the period and the duty are significantly different. 270 */ 271 duty_freq = NS_PER_SEC / duty; 272 if (duty_freq < period_freq) { 273 device_printf(sc->dev, "duty < period\n"); 274 return (EINVAL); 275 } 276 277 /* First test without prescaler */ 278 clk_rate = AW_PWM_MAX_FREQ; 279 prescaler = AW_PWM_CTRL_PRESCALE_MASK; 280 div = AW_PWM_MAX_FREQ / period_freq; 281 if ((div - 1) > AW_PWM_PERIOD_TOTAL_MASK) { 282 /* Test all prescaler */ 283 for (i = 0; i < nitems(aw_pwm_clk_prescaler); i++) { 284 if (aw_pwm_clk_prescaler[i] == 0) 285 continue; 286 div = AW_PWM_MAX_FREQ / aw_pwm_clk_prescaler[i] / period_freq; 287 if ((div - 1) < AW_PWM_PERIOD_TOTAL_MASK ) { 288 prescaler = i; 289 clk_rate = AW_PWM_MAX_FREQ / aw_pwm_clk_prescaler[i]; 290 break; 291 } 292 } 293 if (prescaler == AW_PWM_CTRL_PRESCALE_MASK) 294 return (EINVAL); 295 } 296 297 reg = AW_PWM_READ(sc, AW_PWM_CTRL); 298 299 /* Write the prescalar */ 300 reg &= ~AW_PWM_CTRL_PRESCALE_MASK; 301 reg |= prescaler; 302 303 reg &= ~AW_PWM_CTRL_MODE_MASK; 304 reg |= AW_PWM_CTRL_CYCLE_MODE; 305 306 reg &= ~AW_PWM_CTRL_PULSE_START; 307 reg &= ~AW_PWM_CTRL_CLK_BYPASS; 308 309 AW_PWM_WRITE(sc, AW_PWM_CTRL, reg); 310 311 /* Write the total/active cycles */ 312 reg = ((clk_rate / period_freq - 1) << AW_PWM_PERIOD_TOTAL_SHIFT) | 313 ((clk_rate / duty_freq) << AW_PWM_PERIOD_ACTIVE_SHIFT); 314 AW_PWM_WRITE(sc, AW_PWM_PERIOD, reg); 315 316 sc->period = period; 317 sc->duty = duty; 318 319 return (0); 320 } 321 322 static int 323 aw_pwm_channel_get_config(device_t dev, u_int channel, u_int *period, u_int *duty) 324 { 325 struct aw_pwm_softc *sc; 326 327 sc = device_get_softc(dev); 328 329 *period = sc->period; 330 *duty = sc->duty; 331 332 return (0); 333 } 334 335 static int 336 aw_pwm_channel_enable(device_t dev, u_int channel, bool enable) 337 { 338 struct aw_pwm_softc *sc; 339 uint32_t reg; 340 341 sc = device_get_softc(dev); 342 343 if (enable && sc->enabled) 344 return (0); 345 346 reg = AW_PWM_READ(sc, AW_PWM_CTRL); 347 if (enable) 348 reg |= AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN; 349 else 350 reg &= ~(AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN); 351 352 AW_PWM_WRITE(sc, AW_PWM_CTRL, reg); 353 354 sc->enabled = enable; 355 356 return (0); 357 } 358 359 static int 360 aw_pwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled) 361 { 362 struct aw_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 aw_pwm_methods[] = { 372 /* Device interface */ 373 DEVMETHOD(device_probe, aw_pwm_probe), 374 DEVMETHOD(device_attach, aw_pwm_attach), 375 DEVMETHOD(device_detach, aw_pwm_detach), 376 377 /* ofw_bus interface */ 378 DEVMETHOD(ofw_bus_get_node, aw_pwm_get_node), 379 380 /* pwmbus interface */ 381 DEVMETHOD(pwmbus_channel_count, aw_pwm_channel_count), 382 DEVMETHOD(pwmbus_channel_config, aw_pwm_channel_config), 383 DEVMETHOD(pwmbus_channel_get_config, aw_pwm_channel_get_config), 384 DEVMETHOD(pwmbus_channel_enable, aw_pwm_channel_enable), 385 DEVMETHOD(pwmbus_channel_is_enabled, aw_pwm_channel_is_enabled), 386 387 DEVMETHOD_END 388 }; 389 390 static driver_t aw_pwm_driver = { 391 "pwm", 392 aw_pwm_methods, 393 sizeof(struct aw_pwm_softc), 394 }; 395 396 DRIVER_MODULE(aw_pwm, simplebus, aw_pwm_driver, 0, 0); 397 MODULE_VERSION(aw_pwm, 1); 398 SIMPLEBUS_PNP_INFO(compat_data); 399