#include <asm/io.h>
#include <asm/arch/dma.h>
#include <asm/arch/mcspi.h>
+#include <asm/arch/clock.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
data_type = OMAP_DMA_DATA_TYPE_S32;
element_count = count >> 2;
} else
- return;
+ goto out;
/* RX_ONLY mode needs dummy data in TX reg */
if (tx == NULL)
if (tx != NULL)
dma_unmap_single(NULL, xfer->tx_dma,
count, DMA_TO_DEVICE);
- return;
+ goto out;
}
omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
wait_for_completion(&mcspi_dma->dma_rx_completion);
dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
}
-
+out:
omap2_mcspi_set_enable(spi, 0);
}
+static int mcspi_wait_for_reg_bit(unsigned long reg, unsigned long bit)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (!(__raw_readl(reg) & bit)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ }
+ return 0;
+}
+
static void omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
{
struct omap2_mcspi * mcspi;
while (c--) {
if (tx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_TXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
#ifdef VERBOSE
dev_dbg(&spi->dev, "write-%d %02x\n",
word_len, *tx);
__raw_writel(*tx, tx_reg);
}
if (rx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_RXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
if (c == 0 && tx == NULL)
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
c >>= 1;
while (c--) {
if (tx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_TXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
#ifdef VERBOSE
dev_dbg(&spi->dev, "write-%d %04x\n",
word_len, *tx);
__raw_writel(*tx++, tx_reg);
}
if (rx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_RXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
if (c == 0 && tx == NULL)
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
c >>= 2;
while (c--) {
if (tx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_TXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
#ifdef VERBOSE
dev_dbg(&spi->dev, "write-%d %04x\n",
word_len, *tx);
__raw_writel(*tx++, tx_reg);
}
if (rx != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_RXS));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+ dev_err(&spi->dev, "RXS timed out\n");
+ goto out;
+ }
if (c == 0 && tx == NULL)
omap2_mcspi_set_enable(spi, 0);
*rx++ = __raw_readl(rx_reg);
}
if (xfer->tx_buf != NULL) {
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_TXS));
- while (!(__raw_readl(chstat_reg) & OMAP2_MCSPI_CHSTAT_EOT));
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+ dev_err(&spi->dev, "TXS timed out\n");
+ goto out;
+ }
+ if (mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_EOT) < 0)
+ dev_err(&spi->dev, "EOT timed out\n");
+out:
omap2_mcspi_set_enable(spi, 0);
}
}
{
struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi_device_config *conf;
+ struct omap2_mcspi * mcspi;
u32 l = 0, div = 0;
u8 word_len = spi->bits_per_word;
+ mcspi = class_get_devdata(&spi->master->cdev);
+
if (t != NULL && t->bits_per_word)
word_len = t->bits_per_word;
if (!word_len)
conf = (struct omap2_mcspi_device_config *) spi->controller_data;
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
+
if (conf->single_channel == 1)
omap2_mcspi_set_master_mode(spi, 1);
else
word_len < 4 || word_len > 32 ||
div > 15) {
dev_err(&spi->dev, "Invalid McSPI channel setting\n");
+ clk_disable(mcspi->fck);
+ clk_disable(mcspi->ick);
return -EINVAL;
}
(spi->mode & SPI_CPHA) ? "odd" : "even",
(spi->mode & SPI_CPOL) ? "" : "not");
+ clk_disable(mcspi->fck);
+ clk_disable(mcspi->ick);
+
return 0;
}
}
}
-
static void omap2_mcspi_work(struct work_struct *work)
{
struct omap2_mcspi *mcspi = container_of(work, struct omap2_mcspi, work);
par_override = 0;
}
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
+
if (!cs_active) {
omap2_mcspi_force_cs(spi, 1);
cs_active = 1;
omap2_mcspi_force_cs(spi, 0);
cs_active = 0;
}
+ clk_disable(mcspi->ick);
+ clk_disable(mcspi->fck);
}
+ clk_enable(mcspi->ick);
+ clk_enable(mcspi->fck);
/* Restore defaults they are overriden */
if (par_override) {
par_override = 0;
if (cs_active)
omap2_mcspi_force_cs(spi, 0);
+ clk_disable(mcspi->ick);
+ clk_disable(mcspi->fck);
m->status = status;
m->complete(m->context);
status = PTR_ERR(mcspi->ick);
goto err1;
}
- clk_enable(mcspi->ick);
mcspi->fck = clk_get(&pdev->dev, "mcspi_fck");
if (IS_ERR(mcspi->fck)) {
dev_err(&pdev->dev, "can't get mcspi_fck\n");
status = PTR_ERR(mcspi->fck);
goto err2;
}
- clk_enable(mcspi->fck);
mcspi->dma_channels =
(struct omap2_mcspi_dma *)kzalloc(master->num_chipselect *
err4:
kfree(mcspi->dma_channels);
err3:
- clk_disable(mcspi->fck);
clk_put(mcspi->fck);
err2:
- clk_disable(mcspi->ick);
clk_put(mcspi->ick);
err1:
class_device_put(&master->cdev);
spi_unregister_master(master);
mcspi = class_get_devdata(&master->cdev);
- clk_disable(mcspi->fck);
clk_put(mcspi->fck);
- clk_disable(mcspi->ick);
clk_put(mcspi->ick);
class_device_put(&master->cdev);
kfree(mcspi->dma_channels);