Module Name: src
Committed By: hkenken
Date: Wed May 20 05:10:42 UTC 2020
Modified Files:
src/sys/arch/arm/imx: files.imx51 imx51_pwm.c imxpwm.c imxpwmreg.h
imxpwmvar.h
src/sys/arch/evbarm/netwalker: netwalker_backlight.c
Log Message:
Use kernel API of PWM subsystems for i.MX PWM driver.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/arm/imx/files.imx51
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/imx51_pwm.c \
src/sys/arch/arm/imx/imxpwm.c src/sys/arch/arm/imx/imxpwmreg.h \
src/sys/arch/arm/imx/imxpwmvar.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/netwalker/netwalker_backlight.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/imx/files.imx51
diff -u src/sys/arch/arm/imx/files.imx51:1.20 src/sys/arch/arm/imx/files.imx51:1.21
--- src/sys/arch/arm/imx/files.imx51:1.20 Sat Oct 12 06:46:13 2019
+++ src/sys/arch/arm/imx/files.imx51 Wed May 20 05:10:42 2020
@@ -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 @@ defparam opt_imxspi.h IMXSPI_DEBUG
# 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
Index: src/sys/arch/arm/imx/imx51_pwm.c
diff -u src/sys/arch/arm/imx/imx51_pwm.c:1.1 src/sys/arch/arm/imx/imx51_pwm.c:1.2
--- src/sys/arch/arm/imx/imx51_pwm.c:1.1 Tue May 6 11:22:53 2014
+++ src/sys/arch/arm/imx/imx51_pwm.c Wed May 20 05:10:42 2020
@@ -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 @@ imxpwm_attach(struct imxpwm_softc *sc, v
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);
}
Index: src/sys/arch/arm/imx/imxpwm.c
diff -u src/sys/arch/arm/imx/imxpwm.c:1.1 src/sys/arch/arm/imx/imxpwm.c:1.2
--- src/sys/arch/arm/imx/imxpwm.c:1.1 Tue May 6 11:22:53 2014
+++ src/sys/arch/arm/imx/imxpwm.c Wed May 20 05:10:42 2020
@@ -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)
-{
- return bus_space_read_4(sc->sc_iot, sc->sc_ioh, o);
-}
+#include <dev/pwm/pwmvar.h>
-static inline void
-imxpwm_write(struct imxpwm_softc *sc, bus_size_t o, uint32_t v)
-{
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, o, v);
-}
+#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))
-static int
+int
imxpwm_intr(void *arg)
{
struct imxpwm_softc *sc = arg;
- uint32_t sts = imxpwm_read(sc, PWM_SR);
- imxpwm_write(sc, PWM_SR, sts);
+ uint32_t sts = PWM_READ(sc, PWM_SR);
- if ((sts & SR_ROV) && (sc->sc_handler != NULL))
- sc->sc_handler(sc->sc_cookie);
+ if (sts & PWM_SR_ROV) {
+ if (sc->sc_handler != NULL)
+ sc->sc_handler(sc->sc_cookie);
+ }
+
+ PWM_WRITE(sc, PWM_SR, sts);
return 1;
}
-void
-imxpwm_attach_common(struct imxpwm_softc *sc)
+static int
+imxpwm_enable(pwm_tag_t pwm, bool enable)
{
- uint32_t reg;
- int div;
+ struct imxpwm_softc * const sc = device_private(pwm->pwm_dev);
+ uint32_t cr, ocr;
- if (sc->sc_handler != NULL) {
- sc->sc_ih = intr_establish(sc->sc_intr, IPL_BIO, IST_LEVEL,
- imxpwm_intr, sc);
+ ocr = cr = PWM_READ(sc, PWM_CR);
+ if (enable)
+ cr |= PWM_CR_EN;
+ else
+ cr &= ~PWM_CR_EN;
- reg = IR_RIE;
- imxpwm_write(sc, PWM_IR, reg);
- }
+ if (cr != ocr)
+ PWM_WRITE(sc, PWM_CR, cr);
- if (sc->sc_hz <= 0)
- sc->sc_hz = IMXPWM_DEFAULT_HZ;
- div = 0;
+ return 0;
+}
+
+static int
+imxpwm_get_config(pwm_tag_t pwm, struct pwm_config *conf)
+{
+ 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;
+
+ if (conf->period == 0)
+ return EINVAL;
+ uint64_t rate;
+ u_int cycles;
+ int div = 0;
do {
div++;
- sc->sc_cycle = sc->sc_freq / div / sc->sc_hz;
- } while (sc->sc_cycle > 0xffff);
+ rate = sc->sc_freq / div;
+ cycles = (u_int)((conf->period * rate) / 1000000000);
+ } while (cycles > 0xffff);
+ pr = __SHIFTIN(cycles - 2, PWM_PR_PERIOD);
+
+ 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);
+
+ 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);
- imxpwm_write(sc, PWM_PR, __SHIFTIN(sc->sc_cycle - 2, PR_PERIOD));
+ sc->sc_conf = *conf;
- reg = 0;
- reg |= __SHIFTIN(CLKSRC_IPG_CLK, CR_CLKSRC);
- reg |= __SHIFTIN(div - 1, CR_PRESCALER);
- reg |= CR_EN;
- imxpwm_write(sc, PWM_CR, reg);
+ return 0;
}
-int
-imxpwm_set_pwm(struct imxpwm_softc *sc, int duty)
+void
+imxpwm_attach_common(struct imxpwm_softc *sc)
{
- if (duty < 0 || IMXPWM_DUTY_MAX < duty)
- return EINVAL;
+ uint32_t reg;
+ int error;
- sc->sc_duty = duty;
+ if (sc->sc_handler != NULL) {
+ reg = PWM_IR_RIE;
+ PWM_WRITE(sc, PWM_IR, reg);
+ }
- 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));
+ if (sc->sc_clk) {
+ error = clk_enable(sc->sc_clk);
+ if (error != 0) {
+ aprint_error(": couldn't enable clk\n");
+ return;
+ }
+ }
- return 0;
+ reg = PWM_READ(sc, PWM_CR);
+ reg &= PWM_CR_CLKSRC;
+ reg |= __SHIFTIN(CLKSRC_IPG_CLK, PWM_CR_CLKSRC);
+ PWM_WRITE(sc, PWM_CR, reg);
+
+ 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;
+
+ /* Set default settings */
+ struct pwm_config conf = {
+ .period = 1000000,
+ .duty_cycle = 0,
+ .polarity = PWM_ACTIVE_HIGH,
+ };
+ pwm_set_config(&sc->sc_pwm, &conf);
}
+
Index: src/sys/arch/arm/imx/imxpwmreg.h
diff -u src/sys/arch/arm/imx/imxpwmreg.h:1.1 src/sys/arch/arm/imx/imxpwmreg.h:1.2
--- src/sys/arch/arm/imx/imxpwmreg.h:1.1 Tue May 6 11:22:53 2014
+++ src/sys/arch/arm/imx/imxpwmreg.h Wed May 20 05:10:42 2020
@@ -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)
#define CLKSRC_IPG_CLK 1
#define CLKSRC_IPG_CLK_HIGHFREQ 2
#define CLKSRC_IPG_CLK_32K 3
-#define CR_PRESCALER __BITS(15, 4)
-#define CR_SWR __BIT(3)
-#define CR_REPEAT __BITS(2, 1)
-#define CR_EN __BIT(0)
-#define PWM_SR 0x04 /* PWM Status Register */
-#define SR_FWE __BIT(6)
-#define SR_CMP __BIT(5)
-#define SR_ROV __BIT(4)
-#define SR_FE __BIT(3)
-#define SR_FIFOAV __BITS(2, 0)
-#define PWM_IR 0x08 /* PWM Interrupt Register */
-#define IR_CIE __BIT(2)
-#define IR_RIE __BIT(1)
-#define IR_FIE __BIT(0)
-#define PWM_SAR 0x0C /* PWM Sample Register */
-#define SAR_SAMPLE __BITS(15, 0)
-#define PWM_PR 0x10 /* PWM Period Register */
-#define PR_PERIOD __BITS(15, 0)
-#define PWM_CNR 0x14 /* PWM Counter Register */
-#define CNR_COUNT __BITS(15, 0)
+#define PWM_CR_PRESCALER __BITS(15, 4)
+#define PWM_CR_SWR __BIT(3)
+#define PWM_CR_REPEAT __BITS(2, 1)
+#define PWM_CR_EN __BIT(0)
+#define PWM_SR 0x04 /* PWM Status Register */
+#define PWM_SR_FWE __BIT(6)
+#define PWM_SR_CMP __BIT(5)
+#define PWM_SR_ROV __BIT(4)
+#define PWM_SR_FE __BIT(3)
+#define PWM_SR_FIFOAV __BITS(2, 0)
+#define PWM_IR 0x08 /* PWM Interrupt Register */
+#define PWM_IR_CIE __BIT(2)
+#define PWM_IR_RIE __BIT(1)
+#define PWM_IR_FIE __BIT(0)
+#define PWM_SAR 0x0C /* PWM Sample Register */
+#define PWM_SAR_SAMPLE __BITS(15, 0)
+#define PWM_PR 0x10 /* PWM Period Register */
+#define PWM_PR_PERIOD __BITS(15, 0)
+#define PWM_CNR 0x14 /* PWM Counter Register */
+#define PWM_CNR_COUNT __BITS(15, 0)
#endif /* _ARM_IMX_IMXPWMREG_H_ */
Index: src/sys/arch/arm/imx/imxpwmvar.h
diff -u src/sys/arch/arm/imx/imxpwmvar.h:1.1 src/sys/arch/arm/imx/imxpwmvar.h:1.2
--- src/sys/arch/arm/imx/imxpwmvar.h:1.1 Tue May 6 11:22:53 2014
+++ src/sys/arch/arm/imx/imxpwmvar.h Wed May 20 05:10:42 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imxpwmvar.h,v 1.1 2014/05/06 11:22:53 hkenken Exp $ */
+/* $NetBSD: imxpwmvar.h,v 1.2 2020/05/20 05:10:42 hkenken Exp $ */
/*
* Copyright (c) 2014 Genetec Corporation. All rights reserved.
@@ -29,6 +29,8 @@
#ifndef _ARM_IMX_IMXPWMVAR_H_
#define _ARM_IMX_IMXPWMVAR_H_
+#include <dev/pwm/pwmvar.h>
+
struct imxpwm_softc {
device_t sc_dev;
bus_space_tag_t sc_iot;
@@ -36,12 +38,11 @@ struct imxpwm_softc {
int sc_intr;
void *sc_ih;
- long sc_freq;
- long sc_hz;
-#define IMXPWM_DEFAULT_HZ 1000
- long sc_cycle;
- int sc_duty;
-#define IMXPWM_DUTY_MAX 1000
+ struct clk *sc_clk;
+ u_int sc_freq;
+
+ struct pwm_controller sc_pwm;
+ struct pwm_config sc_conf;
int (*sc_handler)(void *);
void *sc_cookie;
@@ -51,6 +52,6 @@ int imxpwm_match(device_t, cfdata_t, voi
void imxpwm_attach(struct imxpwm_softc *, void *);
void imxpwm_attach_common(struct imxpwm_softc *);
-int imxpwm_set_pwm(struct imxpwm_softc *, int);
+int imxpwm_intr(void *);
#endif /* _ARM_IMX_IMXPWMVAR_H_ */
Index: src/sys/arch/evbarm/netwalker/netwalker_backlight.c
diff -u src/sys/arch/evbarm/netwalker/netwalker_backlight.c:1.2 src/sys/arch/evbarm/netwalker/netwalker_backlight.c:1.3
--- src/sys/arch/evbarm/netwalker/netwalker_backlight.c:1.2 Mon Dec 21 04:26:29 2015
+++ src/sys/arch/evbarm/netwalker/netwalker_backlight.c Wed May 20 05:10:42 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: netwalker_backlight.c,v 1.2 2015/12/21 04:26:29 hkenken Exp $ */
+/* $NetBSD: netwalker_backlight.c,v 1.3 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: netwalker_backlight.c,v 1.2 2015/12/21 04:26:29 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netwalker_backlight.c,v 1.3 2020/05/20 05:10:42 hkenken Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -35,6 +35,8 @@ __KERNEL_RCSID(0, "$NetBSD: netwalker_ba
#include <sys/device.h>
#include <sys/pmf.h>
+#include <dev/pwm/pwmvar.h>
+
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wsfb/genfbvar.h>
@@ -91,7 +93,6 @@ netwalker_backlight_attach(device_t pare
struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
imxpwm->sc_dev = self;
- imxpwm->sc_hz = 1000; /* 1000 Hz */
imxpwm->sc_handler = NULL;
imxpwm->sc_cookie = sc;
imxpwm_attach(imxpwm, aux);
@@ -102,9 +103,8 @@ netwalker_backlight_attach(device_t pare
netwalker_backlight_sc = sc;
/* BackLight 100% On */
- sc->sc_brightness = BRIGHTNESS_MAX;
sc->sc_islit = true;
- imxpwm_set_pwm(imxpwm, 1000);
+ netwalker_set_brightness(sc, BRIGHTNESS_MAX);
if (!pmf_device_register(self, netwalker_backlight_suspend,
netwalker_backlight_resume))
@@ -141,9 +141,8 @@ static int
netwalker_backlight_detach(device_t self, int flags)
{
struct netwalker_backlight_softc *sc = device_private(self);
- struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
- imxpwm_set_pwm(imxpwm, 0);
+ netwalker_set_brightness(sc, 0);
pmf_device_deregister(self);
return 0;
}
@@ -186,7 +185,7 @@ netwalker_backlight_set_brightness(void
{
struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
- KASSERT(level >= 0 && level <= 255);
+ KASSERT(level >= 0 && level <= BRIGHTNESS_MAX);
sc->sc_brightness = level;
netwalker_set_brightness(sc, sc->sc_brightness);
@@ -204,7 +203,7 @@ netwalker_backlight_upd_brightness(void
sc->sc_brightness += delta;
if (sc->sc_brightness < 0) sc->sc_brightness = 0;
- if (sc->sc_brightness > 255) sc->sc_brightness = 255;
+ if (sc->sc_brightness > BRIGHTNESS_MAX) sc->sc_brightness = BRIGHTNESS_MAX;
netwalker_set_brightness(sc, sc->sc_brightness);
return 0;
@@ -276,10 +275,21 @@ netwalker_brightness_down(device_t dv)
}
static void
-netwalker_set_brightness(struct netwalker_backlight_softc *sc, int newval)
+netwalker_set_pwm(struct netwalker_backlight_softc *sc, int val)
{
- struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
+ pwm_tag_t pwm = &sc->sc_imxpwm.sc_pwm;
+ struct pwm_config conf;
+ pwm_disable(pwm);
+ pwm_get_config(pwm, &conf);
+ conf.duty_cycle = (conf.period * val) / BRIGHTNESS_MAX;
+ pwm_set_config(pwm, &conf);
+ pwm_enable(pwm);
+}
+
+static void
+netwalker_set_brightness(struct netwalker_backlight_softc *sc, int newval)
+{
if (newval < 0)
newval = 0;
else if (newval > BRIGHTNESS_MAX)
@@ -287,9 +297,9 @@ netwalker_set_brightness(struct netwalke
sc->sc_brightness = newval;
if (sc->sc_islit)
- imxpwm_set_pwm(imxpwm, 1000 * sc->sc_brightness / BRIGHTNESS_MAX);
+ netwalker_set_pwm(sc, sc->sc_brightness);
else
- imxpwm_set_pwm(imxpwm, 0);
+ netwalker_set_pwm(sc, 0);
}
int