summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2016-06-17 09:44:00 -0600
committerSimon Glass <sjg@chromium.org>2016-06-19 17:05:55 -0600
commit135aa95002646c46e89de93fa36adad1b010548f (patch)
treeb601e08f7d91c7e2cda127d59f8f81128d0cb1ac /include
parent4581b717b1bf0fb04e7d9fcaf3d4c23d357154ac (diff)
downloadtalos-obmc-uboot-135aa95002646c46e89de93fa36adad1b010548f.tar.gz
talos-obmc-uboot-135aa95002646c46e89de93fa36adad1b010548f.zip
clk: convert API to match reset/mailbox style
The following changes are made to the clock API: * The concept of "clocks" and "peripheral clocks" are unified; each clock provider now implements a single set of clocks. This provides a simpler conceptual interface to clients, and better aligns with device tree clock bindings. * Clocks are now identified with a single "struct clk", rather than requiring clients to store the clock provider device and clock identity values separately. For simple clock consumers, this isolates clients from internal details of the clock API. * clk.h is split so it only contains the client/consumer API, whereas clk-uclass.h contains the provider API. This aligns with the recently added reset and mailbox APIs. * clk_ops .of_xlate(), .request(), and .free() are added so providers can customize these operations if needed. This also aligns with the recently added reset and mailbox APIs. * clk_disable() is added. * All users of the current clock APIs are updated. * Sandbox clock tests are updated to exercise clock lookup via DT, and clock enable/disable. * rkclk_get_clk() is removed and replaced with standard APIs. Buildman shows no clock-related errors for any board for which buildman can download a toolchain. test/py passes for sandbox (which invokes the dm clk test amongst others). Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'include')
-rw-r--r--include/clk-uclass.h95
-rw-r--r--include/clk.h220
2 files changed, 226 insertions, 89 deletions
diff --git a/include/clk-uclass.h b/include/clk-uclass.h
new file mode 100644
index 0000000000..07c1065495
--- /dev/null
+++ b/include/clk-uclass.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _CLK_UCLASS_H
+#define _CLK_UCLASS_H
+
+/* See clk.h for background documentation. */
+
+#include <clk.h>
+#include <fdtdec.h>
+
+/**
+ * struct clk_ops - The functions that a clock driver must implement.
+ */
+struct clk_ops {
+ /**
+ * of_xlate - Translate a client's device-tree (OF) clock specifier.
+ *
+ * The clock core calls this function as the first step in implementing
+ * a client's clk_get_by_*() call.
+ *
+ * If this function pointer is set to NULL, the clock core will use a
+ * default implementation, which assumes #clock-cells = <1>, and that
+ * the DT cell contains a simple integer clock ID.
+ *
+ * At present, the clock API solely supports device-tree. If this
+ * changes, other xxx_xlate() functions may be added to support those
+ * other mechanisms.
+ *
+ * @clock: The clock struct to hold the translation result.
+ * @args: The clock specifier values from device tree.
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*of_xlate)(struct clk *clock,
+ struct fdtdec_phandle_args *args);
+ /**
+ * request - Request a translated clock.
+ *
+ * The clock core calls this function as the second step in
+ * implementing a client's clk_get_by_*() call, following a successful
+ * xxx_xlate() call, or as the only step in implementing a client's
+ * clk_request() call.
+ *
+ * @clock: The clock struct to request; this has been fille in by
+ * a previoux xxx_xlate() function call, or by the caller
+ * of clk_request().
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*request)(struct clk *clock);
+ /**
+ * free - Free a previously requested clock.
+ *
+ * This is the implementation of the client clk_free() API.
+ *
+ * @clock: The clock to free.
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*free)(struct clk *clock);
+ /**
+ * get_rate() - Get current clock rate.
+ *
+ * @clk: The clock to query.
+ * @return clock rate in Hz, or -ve error code
+ */
+ ulong (*get_rate)(struct clk *clk);
+ /**
+ * set_rate() - Set current clock rate.
+ *
+ * @clk: The clock to manipulate.
+ * @rate: New clock rate in Hz.
+ * @return new rate, or -ve error code.
+ */
+ ulong (*set_rate)(struct clk *clk, ulong rate);
+ /**
+ * enable() - Enable a clock.
+ *
+ * @clk: The clock to manipulate.
+ * @return zero on success, or -ve error code.
+ */
+ int (*enable)(struct clk *clk);
+ /**
+ * disable() - Disable a clock.
+ *
+ * @clk: The clock to manipulate.
+ * @return zero on success, or -ve error code.
+ */
+ int (*disable)(struct clk *clk);
+};
+
+#endif
diff --git a/include/clk.h b/include/clk.h
index ca20c3dd27..2f31cf70e3 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
+ * Copyright (c) 2016, NVIDIA CORPORATION.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -8,125 +9,166 @@
#ifndef _CLK_H_
#define _CLK_H_
-#include <errno.h>
#include <linux/types.h>
-struct udevice;
+/**
+ * A clock is a hardware signal that oscillates autonomously at a specific
+ * frequency and duty cycle. Most hardware modules require one or more clock
+ * signal to drive their operation. Clock signals are typically generated
+ * externally to the HW module consuming them, by an entity this API calls a
+ * clock provider. This API provides a standard means for drivers to enable and
+ * disable clocks, and to set the rate at which they oscillate.
+ *
+ * A driver that implements UCLASS_CLOCK is a clock provider. A provider will
+ * often implement multiple separate clocks, since the hardware it manages
+ * often has this capability. clock_uclass.h describes the interface which
+ * clock providers must implement.
+ *
+ * Clock consumers/clients are the HW modules driven by the clock signals. This
+ * header file describes the API used by drivers for those HW modules.
+ */
-int soc_clk_dump(void);
+struct udevice;
-struct clk_ops {
- /**
- * get_rate() - Get current clock rate
- *
- * @dev: Device to check (UCLASS_CLK)
- * @return clock rate in Hz, or -ve error code
- */
- ulong (*get_rate)(struct udevice *dev);
-
- /**
- * set_rate() - Set current clock rate
- *
- * @dev: Device to adjust
- * @rate: New clock rate in Hz
- * @return new rate, or -ve error code
- */
- ulong (*set_rate)(struct udevice *dev, ulong rate);
-
- /**
- * enable() - Enable the clock for a peripheral
- *
- * @dev: clock provider
- * @periph: Peripheral ID to enable
- * @return zero on success, or -ve error code
- */
- int (*enable)(struct udevice *dev, int periph);
-
- /**
- * get_periph_rate() - Get clock rate for a peripheral
- *
- * @dev: Device to check (UCLASS_CLK)
- * @periph: Peripheral ID to check
- * @return clock rate in Hz, or -ve error code
- */
- ulong (*get_periph_rate)(struct udevice *dev, int periph);
-
- /**
- * set_periph_rate() - Set current clock rate for a peripheral
- *
- * @dev: Device to update (UCLASS_CLK)
- * @periph: Peripheral ID to update
- * @return new clock rate in Hz, or -ve error code
+/**
+ * struct clk - A handle to (allowing control of) a single clock.
+ *
+ * Clients provide storage for clock handles. The content of the structure is
+ * managed solely by the clock API and clock drivers. A clock struct is
+ * initialized by "get"ing the clock struct. The clock struct is passed to all
+ * other clock APIs to identify which clock signal to operate upon.
+ *
+ * @dev: The device which implements the clock signal.
+ * @id: The clock signal ID within the provider.
+ *
+ * Currently, the clock API assumes that a single integer ID is enough to
+ * identify and configure any clock signal for any clock provider. If this
+ * assumption becomes invalid in the future, the struct could be expanded to
+ * either (a) add more fields to allow clock providers to store additional
+ * information, or (b) replace the id field with an opaque pointer, which the
+ * provider would dynamically allocated during its .of_xlate op, and process
+ * during is .request op. This may require the addition of an extra op to clean
+ * up the allocation.
+ */
+struct clk {
+ struct udevice *dev;
+ /*
+ * Written by of_xlate. We assume a single id is enough for now. In the
+ * future, we might add more fields here.
*/
- ulong (*set_periph_rate)(struct udevice *dev, int periph, ulong rate);
+ unsigned long id;
};
-#define clk_get_ops(dev) ((struct clk_ops *)(dev)->driver->ops)
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+/**
+ * clock_get_by_index - Get/request a clock by integer index.
+ *
+ * This looks up and requests a clock. The index is relative to the client
+ * device; each device is assumed to have n clocks associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device clock indices to provider clocks may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev: The client device.
+ * @index: The index of the clock to request, within the client's list of
+ * clocks.
+ * @clock A pointer to a clock struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int clk_get_by_index(struct udevice *dev, int index, struct clk *clk);
/**
- * clk_get_rate() - Get current clock rate
+ * clock_get_by_name - Get/request a clock by name.
*
- * @dev: Device to check (UCLASS_CLK)
- * @return clock rate in Hz, or -ve error code
+ * This looks up and requests a clock. The name is relative to the client
+ * device; each device is assumed to have n clocks associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device clock names to provider clocks may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev: The client device.
+ * @name: The name of the clock to request, within the client's list of
+ * clocks.
+ * @clock: A pointer to a clock struct to initialize.
+ * @return 0 if OK, or a negative error code.
*/
-ulong clk_get_rate(struct udevice *dev);
+int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
+#else
+static inline int clk_get_by_index(struct udevice *dev, int index,
+ struct clk *clk)
+{
+ return -ENOSYS;
+}
+
+static int clk_get_by_name(struct udevice *dev, const char *name,
+ struct clk *clk)
+{
+ return -ENOSYS;
+}
+#endif
/**
- * clk_set_rate() - Set current clock rate
+ * clk_request - Request a clock by provider-specific ID.
*
- * @dev: Device to adjust
- * @rate: New clock rate in Hz
- * @return new rate, or -ve error code
+ * This requests a clock using a provider-specific ID. Generally, this function
+ * should not be used, since clk_get_by_index/name() provide an interface that
+ * better separates clients from intimate knowledge of clock providers.
+ * However, this function may be useful in core SoC-specific code.
+ *
+ * @dev: The clock provider device.
+ * @clock: A pointer to a clock struct to initialize. The caller must
+ * have already initialized any field in this struct which the
+ * clock provider uses to identify the clock.
+ * @return 0 if OK, or a negative error code.
*/
-ulong clk_set_rate(struct udevice *dev, ulong rate);
+int clk_request(struct udevice *dev, struct clk *clk);
/**
- * clk_enable() - Enable the clock for a peripheral
+ * clock_free - Free a previously requested clock.
*
- * @dev: clock provider
- * @periph: Peripheral ID to enable
- * @return zero on success, or -ve error code
+ * @clock: A clock struct that was previously successfully requested by
+ * clk_request/get_by_*().
+ * @return 0 if OK, or a negative error code.
*/
-int clk_enable(struct udevice *dev, int periph);
+int clk_free(struct clk *clk);
/**
- * clk_get_periph_rate() - Get current clock rate for a peripheral
+ * clk_get_rate() - Get current clock rate.
*
- * @dev: Device to check (UCLASS_CLK)
- * @return clock rate in Hz, -ve error code
+ * @clk: A clock struct that was previously successfully requested by
+ * clk_request/get_by_*().
+ * @return clock rate in Hz, or -ve error code.
*/
-ulong clk_get_periph_rate(struct udevice *dev, int periph);
+ulong clk_get_rate(struct clk *clk);
/**
- * clk_set_periph_rate() - Set current clock rate for a peripheral
+ * clk_set_rate() - Set current clock rate.
*
- * @dev: Device to update (UCLASS_CLK)
- * @periph: Peripheral ID to update
- * @return new clock rate in Hz, or -ve error code
+ * @clk: A clock struct that was previously successfully requested by
+ * clk_request/get_by_*().
+ * @rate: New clock rate in Hz.
+ * @return new rate, or -ve error code.
*/
-ulong clk_set_periph_rate(struct udevice *dev, int periph, ulong rate);
+ulong clk_set_rate(struct clk *clk, ulong rate);
-#if CONFIG_IS_ENABLED(OF_CONTROL)
/**
- * clk_get_by_index() - look up a clock referenced by a device
+ * clk_enable() - Enable (turn on) a clock.
*
- * Parse a device's 'clocks' list, returning information on the indexed clock,
- * ensuring that it is activated.
+ * @clk: A clock struct that was previously successfully requested by
+ * clk_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int clk_enable(struct clk *clk);
+
+/**
+ * clk_disable() - Disable (turn off) a clock.
*
- * @dev: Device containing the clock reference
- * @index: Clock index to return (0 = first)
- * @clk_devp: Returns clock device
- * @return: Peripheral ID for the device to control. This is the first
- * argument after the clock node phandle. If there is no arguemnt,
- * returns 0. Return -ve error code on any error
+ * @clk: A clock struct that was previously successfully requested by
+ * clk_request/get_by_*().
+ * @return zero on success, or -ve error code.
*/
-int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp);
-#else
-static inline int clk_get_by_index(struct udevice *dev, int index,
- struct udevice **clk_devp)
-{
- return -ENOSYS;
-}
-#endif
+int clk_disable(struct clk *clk);
-#endif /* _CLK_H_ */
+int soc_clk_dump(void);
+
+#endif
OpenPOWER on IntegriCloud