aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/sunxi/clk-sunxi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-20 19:42:36 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-20 19:42:36 -0500
commitbfc7249cc293deac8f2678b7ec3d2407b68c0a33 (patch)
tree6a73d533cc72fbc583ca1af46defe7d3c26d2751 /drivers/clk/sunxi/clk-sunxi.c
parenta4e1328a9d20ccf4a9e5a19fce172e6deb2a33e2 (diff)
parentf1e9203e2366164b832d8a6ce10134de8c575178 (diff)
Merge tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux
Pull clk framework updates from Mike Turquette: "This is much later than usual due to several last minute bugs that had to be addressed. As usual the majority of changes are new drivers and modifications to existing drivers. The core recieved many fixes along with the groundwork for several large changes coming in the future which will better parition clock providers from clock consumers" * tag 'clk-for-linus-3.19' of git://git.linaro.org/people/mike.turquette/linux: (86 commits) clk: samsung: Fix Exynos 5420 pinctrl setup and clock disable failure due to domain being gated ARM: OMAP3: clock: fix boot breakage in legacy mode ARM: OMAP2+: clock: fix DPLL code to use new determine rate APIs clk: Really fix deadlock with mmap_sem clk: mmp: fix sparse non static symbol warning clk: Change clk_ops->determine_rate to return a clk_hw as the best parent clk: change clk_debugfs_add_file to take a struct clk_hw clk: Don't expose __clk_get_accuracy clk: Don't try to use a struct clk* after it could have been freed clk: Remove unused function __clk_get_prepare_count clk: samsung: Fix double add of syscore ops after driver rebind clk: samsung: exynos4: set parent of sclk_hdmiphy to hdmi clk: samsung: exynos4415: Fix build with PM_SLEEP disabled clk: samsung: remove unnecessary inclusion of header files from clk.h clk: samsung: remove unnecessary CONFIG_OF from clk.c clk: samsung: Spelling s/bwtween/between/ clk: rockchip: Add support for the mmc clock phases using the framework clk: rockchip: add bindings for the mmc clocks clk: rockchip: rk3288 export i2s0_clkout for use in DT clk: rockchip: use clock ID for DMC (memory controller) on rk3288 ...
Diffstat (limited to 'drivers/clk/sunxi/clk-sunxi.c')
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c85
1 files changed, 59 insertions, 26 deletions
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index d5dc951264ca..570202582dcf 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -245,9 +245,9 @@ static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
245} 245}
246 246
247/** 247/**
248 * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6 248 * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2
249 * PLL6 rate is calculated as follows 249 * PLL6x2 rate is calculated as follows
250 * rate = parent_rate * n * (k + 1) / 2 250 * rate = parent_rate * (n + 1) * (k + 1)
251 * parent_rate is always 24Mhz 251 * parent_rate is always 24Mhz
252 */ 252 */
253 253
@@ -256,13 +256,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
256{ 256{
257 u8 div; 257 u8 div;
258 258
259 /* 259 /* Normalize value to a parent_rate multiple (24M) */
260 * We always have 24MHz / 2, so we can just say that our
261 * parent clock is 12MHz.
262 */
263 parent_rate = parent_rate / 2;
264
265 /* Normalize value to a parent_rate multiple (24M / 2) */
266 div = *freq / parent_rate; 260 div = *freq / parent_rate;
267 *freq = parent_rate * div; 261 *freq = parent_rate * div;
268 262
@@ -274,7 +268,7 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
274 if (*k > 3) 268 if (*k > 3)
275 *k = 3; 269 *k = 3;
276 270
277 *n = DIV_ROUND_UP(div, (*k+1)); 271 *n = DIV_ROUND_UP(div, (*k+1)) - 1;
278} 272}
279 273
280/** 274/**
@@ -445,6 +439,7 @@ static struct clk_factors_config sun6i_a31_pll6_config = {
445 .nwidth = 5, 439 .nwidth = 5,
446 .kshift = 4, 440 .kshift = 4,
447 .kwidth = 2, 441 .kwidth = 2,
442 .n_start = 1,
448}; 443};
449 444
450static struct clk_factors_config sun4i_apb1_config = { 445static struct clk_factors_config sun4i_apb1_config = {
@@ -504,9 +499,12 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = {
504 .enable = 31, 499 .enable = 31,
505 .table = &sun6i_a31_pll6_config, 500 .table = &sun6i_a31_pll6_config,
506 .getter = sun6i_a31_get_pll6_factors, 501 .getter = sun6i_a31_get_pll6_factors,
502 .name = "pll6x2",
507}; 503};
508 504
509static const struct factors_data sun4i_apb1_data __initconst = { 505static const struct factors_data sun4i_apb1_data __initconst = {
506 .mux = 24,
507 .muxmask = BIT(1) | BIT(0),
510 .table = &sun4i_apb1_config, 508 .table = &sun4i_apb1_config,
511 .getter = sun4i_get_apb1_factors, 509 .getter = sun4i_get_apb1_factors,
512}; 510};
@@ -514,6 +512,7 @@ static const struct factors_data sun4i_apb1_data __initconst = {
514static const struct factors_data sun7i_a20_out_data __initconst = { 512static const struct factors_data sun7i_a20_out_data __initconst = {
515 .enable = 31, 513 .enable = 31,
516 .mux = 24, 514 .mux = 24,
515 .muxmask = BIT(1) | BIT(0),
517 .table = &sun7i_a20_out_config, 516 .table = &sun7i_a20_out_config,
518 .getter = sun7i_a20_get_out_factors, 517 .getter = sun7i_a20_get_out_factors,
519}; 518};
@@ -544,10 +543,6 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
544 .shift = 12, 543 .shift = 12,
545}; 544};
546 545
547static const struct mux_data sun4i_apb1_mux_data __initconst = {
548 .shift = 24,
549};
550
551static void __init sunxi_mux_clk_setup(struct device_node *node, 546static void __init sunxi_mux_clk_setup(struct device_node *node,
552 struct mux_data *data) 547 struct mux_data *data)
553{ 548{
@@ -633,12 +628,6 @@ static const struct div_data sun4i_apb0_data __initconst = {
633 .table = sun4i_apb0_table, 628 .table = sun4i_apb0_table,
634}; 629};
635 630
636static const struct div_data sun6i_a31_apb2_div_data __initconst = {
637 .shift = 0,
638 .pow = 0,
639 .width = 4,
640};
641
642static void __init sunxi_divider_clk_setup(struct device_node *node, 631static void __init sunxi_divider_clk_setup(struct device_node *node,
643 struct div_data *data) 632 struct div_data *data)
644{ 633{
@@ -757,6 +746,18 @@ static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
757 .mask = {0x25386742, 0x2505111}, 746 .mask = {0x25386742, 0x2505111},
758}; 747};
759 748
749static const struct gates_data sun9i_a80_ahb0_gates_data __initconst = {
750 .mask = {0xF5F12B},
751};
752
753static const struct gates_data sun9i_a80_ahb1_gates_data __initconst = {
754 .mask = {0x1E20003},
755};
756
757static const struct gates_data sun9i_a80_ahb2_gates_data __initconst = {
758 .mask = {0x9B7},
759};
760
760static const struct gates_data sun4i_apb0_gates_data __initconst = { 761static const struct gates_data sun4i_apb0_gates_data __initconst = {
761 .mask = {0x4EF}, 762 .mask = {0x4EF},
762}; 763};
@@ -773,6 +774,10 @@ static const struct gates_data sun7i_a20_apb0_gates_data __initconst = {
773 .mask = { 0x4ff }, 774 .mask = { 0x4ff },
774}; 775};
775 776
777static const struct gates_data sun9i_a80_apb0_gates_data __initconst = {
778 .mask = {0xEB822},
779};
780
776static const struct gates_data sun4i_apb1_gates_data __initconst = { 781static const struct gates_data sun4i_apb1_gates_data __initconst = {
777 .mask = {0xFF00F7}, 782 .mask = {0xFF00F7},
778}; 783};
@@ -801,6 +806,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
801 .mask = { 0xff80ff }, 806 .mask = { 0xff80ff },
802}; 807};
803 808
809static const struct gates_data sun9i_a80_apb1_gates_data __initconst = {
810 .mask = {0x3F001F},
811};
812
804static const struct gates_data sun8i_a23_apb2_gates_data __initconst = { 813static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
805 .mask = {0x1F0007}, 814 .mask = {0x1F0007},
806}; 815};
@@ -893,6 +902,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
893 902
894struct divs_data { 903struct divs_data {
895 const struct factors_data *factors; /* data for the factor clock */ 904 const struct factors_data *factors; /* data for the factor clock */
905 int ndivs; /* number of children */
896 struct { 906 struct {
897 u8 fixed; /* is it a fixed divisor? if not... */ 907 u8 fixed; /* is it a fixed divisor? if not... */
898 struct clk_div_table *table; /* is it a table based divisor? */ 908 struct clk_div_table *table; /* is it a table based divisor? */
@@ -912,6 +922,7 @@ static struct clk_div_table pll6_sata_tbl[] = {
912 922
913static const struct divs_data pll5_divs_data __initconst = { 923static const struct divs_data pll5_divs_data __initconst = {
914 .factors = &sun4i_pll5_data, 924 .factors = &sun4i_pll5_data,
925 .ndivs = 2,
915 .div = { 926 .div = {
916 { .shift = 0, .pow = 0, }, /* M, DDR */ 927 { .shift = 0, .pow = 0, }, /* M, DDR */
917 { .shift = 16, .pow = 1, }, /* P, other */ 928 { .shift = 16, .pow = 1, }, /* P, other */
@@ -920,12 +931,21 @@ static const struct divs_data pll5_divs_data __initconst = {
920 931
921static const struct divs_data pll6_divs_data __initconst = { 932static const struct divs_data pll6_divs_data __initconst = {
922 .factors = &sun4i_pll6_data, 933 .factors = &sun4i_pll6_data,
934 .ndivs = 2,
923 .div = { 935 .div = {
924 { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ 936 { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
925 { .fixed = 2 }, /* P, other */ 937 { .fixed = 2 }, /* P, other */
926 } 938 }
927}; 939};
928 940
941static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
942 .factors = &sun6i_a31_pll6_data,
943 .ndivs = 1,
944 .div = {
945 { .fixed = 2 }, /* normal output */
946 }
947};
948
929/** 949/**
930 * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks 950 * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
931 * 951 *
@@ -950,7 +970,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
950 struct clk_fixed_factor *fix_factor; 970 struct clk_fixed_factor *fix_factor;
951 struct clk_divider *divider; 971 struct clk_divider *divider;
952 void __iomem *reg; 972 void __iomem *reg;
953 int i = 0; 973 int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
954 int flags, clkflags; 974 int flags, clkflags;
955 975
956 /* Set up factor clock that we will be dividing */ 976 /* Set up factor clock that we will be dividing */
@@ -973,7 +993,11 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
973 * our RAM clock! */ 993 * our RAM clock! */
974 clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT; 994 clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
975 995
976 for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) { 996 /* if number of children known, use it */
997 if (data->ndivs)
998 ndivs = data->ndivs;
999
1000 for (i = 0; i < ndivs; i++) {
977 if (of_property_read_string_index(node, "clock-output-names", 1001 if (of_property_read_string_index(node, "clock-output-names",
978 i, &clk_name) != 0) 1002 i, &clk_name) != 0)
979 break; 1003 break;
@@ -1062,7 +1086,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
1062 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,}, 1086 {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
1063 {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,}, 1087 {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
1064 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,}, 1088 {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
1065 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
1066 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,}, 1089 {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
1067 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,}, 1090 {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
1068 {} 1091 {}
@@ -1074,7 +1097,6 @@ static const struct of_device_id clk_div_match[] __initconst = {
1074 {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,}, 1097 {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,},
1075 {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,}, 1098 {.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
1076 {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,}, 1099 {.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
1077 {.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
1078 {} 1100 {}
1079}; 1101};
1080 1102
@@ -1082,13 +1104,13 @@ static const struct of_device_id clk_div_match[] __initconst = {
1082static const struct of_device_id clk_divs_match[] __initconst = { 1104static const struct of_device_id clk_divs_match[] __initconst = {
1083 {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,}, 1105 {.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
1084 {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,}, 1106 {.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
1107 {.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,},
1085 {} 1108 {}
1086}; 1109};
1087 1110
1088/* Matches for mux clocks */ 1111/* Matches for mux clocks */
1089static const struct of_device_id clk_mux_match[] __initconst = { 1112static const struct of_device_id clk_mux_match[] __initconst = {
1090 {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, 1113 {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
1091 {.compatible = "allwinner,sun4i-a10-apb1-mux-clk", .data = &sun4i_apb1_mux_data,},
1092 {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, 1114 {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
1093 {} 1115 {}
1094}; 1116};
@@ -1102,16 +1124,21 @@ static const struct of_device_id clk_gates_match[] __initconst = {
1102 {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,}, 1124 {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
1103 {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,}, 1125 {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
1104 {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,}, 1126 {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
1127 {.compatible = "allwinner,sun9i-a80-ahb0-gates-clk", .data = &sun9i_a80_ahb0_gates_data,},
1128 {.compatible = "allwinner,sun9i-a80-ahb1-gates-clk", .data = &sun9i_a80_ahb1_gates_data,},
1129 {.compatible = "allwinner,sun9i-a80-ahb2-gates-clk", .data = &sun9i_a80_ahb2_gates_data,},
1105 {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,}, 1130 {.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
1106 {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,}, 1131 {.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
1107 {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,}, 1132 {.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
1108 {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,}, 1133 {.compatible = "allwinner,sun7i-a20-apb0-gates-clk", .data = &sun7i_a20_apb0_gates_data,},
1134 {.compatible = "allwinner,sun9i-a80-apb0-gates-clk", .data = &sun9i_a80_apb0_gates_data,},
1109 {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,}, 1135 {.compatible = "allwinner,sun4i-a10-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
1110 {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,}, 1136 {.compatible = "allwinner,sun5i-a10s-apb1-gates-clk", .data = &sun5i_a10s_apb1_gates_data,},
1111 {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,}, 1137 {.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
1112 {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,}, 1138 {.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
1113 {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,}, 1139 {.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
1114 {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,}, 1140 {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
1141 {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
1115 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, 1142 {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
1116 {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,}, 1143 {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
1117 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, 1144 {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
@@ -1200,3 +1227,9 @@ static void __init sun6i_init_clocks(struct device_node *node)
1200} 1227}
1201CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); 1228CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
1202CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); 1229CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
1230
1231static void __init sun9i_init_clocks(struct device_node *node)
1232{
1233 sunxi_init_clocks(NULL, 0);
1234}
1235CLK_OF_DECLARE(sun9i_a80_clk_init, "allwinner,sun9i-a80", sun9i_init_clocks);