1 /* $NetBSD: imxpwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Genetec Corporation. All rights reserved. 5 * Written by Hashimoto Kenichi for Genetec Corporation. 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 GENETEC CORPORATION ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: imxpwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $"); 31 32 #include "opt_imx.h" 33 #include "locators.h" 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/device.h> 39 40 #include <arm/imx/imxpwmreg.h> 41 #include <arm/imx/imxpwmvar.h> 42 43 static inline uint32_t 44 imxpwm_read(struct imxpwm_softc *sc, bus_size_t o) 45 { 46 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, o); 47 } 48 49 static inline void 50 imxpwm_write(struct imxpwm_softc *sc, bus_size_t o, uint32_t v) 51 { 52 bus_space_write_4(sc->sc_iot, sc->sc_ioh, o, v); 53 } 54 55 static int 56 imxpwm_intr(void *arg) 57 { 58 struct imxpwm_softc *sc = arg; 59 uint32_t sts = imxpwm_read(sc, PWM_SR); 60 61 imxpwm_write(sc, PWM_SR, sts); 62 63 if ((sts & SR_ROV) && (sc->sc_handler != NULL)) 64 sc->sc_handler(sc->sc_cookie); 65 66 return 1; 67 } 68 69 void 70 imxpwm_attach_common(struct imxpwm_softc *sc) 71 { 72 uint32_t reg; 73 int div; 74 75 if (sc->sc_handler != NULL) { 76 sc->sc_ih = intr_establish(sc->sc_intr, IPL_BIO, IST_LEVEL, 77 imxpwm_intr, sc); 78 79 reg = IR_RIE; 80 imxpwm_write(sc, PWM_IR, reg); 81 } 82 83 if (sc->sc_hz <= 0) 84 sc->sc_hz = IMXPWM_DEFAULT_HZ; 85 div = 0; 86 do { 87 div++; 88 sc->sc_cycle = sc->sc_freq / div / sc->sc_hz; 89 } while (sc->sc_cycle > 0xffff); 90 91 imxpwm_write(sc, PWM_PR, __SHIFTIN(sc->sc_cycle - 2, PR_PERIOD)); 92 93 reg = 0; 94 reg |= __SHIFTIN(CLKSRC_IPG_CLK, CR_CLKSRC); 95 reg |= __SHIFTIN(div - 1, CR_PRESCALER); 96 reg |= CR_EN; 97 imxpwm_write(sc, PWM_CR, reg); 98 } 99 100 int 101 imxpwm_set_pwm(struct imxpwm_softc *sc, int duty) 102 { 103 if (duty < 0 || IMXPWM_DUTY_MAX < duty) 104 return EINVAL; 105 106 sc->sc_duty = duty; 107 108 uint16_t reg = sc->sc_cycle * sc->sc_duty / IMXPWM_DUTY_MAX; 109 if (reg != 0) 110 reg -= 1; 111 imxpwm_write(sc, PWM_SAR, __SHIFTIN(reg, SAR_SAMPLE)); 112 113 return 0; 114 } 115