aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-11-21 04:06:05 -0500
committerOlof Johansson <olof@lixom.net>2012-11-21 05:13:11 -0500
commit17bffc78438d010c3e57ad5c1956e3ab50be423a (patch)
treeb69583a61ba780be64ce806c208bc170ff44fa4f /drivers/clk
parentf86804af89686562fdeeabbdc0dfc6db9397f202 (diff)
parentbcd6f569e87471d7f104bd9497f0b516a3b12e32 (diff)
Merge branch 'depends/clk' into next/soc
From Mike Turquette: * depends/clk: clk: Common clocks implementation for Versatile Express clk: Versatile Express clock generators ("osc") driver CLK: clk-twl6040: Initial clock driver for OMAP4+ McPDM fclk clock clk: fix return value check in sirfsoc_of_clk_init() clk: fix return value check in of_fixed_clk_setup() clk: ux500: Update sdmmc clock to 100MHz for u8500 clk: ux500: Support prcmu ape opp voltage clock mfd: dbx500: Export prmcu_request_ape_opp_100_voltage clk: Don't return negative numbers for unsigned values with !clk clk: Fix documentation typos clk: Document .is_enabled op clk: SPEAr: Vco-pll: Fix compilation warning
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig16
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-fixed-rate.c2
-rw-r--r--drivers/clk/clk-prima2.c84
-rw-r--r--drivers/clk/clk-twl6040.c126
-rw-r--r--drivers/clk/clk.c20
-rw-r--r--drivers/clk/spear/clk-vco-pll.c2
-rw-r--r--drivers/clk/ux500/clk-prcmu.c55
-rw-r--r--drivers/clk/ux500/clk.h6
-rw-r--r--drivers/clk/ux500/u8500_clk.c5
-rw-r--r--drivers/clk/versatile/Makefile2
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c146
-rw-r--r--drivers/clk/versatile/clk-vexpress.c142
13 files changed, 548 insertions, 59 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index bace9e98f75d..823f62d900ba 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -42,10 +42,12 @@ config COMMON_CLK_WM831X
42 42
43config COMMON_CLK_VERSATILE 43config COMMON_CLK_VERSATILE
44 bool "Clock driver for ARM Reference designs" 44 bool "Clock driver for ARM Reference designs"
45 depends on ARCH_INTEGRATOR || ARCH_REALVIEW 45 depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS
46 ---help--- 46 ---help---
47 Supports clocking on ARM Reference designs Integrator/AP, 47 Supports clocking on ARM Reference designs:
48 Integrator/CP, RealView PB1176, EB, PB11MP and PBX. 48 - Integrator/AP and Integrator/CP
49 - RealView PB1176, EB, PB11MP and PBX
50 - Versatile Express
49 51
50config COMMON_CLK_MAX77686 52config COMMON_CLK_MAX77686
51 tristate "Clock driver for Maxim 77686 MFD" 53 tristate "Clock driver for Maxim 77686 MFD"
@@ -53,4 +55,12 @@ config COMMON_CLK_MAX77686
53 ---help--- 55 ---help---
54 This driver supports Maxim 77686 crystal oscillator clock. 56 This driver supports Maxim 77686 crystal oscillator clock.
55 57
58config CLK_TWL6040
59 tristate "External McPDM functional clock from twl6040"
60 depends on TWL6040_CORE
61 ---help---
62 Enable the external functional clock support on OMAP4+ platforms for
63 McPDM. McPDM module is using the external bit clock on the McPDM bus
64 as functional clock.
65
56endmenu 66endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 9c300a828ede..a96bda3d3b84 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o
24# Chip specific 24# Chip specific
25obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o 25obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
26obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o 26obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
27obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index f5ec0eebd4d7..af78ed6b67ef 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -97,7 +97,7 @@ void __init of_fixed_clk_setup(struct device_node *node)
97 of_property_read_string(node, "clock-output-names", &clk_name); 97 of_property_read_string(node, "clock-output-names", &clk_name);
98 98
99 clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); 99 clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
100 if (clk) 100 if (!IS_ERR(clk))
101 of_clk_add_provider(node, of_clk_src_simple_get, clk); 101 of_clk_add_provider(node, of_clk_src_simple_get, clk);
102} 102}
103EXPORT_SYMBOL_GPL(of_fixed_clk_setup); 103EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
index 517874fa6858..a203ecccdc4f 100644
--- a/drivers/clk/clk-prima2.c
+++ b/drivers/clk/clk-prima2.c
@@ -1054,118 +1054,118 @@ void __init sirfsoc_of_clk_init(void)
1054 /* These are always available (RTC and 26MHz OSC)*/ 1054 /* These are always available (RTC and 26MHz OSC)*/
1055 clk = clk_register_fixed_rate(NULL, "rtc", NULL, 1055 clk = clk_register_fixed_rate(NULL, "rtc", NULL,
1056 CLK_IS_ROOT, 32768); 1056 CLK_IS_ROOT, 32768);
1057 BUG_ON(!clk); 1057 BUG_ON(IS_ERR(clk));
1058 clk = clk_register_fixed_rate(NULL, "osc", NULL, 1058 clk = clk_register_fixed_rate(NULL, "osc", NULL,
1059 CLK_IS_ROOT, 26000000); 1059 CLK_IS_ROOT, 26000000);
1060 BUG_ON(!clk); 1060 BUG_ON(IS_ERR(clk));
1061 1061
1062 clk = clk_register(NULL, &clk_pll1.hw); 1062 clk = clk_register(NULL, &clk_pll1.hw);
1063 BUG_ON(!clk); 1063 BUG_ON(IS_ERR(clk));
1064 clk = clk_register(NULL, &clk_pll2.hw); 1064 clk = clk_register(NULL, &clk_pll2.hw);
1065 BUG_ON(!clk); 1065 BUG_ON(IS_ERR(clk));
1066 clk = clk_register(NULL, &clk_pll3.hw); 1066 clk = clk_register(NULL, &clk_pll3.hw);
1067 BUG_ON(!clk); 1067 BUG_ON(IS_ERR(clk));
1068 clk = clk_register(NULL, &clk_mem.hw); 1068 clk = clk_register(NULL, &clk_mem.hw);
1069 BUG_ON(!clk); 1069 BUG_ON(IS_ERR(clk));
1070 clk = clk_register(NULL, &clk_sys.hw); 1070 clk = clk_register(NULL, &clk_sys.hw);
1071 BUG_ON(!clk); 1071 BUG_ON(IS_ERR(clk));
1072 clk = clk_register(NULL, &clk_security.hw); 1072 clk = clk_register(NULL, &clk_security.hw);
1073 BUG_ON(!clk); 1073 BUG_ON(IS_ERR(clk));
1074 clk_register_clkdev(clk, NULL, "b8030000.security"); 1074 clk_register_clkdev(clk, NULL, "b8030000.security");
1075 clk = clk_register(NULL, &clk_dsp.hw); 1075 clk = clk_register(NULL, &clk_dsp.hw);
1076 BUG_ON(!clk); 1076 BUG_ON(IS_ERR(clk));
1077 clk = clk_register(NULL, &clk_gps.hw); 1077 clk = clk_register(NULL, &clk_gps.hw);
1078 BUG_ON(!clk); 1078 BUG_ON(IS_ERR(clk));
1079 clk_register_clkdev(clk, NULL, "a8010000.gps"); 1079 clk_register_clkdev(clk, NULL, "a8010000.gps");
1080 clk = clk_register(NULL, &clk_mf.hw); 1080 clk = clk_register(NULL, &clk_mf.hw);
1081 BUG_ON(!clk); 1081 BUG_ON(IS_ERR(clk));
1082 clk = clk_register(NULL, &clk_io.hw); 1082 clk = clk_register(NULL, &clk_io.hw);
1083 BUG_ON(!clk); 1083 BUG_ON(IS_ERR(clk));
1084 clk_register_clkdev(clk, NULL, "io"); 1084 clk_register_clkdev(clk, NULL, "io");
1085 clk = clk_register(NULL, &clk_cpu.hw); 1085 clk = clk_register(NULL, &clk_cpu.hw);
1086 BUG_ON(!clk); 1086 BUG_ON(IS_ERR(clk));
1087 clk_register_clkdev(clk, NULL, "cpu"); 1087 clk_register_clkdev(clk, NULL, "cpu");
1088 clk = clk_register(NULL, &clk_uart0.hw); 1088 clk = clk_register(NULL, &clk_uart0.hw);
1089 BUG_ON(!clk); 1089 BUG_ON(IS_ERR(clk));
1090 clk_register_clkdev(clk, NULL, "b0050000.uart"); 1090 clk_register_clkdev(clk, NULL, "b0050000.uart");
1091 clk = clk_register(NULL, &clk_uart1.hw); 1091 clk = clk_register(NULL, &clk_uart1.hw);
1092 BUG_ON(!clk); 1092 BUG_ON(IS_ERR(clk));
1093 clk_register_clkdev(clk, NULL, "b0060000.uart"); 1093 clk_register_clkdev(clk, NULL, "b0060000.uart");
1094 clk = clk_register(NULL, &clk_uart2.hw); 1094 clk = clk_register(NULL, &clk_uart2.hw);
1095 BUG_ON(!clk); 1095 BUG_ON(IS_ERR(clk));
1096 clk_register_clkdev(clk, NULL, "b0070000.uart"); 1096 clk_register_clkdev(clk, NULL, "b0070000.uart");
1097 clk = clk_register(NULL, &clk_tsc.hw); 1097 clk = clk_register(NULL, &clk_tsc.hw);
1098 BUG_ON(!clk); 1098 BUG_ON(IS_ERR(clk));
1099 clk_register_clkdev(clk, NULL, "b0110000.tsc"); 1099 clk_register_clkdev(clk, NULL, "b0110000.tsc");
1100 clk = clk_register(NULL, &clk_i2c0.hw); 1100 clk = clk_register(NULL, &clk_i2c0.hw);
1101 BUG_ON(!clk); 1101 BUG_ON(IS_ERR(clk));
1102 clk_register_clkdev(clk, NULL, "b00e0000.i2c"); 1102 clk_register_clkdev(clk, NULL, "b00e0000.i2c");
1103 clk = clk_register(NULL, &clk_i2c1.hw); 1103 clk = clk_register(NULL, &clk_i2c1.hw);
1104 BUG_ON(!clk); 1104 BUG_ON(IS_ERR(clk));
1105 clk_register_clkdev(clk, NULL, "b00f0000.i2c"); 1105 clk_register_clkdev(clk, NULL, "b00f0000.i2c");
1106 clk = clk_register(NULL, &clk_spi0.hw); 1106 clk = clk_register(NULL, &clk_spi0.hw);
1107 BUG_ON(!clk); 1107 BUG_ON(IS_ERR(clk));
1108 clk_register_clkdev(clk, NULL, "b00d0000.spi"); 1108 clk_register_clkdev(clk, NULL, "b00d0000.spi");
1109 clk = clk_register(NULL, &clk_spi1.hw); 1109 clk = clk_register(NULL, &clk_spi1.hw);
1110 BUG_ON(!clk); 1110 BUG_ON(IS_ERR(clk));
1111 clk_register_clkdev(clk, NULL, "b0170000.spi"); 1111 clk_register_clkdev(clk, NULL, "b0170000.spi");
1112 clk = clk_register(NULL, &clk_pwmc.hw); 1112 clk = clk_register(NULL, &clk_pwmc.hw);
1113 BUG_ON(!clk); 1113 BUG_ON(IS_ERR(clk));
1114 clk_register_clkdev(clk, NULL, "b0130000.pwm"); 1114 clk_register_clkdev(clk, NULL, "b0130000.pwm");
1115 clk = clk_register(NULL, &clk_efuse.hw); 1115 clk = clk_register(NULL, &clk_efuse.hw);
1116 BUG_ON(!clk); 1116 BUG_ON(IS_ERR(clk));
1117 clk_register_clkdev(clk, NULL, "b0140000.efusesys"); 1117 clk_register_clkdev(clk, NULL, "b0140000.efusesys");
1118 clk = clk_register(NULL, &clk_pulse.hw); 1118 clk = clk_register(NULL, &clk_pulse.hw);
1119 BUG_ON(!clk); 1119 BUG_ON(IS_ERR(clk));
1120 clk_register_clkdev(clk, NULL, "b0150000.pulsec"); 1120 clk_register_clkdev(clk, NULL, "b0150000.pulsec");
1121 clk = clk_register(NULL, &clk_dmac0.hw); 1121 clk = clk_register(NULL, &clk_dmac0.hw);
1122 BUG_ON(!clk); 1122 BUG_ON(IS_ERR(clk));
1123 clk_register_clkdev(clk, NULL, "b00b0000.dma-controller"); 1123 clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
1124 clk = clk_register(NULL, &clk_dmac1.hw); 1124 clk = clk_register(NULL, &clk_dmac1.hw);
1125 BUG_ON(!clk); 1125 BUG_ON(IS_ERR(clk));
1126 clk_register_clkdev(clk, NULL, "b0160000.dma-controller"); 1126 clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
1127 clk = clk_register(NULL, &clk_nand.hw); 1127 clk = clk_register(NULL, &clk_nand.hw);
1128 BUG_ON(!clk); 1128 BUG_ON(IS_ERR(clk));
1129 clk_register_clkdev(clk, NULL, "b0030000.nand"); 1129 clk_register_clkdev(clk, NULL, "b0030000.nand");
1130 clk = clk_register(NULL, &clk_audio.hw); 1130 clk = clk_register(NULL, &clk_audio.hw);
1131 BUG_ON(!clk); 1131 BUG_ON(IS_ERR(clk));
1132 clk_register_clkdev(clk, NULL, "b0040000.audio"); 1132 clk_register_clkdev(clk, NULL, "b0040000.audio");
1133 clk = clk_register(NULL, &clk_usp0.hw); 1133 clk = clk_register(NULL, &clk_usp0.hw);
1134 BUG_ON(!clk); 1134 BUG_ON(IS_ERR(clk));
1135 clk_register_clkdev(clk, NULL, "b0080000.usp"); 1135 clk_register_clkdev(clk, NULL, "b0080000.usp");
1136 clk = clk_register(NULL, &clk_usp1.hw); 1136 clk = clk_register(NULL, &clk_usp1.hw);
1137 BUG_ON(!clk); 1137 BUG_ON(IS_ERR(clk));
1138 clk_register_clkdev(clk, NULL, "b0090000.usp"); 1138 clk_register_clkdev(clk, NULL, "b0090000.usp");
1139 clk = clk_register(NULL, &clk_usp2.hw); 1139 clk = clk_register(NULL, &clk_usp2.hw);
1140 BUG_ON(!clk); 1140 BUG_ON(IS_ERR(clk));
1141 clk_register_clkdev(clk, NULL, "b00a0000.usp"); 1141 clk_register_clkdev(clk, NULL, "b00a0000.usp");
1142 clk = clk_register(NULL, &clk_vip.hw); 1142 clk = clk_register(NULL, &clk_vip.hw);
1143 BUG_ON(!clk); 1143 BUG_ON(IS_ERR(clk));
1144 clk_register_clkdev(clk, NULL, "b00c0000.vip"); 1144 clk_register_clkdev(clk, NULL, "b00c0000.vip");
1145 clk = clk_register(NULL, &clk_gfx.hw); 1145 clk = clk_register(NULL, &clk_gfx.hw);
1146 BUG_ON(!clk); 1146 BUG_ON(IS_ERR(clk));
1147 clk_register_clkdev(clk, NULL, "98000000.graphics"); 1147 clk_register_clkdev(clk, NULL, "98000000.graphics");
1148 clk = clk_register(NULL, &clk_mm.hw); 1148 clk = clk_register(NULL, &clk_mm.hw);
1149 BUG_ON(!clk); 1149 BUG_ON(IS_ERR(clk));
1150 clk_register_clkdev(clk, NULL, "a0000000.multimedia"); 1150 clk_register_clkdev(clk, NULL, "a0000000.multimedia");
1151 clk = clk_register(NULL, &clk_lcd.hw); 1151 clk = clk_register(NULL, &clk_lcd.hw);
1152 BUG_ON(!clk); 1152 BUG_ON(IS_ERR(clk));
1153 clk_register_clkdev(clk, NULL, "90010000.display"); 1153 clk_register_clkdev(clk, NULL, "90010000.display");
1154 clk = clk_register(NULL, &clk_vpp.hw); 1154 clk = clk_register(NULL, &clk_vpp.hw);
1155 BUG_ON(!clk); 1155 BUG_ON(IS_ERR(clk));
1156 clk_register_clkdev(clk, NULL, "90020000.vpp"); 1156 clk_register_clkdev(clk, NULL, "90020000.vpp");
1157 clk = clk_register(NULL, &clk_mmc01.hw); 1157 clk = clk_register(NULL, &clk_mmc01.hw);
1158 BUG_ON(!clk); 1158 BUG_ON(IS_ERR(clk));
1159 clk = clk_register(NULL, &clk_mmc23.hw); 1159 clk = clk_register(NULL, &clk_mmc23.hw);
1160 BUG_ON(!clk); 1160 BUG_ON(IS_ERR(clk));
1161 clk = clk_register(NULL, &clk_mmc45.hw); 1161 clk = clk_register(NULL, &clk_mmc45.hw);
1162 BUG_ON(!clk); 1162 BUG_ON(IS_ERR(clk));
1163 clk = clk_register(NULL, &usb_pll_clk_hw); 1163 clk = clk_register(NULL, &usb_pll_clk_hw);
1164 BUG_ON(!clk); 1164 BUG_ON(IS_ERR(clk));
1165 clk = clk_register(NULL, &clk_usb0.hw); 1165 clk = clk_register(NULL, &clk_usb0.hw);
1166 BUG_ON(!clk); 1166 BUG_ON(IS_ERR(clk));
1167 clk_register_clkdev(clk, NULL, "b00e0000.usb"); 1167 clk_register_clkdev(clk, NULL, "b00e0000.usb");
1168 clk = clk_register(NULL, &clk_usb1.hw); 1168 clk = clk_register(NULL, &clk_usb1.hw);
1169 BUG_ON(!clk); 1169 BUG_ON(IS_ERR(clk));
1170 clk_register_clkdev(clk, NULL, "b00f0000.usb"); 1170 clk_register_clkdev(clk, NULL, "b00f0000.usb");
1171} 1171}
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
new file mode 100644
index 000000000000..f4a3389c3d09
--- /dev/null
+++ b/drivers/clk/clk-twl6040.c
@@ -0,0 +1,126 @@
1/*
2* TWL6040 clock module driver for OMAP4 McPDM functional clock
3*
4* Copyright (C) 2012 Texas Instruments Inc.
5* Peter Ujfalusi <peter.ujfalusi@ti.com>
6*
7* This program is free software; you can redistribute it and/or
8* modify it under the terms of the GNU General Public License
9* version 2 as published by the Free Software Foundation.
10*
11* This program is distributed in the hope that it will be useful, but
12* WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14* General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program; if not, write to the Free Software
18* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19* 02110-1301 USA
20*
21*/
22
23#include <linux/clk.h>
24#include <linux/module.h>
25#include <linux/slab.h>
26#include <linux/platform_device.h>
27#include <linux/mfd/twl6040.h>
28#include <linux/clk-provider.h>
29
30struct twl6040_clk {
31 struct twl6040 *twl6040;
32 struct device *dev;
33 struct clk_hw mcpdm_fclk;
34 struct clk *clk;
35 int enabled;
36};
37
38static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
39{
40 struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
41 mcpdm_fclk);
42 return twl6040_clk->enabled;
43}
44
45static int twl6040_bitclk_prepare(struct clk_hw *hw)
46{
47 struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
48 mcpdm_fclk);
49 int ret;
50
51 ret = twl6040_power(twl6040_clk->twl6040, 1);
52 if (!ret)
53 twl6040_clk->enabled = 1;
54
55 return ret;
56}
57
58static void twl6040_bitclk_unprepare(struct clk_hw *hw)
59{
60 struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
61 mcpdm_fclk);
62 int ret;
63
64 ret = twl6040_power(twl6040_clk->twl6040, 0);
65 if (!ret)
66 twl6040_clk->enabled = 0;
67}
68
69static const struct clk_ops twl6040_mcpdm_ops = {
70 .is_enabled = twl6040_bitclk_is_enabled,
71 .prepare = twl6040_bitclk_prepare,
72 .unprepare = twl6040_bitclk_unprepare,
73};
74
75static struct clk_init_data wm831x_clkout_init = {
76 .name = "mcpdm_fclk",
77 .ops = &twl6040_mcpdm_ops,
78 .flags = CLK_IS_ROOT,
79};
80
81static int __devinit twl6040_clk_probe(struct platform_device *pdev)
82{
83 struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
84 struct twl6040_clk *clkdata;
85
86 clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
87 if (!clkdata)
88 return -ENOMEM;
89
90 clkdata->dev = &pdev->dev;
91 clkdata->twl6040 = twl6040;
92
93 clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
94 clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
95 if (!clkdata->clk)
96 return -EINVAL;
97
98 dev_set_drvdata(&pdev->dev, clkdata);
99
100 return 0;
101}
102
103static int __devexit twl6040_clk_remove(struct platform_device *pdev)
104{
105 struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
106
107 clk_unregister(clkdata->clk);
108
109 return 0;
110}
111
112static struct platform_driver twl6040_clk_driver = {
113 .driver = {
114 .name = "twl6040-clk",
115 .owner = THIS_MODULE,
116 },
117 .probe = twl6040_clk_probe,
118 .remove = __devexit_p(twl6040_clk_remove),
119};
120
121module_platform_driver(twl6040_clk_driver);
122
123MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
124MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
125MODULE_ALIAS("platform:twl6040-clk");
126MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 56e4495ebeb1..bbe52c4ae7ca 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -261,7 +261,7 @@ inline struct clk_hw *__clk_get_hw(struct clk *clk)
261 261
262inline u8 __clk_get_num_parents(struct clk *clk) 262inline u8 __clk_get_num_parents(struct clk *clk)
263{ 263{
264 return !clk ? -EINVAL : clk->num_parents; 264 return !clk ? 0 : clk->num_parents;
265} 265}
266 266
267inline struct clk *__clk_get_parent(struct clk *clk) 267inline struct clk *__clk_get_parent(struct clk *clk)
@@ -269,14 +269,14 @@ inline struct clk *__clk_get_parent(struct clk *clk)
269 return !clk ? NULL : clk->parent; 269 return !clk ? NULL : clk->parent;
270} 270}
271 271
272inline int __clk_get_enable_count(struct clk *clk) 272inline unsigned int __clk_get_enable_count(struct clk *clk)
273{ 273{
274 return !clk ? -EINVAL : clk->enable_count; 274 return !clk ? 0 : clk->enable_count;
275} 275}
276 276
277inline int __clk_get_prepare_count(struct clk *clk) 277inline unsigned int __clk_get_prepare_count(struct clk *clk)
278{ 278{
279 return !clk ? -EINVAL : clk->prepare_count; 279 return !clk ? 0 : clk->prepare_count;
280} 280}
281 281
282unsigned long __clk_get_rate(struct clk *clk) 282unsigned long __clk_get_rate(struct clk *clk)
@@ -302,15 +302,15 @@ out:
302 302
303inline unsigned long __clk_get_flags(struct clk *clk) 303inline unsigned long __clk_get_flags(struct clk *clk)
304{ 304{
305 return !clk ? -EINVAL : clk->flags; 305 return !clk ? 0 : clk->flags;
306} 306}
307 307
308int __clk_is_enabled(struct clk *clk) 308bool __clk_is_enabled(struct clk *clk)
309{ 309{
310 int ret; 310 int ret;
311 311
312 if (!clk) 312 if (!clk)
313 return -EINVAL; 313 return false;
314 314
315 /* 315 /*
316 * .is_enabled is only mandatory for clocks that gate 316 * .is_enabled is only mandatory for clocks that gate
@@ -323,7 +323,7 @@ int __clk_is_enabled(struct clk *clk)
323 323
324 ret = clk->ops->is_enabled(clk->hw); 324 ret = clk->ops->is_enabled(clk->hw);
325out: 325out:
326 return ret; 326 return !!ret;
327} 327}
328 328
329static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk) 329static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
@@ -568,7 +568,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
568 unsigned long parent_rate = 0; 568 unsigned long parent_rate = 0;
569 569
570 if (!clk) 570 if (!clk)
571 return -EINVAL; 571 return 0;
572 572
573 if (!clk->ops->round_rate) { 573 if (!clk->ops->round_rate) {
574 if (clk->flags & CLK_SET_RATE_PARENT) 574 if (clk->flags & CLK_SET_RATE_PARENT)
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
index 5f1b6badeb15..1b9b65bca51e 100644
--- a/drivers/clk/spear/clk-vco-pll.c
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -147,7 +147,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
147 struct clk_pll *pll = to_clk_pll(hw); 147 struct clk_pll *pll = to_clk_pll(hw);
148 struct pll_rate_tbl *rtbl = pll->vco->rtbl; 148 struct pll_rate_tbl *rtbl = pll->vco->rtbl;
149 unsigned long flags = 0, val; 149 unsigned long flags = 0, val;
150 int i; 150 int uninitialized_var(i);
151 151
152 clk_pll_round_rate_index(hw, drate, NULL, &i); 152 clk_pll_round_rate_index(hw, drate, NULL, &i);
153 153
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 930cdfeb47ab..04577ca6a308 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -133,6 +133,40 @@ out_error:
133 hw->init->name); 133 hw->init->name);
134} 134}
135 135
136static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
137{
138 int err;
139 struct clk_prcmu *clk = to_clk_prcmu(hw);
140
141 err = prcmu_request_ape_opp_100_voltage(true);
142 if (err) {
143 pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
144 __func__, hw->init->name);
145 return err;
146 }
147
148 err = prcmu_request_clock(clk->cg_sel, true);
149 if (err)
150 prcmu_request_ape_opp_100_voltage(false);
151
152 return err;
153}
154
155static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
156{
157 struct clk_prcmu *clk = to_clk_prcmu(hw);
158
159 if (prcmu_request_clock(clk->cg_sel, false))
160 goto out_error;
161 if (prcmu_request_ape_opp_100_voltage(false))
162 goto out_error;
163 return;
164
165out_error:
166 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
167 hw->init->name);
168}
169
136static struct clk_ops clk_prcmu_scalable_ops = { 170static struct clk_ops clk_prcmu_scalable_ops = {
137 .prepare = clk_prcmu_prepare, 171 .prepare = clk_prcmu_prepare,
138 .unprepare = clk_prcmu_unprepare, 172 .unprepare = clk_prcmu_unprepare,
@@ -167,6 +201,17 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
167 .recalc_rate = clk_prcmu_recalc_rate, 201 .recalc_rate = clk_prcmu_recalc_rate,
168}; 202};
169 203
204static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
205 .prepare = clk_prcmu_opp_volt_prepare,
206 .unprepare = clk_prcmu_opp_volt_unprepare,
207 .enable = clk_prcmu_enable,
208 .disable = clk_prcmu_disable,
209 .is_enabled = clk_prcmu_is_enabled,
210 .recalc_rate = clk_prcmu_recalc_rate,
211 .round_rate = clk_prcmu_round_rate,
212 .set_rate = clk_prcmu_set_rate,
213};
214
170static struct clk *clk_reg_prcmu(const char *name, 215static struct clk *clk_reg_prcmu(const char *name,
171 const char *parent_name, 216 const char *parent_name,
172 u8 cg_sel, 217 u8 cg_sel,
@@ -250,3 +295,13 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
250 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 295 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
251 &clk_prcmu_opp_gate_ops); 296 &clk_prcmu_opp_gate_ops);
252} 297}
298
299struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
300 const char *parent_name,
301 u8 cg_sel,
302 unsigned long rate,
303 unsigned long flags)
304{
305 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
306 &clk_prcmu_opp_volt_scalable_ops);
307}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
index 836d7d16751e..f36eeedca493 100644
--- a/drivers/clk/ux500/clk.h
+++ b/drivers/clk/ux500/clk.h
@@ -45,4 +45,10 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
45 u8 cg_sel, 45 u8 cg_sel,
46 unsigned long flags); 46 unsigned long flags);
47 47
48struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
49 const char *parent_name,
50 u8 cg_sel,
51 unsigned long rate,
52 unsigned long flags);
53
48#endif /* __UX500_CLK_H */ 54#endif /* __UX500_CLK_H */
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index ca4a25ed844c..7bebf1f62c65 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -170,10 +170,11 @@ void u8500_clk_init(void)
170 clk_register_clkdev(clk, NULL, "mtu0"); 170 clk_register_clkdev(clk, NULL, "mtu0");
171 clk_register_clkdev(clk, NULL, "mtu1"); 171 clk_register_clkdev(clk, NULL, "mtu1");
172 172
173 clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT); 173 clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
174 100000000,
175 CLK_IS_ROOT|CLK_SET_RATE_GATE);
174 clk_register_clkdev(clk, NULL, "sdmmc"); 176 clk_register_clkdev(clk, NULL, "sdmmc");
175 177
176
177 clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", 178 clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
178 PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); 179 PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
179 clk_register_clkdev(clk, "dsihs2", "mcde"); 180 clk_register_clkdev(clk, "dsihs2", "mcde");
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c0a0f6478798..c776053e5bb4 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -2,3 +2,5 @@
2obj-$(CONFIG_ICST) += clk-icst.o 2obj-$(CONFIG_ICST) += clk-icst.o
3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o 3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o 4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
5obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
6obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
new file mode 100644
index 000000000000..dcb6ae0a0425
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -0,0 +1,146 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2012 ARM Limited
12 */
13
14#define pr_fmt(fmt) "vexpress-osc: " fmt
15
16#include <linux/clkdev.h>
17#include <linux/clk-provider.h>
18#include <linux/err.h>
19#include <linux/of.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/vexpress.h>
23
24struct vexpress_osc {
25 struct vexpress_config_func *func;
26 struct clk_hw hw;
27 unsigned long rate_min;
28 unsigned long rate_max;
29};
30
31#define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw)
32
33static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
34 unsigned long parent_rate)
35{
36 struct vexpress_osc *osc = to_vexpress_osc(hw);
37 u32 rate;
38
39 vexpress_config_read(osc->func, 0, &rate);
40
41 return rate;
42}
43
44static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
45 unsigned long *parent_rate)
46{
47 struct vexpress_osc *osc = to_vexpress_osc(hw);
48
49 if (WARN_ON(osc->rate_min && rate < osc->rate_min))
50 rate = osc->rate_min;
51
52 if (WARN_ON(osc->rate_max && rate > osc->rate_max))
53 rate = osc->rate_max;
54
55 return rate;
56}
57
58static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
59 unsigned long parent_rate)
60{
61 struct vexpress_osc *osc = to_vexpress_osc(hw);
62
63 return vexpress_config_write(osc->func, 0, rate);
64}
65
66static struct clk_ops vexpress_osc_ops = {
67 .recalc_rate = vexpress_osc_recalc_rate,
68 .round_rate = vexpress_osc_round_rate,
69 .set_rate = vexpress_osc_set_rate,
70};
71
72
73struct clk * __init vexpress_osc_setup(struct device *dev)
74{
75 struct clk_init_data init;
76 struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
77
78 if (!osc)
79 return NULL;
80
81 osc->func = vexpress_config_func_get_by_dev(dev);
82 if (!osc->func) {
83 kfree(osc);
84 return NULL;
85 }
86
87 init.name = dev_name(dev);
88 init.ops = &vexpress_osc_ops;
89 init.flags = CLK_IS_ROOT;
90 init.num_parents = 0;
91 osc->hw.init = &init;
92
93 return clk_register(NULL, &osc->hw);
94}
95
96void __init vexpress_osc_of_setup(struct device_node *node)
97{
98 struct clk_init_data init;
99 struct vexpress_osc *osc;
100 struct clk *clk;
101 u32 range[2];
102
103 osc = kzalloc(sizeof(*osc), GFP_KERNEL);
104 if (!osc)
105 goto error;
106
107 osc->func = vexpress_config_func_get_by_node(node);
108 if (!osc->func) {
109 pr_err("Failed to obtain config func for node '%s'!\n",
110 node->name);
111 goto error;
112 }
113
114 if (of_property_read_u32_array(node, "freq-range", range,
115 ARRAY_SIZE(range)) == 0) {
116 osc->rate_min = range[0];
117 osc->rate_max = range[1];
118 }
119
120 of_property_read_string(node, "clock-output-names", &init.name);
121 if (!init.name)
122 init.name = node->name;
123
124 init.ops = &vexpress_osc_ops;
125 init.flags = CLK_IS_ROOT;
126 init.num_parents = 0;
127
128 osc->hw.init = &init;
129
130 clk = clk_register(NULL, &osc->hw);
131 if (IS_ERR(clk)) {
132 pr_err("Failed to register clock '%s'!\n", init.name);
133 goto error;
134 }
135
136 of_clk_add_provider(node, of_clk_src_simple_get, clk);
137
138 pr_debug("Registered clock '%s'\n", init.name);
139
140 return;
141
142error:
143 if (osc->func)
144 vexpress_config_func_put(osc->func);
145 kfree(osc);
146}
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c
new file mode 100644
index 000000000000..c742ac7c60bb
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress.c
@@ -0,0 +1,142 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * Copyright (C) 2012 ARM Limited
12 */
13
14#include <linux/clkdev.h>
15#include <linux/clk-provider.h>
16#include <linux/err.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/vexpress.h>
20
21#include <asm/hardware/sp810.h>
22
23static struct clk *vexpress_sp810_timerclken[4];
24static DEFINE_SPINLOCK(vexpress_sp810_lock);
25
26static void __init vexpress_sp810_init(void __iomem *base)
27{
28 int i;
29
30 if (WARN_ON(!base))
31 return;
32
33 for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
34 char name[12];
35 const char *parents[] = {
36 "v2m:refclk32khz", /* REFCLK */
37 "v2m:refclk1mhz" /* TIMCLK */
38 };
39
40 snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
41
42 vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
43 parents, 2, 0, base + SCCTRL,
44 SCCTRL_TIMERENnSEL_SHIFT(i), 1,
45 0, &vexpress_sp810_lock);
46
47 if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
48 break;
49 }
50}
51
52
53static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
54 "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
55 "mb:mmci", "mb:kmi0", "mb:kmi1"
56};
57
58void __init vexpress_clk_init(void __iomem *sp810_base)
59{
60 struct clk *clk;
61 int i;
62
63 clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
64 CLK_IS_ROOT, 0);
65 WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
66
67 clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
68 CLK_IS_ROOT, 24000000);
69 for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
70 WARN_ON(clk_register_clkdev(clk, NULL,
71 vexpress_clk_24mhz_periphs[i]));
72
73 clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
74 CLK_IS_ROOT, 32768);
75 WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
76
77 clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
78 CLK_IS_ROOT, 1000000);
79
80 vexpress_sp810_init(sp810_base);
81
82 for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
83 WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
84
85 WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
86 "v2m-timer0", "sp804"));
87 WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
88 "v2m-timer1", "sp804"));
89}
90
91#if defined(CONFIG_OF)
92
93struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
94{
95 if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
96 ARRAY_SIZE(vexpress_sp810_timerclken)))
97 return NULL;
98
99 return vexpress_sp810_timerclken[clkspec->args[0]];
100}
101
102static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
103 { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
104 { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
105 {}
106};
107
108void __init vexpress_clk_of_init(void)
109{
110 struct device_node *node;
111 struct clk *clk;
112 struct clk *refclk, *timclk;
113
114 of_clk_init(vexpress_fixed_clk_match);
115
116 node = of_find_compatible_node(NULL, NULL, "arm,sp810");
117 vexpress_sp810_init(of_iomap(node, 0));
118 of_clk_add_provider(node, vexpress_sp810_of_get, NULL);
119
120 /* Select "better" (faster) parent for SP804 timers */
121 refclk = of_clk_get_by_name(node, "refclk");
122 timclk = of_clk_get_by_name(node, "timclk");
123 if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) {
124 int i = 0;
125
126 if (clk_get_rate(refclk) > clk_get_rate(timclk))
127 clk = refclk;
128 else
129 clk = timclk;
130
131 for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
132 WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i],
133 clk));
134 }
135
136 WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
137 "v2m-timer0", "sp804"));
138 WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
139 "v2m-timer1", "sp804"));
140}
141
142#endif