diff options
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-msm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock-debug.c | 123 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock-pcom.c | 118 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock-pcom.h | 30 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.c | 146 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.h | 46 | ||||
-rw-r--r-- | arch/arm/mach-msm/devices-msm7x00.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-msm/devices-msm7x30.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-msm/devices-qsd8x50.c | 2 |
10 files changed, 108 insertions, 364 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d423d58f938d..af88c834a7c2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -622,8 +622,8 @@ config ARCH_MSM | |||
622 | bool "Qualcomm MSM" | 622 | bool "Qualcomm MSM" |
623 | select ARCH_REQUIRE_GPIOLIB | 623 | select ARCH_REQUIRE_GPIOLIB |
624 | select CLKDEV_LOOKUP | 624 | select CLKDEV_LOOKUP |
625 | select COMMON_CLK | ||
625 | select GENERIC_CLOCKEVENTS | 626 | select GENERIC_CLOCKEVENTS |
626 | select HAVE_CLK | ||
627 | help | 627 | help |
628 | Support for Qualcomm MSM/QSD based systems. This runs on the | 628 | Support for Qualcomm MSM/QSD based systems. This runs on the |
629 | apps processor of the MSM/QSD and depends on a shared memory | 629 | apps processor of the MSM/QSD and depends on a shared memory |
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 3dbae7406e0f..700d77b7eb1a 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | obj-y += io.o timer.o | 1 | obj-y += io.o timer.o |
2 | obj-y += clock.o | 2 | obj-y += clock.o |
3 | obj-$(CONFIG_DEBUG_FS) += clock-debug.o | ||
4 | 3 | ||
5 | obj-$(CONFIG_MSM_VIC) += irq-vic.o | 4 | obj-$(CONFIG_MSM_VIC) += irq-vic.o |
6 | obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o | 5 | obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o |
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c deleted file mode 100644 index c4b34d7d26fb..000000000000 --- a/arch/arm/mach-msm/clock-debug.c +++ /dev/null | |||
@@ -1,123 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Google, Inc. | ||
3 | * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. | ||
4 | * | ||
5 | * This software is licensed under the terms of the GNU General Public | ||
6 | * License version 2, as published by the Free Software Foundation, and | ||
7 | * may be copied, distributed, and modified under those terms. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include "clock.h" | ||
22 | |||
23 | static int clock_debug_rate_set(void *data, u64 val) | ||
24 | { | ||
25 | struct clk *clock = data; | ||
26 | int ret; | ||
27 | |||
28 | ret = clk_set_rate(clock, val); | ||
29 | if (ret != 0) | ||
30 | printk(KERN_ERR "clk_set%s_rate failed (%d)\n", | ||
31 | (clock->flags & CLK_MIN) ? "_min" : "", ret); | ||
32 | return ret; | ||
33 | } | ||
34 | |||
35 | static int clock_debug_rate_get(void *data, u64 *val) | ||
36 | { | ||
37 | struct clk *clock = data; | ||
38 | *val = clk_get_rate(clock); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get, | ||
43 | clock_debug_rate_set, "%llu\n"); | ||
44 | |||
45 | static int clock_debug_enable_set(void *data, u64 val) | ||
46 | { | ||
47 | struct clk *clock = data; | ||
48 | int rc = 0; | ||
49 | |||
50 | if (val) | ||
51 | rc = clock->ops->enable(clock->id); | ||
52 | else | ||
53 | clock->ops->disable(clock->id); | ||
54 | |||
55 | return rc; | ||
56 | } | ||
57 | |||
58 | static int clock_debug_enable_get(void *data, u64 *val) | ||
59 | { | ||
60 | struct clk *clock = data; | ||
61 | |||
62 | *val = clock->ops->is_enabled(clock->id); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get, | ||
68 | clock_debug_enable_set, "%llu\n"); | ||
69 | |||
70 | static int clock_debug_local_get(void *data, u64 *val) | ||
71 | { | ||
72 | struct clk *clock = data; | ||
73 | |||
74 | *val = clock->ops->is_local(clock->id); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get, | ||
80 | NULL, "%llu\n"); | ||
81 | |||
82 | static struct dentry *debugfs_base; | ||
83 | |||
84 | int __init clock_debug_init(void) | ||
85 | { | ||
86 | debugfs_base = debugfs_create_dir("clk", NULL); | ||
87 | if (!debugfs_base) | ||
88 | return -ENOMEM; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int __init clock_debug_add(struct clk *clock) | ||
93 | { | ||
94 | char temp[50], *ptr; | ||
95 | struct dentry *clk_dir; | ||
96 | |||
97 | if (!debugfs_base) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1); | ||
101 | for (ptr = temp; *ptr; ptr++) | ||
102 | *ptr = tolower(*ptr); | ||
103 | |||
104 | clk_dir = debugfs_create_dir(temp, debugfs_base); | ||
105 | if (!clk_dir) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir, | ||
109 | clock, &clock_rate_fops)) | ||
110 | goto error; | ||
111 | |||
112 | if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir, | ||
113 | clock, &clock_enable_fops)) | ||
114 | goto error; | ||
115 | |||
116 | if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock, | ||
117 | &clock_local_fops)) | ||
118 | goto error; | ||
119 | return 0; | ||
120 | error: | ||
121 | debugfs_remove_recursive(clk_dir); | ||
122 | return -ENOMEM; | ||
123 | } | ||
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c index 632173186a69..9a80449518e6 100644 --- a/arch/arm/mach-msm/clock-pcom.c +++ b/arch/arm/mach-msm/clock-pcom.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007 Google, Inc. | 2 | * Copyright (C) 2007 Google, Inc. |
3 | * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. | 3 | * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. |
4 | * | 4 | * |
5 | * This software is licensed under the terms of the GNU General Public | 5 | * This software is licensed under the terms of the GNU General Public |
6 | * License version 2, as published by the Free Software Foundation, and | 6 | * License version 2, as published by the Free Software Foundation, and |
@@ -13,9 +13,12 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | ||
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/clk-provider.h> | ||
21 | #include <linux/clkdev.h> | ||
19 | 22 | ||
20 | #include <mach/clk.h> | 23 | #include <mach/clk.h> |
21 | 24 | ||
@@ -23,11 +26,20 @@ | |||
23 | #include "clock.h" | 26 | #include "clock.h" |
24 | #include "clock-pcom.h" | 27 | #include "clock-pcom.h" |
25 | 28 | ||
26 | /* | 29 | struct clk_pcom { |
27 | * glue for the proc_comm interface | 30 | unsigned id; |
28 | */ | 31 | unsigned long flags; |
29 | static int pc_clk_enable(unsigned id) | 32 | struct msm_clk msm_clk; |
33 | }; | ||
34 | |||
35 | static inline struct clk_pcom *to_clk_pcom(struct clk_hw *hw) | ||
30 | { | 36 | { |
37 | return container_of(to_msm_clk(hw), struct clk_pcom, msm_clk); | ||
38 | } | ||
39 | |||
40 | static int pc_clk_enable(struct clk_hw *hw) | ||
41 | { | ||
42 | unsigned id = to_clk_pcom(hw)->id; | ||
31 | int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); | 43 | int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); |
32 | if (rc < 0) | 44 | if (rc < 0) |
33 | return rc; | 45 | return rc; |
@@ -35,14 +47,16 @@ static int pc_clk_enable(unsigned id) | |||
35 | return (int)id < 0 ? -EINVAL : 0; | 47 | return (int)id < 0 ? -EINVAL : 0; |
36 | } | 48 | } |
37 | 49 | ||
38 | static void pc_clk_disable(unsigned id) | 50 | static void pc_clk_disable(struct clk_hw *hw) |
39 | { | 51 | { |
52 | unsigned id = to_clk_pcom(hw)->id; | ||
40 | msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); | 53 | msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); |
41 | } | 54 | } |
42 | 55 | ||
43 | int pc_clk_reset(unsigned id, enum clk_reset_action action) | 56 | static int pc_clk_reset(struct clk_hw *hw, enum clk_reset_action action) |
44 | { | 57 | { |
45 | int rc; | 58 | int rc; |
59 | unsigned id = to_clk_pcom(hw)->id; | ||
46 | 60 | ||
47 | if (action == CLK_RESET_ASSERT) | 61 | if (action == CLK_RESET_ASSERT) |
48 | rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL); | 62 | rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL); |
@@ -55,83 +69,99 @@ int pc_clk_reset(unsigned id, enum clk_reset_action action) | |||
55 | return (int)id < 0 ? -EINVAL : 0; | 69 | return (int)id < 0 ? -EINVAL : 0; |
56 | } | 70 | } |
57 | 71 | ||
58 | static int pc_clk_set_rate(unsigned id, unsigned rate) | 72 | static int pc_clk_set_rate(struct clk_hw *hw, unsigned long new_rate, |
73 | unsigned long p_rate) | ||
59 | { | 74 | { |
60 | /* The rate _might_ be rounded off to the nearest KHz value by the | 75 | struct clk_pcom *p = to_clk_pcom(hw); |
76 | unsigned id = p->id, rate = new_rate; | ||
77 | int rc; | ||
78 | |||
79 | /* | ||
80 | * The rate _might_ be rounded off to the nearest KHz value by the | ||
61 | * remote function. So a return value of 0 doesn't necessarily mean | 81 | * remote function. So a return value of 0 doesn't necessarily mean |
62 | * that the exact rate was set successfully. | 82 | * that the exact rate was set successfully. |
63 | */ | 83 | */ |
64 | int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); | 84 | if (p->flags & CLKFLAG_MIN) |
65 | if (rc < 0) | 85 | rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate); |
66 | return rc; | ||
67 | else | ||
68 | return (int)id < 0 ? -EINVAL : 0; | ||
69 | } | ||
70 | |||
71 | static int pc_clk_set_min_rate(unsigned id, unsigned rate) | ||
72 | { | ||
73 | int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate); | ||
74 | if (rc < 0) | ||
75 | return rc; | ||
76 | else | 86 | else |
77 | return (int)id < 0 ? -EINVAL : 0; | 87 | rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); |
78 | } | ||
79 | |||
80 | static int pc_clk_set_max_rate(unsigned id, unsigned rate) | ||
81 | { | ||
82 | int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate); | ||
83 | if (rc < 0) | 88 | if (rc < 0) |
84 | return rc; | 89 | return rc; |
85 | else | 90 | else |
86 | return (int)id < 0 ? -EINVAL : 0; | 91 | return (int)id < 0 ? -EINVAL : 0; |
87 | } | 92 | } |
88 | 93 | ||
89 | static unsigned pc_clk_get_rate(unsigned id) | 94 | static unsigned long pc_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate) |
90 | { | 95 | { |
96 | unsigned id = to_clk_pcom(hw)->id; | ||
91 | if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL)) | 97 | if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL)) |
92 | return 0; | 98 | return 0; |
93 | else | 99 | else |
94 | return id; | 100 | return id; |
95 | } | 101 | } |
96 | 102 | ||
97 | static unsigned pc_clk_is_enabled(unsigned id) | 103 | static int pc_clk_is_enabled(struct clk_hw *hw) |
98 | { | 104 | { |
105 | unsigned id = to_clk_pcom(hw)->id; | ||
99 | if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL)) | 106 | if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL)) |
100 | return 0; | 107 | return 0; |
101 | else | 108 | else |
102 | return id; | 109 | return id; |
103 | } | 110 | } |
104 | 111 | ||
105 | static long pc_clk_round_rate(unsigned id, unsigned rate) | 112 | static long pc_clk_round_rate(struct clk_hw *hw, unsigned long rate, |
113 | unsigned long *p_rate) | ||
106 | { | 114 | { |
107 | |||
108 | /* Not really supported; pc_clk_set_rate() does rounding on it's own. */ | 115 | /* Not really supported; pc_clk_set_rate() does rounding on it's own. */ |
109 | return rate; | 116 | return rate; |
110 | } | 117 | } |
111 | 118 | ||
112 | static bool pc_clk_is_local(unsigned id) | 119 | static struct clk_ops clk_ops_pcom = { |
113 | { | ||
114 | return false; | ||
115 | } | ||
116 | |||
117 | struct clk_ops clk_ops_pcom = { | ||
118 | .enable = pc_clk_enable, | 120 | .enable = pc_clk_enable, |
119 | .disable = pc_clk_disable, | 121 | .disable = pc_clk_disable, |
120 | .auto_off = pc_clk_disable, | ||
121 | .reset = pc_clk_reset, | ||
122 | .set_rate = pc_clk_set_rate, | 122 | .set_rate = pc_clk_set_rate, |
123 | .set_min_rate = pc_clk_set_min_rate, | 123 | .recalc_rate = pc_clk_recalc_rate, |
124 | .set_max_rate = pc_clk_set_max_rate, | ||
125 | .get_rate = pc_clk_get_rate, | ||
126 | .is_enabled = pc_clk_is_enabled, | 124 | .is_enabled = pc_clk_is_enabled, |
127 | .round_rate = pc_clk_round_rate, | 125 | .round_rate = pc_clk_round_rate, |
128 | .is_local = pc_clk_is_local, | ||
129 | }; | 126 | }; |
130 | 127 | ||
131 | static int msm_clock_pcom_probe(struct platform_device *pdev) | 128 | static int msm_clock_pcom_probe(struct platform_device *pdev) |
132 | { | 129 | { |
133 | const struct pcom_clk_pdata *pdata = pdev->dev.platform_data; | 130 | const struct pcom_clk_pdata *pdata = pdev->dev.platform_data; |
134 | msm_clock_init(pdata->lookup, pdata->num_lookups); | 131 | int i, ret; |
132 | |||
133 | for (i = 0; i < pdata->num_lookups; i++) { | ||
134 | const struct clk_pcom_desc *desc = &pdata->lookup[i]; | ||
135 | struct clk *c; | ||
136 | struct clk_pcom *p; | ||
137 | struct clk_hw *hw; | ||
138 | struct clk_init_data init; | ||
139 | |||
140 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | ||
141 | if (!p) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | p->id = desc->id; | ||
145 | p->flags = desc->flags; | ||
146 | p->msm_clk.reset = pc_clk_reset; | ||
147 | |||
148 | hw = &p->msm_clk.hw; | ||
149 | hw->init = &init; | ||
150 | |||
151 | init.name = desc->name; | ||
152 | init.ops = &clk_ops_pcom; | ||
153 | init.num_parents = 0; | ||
154 | init.flags = CLK_IS_ROOT; | ||
155 | |||
156 | if (!(p->flags & CLKFLAG_AUTO_OFF)) | ||
157 | init.flags |= CLK_IGNORE_UNUSED; | ||
158 | |||
159 | c = devm_clk_register(&pdev->dev, hw); | ||
160 | ret = clk_register_clkdev(c, desc->con, desc->dev); | ||
161 | if (ret) | ||
162 | return ret; | ||
163 | } | ||
164 | |||
135 | return 0; | 165 | return 0; |
136 | } | 166 | } |
137 | 167 | ||
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h index 87406a373d2b..5bb164fd46a8 100644 --- a/arch/arm/mach-msm/clock-pcom.h +++ b/arch/arm/mach-msm/clock-pcom.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | 1 | /* |
2 | * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | ||
2 | * | 3 | * |
3 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License version 2 and | 5 | * it under the terms of the GNU General Public License version 2 and |
@@ -120,26 +121,25 @@ | |||
120 | 121 | ||
121 | #define P_NR_CLKS 102 | 122 | #define P_NR_CLKS 102 |
122 | 123 | ||
123 | struct clk_ops; | 124 | struct clk_pcom_desc { |
124 | extern struct clk_ops clk_ops_pcom; | 125 | unsigned id; |
126 | const char *name; | ||
127 | const char *con; | ||
128 | const char *dev; | ||
129 | unsigned long flags; | ||
130 | }; | ||
125 | 131 | ||
126 | struct pcom_clk_pdata { | 132 | struct pcom_clk_pdata { |
127 | struct clk_lookup *lookup; | 133 | struct clk_pcom_desc *lookup; |
128 | u32 num_lookups; | 134 | u32 num_lookups; |
129 | }; | 135 | }; |
130 | 136 | ||
131 | int pc_clk_reset(unsigned id, enum clk_reset_action action); | ||
132 | |||
133 | #define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \ | 137 | #define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \ |
134 | .con_id = clk_name, \ | 138 | .id = P_##clk_id, \ |
135 | .dev_id = clk_dev, \ | 139 | .name = #clk_id, \ |
136 | .clk = &(struct clk){ \ | 140 | .con = clk_name, \ |
137 | .id = P_##clk_id, \ | 141 | .dev = clk_dev, \ |
138 | .remote_id = P_##clk_id, \ | 142 | .flags = clk_flags, \ |
139 | .ops = &clk_ops_pcom, \ | ||
140 | .flags = clk_flags, \ | ||
141 | .dbg_name = #clk_id, \ | ||
142 | }, \ | ||
143 | } | 143 | } |
144 | 144 | ||
145 | #endif | 145 | #endif |
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index d72dd3770298..35ea02b52483 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* arch/arm/mach-msm/clock.c | 1 | /* arch/arm/mach-msm/clock.c |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Google, Inc. | 3 | * Copyright (C) 2007 Google, Inc. |
4 | * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. | 4 | * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. |
5 | * | 5 | * |
6 | * This software is licensed under the terms of the GNU General Public | 6 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 7 | * License version 2, as published by the Free Software Foundation, and |
@@ -14,151 +14,15 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/clk-provider.h> |
18 | #include <linux/list.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/pm_qos.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/module.h> | 18 | #include <linux/module.h> |
26 | #include <linux/clkdev.h> | ||
27 | 19 | ||
28 | #include "clock.h" | 20 | #include "clock.h" |
29 | 21 | ||
30 | static DEFINE_MUTEX(clocks_mutex); | ||
31 | static DEFINE_SPINLOCK(clocks_lock); | ||
32 | static LIST_HEAD(clocks); | ||
33 | |||
34 | /* | ||
35 | * Standard clock functions defined in include/linux/clk.h | ||
36 | */ | ||
37 | int clk_enable(struct clk *clk) | ||
38 | { | ||
39 | unsigned long flags; | ||
40 | spin_lock_irqsave(&clocks_lock, flags); | ||
41 | clk->count++; | ||
42 | if (clk->count == 1) | ||
43 | clk->ops->enable(clk->id); | ||
44 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
45 | return 0; | ||
46 | } | ||
47 | EXPORT_SYMBOL(clk_enable); | ||
48 | |||
49 | void clk_disable(struct clk *clk) | ||
50 | { | ||
51 | unsigned long flags; | ||
52 | spin_lock_irqsave(&clocks_lock, flags); | ||
53 | BUG_ON(clk->count == 0); | ||
54 | clk->count--; | ||
55 | if (clk->count == 0) | ||
56 | clk->ops->disable(clk->id); | ||
57 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
58 | } | ||
59 | EXPORT_SYMBOL(clk_disable); | ||
60 | |||
61 | int clk_reset(struct clk *clk, enum clk_reset_action action) | 22 | int clk_reset(struct clk *clk, enum clk_reset_action action) |
62 | { | 23 | { |
63 | return clk->ops->reset(clk->remote_id, action); | 24 | struct clk_hw *hw = __clk_get_hw(clk); |
25 | struct msm_clk *m = to_msm_clk(hw); | ||
26 | return m->reset(hw, action); | ||
64 | } | 27 | } |
65 | EXPORT_SYMBOL(clk_reset); | 28 | EXPORT_SYMBOL(clk_reset); |
66 | |||
67 | unsigned long clk_get_rate(struct clk *clk) | ||
68 | { | ||
69 | return clk->ops->get_rate(clk->id); | ||
70 | } | ||
71 | EXPORT_SYMBOL(clk_get_rate); | ||
72 | |||
73 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
74 | { | ||
75 | int ret; | ||
76 | if (clk->flags & CLKFLAG_MAX) { | ||
77 | ret = clk->ops->set_max_rate(clk->id, rate); | ||
78 | if (ret) | ||
79 | return ret; | ||
80 | } | ||
81 | if (clk->flags & CLKFLAG_MIN) { | ||
82 | ret = clk->ops->set_min_rate(clk->id, rate); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | if (clk->flags & CLKFLAG_MAX || clk->flags & CLKFLAG_MIN) | ||
88 | return ret; | ||
89 | |||
90 | return clk->ops->set_rate(clk->id, rate); | ||
91 | } | ||
92 | EXPORT_SYMBOL(clk_set_rate); | ||
93 | |||
94 | long clk_round_rate(struct clk *clk, unsigned long rate) | ||
95 | { | ||
96 | return clk->ops->round_rate(clk->id, rate); | ||
97 | } | ||
98 | EXPORT_SYMBOL(clk_round_rate); | ||
99 | |||
100 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
101 | { | ||
102 | return -ENOSYS; | ||
103 | } | ||
104 | EXPORT_SYMBOL(clk_set_parent); | ||
105 | |||
106 | struct clk *clk_get_parent(struct clk *clk) | ||
107 | { | ||
108 | return ERR_PTR(-ENOSYS); | ||
109 | } | ||
110 | EXPORT_SYMBOL(clk_get_parent); | ||
111 | |||
112 | /* EBI1 is the only shared clock that several clients want to vote on as of | ||
113 | * this commit. If this changes in the future, then it might be better to | ||
114 | * make clk_min_rate handle the voting or make ebi1_clk_set_min_rate more | ||
115 | * generic to support different clocks. | ||
116 | */ | ||
117 | static struct clk *ebi1_clk; | ||
118 | |||
119 | void msm_clock_init(struct clk_lookup *clock_tbl, size_t num_clocks) | ||
120 | { | ||
121 | unsigned n; | ||
122 | |||
123 | mutex_lock(&clocks_mutex); | ||
124 | for (n = 0; n < num_clocks; n++) { | ||
125 | clkdev_add(&clock_tbl[n]); | ||
126 | list_add_tail(&clock_tbl[n].clk->list, &clocks); | ||
127 | } | ||
128 | mutex_unlock(&clocks_mutex); | ||
129 | |||
130 | ebi1_clk = clk_get(NULL, "ebi1_clk"); | ||
131 | BUG_ON(ebi1_clk == NULL); | ||
132 | |||
133 | } | ||
134 | |||
135 | /* The bootloader and/or AMSS may have left various clocks enabled. | ||
136 | * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have | ||
137 | * not been explicitly enabled by a clk_enable() call. | ||
138 | */ | ||
139 | static int __init clock_late_init(void) | ||
140 | { | ||
141 | unsigned long flags; | ||
142 | struct clk *clk; | ||
143 | unsigned count = 0; | ||
144 | |||
145 | clock_debug_init(); | ||
146 | mutex_lock(&clocks_mutex); | ||
147 | list_for_each_entry(clk, &clocks, list) { | ||
148 | clock_debug_add(clk); | ||
149 | if (clk->flags & CLKFLAG_AUTO_OFF) { | ||
150 | spin_lock_irqsave(&clocks_lock, flags); | ||
151 | if (!clk->count) { | ||
152 | count++; | ||
153 | clk->ops->auto_off(clk->id); | ||
154 | } | ||
155 | spin_unlock_irqrestore(&clocks_lock, flags); | ||
156 | } | ||
157 | } | ||
158 | mutex_unlock(&clocks_mutex); | ||
159 | pr_info("clock_late_init() disabled %d unused clocks\n", count); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | late_initcall(clock_late_init); | ||
164 | |||
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h index cc76bfe9ba46..42d29dd7aafc 100644 --- a/arch/arm/mach-msm/clock.h +++ b/arch/arm/mach-msm/clock.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* arch/arm/mach-msm/clock.h | 1 | /* arch/arm/mach-msm/clock.h |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Google, Inc. | 3 | * Copyright (C) 2007 Google, Inc. |
4 | * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. | 4 | * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. |
5 | * | 5 | * |
6 | * This software is licensed under the terms of the GNU General Public | 6 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 7 | * License version 2, as published by the Free Software Foundation, and |
@@ -17,8 +17,7 @@ | |||
17 | #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H | 17 | #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H |
18 | #define __ARCH_ARM_MACH_MSM_CLOCK_H | 18 | #define __ARCH_ARM_MACH_MSM_CLOCK_H |
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/clk-provider.h> |
21 | #include <linux/list.h> | ||
22 | #include <mach/clk.h> | 21 | #include <mach/clk.h> |
23 | 22 | ||
24 | #define CLK_FIRST_AVAILABLE_FLAG 0x00000100 | 23 | #define CLK_FIRST_AVAILABLE_FLAG 0x00000100 |
@@ -26,44 +25,19 @@ | |||
26 | #define CLKFLAG_MIN 0x00000400 | 25 | #define CLKFLAG_MIN 0x00000400 |
27 | #define CLKFLAG_MAX 0x00000800 | 26 | #define CLKFLAG_MAX 0x00000800 |
28 | 27 | ||
29 | struct clk_ops { | ||
30 | int (*enable)(unsigned id); | ||
31 | void (*disable)(unsigned id); | ||
32 | void (*auto_off)(unsigned id); | ||
33 | int (*reset)(unsigned id, enum clk_reset_action action); | ||
34 | int (*set_rate)(unsigned id, unsigned rate); | ||
35 | int (*set_min_rate)(unsigned id, unsigned rate); | ||
36 | int (*set_max_rate)(unsigned id, unsigned rate); | ||
37 | unsigned (*get_rate)(unsigned id); | ||
38 | unsigned (*is_enabled)(unsigned id); | ||
39 | long (*round_rate)(unsigned id, unsigned rate); | ||
40 | bool (*is_local)(unsigned id); | ||
41 | }; | ||
42 | |||
43 | struct clk { | ||
44 | uint32_t id; | ||
45 | uint32_t remote_id; | ||
46 | uint32_t count; | ||
47 | uint32_t flags; | ||
48 | struct clk_ops *ops; | ||
49 | const char *dbg_name; | ||
50 | struct list_head list; | ||
51 | }; | ||
52 | |||
53 | #define OFF CLKFLAG_AUTO_OFF | 28 | #define OFF CLKFLAG_AUTO_OFF |
54 | #define CLK_MIN CLKFLAG_MIN | 29 | #define CLK_MIN CLKFLAG_MIN |
55 | #define CLK_MAX CLKFLAG_MAX | 30 | #define CLK_MAX CLKFLAG_MAX |
56 | #define CLK_MINMAX (CLK_MIN | CLK_MAX) | 31 | #define CLK_MINMAX (CLK_MIN | CLK_MAX) |
57 | 32 | ||
58 | #ifdef CONFIG_DEBUG_FS | 33 | struct msm_clk { |
59 | int __init clock_debug_init(void); | 34 | int (*reset)(struct clk_hw *hw, enum clk_reset_action action); |
60 | int __init clock_debug_add(struct clk *clock); | 35 | struct clk_hw hw; |
61 | #else | 36 | }; |
62 | static inline int __init clock_debug_init(void) { return 0; } | ||
63 | static inline int __init clock_debug_add(struct clk *clock) { return 0; } | ||
64 | #endif | ||
65 | 37 | ||
66 | struct clk_lookup; | 38 | static inline struct msm_clk *to_msm_clk(struct clk_hw *hw) |
67 | void msm_clock_init(struct clk_lookup *clock_tbl, size_t num_clocks); | 39 | { |
40 | return container_of(hw, struct msm_clk, hw); | ||
41 | } | ||
68 | 42 | ||
69 | #endif | 43 | #endif |
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c index 9edfe68e9fe9..6d50fb964863 100644 --- a/arch/arm/mach-msm/devices-msm7x00.c +++ b/arch/arm/mach-msm/devices-msm7x00.c | |||
@@ -425,7 +425,7 @@ struct platform_device msm_device_mdp = { | |||
425 | .resource = resources_mdp, | 425 | .resource = resources_mdp, |
426 | }; | 426 | }; |
427 | 427 | ||
428 | static struct clk_lookup msm_clocks_7x01a[] = { | 428 | static struct clk_pcom_desc msm_clocks_7x01a[] = { |
429 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), | 429 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), |
430 | CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), | 430 | CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), |
431 | CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0), | 431 | CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0), |
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c index 6444f0e618f6..d4db75acff56 100644 --- a/arch/arm/mach-msm/devices-msm7x30.c +++ b/arch/arm/mach-msm/devices-msm7x30.c | |||
@@ -161,7 +161,7 @@ struct platform_device msm_device_hsusb_host = { | |||
161 | }, | 161 | }, |
162 | }; | 162 | }; |
163 | 163 | ||
164 | static struct clk_lookup msm_clocks_7x30[] = { | 164 | static struct clk_pcom_desc msm_clocks_7x30[] = { |
165 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), | 165 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), |
166 | CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), | 166 | CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), |
167 | CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0), | 167 | CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0), |
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c index caa9a1f0bcbd..f5518112284b 100644 --- a/arch/arm/mach-msm/devices-qsd8x50.c +++ b/arch/arm/mach-msm/devices-qsd8x50.c | |||
@@ -323,7 +323,7 @@ int __init msm_add_sdcc(unsigned int controller, | |||
323 | return platform_device_register(pdev); | 323 | return platform_device_register(pdev); |
324 | } | 324 | } |
325 | 325 | ||
326 | static struct clk_lookup msm_clocks_8x50[] = { | 326 | static struct clk_pcom_desc msm_clocks_8x50[] = { |
327 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), | 327 | CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), |
328 | CLK_PCOM("ce_clk", CE_CLK, NULL, 0), | 328 | CLK_PCOM("ce_clk", CE_CLK, NULL, 0), |
329 | CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), | 329 | CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), |