Index: head/sys/arm/allwinner/aw_pwm.c =================================================================== --- head/sys/arm/allwinner/aw_pwm.c (revision 342086) +++ head/sys/arm/allwinner/aw_pwm.c (revision 342087) @@ -1,340 +1,340 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "pwm_if.h" #define AW_PWM_CTRL 0x00 #define AW_PWM_CTRL_PRESCALE_MASK 0xF #define AW_PWM_CTRL_EN (1 << 4) #define AW_PWM_CTRL_ACTIVE_LEVEL_HIGH (1 << 5) #define AW_PWM_CTRL_GATE (1 << 6) #define AW_PWM_CTRL_MODE_MASK 0x80 #define AW_PWM_CTRL_PULSE_MODE (1 << 7) #define AW_PWM_CTRL_CYCLE_MODE (0 << 7) #define AW_PWM_CTRL_PULSE_START (1 << 8) #define AW_PWM_CTRL_CLK_BYPASS (1 << 9) #define AW_PWM_CTRL_PERIOD_BUSY (1 << 28) #define AW_PWM_PERIOD 0x04 #define AW_PWM_PERIOD_TOTAL_MASK 0xFFFF #define AW_PWM_PERIOD_TOTAL_SHIFT 16 #define AW_PWM_PERIOD_ACTIVE_MASK 0xFFFF #define AW_PWM_PERIOD_ACTIVE_SHIFT 0 #define AW_PWM_MAX_FREQ 24000000 #define NS_PER_SEC 1000000000 static struct ofw_compat_data compat_data[] = { { "allwinner,sun5i-a13-pwm", 1 }, { NULL, 0 } }; static struct resource_spec aw_pwm_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, 0 } }; struct aw_pwm_softc { device_t dev; device_t busdev; clk_t clk; struct resource *res; uint64_t clk_freq; - uint64_t period; - uint64_t duty; + unsigned int period; + unsigned int duty; uint32_t flags; bool enabled; }; static uint32_t aw_pwm_clk_prescaler[] = { 120, 180, 240, 360, 480, 0, 0, 0, 12000, 24000, 36000, 48000, 72000, 0, 0, 1, }; #define AW_PWM_READ(sc, reg) bus_read_4((sc)->res, (reg)) #define AW_PWM_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val)) static int aw_pwm_probe(device_t dev); static int aw_pwm_attach(device_t dev); static int aw_pwm_detach(device_t dev); static int aw_pwm_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) return (ENXIO); device_set_desc(dev, "Allwinner PWM"); return (BUS_PROBE_DEFAULT); } static int aw_pwm_attach(device_t dev) { struct aw_pwm_softc *sc; /* uint32_t reg; */ int error; sc = device_get_softc(dev); sc->dev = dev; error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (error != 0) { device_printf(dev, "cannot get clock\n"); goto fail; } error = clk_enable(sc->clk); error = clk_get_freq(sc->clk, &sc->clk_freq); if (bus_alloc_resources(dev, aw_pwm_spec, &sc->res) != 0) { device_printf(dev, "cannot allocate resources for device\n"); error = ENXIO; goto fail; } if ((sc->busdev = pwmbus_attach_bus(dev)) == NULL) device_printf(dev, "Cannot attach pwm bus\n"); return (0); fail: aw_pwm_detach(dev); return (error); } static int aw_pwm_detach(device_t dev) { struct aw_pwm_softc *sc; sc = device_get_softc(dev); bus_generic_detach(sc->dev); bus_release_resources(dev, aw_pwm_spec, &sc->res); return (0); } static int aw_pwm_channel_max(device_t dev, int *nchannel) { *nchannel = 1; return (0); } static int -aw_pwm_channel_config(device_t dev, int channel, uint64_t period, uint64_t duty) +aw_pwm_channel_config(device_t dev, int channel, unsigned int period, unsigned int duty) { struct aw_pwm_softc *sc; uint64_t period_freq, duty_freq; uint64_t clk_rate, div; uint32_t reg; int prescaler; int i; sc = device_get_softc(dev); period_freq = NS_PER_SEC / period; if (period_freq > AW_PWM_MAX_FREQ) return (EINVAL); duty_freq = NS_PER_SEC / duty; if (duty_freq < period_freq) { device_printf(sc->dev, "duty < period\n"); return (EINVAL); } /* First test without prescaler */ clk_rate = AW_PWM_MAX_FREQ; prescaler = AW_PWM_CTRL_PRESCALE_MASK; div = AW_PWM_MAX_FREQ / period_freq; if ((div - 1) > AW_PWM_PERIOD_TOTAL_MASK) { /* Test all prescaler */ for (i = 0; i < nitems(aw_pwm_clk_prescaler); i++) { if (aw_pwm_clk_prescaler[i] == 0) continue; div = (AW_PWM_MAX_FREQ * aw_pwm_clk_prescaler[i]) / period_freq; if ((div - 1) < AW_PWM_PERIOD_TOTAL_MASK ) { prescaler = i; clk_rate = AW_PWM_MAX_FREQ / aw_pwm_clk_prescaler[i]; break; } } if (prescaler == AW_PWM_CTRL_PRESCALE_MASK) return (EINVAL); } reg = AW_PWM_READ(sc, AW_PWM_CTRL); if (reg & AW_PWM_CTRL_PERIOD_BUSY) { device_printf(sc->dev, "pwm busy\n"); return (EBUSY); } /* Write the prescalar */ reg &= ~AW_PWM_CTRL_PRESCALE_MASK; reg |= prescaler; AW_PWM_WRITE(sc, AW_PWM_CTRL, reg); /* Write the total/active cycles */ reg = ((clk_rate / period_freq) << AW_PWM_PERIOD_TOTAL_SHIFT) | ((clk_rate / duty_freq) << AW_PWM_PERIOD_ACTIVE_SHIFT); AW_PWM_WRITE(sc, AW_PWM_PERIOD, reg); sc->period = period; sc->duty = duty; return (0); } static int -aw_pwm_channel_get_config(device_t dev, int channel, uint64_t *period, uint64_t *duty) +aw_pwm_channel_get_config(device_t dev, int channel, unsigned int *period, unsigned int *duty) { struct aw_pwm_softc *sc; sc = device_get_softc(dev); *period = sc->period; *duty = sc->duty; return (0); } static int aw_pwm_channel_enable(device_t dev, int channel, bool enable) { struct aw_pwm_softc *sc; uint32_t reg; sc = device_get_softc(dev); if (enable && sc->enabled) return (0); reg = AW_PWM_READ(sc, AW_PWM_CTRL); if (enable) reg |= AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN; else reg &= ~(AW_PWM_CTRL_GATE | AW_PWM_CTRL_EN); AW_PWM_WRITE(sc, AW_PWM_CTRL, reg); sc->enabled = enable; return (0); } static int aw_pwm_channel_is_enabled(device_t dev, int channel, bool *enabled) { struct aw_pwm_softc *sc; sc = device_get_softc(dev); *enabled = sc->enabled; return (0); } static device_t aw_pwm_get_bus(device_t dev) { struct aw_pwm_softc *sc; sc = device_get_softc(dev); return (sc->busdev); } static device_method_t aw_pwm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, aw_pwm_probe), DEVMETHOD(device_attach, aw_pwm_attach), DEVMETHOD(device_detach, aw_pwm_detach), /* pwm interface */ DEVMETHOD(pwm_get_bus, aw_pwm_get_bus), DEVMETHOD(pwm_channel_max, aw_pwm_channel_max), DEVMETHOD(pwm_channel_config, aw_pwm_channel_config), DEVMETHOD(pwm_channel_get_config, aw_pwm_channel_get_config), DEVMETHOD(pwm_channel_enable, aw_pwm_channel_enable), DEVMETHOD(pwm_channel_is_enabled, aw_pwm_channel_is_enabled), DEVMETHOD_END }; static driver_t aw_pwm_driver = { "pwm", aw_pwm_methods, sizeof(struct aw_pwm_softc), }; static devclass_t aw_pwm_devclass; DRIVER_MODULE(aw_pwm, simplebus, aw_pwm_driver, aw_pwm_devclass, 0, 0); SIMPLEBUS_PNP_INFO(compat_data); Index: head/sys/dev/pwm/pwm_if.m =================================================================== --- head/sys/dev/pwm/pwm_if.m (revision 342086) +++ head/sys/dev/pwm/pwm_if.m (revision 342087) @@ -1,106 +1,106 @@ #- # SPDX-License-Identifier: BSD-2-Clause-FreeBSD # # Copyright (c) 2018 Emmanuel Vadot # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # #include INTERFACE pwm; # # Get the bus # METHOD device_t get_bus { device_t dev; }; # # Config the period (Total number of cycle in ns) and # the duty (active number of cycle in ns) # METHOD int channel_config { device_t dev; int channel; - uint64_t period; - uint64_t duty; + unsigned int period; + unsigned duty; }; # # Get the period (Total number of cycle in ns) and # the duty (active number of cycle in ns) # METHOD int channel_get_config { device_t dev; int channel; - uint64_t *period; - uint64_t *duty; + unsigned int *period; + unsigned int *duty; }; # # Set the flags # METHOD int channel_set_flags { device_t dev; int channel; uint32_t flags; }; # # Get the flags # METHOD int channel_get_flags { device_t dev; int channel; uint32_t *flags; }; # # Enable the pwm output # METHOD int channel_enable { device_t dev; int channel; bool enable; }; # # Is the pwm output enabled # METHOD int channel_is_enabled { device_t dev; int channel; bool *enabled; }; # # Get the number of channels # METHOD int channel_max { device_t dev; int *nchannel; }; Index: head/sys/dev/pwm/pwmbus.c =================================================================== --- head/sys/dev/pwm/pwmbus.c (revision 342086) +++ head/sys/dev/pwm/pwmbus.c (revision 342087) @@ -1,244 +1,244 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include "pwmbus_if.h" #include "pwm_if.h" struct pwmbus_channel_data { int reserved; char *name; }; struct pwmbus_softc { device_t busdev; device_t dev; int nchannels; }; device_t pwmbus_attach_bus(device_t dev) { device_t busdev; #ifdef FDT phandle_t node; #endif busdev = device_add_child(dev, "pwmbus", -1); if (busdev == NULL) { device_printf(dev, "Cannot add child pwmbus\n"); return (NULL); } if (device_add_child(dev, "pwmc", -1) == NULL) { device_printf(dev, "Cannot add pwmc\n"); device_delete_child(dev, busdev); return (NULL); } #ifdef FDT node = ofw_bus_get_node(dev); OF_device_register_xref(OF_xref_from_node(node), dev); #endif bus_generic_attach(dev); return (busdev); } static int pwmbus_probe(device_t dev) { device_set_desc(dev, "PWM bus"); return (BUS_PROBE_GENERIC); } static int pwmbus_attach(device_t dev) { struct pwmbus_softc *sc; sc = device_get_softc(dev); sc->busdev = dev; sc->dev = device_get_parent(dev); if (PWM_CHANNEL_MAX(sc->dev, &sc->nchannels) != 0 || sc->nchannels == 0) return (ENXIO); if (bootverbose) device_printf(dev, "Registering %d channel(s)\n", sc->nchannels); bus_generic_probe(dev); return (bus_generic_attach(dev)); } static int pwmbus_detach(device_t dev) { device_t *devlist; int i, rv, ndevs; rv = bus_generic_detach(dev); if (rv != 0) return (rv); rv = device_get_children(dev, &devlist, &ndevs); if (rv != 0) return (rv); for (i = 0; i < ndevs; i++) device_delete_child(dev, devlist[i]); return (0); } static int -pwmbus_channel_config(device_t bus, int channel, uint64_t period, uint64_t duty) +pwmbus_channel_config(device_t bus, int channel, unsigned int period, unsigned int duty) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_CONFIG(sc->dev, channel, period, duty)); } static int -pwmbus_channel_get_config(device_t bus, int channel, uint64_t *period, uint64_t *duty) +pwmbus_channel_get_config(device_t bus, int channel, unsigned int *period, unsigned int *duty) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_GET_CONFIG(sc->dev, channel, period, duty)); } static int pwmbus_channel_set_flags(device_t bus, int channel, uint32_t flags) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_SET_FLAGS(sc->dev, channel, flags)); } static int pwmbus_channel_get_flags(device_t bus, int channel, uint32_t *flags) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_GET_FLAGS(sc->dev, channel, flags)); } static int pwmbus_channel_enable(device_t bus, int channel, bool enable) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_ENABLE(sc->dev, channel, enable)); } static int pwmbus_channel_is_enabled(device_t bus, int channel, bool *enable) { struct pwmbus_softc *sc; sc = device_get_softc(bus); if (channel > sc->nchannels) return (EINVAL); return (PWM_CHANNEL_IS_ENABLED(sc->dev, channel, enable)); } static device_method_t pwmbus_methods[] = { /* device_if */ DEVMETHOD(device_probe, pwmbus_probe), DEVMETHOD(device_attach, pwmbus_attach), DEVMETHOD(device_detach, pwmbus_detach), /* pwm interface */ DEVMETHOD(pwmbus_channel_config, pwmbus_channel_config), DEVMETHOD(pwmbus_channel_get_config, pwmbus_channel_get_config), DEVMETHOD(pwmbus_channel_set_flags, pwmbus_channel_set_flags), DEVMETHOD(pwmbus_channel_get_flags, pwmbus_channel_get_flags), DEVMETHOD(pwmbus_channel_enable, pwmbus_channel_enable), DEVMETHOD(pwmbus_channel_is_enabled, pwmbus_channel_is_enabled), DEVMETHOD_END }; driver_t pwmbus_driver = { "pwmbus", pwmbus_methods, sizeof(struct pwmbus_softc), }; devclass_t pwmbus_devclass; EARLY_DRIVER_MODULE(pwmbus, pwm, pwmbus_driver, pwmbus_devclass, 0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(pwmbus, 1); Index: head/sys/dev/pwm/pwmbus_if.m =================================================================== --- head/sys/dev/pwm/pwmbus_if.m (revision 342086) +++ head/sys/dev/pwm/pwmbus_if.m (revision 342087) @@ -1,111 +1,111 @@ #- # SPDX-License-Identifier: BSD-2-Clause-FreeBSD # # Copyright (c) 2018 Emmanuel Vadot # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $FreeBSD$ # #include INTERFACE pwmbus; CODE { static int pwm_default_set_flags(device_t dev, int channel, uint32_t flags) { return (EOPNOTSUPP); } static int pwm_default_get_flags(device_t dev, int channel, uint32_t *flags) { *flags = 0; return (0); } }; HEADER { #include }; # # Config the period (Total number of cycle in ns) and # the duty (active number of cycle in ns) # METHOD int channel_config { device_t bus; int channel; - uint64_t period; - uint64_t duty; + unsigned int period; + unsigned int duty; }; # # Get the period (Total number of cycle in ns) and # the duty (active number of cycle in ns) # METHOD int channel_get_config { device_t bus; int channel; - uint64_t *period; - uint64_t *duty; + unsigned int *period; + unsigned int *duty; }; # # Set the flags # METHOD int channel_set_flags { device_t bus; int channel; uint32_t flags; } DEFAULT pwm_default_set_flags; # # Get the flags # METHOD int channel_get_flags { device_t dev; int channel; uint32_t *flags; } DEFAULT pwm_default_get_flags; # # Enable the pwm output # METHOD int channel_enable { device_t bus; int channel; bool enable; }; # # Is the pwm output enabled # METHOD int channel_is_enabled { device_t bus; int channel; bool *enabled; }; Index: head/sys/sys/pwm.h =================================================================== --- head/sys/sys/pwm.h (revision 342086) +++ head/sys/sys/pwm.h (revision 342087) @@ -1,53 +1,53 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _PWM_H_ #define _PWM_H_ #define PWM_POLARITY_INVERTED (1 << 0) struct pwm_state { int channel; - uint64_t period; - uint64_t duty; + unsigned int period; + unsigned int duty; uint32_t flags; bool enable; }; /* * ioctls */ #define PWMMAXCHANNEL _IOWR('G', 0, int) #define PWMGETSTATE _IOWR('G', 1, struct pwm_state) #define PWMSETSTATE _IOWR('G', 2, struct pwm_state) #endif /* _PWM_H_ */ Index: head/usr.sbin/pwm/pwm.c =================================================================== --- head/usr.sbin/pwm/pwm.c (revision 342086) +++ head/usr.sbin/pwm/pwm.c (revision 342087) @@ -1,218 +1,218 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PWM_ENABLE 0x0001 #define PWM_DISABLE 0x0002 #define PWM_SHOW_CONFIG 0x0004 #define PWM_PERIOD 0x0008 #define PWM_DUTY 0x0010 static void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tpwm [-f dev] -c channel -E\n"); fprintf(stderr, "\tpwm [-f dev] -c channel -D\n"); fprintf(stderr, "\tpwm [-f dev] -c channel -C\n"); fprintf(stderr, "\tpwm [-f dev] -c channel -p period\n"); fprintf(stderr, "\tpwm [-f dev] -c channel -d duty\n"); exit(1); } int main(int argc, char *argv[]) { struct pwm_state state; int fd; int channel, nchannels; int period, duty; int action, ch; cap_rights_t right_ioctl; const unsigned long pwm_ioctls[] = {PWMGETSTATE, PWMSETSTATE, PWMMAXCHANNEL}; action = 0; fd = -1; channel = -1; period = duty = -1; while ((ch = getopt(argc, argv, "f:c:EDCp:d:")) != -1) { switch (ch) { case 'E': if (action) usage(); action = PWM_ENABLE; break; case 'D': if (action) usage(); action = PWM_DISABLE; break; case 'C': if (action) usage(); action = PWM_SHOW_CONFIG; break; case 'p': if (action & ~(PWM_PERIOD | PWM_DUTY)) usage(); action = PWM_PERIOD; period = strtol(optarg, NULL, 10); break; case 'd': if (action & ~(PWM_PERIOD | PWM_DUTY)) usage(); action = PWM_DUTY; duty = strtol(optarg, NULL, 10); break; case 'c': if (channel != -1) usage(); channel = strtol(optarg, NULL, 10); break; case 'f': if ((fd = open(optarg, O_RDWR)) < 0) { fprintf(stderr, "pwm: cannot open %s %s\n", optarg, strerror(errno)); exit(1); } } } if (fd == -1) { if ((fd = open("/dev/pwmc0", O_RDWR)) < 0) { fprintf(stderr, "pwm: cannot open %s %s\n", optarg, strerror(errno)); exit(1); } } if (action == 0 || fd == -1) usage(); if (caph_limit_stdio() < 0) { fprintf(stderr, "can't limit stdio rights"); goto fail; } caph_cache_catpages(); cap_rights_init(&right_ioctl, CAP_IOCTL); if (caph_rights_limit(fd, &right_ioctl) < 0) { fprintf(stderr, "cap_right_limit() failed\n"); goto fail; } if (caph_ioctls_limit(fd, pwm_ioctls, nitems(pwm_ioctls)) < 0) { fprintf(stderr, "caph_ioctls_limit() failed\n"); goto fail; } if (caph_enter() < 0) { fprintf(stderr, "failed to enter capability mode\n"); goto fail; } /* Check if the channel is correct */ if (ioctl(fd, PWMMAXCHANNEL, &nchannels) == -1) { fprintf(stderr, "ioctl: %s\n", strerror(errno)); goto fail; } if (channel > nchannels) { fprintf(stderr, "pwm controller only support %d channels\n", nchannels); goto fail; } /* Fill the common args */ state.channel = channel; if (ioctl(fd, PWMGETSTATE, &state) == -1) { fprintf(stderr, "Cannot get current state of the pwm controller\n"); goto fail; } switch (action) { case PWM_ENABLE: if (state.enable == false) { state.enable = true; if (ioctl(fd, PWMSETSTATE, &state) == -1) { fprintf(stderr, "Cannot enable the pwm controller\n"); goto fail; } } break; case PWM_DISABLE: if (state.enable == true) { state.enable = false; if (ioctl(fd, PWMSETSTATE, &state) == -1) { fprintf(stderr, "Cannot disable the pwm controller\n"); goto fail; } } break; case PWM_SHOW_CONFIG: - printf("period: %ju\nduty: %ju\nenabled:%d\n", - (uintmax_t) state.period, - (uintmax_t) state.duty, + printf("period: %u\nduty: %u\nenabled:%d\n", + state.period, + state.duty, state.enable); break; case PWM_PERIOD: case PWM_DUTY: if (period != -1) state.period = period; if (duty != -1) state.duty = duty; if (ioctl(fd, PWMSETSTATE, &state) == -1) { fprintf(stderr, "Cannot configure the pwm controller\n"); goto fail; } break; } close(fd); return (0); fail: close(fd); return (1); }