Clock API

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_CLK is a clock provider. A provider will often implement multiple separate clocks, since the hardware it manages often has this capability. clk-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.

Client API

struct clk

A handle to (allowing control of) a single clock.

Definition

struct clk {
  struct udevice *dev;
  long long rate;
  u32 flags;
  int enable_count;
  unsigned long id;
  unsigned long data;
};

Members

dev

The device which implements the clock signal.

rate

The clock rate (in HZ).

flags

Flags used across common clock structure (e.g. CLK_) Clock IP blocks specific flags (i.e. mux, div, gate, etc) are defined in struct’s for those devices (e.g. struct clk_mux).

enable_count

The number of times this clock has been enabled.

id

The clock signal ID within the provider.

data

An optional data field for scenarios where a single integer ID is not sufficient. If used, it can be populated through an .of_xlate op and processed during the various clock ops.

Description

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.

Should additional information to identify and configure any clock signal for any provider be required 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_bulk

A handle to (allowing control of) a bulk of clocks.

Definition

struct clk_bulk {
  struct clk *clks;
  unsigned int count;
};

Members

clks

An array of clock handles.

count

The number of clock handles in the clks array.

Description

Clients provide storage for the clock bulk. The content of the structure is managed solely by the clock API. A clock bulk struct is initialized by “get”ing the clock bulk struct. The clock bulk struct is passed to all other bulk clock APIs to apply the API to all the clock in the bulk struct.

int clk_get_by_phandle(struct udevice *dev, const struct phandle_1_arg *cells, struct clk *clk)

Get a clock by its phandle information (of-platadata)

Parameters

struct udevice *dev

Device containing the phandle

const struct phandle_1_arg *cells

Phandle info

struct clk *clk

A pointer to a clock struct to initialise

Description

This function is used when of-platdata is enabled.

This looks up a clock using the phandle info. With dtoc, each phandle in the ‘clocks’ property is transformed into an idx representing the device. For example:

clocks = <&dpll_mpu_ck 23>;

might result in:

.clocks = {1, {23}},},

indicating that the clock is udevice idx 1 in dt-plat.c with an argument of 23. This function can return a valid clock given the above information. In this example it would return a clock containing the ‘dpll_mpu_ck’ device and the clock ID 23.

Return

0 if OK, or a negative error code.

int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)

Get/request a clock by integer index.

Parameters

struct udevice *dev

The client device.

int index

The index of the clock to request, within the client’s list of clocks.

struct clk *clk

A pointer to a clock struct to initialize.

Description

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.

Return

0 if OK, or a negative error code.

int clk_get_by_index_nodev(ofnode node, int index, struct clk *clk)

Get/request a clock by integer index without a device.

Parameters

ofnode node

The client ofnode.

int index

The index of the clock to request, within the client’s list of clocks.

struct clk *clk

A pointer to a clock struct to initialize.

Return

0 if OK, or a negative error code.

int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)

Get/request all clocks of a device.

Parameters

struct udevice *dev

The client device.

struct clk_bulk *bulk

A pointer to a clock bulk struct to initialize.

Description

This looks up and requests all clocks of the client device; each device is assumed to have n clocks associated with it somehow, and this function finds and requests all of them in a separate structure. The mapping of client device clock indices to provider clocks may be via device-tree properties, board-provided mapping tables, or some other mechanism.

Return

0 if OK, or a negative error code.

int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)

Get/request a clock by name.

Parameters

struct udevice *dev

The client device.

const char *name

The name of the clock to request, within the client’s list of clocks, or NULL to request the first clock in the list.

struct clk *clk

A pointer to a clock struct to initialize.

Description

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.

Return

0 if OK, or a negative error code.

int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk)

Get/request a clock by name without a device.

Parameters

ofnode node

The client ofnode.

const char *name

The name of the clock to request, within the client’s list of clocks, or NULL to request the first clock in the list.

struct clk *clk

A pointer to a clock struct to initialize.

Return

0 if OK, or a negative error code.

struct clk *devm_clk_get(struct udevice *dev, const char *id)

lookup and obtain a managed reference to a clock producer.

Parameters

struct udevice *dev

device for clock “consumer”

const char *id

clock consumer ID

Description

The implementation uses dev and id to determine the clock consumer, and thereby the clock producer. (IOW, id may be identical strings, but clk_get may return different clock producers depending on dev.)

Drivers must assume that the clock source is not enabled.

The clock will automatically be freed when the device is unbound from the bus.

Return

a struct clk corresponding to the clock producer, or valid IS_ERR() condition containing errno

struct clk *devm_clk_get_optional(struct udevice *dev, const char *id)

lookup and obtain a managed reference to an optional clock producer.

Parameters

struct udevice *dev

device for clock “consumer”

const char *id

clock consumer ID

Description

Behaves the same as devm_clk_get() except where there is no clock producer. In this case, instead of returning -ENOENT, the function returns NULL.

int clk_release_all(struct clk *clk, unsigned int count)

Disable (turn off)/Free an array of previously requested clocks.

Parameters

struct clk *clk

A clock struct array that was previously successfully requested by clk_request/get_by_*().

unsigned int count

Number of clock contained in the array

Description

For each clock contained in the clock array, this function will check if clock has been previously requested and then will disable and free it.

Return

zero on success, or -ve error code.

int clk_get_by_name_optional(struct udevice *dev, const char *name, struct clk *clk)

Get/request a optional clock by name.

Parameters

struct udevice *dev

The client device.

const char *name

The name of the clock to request, within the client’s list of clocks.

struct clk *clk

A pointer to a clock struct to initialize.

Description

Behaves the same as clk_get_by_name(), except when there is no clock provider. In the latter case, return 0.

Return

0 if OK, or a negative error code.

int clk_get_by_name_nodev_optional(ofnode node, const char *name, struct clk *clk)

Get/request an optinonal clock by name without a device.

Parameters

ofnode node

The client ofnode.

const char *name

The name of the clock to request, within the client’s list of clocks.

struct clk *clk

A pointer to a clock struct to initialize.

Description

Behaves the same as clk_get_by_name_nodev() except where there is no clock producer, in this case, skip the error number -ENODATA, and the function returns 0.

enum clk_defaults_stage

What stage clk_set_defaults() is called at

Constants

CLK_DEFAULTS_PRE

Called before probe. Setting of defaults for clocks owned by this clock driver will be defered until after probing.

CLK_DEFAULTS_POST

Called after probe. Only defaults for clocks owned by this clock driver will be set.

CLK_DEFAULTS_POST_FORCE

Called after probe, and always set defaults, even before relocation. Usually, defaults are not set pre-relocation to avoid setting them twice (when the device is probed again post-relocation). This may incur a performance cost as device tree properties must be parsed for a second time. However, when not using SPL, pre-relocation may be the only time we can set defaults for some clocks (such as those used for the RAM we will relocate into).

int clk_set_defaults(struct udevice *dev, enum clk_defaults_stage stage)

Process assigned-{clocks/clock-parents/clock-rates} properties to configure clocks

Parameters

struct udevice *dev

A device to process (the ofnode associated with this device will be processed).

enum clk_defaults_stage stage

The stage of the probing process this function is called during.

Return

zero on success, or -ve error code.

int clk_release_bulk(struct clk_bulk *bulk)

Disable (turn off)/Free an array of previously requested clocks in a clock bulk struct.

Parameters

struct clk_bulk *bulk

A clock bulk struct that was previously successfully requested by clk_get_bulk().

Description

For each clock contained in the clock bulk struct, this function will check if clock has been previously requested and then will disable and free it.

Return

zero on success, or -ve error code.

int clk_request(struct udevice *dev, struct clk *clk)

Request a clock by provider-specific ID.

Parameters

struct udevice *dev

The clock provider device.

struct clk *clk

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.

Description

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.

Return

0 if OK, or a negative error code.

ulong clk_get_rate(struct clk *clk)

Get current clock rate.

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

Return

clock rate in Hz on success, 0 for invalid clock, or -ve error code

for other errors.

struct clk *clk_get_parent(struct clk *clk)

Get current clock’s parent.

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

Return

pointer to parent’s struct clk, or error code passed as pointer

ulong clk_get_parent_rate(struct clk *clk)

Get parent of current clock rate.

Parameters

struct clk *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_round_rate(struct clk *clk, ulong rate)

Adjust a rate to the exact rate a clock can provide

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

ulong rate

desired clock rate in Hz.

Description

This answers the question “if I were to pass rate to clk_set_rate(), what clock rate would I end up with?” without changing the hardware in any way. In other words:

rate = clk_round_rate(clk, r);

and:

rate = clk_set_rate(clk, r);

are equivalent except the former does not modify the clock hardware in any way.

Return

rounded rate in Hz, or -ve error code.

ulong clk_set_rate(struct clk *clk, ulong rate)

Set current clock rate.

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

ulong rate

New clock rate in Hz.

Return

new rate, or -ve error code.

int clk_set_parent(struct clk *clk, struct clk *parent)

Set current clock parent.

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

struct clk *parent

A clock struct that was previously successfully requested by clk_request/get_by_*().

Return

new rate, or -ve error code.

int clk_enable(struct clk *clk)

Enable (turn on) a clock.

Parameters

struct clk *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_bulk(struct clk_bulk *bulk)

Enable (turn on) all clocks in a clock bulk struct.

Parameters

struct clk_bulk *bulk

A clock bulk struct that was previously successfully requested by clk_get_bulk().

Return

zero on success, or -ve error code.

int clk_disable(struct clk *clk)

Disable (turn off) a clock.

Parameters

struct clk *clk

A clock struct that was previously successfully requested by clk_request/get_by_*().

Return

zero on success, or -ve error code.

int clk_disable_bulk(struct clk_bulk *bulk)

Disable (turn off) all clocks in a clock bulk struct.

Parameters

struct clk_bulk *bulk

A clock bulk struct that was previously successfully requested by clk_get_bulk().

Return

zero on success, or -ve error code.

bool clk_is_match(const struct clk *p, const struct clk *q)

check if two clk’s point to the same hardware clock

Parameters

const struct clk *p

clk compared against q

const struct clk *q

clk compared against p

Return

true if the two struct clk pointers both point to the same hardware clock node, and false otherwise. Note that two NULL clks are treated as matching.

int clk_get_by_id(ulong id, struct clk **clkp)

Get the clock by its ID

Parameters

ulong id

The clock ID to search for

struct clk **clkp

A pointer to clock struct that has been found among added clocks to UCLASS_CLK

Return

zero on success, or -ENOENT on error

bool clk_dev_binded(struct clk *clk)

Check whether the clk has a device binded

Parameters

struct clk *clk

A pointer to the clk

Return

true on binded, or false on no

bool clk_valid(struct clk *clk)

check if clk is valid

Parameters

struct clk *clk

the clock to check

Return

true if valid, or false

Driver API

struct clk_ops

The functions that a clock driver must implement.

Definition

struct clk_ops {
  int (*of_xlate)(struct clk *clock, struct ofnode_phandle_args *args);
  int (*request)(struct clk *clock);
  ulong (*round_rate)(struct clk *clk, ulong rate);
  ulong (*get_rate)(struct clk *clk);
  ulong (*set_rate)(struct clk *clk, ulong rate);
  int (*set_parent)(struct clk *clk, struct clk *parent);
  int (*enable)(struct clk *clk);
  int (*disable)(struct clk *clk);
#if IS_ENABLED(CONFIG_CMD_CLK);
  void (*dump)(struct udevice *dev);
#endif;
};

Members

of_xlate

Translate a client’s device-tree (OF) clock specifier.

request

Request a translated clock.

round_rate

Adjust a rate to the exact rate a clock can provide.

get_rate

Get current clock rate.

set_rate

Set current clock rate.

set_parent

Set current clock parent

enable

Enable a clock.

disable

Disable a clock.

dump

Print clock information.

Description

The individual methods are described more fully below.

int of_xlate(struct clk *clock, struct ofnode_phandle_args *args)

Translate a client’s device-tree (OF) clock specifier.

Parameters

struct clk *clock

The clock struct to hold the translation result.

struct ofnode_phandle_args *args

The clock specifier values from device tree.

Description

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.

This function should be a simple translation of args into clock->id and (optionally) clock->data. All other processing, allocation, or error checking should take place in request().

At present, the clock API solely supports device-tree. If this changes, other xxx_xlate() functions may be added to support those other mechanisms.

Return

  • 0 on success

  • -EINVAL if args does not have the correct format. For example, it could have too many/few arguments.

  • -ENOENT if args has the correct format but cannot be translated. This can happen if translation involves a table lookup and args is not present.

int request(struct clk *clock)

Request a translated clock.

Parameters

struct clk *clock

The clock struct to request; this has been filled in by a previoux xxx_xlate() function call, or by the caller of clk_request().

Description

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.

This is the right place to do bounds checking (rejecting invalid or unimplemented clocks), allocate resources, or perform other setup not done during driver probe(). Most clock drivers should allocate resources in their probe() function, but it is possible to lazily initialize something here.

Return

  • 0 on success

  • -ENOENT, if there is no clock corresponding to clock->id and clock->data.

ulong round_rate(struct clk *clk, ulong rate)

Adjust a rate to the exact rate a clock can provide.

Parameters

struct clk *clk

The clock to query.

ulong rate

Desired clock rate in Hz.

Description

This function returns a new rate which can be provided to set_rate(). This new rate should be the closest rate to rate which can be set without rounding. The following pseudo-code should hold:

for all rate in range(ULONG_MAX):
  rounded = round_rate(clk, rate)
  new_rate = set_rate(clk, rate)
  assert(IS_ERR_VALUE(new_rate) || new_rate == rounded)

Return

  • The rounded rate in Hz on success

  • A negative error value from another API (such as clk_get_rate()). This function must not return an error for any other reason.

ulong get_rate(struct clk *clk)

Get current clock rate.

Parameters

struct clk *clk

The clock to query.

Description

This returns the current rate of a clock. If the clock is disabled, it returns the rate at which the clock would run if it was enabled. The following pseudo-code should hold:

disable(clk)
rate = get_rate(clk)
enable(clk)
assert(get_rate(clk) == rate)

Return

  • The rate of clk

  • -ENOSYS if this function is not implemented for clk

  • -ENOENT if clk->id is invalid. Prefer using an assert instead, and doing this check in request().

  • Another negative error value (such as EIO or ECOMM) if the rate could not be determined due to a bus error.

ulong set_rate(struct clk *clk, ulong rate)

Set current clock rate.

Parameters

struct clk *clk

The clock to manipulate.

ulong rate

New clock rate in Hz.

Description

Set the rate of clk to rate. The actual rate may be rounded. However, excessive rounding should be avoided. It is left to the driver author’s discretion when this function should attempt to round and when it should return an error. For example, a dividing clock might use the following pseudo-logic when implemening this function:

divisor = parent_rate / rate
if divisor < min || divisor > max:
  return -EINVAL

If there is any concern about rounding, prefer to let consumers make the decision by calling round_rate().

Return

  • The new rate on success

  • -ENOSYS if this function is not implemented for clk

  • -ENOENT if clk->id is invalid. Prefer using an assert instead, and doing this check in request().

  • -EINVAL if rate is not valid for clk.

  • Another negative error value (such as EIO or ECOMM) if the rate could not be set due to a bus error.

int set_parent(struct clk *clk, struct clk *parent)

Set current clock parent

Parameters

struct clk *clk

The clock to manipulate.

struct clk *parent

New clock parent.

Description

Set the current parent of clk to parent. The rate of the clock may be modified by this call. If clk was enabled before this function, it should remain enabled after this function, although it may be temporarily disabled if necessary.

Return

  • 0 on success

  • -ENOSYS if this function is not implemented for clk

  • -ENOENT if clk->id or parent->id is invalid. Prefer using an assert instead, and doing this check in request().

  • -EINVAL if parent is not a valid parent for clk.

  • Another negative error value (such as EIO or ECOMM) if the parent could not be set due to a bus error.

int enable(struct clk *clk)

Enable a clock.

Parameters

struct clk *clk

The clock to manipulate.

Description

Enable (un-gate) the clock. This function should not modify the rate of the clock (see get_rate() for details).

Return

  • 0 on success

  • -ENOSYS if this function is not implemented for clk

  • -ENOENT if clk->id is invalid. Prefer using an assert instead, and doing this check in request().

  • Another negative error value (such as EIO or ECOMM) if the clock could not be enabled due to a bus error.

int disable(struct clk *clk)

Disable a clock.

Parameters

struct clk *clk

The clock to manipulate.

Description

Disable (gate) the clock. This function should not modify the rate of the clock (see get_rate() for details).

  • 0 on success

  • -ENOSYS if this function is not implemented for clk

  • -ENOENT if clk->id is invalid. Prefer using an assert instead, and doing this check in request().

  • Another negative error value (such as EIO or ECOMM) if the clock could not be disabled due to a bus error.

void dump(struct udevice *dev)

Print clock information.

Parameters

struct udevice *dev

The clock device to dump.

Description

If present, this function is called by “clk dump” command for each bound device.