Skip to content

Commit

Permalink
ARM: 6467/1: amba: optional PrimeCell core voltage switch
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Linus Walleij authored and Russell King committed Nov 26, 2010
1 parent 283a1b9 commit 65500fa
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
39 changes: 39 additions & 0 deletions drivers/amba/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
clk_put(pclk);
}

static int amba_get_enable_vcore(struct amba_device *pcdev)
{
struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
int ret;

pcdev->vcore = vcore;

if (IS_ERR(vcore)) {
/* It is OK not to supply a vcore regulator */
if (PTR_ERR(vcore) == -ENODEV)
return 0;
return PTR_ERR(vcore);
}

ret = regulator_enable(vcore);
if (ret) {
regulator_put(vcore);
pcdev->vcore = ERR_PTR(-ENODEV);
}

return ret;
}

static void amba_put_disable_vcore(struct amba_device *pcdev)
{
struct regulator *vcore = pcdev->vcore;

if (!IS_ERR(vcore)) {
regulator_disable(vcore);
regulator_put(vcore);
}
}

/*
* These are the device model conversion veneers; they convert the
* device model structures to our more specific structures.
Expand All @@ -159,6 +192,10 @@ static int amba_probe(struct device *dev)
int ret;

do {
ret = amba_get_enable_vcore(pcdev);
if (ret)
break;

ret = amba_get_enable_pclk(pcdev);
if (ret)
break;
Expand All @@ -168,6 +205,7 @@ static int amba_probe(struct device *dev)
break;

amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);
} while (0);

return ret;
Expand All @@ -180,6 +218,7 @@ static int amba_remove(struct device *dev)
int ret = drv->remove(pcdev);

amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);

return ret;
}
Expand Down
8 changes: 8 additions & 0 deletions include/linux/amba/bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/resource.h>
#include <linux/regulator/consumer.h>

#define AMBA_NR_IRQS 2
#define AMBA_CID 0xb105f00d
Expand All @@ -28,6 +29,7 @@ struct amba_device {
struct device dev;
struct resource res;
struct clk *pclk;
struct regulator *vcore;
u64 dma_mask;
unsigned int periphid;
unsigned int irq[AMBA_NR_IRQS];
Expand Down Expand Up @@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *);
#define amba_pclk_disable(d) \
do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)

#define amba_vcore_enable(d) \
(IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))

#define amba_vcore_disable(d) \
do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)

/* Some drivers don't use the struct amba_device */
#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
Expand Down

0 comments on commit 65500fa

Please sign in to comment.