Commit 18974369 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'clk' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm

* 'clk' of http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm:
  ARM: 7131/1: clkdev: Add Common Macro for clk_lookup
  clk: spi-pl022: convert to clk_prepare()/clk_unprepare()
  clk: timer-sp: convert to clk_prepare()/clk_unprepare()
  clk: sa1111: convert to clk_prepare()/clk_unprepare()
  clk: mmci: convert to clk_prepare()/clk_unprepare()
  clk: amba-pl011: convert to clk_prepare()/clk_unprepare()
  clk: amba-pl010: convert to clk_prepare()/clk_unprepare()
  clk: amba-clcd: convert to clk_prepare()/clk_unprepare()
  clk: amba bus: convert to clk_prepare()/clk_unprepare()
  clk: provide prepare/unprepare functions
parents 7e0a6fd5 196a57c2
...@@ -718,6 +718,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) ...@@ -718,6 +718,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
goto err_free; goto err_free;
} }
ret = clk_prepare(sachip->clk);
if (ret)
goto err_clkput;
spin_lock_init(&sachip->lock); spin_lock_init(&sachip->lock);
sachip->dev = me; sachip->dev = me;
...@@ -733,7 +737,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) ...@@ -733,7 +737,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
sachip->base = ioremap(mem->start, PAGE_SIZE * 2); sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
if (!sachip->base) { if (!sachip->base) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_clkput; goto err_clk_unprep;
} }
/* /*
...@@ -809,6 +813,8 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) ...@@ -809,6 +813,8 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
err_unmap: err_unmap:
iounmap(sachip->base); iounmap(sachip->base);
err_clk_unprep:
clk_unprepare(sachip->clk);
err_clkput: err_clkput:
clk_put(sachip->clk); clk_put(sachip->clk);
err_free: err_free:
...@@ -835,6 +841,7 @@ static void __sa1111_remove(struct sa1111 *sachip) ...@@ -835,6 +841,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
sa1111_writel(0, irqbase + SA1111_WAKEEN1); sa1111_writel(0, irqbase + SA1111_WAKEEN1);
clk_disable(sachip->clk); clk_disable(sachip->clk);
clk_unprepare(sachip->clk);
if (sachip->irq != NO_IRQ) { if (sachip->irq != NO_IRQ) {
irq_set_chained_handler(sachip->irq, NULL); irq_set_chained_handler(sachip->irq, NULL);
......
...@@ -41,9 +41,17 @@ static long __init sp804_get_clock_rate(const char *name) ...@@ -41,9 +41,17 @@ static long __init sp804_get_clock_rate(const char *name)
return PTR_ERR(clk); return PTR_ERR(clk);
} }
err = clk_prepare(clk);
if (err) {
pr_err("sp804: %s clock failed to prepare: %d\n", name, err);
clk_put(clk);
return err;
}
err = clk_enable(clk); err = clk_enable(clk);
if (err) { if (err) {
pr_err("sp804: %s clock failed to enable: %d\n", name, err); pr_err("sp804: %s clock failed to enable: %d\n", name, err);
clk_unprepare(clk);
clk_put(clk); clk_put(clk);
return err; return err;
} }
...@@ -52,6 +60,7 @@ static long __init sp804_get_clock_rate(const char *name) ...@@ -52,6 +60,7 @@ static long __init sp804_get_clock_rate(const char *name)
if (rate < 0) { if (rate < 0) {
pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
clk_disable(clk); clk_disable(clk);
clk_unprepare(clk);
clk_put(clk); clk_put(clk);
} }
......
...@@ -460,9 +460,17 @@ static int amba_get_enable_pclk(struct amba_device *pcdev) ...@@ -460,9 +460,17 @@ static int amba_get_enable_pclk(struct amba_device *pcdev)
if (IS_ERR(pclk)) if (IS_ERR(pclk))
return PTR_ERR(pclk); return PTR_ERR(pclk);
ret = clk_prepare(pclk);
if (ret) {
clk_put(pclk);
return ret;
}
ret = clk_enable(pclk); ret = clk_enable(pclk);
if (ret) if (ret) {
clk_unprepare(pclk);
clk_put(pclk); clk_put(pclk);
}
return ret; return ret;
} }
...@@ -472,6 +480,7 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) ...@@ -472,6 +480,7 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
struct clk *pclk = pcdev->pclk; struct clk *pclk = pcdev->pclk;
clk_disable(pclk); clk_disable(pclk);
clk_unprepare(pclk);
clk_put(pclk); clk_put(pclk);
} }
......
...@@ -1160,10 +1160,14 @@ static int __devinit mmci_probe(struct amba_device *dev, ...@@ -1160,10 +1160,14 @@ static int __devinit mmci_probe(struct amba_device *dev,
goto host_free; goto host_free;
} }
ret = clk_enable(host->clk); ret = clk_prepare(host->clk);
if (ret) if (ret)
goto clk_free; goto clk_free;
ret = clk_enable(host->clk);
if (ret)
goto clk_unprep;
host->plat = plat; host->plat = plat;
host->variant = variant; host->variant = variant;
host->mclk = clk_get_rate(host->clk); host->mclk = clk_get_rate(host->clk);
...@@ -1351,6 +1355,8 @@ static int __devinit mmci_probe(struct amba_device *dev, ...@@ -1351,6 +1355,8 @@ static int __devinit mmci_probe(struct amba_device *dev,
iounmap(host->base); iounmap(host->base);
clk_disable: clk_disable:
clk_disable(host->clk); clk_disable(host->clk);
clk_unprep:
clk_unprepare(host->clk);
clk_free: clk_free:
clk_put(host->clk); clk_put(host->clk);
host_free: host_free:
...@@ -1398,6 +1404,7 @@ static int __devexit mmci_remove(struct amba_device *dev) ...@@ -1398,6 +1404,7 @@ static int __devexit mmci_remove(struct amba_device *dev)
iounmap(host->base); iounmap(host->base);
clk_disable(host->clk); clk_disable(host->clk);
clk_unprepare(host->clk);
clk_put(host->clk); clk_put(host->clk);
if (host->vcc) if (host->vcc)
......
...@@ -2187,6 +2187,13 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2187,6 +2187,13 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
goto err_no_clk; goto err_no_clk;
} }
status = clk_prepare(pl022->clk);
if (status) {
dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
goto err_clk_prep;
}
/* Disable SSP */ /* Disable SSP */
writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
SSP_CR1(pl022->virtbase)); SSP_CR1(pl022->virtbase));
...@@ -2238,6 +2245,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2238,6 +2245,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
pl022_dma_remove(pl022); pl022_dma_remove(pl022);
free_irq(adev->irq[0], pl022); free_irq(adev->irq[0], pl022);
err_no_irq: err_no_irq:
clk_unprepare(pl022->clk);
err_clk_prep:
clk_put(pl022->clk); clk_put(pl022->clk);
err_no_clk: err_no_clk:
iounmap(pl022->virtbase); iounmap(pl022->virtbase);
...@@ -2271,6 +2280,7 @@ pl022_remove(struct amba_device *adev) ...@@ -2271,6 +2280,7 @@ pl022_remove(struct amba_device *adev)
pl022_dma_remove(pl022); pl022_dma_remove(pl022);
free_irq(adev->irq[0], pl022); free_irq(adev->irq[0], pl022);
clk_disable(pl022->clk); clk_disable(pl022->clk);
clk_unprepare(pl022->clk);
clk_put(pl022->clk); clk_put(pl022->clk);
iounmap(pl022->virtbase); iounmap(pl022->virtbase);
amba_release_regions(adev); amba_release_regions(adev);
......
...@@ -312,12 +312,16 @@ static int pl010_startup(struct uart_port *port) ...@@ -312,12 +312,16 @@ static int pl010_startup(struct uart_port *port)
struct uart_amba_port *uap = (struct uart_amba_port *)port; struct uart_amba_port *uap = (struct uart_amba_port *)port;
int retval; int retval;
retval = clk_prepare(uap->clk);
if (retval)
goto out;
/* /*
* Try to enable the clock producer. * Try to enable the clock producer.
*/ */
retval = clk_enable(uap->clk); retval = clk_enable(uap->clk);
if (retval) if (retval)
goto out; goto clk_unprep;
uap->port.uartclk = clk_get_rate(uap->clk); uap->port.uartclk = clk_get_rate(uap->clk);
...@@ -343,6 +347,8 @@ static int pl010_startup(struct uart_port *port) ...@@ -343,6 +347,8 @@ static int pl010_startup(struct uart_port *port)
clk_dis: clk_dis:
clk_disable(uap->clk); clk_disable(uap->clk);
clk_unprep:
clk_unprepare(uap->clk);
out: out:
return retval; return retval;
} }
...@@ -370,6 +376,7 @@ static void pl010_shutdown(struct uart_port *port) ...@@ -370,6 +376,7 @@ static void pl010_shutdown(struct uart_port *port)
* Shut down the clock producer * Shut down the clock producer
*/ */
clk_disable(uap->clk); clk_disable(uap->clk);
clk_unprepare(uap->clk);
} }
static void static void
...@@ -626,6 +633,7 @@ static int __init pl010_console_setup(struct console *co, char *options) ...@@ -626,6 +633,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
int bits = 8; int bits = 8;
int parity = 'n'; int parity = 'n';
int flow = 'n'; int flow = 'n';
int ret;
/* /*
* Check whether an invalid uart number has been specified, and * Check whether an invalid uart number has been specified, and
...@@ -638,6 +646,10 @@ static int __init pl010_console_setup(struct console *co, char *options) ...@@ -638,6 +646,10 @@ static int __init pl010_console_setup(struct console *co, char *options)
if (!uap) if (!uap)
return -ENODEV; return -ENODEV;
ret = clk_prepare(uap->clk);
if (ret)
return ret;
uap->port.uartclk = clk_get_rate(uap->clk); uap->port.uartclk = clk_get_rate(uap->clk);
if (options) if (options)
......
...@@ -1367,12 +1367,16 @@ static int pl011_startup(struct uart_port *port) ...@@ -1367,12 +1367,16 @@ static int pl011_startup(struct uart_port *port)
unsigned int cr; unsigned int cr;
int retval; int retval;
retval = clk_prepare(uap->clk);
if (retval)
goto out;
/* /*
* Try to enable the clock producer. * Try to enable the clock producer.
*/ */
retval = clk_enable(uap->clk); retval = clk_enable(uap->clk);
if (retval) if (retval)
goto out; goto clk_unprep;
uap->port.uartclk = clk_get_rate(uap->clk); uap->port.uartclk = clk_get_rate(uap->clk);
...@@ -1446,6 +1450,8 @@ static int pl011_startup(struct uart_port *port) ...@@ -1446,6 +1450,8 @@ static int pl011_startup(struct uart_port *port)
clk_dis: clk_dis:
clk_disable(uap->clk); clk_disable(uap->clk);
clk_unprep:
clk_unprepare(uap->clk);
out: out:
return retval; return retval;
} }
...@@ -1497,6 +1503,7 @@ static void pl011_shutdown(struct uart_port *port) ...@@ -1497,6 +1503,7 @@ static void pl011_shutdown(struct uart_port *port)
* Shut down the clock producer * Shut down the clock producer
*/ */
clk_disable(uap->clk); clk_disable(uap->clk);
clk_unprepare(uap->clk);
if (uap->port.dev->platform_data) { if (uap->port.dev->platform_data) {
struct amba_pl011_data *plat; struct amba_pl011_data *plat;
...@@ -1800,6 +1807,7 @@ static int __init pl011_console_setup(struct console *co, char *options) ...@@ -1800,6 +1807,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
int bits = 8; int bits = 8;
int parity = 'n'; int parity = 'n';
int flow = 'n'; int flow = 'n';
int ret;
/* /*
* Check whether an invalid uart number has been specified, and * Check whether an invalid uart number has been specified, and
...@@ -1812,6 +1820,10 @@ static int __init pl011_console_setup(struct console *co, char *options) ...@@ -1812,6 +1820,10 @@ static int __init pl011_console_setup(struct console *co, char *options)
if (!uap) if (!uap)
return -ENODEV; return -ENODEV;
ret = clk_prepare(uap->clk);
if (ret)
return ret;
if (uap->port.dev->platform_data) { if (uap->port.dev->platform_data) {
struct amba_pl011_data *plat; struct amba_pl011_data *plat;
......
...@@ -447,6 +447,10 @@ static int clcdfb_register(struct clcd_fb *fb) ...@@ -447,6 +447,10 @@ static int clcdfb_register(struct clcd_fb *fb)
goto out; goto out;
} }
ret = clk_prepare(fb->clk);
if (ret)
goto free_clk;
fb->fb.device = &fb->dev->dev; fb->fb.device = &fb->dev->dev;
fb->fb.fix.mmio_start = fb->dev->res.start; fb->fb.fix.mmio_start = fb->dev->res.start;
...@@ -456,7 +460,7 @@ static int clcdfb_register(struct clcd_fb *fb) ...@@ -456,7 +460,7 @@ static int clcdfb_register(struct clcd_fb *fb)
if (!fb->regs) { if (!fb->regs) {
printk(KERN_ERR "CLCD: unable to remap registers\n"); printk(KERN_ERR "CLCD: unable to remap registers\n");
ret = -ENOMEM; ret = -ENOMEM;
goto free_clk; goto clk_unprep;
} }
fb->fb.fbops = &clcdfb_ops; fb->fb.fbops = &clcdfb_ops;
...@@ -530,6 +534,8 @@ static int clcdfb_register(struct clcd_fb *fb) ...@@ -530,6 +534,8 @@ static int clcdfb_register(struct clcd_fb *fb)
fb_dealloc_cmap(&fb->fb.cmap); fb_dealloc_cmap(&fb->fb.cmap);
unmap: unmap:
iounmap(fb->regs); iounmap(fb->regs);
clk_unprep:
clk_unprepare(fb->clk);
free_clk: free_clk:
clk_put(fb->clk); clk_put(fb->clk);
out: out:
...@@ -595,6 +601,7 @@ static int clcdfb_remove(struct amba_device *dev) ...@@ -595,6 +601,7 @@ static int clcdfb_remove(struct amba_device *dev)
if (fb->fb.cmap.len) if (fb->fb.cmap.len)
fb_dealloc_cmap(&fb->fb.cmap); fb_dealloc_cmap(&fb->fb.cmap);
iounmap(fb->regs); iounmap(fb->regs);
clk_unprepare(fb->clk);
clk_put(fb->clk); clk_put(fb->clk);
fb->board->remove(fb); fb->board->remove(fb);
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#ifndef __LINUX_CLK_H #ifndef __LINUX_CLK_H
#define __LINUX_CLK_H #define __LINUX_CLK_H
#include <linux/kernel.h>
struct device; struct device;
/* /*
...@@ -40,12 +42,32 @@ struct clk; ...@@ -40,12 +42,32 @@ struct clk;
*/ */
struct clk *clk_get(struct device *dev, const char *id); struct clk *clk_get(struct device *dev, const char *id);
/**
* clk_prepare - prepare a clock source
* @clk: clock source
*
* This prepares the clock source for use.
*
* Must not be called from within atomic context.
*/
#ifdef CONFIG_HAVE_CLK_PREPARE
int clk_prepare(struct clk *clk);
#else
static inline int clk_prepare(struct clk *clk)
{
might_sleep();
return 0;
}
#endif
/** /**
* clk_enable - inform the system when the clock source should be running. * clk_enable - inform the system when the clock source should be running.
* @clk: clock source * @clk: clock source
* *
* If the clock can not be enabled/disabled, this should return success. * If the clock can not be enabled/disabled, this should return success.
* *
* May be called from atomic contexts.
*
* Returns success (0) or negative errno. * Returns success (0) or negative errno.
*/ */
int clk_enable(struct clk *clk); int clk_enable(struct clk *clk);
...@@ -57,6 +79,8 @@ int clk_enable(struct clk *clk); ...@@ -57,6 +79,8 @@ int clk_enable(struct clk *clk);
* Inform the system that a clock source is no longer required by * Inform the system that a clock source is no longer required by
* a driver and may be shut down. * a driver and may be shut down.
* *
* May be called from atomic contexts.
*
* Implementation detail: if the clock source is shared between * Implementation detail: if the clock source is shared between
* multiple drivers, clk_enable() calls must be balanced by the * multiple drivers, clk_enable() calls must be balanced by the
* same number of clk_disable() calls for the clock source to be * same number of clk_disable() calls for the clock source to be
...@@ -64,6 +88,25 @@ int clk_enable(struct clk *clk); ...@@ -64,6 +88,25 @@ int clk_enable(struct clk *clk);
*/ */
void clk_disable(struct clk *clk); void clk_disable(struct clk *clk);
/**
* clk_unprepare - undo preparation of a clock source
* @clk: clock source
*
* This undoes a previously prepared clock. The caller must balance
* the number of prepare and unprepare calls.
*
* Must not be called from within atomic context.
*/
#ifdef CONFIG_HAVE_CLK_PREPARE
void clk_unprepare(struct clk *clk);
#else
static inline void clk_unprepare(struct clk *clk)
{
might_sleep();
}
#endif
/** /**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source. * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled. * This is only valid once the clock source has been enabled.
......
...@@ -24,6 +24,13 @@ struct clk_lookup { ...@@ -24,6 +24,13 @@ struct clk_lookup {
struct clk *clk; struct clk *clk;
}; };
#define CLKDEV_INIT(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = c, \
}
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
const char *dev_fmt, ...); const char *dev_fmt, ...);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment