aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2010-11-04 08:06:59 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-11-26 05:59:12 -0500
commit65500fa94aaeb3475e39c0c5180f188014164ca4 (patch)
treea8385820eaf63769d523c8ed726e0a1f6da081fa
parent283a1b92e25fe3a62c766a042f96dad2eefa7d17 (diff)
ARM: 6467/1: amba: optional PrimeCell core voltage switch
On some contemporary sub-micron SoCs, peripherals on the chip have power domain switches, i.e. the voltage to the core may be turned off to conserve power. In the Ux500 we have this for out PrimeCell derivates. This patch makes it possible to specify an (optional) regulator to handle the voltage domain switch on AMBA PrimeCells, modeled very similar to how block clocks are handled. Additional amba_vcore_[enable|disable] calls are supplied to make it possible introduce optional powering off of the core voltage. Using this will require code to spool/unspool any core HW state. Cc: Rabin Vincent <rabin.vincent@stericsson.com> Cc: Bengt Jonsson <bengt.g.jonsson@stericsson.com> Cc: Jonas Aaberg <jonas.aberg@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/amba/bus.c39
-rw-r--r--include/linux/amba/bus.h8
2 files changed, 47 insertions, 0 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 2737b9752205..e7df019d29d4 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
147 clk_put(pclk); 147 clk_put(pclk);
148} 148}
149 149
150static int amba_get_enable_vcore(struct amba_device *pcdev)
151{
152 struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
153 int ret;
154
155 pcdev->vcore = vcore;
156
157 if (IS_ERR(vcore)) {
158 /* It is OK not to supply a vcore regulator */
159 if (PTR_ERR(vcore) == -ENODEV)
160 return 0;
161 return PTR_ERR(vcore);
162 }
163
164 ret = regulator_enable(vcore);
165 if (ret) {
166 regulator_put(vcore);
167 pcdev->vcore = ERR_PTR(-ENODEV);
168 }
169
170 return ret;
171}
172
173static void amba_put_disable_vcore(struct amba_device *pcdev)
174{
175 struct regulator *vcore = pcdev->vcore;
176
177 if (!IS_ERR(vcore)) {
178 regulator_disable(vcore);
179 regulator_put(vcore);
180 }
181}
182
150/* 183/*
151 * These are the device model conversion veneers; they convert the 184 * These are the device model conversion veneers; they convert the
152 * device model structures to our more specific structures. 185 * device model structures to our more specific structures.
@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev)
159 int ret; 192 int ret;
160 193
161 do { 194 do {
195 ret = amba_get_enable_vcore(pcdev);
196 if (ret)
197 break;
198
162 ret = amba_get_enable_pclk(pcdev); 199 ret = amba_get_enable_pclk(pcdev);
163 if (ret) 200 if (ret)
164 break; 201 break;
@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev)
168 break; 205 break;
169 206
170 amba_put_disable_pclk(pcdev); 207 amba_put_disable_pclk(pcdev);
208 amba_put_disable_vcore(pcdev);
171 } while (0); 209 } while (0);
172 210
173 return ret; 211 return ret;
@@ -180,6 +218,7 @@ static int amba_remove(struct device *dev)
180 int ret = drv->remove(pcdev); 218 int ret = drv->remove(pcdev);
181 219
182 amba_put_disable_pclk(pcdev); 220 amba_put_disable_pclk(pcdev);
221 amba_put_disable_vcore(pcdev);
183 222
184 return ret; 223 return ret;
185} 224}
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index c6454cca0447..9e7f259346e1 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -18,6 +18,7 @@
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/resource.h> 20#include <linux/resource.h>
21#include <linux/regulator/consumer.h>
21 22
22#define AMBA_NR_IRQS 2 23#define AMBA_NR_IRQS 2
23#define AMBA_CID 0xb105f00d 24#define AMBA_CID 0xb105f00d
@@ -28,6 +29,7 @@ struct amba_device {
28 struct device dev; 29 struct device dev;
29 struct resource res; 30 struct resource res;
30 struct clk *pclk; 31 struct clk *pclk;
32 struct regulator *vcore;
31 u64 dma_mask; 33 u64 dma_mask;
32 unsigned int periphid; 34 unsigned int periphid;
33 unsigned int irq[AMBA_NR_IRQS]; 35 unsigned int irq[AMBA_NR_IRQS];
@@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *);
71#define amba_pclk_disable(d) \ 73#define amba_pclk_disable(d) \
72 do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) 74 do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
73 75
76#define amba_vcore_enable(d) \
77 (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
78
79#define amba_vcore_disable(d) \
80 do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
81
74/* Some drivers don't use the struct amba_device */ 82/* Some drivers don't use the struct amba_device */
75#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) 83#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
76#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) 84#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)