Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -2738,6 +2738,11 @@ dev/puc/puc_cfg.c optional puc dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci +dev/pwm/pwmc.c optional pwm +dev/pwm/pwmbus.c optional pwm +dev/pwm/pwm_if.m optional pwm +dev/pwm/pwmbus_if.m optional pwm +dev/pwm/ofw_pwm.c optional pwm fdt dev/quicc/quicc_core.c optional quicc dev/ral/rt2560.c optional ral dev/ral/rt2661.c optional ral Index: sys/dev/pwm/ofw_pwm.c =================================================================== --- /dev/null +++ sys/dev/pwm/ofw_pwm.c @@ -0,0 +1,109 @@ +/*- + * 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 +#include +#include +#include +#include + +#include +#include + +#include + +#include "pwm_if.h" + +int +pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, + const char *prop_name, int idx, pwm_channel_t *out_channel) +{ + phandle_t xref; + pcell_t *cells; + struct pwm_channel channel; + int ncells, rv; + + rv = ofw_bus_parse_xref_list_alloc(node, prop_name, "#pwm-cells", + idx, &xref, &ncells, &cells); + if (rv != 0) + return (rv); + + channel.dev = OF_device_from_xref(xref); + if (channel.dev == NULL) { + OF_prop_free(cells); + return (ENODEV); + } + + channel.busdev = PWM_GET_BUS(channel.dev); + if (channel.busdev == NULL) { + OF_prop_free(cells); + return (ENODEV); + } + + channel.channel = cells[0]; + channel.period = cells[1]; + + if (ncells >= 3) + channel.flags = cells[2]; + + *out_channel = malloc(sizeof(struct pwm_channel), M_DEVBUF, M_WAITOK | M_ZERO); + **out_channel = channel; + return (0); +} + +int +pwm_get_by_ofw_idx(device_t consumer, phandle_t node, int idx, + pwm_channel_t *out_channel) +{ + + return (pwm_get_by_ofw_propidx(consumer, node, "pwms", idx, out_channel)); +} + +int +pwm_get_by_ofw_property(device_t consumer, phandle_t node, + const char *prop_name, pwm_channel_t *out_channel) +{ + + return (pwm_get_by_ofw_propidx(consumer, node, prop_name, 0, out_channel)); +} + +int +pwm_get_by_ofw_name(device_t consumer, phandle_t node, const char *name, + pwm_channel_t *out_channel) +{ + int rv, idx; + + rv = ofw_bus_find_string_index(node, "pwm-names", name, &idx); + if (rv != 0) + return (rv); + + return (pwm_get_by_ofw_idx(consumer, node, idx, out_channel)); +} Index: sys/dev/pwm/pwm_if.m =================================================================== --- /dev/null +++ sys/dev/pwm/pwm_if.m @@ -0,0 +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; +}; + +# +# 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; +}; + +# +# 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: sys/dev/pwm/pwmbus.h =================================================================== --- /dev/null +++ sys/dev/pwm/pwmbus.h @@ -0,0 +1,64 @@ +/*- + * 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. + */ + +#ifndef _PWMBUS_H_ + +#include +#include + +#define PWM_POLARITY_INVERTED (1 << 0) + +struct pwm_channel { + device_t dev; + device_t busdev; + int channel; + uint64_t period; + uint64_t duty; + uint32_t flags; + bool enabled; +}; +typedef struct pwm_channel *pwm_channel_t; + +device_t pwmbus_attach_bus(device_t dev); +int pwmbus_acquire_channel(device_t bus, int channel); +int pwmbus_release_channel(device_t bus, int channel); + +int +pwm_get_by_ofw_propidx(device_t consumer, phandle_t node, + const char *prop_name, int idx, pwm_channel_t *channel); +int +pwm_get_by_ofw_idx(device_t consumer, phandle_t node, int idx, + pwm_channel_t *out_channel); +int +pwm_get_by_ofw_property(device_t consumer, phandle_t node, + const char *prop_name, pwm_channel_t *out_channel); +int +pwm_get_by_ofw_name(device_t consumer, phandle_t node, const char *name, + pwm_channel_t *out_channel); + +#endif /* _PWMBUS_H_ */ Index: sys/dev/pwm/pwmbus.c =================================================================== --- /dev/null +++ sys/dev/pwm/pwmbus.c @@ -0,0 +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) +{ + 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) +{ + 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: sys/dev/pwm/pwmbus_if.m =================================================================== --- /dev/null +++ sys/dev/pwm/pwmbus_if.m @@ -0,0 +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; +}; + +# +# 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; +}; + +# +# 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: sys/dev/pwm/pwmc.c =================================================================== --- /dev/null +++ sys/dev/pwm/pwmc.c @@ -0,0 +1,161 @@ +/*- + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "pwmbus_if.h" +#include "pwm_if.h" + +struct pwmc_softc { + device_t dev; + device_t pdev; + struct cdev *pwm_dev; + char name[32]; +}; + +static int +pwm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td) +{ + struct pwmc_softc *sc; + struct pwm_state state; + device_t bus; + int nchannel; + int rv = 0; + + sc = dev->si_drv1; + bus = PWM_GET_BUS(sc->pdev); + if (bus == NULL) + return (EINVAL); + + switch (cmd) { + case PWMMAXCHANNEL: + nchannel = -1; + rv = PWM_CHANNEL_MAX(sc->pdev, &nchannel); + bcopy(&nchannel, data, sizeof(nchannel)); + break; + case PWMSETSTATE: + bcopy(data, &state, sizeof(state)); + rv = PWMBUS_CHANNEL_CONFIG(bus, state.channel, + state.period, state.duty); + if (rv == 0) + rv = PWMBUS_CHANNEL_ENABLE(bus, state.channel, + state.enable); + break; + case PWMGETSTATE: + bcopy(data, &state, sizeof(state)); + rv = PWMBUS_CHANNEL_GET_CONFIG(bus, state.channel, + &state.period, &state.duty); + if (rv != 0) + return (rv); + rv = PWMBUS_CHANNEL_IS_ENABLED(bus, state.channel, + &state.enable); + if (rv != 0) + return (rv); + bcopy(&state, data, sizeof(state)); + break; + } + + return (rv); +} + +static struct cdevsw pwm_cdevsw = { + .d_version = D_VERSION, + .d_name = "pwm", + .d_ioctl = pwm_ioctl +}; + +static int +pwmc_probe(device_t dev) +{ + + device_set_desc(dev, "PWM Controller"); + return (0); +} + +static int +pwmc_attach(device_t dev) +{ + struct pwmc_softc *sc; + struct make_dev_args args; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->pdev = device_get_parent(dev); + + snprintf(sc->name, sizeof(sc->name), "pwmc%d", device_get_unit(dev)); + make_dev_args_init(&args); + args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK; + args.mda_devsw = &pwm_cdevsw; + args.mda_uid = UID_ROOT; + args.mda_gid = GID_OPERATOR; + args.mda_mode = 0600; + args.mda_si_drv1 = sc; + if (make_dev_s(&args, &sc->pwm_dev, "%s", sc->name) != 0) { + device_printf(dev, "Failed to make PWM device\n"); + return (ENXIO); + } + return (0); +} + +static int +pwmc_detach(device_t dev) +{ + + return (0); +} + +static device_method_t pwmc_methods[] = { + /* device_if */ + DEVMETHOD(device_probe, pwmc_probe), + DEVMETHOD(device_attach, pwmc_attach), + DEVMETHOD(device_detach, pwmc_detach), + + DEVMETHOD_END +}; + +driver_t pwmc_driver = { + "pwmc", + pwmc_methods, + sizeof(struct pwmc_softc), +}; +devclass_t pwmc_devclass; + +DRIVER_MODULE(pwmc, pwm, pwmc_driver, pwmc_devclass, 0, 0); +MODULE_VERSION(pwmc, 1); Index: sys/sys/pwm.h =================================================================== --- /dev/null +++ sys/sys/pwm.h @@ -0,0 +1,51 @@ +/*- + * 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. + */ + +#ifndef _PWM_H_ +#define _PWM_H_ + +#define PWM_POLARITY_INVERTED (1 << 0) + +struct pwm_state { + int channel; + uint64_t period; + uint64_t 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_ */