summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2013-01-22 12:26:27 +0200
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-26 15:21:37 +0800
commit3343b7a6d2cd0a980d0c4a0ce02ef48b6bfcc12a (patch)
tree09a2525b7710c0366dc99ba86cd51ec5a6e4c6f8 /drivers/spi
parent7f86bde90e2e1f693d93922fc0f4d50f001ce1a5 (diff)
downloadop-kernel-dev-3343b7a6d2cd0a980d0c4a0ce02ef48b6bfcc12a.zip
op-kernel-dev-3343b7a6d2cd0a980d0c4a0ce02ef48b6bfcc12a.tar.gz
spi/pxa2xx: convert to the common clk framework
Convert clk_enable() to clk_prepare_enable() and clk_disable() to clk_disable_unprepare() respectively in order to support the common clk framework. Otherwise we get warnings on the console as the clock is not prepared before it is enabled. In addition we must cache the maximum clock rate to drv_data->max_clk_rate at probe time because clk_get_rate() cannot be called in tasklet context. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pxa2xx.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index a241891..304cf6e 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -114,6 +115,9 @@ struct driver_data {
u32 clear_sr;
u32 mask_sr;
+ /* Maximun clock rate */
+ unsigned long max_clk_rate;
+
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
@@ -891,9 +895,12 @@ static int set_dma_burst_and_threshold(struct chip_data *chip,
return retval;
}
-static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
+static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
{
- unsigned long ssp_clk = clk_get_rate(ssp->clk);
+ unsigned long ssp_clk = drv_data->max_clk_rate;
+ const struct ssp_device *ssp = drv_data->ssp;
+
+ rate = min_t(int, ssp_clk, rate);
if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
@@ -908,7 +915,6 @@ static void pump_transfers(unsigned long data)
struct spi_transfer *transfer = NULL;
struct spi_transfer *previous = NULL;
struct chip_data *chip = NULL;
- struct ssp_device *ssp = drv_data->ssp;
void __iomem *reg = drv_data->ioaddr;
u32 clk_div = 0;
u8 bits = 0;
@@ -1005,7 +1011,7 @@ static void pump_transfers(unsigned long data)
if (transfer->bits_per_word)
bits = transfer->bits_per_word;
- clk_div = ssp_get_clk_div(ssp, speed);
+ clk_div = ssp_get_clk_div(drv_data, speed);
if (bits <= 8) {
drv_data->n_bytes = 1;
@@ -1214,7 +1220,6 @@ static int setup(struct spi_device *spi)
struct pxa2xx_spi_chip *chip_info = NULL;
struct chip_data *chip;
struct driver_data *drv_data = spi_master_get_devdata(spi->master);
- struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div;
uint tx_thres = TX_THRESH_DFLT;
uint rx_thres = RX_THRESH_DFLT;
@@ -1296,7 +1301,7 @@ static int setup(struct spi_device *spi)
}
}
- clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz);
+ clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
chip->speed_hz = spi->max_speed_hz;
chip->cr0 = clk_div
@@ -1312,12 +1317,12 @@ static int setup(struct spi_device *spi)
/* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (!pxa25x_ssp_comp(drv_data))
dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- clk_get_rate(ssp->clk)
+ drv_data->max_clk_rate
/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO");
else
dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
- clk_get_rate(ssp->clk) / 2
+ drv_data->max_clk_rate / 2
/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO");
@@ -1470,7 +1475,9 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
/* Enable SOC clock */
- clk_enable(ssp->clk);
+ clk_prepare_enable(ssp->clk);
+
+ drv_data->max_clk_rate = clk_get_rate(ssp->clk);
/* Load default SSP configuration */
write_SSCR0(0, drv_data->ioaddr);
@@ -1499,7 +1506,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return status;
out_error_clock_enabled:
- clk_disable(ssp->clk);
+ clk_disable_unprepare(ssp->clk);
out_error_dma_alloc:
if (drv_data->tx_channel != -1)
@@ -1527,7 +1534,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
/* Disable the SSP at the peripheral and SOC level */
write_SSCR0(0, drv_data->ioaddr);
- clk_disable(ssp->clk);
+ clk_disable_unprepare(ssp->clk);
/* Release DMA */
if (drv_data->master_info->enable_dma) {
@@ -1571,7 +1578,7 @@ static int pxa2xx_spi_suspend(struct device *dev)
if (status != 0)
return status;
write_SSCR0(0, drv_data->ioaddr);
- clk_disable(ssp->clk);
+ clk_disable_unprepare(ssp->clk);
return 0;
}
@@ -1590,7 +1597,7 @@ static int pxa2xx_spi_resume(struct device *dev)
DRCMR_MAPVLD | drv_data->tx_channel;
/* Enable the SSP clock */
- clk_enable(ssp->clk);
+ clk_prepare_enable(ssp->clk);
/* Start the queue running */
status = spi_master_resume(drv_data->master);
OpenPOWER on IntegriCloud