Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Dec 2018 20:56:57 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342003 - in head: share/man/man9 sys/conf sys/dev/pwm sys/sys usr.sbin usr.sbin/pwm
Message-ID:  <201812122056.wBCKuvkH073105@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Wed Dec 12 20:56:56 2018
New Revision: 342003
URL: https://svnweb.freebsd.org/changeset/base/342003

Log:
  Add a pwm subsystem so we can configure pwm controller from kernel and userland.
  
  The pwm subsystem consist of API for PWM controllers, pwmbus to register them
  and a pwm(8) utility to talk to them from userland.
  
  Reviewed by:	oshgobo (capsicum), bcr (manpage), 0mp (manpage)
  Differential Revision:	https://reviews.freebsd.org/D17938

Added:
  head/share/man/man9/pwm.9   (contents, props changed)
  head/share/man/man9/pwmbus.9   (contents, props changed)
  head/sys/dev/pwm/
  head/sys/dev/pwm/ofw_pwm.c   (contents, props changed)
  head/sys/dev/pwm/pwm_if.m   (contents, props changed)
  head/sys/dev/pwm/pwmbus.c   (contents, props changed)
  head/sys/dev/pwm/pwmbus.h   (contents, props changed)
  head/sys/dev/pwm/pwmbus_if.m   (contents, props changed)
  head/sys/dev/pwm/pwmc.c   (contents, props changed)
  head/sys/sys/pwm.h   (contents, props changed)
  head/usr.sbin/pwm/
  head/usr.sbin/pwm/Makefile   (contents, props changed)
  head/usr.sbin/pwm/pwm.8   (contents, props changed)
  head/usr.sbin/pwm/pwm.c   (contents, props changed)
Modified:
  head/share/man/man9/Makefile
  head/sys/conf/files
  head/usr.sbin/Makefile

Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile	Wed Dec 12 20:40:01 2018	(r342002)
+++ head/share/man/man9/Makefile	Wed Dec 12 20:56:56 2018	(r342003)
@@ -269,6 +269,8 @@ MAN=	accept_filter.9 \
 	proc_rwmem.9 \
 	pseudofs.9 \
 	psignal.9 \
+	pwm.9 \
+	pwmbus.9 \
 	random.9 \
 	random_harvest.9 \
 	ratecheck.9 \

Added: head/share/man/man9/pwm.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/pwm.9	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
+.\"
+.\" 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 DEVELOPERS ``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 DEVELOPERS 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$
+.\"
+.Dd November 12, 2018
+.Dt PWM 9
+.Os
+.Sh NAME
+.Nm pwm ,
+.Nm PWM_GET_BUS ,
+.Nm PWM_CHANNEL_CONFIG ,
+.Nm PWM_CHANNEL_GET_CONFIG ,
+.Nm PWM_CHANNEL_SET_FLAGS ,
+.Nm PWM_CHANNEL_GET_FLAGS ,
+.Nm PWM_CHANNEL_ENABLE ,
+.Nm PWM_CHANNEL_IS_ENABLED ,
+.Nm PWM_CHANNEL_MAX
+.Nd PWM methods
+.Sh SYNOPSIS
+.Cd "device pwm"
+.In "pwm_if.h"
+.Ft device_t
+.Fn PWM_GET_BUS "device_t dev"
+.Ft int
+.Fn PWM_CHANNEL_CONFIG "device_t dev" "int channel" "uint64_t period" "uint64_t duty"
+.Ft int
+.Fn PWM_CHANNEL_GET_CONFIG "device_t dev" "int channel" "uint64_t *period" "uint64_t *duty"
+.Ft int
+.Fn PWM_CHANNEL_SET_FLAGS "device_t dev" "int channel" "uint32_t flags"
+.Ft int
+.Fn PWM_CHANNEL_GET_FLAGS "device_t dev" "int channel" "uint32_t *flags"
+.Ft int
+.Fn PWM_CHANNEL_ENABLE "device_t dev" "int channel" "bool enable"
+.Ft int
+.Fn PWM_CHANNEL_IS_ENABLED "device_t dev" "int channel" "bool *enabled"
+.Ft int
+.Fn PWM_CHANNEL_MAX "device_t dev" "int channel" "int *nchannel"
+.Sh DESCRIPTION
+The PWM (Pulse-Width Modulation) interface allows the device driver to register to a global
+bus so other devices in the kernel can use them in a generic way.
+.Sh INTERFACE
+.Bl -tag -width indent
+.It Fn PWM_GET_BUS "device_t dev"
+Return the bus device.
+.It Fn PWM_CHANNEL_CONFIG "device_t dev" "int channel" "uint64_t period" "uint64_t duty"
+Configure the period and duty (in nanoseconds) in the PWM controller for the specified channel.
+Returns 0 on success or
+.Er EINVAL
+if the values are not supported by the controller or
+.Er EBUSY
+is the PWM controller is in use and does not support changing the value on the fly.
+.It Fn PWM_CHANNEL_GET_CONFIG "device_t dev" "int channel" "uint64_t *period" "uint64_t *duty"
+Get the current configuration of the period and duty for the specified channel.
+.It Fn PWM_CHANNEL_SET_FLAGS "device_t dev" "int channel" "uint32_t flags"
+Set the flags of the channel (like inverted polarity).
+.It Fn PWM_CHANNEL_GET_FLAGS "device_t dev" "int channel" "uint32_t *flags"
+Get the current flags for the channel.
+.It Fn PWM_CHANNEL_ENABLE "device_t dev" "int channel" "bool enable"
+Enable the PWM channel.
+.It Fn PWM_CHANNEL_ISENABLED "device_t dev" "int channel" "bool *enable"
+Test if the PWM channel is enabled.
+.It PWM_CHANNEL_MAX "device_t dev" "int channel" "int *nchannel"
+Get the maximum number of channels supported by the controller.
+.El
+.Sh HISTORY
+The
+.Nm pwm
+interface first appeared in
+.Fx 13.0 .
+The
+.Nm pwm
+interface and manual page was written by
+.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .

Added: head/share/man/man9/pwmbus.9
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man9/pwmbus.9	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
+.\"
+.\" 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 DEVELOPERS ``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 DEVELOPERS 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$
+.\"
+.Dd November 12, 2018
+.Dt PWMBUS 9
+.Os
+.Sh NAME
+.Nm pwmbus ,
+.Nm pwmbus_attach_bus ,
+.Nm PWMBUS_GET_BUS ,
+.Nm PWMBUS_CHANNEL_CONFIG ,
+.Nm PWMBUS_CHANNEL_GET_CONFIG ,
+.Nm PWMBUS_CHANNEL_SET_FLAGS ,
+.Nm PWMBUS_CHANNEL_GET_FLAGS ,
+.Nm PWMBUS_CHANNEL_ENABLE ,
+.Nm PWMBUS_CHANNEL_IS_ENABLED ,
+.Nm PWMBUS_CHANNEL_MAX
+.Nd PWMBUS methods
+.Sh SYNOPSIS
+.Cd "device pwm"
+.In "pwmbus_if.h"
+.Ft device_t
+.Fn pwmbus_attach_bus "device_t dev"
+.Ft int
+.Fn PWMBUS_CHANNEL_CONFIG "device_t bus" "int channel" "uint64_t period" "uint64_t duty"
+.Ft int
+.Fn PWMBUS_CHANNEL_GET_CONFIG "device_t bus" "int channel" "uint64_t *period" "uint64_t *duty"
+.Ft int
+.Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
+.Ft int
+.Fn PWMBUS_CHANNEL_GET_FLAGS "device_t bus" "int channel" "uint32_t *flags"
+.Ft int
+.Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
+.Ft int
+.Fn PWMBUS_CHANNEL_IS_ENABLED "device_t bus" "int channel" "bool *enabled"
+.Ft int
+.Fn PWMBUS_CHANNEL_MAX "device_t bus" "int channel" "int *nchannel"
+.Sh DESCRIPTION
+The PWMBUS (Pulse-Width Modulation) interface allows the device driver to register to a global
+bus so other devices in the kernel can use them in a generic way
+.Sh INTERFACE
+.Bl -tag -width indent
+.It Fn pwmbus_attach_bus "device_t dev"
+Attach the
+.Nm pwmbus
+to the device driver
+.It Fn PWMBUS_CHANNEL_CONFIG "device_t bus" "int channel" "uint64_t period" "uint64_t duty"
+Configure the period and duty (in nanoseconds) in the PWM controller on the bus for the specified channel.
+Returns 0 on success or
+.Er EINVAL
+is the values are not supported by the controller or
+.Er EBUSY
+is the PWMBUS controller is in use and doesn't support changing the value on the fly.
+.It Fn PWMBUS_CHANNEL_GET_CONFIG "device_t bus" "int channel" "uint64_t *period" "uint64_t *duty"
+Get the current configuration of the period and duty for the specified channel.
+.It Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
+Set the flags of the channel (like inverted polarity), if the driver or controller
+doesn't support this a default method is used.
+.It Fn PWMBUS_CHANNEL_GET_FLAGS "device_t bus" "int channel" "uint32_t *flags"
+Get the current flags for the channel, if the driver or controller
+doesn't support this, a default method is used.
+.It Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
+Enable the PWM channel.
+.It Fn PWMBUS_CHANNEL_ISENABLED "device_t bus" "int channel" "bool *enable"
+Test if the PWM channel is enabled.
+.It PWMBUS_CHANNEL_MAX "device_t bus" "int channel" "int *nchannel"
+Get the maximum number of channel supported by the controller.
+.El
+.Sh HISTORY
+The
+.Nm pwmbus
+interface first appear in
+.Fx 13.0 .
+The
+.Nm pwmbus
+interface and manual page was written by
+.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Wed Dec 12 20:40:01 2018	(r342002)
+++ head/sys/conf/files	Wed Dec 12 20:56:56 2018	(r342003)
@@ -2746,6 +2746,11 @@ dev/puc/puc.c			optional puc
 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

Added: head/sys/dev/pwm/ofw_pwm.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/ofw_pwm.c	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,109 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pwm/pwmbus.h>
+
+#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));
+}

Added: head/sys/dev/pwm/pwm_if.m
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/pwm_if.m	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,106 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+#
+# Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+#
+# 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 <sys/bus.h>
+
+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;
+};

Added: head/sys/dev/pwm/pwmbus.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/pwmbus.c	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,244 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pwm/pwmbus.h>
+
+#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);

Added: head/sys/dev/pwm/pwmbus.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/pwmbus.h	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ * 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 _PWMBUS_H_
+
+#include <dev/ofw/openfirm.h>
+#include <sys/pwm.h>
+
+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_ */

Added: head/sys/dev/pwm/pwmbus_if.m
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/pwmbus_if.m	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,111 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+#
+# Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+#
+# 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 <sys/bus.h>
+
+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 <sys/pwm.h>
+};
+
+#
+# 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;
+};

Added: head/sys/dev/pwm/pwmc.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/pwm/pwmc.c	Wed Dec 12 20:56:56 2018	(r342003)
@@ -0,0 +1,161 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/time.h>
+
+#include <sys/pwm.h>
+
+#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;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812122056.wBCKuvkH073105>