1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- /*
- * clkt_clksel.c - OMAP2/3/4 clksel clock functions
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *
- * clksel clocks are clocks that do not have a fixed parent, or that
- * can divide their parent's rate, or possibly both at the same time, based
- * on the contents of a hardware register bitfield.
- *
- * All of the various mux and divider settings can be encoded into
- * struct clksel* data structures, and then these can be autogenerated
- * from some hardware database for each new chip generation. This
- * should avoid the need to write, review, and validate a lot of new
- * clock code for each new chip, since it can be exported from the SoC
- * design flow. This is now done on OMAP4.
- *
- * The fusion of mux and divider clocks is a software creation. In
- * hardware reality, the multiplexer (parent selection) and the
- * divider exist separately. XXX At some point these clksel clocks
- * should be split into "divider" clocks and "mux" clocks to better
- * match the hardware.
- *
- * (The name "clksel" comes from the name of the corresponding
- * register field in the OMAP2/3 family of SoCs.)
- *
- * XXX Currently these clocks are only used in the OMAP2/3/4 code, but
- * many of the OMAP1 clocks should be convertible to use this
- * mechanism.
- */
- #undef DEBUG
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/clk-provider.h>
- #include <linux/io.h>
- #include <linux/bug.h>
- #include "clock.h"
- /* Private functions */
- /**
- * _get_clksel_by_parent() - return clksel struct for a given clk & parent
- * @clk: OMAP struct clk ptr to inspect
- * @src_clk: OMAP struct clk ptr of the parent clk to search for
- *
- * Scan the struct clksel array associated with the clock to find
- * the element associated with the supplied parent clock address.
- * Returns a pointer to the struct clksel on success or NULL on error.
- */
- static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
- struct clk *src_clk)
- {
- const struct clksel *clks;
- if (!src_clk)
- return NULL;
- for (clks = clk->clksel; clks->parent; clks++)
- if (clks->parent == src_clk)
- break; /* Found the requested parent */
- if (!clks->parent) {
- /* This indicates a data problem */
- WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
- __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
- return NULL;
- }
- return clks;
- }
- /**
- * _write_clksel_reg() - program a clock's clksel register in hardware
- * @clk: struct clk * to program
- * @v: clksel bitfield value to program (with LSB at bit 0)
- *
- * Shift the clksel register bitfield value @v to its appropriate
- * location in the clksel register and write it in. This function
- * will ensure that the write to the clksel_reg reaches its
- * destination before returning -- important since PRM and CM register
- * accesses can be quite slow compared to ARM cycles -- but does not
|