Skip to contentSkip to conversation

Convert i.MX architecture to generic clock framework

PATCH New Sascha Hauer 13 participants 101 messages Apr 10, 2012 – Apr 24, 2012

Subsystems (20)
lore
Share & tools
lore

Sascha Hauer

author maintainer
#0 lore raw

Hi All,

The following series is the first series converting the complete i.MX architecture to the generic clock framework. I am currently waiting for Mike posting his cleanup series to the clock framework which will cause some adjustments to this series. However, this series will only need some changes to the interface between i.MX and the clock framework. The association between the devices and the clocks (clk_lookup) and also the clocks themselves will stay unchanged. Due to the huge amount of changes there *will* be regressions, so now is the time to check if this works with your favourite devices and boards. I'll happily integrate fixup patches into this series.

As mentioned before my plan is to put this into the arm-soc staging area soon (hopefully when Mikes series is posted and acked)

Thanks to Shawn for porting over the i.MX6.

Sascha

The following changes since commit b41c67c587c98eb2efb2a79d4b8122b04b519d4a:

clkdev: Implement managed clk_get() (2012-04-10 09:35:09 +0200)

are available in the git repository at:

git://git.pengutronix.de/git/imx/linux-2.6.git work/v3.4-rc2-imx-clk

for you to fetch changes up to 3134a067ba4a66921acc8461165634abbae42e22:

ARM i.MX: Remove now unused struct clk argument from mxc_timer_init (2012-04-10 09:35:54 +0200)

----------------------------------------------------------------
Sascha Hauer (35):
clkdev: add clkname to struct clk_lookup
clk: add a fixed factor clock
dmaengine i.MX SDMA: do not depend on grouped clocks spi i.MX: do not depend on grouped clocks
video imxfb: do not depend on grouped clocks
net fec: do not depend on grouped clocks
mmc mxcmmc: do not depend on grouped clocks
mmc sdhc i.MX: do not depend on grouped clocks
serial i.MX: do not depend on grouped clocks
mtd mxc_nand: prepare/unprepare clock
USB ehci mxc: prepare/unprepare clock
w1 i.MX: prepare/unprepare clock
watchdog imx2: prepare clk before enabling it
media mx3 camera: prepare clk before enabling it dmaengine i.MX ipu: clk_prepare/unprepare clock
ARM i.MX5: prepare gpc_dvfs_clk
ARM i.MX: prepare for common clock framework
ARM i.MX timer: request correct clock
ARM i.MX: Add common clock support for pllv1
ARM i.MX: Add common clock support for pllv2
ARM i.MX: Add common clock support for 2bit gate
ARM i.MX3: Make ccm base address a variable
ARM i.MX25: implement clocks using common clock framework ARM i.MX1: implement clocks using common clock framework ARM i.MX21: implement clocks using common clock framework ARM i.MX27: implement clocks using common clock framework ARM i.MX31: implement clocks using common clock framework ARM i.MX5: implement clocks using common clock framework ARM i.MX35: implement clocks using common clock framework ARM i.MX: remove now unused old clock support
ARM i.MX pllv1: move mxc_decode_pll to its only user ARM i.MX: remove unused legacy clock support
USB gadget i.MX: fix clock handling
USB ehci i.MX: Fix clock handling
ARM i.MX: Remove now unused struct clk argument from mxc_timer_init

Shawn Guo (5):
clk: declare clk_ops of basic clks in clk-provider.h
ARM: imx: add common clock support for pllv3
ARM: imx: add common clock support for pfd
ARM: imx: add common clock support for clk busy
ARM: imx6: implement clocks using common clock framework

 arch/arm/mach-imx/Kconfig               |    8 +
 arch/arm/mach-imx/Makefile              |   19 +-
 arch/arm/mach-imx/clk-busy.c            |  167 +++
 arch/arm/mach-imx/clk-gate2.c           |  125 ++
 arch/arm/mach-imx/clk-imx1.c            |  108 ++
 arch/arm/mach-imx/clk-imx21.c           |  173 +++
 arch/arm/mach-imx/clk-imx25.c           |  232 ++++
 arch/arm/mach-imx/clk-imx27.c           |  254 ++++
 arch/arm/mach-imx/clk-imx31.c           |  167 +++
 arch/arm/mach-imx/clk-imx35.c           |  258 ++++
 arch/arm/mach-imx/clk-imx51-imx53.c     |  412 ++++++
 arch/arm/mach-imx/clk-imx6q.c           |  407 ++++++
 arch/arm/mach-imx/clk-pfd.c             |  138 ++
 arch/arm/mach-imx/clk-pllv1.c           |  104 ++
 arch/arm/mach-imx/clk-pllv2.c           |  243 ++++
 arch/arm/mach-imx/clk-pllv3.c           |  408 ++++++
 arch/arm/mach-imx/clk.h                 |   83 ++
 arch/arm/mach-imx/clock-imx1.c          |  636 ----------
 arch/arm/mach-imx/clock-imx21.c         | 1239 ------------------
 arch/arm/mach-imx/clock-imx25.c         |  346 -----
 arch/arm/mach-imx/clock-imx27.c         |  785 ------------
 arch/arm/mach-imx/clock-imx31.c         |  630 ---------
 arch/arm/mach-imx/clock-imx35.c         |  536 --------
 arch/arm/mach-imx/clock-imx6q.c         | 2111 -------------------------------
 arch/arm/mach-imx/clock-mx51-mx53.c     | 1675 ------------------------
 arch/arm/mach-imx/crmregs-imx3.h        |   79 +-
 arch/arm/mach-imx/mm-imx3.c             |    6 +
 arch/arm/mach-imx/mm-imx5.c             |    1 +
 arch/arm/mach-imx/pm-imx3.c             |    4 +-
 arch/arm/plat-mxc/clock.c               |  228 +---
 arch/arm/plat-mxc/include/mach/clock.h  |   43 +-
 arch/arm/plat-mxc/include/mach/common.h |    2 +-
 arch/arm/plat-mxc/time.c                |   16 +-
 drivers/clk/Makefile                    |    2 +-
 drivers/clk/clk-fixed-factor.c          |   97 ++
 drivers/clk/clkdev.c                    |    8 +
 drivers/dma/imx-sdma.c                  |   40 +-
 drivers/dma/ipu/ipu_idmac.c             |    6 +-
 drivers/media/video/mx3_camera.c        |    4 +-
 drivers/mmc/host/mxcmmc.c               |   39 +-
 drivers/mmc/host/sdhci-esdhc-imx.c      |   42 +-
 drivers/mtd/nand/mxc_nand.c             |    6 +-
 drivers/net/ethernet/freescale/fec.c    |   35 +-
 drivers/spi/spi-imx.c                   |   30 +-
 drivers/tty/serial/imx.c                |   38 +-
 drivers/usb/gadget/fsl_mxc_udc.c        |   74 +-
 drivers/usb/host/ehci-mxc.c             |   58 +-
 drivers/video/imxfb.c                   |   50 +-
 drivers/w1/masters/mxc_w1.c             |    4 +-
 drivers/watchdog/imx2_wdt.c             |    2 +-
 include/linux/clk-private.h             |    8 -
 include/linux/clk-provider.h            |   12 +
 include/linux/clkdev.h                  |    3 +
 53 files changed, 3736 insertions(+), 8465 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-busy.c
 create mode 100644 arch/arm/mach-imx/clk-gate2.c
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
 create mode 100644 arch/arm/mach-imx/clk-imx21.c
 create mode 100644 arch/arm/mach-imx/clk-imx25.c
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
 create mode 100644 arch/arm/mach-imx/clk-imx31.c
 create mode 100644 arch/arm/mach-imx/clk-imx35.c
 create mode 100644 arch/arm/mach-imx/clk-imx51-imx53.c
 create mode 100644 arch/arm/mach-imx/clk-imx6q.c
 create mode 100644 arch/arm/mach-imx/clk-pfd.c
 create mode 100644 arch/arm/mach-imx/clk-pllv1.c
 create mode 100644 arch/arm/mach-imx/clk-pllv2.c
 create mode 100644 arch/arm/mach-imx/clk-pllv3.c
 create mode 100644 arch/arm/mach-imx/clk.h
 delete mode 100644 arch/arm/mach-imx/clock-imx1.c
 delete mode 100644 arch/arm/mach-imx/clock-imx21.c
 delete mode 100644 arch/arm/mach-imx/clock-imx25.c
 delete mode 100644 arch/arm/mach-imx/clock-imx27.c
 delete mode 100644 arch/arm/mach-imx/clock-imx31.c
 delete mode 100644 arch/arm/mach-imx/clock-imx35.c
 delete mode 100644 arch/arm/mach-imx/clock-imx6q.c
 delete mode 100644 arch/arm/mach-imx/clock-mx51-mx53.c
 create mode 100644 drivers/clk/clk-fixed-factor.c
author maintainer
#1 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

With the generic clock framework we do not necessarily have a pointer to the struct clk we want to register a lookup for, so add a const char *clkname field to struct clk_lookup so that a lookup can be registered with a clock name.

---
 drivers/clk/clkdev.c   |    8 ++++++++
 include/linux/clkdev.h |    3 +++
 2 files changed, 11 insertions(+)
drivers/clk/clkdev.c +8 -0
index a9a1137..535d3d7 100644
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
@@ -67,6 +68,13 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 
 	mutex_lock(&clocks_mutex);
 	cl = clk_find(dev_id, con_id);
+#ifdef CONFIG_COMMON_CLK
+	if (cl && cl->clkname && !cl->clk) {
+		cl->clk = __clk_lookup(cl->clkname);
+		if (!cl->clk)
+			return ERR_PTR(-ENOENT);
+	}
+#endif
 	if (cl && !__clk_get(cl->clk))
 		cl = NULL;
 	mutex_unlock(&clocks_mutex);
include/linux/clkdev.h +3 -0
index d9a4fd0..2f589ff 100644
@@ -21,6 +21,9 @@ struct clk_lookup {
 	struct list_head	node;
 	const char		*dev_id;
 	const char		*con_id;
+#ifdef CONFIG_COMMON_CLK
+	const char		*clkname;
+#endif
 	struct clk		*clk;
 };
 
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 4 lines · Sascha Hauer

With the generic clock framework we do not necessarily have a pointer to the struct clk we want to register a lookup for, so add a const char *clkname field to struct clk_lookup so that a lookup can be registered with a clock name.

All this silly names all over the place is getting to be utterly rediculous. Why do we need to name clocks and look them up by name when we have a perfectly good way (clkdev) to do this already? Yes, it takes a struct clk pointer but that's exactly because that's what it has to return.

Why do we want to have another idiotic string to look up a clock which is named using an idiotic scheme to find out its pointer to only then register that with clkdev?

I think this clk stuff has gone totally insane wrt names recently.

author maintainer
#3 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 12 lines · Russell King - ARM Linux
Quoted 4 lines · Sascha Hauer

With the generic clock framework we do not necessarily have a pointer to the struct clk we want to register a lookup for, so add a const char *clkname field to struct clk_lookup so that a lookup can be registered with a clock name.

All this silly names all over the place is getting to be utterly rediculous. Why do we need to name clocks and look them up by name when we have a perfectly good way (clkdev) to do this already? Yes, it takes a struct clk pointer but that's exactly because that's what it has to return.

Quoted 5 lines

Why do we want to have another idiotic string to look up a clock which is named using an idiotic scheme to find out its pointer to only then register that with clkdev?

I think this clk stuff has gone totally insane wrt names recently.

clk names and clk lookups are two different things. The former is a unique identifier for a clock whereas the latter associates a clock to a device. Multiple lookups can point to the same clock, so they can't be used to identify a particular clock. I know I'm not telling anything new to you here, so I think your question goes down to why we need a unique identifier string for clocks.

For me the big advantage for clocks having unique names is that I do not have to have a struct clk * to pass the (possible) parents of a clock to the clock framework during registration. Also it makes us independent of the registration order of the clock tree (no need to register the parents before the children). The debugfs representation of the clock tree also makes use of the names.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#4 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 26 lines · Sascha Hauer
Quoted 12 lines · Russell King - ARM Linux
Quoted 4 lines · Sascha Hauer

With the generic clock framework we do not necessarily have a pointer to the struct clk we want to register a lookup for, so add a const char *clkname field to struct clk_lookup so that a lookup can be registered with a clock name.

All this silly names all over the place is getting to be utterly rediculous. Why do we need to name clocks and look them up by name when we have a perfectly good way (clkdev) to do this already? Yes, it takes a struct clk pointer but that's exactly because that's what it has to return.

Quoted 5 lines

Why do we want to have another idiotic string to look up a clock which is named using an idiotic scheme to find out its pointer to only then register that with clkdev?

I think this clk stuff has gone totally insane wrt names recently.

clk names and clk lookups are two different things. The former is a unique identifier for a clock whereas the latter associates a clock to a device. Multiple lookups can point to the same clock, so they can't be used to identify a particular clock. I know I'm not telling anything new to you here, so I think your question goes down to why we need a unique identifier string for clocks.

Quoted 6 lines

For me the big advantage for clocks having unique names is that I do not have to have a struct clk * to pass the (possible) parents of a clock to the clock framework during registration. Also it makes us independent of the registration order of the clock tree (no need to register the parents before the children). The debugfs representation of the clock tree also makes use of the names.

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

BRs
Richard

#5 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 2 lines · Richard Zhao

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

#6 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 9 lines · Mark Brown
Quoted 2 lines · Richard Zhao

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

My point is using string lookup as less as possible. When one register a clk, one already got the struct clk* pointer and could use it in struct lookup.

I'm worried about the performance as I saw string lookup is used more and more often. In fast boot case, for example, even 5ms is important.

Thanks
Richard

#7 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 8 lines · Richard Zhao
Quoted 4 lines · Mark Brown

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

My point is using string lookup as less as possible. When one register

That's not really relevant to what I'm saying here - I'm not commenting on your goal, I'm commenting on the solution. Obviously we want to be able to use things with DT but if we rely on it then we still need to solve the same problem for non-DT platforms.

Quoted 2 lines

a clk, one already got the struct clk* pointer and could use it in struct lookup.

How will you handle cases where one clock supplies another?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120411/3a29c1c3/attachment.sig>

#8 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 5 lines · Mark Brown
Quoted 2 lines · Richard Zhao

a clk, one already got the struct clk* pointer and could use it in struct lookup.

How will you handle cases where one clock supplies another?

What has that got to do with clkdev (which is the topic in this thread)?

#9 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 8 lines · Russell King - ARM Linux
Quoted 5 lines · Mark Brown
Quoted 2 lines · Richard Zhao

a clk, one already got the struct clk* pointer and could use it in struct lookup.

How will you handle cases where one clock supplies another?

What has that got to do with clkdev (which is the topic in this thread)?

I'm expecting (well, hoping) that at some point we'll want to connect
clock trees between devices and it seems likely that clkdev will be
pressed into service for that since it's how we're binding clocks at the
minute. It may be that we come up with some other scheme for making
those connections but as we appear to be defining a new scheme for
binding clocks together anyway it seems sensible that we should at least
be considering that case.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120411/bf7b8f1a/attachment-0001.sig>

#10 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 10 lines · Mark Brown
Quoted 8 lines · Russell King - ARM Linux
Quoted 5 lines · Mark Brown
Quoted 2 lines · Richard Zhao

a clk, one already got the struct clk* pointer and could use it in struct lookup.

How will you handle cases where one clock supplies another?

What has that got to do with clkdev (which is the topic in this thread)?

Quoted 7 lines

I'm expecting (well, hoping) that at some point we'll want to connect clock trees between devices and it seems likely that clkdev will be pressed into service for that since it's how we're binding clocks at the minute. It may be that we come up with some other scheme for making those connections but as we appear to be defining a new scheme for binding clocks together anyway it seems sensible that we should at least be considering that case.

clkdev is just a mechanism to obtain a struct clk for a particular input on a particular device. Nothing more, nothing less. So how does this detail about how the struct clk ultimate gets used concern clkdev?

#11 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 3 lines · Russell King - ARM Linux

clkdev is just a mechanism to obtain a struct clk for a particular input on a particular device. Nothing more, nothing less. So how does this detail about how the struct clk ultimate gets used concern clkdev?

It shouldn't.

The main point I'm trying to make is that if we're adding an alternative mechanism to the direct pointers for specifying the bindings to clkdev (which is broadly the point of the original patch, AFAICT based on a desire to split the mapping out from the definitions) then having it rely on device tree in the first instance means we'll just need to solve the same problem again for non-DT systems. Richard was saying that the problem Sascha was trying to solve is irrelevant because we can rely on device tree but device tree is not widely available enough for that.

The bit about clock to clock mappings was mostly an aside since it seems
like it's roughly the same as what Sascha was trying to do and if we're
going to add something new it'd be better if it handled that case also;
that said re-reading Richard's message I'm not sure if this is actually
a suggestion of a new mechanism.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120411/eb2f1efe/attachment.sig>

#12 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 7 lines · Mark Brown
Quoted 3 lines · Russell King - ARM Linux

clkdev is just a mechanism to obtain a struct clk for a particular input on a particular device. Nothing more, nothing less. So how does this detail about how the struct clk ultimate gets used concern clkdev?

It shouldn't.

Quoted 8 lines

The main point I'm trying to make is that if we're adding an alternative mechanism to the direct pointers for specifying the bindings to clkdev (which is broadly the point of the original patch, AFAICT based on a desire to split the mapping out from the definitions) then having it rely on device tree in the first instance means we'll just need to solve the same problem again for non-DT systems. Richard was saying that the problem Sascha was trying to solve is irrelevant because we can rely on device tree but device tree is not widely available enough for that.

Err what? Look, it's very very simple.

clkdev is all about translating a device + connection ID to a struct clk pointer. That's all, nothing more, nothing less.

What I see going on is that people want to translate a device + connection ID to some other name, and use this other name to look up a struct clk. Utterly idiotic and pointless. Whether it be OF or not OF.

It's a crazy absurd idea. At some point, you have to do some kind of lookup and return a struct clk. Why the hell have this insane double mapping?

Look, solving the DT problem with clkdev is really simple. You have the DT node for the struct device, so you can look up DT properties associated with that device. Properties have a name, and you can use the connection ID to translate into a DT property name to be looked up - eg, clk_%s. This can return a phandle or whatever else which could then be translated into a struct clk if you're representing each clk as a node in DT.

Nice and simple, no need for any additional crappy translation what so ever - and, oh my god, it reduces the amount of list based searching required to do the translation.

And it also allows non-DT to work just fine provided you register your clk lookups _after_ you know the struct clk pointers which is exactly what happens today.

Now, if getting the struct clk pointers is insanely difficult because of the design of the common clk stuff, then that's where the problem lies, and that problem needs to be fixed, and clkdev does not need to be bodged around to fix a problem which is not relevant to it.

#13 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 7 lines · Russell King - ARM Linux

What I see going on is that people want to translate a device + connection ID to some other name, and use this other name to look up a struct clk. Utterly idiotic and pointless. Whether it be OF or not OF.

It's a crazy absurd idea. At some point, you have to do some kind of lookup and return a struct clk. Why the hell have this insane double mapping?

I agree, that is silly. I had understood from Sascha's comments that the use case was building up the SoC clock tree with some indirect references. I can understand someone wanting to do that for a use case like grafting chunks of tree built up of static data together, it might be a bit more nicely data driven.

Quoted 2 lines

Look, solving the DT problem with clkdev is really simple. You have the DT node for the struct device, so you can look up DT properties associated

Yes, DT is completely straightforward here.

Quoted 8 lines

And it also allows non-DT to work just fine provided you register your clk lookups _after_ you know the struct clk pointers which is exactly what happens today.

Now, if getting the struct clk pointers is insanely difficult because of the design of the common clk stuff, then that's where the problem lies, and that problem needs to be fixed, and clkdev does not need to be bodged around to fix a problem which is not relevant to it.

I don't think it's anything particularly to do with the common clk stuff
really (at least I share your opinion that it shouldn't be) but it does
seem like it might be a real pain once we start deploying clock trees
that go off SoC.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120412/6f2bafb0/attachment.sig>

#14 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

In reply to Richard Zhao
Quoted 10 lines · Richard Zhao
Quoted 9 lines · Mark Brown
Quoted 2 lines · Richard Zhao

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

Quoted 6 lines

My point is using string lookup as less as possible. When one register a clk, one already got the struct clk* pointer and could use it in struct lookup.

I'm worried about the performance as I saw string lookup is used more and more often. In fast boot case, for example, even 5ms is important.

Yes, and you're not the only one who has that concern. What this patch does is turn a pair of string compares through a table into that plus another set of string compares across all struct clk, which will make the lookup yet more expensive.

I see no reason why you'd register the cl_lookup structures before you know about which clks actually exist - and if they already exist, then you can already find the struct clk pointer and use that to register the proper return value for clk_get() via the clkdev APIs.

As I've said in the past, naming individual clock structures is the stupidest thing that anyone ever did and causes nothing but problems. We've seen that in the drivers with the abuse of clk_get(NULL, name) where people wanted to pass the name in via platform data. We're starting to see the same thing here as well, except the problem people will see will be boot performance instead caused by multiple levels of string compares.

author maintainer
#15 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 23 lines · Russell King - ARM Linux
Quoted 10 lines · Richard Zhao
Quoted 9 lines · Mark Brown
Quoted 2 lines · Richard Zhao

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

Quoted 6 lines

My point is using string lookup as less as possible. When one register a clk, one already got the struct clk* pointer and could use it in struct lookup.

I'm worried about the performance as I saw string lookup is used more and more often. In fast boot case, for example, even 5ms is important.

Yes, and you're not the only one who has that concern. What this patch does is turn a pair of string compares through a table into that plus another set of string compares across all struct clk, which will make the lookup yet more expensive.

Quoted 4 lines

I see no reason why you'd register the cl_lookup structures before you know about which clks actually exist - and if they already exist, then you can already find the struct clk pointer and use that to register the proper return value for clk_get() via the clkdev APIs.

Indeed I have struct clk pointers, so I can instead use a to-be-written combination of clkdev_alloc/clkdev_add. Would that be ok?

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#16 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 6 lines · Sascha Hauer
Quoted 5 lines · Russell King - ARM Linux

Yes, and you're not the only one who has that concern. What this patch does is turn a pair of string compares through a table into that plus another set of string compares across all struct clk, which will make the lookup yet more expensive.

Quoted 7 lines
Quoted 4 lines

I see no reason why you'd register the cl_lookup structures before you know about which clks actually exist - and if they already exist, then you can already find the struct clk pointer and use that to register the proper return value for clk_get() via the clkdev APIs.

Indeed I have struct clk pointers, so I can instead use a to-be-written combination of clkdev_alloc/clkdev_add. Would that be ok?

As we already have clkdev_alloc and clkdev_add, then I don't see that as a problem - except we may have to change __clkdev_alloc() so that it can be used before kmalloc() is up and running.

#17 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 5 lines · Russell King - ARM Linux
Quoted 2 lines
Quoted 2 lines

Indeed I have struct clk pointers, so I can instead use a to-be-written combination of clkdev_alloc/clkdev_add. Would that be ok?

As we already have clkdev_alloc and clkdev_add, then I don't see that as a problem - except we may have to change __clkdev_alloc() so that it can be used before kmalloc() is up and running.

Instead of platforms calling these routines, can we have these calls from clk_register_*() routines directly? So, for every clock registered with common clk framework this gets done automatically. We just need to pass dev & con id strings to these routines.

Signature · 1 line
viresh
#18 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 12 lines · Viresh Kumar
Quoted 5 lines · Russell King - ARM Linux
Quoted 2 lines
Quoted 2 lines

Indeed I have struct clk pointers, so I can instead use a to-be-written combination of clkdev_alloc/clkdev_add. Would that be ok?

As we already have clkdev_alloc and clkdev_add, then I don't see that as a problem - except we may have to change __clkdev_alloc() so that it can be used before kmalloc() is up and running.

Instead of platforms calling these routines, can we have these calls from clk_register_*() routines directly? So, for every clock registered with common clk framework this gets done automatically. We just need to pass dev & con id strings to these routines.

No.

Only small portion of the entire clock tree need to be in the lookup, usually the leaf clocks that device drivers need to access/manage.

Regards,
Shawn

#19 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 10 lines · Shawn Guo
Quoted 6 lines
Quoted 6 lines

Instead of platforms calling these routines, can we have these calls from clk_register_*() routines directly? So, for every clock registered with common clk framework this gets done automatically. We just need to pass dev & con id strings to these routines.

No.

Only small portion of the entire clock tree need to be in the lookup, usually the leaf clocks that device drivers need to access/manage.

I am not asking to enforce this for all clocks and create too many clk lookups. But do it for all clk_register() calls, that have valid dev_id or con_id.

Apart from device clocks, there are other clocks, parent selection, etc that need it, so that we can do clk_get_sys().

Signature · 1 line
viresh
#20 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 7 lines · Viresh Kumar
Quoted 6 lines · Shawn Guo
Quoted 6 lines
Quoted 6 lines

Instead of platforms calling these routines, can we have these calls from clk_register_*() routines directly? So, for every clock registered with common clk framework this gets done automatically. We just need to pass dev & con id strings to these routines.

Quoted 8 lines
Quoted 4 lines

No.

Only small portion of the entire clock tree need to be in the lookup, usually the leaf clocks that device drivers need to access/manage.

I am not asking to enforce this for all clocks and create too many clk lookups. But do it for all clk_register() calls, that have valid dev_id or con_id.

It makes sense then. Only concern I have is the long argument list of clk_register() becomes even longer.

Regards,
Shawn

Quoted 2 lines

Apart from device clocks, there are other clocks, parent selection, etc that need it, so that we can do clk_get_sys().

#21 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 2 lines · Shawn Guo

It makes sense then. Only concern I have is the long argument list of clk_register() becomes even longer.

Or we need to dump the arguments into a struct.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120413/f83715ee/attachment.sig>

#22 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 1 line · Mark Brown

Or we need to dump the arguments into a struct.

Then we would end up creating too many structures in our mach/clock.c files. That will look bad. May perform better. :)

Signature · 1 line
viresh
#23 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 5 lines · Viresh Kumar
Quoted 1 line · Mark Brown

Or we need to dump the arguments into a struct.

Then we would end up creating too many structures in our mach/clock.c files. That will look bad. May perform better. :)

or pass struct clk_lookup* ? For non-leaf clks, it's NULL.

Quoted 4 lines
Signature · 2 lines
-- 
viresh
#24 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 7 lines · Richard Zhao
Quoted 5 lines · Viresh Kumar
Quoted 1 line · Mark Brown

Or we need to dump the arguments into a struct.

Then we would end up creating too many structures in our mach/clock.c files. That will look bad. May perform better. :)

or pass struct clk_lookup* ? For non-leaf clks, it's NULL.

What's wrong with the struct clk returned from clk_register() - why not do this as a two-step process? Especially as you may want to associate a single clock with more than one clk_lookup.

#25 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 2 lines · Russell King - ARM Linux

What's wrong with the struct clk returned from clk_register() - why not do this as a two-step process?

Code duplication on all platforms for creating these lookups.

Quoted 2 lines

Especially as you may want to
associate a single clock with more than one clk_lookup.

Can still be done, as we are still getting clk pointer back.

Signature · 1 line
viresh
#26 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 10 lines · Viresh Kumar
Quoted 2 lines · Russell King - ARM Linux

What's wrong with the struct clk returned from clk_register() - why not do this as a two-step process?

Code duplication on all platforms for creating these lookups.

Quoted 2 lines

Especially as you may want to
associate a single clock with more than one clk_lookup.

Can still be done, as we are still getting clk pointer back.

You're not convincing me that you're approach here is correct, and I really doubt that this will have any effect at saving lines of code - your argument list is soo long that you'll have to wrap it onto several lines.

So I don't buy the 'code duplication' argument here - I think that's a red herring, and I think you're better off making interfaces which are simpler to use.

#27 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 1 line · Russell King - ARM Linux

You're not convincing me that you're approach here is correct, and

:(

Quoted 3 lines

I really doubt that this will have any effect at saving lines of code - your argument list is soo long that you'll have to wrap it onto several lines.

There are two ways here:
1. Leave clk_register() untouched and create lookups in machine code.
2. change clk_register():
A. pass all arguments as i mentioned in my patch B. pass structure instead of all so many args.

Option 2 will have much lesser code than option 1, with both option A & B. In option 2.A.: we can create separate registration routines to save extra arguments passed, like:

struct clk *clk_register_gate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx,

		u8 clk_gate_flags, spinlock_t *lock, struct clk_lookup **cl,
		const char *dev_id, const char *con_id);

static inline struct clk *clk_register_gate_nolookup(struct device *dev,
const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock);

Nodes, that don't need lookup stuff, can go ahead as earlier, just need to add _nolookup in existing routine name.

Signature · 1 line
viresh
#28 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 2 lines · Viresh Kumar

Nodes, that don't need lookup stuff, can go ahead as earlier, just need to add _nolookup in existing routine name.

Or just have the core function handle NULL as a lookup array gracefully.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120413/24bcc1a6/attachment.sig>

#29 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

In reply to Viresh Kumar
Quoted 22 lines · Viresh Kumar
Quoted 1 line · Russell King - ARM Linux

You're not convincing me that you're approach here is correct, and

:(

Quoted 3 lines

I really doubt that this will have any effect at saving lines of code - your argument list is soo long that you'll have to wrap it onto several lines.

There are two ways here:
1. Leave clk_register() untouched and create lookups in machine code.
2. change clk_register():
A. pass all arguments as i mentioned in my patch B. pass structure instead of all so many args.

Option 2 will have much lesser code than option 1, with both option A & B. In option 2.A.: we can create separate registration routines to save extra arguments passed, like:

struct clk *clk_register_gate(struct device *dev, const char *name,

(quoted diff) +0 -0
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
Quoted 2 lines
		u8 clk_gate_flags, spinlock_t *lock, struct clk_lookup **cl,
		const char *dev_id, const char *con_id);

So you're going to have something around 4-5 lines of arguments per function call to use this function. That's not elegant, that's not easy to use, that's not nice. And I doubt that it really solves any code space concern because the compiler will have to store pointers and values somewhere, and shuffle those into registers and onto the stack for every function call using additional code to do that.

I really don't get why you think this is an improvement.

#30 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

Quoted 6 lines · Russell King - ARM Linux

So you're going to have something around 4-5 lines of arguments per function call to use this function. That's not elegant, that's not easy to use, that's not nice. And I doubt that it really solves any code space concern because the compiler will have to store pointers and values somewhere, and shuffle those into registers and onto the stack for every function call using additional code to do that.

But it is still the same with the current implementation. Right now also we have too many arguments. Even if we do clkdev_alloc() in platform files.

Quoted 1 line

I really don't get why you think this is an improvement.

Only improvement is simplicity at the end of machine clock.c files, that don't need to do clkdev_alloc() for every clock they clk_lookups.

I didn't liked this long of argument list, but couldn't think of something better, that makes machine clock code easy. :(

Signature · 1 line
viresh
#31 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

In reply to Russell King - ARM Linux
Quoted 26 lines · Russell King - ARM Linux
Quoted 19 lines · Viresh Kumar
Quoted 1 line · Russell King - ARM Linux

You're not convincing me that you're approach here is correct, and

:(

Quoted 3 lines

I really doubt that this will have any effect at saving lines of code - your argument list is soo long that you'll have to wrap it onto several lines.

There are two ways here:
1. Leave clk_register() untouched and create lookups in machine code.
2. change clk_register():
? ? ? A. pass all arguments as i mentioned in my patch
? ? ? B. pass structure instead of all so many args.

Option 2 will have much lesser code than option 1, with both option A & B. In option 2.A.: we can create separate registration routines to save extra arguments passed, like:

Quoted 5 lines

?struct clk *clk_register_gate(struct device *dev, const char *name, ? ? ? ? ? ? ? const char *parent_name, unsigned long flags,
? ? ? ? ? ? ? void __iomem *reg, u8 bit_idx,
? ? ? ? ? ? ? u8 clk_gate_flags, spinlock_t *lock, struct clk_lookup **cl, ? ? ? ? ? ? ? const char *dev_id, const char *con_id);

Quoted 8 lines

So you're going to have something around 4-5 lines of arguments per function call to use this function. ?That's not elegant, that's not easy to use, that's not nice. ?And I doubt that it really solves any code space concern because the compiler will have to store pointers and values somewhere, and shuffle those into registers and onto the stack for every function call using additional code to do that.

I really don't get why you think this is an improvement.

My hope is that forthcoming struct clk_hw/static initializer patch will reduce the number of arguments to clk_register considerably. These interfaces are not frozen and everyone concerned with using the common framework is still figuring out exactly how this stuff should look.

http://article.gmane.org/gmane.linux.ports.arm.msm/2587

Regards,
Mike

#32 lore raw

PATCH 1/40 clkdev: add clkname to struct clk_lookup

In reply to Russell King - ARM Linux
Quoted 28 lines · Russell King - ARM Linux
Quoted 10 lines · Richard Zhao
Quoted 9 lines · Mark Brown
Quoted 2 lines · Richard Zhao

I don't like string loopup either. And after DT binding, we can use phandler to refer clk.

No, this is only useful on platforms that use DT. This is a generic Linux API so it needs to support architectures and platforms that don't use DT as it's vanishingly unlikely that DT will ever be adopted by all platforms.

Quoted 6 lines

My point is using string lookup as less as possible. When one register a clk, one already got the struct clk* pointer and could use it in struct lookup.

I'm worried about the performance as I saw string lookup is used more and more often. In fast boot case, for example, even 5ms is important.

Yes, and you're not the only one who has that concern. What this patch does is turn a pair of string compares through a table into that plus another set of string compares across all struct clk, which will make the lookup yet more expensive.

I see no reason why you'd register the cl_lookup structures before you know about which clks actually exist - and if they already exist, then you can already find the struct clk pointer and use that to register the proper return value for clk_get() via the clkdev APIs.

Quoted 7 lines

As I've said in the past, naming individual clock structures is the stupidest thing that anyone ever did and causes nothing but problems. We've seen that in the drivers with the abuse of clk_get(NULL, name) where people wanted to pass the name in via platform data. We're starting to see the same thing here as well, except the problem people will see will be boot performance instead caused by multiple levels of string compares.

I just realized an important benefit of string lookup is we can define machine specific lookups at its machine file.
Without it, we have to expose machine specific clk twice. For example, cko1 is SoC internal clock name and is connected to sgtl5000 audio codec. {"sgtl5000-dev-name", "function name"} lookup is board specific, and {NULL, "cko1"} is SoC specific. We have to expose both of them.

Thanks
Richard

Quoted 1 line
author maintainer
#33 lore raw

PATCH 2/40 clk: add a fixed factor clock

In reply to Sascha Hauer

Having fixed factors/dividers in hardware is a common pattern, so add a basic clock type doing this. It basically describes a fixed factor clock using a nominator and a denominator.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c
drivers/clk/Makefile +1 -1
index 1f736bc..24aa714 100644
@@ -1,4 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
-				   clk-mux.o clk-divider.o
+				   clk-mux.o clk-divider.o clk-fixed-factor.o
drivers/clk/clk-fixed-factor.c new file +97 -0

97 lines not on this page · raw message

include/linux/clk-provider.h +4 -0
index 5508897..21ca2f8 100644
@@ -257,6 +257,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
+struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned int mult, unsigned int div);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
Signature · 1 line
1.7.9.5
#34 lore raw

PATCH 2/40 clk: add a fixed factor clock

Quoted 11 lines · Sascha Hauer

Having fixed factors/dividers in hardware is a common pattern, so add a basic clock type doing this. It basically describes a fixed factor clock using a nominator and a denominator.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c

Please see if below changes look fine to you. They would be required once you rebase over latest patches floated by Mike:

---
 drivers/clk/clk-fixed-factor.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)
drivers/clk/clk-fixed-factor.c +5 -3
index 7c5e1fc..45a4823 100644
@@ -16,7 +16,7 @@ struct clk_fixed_factor {
        struct clk_hw   hw;
        unsigned int    mult;
        unsigned int    div;
-       char            *parent[1];
+       const char      *parent[1];
 };
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
@@ -86,11 +86,13 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
                        fix->parent,
                        (parent_name ? 1 : 0),
                        flags);
+
+       if (parent_name)
+               kfree(fix->parent[0]);
+
        if (clk)
                return clk;
-
 out:
-       kfree(fix->parent[0]);
        kfree(fix);
 
        return NULL;
Signature · 1 line
viresh
#35 lore raw

PATCH 2/40 clk: add a fixed factor clock

In reply to Sascha Hauer
Quoted 11 lines · Sascha Hauer

Having fixed factors/dividers in hardware is a common pattern, so add a basic clock type doing this. It basically describes a fixed factor clock using a nominator and a denominator.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c

@Mike: It would be better if you can take this patch atleast ASAP in your next, so that Arnd can pull in SPEAr clk patches.

Hi Sascha/Mike,

Please see if following can be squashed with this patch. This clock is used for SPEAr too :)

---
 drivers/clk/clk-fixed-factor.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)
drivers/clk/clk-fixed-factor.c +2 -10
index 7c5e1fc..aaf5a88 100644
@@ -16,7 +16,6 @@ struct clk_fixed_factor {
 	struct clk_hw	hw;
 	unsigned int	mult;
 	unsigned int	div;
-	char		*parent[1];
 };
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
@@ -75,22 +74,15 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	fix->mult = mult;
 	fix->div = div;
 
-	if (parent_name) {
-		fix->parent[0] = kstrdup(parent_name, GFP_KERNEL);
-		if (!fix->parent[0])
-			goto out;
-	}
-
 	clk = clk_register(dev, name,
 			&clk_fixed_factor_ops, &fix->hw,
-			fix->parent,
+			&parent_name,
 			(parent_name ? 1 : 0),
 			flags);
+
 	if (clk)
 		return clk;
 
-out:
-	kfree(fix->parent[0]);
 	kfree(fix);
 
 	return NULL;
Signature · 1 line
1.7.9
#36 lore raw

PATCH 2/40 clk: add a fixed factor clock

Quoted 30 lines · Viresh Kumar
Quoted 11 lines · Sascha Hauer

Having fixed factors/dividers in hardware is a common pattern, so add a basic clock type doing this. It basically describes a fixed factor clock using a nominator and a denominator.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c

@Mike: It would be better if you can take this patch atleast ASAP in your next, so that Arnd can pull in SPEAr clk patches.

Hi Sascha/Mike,

Please see if following can be squashed with this patch. This clock is used for SPEAr too :)

---
 drivers/clk/clk-fixed-factor.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)
drivers/clk/clk-fixed-factor.c +0 -0
index 7c5e1fc..aaf5a88 100644

drivers/clk/clk-fixed-factor.c struct clk_fixed_factor { · line 19

Quoted 4 lines
drivers/clk/clk-fixed-factor.c +0 -1
@@ -16,7 +16,6 @@ struct clk_fixed_factor {
 	struct clk_hw	hw;
 	unsigned int	mult;
 	unsigned int	div;
-	char		*parent[1];

add const here

drivers/clk/clk-fixed-factor.c struct clk *clk_register_fixed_factor(struct device *dev, const char *name, · line 78

Quoted 8 lines
drivers/clk/clk-fixed-factor.c +0 -1
 };
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
@@ -75,22 +74,15 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	fix->mult = mult;
 	fix->div = div;
 
-	if (parent_name) {
		char *tmp = kstrdup(parent_name, GFP_KERNEL);
		if (!tmp)
			goto out;
		fix->parent[0] = tmp;

drivers/clk/clk-fixed-factor.c struct clk *clk_register_fixed_factor(struct device *dev, const char *name, · line 79

Quoted 6 lines
drivers/clk/clk-fixed-factor.c +1 -3
-	}
-
 	clk = clk_register(dev, name,
 			&clk_fixed_factor_ops, &fix->hw,
-			fix->parent,
+			&parent_name,

&parent_name is a pointer to a stack variable, right? clk_register saves it in the clk struct for later use, when the stack is already gone.

drivers/clk/clk-fixed-factor.c struct clk *clk_register_fixed_factor(struct device *dev, const char *name, · line 88

Quoted 11 lines
drivers/clk/clk-fixed-factor.c +1 -2
 			(parent_name ? 1 : 0),
 			flags);
+
 	if (clk)
 		return clk;
 
-out:
-	kfree(fix->parent[0]);
 	kfree(fix);
 
 	return NULL;

BRs,
Domenico

#37 lore raw

PATCH 2/40 clk: add a fixed factor clock

Quoted 11 lines · Domenico Andreoli

drivers/clk/clk-fixed-factor.c struct clk_fixed_factor { · line 19

Quoted 7 lines · Viresh Kumar

On 4/10/2012 7:15 PM, Sascha Hauer wrote:

drivers/clk/clk-fixed-factor.c +0 -1
@@ -16,7 +16,6 @@ struct clk_fixed_factor {
 	struct clk_hw	hw;
 	unsigned int	mult;
 	unsigned int	div;
-	char		*parent[1];

add const here

I removed it. :)

Quoted 7 lines

drivers/clk/clk-fixed-factor.c struct clk *clk_register_fixed_factor(struct device *dev, const char *name, · line 79

Quoted 4 lines
drivers/clk/clk-fixed-factor.c +1 -1
 	clk = clk_register(dev, name,
 			&clk_fixed_factor_ops, &fix->hw,
-			fix->parent,
+			&parent_name,

&parent_name is a pointer to a stack variable, right? clk_register saves it in the clk struct for later use, when the stack is already gone.

Yes. It is on stack, but clk_register doesn't save it any more. Following is part of clk_register that saves

	/* copy each string name in case parent_names is __initdata */
	for (i = 0; i < num_parents; i++) {
		clk->parent_names[i] = kstrdup(parent_names[i], GFP_KERNEL);
		if (!clk->parent_names[i]) {
			pr_err("%s: could not copy parent_names\n", __func__);
			goto fail_parent_names_copy;
		}
	}

This happened with following patch sent by Mike. This isn't pushed till now.

Author: Mike Turquette <[email protected]>
Date:   Thu Apr 12 09:02:50 2012 +0800

clk: core: copy parent_names & return error codes

This patch cleans up clk_register and solves a few bugs by teaching clk_register and __clk_init to return error codes (instead of just NULL) to better align with the existing clk.h api.

Along with that change this patch also introduces a new behavior whereby clk_register copies the parent_names array, thus allowing platforms to declare their parent_names arrays as __initdata.

--
Viresh

author maintainer
#38 lore raw

PATCH 2/40 clk: add a fixed factor clock

In reply to Viresh Kumar
Quoted 13 lines · Viresh Kumar
Quoted 11 lines · Sascha Hauer

Having fixed factors/dividers in hardware is a common pattern, so add a basic clock type doing this. It basically describes a fixed factor clock using a nominator and a denominator.

---
 drivers/clk/Makefile           |    2 +-
 drivers/clk/clk-fixed-factor.c |   97 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h   |    4 ++
 3 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-fixed-factor.c
Quoted 7 lines

@Mike: It would be better if you can take this patch atleast ASAP in your next, so that Arnd can pull in SPEAr clk patches.

Hi Sascha/Mike,

Please see if following can be squashed with this patch. This clock is used for SPEAr too :)

Generally yes, but I want to delay this until we have an official branch for clk-common-next (In which probably clk_register copies the parent names)

Sascha

Quoted 45 lines
---
 drivers/clk/clk-fixed-factor.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)
drivers/clk/clk-fixed-factor.c +2 -10
index 7c5e1fc..aaf5a88 100644
@@ -16,7 +16,6 @@ struct clk_fixed_factor {
 	struct clk_hw	hw;
 	unsigned int	mult;
 	unsigned int	div;
-	char		*parent[1];
 };
 
 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw)
@@ -75,22 +74,15 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	fix->mult = mult;
 	fix->div = div;
 
-	if (parent_name) {
-		fix->parent[0] = kstrdup(parent_name, GFP_KERNEL);
-		if (!fix->parent[0])
-			goto out;
-	}
-
 	clk = clk_register(dev, name,
 			&clk_fixed_factor_ops, &fix->hw,
-			fix->parent,
+			&parent_name,
 			(parent_name ? 1 : 0),
 			flags);
+
 	if (clk)
 		return clk;
 
-out:
-	kfree(fix->parent[0]);
 	kfree(fix);
 
 	return NULL;
Signature · 1 line
1.7.9
Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#39 lore raw

PATCH 3/40 clk: declare clk_ops of basic clks in clk-provider.h

In reply to Sascha Hauer

From: Shawn Guo <[email protected]>

Besides the static initialization, the clk_ops of basic clks could also be used by particular clk type being subclass of the basic clks.

For example, clk_busy_divider has the same clk_ops as clk_divider, except it has to wait for a busy bit before return success with .set_rate. clk_busy_divider will somehow reuse clk_ops of clk_divider.

Since clk-provider.h is included by clk-private.h, it's safe to move those clk_ops declaration of basic clks form clk-private.h into clk-provider.h, so that implementation of clks like clk_busy_divider above do not need to include clk-private.h to access those clk_ops.

---
 include/linux/clk-private.h  |    8 --------
 include/linux/clk-provider.h |    8 ++++++++
 2 files changed, 8 insertions(+), 8 deletions(-)
include/linux/clk-private.h +0 -8
index 5e4312b..f19fee0 100644
@@ -55,8 +55,6 @@ struct clk {
  * alternative macro for static initialization
  */
 
-extern struct clk_ops clk_fixed_rate_ops;
-
 #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
 				_fixed_rate_flags)		\
 	static struct clk _name;				\
@@ -78,8 +76,6 @@ extern struct clk_ops clk_fixed_rate_ops;
 		.flags = _flags,				\
 	};
 
-extern struct clk_ops clk_gate_ops;
-
 #define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _bit_idx,		\
 				_gate_flags, _lock)		\
@@ -110,8 +106,6 @@ extern struct clk_ops clk_gate_ops;
 		.flags = _flags,				\
 	};
 
-extern struct clk_ops clk_divider_ops;
-
 #define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
 				_divider_flags, _lock)		\
@@ -143,8 +137,6 @@ extern struct clk_ops clk_divider_ops;
 		.flags = _flags,				\
 	};
 
-extern struct clk_ops clk_mux_ops;
-
 #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
 				_reg, _shift, _width,		\
 				_mux_flags, _lock)		\
include/linux/clk-provider.h +8 -0
index 21ca2f8..587f54b 100644
@@ -149,6 +149,8 @@ struct clk_fixed_rate {
 	u8		flags;
 };
 
+extern struct clk_ops clk_fixed_rate_ops;
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate);
@@ -180,6 +182,8 @@ struct clk_gate {
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
 
+extern struct clk_ops clk_gate_ops;
+
 struct clk *clk_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
@@ -218,6 +222,8 @@ struct clk_divider {
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
 
+extern struct clk_ops clk_divider_ops;
+
 struct clk *clk_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
@@ -252,6 +258,8 @@ struct clk_mux {
 #define CLK_MUX_INDEX_ONE		BIT(0)
 #define CLK_MUX_INDEX_BIT		BIT(1)
 
+extern struct clk_ops clk_mux_ops;
+
 struct clk *clk_register_mux(struct device *dev, const char *name,
 		char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
Signature · 1 line
1.7.9.5
author maintainer
#40 lore raw

PATCH 4/40 dmaengine i.MX SDMA: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/dma/imx-sdma.c |   40 ++++++++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 12 deletions(-)
drivers/dma/imx-sdma.c +28 -12
index d3e38e2..fddccae 100644
@@ -322,7 +322,8 @@ struct sdma_engine {
 	struct sdma_context_data	*context;
 	dma_addr_t			context_phys;
 	struct dma_device		dma_device;
-	struct clk			*clk;
+	struct clk			*clk_ipg;
+	struct clk			*clk_ahb;
 	struct mutex			channel_0_lock;
 	struct sdma_script_start_addrs	*script_addrs;
 };
@@ -859,7 +860,8 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
 	sdmac->peripheral_type = data->peripheral_type;
 	sdmac->event_id0 = data->dma_request;
 
-	clk_enable(sdmac->sdma->clk);
+	clk_enable(sdmac->sdma->clk_ipg);
+	clk_enable(sdmac->sdma->clk_ahb);
 
 	ret = sdma_request_channel(sdmac);
 	if (ret)
@@ -896,7 +898,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
 	dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
 
-	clk_disable(sdma->clk);
+	clk_disable(sdma->clk_ipg);
+	clk_disable(sdma->clk_ahb);
 }
 
 static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
@@ -1169,12 +1172,14 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
 	addr = (void *)header + header->script_addrs_start;
 	ram_code = (void *)header + header->ram_code_start;
 
-	clk_enable(sdma->clk);
+	clk_enable(sdma->clk_ipg);
+	clk_enable(sdma->clk_ahb);
 	/* download the RAM image for SDMA */
 	sdma_load_script(sdma, ram_code,
 			header->ram_code_size,
 			addr->ram_code_start_addr);
-	clk_disable(sdma->clk);
+	clk_disable(sdma->clk_ipg);
+	clk_disable(sdma->clk_ahb);
 
 	sdma_add_scripts(sdma, addr);
 
@@ -1216,7 +1221,8 @@ static int __init sdma_init(struct sdma_engine *sdma)
 		return -ENODEV;
 	}
 
-	clk_enable(sdma->clk);
+	clk_enable(sdma->clk_ipg);
+	clk_enable(sdma->clk_ahb);
 
 	/* Be sure SDMA has not started yet */
 	writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
@@ -1269,12 +1275,14 @@ static int __init sdma_init(struct sdma_engine *sdma)
 	/* Initializes channel's priorities */
 	sdma_set_channel_priority(&sdma->channel[0], 7);
 
-	clk_disable(sdma->clk);
+	clk_disable(sdma->clk_ipg);
+	clk_disable(sdma->clk_ahb);
 
 	return 0;
 
 err_dma_alloc:
-	clk_disable(sdma->clk);
+	clk_disable(sdma->clk_ipg);
+	clk_disable(sdma->clk_ahb);
 	dev_err(sdma->dev, "initialisation failed with %d\n", ret);
 	return ret;
 }
@@ -1313,12 +1321,21 @@ static int __init sdma_probe(struct platform_device *pdev)
 		goto err_request_region;
 	}
 
-	sdma->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(sdma->clk)) {
-		ret = PTR_ERR(sdma->clk);
+	sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(sdma->clk_ipg)) {
+		ret = PTR_ERR(sdma->clk_ipg);
 		goto err_clk;
 	}
 
+	sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sdma->clk_ahb)) {
+		ret = PTR_ERR(sdma->clk_ahb);
+		goto err_clk;
+	}
+
+	clk_prepare(sdma->clk_ipg);
+	clk_prepare(sdma->clk_ahb);
+
 	sdma->regs = ioremap(iores->start, resource_size(iores));
 	if (!sdma->regs) {
 		ret = -ENOMEM;
@@ -1426,7 +1443,6 @@ err_alloc:
 err_request_irq:
 	iounmap(sdma->regs);
 err_ioremap:
-	clk_put(sdma->clk);
 err_clk:
 	release_mem_region(iores->start, resource_size(iores));
 err_request_region:
Signature · 1 line
1.7.9.5
author maintainer
#41 lore raw

PATCH 5/40 spi i.MX: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/spi/spi-imx.c |   30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/spi/spi-imx.c +19 -11
index 31054e3..b54bfe8 100644
@@ -85,7 +85,8 @@ struct spi_imx_data {
 	struct completion xfer_done;
 	void *base;
 	int irq;
-	struct clk *clk;
+	struct clk *clk_per;
+	struct clk *clk_ipg;
 	unsigned long spi_clk;
 
 	unsigned int count;
@@ -841,15 +842,22 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 		goto out_iounmap;
 	}
 
-	spi_imx->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(spi_imx->clk)) {
-		dev_err(&pdev->dev, "unable to get clock\n");
-		ret = PTR_ERR(spi_imx->clk);
+	spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(spi_imx->clk_ipg)) {
+		ret = PTR_ERR(spi_imx->clk_ipg);
 		goto out_free_irq;
 	}
 
-	clk_enable(spi_imx->clk);
-	spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
+	spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(spi_imx->clk_per)) {
+		ret = PTR_ERR(spi_imx->clk_per);
+		goto out_free_irq;
+	}
+
+	clk_prepare_enable(spi_imx->clk_per);
+	clk_prepare_enable(spi_imx->clk_ipg);
+
+	spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
 
 	spi_imx->devtype_data->reset(spi_imx);
 
@@ -867,8 +875,8 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 	return ret;
 
 out_clk_put:
-	clk_disable(spi_imx->clk);
-	clk_put(spi_imx->clk);
+	clk_disable_unprepare(spi_imx->clk_per);
+	clk_disable_unprepare(spi_imx->clk_ipg);
 out_free_irq:
 	free_irq(spi_imx->irq, spi_imx);
 out_iounmap:
@@ -896,8 +904,8 @@ static int __devexit spi_imx_remove(struct platform_device *pdev)
 	spi_bitbang_stop(&spi_imx->bitbang);
 
 	writel(0, spi_imx->base + MXC_CSPICTRL);
-	clk_disable(spi_imx->clk);
-	clk_put(spi_imx->clk);
+	clk_disable_unprepare(spi_imx->clk_per);
+	clk_disable_unprepare(spi_imx->clk_ipg);
 	free_irq(spi_imx->irq, spi_imx);
 	iounmap(spi_imx->base);
 
Signature · 1 line
1.7.9.5
author maintainer
#42 lore raw

PATCH 6/40 video imxfb: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/video/imxfb.c |   50 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 15 deletions(-)
drivers/video/imxfb.c +35 -15
index f135dbe..caad368 100644
@@ -131,7 +131,9 @@ struct imxfb_rgb {
 struct imxfb_info {
 	struct platform_device  *pdev;
 	void __iomem		*regs;
-	struct clk		*clk;
+	struct clk		*clk_ipg;
+	struct clk		*clk_ahb;
+	struct clk		*clk_per;
 
 	/*
 	 * These are the addresses we mapped
@@ -340,7 +342,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
 	pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
 
-	lcd_clk = clk_get_rate(fbi->clk);
+	lcd_clk = clk_get_rate(fbi->clk_per);
 
 	tmp = var->pixclock * (unsigned long long)lcd_clk;
 
@@ -455,11 +457,17 @@ static int imxfb_bl_update_status(struct backlight_device *bl)
 
 	fbi->pwmr = (fbi->pwmr & ~0xFF) | brightness;
 
-	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-		clk_enable(fbi->clk);
+	if (bl->props.fb_blank != FB_BLANK_UNBLANK) {
+		clk_prepare_enable(fbi->clk_ipg);
+		clk_prepare_enable(fbi->clk_ahb);
+		clk_prepare_enable(fbi->clk_per);
+	}
 	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
-	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-		clk_disable(fbi->clk);
+	if (bl->props.fb_blank != FB_BLANK_UNBLANK) {
+		clk_disable_unprepare(fbi->clk_per);
+		clk_disable_unprepare(fbi->clk_ahb);
+		clk_disable_unprepare(fbi->clk_ipg);
+	}
 
 	return 0;
 }
@@ -522,7 +530,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
 	 */
 	writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR);
 
-	clk_enable(fbi->clk);
+	clk_prepare_enable(fbi->clk_ipg);
+	clk_prepare_enable(fbi->clk_ahb);
+	clk_prepare_enable(fbi->clk_per);
 
 	if (fbi->backlight_power)
 		fbi->backlight_power(1);
@@ -539,7 +549,9 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
 	if (fbi->lcd_power)
 		fbi->lcd_power(0);
 
-	clk_disable(fbi->clk);
+	clk_disable_unprepare(fbi->clk_per);
+	clk_disable_unprepare(fbi->clk_ipg);
+	clk_disable_unprepare(fbi->clk_ahb);
 
 	writel(0, fbi->regs + LCDC_RMCR);
 }
@@ -770,10 +782,21 @@ static int __init imxfb_probe(struct platform_device *pdev)
 		goto failed_req;
 	}
 
-	fbi->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(fbi->clk)) {
-		ret = PTR_ERR(fbi->clk);
-		dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
+	fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(fbi->clk_ipg)) {
+		ret = PTR_ERR(fbi->clk_ipg);
+		goto failed_getclock;
+	}
+
+	fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(fbi->clk_ahb)) {
+		ret = PTR_ERR(fbi->clk_ahb);
+		goto failed_getclock;
+	}
+
+	fbi->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(fbi->clk_per)) {
+		ret = PTR_ERR(fbi->clk_per);
 		goto failed_getclock;
 	}
 
@@ -858,7 +881,6 @@ failed_platform_init:
 failed_map:
 	iounmap(fbi->regs);
 failed_ioremap:
-	clk_put(fbi->clk);
 failed_getclock:
 	release_mem_region(res->start, resource_size(res));
 failed_req:
@@ -895,8 +917,6 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
 
 	iounmap(fbi->regs);
 	release_mem_region(res->start, resource_size(res));
-	clk_disable(fbi->clk);
-	clk_put(fbi->clk);
 
 	platform_set_drvdata(pdev, NULL);
 
Signature · 1 line
1.7.9.5
author maintainer
#43 lore raw

PATCH 7/40 net fec: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/net/ethernet/freescale/fec.c |   35 ++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)
drivers/net/ethernet/freescale/fec.c +23 -12
index a12b3f5..b249463 100644
@@ -206,7 +206,8 @@ struct fec_enet_private {
 
 	struct net_device *netdev;
 
-	struct clk *clk;
+	struct clk *clk_ipg;
+	struct clk *clk_ahb;
 
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	unsigned char *tx_bounce[TX_RING_SIZE];
@@ -1064,7 +1065,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
 	 * Reference Manual has an error on this, and gets fixed on i.MX6Q
 	 * document.
 	 */
-	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk), 5000000);
+	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
 	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
 		fep->phy_speed--;
 	fep->phy_speed <<= 1;
@@ -1609,12 +1610,20 @@ fec_probe(struct platform_device *pdev)
 		}
 	}
 
-	fep->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(fep->clk)) {
-		ret = PTR_ERR(fep->clk);
+	fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(fep->clk_ipg)) {
+		ret = PTR_ERR(fep->clk_ipg);
 		goto failed_clk;
 	}
-	clk_prepare_enable(fep->clk);
+
+	fep->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(fep->clk_ahb)) {
+		ret = PTR_ERR(fep->clk_ahb);
+		goto failed_clk;
+	}
+
+	clk_prepare_enable(fep->clk_ahb);
+	clk_prepare_enable(fep->clk_ipg);
 
 	ret = fec_enet_init(ndev);
 	if (ret)
@@ -1637,8 +1646,8 @@ failed_register:
 	fec_enet_mii_remove(fep);
 failed_mii_init:
 failed_init:
-	clk_disable_unprepare(fep->clk);
-	clk_put(fep->clk);
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
 failed_clk:
 	for (i = 0; i < FEC_IRQ_NUM; i++) {
 		irq = platform_get_irq(pdev, i);
@@ -1670,8 +1679,8 @@ fec_drv_remove(struct platform_device *pdev)
 		if (irq > 0)
 			free_irq(irq, ndev);
 	}
-	clk_disable_unprepare(fep->clk);
-	clk_put(fep->clk);
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
 	iounmap(fep->hwp);
 	free_netdev(ndev);
 
@@ -1695,7 +1704,8 @@ fec_suspend(struct device *dev)
 		fec_stop(ndev);
 		netif_device_detach(ndev);
 	}
-	clk_disable_unprepare(fep->clk);
+	clk_disable_unprepare(fep->clk_ahb);
+	clk_disable_unprepare(fep->clk_ipg);
 
 	return 0;
 }
@@ -1706,7 +1716,8 @@ fec_resume(struct device *dev)
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	clk_prepare_enable(fep->clk);
+	clk_prepare_enable(fep->clk_ahb);
+	clk_prepare_enable(fep->clk_ipg);
 	if (netif_running(ndev)) {
 		fec_restart(ndev, fep->full_duplex);
 		netif_device_attach(ndev);
Signature · 1 line
1.7.9.5
author maintainer
#44 lore raw

PATCH 8/40 mmc mxcmmc: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/mmc/host/mxcmmc.c |   39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)
drivers/mmc/host/mxcmmc.c +25 -14
index b2058b4..28ed52d 100644
@@ -136,7 +136,8 @@ struct mxcmci_host {
 	u16			rev_no;
 	unsigned int		cmdat;
 
-	struct clk		*clk;
+	struct clk		*clk_ipg;
+	struct clk		*clk_per;
 
 	int			clock;
 
@@ -672,7 +673,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
 {
 	unsigned int divider;
 	int prescaler = 0;
-	unsigned int clk_in = clk_get_rate(host->clk);
+	unsigned int clk_in = clk_get_rate(host->clk_per);
 
 	while (prescaler <= 0x800) {
 		for (divider = 1; divider <= 0xF; divider++) {
@@ -900,12 +901,20 @@ static int mxcmci_probe(struct platform_device *pdev)
 	host->res = r;
 	host->irq = irq;
 
-	host->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(host->clk)) {
-		ret = PTR_ERR(host->clk);
+	host->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(host->clk_ipg)) {
+		ret = PTR_ERR(host->clk_ipg);
 		goto out_iounmap;
 	}
-	clk_enable(host->clk);
+
+	host->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(host->clk_per)) {
+		ret = PTR_ERR(host->clk_per);
+		goto out_iounmap;
+	}
+
+	clk_prepare_enable(host->clk_per);
+	clk_prepare_enable(host->clk_ipg);
 
 	mxcmci_softreset(host);
 
@@ -917,8 +926,8 @@ static int mxcmci_probe(struct platform_device *pdev)
 		goto out_clk_put;
 	}
 
-	mmc->f_min = clk_get_rate(host->clk) >> 16;
-	mmc->f_max = clk_get_rate(host->clk) >> 1;
+	mmc->f_min = clk_get_rate(host->clk_per) >> 16;
+	mmc->f_max = clk_get_rate(host->clk_per) >> 1;
 
 	/* recommended in data sheet */
 	writew(0x2db4, host->base + MMC_REG_READ_TO);
@@ -967,8 +976,8 @@ out_free_dma:
 	if (host->dma)
 		dma_release_channel(host->dma);
 out_clk_put:
-	clk_disable(host->clk);
-	clk_put(host->clk);
+	clk_disable_unprepare(host->clk_per);
+	clk_disable_unprepare(host->clk_ipg);
 out_iounmap:
 	iounmap(host->base);
 out_free:
@@ -999,8 +1008,8 @@ static int mxcmci_remove(struct platform_device *pdev)
 	if (host->dma)
 		dma_release_channel(host->dma);
 
-	clk_disable(host->clk);
-	clk_put(host->clk);
+	clk_disable_unprepare(host->clk_per);
+	clk_disable_unprepare(host->clk_ipg);
 
 	release_mem_region(host->res->start, resource_size(host->res));
 
@@ -1018,7 +1027,8 @@ static int mxcmci_suspend(struct device *dev)
 
 	if (mmc)
 		ret = mmc_suspend_host(mmc);
-	clk_disable(host->clk);
+	clk_disable_unprepare(host->clk_per);
+	clk_disable_unprepare(host->clk_ipg);
 
 	return ret;
 }
@@ -1029,7 +1039,8 @@ static int mxcmci_resume(struct device *dev)
 	struct mxcmci_host *host = mmc_priv(mmc);
 	int ret = 0;
 
-	clk_enable(host->clk);
+	clk_prepare_enable(host->clk_per);
+	clk_prepare_enable(host->clk_ipg);
 	if (mmc)
 		ret = mmc_resume_host(mmc);
 
Signature · 1 line
1.7.9.5
author maintainer
#45 lore raw

PATCH 9/40 mmc sdhc i.MX: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/mmc/host/sdhci-esdhc-imx.c |   42 ++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +31 -11
index 6193a0d..938095a 100644
@@ -69,6 +69,9 @@ struct pltfm_imx_data {
 	u32 scratchpad;
 	enum imx_esdhc_type devtype;
 	struct esdhc_platform_data boarddata;
+	struct clk *clk_ipg;
+	struct clk *clk_ahb;
+	struct clk *clk_per;
 };
 
 static struct platform_device_id imx_esdhc_devtype[] = {
@@ -437,7 +440,6 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_host *host;
 	struct esdhc_platform_data *boarddata;
-	struct clk *clk;
 	int err;
 	struct pltfm_imx_data *imx_data;
 
@@ -458,14 +460,29 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	imx_data->devtype = pdev->id_entry->driver_data;
 	pltfm_host->priv = imx_data;
 
-	clk = clk_get(mmc_dev(host->mmc), NULL);
-	if (IS_ERR(clk)) {
-		dev_err(mmc_dev(host->mmc), "clk err\n");
-		err = PTR_ERR(clk);
+	imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(imx_data->clk_ipg)) {
+		err = PTR_ERR(imx_data->clk_ipg);
 		goto err_clk_get;
 	}
-	clk_prepare_enable(clk);
-	pltfm_host->clk = clk;
+
+	imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(imx_data->clk_ahb)) {
+		err = PTR_ERR(imx_data->clk_ahb);
+		goto err_clk_get;
+	}
+
+	imx_data->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(imx_data->clk_per)) {
+		err = PTR_ERR(imx_data->clk_per);
+		goto err_clk_get;
+	}
+
+	pltfm_host->clk = imx_data->clk_per;
+
+	clk_prepare_enable(imx_data->clk_per);
+	clk_prepare_enable(imx_data->clk_ipg);
+	clk_prepare_enable(imx_data->clk_ahb);
 
 	if (!is_imx25_esdhc(imx_data))
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
@@ -559,8 +576,9 @@ no_card_detect_irq:
 		gpio_free(boarddata->wp_gpio);
 no_card_detect_pin:
 no_board_data:
-	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
+	clk_disable_unprepare(imx_data->clk_per);
+	clk_disable_unprepare(imx_data->clk_ipg);
+	clk_disable_unprepare(imx_data->clk_ahb);
 err_clk_get:
 	kfree(imx_data);
 err_imx_data:
@@ -586,8 +604,10 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 		gpio_free(boarddata->cd_gpio);
 	}
 
-	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
+	clk_disable_unprepare(imx_data->clk_per);
+	clk_disable_unprepare(imx_data->clk_ipg);
+	clk_disable_unprepare(imx_data->clk_ahb);
+
 	kfree(imx_data);
 
 	sdhci_pltfm_free(pdev);
Signature · 1 line
1.7.9.5
#46 lore raw

PATCH 9/40 mmc sdhc i.MX: do not depend on grouped clocks

Quoted 78 lines · Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/mmc/host/sdhci-esdhc-imx.c |   42 ++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +24 -7
index 6193a0d..938095a 100644
@@ -69,6 +69,9 @@ struct pltfm_imx_data {
 	u32 scratchpad;
 	enum imx_esdhc_type devtype;
 	struct esdhc_platform_data boarddata;
+	struct clk *clk_ipg;
+	struct clk *clk_ahb;
+	struct clk *clk_per;
 };
 
 static struct platform_device_id imx_esdhc_devtype[] = {
@@ -437,7 +440,6 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_host *host;
 	struct esdhc_platform_data *boarddata;
-	struct clk *clk;
 	int err;
 	struct pltfm_imx_data *imx_data;
 
@@ -458,14 +460,29 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	imx_data->devtype = pdev->id_entry->driver_data;
 	pltfm_host->priv = imx_data;
 
-	clk = clk_get(mmc_dev(host->mmc), NULL);
-	if (IS_ERR(clk)) {
-		dev_err(mmc_dev(host->mmc), "clk err\n");
-		err = PTR_ERR(clk);
+	imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(imx_data->clk_ipg)) {
+		err = PTR_ERR(imx_data->clk_ipg);
 		goto err_clk_get;
 	}
-	clk_prepare_enable(clk);
-	pltfm_host->clk = clk;
+
+	imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(imx_data->clk_ahb)) {
+		err = PTR_ERR(imx_data->clk_ahb);
+		goto err_clk_get;
+	}
+
+	imx_data->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(imx_data->clk_per)) {
+		err = PTR_ERR(imx_data->clk_per);
+		goto err_clk_get;
+	}
+
+	pltfm_host->clk = imx_data->clk_per;
+
+	clk_prepare_enable(imx_data->clk_per);
+	clk_prepare_enable(imx_data->clk_ipg);
+	clk_prepare_enable(imx_data->clk_ahb);
 
 	if (!is_imx25_esdhc(imx_data))
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;

drivers/mmc/host/sdhci-esdhc-imx.c no_card_detect_irq: · line 581

Quoted 8 lines
drivers/mmc/host/sdhci-esdhc-imx.c +3 -2
@@ -559,8 +576,9 @@ no_card_detect_irq:
 		gpio_free(boarddata->wp_gpio);
 no_card_detect_pin:
 no_board_data:
-	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
+	clk_disable_unprepare(imx_data->clk_per);
+	clk_disable_unprepare(imx_data->clk_ipg);
+	clk_disable_unprepare(imx_data->clk_ahb);

You forgot to clk_put them.

drivers/mmc/host/sdhci-esdhc-imx.c static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev) · line 609

Quoted 12 lines
drivers/mmc/host/sdhci-esdhc-imx.c +3 -2
 err_clk_get:
 	kfree(imx_data);
 err_imx_data:
@@ -586,8 +604,10 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
 		gpio_free(boarddata->cd_gpio);
 	}
 
-	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
+	clk_disable_unprepare(imx_data->clk_per);
+	clk_disable_unprepare(imx_data->clk_ipg);
+	clk_disable_unprepare(imx_data->clk_ahb);

ditto

Thanks
Richard

Quoted 13 lines
drivers/mmc/host/sdhci-esdhc-imx.c +1 -0
+
 	kfree(imx_data);
 
 	sdhci_pltfm_free(pdev);
Signature · 7 lines
1.7.9.5


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#47 lore raw

PATCH 9/40 mmc sdhc i.MX: do not depend on grouped clocks

Quoted 6 lines

drivers/mmc/host/sdhci-esdhc-imx.c no_card_detect_irq: · line 581

Quoted 5 lines
drivers/mmc/host/sdhci-esdhc-imx.c +3 -2
-	clk_disable_unprepare(pltfm_host->clk);
-	clk_put(pltfm_host->clk);
+	clk_disable_unprepare(imx_data->clk_per);
+	clk_disable_unprepare(imx_data->clk_ipg);
+	clk_disable_unprepare(imx_data->clk_ahb);

You forgot to clk_put them.

Sorry, I just realized you're using the new devm_clk_get.

Richard

author maintainer
#48 lore raw

PATCH 10/40 serial i.MX: do not depend on grouped clocks

In reply to Sascha Hauer

the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks:

ipg: bus clock (needed to access registers)
ahb: dma relevant clock, sometimes referred to as hclk in the datasheet
per: bit clock, pixel clock

This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework

---
 drivers/tty/serial/imx.c |   38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)
drivers/tty/serial/imx.c +23 -15
index e7fecee..267ec6d 100644
@@ -204,7 +204,8 @@ struct imx_port {
 	unsigned int		irda_inv_rx:1;
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
-	struct clk		*clk;
+	struct clk		*clk_ipg;
+	struct clk		*clk_per;
 	struct imx_uart_data	*devdata;
 };
 
@@ -672,7 +673,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 	 * RFDIV is set such way to satisfy requested uartclk value
 	 */
 	val = TXTL << 10 | RXTL;
-	ufcr_rfdiv = (clk_get_rate(sport->clk) + sport->port.uartclk / 2)
+	ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2)
 			/ sport->port.uartclk;
 
 	if(!ufcr_rfdiv)
@@ -1285,7 +1286,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,
 		else
 			ucfr_rfdiv = 6 - ucfr_rfdiv;
 
-		uartclk = clk_get_rate(sport->clk);
+		uartclk = clk_get_rate(sport->clk_per);
 		uartclk /= ucfr_rfdiv;
 
 		{	/*
@@ -1503,14 +1504,22 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
 
-	sport->clk = clk_get(&pdev->dev, "uart");
-	if (IS_ERR(sport->clk)) {
-		ret = PTR_ERR(sport->clk);
+	sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(sport->clk_ipg)) {
+		ret = PTR_ERR(sport->clk_ipg);
 		goto unmap;
 	}
-	clk_prepare_enable(sport->clk);
 
-	sport->port.uartclk = clk_get_rate(sport->clk);
+	sport->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(sport->clk_per)) {
+		ret = PTR_ERR(sport->clk_per);
+		goto unmap;
+	}
+
+	clk_prepare_enable(sport->clk_per);
+	clk_prepare_enable(sport->clk_ipg);
+
+	sport->port.uartclk = clk_get_rate(sport->clk_per);
 
 	imx_ports[sport->port.line] = sport;
 
@@ -1531,8 +1540,8 @@ deinit:
 	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 clkput:
-	clk_disable_unprepare(sport->clk);
-	clk_put(sport->clk);
+	clk_disable_unprepare(sport->clk_per);
+	clk_disable_unprepare(sport->clk_ipg);
 unmap:
 	iounmap(sport->port.membase);
 free:
@@ -1550,11 +1559,10 @@ static int serial_imx_remove(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 
-	if (sport) {
-		uart_remove_one_port(&imx_reg, &sport->port);
-		clk_disable_unprepare(sport->clk);
-		clk_put(sport->clk);
-	}
+	uart_remove_one_port(&imx_reg, &sport->port);
+
+	clk_disable_unprepare(sport->clk_per);
+	clk_disable_unprepare(sport->clk_ipg);
 
 	if (pdata && pdata->exit)
 		pdata->exit(pdev);
Signature · 1 line
1.7.9.5
author maintainer
#49 lore raw

PATCH 11/40 mtd mxc_nand: prepare/unprepare clock

In reply to Sascha Hauer
---
 drivers/mtd/nand/mxc_nand.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/mtd/nand/mxc_nand.c +3 -3
index cc0678a..9e374e9 100644
@@ -690,7 +690,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
 	if (chip == -1) {
 		/* Disable the NFC clock */
 		if (host->clk_act) {
-			clk_disable(host->clk);
+			clk_disable_unprepare(host->clk);
 			host->clk_act = 0;
 		}
 		return;
@@ -698,7 +698,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
 
 	if (!host->clk_act) {
 		/* Enable the NFC clock */
-		clk_enable(host->clk);
+		clk_prepare_enable(host->clk);
 		host->clk_act = 1;
 	}
 
@@ -1078,7 +1078,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		goto eclk;
 	}
 
-	clk_enable(host->clk);
+	clk_prepare_enable(host->clk);
 	host->clk_act = 1;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Signature · 1 line
1.7.9.5
author maintainer
#50 lore raw

PATCH 12/40 USB ehci mxc: prepare/unprepare clock

In reply to Sascha Hauer
---
 drivers/usb/host/ehci-mxc.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/usb/host/ehci-mxc.c +9 -9
index a797d51..ae16c34 100644
@@ -171,7 +171,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 		ret = PTR_ERR(priv->usbclk);
 		goto err_clk;
 	}
-	clk_enable(priv->usbclk);
+	clk_prepare_enable(priv->usbclk);
 
 	if (!cpu_is_mx35() && !cpu_is_mx25()) {
 		priv->ahbclk = clk_get(dev, "usb_ahb");
@@ -179,7 +179,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 			ret = PTR_ERR(priv->ahbclk);
 			goto err_clk_ahb;
 		}
-		clk_enable(priv->ahbclk);
+		clk_prepare_enable(priv->ahbclk);
 	}
 
 	/* "dr" device has its own clock on i.MX51 */
@@ -189,7 +189,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 			ret = PTR_ERR(priv->phy1clk);
 			goto err_clk_phy;
 		}
-		clk_enable(priv->phy1clk);
+		clk_prepare_enable(priv->phy1clk);
 	}
 
 
@@ -266,16 +266,16 @@ err_add:
 		pdata->exit(pdev);
 err_init:
 	if (priv->phy1clk) {
-		clk_disable(priv->phy1clk);
+		clk_disable_unprepare(priv->phy1clk);
 		clk_put(priv->phy1clk);
 	}
 err_clk_phy:
 	if (priv->ahbclk) {
-		clk_disable(priv->ahbclk);
+		clk_disable_unprepare(priv->ahbclk);
 		clk_put(priv->ahbclk);
 	}
 err_clk_ahb:
-	clk_disable(priv->usbclk);
+	clk_disable_unprepare(priv->usbclk);
 	clk_put(priv->usbclk);
 err_clk:
 	iounmap(hcd->regs);
@@ -307,14 +307,14 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
 	usb_put_hcd(hcd);
 	platform_set_drvdata(pdev, NULL);
 
-	clk_disable(priv->usbclk);
+	clk_disable_unprepare(priv->usbclk);
 	clk_put(priv->usbclk);
 	if (priv->ahbclk) {
-		clk_disable(priv->ahbclk);
+		clk_disable_unprepare(priv->ahbclk);
 		clk_put(priv->ahbclk);
 	}
 	if (priv->phy1clk) {
-		clk_disable(priv->phy1clk);
+		clk_disable_unprepare(priv->phy1clk);
 		clk_put(priv->phy1clk);
 	}
 
Signature · 1 line
1.7.9.5
author maintainer
#51 lore raw

PATCH 13/40 w1 i.MX: prepare/unprepare clock

In reply to Sascha Hauer
---
 drivers/w1/masters/mxc_w1.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/w1/masters/mxc_w1.c +2 -2
index a3b6a74..1cc61a7 100644
@@ -138,7 +138,7 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev)
 		goto failed_ioremap;
 	}
 
-	clk_enable(mdev->clk);
+	clk_prepare_enable(mdev->clk);
 	__raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER);
 
 	mdev->bus_master.data = mdev;
@@ -178,7 +178,7 @@ static int __devexit mxc_w1_remove(struct platform_device *pdev)
 
 	iounmap(mdev->regs);
 	release_mem_region(res->start, resource_size(res));
-	clk_disable(mdev->clk);
+	clk_disable_unprepare(mdev->clk);
 	clk_put(mdev->clk);
 
 	platform_set_drvdata(pdev, NULL);
Signature · 1 line
1.7.9.5
author maintainer
#52 lore raw

PATCH 14/40 watchdog imx2: prepare clk before enabling it

In reply to Sascha Hauer
---
 drivers/watchdog/imx2_wdt.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/watchdog/imx2_wdt.c +1 -1
index 7a2b734..bcfab2b 100644
@@ -121,7 +121,7 @@ static void imx2_wdt_start(void)
 {
 	if (!test_and_set_bit(IMX2_WDT_STATUS_STARTED, &imx2_wdt.status)) {
 		/* at our first start we enable clock and do initialisations */
-		clk_enable(imx2_wdt.clk);
+		clk_prepare_enable(imx2_wdt.clk);
 
 		imx2_wdt_setup();
 	} else	/* delete the timer that pings the watchdog after close */
Signature · 1 line
1.7.9.5
author maintainer
#53 lore raw

PATCH 15/40 media mx3 camera: prepare clk before enabling it

In reply to Sascha Hauer
---
 drivers/media/video/mx3_camera.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/video/mx3_camera.c +2 -2
index 93c35ef..e2e33df 100644
@@ -508,7 +508,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam,
 	/* ipu_csi_init_interface() */
 	csi_reg_write(mx3_cam, conf, CSI_SENS_CONF);
 
-	clk_enable(mx3_cam->clk);
+	clk_prepare_enable(mx3_cam->clk);
 	rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk);
 	dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
 	if (rate)
@@ -549,7 +549,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
 		*ichan = NULL;
 	}
 
-	clk_disable(mx3_cam->clk);
+	clk_disable_unprepare(mx3_cam->clk);
 
 	mx3_cam->icd = NULL;
 
Signature · 1 line
1.7.9.5
author maintainer
#54 lore raw

PATCH 16/40 dmaengine i.MX ipu: clk_prepare/unprepare clock

In reply to Sascha Hauer
---
 drivers/dma/ipu/ipu_idmac.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/dma/ipu/ipu_idmac.c +3 -3
index 62e3f8e..5ec7204 100644
@@ -1715,7 +1715,7 @@ static int __init ipu_probe(struct platform_device *pdev)
 	}
 
 	/* Make sure IPU HSP clock is running */
-	clk_enable(ipu_data.ipu_clk);
+	clk_prepare_enable(ipu_data.ipu_clk);
 
 	/* Disable all interrupts */
 	idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1);
@@ -1747,7 +1747,7 @@ static int __init ipu_probe(struct platform_device *pdev)
 err_idmac_init:
 err_attach_irq:
 	ipu_irq_detach_irq(&ipu_data, pdev);
-	clk_disable(ipu_data.ipu_clk);
+	clk_disable_unprepare(ipu_data.ipu_clk);
 	clk_put(ipu_data.ipu_clk);
 err_clk_get:
 	iounmap(ipu_data.reg_ic);
@@ -1765,7 +1765,7 @@ static int __exit ipu_remove(struct platform_device *pdev)
 
 	ipu_idmac_exit(ipu);
 	ipu_irq_detach_irq(ipu, pdev);
-	clk_disable(ipu->ipu_clk);
+	clk_disable_unprepare(ipu->ipu_clk);
 	clk_put(ipu->ipu_clk);
 	iounmap(ipu->reg_ic);
 	iounmap(ipu->reg_ipu);
Signature · 1 line
1.7.9.5
author maintainer
#55 lore raw

PATCH 17/40 ARM i.MX5: prepare gpc_dvfs_clk

In reply to Sascha Hauer
---
 arch/arm/mach-imx/mm-imx5.c |    1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-imx/mm-imx5.c +1 -0
index 05250ae..d9936ce 100644
@@ -32,6 +32,7 @@ static void imx5_idle(void)
 		gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
 		if (IS_ERR(gpc_dvfs_clk))
 			return;
+		clk_prepare(gpc_dvfs_clk);
 	}
 	clk_enable(gpc_dvfs_clk);
 	mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
Signature · 1 line
1.7.9.5
author maintainer
#56 lore raw

PATCH 18/40 ARM i.MX: prepare for common clock framework

In reply to Sascha Hauer

- Add necessary #ifdefs for CONFIG_COMMON_CLOCK
- Add a global spinlock to protect the CCM registers

---
 arch/arm/mach-imx/clk.h                |   44 ++++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/clock.c              |   11 ++++++++
 arch/arm/plat-mxc/include/mach/clock.h |    4 +++
 3 files changed, 59 insertions(+)
 create mode 100644 arch/arm/mach-imx/clk.h
arch/arm/mach-imx/clk.h new file +44 -0
new file mode 100644
index 0000000..2f1a7b2
@@ -0,0 +1,44 @@
+#ifndef __MACH_IMX_CLK_H
+#define __MACH_IMX_CLK_H
+
+#include <linux/spinlock.h>
+#include <linux/clk-provider.h>
+#include <mach/clock.h>
+
+struct clk *imx_clk_pllv1(const char *name, char *parent,
+		void __iomem *base);
+
+static inline struct clk *imx_clk_fixed(const char *name, int rate)
+{
+	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *imx_clk_divider(const char *name, const char *parent,
+		void __iomem *reg, u8 shift, u8 width)
+{
+	return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+			reg, shift, width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_gate(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
+		u8 shift, u8 width, char **parents, int num_parents)
+{
+	return clk_register_mux(NULL, name, parents, num_parents, 0, reg, shift,
+			width, 0, &imx_ccm_lock);
+}
+
+static inline struct clk *imx_clk_fixed_factor(const char *name,
+		const char *parent, unsigned int mult, unsigned int div)
+{
+	return clk_register_fixed_factor(NULL, name, parent,
+			CLK_SET_RATE_PARENT, mult, div);
+}
+
+#endif
arch/arm/plat-mxc/clock.c +11 -0
index 2ed3ab1..5079787 100644
@@ -41,6 +41,7 @@
 #include <mach/clock.h>
 #include <mach/hardware.h>
 
+#ifndef CONFIG_COMMON_CLK
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
@@ -200,6 +201,16 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#else
+
+/*
+ * Lock to protect the clock module (ccm) registers. Used
+ * on all i.MXs
+ */
+DEFINE_SPINLOCK(imx_ccm_lock);
+
+#endif /* CONFIG_COMMON_CLK */
+
 /*
  * Get the resulting clock rate from a PLL register value and the input
  * frequency. PLLs with this register layout can at least be found on
arch/arm/plat-mxc/include/mach/clock.h +4 -0
index 753a598..bd940c7 100644
@@ -23,6 +23,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/list.h>
 
+#ifndef CONFIG_COMMON_CLK
 struct module;
 
 struct clk {
@@ -59,6 +60,9 @@ struct clk {
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
+#endif /* CONFIG_COMMON_CLK */
+
+extern spinlock_t imx_ccm_lock;
 
 unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
 
Signature · 1 line
1.7.9.5
author maintainer
#57 lore raw

PATCH 19/40 ARM i.MX timer: request correct clock

In reply to Sascha Hauer

We used to pass the timer clock directly to mxc_timer_init. We should instead request the correct clock. This is an intermediate
step: For now we request the clock in the timer code when NULL is passed as clock.
Also, the gpt on some i.MX have an additional ipg clock which can be gated. Request and enable this.

---
 arch/arm/plat-mxc/time.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)
arch/arm/plat-mxc/time.c +14 -0
index 7daf7c9..99f958c 100644
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/clockchips.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <mach/hardware.h>
 #include <asm/sched_clock.h>
@@ -282,6 +283,19 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
 void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
 {
 	uint32_t tctl_val;
+	struct clk *timer_ipg_clk;
+
+	if (!timer_clk) {
+		timer_clk = clk_get_sys("imx-gpt.0", "per");
+		if (IS_ERR(timer_clk)) {
+			pr_err("i.MX timer: unable to get clk\n");
+			return;
+		}
+
+		timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
+		if (!IS_ERR(timer_ipg_clk))
+			clk_prepare_enable(timer_ipg_clk);
+	}
 
 	clk_prepare_enable(timer_clk);
 
Signature · 1 line
1.7.9.5
author maintainer
#58 lore raw

PATCH 20/40 ARM i.MX: Add common clock support for pllv1

In reply to Sascha Hauer

The pllv1 is found on i.MX1, i.M25, i.MX27, i.MX31 and i.MX35. Currently only reading the rate is supported.

---
 arch/arm/mach-imx/Makefile    |    2 ++
 arch/arm/mach-imx/clk-pllv1.c |   59 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 arch/arm/mach-imx/clk-pllv1.c
arch/arm/mach-imx/Makefile +2 -0
index ab939c5..7e71b39 100644
@@ -11,6 +11,8 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
arch/arm/mach-imx/clk-pllv1.c new file +59 -0

59 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#59 lore raw

PATCH 21/40 ARM i.MX: Add common clock support for pllv2

In reply to Sascha Hauer

This PLL is found on i.MX51 and i.MX53

---
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-pllv2.c |  243 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h       |    3 +
 3 files changed, 247 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-pllv2.c
arch/arm/mach-imx/Makefile +1 -1
index 7e71b39..0c0e5c4 100644
@@ -11,7 +11,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
-obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-pllv2.c new file +243 -0

243 lines not on this page · raw message

arch/arm/mach-imx/clk.h +3 -0
index 2f1a7b2..7897d5b 100644
@@ -8,6 +8,9 @@
 struct clk *imx_clk_pllv1(const char *name, char *parent,
 		void __iomem *base);
 
+struct clk *imx_clk_pllv2(const char *name, char *parent,
+		void __iomem *base);
+
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
 {
 	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
Signature · 1 line
1.7.9.5
author maintainer
#60 lore raw

PATCH 22/40 ARM: imx: add common clock support for pllv3

In reply to Sascha Hauer

From: Shawn Guo <[email protected]>

This PLL is found on i.MX6 SoCs

---
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-pllv3.c |  408 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h       |   13 ++
 3 files changed, 422 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-pllv3.c
arch/arm/mach-imx/Makefile +1 -1
index 0c0e5c4..66bc6be 100644
@@ -11,7 +11,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
-obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-pllv3.c new file +408 -0

408 lines not on this page · raw message

arch/arm/mach-imx/clk.h +13 -0
index 7897d5b..96ac3b1 100644
@@ -5,12 +5,25 @@
 #include <linux/clk-provider.h>
 #include <mach/clock.h>
 
+enum imx_pllv3_type {
+	IMX_PLLV3_GENERIC,
+	IMX_PLLV3_SYS,
+	IMX_PLLV3_USB,
+	IMX_PLLV3_AV,
+	IMX_PLLV3_ENET,
+	IMX_PLLV3_MLB,
+};
+
 struct clk *imx_clk_pllv1(const char *name, char *parent,
 		void __iomem *base);
 
 struct clk *imx_clk_pllv2(const char *name, char *parent,
 		void __iomem *base);
 
+struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
+		char *parent_name, void __iomem *base, u32 gate_mask,
+		u32 div_mask);
+
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
 {
 	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
Signature · 1 line
1.7.9.5
author maintainer
#61 lore raw

PATCH 23/40 ARM i.MX: Add common clock support for 2bit gate

In reply to Sascha Hauer

This gate consists of two bits:

0b00: clk disabled
0b01: clk enabled in run mode and disabled in sleep mode 0b11: clk enabled

Currently only disabled and enabled are supported. As it's unlikely that we find something like this in another SoC create a i.MX specific clk helper for this.

---
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-gate2.c |  125 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h       |   12 ++++
 3 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/Makefile +1 -1
index 66bc6be..1b3f2ae 100644
@@ -11,7 +11,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
-obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-gate2.c new file +125 -0

125 lines not on this page · raw message

arch/arm/mach-imx/clk.h +12 -0
index 96ac3b1..fb44f03 100644
@@ -5,6 +5,11 @@
 #include <linux/clk-provider.h>
 #include <mach/clock.h>
 
+struct clk *clk_register_gate2(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock);
+
 enum imx_pllv3_type {
 	IMX_PLLV3_GENERIC,
 	IMX_PLLV3_SYS,
@@ -43,6 +48,13 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 			shift, 0, &imx_ccm_lock);
 }
 
+static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
+		void __iomem *reg, u8 shift)
+{
+	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, 0, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 		u8 shift, u8 width, char **parents, int num_parents)
 {
Signature · 1 line
1.7.9.5
#62 lore raw

PATCH 23/40 ARM i.MX: Add common clock support for 2bit gate

On Tue, Apr 10, 2012 at 03:45:36PM +0200, Sascha Hauer wrote:
[snip]

Quoted 22 lines
arch/arm/mach-imx/clk-gate2.c new file +22 -0
+struct clk *clk_register_gate2(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate2_flags, spinlock_t *lock)
+{
+	struct clk_gate *gate;
+	struct clk *clk;
+
+	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+	if (!gate) {
+		pr_err("%s: could not allocate gated clk\n", __func__);
+		return NULL;
+	}
+
+	/* struct clk_gate assignments */
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate2_flags;
+	gate->lock = lock;
+
+	if (parent_name) {

arch/arm/mach-imx/clk-gate2.c line 117

Quoted 10 lines
arch/arm/mach-imx/clk-gate2.c new file +10 -0
+		gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+		if (!gate->parent[0])
+			goto out;
+	}
+
+	clk = clk_register(dev, name,
+			&clk_gate2_ops, &gate->hw,
+			gate->parent,
+			(parent_name ? 1 : 0),
+			flags);

Why do you re-use struct clk_gate while you don't use clk_gate_ops? It doesn't follow object oriented thought. struct clk_gate may change according to clk_gate_ops changes.

Thanks
Richard

#63 lore raw

PATCH 23/40 ARM i.MX: Add common clock support for 2bit gate

Sorry Shawn, I steal your name :) . Last mail is from me.

Richard

#64 lore raw

PATCH 23/40 ARM i.MX: Add common clock support for 2bit gate

In reply to Shawn Guo
Quoted 38 lines · Shawn Guo

On Tue, Apr 10, 2012 at 03:45:36PM +0200, Sascha Hauer wrote:
[snip]

Quoted 22 lines
(quoted diff) +22 -0
+struct clk *clk_register_gate2(struct device *dev, const char *name,
+ ? ? ? ? ? ? const char *parent_name, unsigned long flags,
+ ? ? ? ? ? ? void __iomem *reg, u8 bit_idx,
+ ? ? ? ? ? ? u8 clk_gate2_flags, spinlock_t *lock)
+{
+ ? ? struct clk_gate *gate;
+ ? ? struct clk *clk;
+
+ ? ? gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+ ? ? if (!gate) {
+ ? ? ? ? ? ? pr_err("%s: could not allocate gated clk\n", __func__);
+ ? ? ? ? ? ? return NULL;
+ ? ? }
+
+ ? ? /* struct clk_gate assignments */
+ ? ? gate->reg = reg;
+ ? ? gate->bit_idx = bit_idx;
+ ? ? gate->flags = clk_gate2_flags;
+ ? ? gate->lock = lock;
+
+ ? ? if (parent_name) {

Review

Quoted 10 lines
(quoted diff) +10 -0
+ ? ? ? ? ? ? gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+ ? ? ? ? ? ? if (!gate->parent[0])
+ ? ? ? ? ? ? ? ? ? ? goto out;
+ ? ? }
+
+ ? ? clk = clk_register(dev, name,
+ ? ? ? ? ? ? ? ? ? ? &clk_gate2_ops, &gate->hw,
+ ? ? ? ? ? ? ? ? ? ? gate->parent,
+ ? ? ? ? ? ? ? ? ? ? (parent_name ? 1 : 0),
+ ? ? ? ? ? ? ? ? ? ? flags);

Why do you re-use struct clk_gate while you don't use clk_gate_ops? It doesn't follow object oriented thought. struct clk_gate may change according to clk_gate_ops changes.

Quoted 5 lines

Thanks
Richard

Why not expend original clk-gate.c to allow set more than one bit a time to gate that clock?
At least in my platform, some clock need 12bit to get its gate mode, which means that module
has more than one clock concurrently up to work, and only a part of that group work cannot lead
to a correct working mode. This also means those bits need to turn on/off at the same time.

Thanks,
Lei

#65 lore raw

PATCH 23/40 ARM i.MX: Add common clock support for 2bit gate

Quoted 45 lines · Lei Wen
Quoted 38 lines · Shawn Guo

On Tue, Apr 10, 2012 at 03:45:36PM +0200, Sascha Hauer wrote:
[snip]

Quoted 22 lines
(quoted diff) +22 -0
+struct clk *clk_register_gate2(struct device *dev, const char *name,
+ ? ? ? ? ? ? const char *parent_name, unsigned long flags,
+ ? ? ? ? ? ? void __iomem *reg, u8 bit_idx,
+ ? ? ? ? ? ? u8 clk_gate2_flags, spinlock_t *lock)
+{
+ ? ? struct clk_gate *gate;
+ ? ? struct clk *clk;
+
+ ? ? gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+ ? ? if (!gate) {
+ ? ? ? ? ? ? pr_err("%s: could not allocate gated clk\n", __func__);
+ ? ? ? ? ? ? return NULL;
+ ? ? }
+
+ ? ? /* struct clk_gate assignments */
+ ? ? gate->reg = reg;
+ ? ? gate->bit_idx = bit_idx;
+ ? ? gate->flags = clk_gate2_flags;
+ ? ? gate->lock = lock;
+
+ ? ? if (parent_name) {

Review

Quoted 10 lines
(quoted diff) +10 -0
+ ? ? ? ? ? ? gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+ ? ? ? ? ? ? if (!gate->parent[0])
+ ? ? ? ? ? ? ? ? ? ? goto out;
+ ? ? }
+
+ ? ? clk = clk_register(dev, name,
+ ? ? ? ? ? ? ? ? ? ? &clk_gate2_ops, &gate->hw,
+ ? ? ? ? ? ? ? ? ? ? gate->parent,
+ ? ? ? ? ? ? ? ? ? ? (parent_name ? 1 : 0),
+ ? ? ? ? ? ? ? ? ? ? flags);

Why do you re-use struct clk_gate while you don't use clk_gate_ops? It doesn't follow object oriented thought. struct clk_gate may change according to clk_gate_ops changes.

Quoted 5 lines

Thanks
Richard

Quoted 8 lines

Why not expend original clk-gate.c to allow set more than one bit a time to gate that clock?
At least in my platform, some clock need 12bit to get its gate mode, which means that module
has more than one clock concurrently up to work, and only a part of that group work cannot lead
to a correct working mode. This also means those bits need to turn on/off at the same time.

I would also need a double gate, one reg to enable and one to disable, both or-ing the same bitmask. I think this can be addressed in the flags but what about a union to store the different regs, widths, shifts?

thanks,
Domenico

author maintainer
#66 lore raw

PATCH 24/40 ARM: imx: add common clock support for pfd

In reply to Sascha Hauer

From: Shawn Guo <[email protected]>

---
 arch/arm/mach-imx/Makefile  |    3 +-
 arch/arm/mach-imx/clk-pfd.c |  138 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h     |    3 +
 3 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-pfd.c
arch/arm/mach-imx/Makefile +2 -1
index 1b3f2ae..4d6be8d 100644
@@ -11,7 +11,8 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
-obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o
+obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
+			    clk-pfd.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-pfd.c new file +138 -0

138 lines not on this page · raw message

arch/arm/mach-imx/clk.h +3 -0
index fb44f03..50f5638 100644
@@ -29,6 +29,9 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 		char *parent_name, void __iomem *base, u32 gate_mask,
 		u32 div_mask);
 
+struct clk *imx_clk_pfd(const char *name, char *parent_name,
+		void __iomem *reg, u8 idx);
+
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
 {
 	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
Signature · 1 line
1.7.9.5
author maintainer
#67 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

In reply to Sascha Hauer

From: Shawn Guo <[email protected]>

---
 arch/arm/mach-imx/Makefile   |    2 +-
 arch/arm/mach-imx/clk-busy.c |  167 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h      |    8 ++
 3 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/Makefile +1 -1
index 4d6be8d..ae0a779 100644
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
-			    clk-pfd.o
+			    clk-pfd.o clk-busy.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-busy.c new file +167 -0

167 lines not on this page · raw message

arch/arm/mach-imx/clk.h +8 -0
index 50f5638..53ab2f5 100644
@@ -44,6 +44,10 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent,
 			reg, shift, width, 0, &imx_ccm_lock);
 }
 
+struct clk *imx_clk_busy_divider(const char *name, char *parent_name,
+				 void __iomem *reg, u8 shift, u8 width,
+				 void __iomem *busy_reg, u8 busy_shift);
+
 static inline struct clk *imx_clk_gate(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
@@ -65,6 +69,10 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
 			width, 0, &imx_ccm_lock);
 }
 
+struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
+			     u8 width, void __iomem *busy_reg, u8 busy_shift,
+			     char **parent_names, int num_parents);
+
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
Signature · 1 line
1.7.9.5
#68 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

arch/arm/mach-imx/clk-busy.c line 29

Quoted 10 lines · Sascha Hauer
arch/arm/mach-imx/clk-busy.c new file +10 -0
+static int clk_busy_wait(void __iomem *reg, u8 shift)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	while (readl_relaxed(reg) & (1 << shift))
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+	return 0;
+}

MSM also has a bit to poll to see if a clock is enabled or not, similar to this rate switch complete bit. Would it make sense to have another few clock ops like wait_for_enable(), wait_for_rate(), wait_for_disable()? Then you should be able to copy the basic divider ops and assign the wait ops and avoid the wrappers.

Also, why are these drivers in arch/arm? Shouldn't we be putting all clock drivers into drivers/clk/ now?

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
author maintainer
#69 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

Quoted 17 lines · Stephen Boyd

arch/arm/mach-imx/clk-busy.c line 29

Quoted 10 lines · Sascha Hauer
arch/arm/mach-imx/clk-busy.c new file +10 -0
+static int clk_busy_wait(void __iomem *reg, u8 shift)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	while (readl_relaxed(reg) & (1 << shift))
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+	return 0;
+}

MSM also has a bit to poll to see if a clock is enabled or not, similar to this rate switch complete bit. Would it make sense to have another few clock ops like wait_for_enable(), wait_for_rate(), wait_for_disable()? Then you should be able to copy the basic divider ops and assign the wait ops and avoid the wrappers.

I think this won't work. What arguments would your wait_for_* functions take?

Quoted 3 lines

Also, why are these drivers in arch/arm? Shouldn't we be putting all clock drivers into drivers/clk/ now?

The last time this topic came up this was not entirely clear. Personally I do not have a preference.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#70 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

Quoted 17 lines · Sascha Hauer
Quoted 16 lines · Stephen Boyd

arch/arm/mach-imx/clk-busy.c line 29

Quoted 10 lines · Sascha Hauer
arch/arm/mach-imx/clk-busy.c new file +10 -0
+static int clk_busy_wait(void __iomem *reg, u8 shift)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	while (readl_relaxed(reg) & (1 << shift))
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+	return 0;
+}

MSM also has a bit to poll to see if a clock is enabled or not, similar to this rate switch complete bit. Would it make sense to have another few clock ops like wait_for_enable(), wait_for_rate(), wait_for_disable()? Then you should be able to copy the basic divider ops and assign the wait ops and avoid the wrappers.

Quoted 2 lines

I think this won't work. What arguments would your wait_for_* functions take?

I assume the same as what all the other ops take.

wait_for_disable(struct clk_hw *hw)
wait_for_enable(struct clk_hw *hw)
wait_for_rate(struct clk_hw *hw)

Do you see the need for anything else?

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#71 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

Quoted 21 lines · Stephen Boyd
Quoted 17 lines · Sascha Hauer
Quoted 16 lines · Stephen Boyd

arch/arm/mach-imx/clk-busy.c line 29

Quoted 10 lines · Sascha Hauer
arch/arm/mach-imx/clk-busy.c new file +10 -0
+static int clk_busy_wait(void __iomem *reg, u8 shift)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	while (readl_relaxed(reg) & (1 << shift))
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+
+	return 0;
+}

MSM also has a bit to poll to see if a clock is enabled or not, similar to this rate switch complete bit. Would it make sense to have another few clock ops like wait_for_enable(), wait_for_rate(), wait_for_disable()? Then you should be able to copy the basic divider ops and assign the wait ops and avoid the wrappers.

Quoted 2 lines

I think this won't work. What arguments would your wait_for_* functions take?

Quoted 8 lines

I assume the same as what all the other ops take.

wait_for_disable(struct clk_hw *hw)
wait_for_enable(struct clk_hw *hw)
wait_for_rate(struct clk_hw *hw)

Do you see the need for anything else?

I guess Sascha is asking what arguments the particular clk registration function need to take for implementing those wait_for_* ops.

For clk_gate example, besides the existing parameters that clk_register_gate already takes, it needs to take more, probably reg_busy, bit_busy, timeout at least. And we need the same for clk_divider and clk_mux. (Yes, I have clks that need to wait for busy when changing divider and parent.)

Having basic clks support that will definitely reduce the clock driver code, but it will make the long parameter list of basic clks even longer. I do not know which way we should go.

Signature · 2 lines
Regards,
Shawn
#72 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

In reply to Sascha Hauer
Quoted 56 lines · Sascha Hauer

From: Shawn Guo <[email protected]>

---
 arch/arm/mach-imx/Makefile   |    2 +-
 arch/arm/mach-imx/clk-busy.c |  167 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h      |    8 ++
 3 files changed, 176 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/Makefile +1 -1
index 4d6be8d..ae0a779 100644
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-i
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
-			    clk-pfd.o
+			    clk-pfd.o clk-busy.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
arch/arm/mach-imx/clk-busy.c new file +27 -0
new file mode 100644
index 0000000..9450f0b
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include "clk.h"
+
+static int clk_busy_wait(void __iomem *reg, u8 shift)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	while (readl_relaxed(reg) & (1 << shift))
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+

arch/arm/mach-imx/clk-busy.c line 37

Quoted 10 lines
arch/arm/mach-imx/clk-busy.c new file +10 -0
+	return 0;
+}
+
+struct clk_busy_divider {
+	struct clk_hw hw;
+	void __iomem *reg;
+	u8 shift;
+	struct clk_divider div;
+	const struct clk_ops *div_ops;
+};

It's not like a good way to inherit from struct clk_divider. Since we already have struct clk_hw in struct clk_divider, why do you still duplicate hw here?

BRs
Richard

#73 lore raw

PATCH 25/40 ARM: imx: add common clock support for clk busy

On Thu, Apr 12, 2012 at 09:50:14AM +0800, Richard Zhao wrote:
...

Quoted 8 lines

arch/arm/mach-imx/clk-busy.c line 37

Quoted 7 lines
arch/arm/mach-imx/clk-busy.c new file +7 -0
+struct clk_busy_divider {
+	struct clk_hw hw;
+	void __iomem *reg;
+	u8 shift;
+	struct clk_divider div;
+	const struct clk_ops *div_ops;
+};

It's not like a good way to inherit from struct clk_divider.

Any good way to suggest?

Quoted 4 lines

Since we
already have struct clk_hw in struct clk_divider, why do you still duplicate hw here?

I can use the clk_hw in clk_divider, but it will make the translation from clk_hw to clk_busy_divider a bit more complicated. And in any case, clk_busy_divider is a particular type of clk, so it should not be surprising to have a its own clk_hw like any other clks.

Signature · 2 lines
Regards,
Shawn
#74 lore raw

PATCH 1/1 ARM: imx: remove clk_hw from clk_busy

In reply to Sascha Hauer

---
Hi Sascha,

I'm convinced by Richard that we do not need a clk_hw duplication in clk_busy for a better OOP view. So please consider to squash the patch to "ARM: imx: add common clock support for clk busy".

Thanks,
Shawn

 arch/arm/mach-imx/clk-busy.c |   32 ++++++++++++++++++--------------
 1 files changed, 18 insertions(+), 14 deletions(-)
arch/arm/mach-imx/clk-busy.c +18 -14
index 9450f0b..977d50a 100644
@@ -29,14 +29,18 @@ static int clk_busy_wait(void __iomem *reg, u8 shift)
 }
 
 struct clk_busy_divider {
-	struct clk_hw hw;
-	void __iomem *reg;
-	u8 shift;
 	struct clk_divider div;
 	const struct clk_ops *div_ops;
+	void __iomem *reg;
+	u8 shift;
 };
 
-#define to_clk_busy_divider(_hw) container_of(_hw, struct clk_busy_divider, hw)
+static inline struct clk_busy_divider *to_clk_busy_divider(struct clk_hw *hw)
+{
+	struct clk_divider *div = container_of(hw, struct clk_divider, hw);
+
+	return container_of(div, struct clk_busy_divider, div);
+}
 
 static unsigned long clk_busy_divider_recalc_rate(struct clk_hw *hw,
 						  unsigned long parent_rate)
@@ -92,25 +96,27 @@ struct clk *imx_clk_busy_divider(const char *name, char *parent_name,
 	busy->div.lock = &imx_ccm_lock;
 	busy->div_ops = &clk_divider_ops;
 
-	clk = clk_register(NULL, name, &clk_busy_divider_ops, &busy->hw,
+	clk = clk_register(NULL, name, &clk_busy_divider_ops, &busy->div.hw,
 			   &parent_name, 1, CLK_SET_RATE_PARENT);
 	if (!clk)
 		kfree(busy);
 
-	busy->div.hw.clk = clk;
-
 	return clk;
 }
 
 struct clk_busy_mux {
-	struct clk_hw hw;
-	void __iomem *reg;
-	u8 shift;
 	struct clk_mux mux;
 	const struct clk_ops *mux_ops;
+	void __iomem *reg;
+	u8 shift;
 };
 
-#define to_clk_busy_mux(_hw) container_of(_hw, struct clk_busy_mux, hw)
+static inline struct clk_busy_mux *to_clk_busy_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
+
+	return container_of(mux, struct clk_busy_mux, mux);
+}
 
 static u8 clk_busy_mux_get_parent(struct clk_hw *hw)
 {
@@ -156,12 +162,10 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 	busy->mux.lock = &imx_ccm_lock;
 	busy->mux_ops = &clk_mux_ops;
 
-	clk = clk_register(NULL, name, &clk_busy_mux_ops, &busy->hw,
+	clk = clk_register(NULL, name, &clk_busy_mux_ops, &busy->mux.hw,
 			   parent_names, num_parents, 0);
 	if (!clk)
 		kfree(busy);
 
-	busy->mux.hw.clk = clk;
-
 	return clk;
 }
Signature · 1 line
1.7.5.4
author maintainer
#75 lore raw

PATCH 1/1 ARM: imx: remove clk_hw from clk_busy

Quoted 7 lines · Shawn Guo

---
Hi Sascha,

I'm convinced by Richard that we do not need a clk_hw duplication in clk_busy for a better OOP view. So please consider to squash the patch to "ARM: imx: add common clock support for clk busy".

Ok, will do.

Thanks
Sascha

Quoted 87 lines

Thanks,
Shawn

 arch/arm/mach-imx/clk-busy.c |   32 ++++++++++++++++++--------------
 1 files changed, 18 insertions(+), 14 deletions(-)
arch/arm/mach-imx/clk-busy.c +18 -14
index 9450f0b..977d50a 100644
@@ -29,14 +29,18 @@ static int clk_busy_wait(void __iomem *reg, u8 shift)
 }
 
 struct clk_busy_divider {
-	struct clk_hw hw;
-	void __iomem *reg;
-	u8 shift;
 	struct clk_divider div;
 	const struct clk_ops *div_ops;
+	void __iomem *reg;
+	u8 shift;
 };
 
-#define to_clk_busy_divider(_hw) container_of(_hw, struct clk_busy_divider, hw)
+static inline struct clk_busy_divider *to_clk_busy_divider(struct clk_hw *hw)
+{
+	struct clk_divider *div = container_of(hw, struct clk_divider, hw);
+
+	return container_of(div, struct clk_busy_divider, div);
+}
 
 static unsigned long clk_busy_divider_recalc_rate(struct clk_hw *hw,
 						  unsigned long parent_rate)
@@ -92,25 +96,27 @@ struct clk *imx_clk_busy_divider(const char *name, char *parent_name,
 	busy->div.lock = &imx_ccm_lock;
 	busy->div_ops = &clk_divider_ops;
 
-	clk = clk_register(NULL, name, &clk_busy_divider_ops, &busy->hw,
+	clk = clk_register(NULL, name, &clk_busy_divider_ops, &busy->div.hw,
 			   &parent_name, 1, CLK_SET_RATE_PARENT);
 	if (!clk)
 		kfree(busy);
 
-	busy->div.hw.clk = clk;
-
 	return clk;
 }
 
 struct clk_busy_mux {
-	struct clk_hw hw;
-	void __iomem *reg;
-	u8 shift;
 	struct clk_mux mux;
 	const struct clk_ops *mux_ops;
+	void __iomem *reg;
+	u8 shift;
 };
 
-#define to_clk_busy_mux(_hw) container_of(_hw, struct clk_busy_mux, hw)
+static inline struct clk_busy_mux *to_clk_busy_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux = container_of(hw, struct clk_mux, hw);
+
+	return container_of(mux, struct clk_busy_mux, mux);
+}
 
 static u8 clk_busy_mux_get_parent(struct clk_hw *hw)
 {
@@ -156,12 +162,10 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 	busy->mux.lock = &imx_ccm_lock;
 	busy->mux_ops = &clk_mux_ops;
 
-	clk = clk_register(NULL, name, &clk_busy_mux_ops, &busy->hw,
+	clk = clk_register(NULL, name, &clk_busy_mux_ops, &busy->mux.hw,
 			   parent_names, num_parents, 0);
 	if (!clk)
 		kfree(busy);
 
-	busy->mux.hw.clk = clk;
-
 	return clk;
 }
Signature · 1 line
1.7.5.4
Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#76 lore raw

PATCH 26/40 ARM i.MX3: Make ccm base address a variable

In reply to Sascha Hauer

Instead of having a cpu_is_* in each ccm register access it is mor efficient to make it a variable.

---
 arch/arm/mach-imx/crmregs-imx3.h |   79 +++++++++++++++++++-------------------
 arch/arm/mach-imx/mm-imx3.c      |    6 +++
 arch/arm/mach-imx/pm-imx3.c      |    4 +-
 3 files changed, 47 insertions(+), 42 deletions(-)
arch/arm/mach-imx/crmregs-imx3.h +39 -40
index 5314127..a1dfde5 100644
@@ -24,48 +24,47 @@
 #define CKIH_CLK_FREQ_27MHZ     27000000
 #define CKIL_CLK_FREQ           32768
 
-#define MXC_CCM_BASE		(cpu_is_mx31() ? \
-MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR) : MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR))
+extern void __iomem *mx3_ccm_base;
 
 /* Register addresses */
-#define MXC_CCM_CCMR		(MXC_CCM_BASE + 0x00)
-#define MXC_CCM_PDR0		(MXC_CCM_BASE + 0x04)
-#define MXC_CCM_PDR1		(MXC_CCM_BASE + 0x08)
-#define MX35_CCM_PDR2		(MXC_CCM_BASE + 0x0C)
-#define MXC_CCM_RCSR		(MXC_CCM_BASE + 0x0C)
-#define MX35_CCM_PDR3		(MXC_CCM_BASE + 0x10)
-#define MXC_CCM_MPCTL		(MXC_CCM_BASE + 0x10)
-#define MX35_CCM_PDR4		(MXC_CCM_BASE + 0x14)
-#define MXC_CCM_UPCTL		(MXC_CCM_BASE + 0x14)
-#define MX35_CCM_RCSR		(MXC_CCM_BASE + 0x18)
-#define MXC_CCM_SRPCTL		(MXC_CCM_BASE + 0x18)
-#define MX35_CCM_MPCTL		(MXC_CCM_BASE + 0x1C)
-#define MXC_CCM_COSR		(MXC_CCM_BASE + 0x1C)
-#define MX35_CCM_PPCTL		(MXC_CCM_BASE + 0x20)
-#define MXC_CCM_CGR0		(MXC_CCM_BASE + 0x20)
-#define MX35_CCM_ACMR		(MXC_CCM_BASE + 0x24)
-#define MXC_CCM_CGR1		(MXC_CCM_BASE + 0x24)
-#define MX35_CCM_COSR		(MXC_CCM_BASE + 0x28)
-#define MXC_CCM_CGR2		(MXC_CCM_BASE + 0x28)
-#define MX35_CCM_CGR0		(MXC_CCM_BASE + 0x2C)
-#define MXC_CCM_WIMR		(MXC_CCM_BASE + 0x2C)
-#define MX35_CCM_CGR1		(MXC_CCM_BASE + 0x30)
-#define MXC_CCM_LDC		(MXC_CCM_BASE + 0x30)
-#define MX35_CCM_CGR2		(MXC_CCM_BASE + 0x34)
-#define MXC_CCM_DCVR0		(MXC_CCM_BASE + 0x34)
-#define MX35_CCM_CGR3		(MXC_CCM_BASE + 0x38)
-#define MXC_CCM_DCVR1		(MXC_CCM_BASE + 0x38)
-#define MXC_CCM_DCVR2		(MXC_CCM_BASE + 0x3C)
-#define MXC_CCM_DCVR3		(MXC_CCM_BASE + 0x40)
-#define MXC_CCM_LTR0		(MXC_CCM_BASE + 0x44)
-#define MXC_CCM_LTR1		(MXC_CCM_BASE + 0x48)
-#define MXC_CCM_LTR2		(MXC_CCM_BASE + 0x4C)
-#define MXC_CCM_LTR3		(MXC_CCM_BASE + 0x50)
-#define MXC_CCM_LTBR0		(MXC_CCM_BASE + 0x54)
-#define MXC_CCM_LTBR1		(MXC_CCM_BASE + 0x58)
-#define MXC_CCM_PMCR0		(MXC_CCM_BASE + 0x5C)
-#define MXC_CCM_PMCR1		(MXC_CCM_BASE + 0x60)
-#define MXC_CCM_PDR2		(MXC_CCM_BASE + 0x64)
+#define MXC_CCM_CCMR		0x00
+#define MXC_CCM_PDR0		0x04
+#define MXC_CCM_PDR1		0x08
+#define MX35_CCM_PDR2		0x0C
+#define MXC_CCM_RCSR		0x0C
+#define MX35_CCM_PDR3		0x10
+#define MXC_CCM_MPCTL		0x10
+#define MX35_CCM_PDR4		0x14
+#define MXC_CCM_UPCTL		0x14
+#define MX35_CCM_RCSR		0x18
+#define MXC_CCM_SRPCTL		0x18
+#define MX35_CCM_MPCTL		0x1C
+#define MXC_CCM_COSR		0x1C
+#define MX35_CCM_PPCTL		0x20
+#define MXC_CCM_CGR0		0x20
+#define MX35_CCM_ACMR		0x24
+#define MXC_CCM_CGR1		0x24
+#define MX35_CCM_COSR		0x28
+#define MXC_CCM_CGR2		0x28
+#define MX35_CCM_CGR0		0x2C
+#define MXC_CCM_WIMR		0x2C
+#define MX35_CCM_CGR1		0x30
+#define MXC_CCM_LDC		0x30
+#define MX35_CCM_CGR2		0x34
+#define MXC_CCM_DCVR0		0x34
+#define MX35_CCM_CGR3		0x38
+#define MXC_CCM_DCVR1		0x38
+#define MXC_CCM_DCVR2		0x3C
+#define MXC_CCM_DCVR3		0x40
+#define MXC_CCM_LTR0		0x44
+#define MXC_CCM_LTR1		0x48
+#define MXC_CCM_LTR2		0x4C
+#define MXC_CCM_LTR3		0x50
+#define MXC_CCM_LTBR0		0x54
+#define MXC_CCM_LTBR1		0x58
+#define MXC_CCM_PMCR0		0x5C
+#define MXC_CCM_PMCR1		0x60
+#define MXC_CCM_PDR2		0x64
 
 /* Register bit definitions */
 #define MXC_CCM_CCMR_WBEN                       (1 << 27)
arch/arm/mach-imx/mm-imx3.c +6 -0
index 7412738..57b39f8 100644
@@ -31,6 +31,10 @@
 #include <mach/iomux-v3.h>
 #include <mach/irqs.h>
 
+#include "crmregs-imx3.h"
+
+void __iomem *mx3_ccm_base;
+
 static void imx3_idle(void)
 {
 	unsigned long reg = 0;
@@ -137,6 +141,7 @@ void __init imx31_init_early(void)
 	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
 	arch_ioremap_caller = imx3_ioremap_caller;
 	arm_pm_idle = imx3_idle;
+	mx3_ccm_base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
 }
 
 void __init mx31_init_irq(void)
@@ -210,6 +215,7 @@ void __init imx35_init_early(void)
 	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
 	arm_pm_idle = imx3_idle;
 	arch_ioremap_caller = imx3_ioremap_caller;
+	mx3_ccm_base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
 }
 
 void __init mx35_init_irq(void)
arch/arm/mach-imx/pm-imx3.c +2 -2
index b375243..822103b 100644
@@ -21,14 +21,14 @@
  */
 void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode)
 {
-	int reg = __raw_readl(MXC_CCM_CCMR);
+	int reg = __raw_readl(mx3_ccm_base + MXC_CCM_CCMR);
 	reg &= ~MXC_CCM_CCMR_LPM_MASK;
 
 	switch (mode) {
 	case MX3_WAIT:
 		if (cpu_is_mx35())
 			reg |= MXC_CCM_CCMR_LPM_WAIT_MX35;
-		__raw_writel(reg, MXC_CCM_CCMR);
+		__raw_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
 		break;
 	default:
 		pr_err("Unknown cpu power mode: %d\n", mode);
Signature · 1 line
1.7.9.5
author maintainer
#77 lore raw

PATCH 27/40 ARM i.MX25: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx25.c |  232 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/Kconfig +1 -0
index 7561eca..0b832b1 100644
@@ -48,6 +48,7 @@ config SOC_IMX21
 config SOC_IMX25
 	bool
 	select ARCH_MX25
+	select COMMON_CLK
 	select CPU_ARM926T
 	select ARCH_MXC_IOMUX_V3
 	select MXC_AVIC
arch/arm/mach-imx/Makefile +1 -1
index ae0a779..173e869 100644
@@ -1,7 +1,7 @@
 obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_SOC_IMX25) += clock-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
arch/arm/mach-imx/clk-imx25.c new file +232 -0

232 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#78 lore raw

PATCH 27/40 ARM i.MX25: implement clocks using common clock framework

Hi

Just a small comment below:

Quoted 33 lines

+static struct clk_lookup lookups[] = {
+ ? ? ? /* i.mx25 has the i.mx21 type uart */
+ ? ? ? clkdev("imx21-uart.0", "ipg", "uart1_ipg")
+ ? ? ? clkdev("imx21-uart.0", "per", "uart_ipg_per")
+ ? ? ? clkdev("imx21-uart.1", "ipg", "uart2_ipg")
+ ? ? ? clkdev("imx21-uart.1", "per", "uart_ipg_per")
+ ? ? ? clkdev("imx21-uart.2", "ipg", "uart3_ipg")
+ ? ? ? clkdev("imx21-uart.2", "per", "uart_ipg_per")
+ ? ? ? clkdev("imx21-uart.3", "ipg", "uart4_ipg")
+ ? ? ? clkdev("imx21-uart.3", "per", "uart_ipg_per")
+ ? ? ? clkdev("imx21-uart.4", "ipg", "uart5_ipg")
+ ? ? ? clkdev("imx21-uart.4", "per", "uart_ipg_per")
+ ? ? ? clkdev("imx-gpt.0", "ipg", "ipg")
+ ? ? ? clkdev("imx-gpt.0", "per", "gpt_ipg_per")
+ ? ? ? clkdev("mxc-ehci.0", "ipg", "ipg")
+ ? ? ? clkdev("mxc-ehci.0", "ahb", "usbotg_ahb")
+ ? ? ? clkdev("mxc-ehci.0", "per", "usbdiv")
+ ? ? ? clkdev("mxc-ehci.1", "ipg", "ipg")
+ ? ? ? clkdev("mxc-ehci.1", "ahb", "usbotg_ahb")
+ ? ? ? clkdev("mxc-ehci.1", "per", "usbdiv")
+ ? ? ? clkdev("mxc-ehci.2", "ipg", "ipg")
+ ? ? ? clkdev("mxc-ehci.2", "ahb", "usbotg_ahb")
+ ? ? ? clkdev("mxc-ehci.2", "per", "usbdiv")
+ ? ? ? clkdev("fsl-usb2-udc", "ipg", "ipg")
+ ? ? ? clkdev("fsl-usb2-udc", "ahb", "usbotg_ahb")
+ ? ? ? clkdev("fsl-usb2-udc", "per", "usbdiv")
+ ? ? ? clkdev("mxc_nand.0", NULL, "nfc_ipg_per")
+ ? ? ? /* i.mx25 has the i.mx35 type cspi */
+ ? ? ? clkdev("imx35-cspi.0", NULL, "cspi1_ipg")
+ ? ? ? clkdev("imx35-cspi.1", NULL, "cspi2_ipg")
+ ? ? ? clkdev("imx35-cspi.2", NULL, "cspi3_ipg")
+ ? ? ? clkdev("mxc_pwm.0", "ipg", "pwm1_ipg")
+ ? ? ? clkdev("mxc_pwm.0", "per", "per10")

Quoted 8 lines

+ ? ? ? clkdev("mxc_pwm.1", "ipg", "pwm1_ipg")
+ ? ? ? clkdev("mxc_pwm.1", "per", "per10")
+ ? ? ? clkdev("mxc_pwm.2", "ipg", "pwm1_ipg")
+ ? ? ? clkdev("mxc_pwm.2", "per", "per10")
+ ? ? ? clkdev("mxc_pwm.3", "ipg", "pwm1_ipg")
+ ? ? ? clkdev("mxc_pwm.3", "per", "per10")
+ ? ? ? clkdev("imx-keypad", NULL, "kpp_ipg")
+ ? ? ? clkdev("mx25-adc", NULL, "tsc_ipg")

Wouldn't it be better to adjust this to mx25-adc.0, since it already has a user: the new i.MX25 ADC TS driver by your colleague Juergen Beiser, no?

Quoted 31 lines

+ ? ? ? clkdev("imx-i2c.0", NULL, "i2c_ipg_per")
+ ? ? ? clkdev("imx-i2c.1", NULL, "i2c_ipg_per")
+ ? ? ? clkdev("imx-i2c.2", NULL, "i2c_ipg_per")
+ ? ? ? clkdev("imx25-fec.0", "ipg", "fec_ipg")
+ ? ? ? clkdev("imx25-fec.0", "ahb", "fec_ahb")
+ ? ? ? clkdev("imxdi_rtc.0", NULL, "dryice_ipg")
+ ? ? ? clkdev("imx-fb.0", "per", "lcdc_ipg_per")
+ ? ? ? clkdev("imx-fb.0", "ipg", "lcdc_ipg")
+ ? ? ? clkdev("imx-fb.0", "ahb", "lcdc_ahb")
+ ? ? ? clkdev("imx2-wdt.0", NULL, "wdt_ipg")
+ ? ? ? clkdev("imx-ssi.0", "per", "ssi1_ipg_per")
+ ? ? ? clkdev("imx-ssi.0", "ipg", "ssi1_ipg")
+ ? ? ? clkdev("imx-ssi.1", "per", "ssi2_ipg_per")
+ ? ? ? clkdev("imx-ssi.1", "ipg", "ssi2_ipg")
+ ? ? ? clkdev("sdhci-esdhc-imx25.0", "per", "esdhc1_ipg_per")
+ ? ? ? clkdev("sdhci-esdhc-imx25.0", "ipg", "esdhc1_ipg")
+ ? ? ? clkdev("sdhci-esdhc-imx25.0", "ahb", "esdhc1_ahb")
+ ? ? ? clkdev("sdhci-esdhc-imx25.1", "per", "esdhc2_ipg_per")
+ ? ? ? clkdev("sdhci-esdhc-imx25.1", "ipg", "esdhc2_ipg")
+ ? ? ? clkdev("sdhci-esdhc-imx25.1", "ahb", "esdhc2_ahb")
+ ? ? ? clkdev("mx2-camera.0", "per", "csi_ipg_per")
+ ? ? ? clkdev("mx2-camera.0", "ipg", "csi_ipg")
+ ? ? ? clkdev("mx2-camera.0", "ahb", "csi_ahb")
+ ? ? ? clkdev(NULL, "audmux", "dummy")
+ ? ? ? clkdev("flexcan.0", NULL, "can1_ipg")
+ ? ? ? clkdev("flexcan.1", NULL, "can2_ipg")
+ ? ? ? /* i.mx25 has the i.mx35 type sdma */
+ ? ? ? clkdev("imx35-sdma", "ipg", "sdma_ipg")
+ ? ? ? clkdev("imx35-sdma", "ahb", "sdma_ahb")
+ ? ? ? clkdev(NULL, "iim", "iim_ipg")
+};

reviewer
#79 lore raw

PATCH 27/40 ARM i.MX25: implement clocks using common clock framework

Quoted 3 lines · Roberto Nibali

Wouldn't it be better to adjust this to mx25-adc.0, since it already has a user: the new i.MX25 ADC TS driver by your colleague Juergen Beiser, no?

Is this mx25 adc driver available somewhere?

Thanks,

Fabio Estevam

#80 lore raw

PATCH 27/40 ARM i.MX25: implement clocks using common clock framework

Hi

Quoted 7 lines · Fabio Estevam
Quoted 3 lines · Roberto Nibali

Wouldn't it be better to adjust this to mx25-adc.0, since it already has a user: the new i.MX25 ADC TS driver by your colleague Juergen Beiser, no?

Is this mx25 adc driver available somewhere?

Yes, but I couldn't find it anymore in the archives. You have to ask Juergen Beisert directly. I could make a diff of my current git tree with regard to the changes, however I have modified some bits an pieces of his original work.

I could have sworn that he posted his driver framework somewhere ...

author maintainer
#81 lore raw

PATCH 28/40 ARM i.MX1: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig    |    1 +
 arch/arm/mach-imx/Makefile   |    2 +-
 arch/arm/mach-imx/clk-imx1.c |  109 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
arch/arm/mach-imx/Kconfig +1 -0
index 0b832b1..c03920a 100644
@@ -34,6 +34,7 @@ config ARCH_MX53
 config SOC_IMX1
 	bool
 	select ARCH_MX1
+	select COMMON_CLK
 	select CPU_ARM920T
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
arch/arm/mach-imx/Makefile +1 -1
index 173e869..52b3af4 100644
@@ -1,4 +1,4 @@
-obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
arch/arm/mach-imx/clk-imx1.c new file +109 -0

109 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#82 lore raw

PATCH 28/40 ARM i.MX1: implement clocks using common clock framework

Here is a new version of the i.MX1 support which does not register the clk lookups based on string names for the clks.

Before converting the rest I'd like to know whether everyones happy with this.

Comments?

Thanks
Sascha

8<---------------------------------------------------

[PATCH] ARM i.MX1: implement clocks using common clock framework

---
 arch/arm/mach-imx/Kconfig    |    1 +
 arch/arm/mach-imx/Makefile   |    2 +-
 arch/arm/mach-imx/clk-imx1.c |  115 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx1.c
arch/arm/mach-imx/Kconfig +1 -0
index 0b832b1..c03920a 100644
@@ -34,6 +34,7 @@ config ARCH_MX53
 config SOC_IMX1
 	bool
 	select ARCH_MX1
+	select COMMON_CLK
 	select CPU_ARM920T
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
arch/arm/mach-imx/Makefile +1 -1
index 173e869..52b3af4 100644
@@ -1,4 +1,4 @@
-obj-$(CONFIG_SOC_IMX1) += clock-imx1.o mm-imx1.o
+obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
 
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
arch/arm/mach-imx/clk-imx1.c new file +115 -0

115 lines not on this page · raw message

Signature · 8 lines
1.7.10


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#83 lore raw

PATCH 29/40 ARM i.MX21: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx21.c |  173 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx21.c
arch/arm/mach-imx/Kconfig +1 -0
index c03920a..d23cebd 100644
@@ -43,6 +43,7 @@ config SOC_IMX21
 	bool
 	select MACH_MX21
 	select CPU_ARM926T
+	select COMMON_CLK
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
 
arch/arm/mach-imx/Makefile +1 -1
index 52b3af4..a2efb79 100644
@@ -1,5 +1,5 @@
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
-obj-$(CONFIG_SOC_IMX21) += clock-imx21.o mm-imx21.o
+obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
arch/arm/mach-imx/clk-imx21.c new file +173 -0

173 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#84 lore raw

PATCH 30/40 ARM i.MX27: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx27.c |  255 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/Kconfig +1 -0
index d23cebd..efed8f9 100644
@@ -59,6 +59,7 @@ config SOC_IMX27
 	bool
 	select MACH_MX27
 	select CPU_ARM926T
+	select COMMON_CLK
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
 
arch/arm/mach-imx/Makefile +1 -1
index a2efb79..c4ab418 100644
@@ -4,7 +4,7 @@ obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
arch/arm/mach-imx/clk-imx27.c new file +255 -0

255 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#85 lore raw

PATCH 31/40 ARM i.MX31: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx31.c |  168 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/Kconfig +1 -0
index efed8f9..692de7b 100644
@@ -68,6 +68,7 @@ config SOC_IMX31
 	select CPU_V6
 	select IMX_HAVE_PLATFORM_MXC_RNGA
 	select MXC_AVIC
+	select COMMON_CLK
 	select SMP_ON_UP if SMP
 
 config SOC_IMX35
arch/arm/mach-imx/Makefile +1 -1
index c4ab418..fdad8f4 100644
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
-obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
+obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
arch/arm/mach-imx/clk-imx31.c new file +168 -0

168 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#86 lore raw

PATCH 32/40 ARM i.MX5: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig           |    1 +
 arch/arm/mach-imx/Makefile          |    2 +-
 arch/arm/mach-imx/clk-imx51-imx53.c |  414 +++++++++++++++++++++++++++++++++++
 3 files changed, 416 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/Kconfig +1 -0
index 692de7b..eb14ae9 100644
@@ -82,6 +82,7 @@ config SOC_IMX35
 config SOC_IMX5
 	select CPU_V7
 	select MXC_TZIC
+	select COMMON_CLK
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_HAS_CPUFREQ
 	select ARCH_MX5
arch/arm/mach-imx/Makefile +1 -1
index fdad8f4..adf2e4f 100644
@@ -9,7 +9,7 @@ obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
 
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o
arch/arm/mach-imx/clk-imx51-imx53.c new file +414 -0

414 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#87 lore raw

PATCH 32/40 ARM i.MX5: implement clocks using common clock framework

Hello Sascha,

I saw some code removed from clk init code. For example:
mx51_clocks_init:
clk_enable(&cpu_clk); clk_enable(&main_bus_clk);
/* move usb_phy_clk to 24MHz */ clk_set_parent(&usb_phy1_clk, &osc_clk);
/* set the usboh3_clk parent to pll2_sw_clk */ clk_set_parent(&usboh3_clk, &pll2_sw_clk);

mx53_clocks_init:
clk_set_parent(&uart_root_clk, &pll3_sw_clk);

Could you explain why you remove them?
If it has reasonable purpose, do you think it's better to put them in a seperate patch? It makes everyone clear what it changed.

Thanks
Richard

author maintainer
#88 lore raw

PATCH 32/40 ARM i.MX5: implement clocks using common clock framework

Quoted 11 lines · Richard Zhao

Hello Sascha,

I saw some code removed from clk init code. For example:
mx51_clocks_init:
clk_enable(&cpu_clk); clk_enable(&main_bus_clk);
/* move usb_phy_clk to 24MHz */ clk_set_parent(&usb_phy1_clk, &osc_clk);
/* set the usboh3_clk parent to pll2_sw_clk */ clk_set_parent(&usboh3_clk, &pll2_sw_clk);

Quoted 6 lines

mx53_clocks_init:
clk_set_parent(&uart_root_clk, &pll3_sw_clk);

Could you explain why you remove them?
If it has reasonable purpose, do you think it's better to put them in a seperate patch? It makes everyone clear what it changed.

I can readd most of them, the setup simply got lost. BTW what is the reason for reparenting the uart clock in the i.MX53 setup? This will break early console support if the bootloader didn't setup the uart clock in the same way already.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#89 lore raw

PATCH 32/40 ARM i.MX5: implement clocks using common clock framework

Quoted 15 lines · Sascha Hauer
Quoted 14 lines · Richard Zhao

Hello Sascha,

I saw some code removed from clk init code. For example:
mx51_clocks_init:
clk_enable(&cpu_clk); clk_enable(&main_bus_clk);
/* move usb_phy_clk to 24MHz */ clk_set_parent(&usb_phy1_clk, &osc_clk);
/* set the usboh3_clk parent to pll2_sw_clk */ clk_set_parent(&usboh3_clk, &pll2_sw_clk);

mx53_clocks_init:
clk_set_parent(&uart_root_clk, &pll3_sw_clk);

Quoted 8 lines
Quoted 3 lines

Could you explain why you remove them?
If it has reasonable purpose, do you think it's better to put them in a seperate patch? It makes everyone clear what it changed.

I can readd most of them, the setup simply got lost. BTW what is the reason for reparenting the uart clock in the i.MX53 setup? This will break early console support if the bootloader didn't setup the uart clock in the same way already.

I think you can remove the uart reparent. The original aim is to avoid use the same pll as display/ipu. Dispaly requires precise clk which sometimes change pll rate.

You might need also check other platforms wheter they lost setup code.

Thanks
Richard

Quoted 9 lines

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#90 lore raw

PATCH 33/40 ARM i.MX35: implement clocks using common clock framework

In reply to Sascha Hauer
---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx35.c |  259 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/Kconfig +1 -0
index eb14ae9..a8b3738 100644
@@ -75,6 +75,7 @@ config SOC_IMX35
 	bool
 	select CPU_V6
 	select ARCH_MXC_IOMUX_V3
+	select COMMON_CLK
 	select HAVE_EPIT
 	select MXC_AVIC
 	select SMP_ON_UP if SMP
arch/arm/mach-imx/Makefile +1 -1
index adf2e4f..38811ad 100644
@@ -7,7 +7,7 @@ obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
-obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o pm-imx3.o
+obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
 
arch/arm/mach-imx/clk-imx35.c new file +259 -0

259 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#91 lore raw

PATCH 34/40 ARM: imx6: implement clocks using common clock framework

In reply to Sascha Hauer

From: Shawn Guo <[email protected]>

---
 arch/arm/mach-imx/Kconfig     |    1 +
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx6q.c |  407 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 409 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/Kconfig +1 -0
index a8b3738..c8e4ec1 100644
@@ -843,6 +843,7 @@ config SOC_IMX6Q
 	bool "i.MX6 Quad support"
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
+	select COMMON_CLK
 	select CPU_V7
 	select HAVE_ARM_SCU
 	select HAVE_IMX_GPC
arch/arm/mach-imx/Makefile +1 -1
index 38811ad..629a339 100644
@@ -73,7 +73,7 @@ obj-$(CONFIG_CPU_V7) += head-v7.o
 AFLAGS_head-v7.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SMP) += platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
+obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
arch/arm/mach-imx/clk-imx6q.c new file +407 -0

407 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#92 lore raw

PATCH 34/40 ARM: imx6: implement clocks using common clock framework

Hi Shawn,

arch/arm/mach-imx/clk-imx6q.c line 165

Quoted 4 lines
arch/arm/mach-imx/clk-imx6q.c new file +4 -0
+
+static const char * const clks_init_on[] __initconst = {
+	"mmdc_ch0_axi", "mmdc_ch1_axi", "uart_ipg", "uart_serial",
+};

I assume uart_ipg and uart_serial is here for the earlyprintk case. This is not needed anymore. earlyprintk depends on an enabled uart anyway, so we can safely assume that the clock is turned on when Linux starts. The clock framework will disable the clock in a late initcall, long after the real driver has taken over and enabled the clock.

I'll fix that on my side.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#93 lore raw

PATCH 34/40 ARM: imx6: implement clocks using common clock framework

Quoted 13 lines · Sascha Hauer

Hi Shawn,

arch/arm/mach-imx/clk-imx6q.c line 165

Quoted 4 lines
arch/arm/mach-imx/clk-imx6q.c new file +4 -0
+
+static const char * const clks_init_on[] __initconst = {
+	"mmdc_ch0_axi", "mmdc_ch1_axi", "uart_ipg", "uart_serial",
+};

I assume uart_ipg and uart_serial is here for the earlyprintk case. This is not needed anymore. earlyprintk depends on an enabled uart anyway, so we can safely assume that the clock is turned on when Linux starts. The clock framework will disable the clock in a late initcall, long after the real driver has taken over and enabled the clock.

Yes, that's the case for the last 2 clocks, but the first 2 clocks are for memory and need to be kept there. Also, currently I do not have uart_ipg in the clkdev for uart driver to look up, so if we remove it from clks_init_on, we need to add it into clkdev.

Signature · 2 lines
Regards,
Shawn
author maintainer
#94 lore raw

PATCH 34/40 ARM: imx6: implement clocks using common clock framework

Quoted 14 lines · Shawn Guo
Quoted 13 lines · Sascha Hauer

Hi Shawn,

arch/arm/mach-imx/clk-imx6q.c line 165

Quoted 4 lines
arch/arm/mach-imx/clk-imx6q.c new file +4 -0
+
+static const char * const clks_init_on[] __initconst = {
+	"mmdc_ch0_axi", "mmdc_ch1_axi", "uart_ipg", "uart_serial",
+};

I assume uart_ipg and uart_serial is here for the earlyprintk case. This is not needed anymore. earlyprintk depends on an enabled uart anyway, so we can safely assume that the clock is turned on when Linux starts. The clock framework will disable the clock in a late initcall, long after the real driver has taken over and enabled the clock.

Quoted 4 lines

Yes, that's the case for the last 2 clocks, but the first 2 clocks are for memory and need to be kept there. Also, currently I do not have uart_ipg in the clkdev for uart driver to look up, so if we remove it from clks_init_on, we need to add it into clkdev.

Yes, I already fixed up the uart clocks.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#95 lore raw

PATCH 35/40 ARM i.MX: remove now unused old clock support

In reply to Sascha Hauer
---
 arch/arm/mach-imx/clock-imx1.c      |  636 -----------
 arch/arm/mach-imx/clock-imx21.c     | 1239 --------------------
 arch/arm/mach-imx/clock-imx25.c     |  346 ------
 arch/arm/mach-imx/clock-imx27.c     |  785 -------------
 arch/arm/mach-imx/clock-imx31.c     |  630 -----------
 arch/arm/mach-imx/clock-imx35.c     |  536 ---------
 arch/arm/mach-imx/clock-imx6q.c     | 2111 -----------------------------------
 arch/arm/mach-imx/clock-mx51-mx53.c | 1675 ---------------------------
 8 files changed, 7958 deletions(-)
 delete mode 100644 arch/arm/mach-imx/clock-imx1.c
 delete mode 100644 arch/arm/mach-imx/clock-imx21.c
 delete mode 100644 arch/arm/mach-imx/clock-imx25.c
 delete mode 100644 arch/arm/mach-imx/clock-imx27.c
 delete mode 100644 arch/arm/mach-imx/clock-imx31.c
 delete mode 100644 arch/arm/mach-imx/clock-imx35.c
 delete mode 100644 arch/arm/mach-imx/clock-imx6q.c
 delete mode 100644 arch/arm/mach-imx/clock-mx51-mx53.c
arch/arm/mach-imx/clock-imx1.c deleted +0 -0
deleted file mode 100644
index 4aabeb2..0000000
arch/arm/mach-imx/clock-imx21.c deleted +0 -0
deleted file mode 100644
index ee15d8c..0000000
arch/arm/mach-imx/clock-imx25.c deleted +0 -0
deleted file mode 100644
index b0fec74c..0000000
arch/arm/mach-imx/clock-imx27.c deleted +0 -0
deleted file mode 100644
index 98e04f5..0000000
arch/arm/mach-imx/clock-imx31.c deleted +0 -0
deleted file mode 100644
index 3a943cd..0000000
arch/arm/mach-imx/clock-imx35.c deleted +0 -0
deleted file mode 100644
index e56c1a8..0000000
arch/arm/mach-imx/clock-imx6q.c deleted +0 -0
deleted file mode 100644
index 111c328..0000000
arch/arm/mach-imx/clock-mx51-mx53.c deleted +0 -0
deleted file mode 100644
index 0847050..0000000
Signature · 1 line
1.7.9.5
author maintainer
#96 lore raw

PATCH 36/40 ARM i.MX pllv1: move mxc_decode_pll to its only user

In reply to Sascha Hauer
---
 arch/arm/mach-imx/clk-pllv1.c          |   47 +++++++++++++++++++++++++++++++-
 arch/arm/plat-mxc/clock.c              |   45 ------------------------------
 arch/arm/plat-mxc/include/mach/clock.h |    2 --
 3 files changed, 46 insertions(+), 48 deletions(-)
arch/arm/mach-imx/clk-pllv1.c +46 -1
index afbd95f..7b29f67 100644
@@ -25,12 +25,57 @@ struct clk_pllv1 {
 
 #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
 
+/*
+ * Get the resulting clock rate from a PLL register value and the input
+ * frequency. PLLs with this register layout can at least be found on
+ * MX1, MX21, MX27 and MX31
+ *
+ *                  mfi + mfn / (mfd + 1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+static unsigned long clk_pllv1_decode(unsigned int reg_val, u32 freq)
+{
+	long long ll;
+	int mfn_abs;
+	unsigned int mfi, mfn, mfd, pd;
+
+	mfi = (reg_val >> 10) & 0xf;
+	mfn = reg_val & 0x3ff;
+	mfd = (reg_val >> 16) & 0x3ff;
+	pd =  (reg_val >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	mfn_abs = mfn;
+
+	/* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
+	 * 2's complements number
+	 */
+	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
+		mfn_abs = 0x400 - mfn;
+
+	freq *= 2;
+	freq /= pd + 1;
+
+	ll = (unsigned long long)freq * mfn_abs;
+
+	do_div(ll, mfd + 1);
+
+	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
+		ll = -ll;
+
+	ll = (freq * mfi) + ll;
+
+	return ll;
+}
+
 static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clk_pllv1 *pll = to_clk_pllv1(hw);
 
-	return mxc_decode_pll(readl(pll->base), parent_rate);
+	return clk_pllv1_decode(readl(pll->base), parent_rate);
 }
 
 struct clk_ops clk_pllv1_ops = {
arch/arm/plat-mxc/clock.c +0 -45

48 lines not on this page · raw message

arch/arm/plat-mxc/include/mach/clock.h +0 -2
index bd940c7..0c4ad77 100644
@@ -64,7 +64,5 @@ void clk_unregister(struct clk *clk);
 
 extern spinlock_t imx_ccm_lock;
 
-unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_ARCH_MXC_CLOCK_H__ */
Signature · 1 line
1.7.9.5
author maintainer
#97 lore raw

PATCH 37/40 ARM i.MX: remove unused legacy clock support

In reply to Sascha Hauer
---
 arch/arm/plat-mxc/clock.c              |  188 +-------------------------------
 arch/arm/plat-mxc/include/mach/clock.h |   43 --------
 2 files changed, 1 insertion(+), 230 deletions(-)
arch/arm/plat-mxc/clock.c +1 -187
index 0ed0954..2b73f3f 100644
@@ -1,9 +1,4 @@
 /*
- * Based on arch/arm/plat-omap/clock.c
- *
- * Copyright (C) 2004 - 2005 Nokia corporation
- * Written by Tuukka Tikkanen <[email protected]>
- * Modified for omap shared clock framework by Tony Lindgren <[email protected]>
  * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel at pengutronix.de
  *
@@ -21,192 +16,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
  */
-
-/* #define DEBUG */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/proc_fs.h>
-#include <linux/semaphore.h>
-#include <linux/string.h>
-
+#include <linux/spinlock.h>
 #include <mach/clock.h>
-#include <mach/hardware.h>
-
-#ifndef CONFIG_COMMON_CLK
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*-------------------------------------------------------------------------
- * Standard clock functions defined in include/linux/clk.h
- *-------------------------------------------------------------------------*/
-
-static void __clk_disable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return;
-	WARN_ON(!clk->usecount);
-
-	if (!(--clk->usecount)) {
-		if (clk->disable)
-			clk->disable(clk);
-		__clk_disable(clk->parent);
-		__clk_disable(clk->secondary);
-	}
-}
-
-static int __clk_enable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	if (clk->usecount++ == 0) {
-		__clk_enable(clk->parent);
-		__clk_enable(clk->secondary);
-
-		if (clk->enable)
-			clk->enable(clk);
-	}
-	return 0;
-}
-
-/* This function increments the reference count on the clock and enables the
- * clock if not already enabled. The parent clock tree is recursively enabled
- */
-int clk_enable(struct clk *clk)
-{
-	int ret = 0;
-
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-	ret = __clk_enable(clk);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-/* This function decrements the reference count on the clock and disables
- * the clock when reference count is 0. The parent clock tree is
- * recursively disabled
- */
-void clk_disable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	mutex_lock(&clocks_mutex);
-	__clk_disable(clk);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_disable);
-
-/* Retrieve the *current* clock rate. If the clock itself
- * does not provide a special calculation routine, ask
- * its parent and so on, until one is able to return
- * a valid clock rate
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return 0UL;
-
-	if (clk->get_rate)
-		return clk->get_rate(clk);
-
-	return clk_get_rate(clk->parent);
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/* Round the requested clock rate to the nearest supported
- * rate that is less than or equal to the requested rate.
- * This is dependent on the clock's current parent.
- */
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
-		return 0;
-
-	return clk->round_rate(clk, rate);
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-/* Set the clock to the requested clock rate. The rate must
- * match a supported rate exactly based on what clk_round_rate returns
- */
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret = -EINVAL;
-
-	if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
-		return ret;
-
-	mutex_lock(&clocks_mutex);
-	ret = clk->set_rate(clk, rate);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-/* Set the clock's parent to another clock source */
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = -EINVAL;
-	struct clk *old;
-
-	if (clk == NULL || IS_ERR(clk) || parent == NULL ||
-	    IS_ERR(parent) || clk->set_parent == NULL)
-		return ret;
-
-	if (clk->usecount)
-		clk_enable(parent);
-
-	mutex_lock(&clocks_mutex);
-	ret = clk->set_parent(clk, parent);
-	if (ret == 0) {
-		old = clk->parent;
-		clk->parent = parent;
-	} else {
-		old = parent;
-	}
-	mutex_unlock(&clocks_mutex);
-
-	if (clk->usecount)
-		clk_disable(old);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-/* Retrieve the clock's parent clock source */
-struct clk *clk_get_parent(struct clk *clk)
-{
-	struct clk *ret = NULL;
-
-	if (clk == NULL || IS_ERR(clk))
-		return ret;
-
-	return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-#else
 
 /*
  * Lock to protect the clock module (ccm) registers. Used
  * on all i.MXs
  */
 DEFINE_SPINLOCK(imx_ccm_lock);
-
-#endif /* CONFIG_COMMON_CLK */
arch/arm/plat-mxc/include/mach/clock.h +0 -43

49 lines not on this page · raw message

Signature · 1 line
1.7.9.5
author maintainer
#98 lore raw

PATCH 38/40 USB gadget i.MX: fix clock handling

In reply to Sascha Hauer

The usbotg core generally has three different clocks:

ipg: Bus register accesses
ahb: DMA clock
per: Clock for generating the 60MHz for the phy

The old i.MX clock support messed this up completely, there were different clocks for different SoCs, but there meaning varied from SoC to SoC. This patch cleans up the breakage introduced by the generic clock support. While at it, also use the managed version of clk_get to make the error path easier.

---
 drivers/usb/gadget/fsl_mxc_udc.c |   74 ++++++++++++--------------------------
 1 file changed, 23 insertions(+), 51 deletions(-)
drivers/usb/gadget/fsl_mxc_udc.c +23 -51
index dcbc0a2..cfaa40a 100644
@@ -21,7 +21,8 @@
 #include <mach/hardware.h>
 
 static struct clk *mxc_ahb_clk;
-static struct clk *mxc_usb_clk;
+static struct clk *mxc_ipg_clk;
+static struct clk *mxc_per_clk;
 
 /* workaround ENGcm09152 for i.MX35 */
 #define USBPHYCTRL_OTGBASE_OFFSET	0x608
@@ -35,55 +36,31 @@ int fsl_udc_clk_init(struct platform_device *pdev)
 
 	pdata = pdev->dev.platform_data;
 
-	if (!cpu_is_mx35() && !cpu_is_mx25()) {
-		mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
-		if (IS_ERR(mxc_ahb_clk))
-			return PTR_ERR(mxc_ahb_clk);
+	mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(mxc_ahb_clk))
+		return PTR_ERR(mxc_ahb_clk);
 
-		ret = clk_enable(mxc_ahb_clk);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n");
-			goto eenahb;
-		}
-	}
+	mxc_per_clk = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(mxc_per_clk))
+		return PTR_ERR(mxc_per_clk);
 
-	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-	mxc_usb_clk = clk_get(&pdev->dev, "usb");
-	if (IS_ERR(mxc_usb_clk)) {
-		dev_err(&pdev->dev, "clk_get(\"usb\") failed\n");
-		ret = PTR_ERR(mxc_usb_clk);
-		goto egusb;
-	}
+	mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(mxc_ipg_clk))
+		return PTR_ERR(mxc_ipg_clk);
 
-	if (!cpu_is_mx51()) {
-		freq = clk_get_rate(mxc_usb_clk);
-		if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
-		    (freq < 59999000 || freq > 60001000)) {
-			dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
-			ret = -EINVAL;
-			goto eclkrate;
-		}
+	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
+	freq = clk_get_rate(mxc_usb_clk);
+	if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
+	    (freq < 59999000 || freq > 60001000)) {
+		dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
+		return -EINVAL;
 	}
 
-	ret = clk_enable(mxc_usb_clk);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "clk_enable(\"usb_clk\") failed\n");
-		goto eenusb;
-	}
+	clk_prepare_enable(mxc_ahb_clk);
+	clk_prepare_enable(mxc_per_clk);
+	clk_prepare_enable(mxc_ipg_clk);
 
 	return 0;
-
-eenusb:
-eclkrate:
-	clk_put(mxc_usb_clk);
-	mxc_usb_clk = NULL;
-egusb:
-	if (!cpu_is_mx35())
-		clk_disable(mxc_ahb_clk);
-eenahb:
-	if (!cpu_is_mx35())
-		clk_put(mxc_ahb_clk);
-	return ret;
 }
 
 void fsl_udc_clk_finalize(struct platform_device *pdev)
@@ -112,12 +89,7 @@ void fsl_udc_clk_finalize(struct platform_device *pdev)
 
 void fsl_udc_clk_release(void)
 {
-	if (mxc_usb_clk) {
-		clk_disable(mxc_usb_clk);
-		clk_put(mxc_usb_clk);
-	}
-	if (!cpu_is_mx35()) {
-		clk_disable(mxc_ahb_clk);
-		clk_put(mxc_ahb_clk);
-	}
+	clk_disable_unprepare(mxc_ahb_clk);
+	clk_disable_unprepare(mxc_ipg_clk);
+	clk_disable_unprepare(mxc_per_clk);
 }
Signature · 1 line
1.7.9.5
author maintainer
#99 lore raw

PATCH 39/40 USB ehci i.MX: Fix clock handling

In reply to Sascha Hauer

The usbotg core generally has three different clocks:

ipg: Bus register accesses
ahb: DMA clock
per: Clock for generating the 60MHz for the phy

The old i.MX clock support messed this up completely, there were different clocks for different SoCs, but there meaning varied from SoC to SoC. This patch cleans up the breakage introduced by the generic clock support. While at it, also use the managed version of clk_get to make the error path easier.

---
 drivers/usb/host/ehci-mxc.c |   52 ++++++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 25 deletions(-)
drivers/usb/host/ehci-mxc.c +27 -25
index ae16c34..a2fb7c5 100644
@@ -32,7 +32,10 @@
 #define ULPI_VIEWPORT_OFFSET	0x170
 
 struct ehci_mxc_priv {
-	struct clk *usbclk, *ahbclk, *phy1clk;
+	struct clk *clk_ipg;
+	struct clk *clk_ahb;
+	struct clk *clk_per;
+	struct clk *phy1clk;
 	struct usb_hcd *hcd;
 };
 
@@ -166,22 +169,28 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 	}
 
 	/* enable clocks */
-	priv->usbclk = clk_get(dev, "usb");
-	if (IS_ERR(priv->usbclk)) {
-		ret = PTR_ERR(priv->usbclk);
+	priv->clk_ipg = devm_clk_get(dev, "ipg");
+	if (IS_ERR(priv->clk_ipg)) {
+		ret = PTR_ERR(priv->clk_ipg);
 		goto err_clk;
 	}
-	clk_prepare_enable(priv->usbclk);
 
-	if (!cpu_is_mx35() && !cpu_is_mx25()) {
-		priv->ahbclk = clk_get(dev, "usb_ahb");
-		if (IS_ERR(priv->ahbclk)) {
-			ret = PTR_ERR(priv->ahbclk);
-			goto err_clk_ahb;
-		}
-		clk_prepare_enable(priv->ahbclk);
+	priv->clk_ahb = devm_clk_get(dev, "ahb");
+	if (IS_ERR(priv->clk_ahb)) {
+		ret = PTR_ERR(priv->clk_ahb);
+		goto err_clk;
+	}
+
+	priv->clk_per = devm_clk_get(dev, "per");
+	if (IS_ERR(priv->clk_per)) {
+		ret = PTR_ERR(priv->clk_per);
+		goto err_clk;
 	}
 
+	clk_prepare_enable(priv->clk_per);
+	clk_prepare_enable(priv->clk_ahb);
+	clk_prepare_enable(priv->clk_ipg);
+
 	/* "dr" device has its own clock on i.MX51 */
 	if (cpu_is_mx51() && (pdev->id == 0)) {
 		priv->phy1clk = clk_get(dev, "usb_phy1");
@@ -270,13 +279,9 @@ err_init:
 		clk_put(priv->phy1clk);
 	}
 err_clk_phy:
-	if (priv->ahbclk) {
-		clk_disable_unprepare(priv->ahbclk);
-		clk_put(priv->ahbclk);
-	}
-err_clk_ahb:
-	clk_disable_unprepare(priv->usbclk);
-	clk_put(priv->usbclk);
+	clk_disable_unprepare(priv->clk_ahb);
+	clk_disable_unprepare(priv->clk_ipg);
+	clk_disable_unprepare(priv->clk_per);
 err_clk:
 	iounmap(hcd->regs);
 err_ioremap:
@@ -307,12 +312,9 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
 	usb_put_hcd(hcd);
 	platform_set_drvdata(pdev, NULL);
 
-	clk_disable_unprepare(priv->usbclk);
-	clk_put(priv->usbclk);
-	if (priv->ahbclk) {
-		clk_disable_unprepare(priv->ahbclk);
-		clk_put(priv->ahbclk);
-	}
+	clk_disable_unprepare(priv->clk_ahb);
+	clk_disable_unprepare(priv->clk_ipg);
+	clk_disable_unprepare(priv->clk_per);
 	if (priv->phy1clk) {
 		clk_disable_unprepare(priv->phy1clk);
 		clk_put(priv->phy1clk);
Signature · 1 line
1.7.9.5
author maintainer
#100 lore raw

PATCH 40/40 ARM i.MX: Remove now unused struct clk argument from mxc_timer_init

In reply to Sascha Hauer
---
 arch/arm/mach-imx/clk-imx1.c            |    3 +--
 arch/arm/mach-imx/clk-imx21.c           |    4 ++--
 arch/arm/mach-imx/clk-imx25.c           |    2 +-
 arch/arm/mach-imx/clk-imx27.c           |    3 +--
 arch/arm/mach-imx/clk-imx31.c           |    3 +--
 arch/arm/mach-imx/clk-imx35.c           |    3 +--
 arch/arm/mach-imx/clk-imx51-imx53.c     |    6 ++----
 arch/arm/mach-imx/clk-imx6q.c           |    2 +-
 arch/arm/plat-mxc/include/mach/common.h |    2 +-
 arch/arm/plat-mxc/time.c                |    4 ++--
 10 files changed, 13 insertions(+), 19 deletions(-)
arch/arm/mach-imx/clk-imx1.c +1 -2
index 60f1801..9d58776 100644
@@ -102,8 +102,7 @@ int __init mx1_clocks_init(unsigned long fref)
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
-	mxc_timer_init(NULL, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR),
-			MX1_TIM1_INT);
+	mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
 
 	return 0;
 }
arch/arm/mach-imx/clk-imx21.c +2 -2
index c4779a0..e4a0ede 100644
@@ -167,7 +167,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
-	mxc_timer_init(NULL, MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR),
-			MX21_INT_GPT1);
+	mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1);
+
 	return 0;
 }
arch/arm/mach-imx/clk-imx25.c +1 -1
index 717b8a0..9cde523 100644
@@ -227,6 +227,6 @@ int __init mx25_clocks_init(void)
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
-	mxc_timer_init(NULL, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+	mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
 	return 0;
 }
arch/arm/mach-imx/clk-imx27.c +1 -2
index 3a1e965..d81c3c6 100644
@@ -246,8 +246,7 @@ int __init mx27_clocks_init(unsigned long fref)
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
-	mxc_timer_init(NULL, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
-			MX27_INT_GPT1);
+	mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
 
 	clk_prepare_enable(emi_ahb);
 
arch/arm/mach-imx/clk-imx31.c +1 -2
index de3addb..b57a460 100644
@@ -161,8 +161,7 @@ int __init mx31_clocks_init(unsigned long fref)
 	mx31_revision();
 	clk_disable_unprepare(iim);
 
-	mxc_timer_init(NULL, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR),
-			MX31_INT_GPT);
+	mxc_timer_init(MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), MX31_INT_GPT);
 
 	return 0;
 }
arch/arm/mach-imx/clk-imx35.c +1 -2
index 7d26ae8..a77502a 100644
@@ -251,8 +251,7 @@ int __init mx35_clocks_init()
 	epit_timer_init(&epit1_clk,
 			MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
 #else
-	mxc_timer_init(NULL, MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR),
-			MX35_INT_GPT);
+	mxc_timer_init(MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
 #endif
 
 	return 0;
arch/arm/mach-imx/clk-imx51-imx53.c +2 -4
index 5b5d7a0..4d8229e 100644
@@ -309,8 +309,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_set_rate(esdhc_b_podf, 166250000);
 
 	/* System timer */
-	mxc_timer_init(NULL, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_INT_GPT);
+	mxc_timer_init(MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_INT_GPT);
 
 	clk_prepare_enable(iim);
 	imx_print_silicon_rev("i.MX51", mx51_revision());
@@ -363,8 +362,7 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_set_rate(esdhc_b_podf, 200000000);
 
 	/* System timer */
-	mxc_timer_init(NULL, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
-		MX53_INT_GPT);
+	mxc_timer_init(MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), MX53_INT_GPT);
 
 	clk_prepare_enable(iim);
 	imx_print_silicon_rev("i.MX53", mx53_revision());
arch/arm/mach-imx/clk-imx6q.c +1 -1
index f379fa6..cd48fa5 100644
@@ -401,7 +401,7 @@ int __init mx6q_clocks_init(void)
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 	irq = irq_of_parse_and_map(np, 0);
-	mxc_timer_init(NULL, base, irq);
+	mxc_timer_init(base, irq);
 
 	return 0;
 }
arch/arm/plat-mxc/include/mach/common.h +1 -1
index 0319c4a..5cae195 100644
@@ -54,7 +54,7 @@ extern void imx50_soc_init(void);
 extern void imx51_soc_init(void);
 extern void imx53_soc_init(void);
 extern void epit_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
-extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
+extern void mxc_timer_init(void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
 extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
 extern int mx25_clocks_init(void);
arch/arm/plat-mxc/time.c +2 -2
index 99f958c..f32a249 100644
@@ -280,10 +280,10 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
 	return 0;
 }
 
-void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
+void __init mxc_timer_init(void __iomem *base, int irq)
 {
 	uint32_t tctl_val;
-	struct clk *timer_ipg_clk;
+	struct clk *timer_ipg_clk, *timer_clk;
 
 	if (!timer_clk) {
 		timer_clk = clk_get_sys("imx-gpt.0", "per");
Signature · 1 line
1.7.9.5