diff mbox

clk: mvebu: Do not gate ge0/1 and runit clocks on Kirkwood

Message ID 1359226864-28811-1-git-send-email-gmbnomis@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Simon Baatz Jan. 26, 2013, 7:01 p.m. UTC
Commits f479db "ARM: Kirkwood: Ensure runit clock always ticks." and
128789 "ARM: Kirkwood: Fix clk problems modular ethernet driver"
ensured that the ge and runit clocks always tick on Kirkwood.  This
prevents the device from locking up and from forgetting the MAC addresses
which are usually set by the boot loader.

When moving the clock gating control to this driver for DT devices, these
changes were disabled.  Ensure that the respective clocks have the
CLK_IGNORE_UNUSED flag set.

Signed-off-by: Simon Baatz <gmbnomis@gmail.com>
---

Hi,

kernel 3.8-rc5 will hang on kirkwood DT if the Ethernet driver is built
as a module or when no driver claiming the runit clock is built in. 
(Usually, at least the serial driver is built in, but it won't request
the clock if "clock-frequency" is given in DT.)

In the past, we fixed this by keeping the clocks ticking (which
probably is not be the nicest solution for the ge clocks).

The patch creates much noise, but is hopefully obvious. I have tested
it on IB-NAS6210 (kirkwood, single Ethernet port).  The other platforms
are only compile tested. I don't know whether something similar is 
required for other platforms as well; I left them untouched.

- Simon

 drivers/clk/mvebu/clk-gating-ctrl.c |  159 +++++++++++++++++------------------
 1 file changed, 79 insertions(+), 80 deletions(-)

Comments

Jason Cooper Jan. 26, 2013, 11:50 p.m. UTC | #1
Simon,

On Sat, Jan 26, 2013 at 08:01:04PM +0100, Simon Baatz wrote:
> Commits f479db "ARM: Kirkwood: Ensure runit clock always ticks." and
> 128789 "ARM: Kirkwood: Fix clk problems modular ethernet driver"
> ensured that the ge and runit clocks always tick on Kirkwood.  This
> prevents the device from locking up and from forgetting the MAC addresses
> which are usually set by the boot loader.
> 
> When moving the clock gating control to this driver for DT devices, these
> changes were disabled.  Ensure that the respective clocks have the
> CLK_IGNORE_UNUSED flag set.
> 
> Signed-off-by: Simon Baatz <gmbnomis@gmail.com>
> ---
> 
> Hi,
> 
> kernel 3.8-rc5 will hang on kirkwood DT if the Ethernet driver is built
> as a module or when no driver claiming the runit clock is built in. 
> (Usually, at least the serial driver is built in, but it won't request
> the clock if "clock-frequency" is given in DT.)
> 
> In the past, we fixed this by keeping the clocks ticking (which
> probably is not be the nicest solution for the ge clocks).

I have to admit, I'm not really keen on this.  Most of these boards only
have one ethernet port, so at least one port would be energized
unnecessarily.

Another facet of this problem is the keymile board.  It has to enable
the clocks for sata in order to boot. (ref: board-km_kirkwood.c).

Perhaps there is some way we could declare certain gate clocks to be
non-gateable in the dts?  runit comes to mind, sata for keymile, and the
relevant ge[01] per board.  After all, it is a characteristic of the
board.  ;-)

eg in kirkwood-km_kirkwood.dts:

gate_clk: clock-gating-control@2011c {
	/*
	 * need both sata clks enabled in order to boot
	 * even though we have no sata
	 */
	ungateable = <14 15>;
};

and in any other board:

gate_clk: clock-gating-control@2011c {
	/* don't lose eth0 mac address */
	ungateable = <0>;
};

where in kirkwood.dtsi we had:

gate_clk: clock-gating-control@2011c {
	compatible = "marvell,kirkwood-gating-clock";
	reg = <0x2011c 0x4>;
	clocks = <&core_clk 0>;
	#clock-cells = <1>;
	ungateable = <7>; /* never gate runit */
};

or, s/ungateable/ignore_unused/g

thx,

Jason.
Simon Baatz Jan. 27, 2013, 1:31 a.m. UTC | #2
On Sat, Jan 26, 2013 at 06:50:37PM -0500, Jason Cooper wrote:
> Simon,
> 
> On Sat, Jan 26, 2013 at 08:01:04PM +0100, Simon Baatz wrote:
> > Commits f479db "ARM: Kirkwood: Ensure runit clock always ticks." and
> > 128789 "ARM: Kirkwood: Fix clk problems modular ethernet driver"
> > ensured that the ge and runit clocks always tick on Kirkwood.  This
> > prevents the device from locking up and from forgetting the MAC addresses
> > which are usually set by the boot loader.
> > 
> > When moving the clock gating control to this driver for DT devices, these
> > changes were disabled.  Ensure that the respective clocks have the
> > CLK_IGNORE_UNUSED flag set.
> > 
> > 
> > In the past, we fixed this by keeping the clocks ticking (which
> > probably is not be the nicest solution for the ge clocks).
> 
> I have to admit, I'm not really keen on this.  Most of these boards only
> have one ethernet port, so at least one port would be energized
> unnecessarily.

Me neither, the patch was intended to get 3.8 to work with
modularized drivers.  It was not intended to be the final solution. 
However, I think I found a better way for 3.8, see below.

> 
> Another facet of this problem is the keymile board.  It has to enable
> the clocks for sata in order to boot. (ref: board-km_kirkwood.c).

I did not notice it before, but looking at this, I realized why there
is the problem with the ge[01] clocks: kirkwood_ge0[01]_init() in common.c
depends on clk pointers that are only initialized in the non-DT case
(kirkwood_clk_init()) but not in the DT case
(kirkwood_legacy_clk_init() in board-dt.c). 

I think we should do the following for 3.8:

- Get the clocks by device name in kirkwood_ge0x_init()
- Only set CLK_IGNORE_UNUSED for "runit" in clk-gating-ctrl.c. (I can
do this by simply adding another case to the existing "ddr"
exception, which makes the patch much less intrusive)

For 3.9 with a DT converted ethernet driver, we will need something
more clever.

If you agree, I can prepare patches for 3.8.

> Perhaps there is some way we could declare certain gate clocks to be
> non-gateable in the dts?  runit comes to mind, sata for keymile, and the
> relevant ge[01] per board.  After all, it is a characteristic of the
> board.  ;-)
> 

I like this idea. That fits my 'more clever' from above ;-)

> eg in kirkwood-km_kirkwood.dts:
> 
> gate_clk: clock-gating-control@2011c {
> 	/*
> 	 * need both sata clks enabled in order to boot
> 	 * even though we have no sata
> 	 */
> 	ungateable = <14 15>;
> };
> 
> and in any other board:
> 
> gate_clk: clock-gating-control@2011c {
> 	/* don't lose eth0 mac address */
> 	ungateable = <0>;
> };
> 
> where in kirkwood.dtsi we had:
> 
> gate_clk: clock-gating-control@2011c {
> 	compatible = "marvell,kirkwood-gating-clock";
> 	reg = <0x2011c 0x4>;
> 	clocks = <&core_clk 0>;
> 	#clock-cells = <1>;
> 	ungateable = <7>; /* never gate runit */
> };
> 
> or, s/ungateable/ignore_unused/g

Yes, probably better.

- Simon
Sebastian Hesselbarth Jan. 27, 2013, 10:15 a.m. UTC | #3
On 01/27/2013 02:31 AM, Simon Baatz wrote:
> On Sat, Jan 26, 2013 at 06:50:37PM -0500, Jason Cooper wrote:
>> Another facet of this problem is the keymile board.  It has to enable
>> the clocks for sata in order to boot. (ref: board-km_kirkwood.c).

The statement in board-km_kirkwood.c is just not true. Andrew and I did
some tests with Valentin Longchamps back when we introduced DT clk
gating. Keymile board hangs not because of the accesses to clk gating
ctrl registers but the phy gating that accessed the sata registers
that are missing on the Kirkwood used on that board.

Phy gates have not been used since DT clk gating at all. If we
reintroduce them in a DT compatible way we can still disable them
for keymile board in DT.

> I think we should do the following for 3.8:
>
> - Get the clocks by device name in kirkwood_ge0x_init()
> - Only set CLK_IGNORE_UNUSED for "runit" in clk-gating-ctrl.c. (I can
> do this by simply adding another case to the existing "ddr"
> exception, which makes the patch much less intrusive)

I agree that we should have .flags for clk-gating-ctrl but that
can live without any DT properties as we already have SoC specific
structs there (and Keymile's kirkwood doesn't hang on clk gating
control register accesses)

>> and in any other board:
>>
>> gate_clk: clock-gating-control@2011c {
>> 	/* don't lose eth0 mac address */
>> 	ungateable =<0>;
>> };

If there is any hang issue with gated ge clk on kirkwood, the
solution is not to just disable the clock gate but make any
code that accesses ge registers prepare the clock.

Sebastian
Simon Baatz Jan. 27, 2013, 10:56 a.m. UTC | #4
Hi Sebastian,

On Sun, Jan 27, 2013 at 11:15:59AM +0100, Sebastian Hesselbarth wrote:
> 
> >I think we should do the following for 3.8:
> >
> >- Get the clocks by device name in kirkwood_ge0x_init()
> >- Only set CLK_IGNORE_UNUSED for "runit" in clk-gating-ctrl.c. (I can
> >do this by simply adding another case to the existing "ddr"
> >exception, which makes the patch much less intrusive)
> 
> I agree that we should have .flags for clk-gating-ctrl but that
> can live without any DT properties as we already have SoC specific
> structs there (and Keymile's kirkwood doesn't hang on clk gating
> control register accesses)

Oh, I just posted the patch with the simple if, not the .flags. As
said, the .flags create much noise.  But I don't mind changing that
back or posting the .flags change separately for 3.9.

I think for "runit" it makes sense to keep it that way (i.e. not in
DT properties).  But the ge clocks are really depending on the number
of interfaces on the particular board.  Having a way not to keep them
running for all boards just not to forget the MAC addresses for those
boards who use them would be nice.

> 
> >>and in any other board:
> >>
> >>gate_clk: clock-gating-control@2011c {
> >>	/* don't lose eth0 mac address */
> >>	ungateable =<0>;
> >>};
> 
> If there is any hang issue with gated ge clk on kirkwood, the
> solution is not to just disable the clock gate but make any
> code that accesses ge registers prepare the clock.

Indeed, there are two issue here. The ge interface forgets its MAC
address (set by the boot loader) when the clock is gated.

In the ge driver, accesses are in the wrong order or there is a
missing delay between the enabling and the hardware access.  Andrew
digged into this at the time. But even if that would work, the
interface would not be usable without a valid MAC address.

- Simon
Sebastian Hesselbarth Jan. 27, 2013, 11:12 a.m. UTC | #5
On 01/27/2013 11:56 AM, Simon Baatz wrote:
> On Sun, Jan 27, 2013 at 11:15:59AM +0100, Sebastian Hesselbarth wrote:
>>
>>> I think we should do the following for 3.8:
>>>
>>> - Get the clocks by device name in kirkwood_ge0x_init()
>>> - Only set CLK_IGNORE_UNUSED for "runit" in clk-gating-ctrl.c. (I can
>>> do this by simply adding another case to the existing "ddr"
>>> exception, which makes the patch much less intrusive)
>>
>> I agree that we should have .flags for clk-gating-ctrl but that
>> can live without any DT properties as we already have SoC specific
>> structs there (and Keymile's kirkwood doesn't hang on clk gating
>> control register accesses)
>
> Oh, I just posted the patch with the simple if, not the .flags. As
> said, the .flags create much noise.  But I don't mind changing that
> back or posting the .flags change separately for 3.9.

I prefer .flags even with the noise the patch will cause. It is a
fix and there is no reason why we should fix that fix later just because
of the amount of changes it will cause.

> I think for "runit" it makes sense to keep it that way (i.e. not in
> DT properties).  But the ge clocks are really depending on the number
> of interfaces on the particular board.  Having a way not to keep them
> running for all boards just not to forget the MAC addresses for those
> boards who use them would be nice.

Except for loosing the MAC address, I disagree. From a "clock gating"
point-of-view all kirkwoods (except that crippled one on keymile board)
are the same. Even if there is no/one/two ethernet _jacks_ on a specific
board you still want to disable all _unused_ ethernet modules inside the
SoC.

We should find a way to retain the MAC address and in the meantime we
can add a "always prepare ge clocks" workaround in
kirkwood_clk_legacy_init().

>> If there is any hang issue with gated ge clk on kirkwood, the
>> solution is not to just disable the clock gate but make any
>> code that accesses ge registers prepare the clock.
>
> Indeed, there are two issue here. The ge interface forgets its MAC
> address (set by the boot loader) when the clock is gated.
>
> In the ge driver, accesses are in the wrong order or there is a
> missing delay between the enabling and the hardware access.  Andrew
> digged into this at the time. But even if that would work, the
> interface would not be usable without a valid MAC address.

Again, then it is about fixing the driver not the clock gating.

I understand that it will render the interface unusable but then a
modular kirkwood kernel is just not supported in the current
state.

Sebastian
Andrew Lunn Jan. 27, 2013, 3:28 p.m. UTC | #6
> Except for loosing the MAC address, I disagree. From a "clock gating"
> point-of-view all kirkwoods (except that crippled one on keymile board)
> are the same. Even if there is no/one/two ethernet _jacks_ on a specific
> board you still want to disable all _unused_ ethernet modules inside the
> SoC.
> 
> We should find a way to retain the MAC address and in the meantime we
> can add a "always prepare ge clocks" workaround in
> kirkwood_clk_legacy_init().

Hi Sebastian

I've been thinking the same, store the MAC address before turning the
clock off and restore it when enabling the clock. We have a need for
special clocks on kirkwood anyway for turning off the sata and pcie
PHYs. So adding special clocks for ethernet is not too big a deal.

      Andrew
Sebastian Hesselbarth Jan. 27, 2013, 3:38 p.m. UTC | #7
On 01/27/2013 04:28 PM, Andrew Lunn wrote:
>> Except for loosing the MAC address, I disagree. From a "clock gating"
>> point-of-view all kirkwoods (except that crippled one on keymile board)
>> are the same. Even if there is no/one/two ethernet _jacks_ on a specific
>> board you still want to disable all _unused_ ethernet modules inside the
>> SoC.
>>
>> We should find a way to retain the MAC address and in the meantime we
>> can add a "always prepare ge clocks" workaround in
>> kirkwood_clk_legacy_init().
>
> I've been thinking the same, store the MAC address before turning the
> clock off and restore it when enabling the clock. We have a need for
> special clocks on kirkwood anyway for turning off the sata and pcie
> PHYs. So adding special clocks for ethernet is not too big a deal.

Andrew,

if Simon confirms that gbe is really loosing its MAC address when
clocks get gated, I still think that we should rely on other mechanisms
to get a valid MAC address.

Have a look at other DT ethernet drivers, they use local-mac-address
property to pass MAC address from boot loader. IMHO that is what we
should exploit on mv643xx_eth, too.

If the property is set on boot, we can store it in some private data.
If it is not set because some legacy u-boot without DT, we can rely
on what is in the MAC address registers and just call modular eth
on those platforms broken. If the easy fix is to update u-boot or
compile it as built-in we shouldn't care at all. Without proper DT
in u-boot you will always have a board specific kernel anyway.

Sebastian
Thomas Petazzoni Jan. 27, 2013, 3:41 p.m. UTC | #8
Dear Andrew Lunn,

On Sun, 27 Jan 2013 16:28:37 +0100, Andrew Lunn wrote:

> I've been thinking the same, store the MAC address before turning the
> clock off and restore it when enabling the clock. We have a need for
> special clocks on kirkwood anyway for turning off the sata and pcie
> PHYs. So adding special clocks for ethernet is not too big a deal.

At least on Armada 370/XP, U-Boot passes the MAC address through a
special ATAG. Willy Tarreau has written some code to read this special
ATAG and feed it into the Device Tree, so that we get the MAC address
as set by U-Boot. I unfortunately haven't had the time to look at
Willy's code and push it, but it does seem like an interesting solution.

Are you interested?

Thomas
Jason Cooper Jan. 27, 2013, 4:41 p.m. UTC | #9
On Sun, Jan 27, 2013 at 04:41:04PM +0100, Thomas Petazzoni wrote:
> Dear Andrew Lunn,
> 
> On Sun, 27 Jan 2013 16:28:37 +0100, Andrew Lunn wrote:
> 
> > I've been thinking the same, store the MAC address before turning the
> > clock off and restore it when enabling the clock. We have a need for
> > special clocks on kirkwood anyway for turning off the sata and pcie
> > PHYs. So adding special clocks for ethernet is not too big a deal.
> 
> At least on Armada 370/XP, U-Boot passes the MAC address through a
> special ATAG. Willy Tarreau has written some code to read this special
> ATAG and feed it into the Device Tree, so that we get the MAC address
> as set by U-Boot. I unfortunately haven't had the time to look at
> Willy's code and push it, but it does seem like an interesting solution.

Does this add on to ARM_ATAG_DTB_COMPAT [1]?  Perhaps APPENDED_DTB
should select it?

Maybe the answer is as simple as having the driver pull the mac address
from the dtb while ARM_ATAG_DTB_COMPAT is configured.

thx,

Jason.

[1] arch/arm/Kconfig:1970
diff mbox

Patch

diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
index 8fa5408..917049c 100644
--- a/drivers/clk/mvebu/clk-gating-ctrl.c
+++ b/drivers/clk/mvebu/clk-gating-ctrl.c
@@ -28,6 +28,7 @@  struct mvebu_soc_descr {
 	const char *name;
 	const char *parent;
 	int bit_idx;
+	unsigned long flags;
 };
 
 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
@@ -88,21 +89,12 @@  static void __init mvebu_clk_gating_setup(
 	}
 
 	for (n = 0; n < ctrl->num_gates; n++) {
-		u8 flags = 0;
 		const char *parent =
 			(descr[n].parent) ? descr[n].parent : default_parent;
-
-		/*
-		 * On Armada 370, the DDR clock is a special case: it
-		 * isn't taken by any driver, but should anyway be
-		 * kept enabled, so we mark it as IGNORE_UNUSED for
-		 * now.
-		 */
-		if (!strcmp(descr[n].name, "ddr"))
-			flags |= CLK_IGNORE_UNUSED;
-
 		ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
-				   flags, base, descr[n].bit_idx, 0, &ctrl->lock);
+						   descr[n].flags, base,
+						   descr[n].bit_idx,
+						   0, &ctrl->lock);
 		WARN_ON(IS_ERR(ctrl->gates[n]));
 	}
 	of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
@@ -114,92 +106,99 @@  static void __init mvebu_clk_gating_setup(
 
 #ifdef CONFIG_MACH_ARMADA_370
 static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
-	{ "audio", NULL, 0 },
-	{ "pex0_en", NULL, 1 },
-	{ "pex1_en", NULL,  2 },
-	{ "ge1", NULL, 3 },
-	{ "ge0", NULL, 4 },
-	{ "pex0", NULL, 5 },
-	{ "pex1", NULL, 9 },
-	{ "sata0", NULL, 15 },
-	{ "sdio", NULL, 17 },
-	{ "tdm", NULL, 25 },
-	{ "ddr", NULL, 28 },
-	{ "sata1", NULL, 30 },
+	{ .name = "audio", .bit_idx = 0 },
+	{ .name = "pex0_en", .bit_idx = 1 },
+	{ .name = "pex1_en", .bit_idx =  2 },
+	{ .name = "ge1", .bit_idx = 3 },
+	{ .name = "ge0", .bit_idx = 4 },
+	{ .name = "pex0", .bit_idx = 5 },
+	{ .name = "pex1", .bit_idx = 9 },
+	{ .name = "sata0", .bit_idx = 15 },
+	{ .name = "sdio", .bit_idx = 17 },
+	{ .name = "tdm", .bit_idx = 25 },
+		/* The DDR clock is a special case: it isn't taken by
+		 * any driver, but should anyway be kept enabled.
+		 */
+	{ .name = "ddr", .bit_idx = 28, .flags = CLK_IGNORE_UNUSED },
+	{ .name = "sata1", .bit_idx = 30 },
 	{ }
 };
 #endif
 
 #ifdef CONFIG_MACH_ARMADA_XP
 static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
-	{ "audio", NULL, 0 },
-	{ "ge3", NULL, 1 },
-	{ "ge2", NULL,  2 },
-	{ "ge1", NULL, 3 },
-	{ "ge0", NULL, 4 },
-	{ "pex0", NULL, 5 },
-	{ "pex1", NULL, 6 },
-	{ "pex2", NULL, 7 },
-	{ "pex3", NULL, 8 },
-	{ "bp", NULL, 13 },
-	{ "sata0lnk", NULL, 14 },
-	{ "sata0", "sata0lnk", 15 },
-	{ "lcd", NULL, 16 },
-	{ "sdio", NULL, 17 },
-	{ "usb0", NULL, 18 },
-	{ "usb1", NULL, 19 },
-	{ "usb2", NULL, 20 },
-	{ "xor0", NULL, 22 },
-	{ "crypto", NULL, 23 },
-	{ "tdm", NULL, 25 },
-	{ "xor1", NULL, 28 },
-	{ "sata1lnk", NULL, 29 },
-	{ "sata1", "sata1lnk", 30 },
+	{ .name = "audio", .bit_idx = 0 },
+	{ .name = "ge3", .bit_idx = 1 },
+	{ .name = "ge2", .bit_idx =  2 },
+	{ .name = "ge1", .bit_idx = 3 },
+	{ .name = "ge0", .bit_idx = 4 },
+	{ .name = "pex0", .bit_idx = 5 },
+	{ .name = "pex1", .bit_idx = 6 },
+	{ .name = "pex2", .bit_idx = 7 },
+	{ .name = "pex3", .bit_idx = 8 },
+	{ .name = "bp", .bit_idx = 13 },
+	{ .name = "sata0lnk", .bit_idx = 14 },
+	{ .name = "sata0", .bit_idx = 15, .parent = "sata0lnk" },
+	{ .name = "lcd", .bit_idx = 16 },
+	{ .name = "sdio", .bit_idx = 17 },
+	{ .name = "usb0", .bit_idx = 18 },
+	{ .name = "usb1", .bit_idx = 19 },
+	{ .name = "usb2", .bit_idx = 20 },
+	{ .name = "xor0", .bit_idx = 22 },
+	{ .name = "crypto", .bit_idx = 23 },
+	{ .name = "tdm", .bit_idx = 25 },
+	{ .name = "xor1", .bit_idx = 28 },
+	{ .name = "sata1lnk", .bit_idx = 29 },
+	{ .name = "sata1", .bit_idx = 30, .parent = "sata1lnk" },
 	{ }
 };
 #endif
 
 #ifdef CONFIG_ARCH_DOVE
 static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
-	{ "usb0", NULL, 0 },
-	{ "usb1", NULL, 1 },
-	{ "ge", "gephy", 2 },
-	{ "sata", NULL, 3 },
-	{ "pex0", NULL, 4 },
-	{ "pex1", NULL, 5 },
-	{ "sdio0", NULL, 8 },
-	{ "sdio1", NULL, 9 },
-	{ "nand", NULL, 10 },
-	{ "camera", NULL, 11 },
-	{ "i2s0", NULL, 12 },
-	{ "i2s1", NULL, 13 },
-	{ "crypto", NULL, 15 },
-	{ "ac97", NULL, 21 },
-	{ "pdma", NULL, 22 },
-	{ "xor0", NULL, 23 },
-	{ "xor1", NULL, 24 },
-	{ "gephy", NULL, 30 },
+	{ .name = "usb0", .bit_idx = 0 },
+	{ .name = "usb1", .bit_idx = 1 },
+	{ .name = "ge", .bit_idx = 2, .parent = "gephy" },
+	{ .name = "sata", .bit_idx = 3 },
+	{ .name = "pex0", .bit_idx = 4 },
+	{ .name = "pex1", .bit_idx = 5 },
+	{ .name = "sdio0", .bit_idx = 8 },
+	{ .name = "sdio1", .bit_idx = 9 },
+	{ .name = "nand", .bit_idx = 10 },
+	{ .name = "camera", .bit_idx = 11 },
+	{ .name = "i2s0", .bit_idx = 12 },
+	{ .name = "i2s1", .bit_idx = 13 },
+	{ .name = "crypto", .bit_idx = 15 },
+	{ .name = "ac97", .bit_idx = 21 },
+	{ .name = "pdma", .bit_idx = 22 },
+	{ .name = "xor0", .bit_idx = 23 },
+	{ .name = "xor1", .bit_idx = 24 },
+	{ .name = "gephy", .bit_idx = 30 },
 	{ }
 };
 #endif
 
 #ifdef CONFIG_ARCH_KIRKWOOD
 static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
-	{ "ge0", NULL, 0 },
-	{ "pex0", NULL, 2 },
-	{ "usb0", NULL, 3 },
-	{ "sdio", NULL, 4 },
-	{ "tsu", NULL, 5 },
-	{ "runit", NULL, 7 },
-	{ "xor0", NULL, 8 },
-	{ "audio", NULL, 9 },
-	{ "sata0", NULL, 14 },
-	{ "sata1", NULL, 15 },
-	{ "xor1", NULL, 16 },
-	{ "crypto", NULL, 17 },
-	{ "pex1", NULL, 18 },
-	{ "ge1", NULL, 19 },
-	{ "tdm", NULL, 20 },
+		/* Prevent that the Ethernet interfaces will forget their
+		 * MAC addresses by keeping the "ge0/1" clocks running.
+		 */
+	{ .name = "ge0", .bit_idx = 0, .flags = CLK_IGNORE_UNUSED },
+	{ .name = "pex0", .bit_idx = 2 },
+	{ .name = "usb0", .bit_idx = 3 },
+	{ .name = "sdio", .bit_idx = 4 },
+	{ .name = "tsu", .bit_idx = 5 },
+		/* Devices will lock hard if the "runit" clock is gated. */
+	{ .name = "runit", .bit_idx = 7, .flags = CLK_IGNORE_UNUSED },
+	{ .name = "xor0", .bit_idx = 8 },
+	{ .name = "audio", .bit_idx = 9 },
+	{ .name = "sata0", .bit_idx = 14 },
+	{ .name = "sata1", .bit_idx = 15 },
+	{ .name = "xor1", .bit_idx = 16 },
+	{ .name = "crypto", .bit_idx = 17 },
+	{ .name = "pex1", .bit_idx = 18 },
+	{ .name = "ge1", .bit_idx = 19, .flags = CLK_IGNORE_UNUSED },
+	{ .name = "tdm", .bit_idx = 20 },
 	{ }
 };
 #endif