Restructure the pwm device hirearchy and interfaces.

The pwm and pwmbus interfaces were nearly identical, this merges them into a
single pwmbus interface.  The pwmbus driver now implements the pwmbus
interface by simply passing all calls through to its parent (the hardware
driver).  The channel_count method moves from pwm to pwmbus, and the
get_bus method is deleted (just no longer needed).

The net effect is that the interface for doing pwm stuff is now the same
regardless of whether you're a child of pwmbus, or some random driver
elsewhere in the hierarchy that is bypassing the pwmbus layer and is talking
directly to the hardware driver via cross-hierarchy connections established
using fdt data.

The pwmc driver is now a child of pwmbus, instead of being its sibling
(that's why the get_bus method is no longer needed; pwmc now gets the
device_t of the bus using device_get_parent()).
This commit is contained in:
Ian Lepore 2019-06-15 22:25:39 +00:00
parent 6bb8042535
commit f8f8d87cd9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=349086
8 changed files with 57 additions and 210 deletions

View File

@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pwm/pwmbus.h>
#include "pwm_if.h"
#include "pwmbus_if.h"
#define AW_PWM_CTRL 0x00
#define AW_PWM_CTRL_PRESCALE_MASK 0xF
@ -346,28 +346,18 @@ aw_pwm_channel_is_enabled(device_t dev, int channel, bool *enabled)
return (0);
}
static device_t
aw_pwm_get_bus(device_t dev)
{
struct aw_pwm_softc *sc;
sc = device_get_softc(dev);
return (sc->busdev);
}
static device_method_t aw_pwm_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, aw_pwm_probe),
DEVMETHOD(device_attach, aw_pwm_attach),
DEVMETHOD(device_detach, aw_pwm_detach),
/* pwm interface */
DEVMETHOD(pwm_get_bus, aw_pwm_get_bus),
DEVMETHOD(pwm_channel_count, aw_pwm_channel_count),
DEVMETHOD(pwm_channel_config, aw_pwm_channel_config),
DEVMETHOD(pwm_channel_get_config, aw_pwm_channel_get_config),
DEVMETHOD(pwm_channel_enable, aw_pwm_channel_enable),
DEVMETHOD(pwm_channel_is_enabled, aw_pwm_channel_is_enabled),
/* pwmbus interface */
DEVMETHOD(pwmbus_channel_count, aw_pwm_channel_count),
DEVMETHOD(pwmbus_channel_config, aw_pwm_channel_config),
DEVMETHOD(pwmbus_channel_get_config, aw_pwm_channel_get_config),
DEVMETHOD(pwmbus_channel_enable, aw_pwm_channel_enable),
DEVMETHOD(pwmbus_channel_is_enabled, aw_pwm_channel_is_enabled),
DEVMETHOD_END
};

View File

@ -2702,7 +2702,6 @@ dev/puc/puc_pccard.c optional puc pccard
dev/puc/puc_pci.c optional puc pci
dev/pwm/pwmc.c optional pwm | pwmc
dev/pwm/pwmbus.c optional pwm | pwmbus
dev/pwm/pwm_if.m optional pwm | pwmbus
dev/pwm/pwmbus_if.m optional pwm | pwmbus
dev/pwm/ofw_pwm.c optional pwm fdt | pwmbus fdt
dev/quicc/quicc_core.c optional quicc

View File

@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pwm/pwmbus.h>
#include "pwm_if.h"
#include "pwmbus_if.h"
int
pwm_get_by_ofw_propidx(device_t consumer, phandle_t node,
@ -62,12 +62,6 @@ pwm_get_by_ofw_propidx(device_t consumer, phandle_t node,
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];

View File

@ -1,106 +0,0 @@
#-
# 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;
unsigned int period;
unsigned duty;
};
#
# Get the period (Total number of cycle in ns) and
# the duty (active number of cycle in ns)
#
METHOD int channel_get_config {
device_t dev;
int channel;
unsigned int *period;
unsigned int *duty;
};
#
# Set the flags
#
METHOD int channel_set_flags {
device_t dev;
int channel;
uint32_t flags;
};
#
# Get the flags
#
METHOD int channel_get_flags {
device_t dev;
int channel;
uint32_t *flags;
};
#
# Enable the pwm output
#
METHOD int channel_enable {
device_t dev;
int channel;
bool enable;
};
#
# Is the pwm output enabled
#
METHOD int channel_is_enabled {
device_t dev;
int channel;
bool *enabled;
};
#
# Get the number of channels
#
METHOD int channel_count {
device_t dev;
int *nchannel;
};

View File

@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <dev/pwm/pwmbus.h>
#include "pwmbus_if.h"
#include "pwm_if.h"
struct pwmbus_channel_data {
int reserved;
@ -55,8 +54,8 @@ struct pwmbus_channel_data {
};
struct pwmbus_softc {
device_t busdev;
device_t dev;
device_t parent;
int nchannels;
};
@ -75,15 +74,18 @@ pwmbus_attach(device_t dev)
struct pwmbus_softc *sc;
sc = device_get_softc(dev);
sc->busdev = dev;
sc->dev = device_get_parent(dev);
sc->dev = dev;
sc->parent = device_get_parent(dev);
if (PWM_CHANNEL_COUNT(sc->dev, &sc->nchannels) != 0 ||
sc->nchannels == 0)
if (PWMBUS_CHANNEL_COUNT(sc->parent, &sc->nchannels) != 0 ||
sc->nchannels == 0) {
device_printf(sc->dev, "No channels on parent %s\n",
device_get_nameunit(sc->parent));
return (ENXIO);
}
device_add_child(sc->dev, "pwmc", -1);
if (bootverbose)
device_printf(dev, "Registering %d channel(s)\n", sc->nchannels);
bus_generic_probe(dev);
return (bus_generic_attach(dev));
@ -101,96 +103,61 @@ pwmbus_detach(device_t dev)
}
static int
pwmbus_channel_config(device_t bus, int chan, u_int period, u_int duty)
pwmbus_channel_config(device_t dev, int chan, u_int period, u_int duty)
{
struct pwmbus_softc *sc;
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_CONFIG(sc->dev, chan, period, duty));
return (PWMBUS_CHANNEL_CONFIG(device_get_parent(dev), chan, period, duty));
}
static int
pwmbus_channel_get_config(device_t bus, int chan, u_int *period, u_int *duty)
pwmbus_channel_get_config(device_t dev, int chan, u_int *period, u_int *duty)
{
struct pwmbus_softc *sc;
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_GET_CONFIG(sc->dev, chan, period, duty));
return (PWMBUS_CHANNEL_GET_CONFIG(device_get_parent(dev), chan, period, duty));
}
static int
pwmbus_channel_set_flags(device_t bus, int chan, uint32_t flags)
pwmbus_channel_get_flags(device_t dev, int chan, uint32_t *flags)
{
struct pwmbus_softc *sc;
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_SET_FLAGS(sc->dev, chan, flags));
return (PWMBUS_CHANNEL_GET_FLAGS(device_get_parent(dev), chan, flags));
}
static int
pwmbus_channel_get_flags(device_t bus, int chan, uint32_t *flags)
pwmbus_channel_enable(device_t dev, int chan, bool enable)
{
struct pwmbus_softc *sc;
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_GET_FLAGS(sc->dev, chan, flags));
return (PWMBUS_CHANNEL_ENABLE(device_get_parent(dev), chan, enable));
}
static int
pwmbus_channel_enable(device_t bus, int chan, bool enable)
pwmbus_channel_set_flags(device_t dev, int chan, uint32_t flags)
{
struct pwmbus_softc *sc;
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_ENABLE(sc->dev, chan, enable));
return (PWMBUS_CHANNEL_SET_FLAGS(device_get_parent(dev), chan, flags));
}
static int
pwmbus_channel_is_enabled(device_t bus, int chan, bool *enable)
pwmbus_channel_is_enabled(device_t dev, int chan, bool *enable)
{
struct pwmbus_softc *sc;
return (PWMBUS_CHANNEL_IS_ENABLED(device_get_parent(dev), chan, enable));
}
sc = device_get_softc(bus);
if (chan > sc->nchannels)
return (EINVAL);
return (PWM_CHANNEL_IS_ENABLED(sc->dev, chan, enable));
static int
pwmbus_channel_count(device_t dev, int *nchannel)
{
return (PWMBUS_CHANNEL_COUNT(device_get_parent(dev), nchannel));
}
static device_method_t pwmbus_methods[] = {
/* device_if */
DEVMETHOD(device_probe, pwmbus_probe),
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),
/* pwmbus_if */
DEVMETHOD(pwmbus_channel_count, pwmbus_channel_count),
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
};

View File

@ -34,7 +34,6 @@
struct pwm_channel {
device_t dev;
device_t busdev;
int channel;
uint64_t period;
uint64_t duty;

View File

@ -105,3 +105,11 @@ METHOD int channel_is_enabled {
int channel;
bool *enabled;
};
#
# Get the number of channels
#
METHOD int channel_count {
device_t bus;
int *nchannel;
};

View File

@ -40,11 +40,9 @@ __FBSDID("$FreeBSD$");
#include <dev/pwm/pwmc.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];
};
@ -60,14 +58,12 @@ pwm_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
int rv = 0;
sc = dev->si_drv1;
bus = PWM_GET_BUS(sc->pdev);
if (bus == NULL)
return (EINVAL);
bus = device_get_parent(sc->dev);
switch (cmd) {
case PWMMAXCHANNEL:
nchannel = -1;
rv = PWM_CHANNEL_COUNT(sc->pdev, &nchannel);
rv = PWMBUS_CHANNEL_COUNT(bus, &nchannel);
bcopy(&nchannel, data, sizeof(nchannel));
break;
case PWMSETSTATE:
@ -106,7 +102,7 @@ pwmc_probe(device_t dev)
{
device_set_desc(dev, "PWM Controller");
return (0);
return (BUS_PROBE_NOWILDCARD);
}
static int
@ -117,7 +113,6 @@ pwmc_attach(device_t dev)
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);
@ -161,5 +156,6 @@ static driver_t pwmc_driver = {
};
static devclass_t pwmc_devclass;
DRIVER_MODULE(pwmc, pwm, pwmc_driver, pwmc_devclass, 0, 0);
DRIVER_MODULE(pwmc, pwmbus, pwmc_driver, pwmc_devclass, 0, 0);
MODULE_DEPEND(pwmc, pwmbus, 1, 1, 1);
MODULE_VERSION(pwmc, 1);