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
This commit is contained in:
parent
9b5ada0b59
commit
9312900f6d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342003
@ -269,6 +269,8 @@ MAN= accept_filter.9 \
|
|||||||
proc_rwmem.9 \
|
proc_rwmem.9 \
|
||||||
pseudofs.9 \
|
pseudofs.9 \
|
||||||
psignal.9 \
|
psignal.9 \
|
||||||
|
pwm.9 \
|
||||||
|
pwmbus.9 \
|
||||||
random.9 \
|
random.9 \
|
||||||
random_harvest.9 \
|
random_harvest.9 \
|
||||||
ratecheck.9 \
|
ratecheck.9 \
|
||||||
|
93
share/man/man9/pwm.9
Normal file
93
share/man/man9/pwm.9
Normal file
@ -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 .
|
98
share/man/man9/pwmbus.9
Normal file
98
share/man/man9/pwmbus.9
Normal file
@ -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 .
|
@ -2746,6 +2746,11 @@ dev/puc/puc.c optional puc
|
|||||||
dev/puc/puc_cfg.c optional puc
|
dev/puc/puc_cfg.c optional puc
|
||||||
dev/puc/puc_pccard.c optional puc pccard
|
dev/puc/puc_pccard.c optional puc pccard
|
||||||
dev/puc/puc_pci.c optional puc pci
|
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/quicc/quicc_core.c optional quicc
|
||||||
dev/ral/rt2560.c optional ral
|
dev/ral/rt2560.c optional ral
|
||||||
dev/ral/rt2661.c optional ral
|
dev/ral/rt2661.c optional ral
|
||||||
|
109
sys/dev/pwm/ofw_pwm.c
Normal file
109
sys/dev/pwm/ofw_pwm.c
Normal file
@ -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));
|
||||||
|
}
|
106
sys/dev/pwm/pwm_if.m
Normal file
106
sys/dev/pwm/pwm_if.m
Normal file
@ -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;
|
||||||
|
};
|
244
sys/dev/pwm/pwmbus.c
Normal file
244
sys/dev/pwm/pwmbus.c
Normal file
@ -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);
|
64
sys/dev/pwm/pwmbus.h
Normal file
64
sys/dev/pwm/pwmbus.h
Normal file
@ -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_ */
|
111
sys/dev/pwm/pwmbus_if.m
Normal file
111
sys/dev/pwm/pwmbus_if.m
Normal file
@ -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;
|
||||||
|
};
|
161
sys/dev/pwm/pwmc.c
Normal file
161
sys/dev/pwm/pwmc.c
Normal file
@ -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;
|
||||||
|
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);
|
53
sys/sys/pwm.h
Normal file
53
sys/sys/pwm.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*-
|
||||||
|
* 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 _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_ */
|
@ -67,6 +67,7 @@ SUBDIR= adduser \
|
|||||||
pstat \
|
pstat \
|
||||||
pw \
|
pw \
|
||||||
pwd_mkdb \
|
pwd_mkdb \
|
||||||
|
pwm \
|
||||||
quot \
|
quot \
|
||||||
rarpd \
|
rarpd \
|
||||||
rmt \
|
rmt \
|
||||||
|
6
usr.sbin/pwm/Makefile
Normal file
6
usr.sbin/pwm/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
|
PROG= pwm
|
||||||
|
MAN= pwm.8
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
96
usr.sbin/pwm/pwm.8
Normal file
96
usr.sbin/pwm/pwm.8
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
.\" 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 8
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pwm
|
||||||
|
.Nd configure pwm controller
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl f Ar device
|
||||||
|
.Fl c Ar channel
|
||||||
|
.Fl E
|
||||||
|
.Nm
|
||||||
|
.Op Fl f Ar device
|
||||||
|
.Fl c Ar channel
|
||||||
|
.Fl D
|
||||||
|
.Nm
|
||||||
|
.Op Fl f Ar device
|
||||||
|
.Fl c Ar channel
|
||||||
|
.Fl C
|
||||||
|
.Nm
|
||||||
|
.Op Fl f Ar device
|
||||||
|
.Fl c Ar channel
|
||||||
|
.Fl p period
|
||||||
|
.Nm
|
||||||
|
.Op Fl f Ar device
|
||||||
|
.Fl c Ar channel
|
||||||
|
.Fl d duty
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility can be used to configure pwm controllers.
|
||||||
|
.Pp
|
||||||
|
The options are as follow:
|
||||||
|
.Bl -tag -width ".Fl f Ar device"
|
||||||
|
.It Fl c Ar channel
|
||||||
|
Channel number to operate on
|
||||||
|
.It Fl E
|
||||||
|
Enable the pwm channel
|
||||||
|
.It Fl D
|
||||||
|
Disable the pwm channel
|
||||||
|
.It Fl C
|
||||||
|
Show the configuration of the pwm channel
|
||||||
|
.It Fl p Ar period
|
||||||
|
Configure the period (in nanoseconds) of the pwm channel
|
||||||
|
.It Fl d Ar duty
|
||||||
|
Configure the duty (in nanoseconds) of the pwm channel
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
.Bl -bullet
|
||||||
|
.It
|
||||||
|
Show the configuration of the pwm channel:
|
||||||
|
.Pp
|
||||||
|
pwm -f /dev/pwmc0 -C
|
||||||
|
.It
|
||||||
|
Configure a 50000 ns period and a 25000 duty cycles:
|
||||||
|
.Pp
|
||||||
|
pwm -f /dev/pwmc0 -p 50000 -d 25000
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr pwm 9 ,
|
||||||
|
.Xr pwmbus 9
|
||||||
|
.Sh HISTORY
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility appeared in
|
||||||
|
.Fx 13.0 .
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility and this manual page were written by
|
||||||
|
.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .
|
218
usr.sbin/pwm/pwm.c
Normal file
218
usr.sbin/pwm/pwm.c
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*-
|
||||||
|
* 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/pwm.h>
|
||||||
|
#include <sys/capsicum.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <capsicum_helpers.h>
|
||||||
|
|
||||||
|
#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: %lu\nduty: %lu\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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user