aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2014-05-09 23:33:38 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2014-06-11 03:58:44 -0400
commit59cb10e32a60533865e26dc9a8303306ba972a70 (patch)
treebfcdb380247d7d945b8c0739e76a68766bb12ba5 /drivers/clk
parentff01df28e558c194836121c6d45954eaa4bcf93d (diff)
clk: sunxi: Move the GMAC clock to a file of its own
Since we have a folder of our own, we can actually make use of it by splitting the huge clock file into several sub drivers. The gmac clock is pretty easy to deal with, since it's pretty much isolated and doesn't have any dependency on the other clocks. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Mike Turquette <mturquette@linaro.org> Signed-off-by: Emilio López <emilio@elopez.com.ar>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/sunxi/Makefile3
-rw-r--r--drivers/clk/sunxi/clk-a20-gmac.c119
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c98
3 files changed, 121 insertions, 99 deletions
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 2c3d2fed2560..839029e36144 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -3,4 +3,5 @@
3# 3#
4 4
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-hosc.o \ No newline at end of file 6obj-y += clk-a10-hosc.o
7obj-y += clk-a20-gmac.o
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c
new file mode 100644
index 000000000000..633ddc4389ef
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a20-gmac.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright 2013 Emilio López
3 * Emilio López <emilio@elopez.com.ar>
4 *
5 * Copyright 2013 Chen-Yu Tsai
6 * Chen-Yu Tsai <wens@csie.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/clkdev.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/slab.h>
24
25static DEFINE_SPINLOCK(gmac_lock);
26
27/**
28 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
29 *
30 * This clock looks something like this
31 * ________________________
32 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
33 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
34 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
35 * |________________________|
36 *
37 * The external 125 MHz reference is optional, i.e. GMAC can use its
38 * internal TX clock just fine. The A31 GMAC clock module does not have
39 * the divider controls for the external reference.
40 *
41 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
42 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
43 * select the appropriate source and gate/ungate the output to the PHY.
44 *
45 * Only the GMAC should use this clock. Altering the clock so that it doesn't
46 * match the GMAC's operation parameters will result in the GMAC not being
47 * able to send traffic out. The GMAC driver should set the clock rate and
48 * enable/disable this clock to configure the required state. The clock
49 * driver then responds by auto-reparenting the clock.
50 */
51
52#define SUN7I_A20_GMAC_GPIT 2
53#define SUN7I_A20_GMAC_MASK 0x3
54#define SUN7I_A20_GMAC_PARENTS 2
55
56static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
57{
58 struct clk *clk;
59 struct clk_mux *mux;
60 struct clk_gate *gate;
61 const char *clk_name = node->name;
62 const char *parents[SUN7I_A20_GMAC_PARENTS];
63 void *reg;
64
65 if (of_property_read_string(node, "clock-output-names", &clk_name))
66 return;
67
68 /* allocate mux and gate clock structs */
69 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
70 if (!mux)
71 return;
72
73 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
74 if (!gate)
75 goto free_mux;
76
77 /* gmac clock requires exactly 2 parents */
78 parents[0] = of_clk_get_parent_name(node, 0);
79 parents[1] = of_clk_get_parent_name(node, 1);
80 if (!parents[0] || !parents[1])
81 goto free_gate;
82
83 reg = of_iomap(node, 0);
84 if (!reg)
85 goto free_gate;
86
87 /* set up gate and fixed rate properties */
88 gate->reg = reg;
89 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
90 gate->lock = &gmac_lock;
91 mux->reg = reg;
92 mux->mask = SUN7I_A20_GMAC_MASK;
93 mux->flags = CLK_MUX_INDEX_BIT;
94 mux->lock = &gmac_lock;
95
96 clk = clk_register_composite(NULL, clk_name,
97 parents, SUN7I_A20_GMAC_PARENTS,
98 &mux->hw, &clk_mux_ops,
99 NULL, NULL,
100 &gate->hw, &clk_gate_ops,
101 0);
102
103 if (IS_ERR(clk))
104 goto iounmap_reg;
105
106 of_clk_add_provider(node, of_clk_src_simple_get, clk);
107 clk_register_clkdev(clk, clk_name, NULL);
108
109 return;
110
111iounmap_reg:
112 iounmap(reg);
113free_gate:
114 kfree(gate);
115free_mux:
116 kfree(mux);
117}
118CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
119 sun7i_a20_gmac_clk_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 4a8294dad613..880095048d4d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -351,104 +351,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
351 *p = calcp; 351 *p = calcp;
352} 352}
353 353
354
355
356/**
357 * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
358 *
359 * This clock looks something like this
360 * ________________________
361 * MII TX clock from PHY >-----|___________ _________|----> to GMAC core
362 * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
363 * Ext. 125MHz RGMII TX clk >--|__divider__/ |
364 * |________________________|
365 *
366 * The external 125 MHz reference is optional, i.e. GMAC can use its
367 * internal TX clock just fine. The A31 GMAC clock module does not have
368 * the divider controls for the external reference.
369 *
370 * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
371 * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
372 * select the appropriate source and gate/ungate the output to the PHY.
373 *
374 * Only the GMAC should use this clock. Altering the clock so that it doesn't
375 * match the GMAC's operation parameters will result in the GMAC not being
376 * able to send traffic out. The GMAC driver should set the clock rate and
377 * enable/disable this clock to configure the required state. The clock
378 * driver then responds by auto-reparenting the clock.
379 */
380
381#define SUN7I_A20_GMAC_GPIT 2
382#define SUN7I_A20_GMAC_MASK 0x3
383#define SUN7I_A20_GMAC_PARENTS 2
384
385static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
386{
387 struct clk *clk;
388 struct clk_mux *mux;
389 struct clk_gate *gate;
390 const char *clk_name = node->name;
391 const char *parents[SUN7I_A20_GMAC_PARENTS];
392 void *reg;
393
394 if (of_property_read_string(node, "clock-output-names", &clk_name))
395 return;
396
397 /* allocate mux and gate clock structs */
398 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
399 if (!mux)
400 return;
401
402 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
403 if (!gate)
404 goto free_mux;
405
406 /* gmac clock requires exactly 2 parents */
407 parents[0] = of_clk_get_parent_name(node, 0);
408 parents[1] = of_clk_get_parent_name(node, 1);
409 if (!parents[0] || !parents[1])
410 goto free_gate;
411
412 reg = of_iomap(node, 0);
413 if (!reg)
414 goto free_gate;
415
416 /* set up gate and fixed rate properties */
417 gate->reg = reg;
418 gate->bit_idx = SUN7I_A20_GMAC_GPIT;
419 gate->lock = &clk_lock;
420 mux->reg = reg;
421 mux->mask = SUN7I_A20_GMAC_MASK;
422 mux->flags = CLK_MUX_INDEX_BIT;
423 mux->lock = &clk_lock;
424
425 clk = clk_register_composite(NULL, clk_name,
426 parents, SUN7I_A20_GMAC_PARENTS,
427 &mux->hw, &clk_mux_ops,
428 NULL, NULL,
429 &gate->hw, &clk_gate_ops,
430 0);
431
432 if (IS_ERR(clk))
433 goto iounmap_reg;
434
435 of_clk_add_provider(node, of_clk_src_simple_get, clk);
436 clk_register_clkdev(clk, clk_name, NULL);
437
438 return;
439
440iounmap_reg:
441 iounmap(reg);
442free_gate:
443 kfree(gate);
444free_mux:
445 kfree(mux);
446}
447CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
448 sun7i_a20_gmac_clk_setup);
449
450
451
452/** 354/**
453 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control 355 * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
454 */ 356 */