Common clock framework: how to use it



Similar documents
MPLAB Harmony System Service Libraries Help

Linux Driver Devices. Why, When, Which, How?

Applying Clang Static Analyzer to Linux Kernel

An Implementation Of Multiprocessor Linux

Kernel Synchronization and Interrupt Handling

Freescale MQX USB Device User Guide

A Survey of Parallel Processing in Linux

Android Sensors This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. CC-BY Google

Embedded Programming in C/C++: Lesson-1: Programming Elements and Programming in C

Keil C51 Cross Compiler

There are various types of NAND Flash available. Bare NAND chips, SmartMediaCards, DiskOnChip.

Virtual Servers. Virtual machines. Virtualization. Design of IBM s VM. Virtual machine systems can give everyone the OS (and hardware) that they want.

Serial Communications

Agenda. Context. System Power Management Issues. Power Capping Overview. Power capping participants. Recommendations

Project No. 2: Process Scheduling in Linux Submission due: April 28, 2014, 11:59pm

Specialized Android APP Development Program with Java (SAADPJ) Duration 2 months

Computer Systems II. Unix system calls. fork( ) wait( ) exit( ) How To Create New Processes? Creating and Executing Processes

Update on big.little scheduling experiments. Morten Rasmussen Technology Researcher

The Linux Kernel Device Model

Linux Scheduler. Linux Scheduler

Application Note: AN00141 xcore-xa - Application Development

Inside Android's UI Embedded Linux Conference Europe 2012 Karim

Iotivity Programmer s Guide Soft Sensor Manager for Android

Embedded Linux Platform Developer

Application Note. Introduction AN2471/D 3/2003. PC Master Software Communication Protocol Specification

Using the VMRC Plug-In: Startup, Invoking Methods, and Shutdown on page 4

TivaWare Utilities Library

The Device Tree: Plug and play for Embedded Linux

Configuring CoreNet Platform Cache (CPC) as SRAM For Use by Linux Applications

Concrete uses of XML in software development and data analysis.

Extending the swsusp Hibernation Framework to ARM. Russell Dill

3.5. cmsg Developer s Guide. Data Acquisition Group JEFFERSON LAB. Version

DragonBoard 410c based on Qualcomm Snapdragon 410 processor Peripherals Programming Guide, Linux Android

Jorix kernel: real-time scheduling

Specific Simple Network Management Tools

Modular Real-Time Linux

Thomas Fahrig Senior Developer Hypervisor Team. Hypervisor Architecture Terminology Goals Basics Details

STUDY OF PERFORMANCE COUNTERS AND PROFILING TOOLS TO MONITOR PERFORMANCE OF APPLICATION

Android builders summit The Android media framework

International Engineering Journal For Research & Development

LLVMLinux: Embracing the Dragon

Going Linux on Massive Multicore

ODBC Client Driver Help Kepware, Inc.

Do More With Less. On Driver-less Interfacing with Embedded Devices. Peter Korsgaard

Embedded Linux development with Buildroot training 3-day session

Android Architecture For Beginners

Top 10 Bug-Killing Coding Standard Rules

Old Company Name in Catalogs and Other Documents

Operating System Manual. Realtime Communication System for netx. Kernel API Function Reference.

TI ARM Lab 7 Accelerometers

OpenAMP Framework for Zynq Devices

Memory Systems. Static Random Access Memory (SRAM) Cell

MatrixSSL Developer s Guide

Chapter 5 Linux Load Balancing Mechanisms

Intel Media Server Studio - Metrics Monitor (v1.1.0) Reference Manual

How to Run the MQX RTOS on Various RAM Memories for i.mx 6SoloX

Linux Kernel Networking. Raoul Rivas

Operating Systems 4 th Class

Hardware Prerequisites Atmel SAM W25 Xplained Pro Evaluation Kit Atmel IO1 extension Micro-USB Cable (Micro-A / Micro-B)

Application Note 120 Communicating Through the 1-Wire Master

Computer Organization and Components

Using IOMMUs for Virtualization in Linux

To Java SE 8, and Beyond (Plan B)

Decomposition into Parts. Software Engineering, Lecture 4. Data and Function Cohesion. Allocation of Functions and Data. Component Interfaces

Secure Boot on i.mx25, i.mx35, and i.mx51 using HABv3

Research and Design of Universal and Open Software Development Platform for Digital Home

Enterprise Backup and Restore technology and solutions

Internal LVDS Dynamic Backlight Brightness Control

Android on i.mx Applications Processors

Upgrading Intel AMT 5.0 drivers to Linux kernel v2.6.31

NIOS II Based Embedded Web Server Development for Networking Applications

Department of Electrical Engineering and Computer Science MASSACHUSETTS INSTITUTE OF TECHNOLOGY Operating System Engineering: Fall 2005

Università Degli Studi di Parma. Distributed Systems Group. Android Development. Lecture 1 Android SDK & Development Environment. Marco Picone

Technical Note. Micron NAND Flash Controller via Xilinx Spartan -3 FPGA. Overview. TN-29-06: NAND Flash Controller on Spartan-3 Overview

Oracle BI EE Implementation on Netezza. Prepared by SureShot Strategies, Inc.

Services. Relational. Databases & JDBC. Today. Relational. Databases SQL JDBC. Next Time. Services. Relational. Databases & JDBC. Today.

1 Abstract Data Types Information Hiding

RS-485 Protocol Manual

Linux scheduler history. We will be talking about the O(1) scheduler

A Programming Language for Processor Based Embedded Systems

Comparing Power Saving Techniques for Multi cores ARM Platforms

GDB Tutorial. A Walkthrough with Examples. CMSC Spring Last modified March 22, GDB Tutorial

Chapter 5 Real time clock by John Leung

EE8205: Embedded Computer System Electrical and Computer Engineering, Ryerson University. Multitasking ARM-Applications with uvision and RTX

USTC Course for students entering Clemson F2013 Equivalent Clemson Course Counts for Clemson MS Core Area. CPSC 822 Case Study in Operating Systems

Implementing Rexx Handlers in NetRexx/Java/Rexx

PAC52XX Clock Control Firmware Design

Real Time Programming: Concepts

Accessing I2C devices with Digi Embedded Linux 5.2 example on Digi Connect ME 9210

LINKED DATA STRUCTURES

A C Test: The 0x10 Best Questions for Would-be Embedded Programmers

KVM & Memory Management Updates

IOMMU: A Detailed view

AN1754 APPLICATION NOTE

Lecture 10: Multiple Clock Domains

Virtual Memory. How is it possible for each process to have contiguous addresses and so many of them? A System Using Virtual Addressing

Libmonitor: A Tool for First-Party Monitoring

Transcription:

Embedded Linux Conference 2013 Common clock framework: how to use it Gregory CLEMENT Free Electrons gregory.clement@free-electrons.com Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 1/40

Gregory CLEMENT Embedded Linux engineer and trainer at Free Electrons since 2010 Embedded Linux development: kernel and driver development, system integration, boot time and power consumption optimization, consulting, etc. Embedded Linux training, Linux driver development training and Android system development training, with materials freely available under a Creative Commons license. http://free-electrons.com Contributing the kernel support for the new Armada 370 and Armada XP ARM SoCs from Marvell. Co-maintainer of mvebu sub-architecture (SoCs from Marvell Embedded Business Unit) Living near Lyon, France Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 2/40

Overview What the common clock framework is Implementation of the common clock framework How to add your own clocks How to deal with the device tree Use of the clocks by device drivers Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 3/40

Clocks Most of the electronic chips are driven by clocks The clocks of the peripherals of an SoC (or even a board) are organized in a tree Controlling clocks is useful for: power management: clock frequency is a parameter of the dynamic power consumption time reference: to compute a baud-rate or a pixel clock for example Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 4/40

The clock framework A clock framework has been available for many years (it comes from the prehistory of git) Offers a a simple API: clk_get, clk_enable, clk_get_rate, clk_set_rate, clk_disable, clk_put,... that were used by device drivers. Nice but had several drawbacks and limitations: Each machine class had its own implementation of this API. Does not allow code sharing, and common mechanisms Does not work for ARM multiplatform kernels. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 5/40

The common clock framework Started by the introduction of a common struct clk in early 2010 by Jeremy Kerr Ended by the merge of the common clock framework in kernel 3.4 in May 2012, submitted by Mike Turquette Implements the clock framework API, some basic clock drivers and makes it possible to implement custom clock drivers Allows to declare the available clocks and their association to devices in the Device Tree (preferred) or statically in the source code (old method) Provides a debugfs representation of the clock tree Is implemented in drivers/clk Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 6/40

Diagram overview of the common clock framework Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 7/40

Interface of the CCF Interface divided into two halves: Common Clock Framework core Common definition of struct clk Common implementation of the clk.h API (defined in drivers/clk/clk.c) struct clk_ops: operations invoked by the clk API implementation Not supposed to be modified when adding a new driver Hardware-specific Callbacks registered with struct clk_ops and the corresponding hardware-specific structures (let s call it struct clk_foo for this talk) Has to be written for each new hardware clock The two halves are tied together by struct clk_hw, which is defined in struct clk_foo and pointed to within struct clk. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 8/40

Implementation of the CCF core Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 9/40

Implementation of the CCF core Implementation defined in drivers/clk/clk.c. Takes care of: Maintaining the clock tree Concurrency prevention (using a global spinlock for clk_enable()/clk_disable() and a global mutex for all other operations) Propagating the operations through the clock tree Notification when rate change occurs on a given clock, the register callback is called. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 10/40

Implementation of the CCF core Common struct clk definition located in include/linux/clk-private.h: struct clk { const char const struct clk_ops struct clk_hw char struct clk struct clk struct hlist_head struct hlist_node... }; *name; *ops; *hw; **parent_names; **parents; *parent; children; child_node; Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 11/40

Implementation of the CCF core The clk_set_rate() example: int clk_set_rate(struct clk *clk, unsigned long rate) { struct clk *top, *fail_clk; int ret = 0; /* prevent racing with updates to the clock topology */ mutex_lock(&prepare_lock); /* bail early if nothing to do */ if (rate == clk->rate) goto out; if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) { For this particular clock, setting its rate is possible only if the clock is ungated (not yet prepared) ret = -EBUSY; goto out; } /* calculate new rates and get the topmost changed clock */ top = clk_calc_new_rates(clk, rate); [...] Exit with error if clk_ calc_ new_ rates( ) failed Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 12/40

Implementation of the CCF core The clk_set_rate() example (continued): /* notify that we are about to change rates */ fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); if (fail_clk) { pr_warn("%s: failed to set %s rate\n", func, fail_clk->name); clk_propagate_rate_change(top, ABORT_RATE_CHANGE); ret = -EBUSY; goto out; } /* change the rates */ clk_change_rate(top); Actually set the rate using the hardware operation out: } mutex_unlock(&prepare_lock); return ret; Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 13/40

Implementation of the hardware clock Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 14/40

Implementation of the hardware clock Relies on.ops and.hw pointers Abstracts the details of struct clk from the hardware-specific bits No need to implement all the operations, only a few are mandatory depending on the clock type The clock is created once the operation set is registered using clk_register() Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 15/40

Implementation of the hardware clock Hardware operations defined in include/linux/clk-provider.h struct clk_ops { int void int void int unsigned long long int u8 int void }; (*prepare)(struct clk_hw *hw); (*unprepare)(struct clk_hw *hw); (*enable)(struct clk_hw *hw); (*disable)(struct clk_hw *hw); (*is_enabled)(struct clk_hw *hw); (*recalc_rate)(struct clk_hw *hw, unsigned long parent_rate); (*round_rate)(struct clk_hw *hw, unsigned long, unsigned long *); (*set_parent)(struct clk_hw *hw, u8 index); (*get_parent)(struct clk_hw *hw); (*set_rate)(struct clk_hw *hw, unsigned long); (*init)(struct clk_hw *hw); Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 16/40

Operations to implement depending on clk capabilities gate change rate single parent multiplexer root.prepare.unprepare.enable y.disable y.is enabled y.recalc rate y.round rate y.set rate y.set parent n y n.get parent n y n.init Legend: y = mandatory, n = invalid or otherwise unnecessary Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 17/40

Hardware clock operations: making clocks available The API is split in two pairs:.prepare(/.unprepare): Called to prepare the clock before actually ungating it Could be called in place of enable in some cases (accessed over I2C) May sleep Must not be called in atomic context.enable(/.disable): Called to ungate the clock once it has been prepared Could be called in place of prepare in some case (accessed over single register in an SoC) Must not sleep Can be called in atomic context.is_enabled: Instead of checking the enable count, querying the hardware to determine if the clock is enabled. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 18/40

Hardware clock operations: managing the rates.round_rate: Returns the closest rate actually supported by the clock. Called by clk_round_rate() or by clk_set_rate() during propagation..set_rate: Changes the rate of the clock. Called by clk_set_rate() or during propagation..recalc_rate: Recalculates the rate of this clock, by querying hardware supported by the clock. Used internally to update the clock tree. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 19/40

Hardware clock operations: managing the parents As seen on the matrix, only used for multiplexers.get_parent: Queries the hardware to determine the parent of a clock. Currently only used when clocks are statically initialized. clk_get_parent() doesn t use it, simply returns the clk->parent internal struct.set_parent: Changes the input source of this clock Receives a index on in either the.parent_names or.parents arrays clk_set_parent() translate clk in index Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 20/40

Hardware clock operations: base clocks The common clock framework provides 5 base clocks: fixed-rate: Is always running and provide always the same rate gate: Have the same rate as its parent and can only be gated or ungated mux: Allow to select a parent among several ones, get the rate from the selected parent, and can t gate or ungate fixed-factor: Divide and multiply the parent rate by constants, can t gate or ungate divider: Divide the parent rate, the divider can be selected among an array provided at registration, can t gate or ungate Most of the clocks can be registered using one of these base clocks. Complex hardware clocks have to be split in base clocks For example a gate clock with a fixed rate will be composed of a fixed rate clock as a parent of a gate clock. New clock type submitted recently: clk-composite. It will allow to aggregate the functionality of the basic clock types into one clock. Still under review. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 21/40

Hardware clock operations: static initialization Put in place to ease migration of the complex SoC to the common clock framework Platforms used to use hundreds clocks statically defined They had to include include/linux/clk-private.h and clk_init() to reuse these definitions. Still possible (but not recommended) to do static initialization Absolutely no new platform should include clk-private.h Clocks must be initialized via a call to clk_register() using clk_init_data objects which get bundled with clk_hw Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 22/40

Hardware clock operations: device tree Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 23/40

Hardware clock operations: device tree The device tree is the preferred way to declare a clock and to get its resources, as for any other driver using DT we have to: Parse the device tree to setup the clock: resources but also properties are retrieved. Create an array ofstruct of_device_id to match the compatible clocks Associate data and setup functions to each node Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 24/40

Declaration of clocks in DT: simple example (1) From arch/arm/boot/dts/ecx-common.dtsi [...] [...] osc: oscillator { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <33333000>; }; ddrpll: ddrpll { #clock-cells = <0>; compatible = "calxeda,hb-pll-clock"; clocks = <&osc>; reg = <0x108>; }; Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 25/40

Managing the device tree: simple example (1) From drivers/clk/clk-highbank.c static const initconst struct of_device_id clk_match[] = { {.compatible = "fixed-clock",.data = of_fixed_clk_setup, }, [...] }; void init highbank_clocks_init(void) { of_clk_init(clk_match); } From drivers/clk/clk.c void init of_clk_init(const struct of_device_id *matches) { struct device_node *np; for_each_matching_node(np, matches) { const struct of_device_id *match = of_match_node(matches, np); of_clk_init_cb_t clk_init_cb = match->data; clk_init_cb(np); } } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 26/40

Managing the device tree: simple example (2) From drivers/clk/clk-fixed-rate.c void init of_fixed_clk_setup(struct device_node *node) { struct clk *clk; const char *clk_name = node->name; u32 rate; if (of_property_read_u32(node, "clock-frequency", &rate)) return; of_property_read_string(node, "clock-output-names", &clk_name); } clk = clk_register_fixed_rate(null, clk_name, NULL, CLK_IS_ROOT, rate); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 27/40

Declaration of clocks in DT: advanced example (1) From arch/arm/boot/dts/armada-xp.dtsi [...] coreclk: mvebu-sar@d0018230 { compatible = "marvell,armada-xp-core-clock"; reg = <0xd0018230 0x08>; #clock-cells = <1>; }; cpuclk: clock-complex@d0018700 { #clock-cells = <1>; compatible = "marvell,armada-xp-cpu-clock"; reg = <0xd0018700 0xA0>; clocks = <&coreclk 1>; }; [...] Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 28/40

Managing the device tree: advanced example (1) From drivers/clk/mvebu/clk-core.c (some parts removed) static const struct core_clocks armada_370_core_clocks = {.get_tclk_freq = armada_370_get_tclk_freq,.num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios), }; static const initdata struct of_device_id clk_core_match[] = { [...] {.compatible = "marvell,armada-xp-core-clock",.data = &armada_xp_core_clocks, }, [...] }; void init mvebu_core_clk_init(void) { struct device_node *np; } for_each_matching_node(np, clk_core_match) { const struct of_device_id *match = of_match_node(clk_core_match, np); mvebu_clk_core_setup(np, (struct core_clocks *)match->data); } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 29/40

Managing the device tree: advanced example (2) From drivers/clk/mvebu/clk-core.c (some parts removed) static void init mvebu_clk_core_setup(struct device_node *np, struct core_clocks *coreclk) { const char *tclk_name = "tclk"; void iomem *base; [...] } base = of_iomap(np, 0); /* Allocate struct for TCLK, cpu clk, and core ratio clocks */ clk_data.clk_num = 2 + coreclk->num_ratios; clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *), GFP_KERNEL); /* Register TCLK */ of_property_read_string_index(np, "clock-output-names", 0, &tclk_name); rate = coreclk->get_tclk_freq(base); clk_data.clks[0] = clk_register_fixed_rate(null, tclk_name, NULL, CLK_IS_ROOT, rate); Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 30/40

Hardware clock operations: device tree Expose the clocks to other nodes of the device tree using of_clk_add_provider() which takes 3 parameters: struct device_node *np: Device node pointer associated to clock provider. This one is usually received by the setup function, when there is a match, with the array previously defined. struct clk *(*clk_src_get)(struct of_phandle_args *args, void *data): Callback for decoding clock. For the devices, called through clk_get() to return the clock associated to the node. void *data: context pointer for the callback, usually a pointer to the clock(s) to associate to the node. Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 31/40

Exposing the clocks on DT: Simple example From drivers/clk/clk.c struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data) { return data; } From drivers/clk/clk-fixed-rate.c void init of_fixed_clk_setup(struct device_node *node) { struct clk *clk; [...] clk = clk_register_fixed_rate(null, clk_name, NULL, CLK_IS_ROOT, rate); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 32/40

Exposing the clocks in DT: Advanced example (1) From include/linux/clk-provider.h struct clk_onecell_data { struct clk **clks; unsigned int clk_num; }; From drivers/clk/clk.c struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data) { struct clk_onecell_data *clk_data = data; unsigned int idx = clkspec->args[0]; if (idx >= clk_data->clk_num) { return ERR_PTR(-EINVAL); } return clk_data->clks[idx]; } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 33/40

Exposing the clocks in DT: Advanced example (2) From drivers/clk/mvebu/clk-core.c (some parts removed) static struct clk_onecell_data clk_data; static void init mvebu_clk_core_setup(struct device_node *np, struct core_clocks *coreclk) { clk_data.clk_num = 2 + coreclk->num_ratios; clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *), GFP_KERNEL); [...] for (n = 0; n < coreclk->num_ratios; n++) { [...] clk_data.clks[2+n] = clk_register_fixed_factor(null, rclk_name, cpuclk_name, 0, mult, div); }; [...] of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 34/40

How device drivers use the CCF Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 35/40

How device drivers use the CCF Use clk_get() to get the clock of the device Link between clock and device done either by platform data (old method) or by device tree (preferred method) Managed version: devm_get_clk() Activate the clock by clk_enable() and/or clk_prepare() (depending of the context), sufficient for most drivers. Manipulate the clock using the clock API Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 36/40

Devices referencing their clock in the Device Tree From arch/arm/boot/dts/armada-xp.dtsi ethernet@d0030000 { compatible = "marvell,armada-370-neta"; reg = <0xd0030000 0x2500>; interrupts = <12>; clocks = <&gateclk 2>; status = "disabled"; }; From arch/arm/boot/dts/highbank.dts watchdog@fff10620 { compatible = "arm,cortex-a9-twd-wdt"; reg = <0xfff10620 0x20>; interrupts = <1 14 0xf01>; clocks = <&a9periphclk>; }; Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 37/40

Example clock usage in a driver From drivers/net/ethernet/marvell/mvneta.c static void mvneta_rx_time_coal_set(struct mvneta_port *pp, struct mvneta_rx_queue *rxq, u32 value) { [...] clk_rate = clk_get_rate(pp->clk); val = (clk_rate / 1000000) * value; mvreg_write(pp, MVNETA_RXQ_TIME_COAL_REG(rxq->id), val); } static int mvneta_probe(struct platform_device *pdev) { [...] pp->clk = devm_clk_get(&pdev->dev, NULL); clk_prepare_enable(pp->clk); [...] } static int mvneta_remove(struct platform_device *pdev) { [...] clk_disable_unprepare(pp->clk); [...] } Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 38/40

Conclusion Efficient way to declare and use clocks: the amount of code to support new clocks is very reduced. Still quite recent: Complex SoCs still need to finish their migration Upcoming features: DVFS (Patch set from Mike Turquette adding new notifications and reentrancy) Composite clock (Patch set from Prashant Gaikwad) Improve debugfs output by adding JSON style (also from Prashant Gaikwad) Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 39/40

Questions? Gregory CLEMENT gregory.clement@free-electrons.com Thanks to Thomas Petazzoni,(Free Electrons, working with me on Marvell mainlining), Mike Turquette (Linaro, CCF maintainer) Slides under CC-BY-SA 3.0 http://free-electrons.com/pub/conferences/2013/elc/common-clockframework-how-to-use-it/ Free Electrons. Kernel, drivers and embedded Linux development, consulting, training and support. http://free-electrons.com 40/40