Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Use kernel API of PWM subsystems for i.MX PWM driver.



details:   https://anonhg.NetBSD.org/src/rev/a347b3e9b51a
branches:  trunk
changeset: 933159:a347b3e9b51a
user:      hkenken <hkenken%NetBSD.org@localhost>
date:      Wed May 20 05:10:42 2020 +0000

description:
Use kernel API of PWM subsystems for i.MX PWM driver.

diffstat:

 sys/arch/arm/imx/files.imx51                    |    4 +-
 sys/arch/arm/imx/imx51_pwm.c                    |   10 +-
 sys/arch/arm/imx/imxpwm.c                       |  169 ++++++++++++++++-------
 sys/arch/arm/imx/imxpwmreg.h                    |   62 ++++----
 sys/arch/arm/imx/imxpwmvar.h                    |   17 +-
 sys/arch/evbarm/netwalker/netwalker_backlight.c |   36 +++-
 6 files changed, 191 insertions(+), 107 deletions(-)

diffs (truncated from 500 to 300 lines):

diff -r faa311b76c10 -r a347b3e9b51a sys/arch/arm/imx/files.imx51
--- a/sys/arch/arm/imx/files.imx51      Wed May 20 02:23:35 2020 +0000
+++ b/sys/arch/arm/imx/files.imx51      Wed May 20 05:10:42 2020 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.imx51,v 1.20 2019/10/12 06:46:13 skrll Exp $
+#      $NetBSD: files.imx51,v 1.21 2020/05/20 05:10:42 hkenken Exp $
 #
 # Configuration info for the Freescale i.MX5x
 #
@@ -137,6 +137,6 @@
 # file arch/arm/imx/imx51_i2s.c                imxi2s needs-flag
 
 # PWM controller
-device imxpwm
+device imxpwm: pwm
 file   arch/arm/imx/imxpwm.c                   imxpwm
 file   arch/arm/imx/imx51_pwm.c                imxpwm
diff -r faa311b76c10 -r a347b3e9b51a sys/arch/arm/imx/imx51_pwm.c
--- a/sys/arch/arm/imx/imx51_pwm.c      Wed May 20 02:23:35 2020 +0000
+++ b/sys/arch/arm/imx/imx51_pwm.c      Wed May 20 05:10:42 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: imx51_pwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $    */
+/*     $NetBSD: imx51_pwm.c,v 1.2 2020/05/20 05:10:42 hkenken Exp $    */
 
 /*-
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx51_pwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx51_pwm.c,v 1.2 2020/05/20 05:10:42 hkenken Exp $");
 
 #include "locators.h"
 #include "opt_imx.h"
@@ -62,10 +62,16 @@
 
        if (aa->aa_size == AXICF_SIZE_DEFAULT)
                aa->aa_size = PWM_SIZE;
+
        sc->sc_iot = aa->aa_iot;
        sc->sc_intr = aa->aa_irq;
        sc->sc_freq = imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
+
        if (bus_space_map(aa->aa_iot, aa->aa_addr, aa->aa_size, 0, &sc->sc_ioh))
                panic("%s: couldn't map", device_xname(sc->sc_dev));
+
+       sc->sc_ih = intr_establish(sc->sc_intr, IPL_BIO, IST_LEVEL,
+           imxpwm_intr, sc);
+
        imxpwm_attach_common(sc);
 }
diff -r faa311b76c10 -r a347b3e9b51a sys/arch/arm/imx/imxpwm.c
--- a/sys/arch/arm/imx/imxpwm.c Wed May 20 02:23:35 2020 +0000
+++ b/sys/arch/arm/imx/imxpwm.c Wed May 20 05:10:42 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: imxpwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $       */
+/*     $NetBSD: imxpwm.c,v 1.2 2020/05/20 05:10:42 hkenken Exp $       */
 
 /*
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -27,88 +27,155 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxpwm.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $");
-
-#include "opt_imx.h"
-#include "locators.h"
+__KERNEL_RCSID(0, "$NetBSD: imxpwm.c,v 1.2 2020/05/20 05:10:42 hkenken Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/device.h>
 
+#include <dev/clk/clk_backend.h>
+
 #include <arm/imx/imxpwmreg.h>
 #include <arm/imx/imxpwmvar.h>
 
-static inline uint32_t
-imxpwm_read(struct imxpwm_softc *sc, bus_size_t o)
+#include <dev/pwm/pwmvar.h>
+
+#define        PWM_READ(sc, reg)               \
+       bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define        PWM_WRITE(sc, reg, val)         \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+int
+imxpwm_intr(void *arg)
 {
-       return bus_space_read_4(sc->sc_iot, sc->sc_ioh, o);
+       struct imxpwm_softc *sc = arg;
+
+       uint32_t sts = PWM_READ(sc, PWM_SR);
+
+       if (sts & PWM_SR_ROV) {
+               if (sc->sc_handler != NULL)
+                       sc->sc_handler(sc->sc_cookie);
+       }
+
+       PWM_WRITE(sc, PWM_SR, sts);
+
+       return 1;
 }
 
-static inline void
-imxpwm_write(struct imxpwm_softc *sc, bus_size_t o, uint32_t v)
+static int
+imxpwm_enable(pwm_tag_t pwm, bool enable)
 {
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, o, v);
+       struct imxpwm_softc * const sc = device_private(pwm->pwm_dev);
+       uint32_t cr, ocr;
+
+       ocr = cr = PWM_READ(sc, PWM_CR);
+       if (enable)
+               cr |= PWM_CR_EN;
+       else
+               cr &= ~PWM_CR_EN;
+
+       if (cr != ocr)
+               PWM_WRITE(sc, PWM_CR, cr);
+
+       return 0;
 }
 
 static int
-imxpwm_intr(void *arg)
+imxpwm_get_config(pwm_tag_t pwm, struct pwm_config *conf)
 {
-       struct imxpwm_softc *sc = arg;
-       uint32_t sts = imxpwm_read(sc, PWM_SR);
+       struct imxpwm_softc * const sc = device_private(pwm->pwm_dev);
+       uint32_t cr, sar, pr;
+
+       cr = PWM_READ(sc, PWM_CR);
+       sar = PWM_READ(sc, PWM_SAR);
+       pr = PWM_READ(sc, PWM_PR);
+
+       const int div           = __SHIFTOUT(cr, PWM_CR_PRESCALER) + 1;
+       const int polarity      = __SHIFTOUT(cr, PWM_CR_POUTC);
+       const uint64_t rate     = sc->sc_freq / div;
+       const u_int cycles      =  __SHIFTOUT(pr, PWM_PR_PERIOD) + 2;
+       const u_int act_cycles  = __SHIFTOUT(sar, PWM_SAR_SAMPLE);
+
+       conf->polarity   = polarity ? PWM_ACTIVE_HIGH : PWM_ACTIVE_LOW;
+       conf->period     = (u_int)(((uint64_t)cycles * 1000000000) / rate);
+       conf->duty_cycle = (u_int)(((uint64_t)act_cycles * 1000000000) / rate);
+
+       return 0;
+}
+
+static int
+imxpwm_set_config(pwm_tag_t pwm, const struct pwm_config *conf)
+{
+       struct imxpwm_softc * const sc = device_private(pwm->pwm_dev);
+       uint32_t cr, sar, pr;
 
-       imxpwm_write(sc, PWM_SR, sts);
+       if (conf->period == 0)
+               return EINVAL;
+       uint64_t rate;
+       u_int cycles;
+       int div = 0;
+       do {
+               div++;
+               rate = sc->sc_freq / div;
+               cycles = (u_int)((conf->period * rate) / 1000000000);
+       } while (cycles > 0xffff);
+       pr = __SHIFTIN(cycles - 2, PWM_PR_PERIOD);
 
-       if ((sts & SR_ROV) && (sc->sc_handler != NULL))
-               sc->sc_handler(sc->sc_cookie);
+       cr = PWM_READ(sc, PWM_CR);
+       cr &= ~PWM_CR_PRESCALER;
+       cr |= __SHIFTIN(div - 1, PWM_CR_PRESCALER);
+       cr &= ~PWM_CR_POUTC;
+       if (conf->polarity == PWM_ACTIVE_LOW)
+               cr |= __SHIFTIN(1, PWM_CR_POUTC);
 
-       return 1;
+       u_int act_cycles = (u_int)((conf->duty_cycle * rate) / 1000000000);
+       sar = __SHIFTIN(act_cycles, PWM_PR_PERIOD);
+
+       PWM_WRITE(sc, PWM_SAR, sar);
+       PWM_WRITE(sc, PWM_PR, pr);
+       PWM_WRITE(sc, PWM_CR, cr);
+
+       sc->sc_conf = *conf;
+
+       return 0;
 }
 
 void
 imxpwm_attach_common(struct imxpwm_softc *sc)
 {
        uint32_t reg;
-       int div;
+       int error;
 
        if (sc->sc_handler != NULL) {
-               sc->sc_ih = intr_establish(sc->sc_intr, IPL_BIO, IST_LEVEL,
-                   imxpwm_intr, sc);
+               reg = PWM_IR_RIE;
+               PWM_WRITE(sc, PWM_IR, reg);
+       }
 
-               reg = IR_RIE;
-               imxpwm_write(sc, PWM_IR, reg);
+       if (sc->sc_clk) {
+               error = clk_enable(sc->sc_clk);
+               if (error != 0) {
+                       aprint_error(": couldn't enable clk\n");
+                       return;
+               }
        }
 
-       if (sc->sc_hz <= 0)
-               sc->sc_hz = IMXPWM_DEFAULT_HZ;
-       div = 0;
-       do {
-               div++;
-               sc->sc_cycle = sc->sc_freq / div / sc->sc_hz;
-       } while (sc->sc_cycle > 0xffff);
+       reg = PWM_READ(sc, PWM_CR);
+       reg &= PWM_CR_CLKSRC;
+       reg |= __SHIFTIN(CLKSRC_IPG_CLK, PWM_CR_CLKSRC);
+       PWM_WRITE(sc, PWM_CR, reg);
 
-       imxpwm_write(sc, PWM_PR, __SHIFTIN(sc->sc_cycle - 2, PR_PERIOD));
+       sc->sc_pwm.pwm_enable     = imxpwm_enable;
+       sc->sc_pwm.pwm_get_config = imxpwm_get_config;
+       sc->sc_pwm.pwm_set_config = imxpwm_set_config;
+       sc->sc_pwm.pwm_dev        = sc->sc_dev;
 
-       reg = 0;
-       reg |= __SHIFTIN(CLKSRC_IPG_CLK, CR_CLKSRC);
-       reg |= __SHIFTIN(div - 1, CR_PRESCALER);
-       reg |= CR_EN;
-       imxpwm_write(sc, PWM_CR, reg);
+       /* Set default settings */
+       struct pwm_config conf = {
+               .period = 1000000,
+               .duty_cycle = 0,
+               .polarity = PWM_ACTIVE_HIGH,
+       };
+       pwm_set_config(&sc->sc_pwm, &conf);
 }
 
-int
-imxpwm_set_pwm(struct imxpwm_softc *sc, int duty)
-{
-       if (duty < 0 || IMXPWM_DUTY_MAX < duty)
-               return EINVAL;
-
-       sc->sc_duty = duty;
-
-       uint16_t reg = sc->sc_cycle * sc->sc_duty / IMXPWM_DUTY_MAX;
-       if (reg != 0)
-               reg -= 1;
-       imxpwm_write(sc, PWM_SAR, __SHIFTIN(reg, SAR_SAMPLE));
-
-       return 0;
-}
diff -r faa311b76c10 -r a347b3e9b51a sys/arch/arm/imx/imxpwmreg.h
--- a/sys/arch/arm/imx/imxpwmreg.h      Wed May 20 02:23:35 2020 +0000
+++ b/sys/arch/arm/imx/imxpwmreg.h      Wed May 20 05:10:42 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: imxpwmreg.h,v 1.1 2014/05/06 11:22:53 hkenken Exp $    */
+/*     $NetBSD: imxpwmreg.h,v 1.2 2020/05/20 05:10:42 hkenken Exp $    */
 
 /*
  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
@@ -29,38 +29,38 @@
 #ifndef        _ARM_IMX_IMXPWMREG_H_
 #define        _ARM_IMX_IMXPWMREG_H_
 
-#define PWM_CR         0x00    /* PWM Control Register */
-#define  CR_FWM                __BITS(27, 26)
-#define  CR_STOPEN     __BIT(25)
-#define  CR_DOZEN      __BIT(24)
-#define  CR_WAITEN     __BIT(23)
-#define  CR_DBGEN      __BIT(22)
-#define  CR_BCTR       __BIT(21)
-#define  CR_HCTR       __BIT(20)
-#define  CR_POUTC      __BITS(19, 18)
-#define  CR_CLKSRC     __BITS(17, 16)
+#define PWM_CR                 0x00    /* PWM Control Register */
+#define  PWM_CR_FWM            __BITS(27, 26)
+#define  PWM_CR_STOPEN         __BIT(25)
+#define  PWM_CR_DOZEN          __BIT(24)
+#define  PWM_CR_WAITEN         __BIT(23)
+#define  PWM_CR_DBGEN          __BIT(22)
+#define  PWM_CR_BCTR           __BIT(21)
+#define  PWM_CR_HCTR           __BIT(20)
+#define  PWM_CR_POUTC          __BITS(19, 18)
+#define  PWM_CR_CLKSRC         __BITS(17, 16)



Home | Main Index | Thread Index | Old Index