X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fspi%2Fspi_imx.c;h=0480d8bb19d32b7a6d81b2b43efafc2a7fe8defd;hb=a42e809aa3150cf03698e10e57eb067dac6805a3;hp=c730d05bfeb68b8db4cc2f3943e3c199821d1d97;hpb=5d9f3f6b7c4c9fe1706006f24f964e7c0fa49fb7;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index c730d05..0480d8bb 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -29,15 +29,15 @@ #include #include #include +#include #include #include -#include #include -#include -#include -#include +#include +#include +#include /*-------------------------------------------------------------------------*/ /* SPI Registers offsets from peripheral base address */ @@ -250,6 +250,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 */ @@ -488,7 +490,7 @@ static int map_dma_buffers(struct driver_data *drv_data) buf, drv_data->tx_map_len, DMA_TO_DEVICE); - if (dma_mapping_error(drv_data->tx_dma)) + if (dma_mapping_error(dev, drv_data->tx_dma)) return -1; drv_data->tx_dma_needs_unmap = 1; @@ -504,20 +506,6 @@ static int map_dma_buffers(struct driver_data *drv_data) if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx)) return -1; - /* NULL rx means write-only transfer and no map needed - since rx DMA will not be used */ - if (drv_data->rx) { - buf = drv_data->rx; - drv_data->rx_dma = dma_map_single( - dev, - buf, - drv_data->len, - DMA_FROM_DEVICE); - if (dma_mapping_error(drv_data->rx_dma)) - return -1; - drv_data->rx_dma_needs_unmap = 1; - } - if (drv_data->tx == NULL) { /* Read only message --> use drv_data->dummy_dma_buf for dummy writes to achive reads */ @@ -531,18 +519,31 @@ static int map_dma_buffers(struct driver_data *drv_data) buf, drv_data->tx_map_len, DMA_TO_DEVICE); - if (dma_mapping_error(drv_data->tx_dma)) { - if (drv_data->rx_dma) { - dma_unmap_single(dev, - drv_data->rx_dma, - drv_data->len, - DMA_FROM_DEVICE); - drv_data->rx_dma_needs_unmap = 0; - } + if (dma_mapping_error(dev, drv_data->tx_dma)) return -1; - } drv_data->tx_dma_needs_unmap = 1; + /* NULL rx means write-only transfer and no map needed + * since rx DMA will not be used */ + if (drv_data->rx) { + buf = drv_data->rx; + drv_data->rx_dma = dma_map_single(dev, + buf, + drv_data->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + if (drv_data->tx_dma) { + dma_unmap_single(dev, + drv_data->tx_dma, + drv_data->tx_map_len, + DMA_TO_DEVICE); + drv_data->tx_dma_needs_unmap = 0; + } + return -1; + } + drv_data->rx_dma_needs_unmap = 1; + } + return 0; } @@ -855,15 +856,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 +948,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 +1110,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 +1177,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 +1306,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 +1323,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 +1354,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; @@ -1379,7 +1381,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->work, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1454,7 +1456,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct spi_imx_master *platform_info; struct spi_master *master; - struct driver_data *drv_data = NULL; + struct driver_data *drv_data; struct resource *res; int irq, status = 0; @@ -1485,6 +1487,14 @@ static int __init spi_imx_probe(struct platform_device *pdev) drv_data->dummy_dma_buf = SPI_DUMMY_u32; + drv_data->clk = clk_get(&pdev->dev, "perclk2"); + if (IS_ERR(drv_data->clk)) { + dev_err(&pdev->dev, "probe - cannot get clock\n"); + status = PTR_ERR(drv_data->clk); + goto err_no_clk; + } + clk_enable(drv_data->clk); + /* Find and map resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -1515,7 +1525,8 @@ static int __init spi_imx_probe(struct platform_device *pdev) status = -ENODEV; goto err_no_irqres; } - status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data); + status = request_irq(irq, spi_int, IRQF_DISABLED, + dev_name(dev), drv_data); if (status < 0) { dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status); goto err_no_irqres; @@ -1526,24 +1537,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 @@ -1620,6 +1631,10 @@ err_no_iomap: kfree(drv_data->ioarea); err_no_iores: + clk_disable(drv_data->clk); + clk_put(drv_data->clk); + +err_no_clk: spi_master_put(master); err_no_pdata: @@ -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);