From owner-svn-src-head@FreeBSD.ORG Tue Sep 2 03:23:07 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 333B9A03; Tue, 2 Sep 2014 03:23:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1D00C1A86; Tue, 2 Sep 2014 03:23:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s823N6bq049580; Tue, 2 Sep 2014 03:23:06 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s823N6X2049576; Tue, 2 Sep 2014 03:23:06 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201409020323.s823N6X2049576@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Tue, 2 Sep 2014 03:23:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r270957 - in head/sys: conf dev/fdt X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Sep 2014 03:23:07 -0000 Author: ian Date: Tue Sep 2 03:23:05 2014 New Revision: 270957 URL: http://svnweb.freebsd.org/changeset/base/270957 Log: Create an interface for drivers to enable or disable their clocks as listed in the clocks=<...> properties of their FDT data. The clock properties consist of 2-cell tuples, each containing a clock device node reference and a clock number. A clock device driver can register itself as providing this interface, then other drivers can turn the FDT clock node reference into the corresponding device_t so that they can use the interface to query and manipulate their clocks. This provides convenience functions to enable or disable all the clocks listed in the properties for a device, so most drivers will be able to manage their clocks with a single call to fdt_clock_enable_all(dev). Added: head/sys/dev/fdt/fdt_clock.c (contents, props changed) head/sys/dev/fdt/fdt_clock.h (contents, props changed) head/sys/dev/fdt/fdt_clock_if.m (contents, props changed) Modified: head/sys/conf/files Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Tue Sep 2 02:56:43 2014 (r270956) +++ head/sys/conf/files Tue Sep 2 03:23:05 2014 (r270957) @@ -1376,6 +1376,8 @@ dev/fatm/if_fatm.c optional fatm pci dev/fb/fbd.c optional fbd | vt dev/fb/fb_if.m standard dev/fb/splash.c optional sc splash +dev/fdt/fdt_clock.c optional fdt +dev/fdt/fdt_clock_if.m optional fdt dev/fdt/fdt_common.c optional fdt dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ Added: head/sys/dev/fdt/fdt_clock.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/fdt/fdt_clock.c Tue Sep 2 03:23:05 2014 (r270957) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2014 Ian Lepore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fdt_clock_if.h" +#include + +/* + * Loop through all the tuples in the clocks= property for a device, enabling or + * disabling each clock. + * + * Be liberal about errors for now: warn about a failure to enable but keep + * trying with any other clocks in the list. Return ENXIO if any errors were + * found, and let the caller decide whether the problem is fatal. + */ +static int +enable_disable_all(device_t consumer, boolean_t enable) +{ + phandle_t cnode; + device_t clockdev; + int clocknum, err, i, ncells; + uint32_t *clks; + boolean_t anyerrors; + + cnode = ofw_bus_get_node(consumer); + ncells = OF_getencprop_alloc(cnode, "clocks", sizeof(*clks), + (void **)&clks); + if (enable && ncells < 2) { + device_printf(consumer, "Warning: No clocks specified in fdt " + "data; device may not function."); + return (ENXIO); + } + anyerrors = false; + for (i = 0; i < ncells; i += 2) { + clockdev = OF_device_from_xref(clks[i]); + clocknum = clks[i + 1]; + if (clockdev == NULL) { + if (enable) + device_printf(consumer, "Warning: can not find " + "driver for clock number %u; device may not " + "function\n", clocknum); + anyerrors = true; + continue; + } + if (enable) + err = FDT_CLOCK_ENABLE(clockdev, clocknum); + else + err = FDT_CLOCK_DISABLE(clockdev, clocknum); + if (err != 0) { + if (enable) + device_printf(consumer, "Warning: failed to " + "enable clock number %u; device may not " + "function\n", clocknum); + anyerrors = true; + } + } + free(clks, M_OFWPROP); + return (anyerrors ? ENXIO : 0); +} + +int +fdt_clock_get_info(device_t consumer, int n, struct fdt_clock_info *info) +{ + phandle_t cnode; + device_t clockdev; + int clocknum, err, ncells; + uint32_t *clks; + + cnode = ofw_bus_get_node(consumer); + ncells = OF_getencprop_alloc(cnode, "clocks", sizeof(*clks), + (void **)&clks); + if (ncells <= 0) + return (ENXIO); + n *= 2; + if (ncells <= n) + err = ENXIO; + else { + clockdev = OF_device_from_xref(clks[n]); + if (clockdev == NULL) + err = ENXIO; + else { + /* + * Make struct contents minimally valid, then call + * provider to fill in what it knows (provider can + * override anything it wants to). + */ + clocknum = clks[n + 1]; + memset(info, 0, sizeof(*info)); + info->provider = clockdev; + info->index = clocknum; + info->name = ""; + err = FDT_CLOCK_GET_INFO(clockdev, clocknum, info); + } + } + free(clks, M_OFWPROP); + return (err); +} + +int +fdt_clock_enable_all(device_t consumer) +{ + + return (enable_disable_all(consumer, true)); +} + +int +fdt_clock_disable_all(device_t consumer) +{ + + return (enable_disable_all(consumer, false)); +} + +void +fdt_clock_register_provider(device_t provider) +{ + + OF_device_register_xref(OF_xref_from_node(provider), provider); +} + +void +fdt_clock_unregister_provider(device_t provider) +{ + + OF_device_register_xref(OF_xref_from_node(provider), NULL); +} + Added: head/sys/dev/fdt/fdt_clock.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/fdt/fdt_clock.h Tue Sep 2 03:23:05 2014 (r270957) @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2014 Ian Lepore + * 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 ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef DEV_FDT_CLOCK_H +#define DEV_FDT_CLOCK_H + +#include "fdt_clock_if.h" + +/* + * Get info about the Nth clock listed in consumer's "clocks" property. + * + * Returns 0 on success, ENXIO if clock #n not found. + */ +int fdt_clock_get_info(device_t consumer, int n, struct fdt_clock_info *info); + +/* + * Look up "clocks" property in consumer's fdt data and enable or disable all + * configured clocks. + */ +int fdt_clock_enable_all(device_t consumer); +int fdt_clock_disable_all(device_t consumer); + +/* + * [Un]register the given device instance as a driver that implements the + * fdt_clock interface. + */ +void fdt_clock_register_provider(device_t provider); +void fdt_clock_unregister_provider(device_t provider); + +#endif /* DEV_FDT_CLOCK_H */ + Added: head/sys/dev/fdt/fdt_clock_if.m ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/fdt/fdt_clock_if.m Tue Sep 2 03:23:05 2014 (r270957) @@ -0,0 +1,81 @@ +#- +# Copyright (c) 2014 Ian Lepore +# 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 + +# +# This is the interface that fdt_clock drivers provide to other drivers. +# In this context, clock refers to a clock signal provided to some other +# hardware component within the system. They are most often found within +# embedded processors that have on-chip IO controllers. +# + +INTERFACE fdt_clock; + +HEADER { + + enum { + FDT_CIFLAG_RUNNING = 0x01, + }; + + struct fdt_clock_info { + device_t provider; + uint32_t index; + const char * name; /* May be "", will not be NULL. */ + uint32_t flags; + uint64_t frequency; /* In Hz. */ + }; +} + +# +# Enable the specified clock. +# Returns 0 on success or a standard errno value. +# +METHOD int enable { + device_t provider; + int index; +}; + +# +# Disable the specified clock. +# Returns 0 on success or a standard errno value. +# +METHOD int disable { + device_t provider; + int index; +}; + +# +# Returns information about the current operational state of specified clock. +# +METHOD int get_info { + device_t provider; + int index; + struct fdt_clock_info *info; +}; +