summary refs log tree commit diff
path: root/drivers/spi/spi_imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi_imx.c')
-rw-r--r--drivers/spi/spi_imx.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index c730d05bfeb6..54ac7bea5f8c 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -29,6 +29,7 @@
 #include <linux/spi/spi.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -250,6 +251,8 @@ struct driver_data {
 	int tx_dma_needs_unmap;
 	size_t tx_map_len;
 	u32 dummy_dma_buf ____cacheline_aligned;
+
+	struct clk *clk;
 };
 
 /* Runtime state */
@@ -855,15 +858,15 @@ static irqreturn_t spi_int(int irq, void *dev_id)
 	return drv_data->transfer_handler(drv_data);
 }
 
-static inline u32 spi_speed_hz(u32 data_rate)
+static inline u32 spi_speed_hz(struct driver_data *drv_data, u32 data_rate)
 {
-	return imx_get_perclk2() / (4 << ((data_rate) >> 13));
+	return clk_get_rate(drv_data->clk) / (4 << ((data_rate) >> 13));
 }
 
-static u32 spi_data_rate(u32 speed_hz)
+static u32 spi_data_rate(struct driver_data *drv_data, u32 speed_hz)
 {
 	u32 div;
-	u32 quantized_hz = imx_get_perclk2() >> 2;
+	u32 quantized_hz = clk_get_rate(drv_data->clk) >> 2;
 
 	for (div = SPI_PERCLK2_DIV_MIN;
 		div <= SPI_PERCLK2_DIV_MAX;
@@ -947,7 +950,7 @@ static void pump_transfers(unsigned long data)
 	tmp = transfer->speed_hz;
 	if (tmp == 0)
 		tmp = chip->max_speed_hz;
-	tmp = spi_data_rate(tmp);
+	tmp = spi_data_rate(drv_data, tmp);
 	u32_EDIT(control, SPI_CONTROL_DATARATE, tmp);
 
 	writel(control, regs + SPI_CONTROL);
@@ -1109,7 +1112,7 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
 	msg->actual_length = 0;
 
 	/* Per transfer setup check */
-	min_speed_hz = spi_speed_hz(SPI_CONTROL_DATARATE_MIN);
+	min_speed_hz = spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN);
 	max_speed_hz = spi->max_speed_hz;
 	list_for_each_entry(trans, &msg->transfers, transfer_list) {
 		tmp = trans->bits_per_word;
@@ -1176,6 +1179,7 @@ msg_rejected:
    applied and notified to the calling driver. */
 static int setup(struct spi_device *spi)
 {
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
 	struct spi_imx_chip *chip_info;
 	struct chip_data *chip;
 	int first_setup = 0;
@@ -1304,14 +1308,14 @@ static int setup(struct spi_device *spi)
 	chip->n_bytes = (tmp <= 8) ? 1 : 2;
 
 	/* SPI datarate */
-	tmp = spi_data_rate(spi->max_speed_hz);
+	tmp = spi_data_rate(drv_data, spi->max_speed_hz);
 	if (tmp == SPI_CONTROL_DATARATE_BAD) {
 		status = -EINVAL;
 		dev_err(&spi->dev,
 			"setup - "
 			"HW min speed (%d Hz) exceeds required "
 			"max speed (%d Hz)\n",
-			spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+			spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN),
 			spi->max_speed_hz);
 		if (first_setup)
 			goto err_first_setup;
@@ -1321,7 +1325,7 @@ static int setup(struct spi_device *spi)
 	} else {
 		u32_EDIT(chip->control, SPI_CONTROL_DATARATE, tmp);
 		/* Actual rounded max_speed_hz */
-		tmp = spi_speed_hz(tmp);
+		tmp = spi_speed_hz(drv_data, tmp);
 		spi->max_speed_hz = tmp;
 		chip->max_speed_hz = tmp;
 	}
@@ -1352,7 +1356,7 @@ static int setup(struct spi_device *spi)
 		chip->period & SPI_PERIOD_WAIT,
 		spi->mode,
 		spi->bits_per_word,
-		spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+		spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN),
 		spi->max_speed_hz);
 	return status;
 
@@ -1465,6 +1469,14 @@ static int __init spi_imx_probe(struct platform_device *pdev)
 		goto err_no_pdata;
 	}
 
+	drv_data->clk = clk_get(&pdev->dev, "perclk2");
+	if (IS_ERR(drv_data->clk)) {
+		dev_err(&pdev->dev, "probe - cannot get get\n");
+		status = PTR_ERR(drv_data->clk);
+		goto err_no_clk;
+	}
+	clk_enable(drv_data->clk);
+
 	/* Allocate master with space for drv_data */
 	master = spi_alloc_master(dev, sizeof(struct driver_data));
 	if (!master) {
@@ -1526,24 +1538,24 @@ static int __init spi_imx_probe(struct platform_device *pdev)
 	drv_data->rx_channel = -1;
 	if (platform_info->enable_dma) {
 		/* Get rx DMA channel */
-		status = imx_dma_request_by_prio(&drv_data->rx_channel,
-			"spi_imx_rx", DMA_PRIO_HIGH);
-		if (status < 0) {
+		drv_data->rx_channel = imx_dma_request_by_prio("spi_imx_rx",
+							       DMA_PRIO_HIGH);
+		if (drv_data->rx_channel < 0) {
 			dev_err(dev,
 				"probe - problem (%d) requesting rx channel\n",
-				status);
+				drv_data->rx_channel);
 			goto err_no_rxdma;
 		} else
 			imx_dma_setup_handlers(drv_data->rx_channel, NULL,
 						dma_err_handler, drv_data);
 
 		/* Get tx DMA channel */
-		status = imx_dma_request_by_prio(&drv_data->tx_channel,
-						"spi_imx_tx", DMA_PRIO_MEDIUM);
-		if (status < 0) {
+		drv_data->tx_channel = imx_dma_request_by_prio("spi_imx_tx",
+							       DMA_PRIO_MEDIUM);
+		if (drv_data->tx_channel < 0) {
 			dev_err(dev,
 				"probe - problem (%d) requesting tx channel\n",
-				status);
+				drv_data->tx_channel);
 			imx_dma_free(drv_data->rx_channel);
 			goto err_no_txdma;
 		} else
@@ -1623,6 +1635,9 @@ err_no_iores:
 	spi_master_put(master);
 
 err_no_pdata:
+	clk_disable(drv_data->clk);
+	clk_put(drv_data->clk);
+err_no_clk:
 err_no_mem:
 	return status;
 }
@@ -1662,6 +1677,9 @@ static int __exit spi_imx_remove(struct platform_device *pdev)
 	if (irq >= 0)
 		free_irq(irq, drv_data);
 
+	clk_disable(drv_data->clk);
+	clk_put(drv_data->clk);
+
 	/* Release map resources */
 	iounmap(drv_data->regs);
 	release_resource(drv_data->ioarea);