 Hi, I'm going to speak about the common clock framework and especially how to use it. So first, let's introduce myself. I'm Gregory Clements. I'm working at FreeElection when we do development on embedded Linux and we also give training on the same subject. I'm contributing to Kenneth's support to the new Armada 370 and Armada XP and Armsock from Marvel and I'm a commentator of the MDBU sub-architecture, MDBU stands for Marvel Embedded Business Unit and I'm living near Lyon in France. So what we are going to see is what the common clock framework is. So we are just focused on which on this tree rod. We are going to speak about the implementation of the common clock framework and see some examples of it. Then how to add your own clocks, how to deal with the device tree and finally a view of how the device uses the common clock framework. So clocks, most of the electronic chip are driven by clocks, so most of the time if you don't have a clock on a chip, it just don't work and usually the clocks of the peripherals of a sock or an album of a broad are organized in a tree. So why controlling a clock is useful is first for power management because the clock frequency is a parameter of the dynamic power consumption and it's also useful for time reference to compute both rate or pixel clock if you want to either you want to directly cut off the clock and so lower the just stop the power and dynamic power consumption or you just want to be able to set the rate or get the rate to do your computation. Then the framework, so the clock framework is available for many years when I do some research on it, my research ends it at 2.6.12 kernel because it came from the pre-story of the git. So it offers a simple API with clock get, clock enable and so on. It's very nice but it adds several drawbacks and the limitation. First each machine class has its own implementation of this API. So at the point there was more than 30 implementation of this clock framework. So it doesn't allow clock sharing. That means that the bug are duplicated or each mentor can add his own bug. And also it doesn't work for a multi-platform kernel because as you have a multiple definition of the same symbol you can't make cobitate to a different sock for the clock framework. So that's why we can with a common clock framework, it started now three years ago by the introduction of the common truth clock by Jeremy Kerr and it ended last year by the merge of the common clock framework as we know it in kernel 3.4 by Mike Chouquette. It implements the clock framework API. It provides some basic clocks driver and it also makes possible to implement your own custom clock driver. It allows also to declare the available clocks and the association using the device 3 so it's preferred way but you can also still use the source code directly. It's the whole method can be still used for legacy reason. It also provides a debug effect representation and it is now implements is a driver clock CLK directory rather than in the arch directory. So here the diagram of the common clock framework is the same as the one you will see in the Thomas presentation at the end of the day. So we have the clock framework which exposes the clock framework API and which is used by the device driver. This clock framework gets all the information, usually gets information about the different clock driver and their resource from the device 3. It also exposes the different clock to the device 3 and it will be used directly by the device driver and it uses the different clock driver to access to the hardware. So we have the five basic clock driver provided by the common clock framework and you can add your own clock driver for specific needs. The entire fast of the common clock framework is composed of two halves. First the core of the clock framework. Here you have the common definition of a strict CLK. You will find this declaration in CLK.h and it is defined in CLK.c. You have the clock's up struct which is where all the operations are described and usually you are not supposed to modify this part of the common clock framework if you just want to add your clock driver. Then you have the hardware specific part. So here there are the callbacks you register with the strict clubs. You will implement your specific part here and it will correspond to your own strict. So let's call it a clock foo. And this part has to be written for each new type of hardware clock. These two halves are t together by the strict clock hw which is defined in your own struct. Let's call it clock foo and it is pointing with the strict clock variable. So now we are going to see the implementation of the common clock framework core. So here mainly this part and the clock framework core will implement all this IPI. So it is taking care of maintaining the clock tree. That means it is mainly taking care of updating the parent of a clock, the children of a clock. If you add a parent in this part that will take care of it, it will take care of propagating the provision. So if you change the rate of a clock, it will take care of changing the rate of the children. If you disable a clock, if you take care of checking if you have to disable the children clock and so on. It will also take care of the concurrency prevention. So it will use global spin lock for clock disabled operation and for all other operation, it will use global new text. And finally it also provides notification on alert so you can, a driver can register a callback and being notified where for example the rate of the clock is changed. And so the main purpose for this is for the debate phase. So here a view of the true clock. So we have the name of the clock, the operation of the clock, a pointer to the clock address and then all of this is related to the clock tree. So the parent name, the pointer to the parents and the list of the children and so on. So we have parts within the clock itself and the operation and those are parts that will be used for the clock tree. So now let's see some code to understand how it works and to have an example of how it is implemented. So the best example I think is the clock set rate. So clock set rate is directly called by the driver. And when a driver calls the clock set rate, the common clock framework will first take care of the racing condition so it will use the global new text. Here it just checks that you have to change the rate or not. Here we have a special case. It's when you have an hardware clock, when you can't change the rate of this clock if it's running. So when you register your clock and you have a setting this flag, then you exit in error because you can't change the rate because the clock is running. If everything is okay, then you are trying to get the topmost change clock. That means that if you change the clock, then maybe depending of the dependency of the parent, the clock children, you have to change another clock. So mainly you are going to walk through the clock tree to find the topmost one. If everything is okay, then you start to notify all the clock trees that you are going to do the change itself. And if everything is okay here, then with this function you will actually change the rate of the clock itself using the clock hardware operation. And if it failed before exiting, you propagate the fact that there was a problem to keep some currency in the clock tree. And once everything is finished, you release the lock. So now we are going to see more in this part. We are going to see the implementation of the hardware clock itself. So it's really the parts that you are going to modify when you register your own clock. So it's mainly all this part. And you will have the choice either to implement your own clock or reuse the basic clock provided by the common clock framework. So it relies on ops and Azure pointer. So here the hardware part is this part of the clock structure, so it's the hardware part of the clock structure. Then you don't have to implement all the operation depending of the clock type you have. You can just implement some part of it. We are going to see just after. And once you have created the set of operation you need, you register it with clock register and then it will create your clock. So here's another view of all the clock operation you can do. And just here, depending of the clock capability you have, in this matrix you can see what you have to, what set of operation you have to implement. So in the case of gate clock, you just have to implement the enable, disable, and it is enable set of operation and all the other are not necessary for a clock that can change its rate. This time you have to implement this set of operation. And then if you have a clock with a signal parent set, then you don't have to implement this one. Same for a root clock, of course. And in the case of the multiplexer clock, then this time that makes sense to implement this one. Now we are going to see each one of this set of operation and see what we expect of them. So first, it's making the clock available. The API is split in two pairs. First is prepare and prepare. So it's, this one may slip and so it must not be called in an automatic context. You, it can be useful to use it. And for example, you can only control your clock through I2C, for example. So in this case, you might want to slip. And then you have the enable, disable. This one are really called to indicate the clock. This one can't slip and so it can be called in an atomic context. So most of the time, you can just implement one of these those. It will really depend of, of your hardware and of, if you need or if you want to be able to call it in atomic context. And you can also implement both. And so you can, as the name, prepare all the things before actually enable it. And the last one is enable. This one is to create, to create the hardware because usually once you just to, to see if a clock is enabled or not, you just have to see the flag. But this function is to go to see it directly in the hardware. The other set of creation is about managing the rate. So run rate returns the closest rate that your clock can actually support. So is it called directly by the API clock run rate? Or it also used when you do a clock set rate during the propagation of your new rate. This function is called by the core of the common clock framework. And set rate is actually change the rate. So it is obviously called when you do a clock set rate or also when there is a propagation of the rate on the clock tree. And finally, recalc rate. It is, this one is not, is never directly called by a device driver, but it is used internally when the core of the common clock framework wants to update the clock tree. Now when you have a multiplexer, in this case you want to deal with the parent of your clock. So get parent, in fact, is, will directly address the hardware to see, to find the parent. And it's only used when a clock are statically initialized. And clock get parent, don't use this one, but just reaching the clock parent internal strict. Clock set parent, this one is called when you do a clock set parent, and it will, how it works, the prototype of this function will receive an index of either the dot parent name or the dot parent's array. And in the clock set parent function which is implemented is a clock common framework. And in this function, you, the clock which is received as parameter will be translate is an index which can be used by the function set parent. Now we are going to see the five base clock which are provided by the clock framework. So the first one is a fixed rate, it's by definition is always running and always provide the same rate. Then you have the gate, the gate clock, it has the same rate as its parent and it can only be gate or un gate. The mix just allow to select the parent between an index of parent she received and as the other it get his rate from his parent. The fixed factor divide and multiply the parent rate by a constant and it can get or un gate. And the divider divide the parent's rate and it receive a parameter array of divider. So in fact, most of the clock you will find on the stock or on the board can be registered using one of these base clock or at least for more complex other clock. You just have to split it in base clock. So for example, if you have a clock, a gate clock, a simple gate clock, then you have to split it into clock, fixed rate clock which will be a parent of gate clock. So that means that even for pretty simple clock, now you're supposed to declare one, two or three clock and some of them are not real clock. That's why there was a new tip which has been submitted recently which is clock a composite and this new type will allow to aggregate the functionality of the basic clock tip but will present only one clock. It's still under review but it should be accepted soon. The last operation we can see is about static initialization. There's still a big paragraph of the documentation about it and you can still find some code about it. So it has been put in place to ease the migration of the component clocks to the common clock framework because when the common clock frameworks was merged in the kernel, there was already a lot of socks which used the clock framework API, not the common one. And so they already have 100 clock statically defined so this API was just as to make possible to reuse all this statically defined clock and directly convert them in the common clock framework. So for new driver, for new sock, you are not supposed to use the clock in it and not supposed to include a clock pre-rate but it's still possible, even it's not recommended, to use static initialization but in this case, you must use clock register and you just have to use clock in data object and bundle them in the clock hardware structure and register them directly. So we have seen the core of the common clock framework. We have seen the implementation of them and now we are going to see the device tree and the device tree will be used for two things. The first thing which is pretty common for most of the drivers is just to get the resources for the driver. So for each one of these clocks, we will get the resources and the parameter from the device tree but it will be also used to expose the clock and that will be used by the device driver. So first, the device tree is still the preferred way to declare the clock and to get its resources. Something with common from most of the device of the driver when you want to register your driver using the device tree, you part the device tree, you set up your clock driver getting the properties and the resources. So what you do, you create an array of Shrugged device ID to match the compatible clock your driver will take care of and then you associated data and set up functions with them. So here is an example. So in DTSI, we have the name of the clock, the compatible string, here is just a fixed clock so you just need the property clock frequency and it will set up this rate. So for another example is this clock, so as we have said, the clock are organized as tree so this one will use this clock as parent clock, so it is done by this, clocks equal and reference on this one and for CalXDA there is a special driver which has been defined and registered with this compatible name and for this one we need a special resource so this I thought it was an offset of the register for the CalXDA driver. So for the call, here we define device ID and the match so here is just an extract so fixed clock will be used and associated with the OF fixed clock set up so what we do is just to call OF clock in it with the matching here and what do OF clock in it, it will parse the device tree and as soon there is a match then it will get from this particular function it will get the function passed as data and call it and so how it is done here is a setup, here we just get the name, get the clock frequency set up and just set up the register, the clock so here even if we declare it as a special clock for CalXDA in fact it's just use one of the five basic clocks which is the fixed rate clock. A more complex example is for example for the CPU clock or the clock clock here we state that we have a clock cell of one that means that instead of declaring just one clock we declare array of clock so it's possible and that means for example that when you want to depend of one disk clock you specify the name of the node and a number which will indicate which one of the clock you want to pick up in this array so how it works as usual here we have but just for our own implementation we have our structure because we have a different function we are going to use here you have still the clock match but instead of passing function for the simple example here we pass our own structure here this clock in it as you see is very close to the OF clock in it so the same thing we pass the device tree and as soon as we have a match we get the data and this time we are going to call our function MVBU clock setup with the data we passed and in this function so we get the resource as usual but here we are going to create an array of clocks so that's why I just as an example but here there is more fact we have a loop when we register a lot of clock and then at the end we just register one clock at a time so the second part which is less usual with device tree and with driver is to expose the clock to the device tree because here we are just getting resource from the device tree but now what we want is that the other device driver are going to use our clock and so what we want to do is to teach the device tree how to get the clock from the information right in the device tree so this is done using OF TLK app provider so what we take three parameters the first one is just the node associated to our clock driver then the function which will be called from the device driver when the device driver will do a clock gate then at the point where the kernel we are going to call this callback and the purpose of this callback is to provide the clock associated to this driver and the data received by the callback most of the time is a pointer to the clock or the clock associated to this node so here an example so yes so this one is more or less the same that for the first simple example just to ring yes so here we have our clock here and it's referenced by this one and so yeah so what should we do we register our clock we have a pointer on this clock and then we add this on provider so the node it's the node we have when we register this clock and we pass a very simple function which this function will just return the data we register so it's very very simple when we have just one clock we just have these simple things but for more advanced the clock driver so when we when we want to deal with an array of driver of clock then we have for example here a small that small structure so it's just an array of clock and a pointer of clock and here just a number of clock you can use what you do when you what the function will do it will receive the data you have just registered and this time we are going to use this first parameter this first parameter will be used here what we want to get just the first argument to the first argument if we go back yes this one is here we have this first argument because we said here that the how clock will take one argument so with this number one whereas for the more simple one we have zero so that's why here yeah there is nothing and when we state that we have one the clock cell is one then we can have the one is this one and so we can get here so using this one is provided by the part of the kernel who deal with the device tree and so it can provide the number we just pass through the device tree and for this simple example once we have the index we can just reach on as a pointer to the clock register in this array and how we register it so it is a clock set up so what we do is we have a loop to register all the clock belonging to this driver and once we have registered of this clock we have put it in the array and you we provide this array and the function to extract them using with clock provider and then the last part is it's not really specific in fact to the common clock framework it's just the same that was used for the clock framework API but now we will have a full picture of the common clock framework so what we what what do you do in a driver you use clock gate to to get the clock for this device the link between the clock you need and your device is done by the device tree or it also can be done by the platform data even if the device tree is a preferred method we also have managed version they have them clock get clock so you just can do a devon clock get clock and you don't have to take care of releasing as a memory and so on once you have a reference on your clock you can activate it using a clock enable or clock prepare or both depending of the context and for most of the delivery is just enough you have enable your clock now it's it's run and so your drive your device can can run but if you need more you can just use the clock API so you can get set the rate change the parent and so on so few example for example for the nvita driver here we are going to use the get clock driver we are going to we say that we want the get clock with the index 2 of this array of clock so here and for a more simple example here we just say that we want this clock because the a9 of perif clock is a simple clock and so in the driver what we what we do in probe we get we do a devon clock gate so we get a reference on the clock and then we can call clock prepare enable so this one do the clock prepare in the clock enable in the same time so we are sure that you are calling everything but that need that means that if you do a prepare you can't use this function in an atomic context and in once you have finished with your device you can just do a clock disable and prepare and that's that's all and at the point if you need to have the rate of your clock you just have to do the clock get right with the pointer to your clock and then you can deal with your clock and do what you need to do with your clock so in conclusion the common clock framework is an efficient way to declare and use the clock is how month of clock of code to support is very reduced now that as most of the framework in the kernel you just have to focus on the implementation of what it is very specific to your hardware and all the common stuff is already there so as you have seen for a very simple clock you it's just a couple of lines if you have just a fixed clock you just have to say to call a clock at a fixed fixed clock and end that all and even for more complex one you can try to split in a simple clock and call all of them and soon with the composite clock you can just have one clock but be able to use the framework from the other it's still quite recent so that means that complex socks still need to finish immigration it's not not yet finished so that means that if you want to have some example from the kernel you must pay attention of if the clock are finished immigration of it's the old way they use it and the incoming feature are the debate face but said from my trick it which will be allowed to change the clock rate according to the voltage or change the voltage according to the clock rate it's for this is that he has to add a new notification and to be sure that frequency will be okay fresh yet also had so the company clock which will be helped to just have one single clock and be able to to use the clock operation already available and it's all he also improves the debug FS output because currently the debug FS is you have one directory for each clock so it's very convenient when you want to debug and when just to see some information but if you want to have a synthetic view of your clock it's maybe less use less useful so this new output will will use a gson style so in one single line you can be able to pass this data and do what you don't with it so thanks for your attention and if you have any question you can ask me and I will ask to a microcator answer it