diff options
Diffstat (limited to 'drivers/spi/spi-imx.c')
-rw-r--r-- | drivers/spi/spi-imx.c | 156 |
1 files changed, 106 insertions, 50 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index dd1ce12aa386..6ec647bbba77 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -39,8 +39,8 @@ #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ #define MXC_INT_RDR BIT(4) /* Receive date threshold interrupt */ -/* The maximum bytes that a sdma BD can transfer.*/ -#define MAX_SDMA_BD_BYTES (1 << 15) +/* The maximum bytes that a sdma BD can transfer. */ +#define MAX_SDMA_BD_BYTES (1 << 15) #define MX51_ECSPI_CTRL_MAX_BURST 512 /* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/ #define MX53_MAX_TRANSFER_BYTES 512 @@ -59,7 +59,9 @@ struct spi_imx_data; struct spi_imx_devtype_data { void (*intctrl)(struct spi_imx_data *, int); - int (*config)(struct spi_device *); + int (*prepare_message)(struct spi_imx_data *, struct spi_message *); + int (*prepare_transfer)(struct spi_imx_data *, struct spi_device *, + struct spi_transfer *); void (*trigger)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *); @@ -85,7 +87,6 @@ struct spi_imx_data { unsigned long spi_clk; unsigned int spi_bus_clk; - unsigned int speed_hz; unsigned int bits_per_word; unsigned int spi_drctl; @@ -256,7 +257,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_INT_RREN (1 << 3) #define MX51_ECSPI_INT_RDREN (1 << 4) -#define MX51_ECSPI_DMA 0x14 +#define MX51_ECSPI_DMA 0x14 #define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f) #define MX51_ECSPI_DMA_RX_WML(wml) (((wml) & 0x3f) << 16) #define MX51_ECSPI_DMA_RXT_WML(wml) (((wml) & 0x3f) << 24) @@ -486,11 +487,12 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx) writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); } -static int mx51_ecspi_config(struct spi_device *spi) +static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, + struct spi_message *msg) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); + struct spi_device *spi = msg->spi; u32 ctrl = MX51_ECSPI_CTRL_ENABLE; - u32 clk = spi_imx->speed_hz, delay, reg; + u32 testreg; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); /* set Master or Slave mode */ @@ -505,19 +507,21 @@ static int mx51_ecspi_config(struct spi_device *spi) if (spi->mode & SPI_READY) ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); - /* set clock speed */ - ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); - spi_imx->spi_bus_clk = clk; - /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) - ctrl |= (spi_imx->slave_burst * 8 - 1) - << MX51_ECSPI_CTRL_BL_OFFSET; + /* + * The ctrl register must be written first, with the EN bit set other + * registers must not be written to. + */ + writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); + + testreg = readl(spi_imx->base + MX51_ECSPI_TESTREG); + if (spi->mode & SPI_LOOP) + testreg |= MX51_ECSPI_TESTREG_LBC; else - ctrl |= (spi_imx->bits_per_word - 1) - << MX51_ECSPI_CTRL_BL_OFFSET; + testreg &= ~MX51_ECSPI_TESTREG_LBC; + writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG); /* * eCSPI burst completion by Chip Select signal in Slave mode @@ -541,25 +545,43 @@ static int mx51_ecspi_config(struct spi_device *spi) cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } + if (spi->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); - if (spi_imx->usedma) - ctrl |= MX51_ECSPI_CTRL_SMC; + writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); - /* CTRL register always go first to bring out controller from reset */ - writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); + return 0; +} - reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); - if (spi->mode & SPI_LOOP) - reg |= MX51_ECSPI_TESTREG_LBC; +static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, + struct spi_device *spi, + struct spi_transfer *t) +{ + u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); + u32 clk = t->speed_hz, delay; + + /* Clear BL field and set the right value */ + ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; + if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) + ctrl |= (spi_imx->slave_burst * 8 - 1) + << MX51_ECSPI_CTRL_BL_OFFSET; else - reg &= ~MX51_ECSPI_TESTREG_LBC; - writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); + ctrl |= (spi_imx->bits_per_word - 1) + << MX51_ECSPI_CTRL_BL_OFFSET; - writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); + /* set clock speed */ + ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | + 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); + ctrl |= mx51_ecspi_clkdiv(spi_imx, t->speed_hz, &clk); + spi_imx->spi_bus_clk = clk; + + if (spi_imx->usedma) + ctrl |= MX51_ECSPI_CTRL_SMC; + + writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); /* * Wait until the changes in the configuration register CONFIGREG @@ -587,7 +609,6 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx) * Configure the DMA register: setup the watermark * and enable DMA request. */ - writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | @@ -659,13 +680,20 @@ static void mx31_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int mx31_config(struct spi_device *spi) +static int mx31_prepare_message(struct spi_imx_data *spi_imx, + struct spi_message *msg) +{ + return 0; +} + +static int mx31_prepare_transfer(struct spi_imx_data *spi_imx, + struct spi_device *spi, + struct spi_transfer *t) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; unsigned int clk; - reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->speed_hz, &clk) << + reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, t->speed_hz, &clk) << MX31_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -700,8 +728,10 @@ static int mx31_config(struct spi_device *spi) writel(reg, spi_imx->base + MX31_CSPI_TESTREG); if (spi_imx->usedma) { - /* configure DMA requests when RXFIFO is half full and - when TXFIFO is half empty */ + /* + * configure DMA requests when RXFIFO is half full and + * when TXFIFO is half empty + */ writel(MX31_DMAREG_RH_DEN | MX31_DMAREG_TH_DEN, spi_imx->base + MX31_CSPI_DMAREG); } @@ -755,14 +785,21 @@ static void mx21_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int mx21_config(struct spi_device *spi) +static int mx21_prepare_message(struct spi_imx_data *spi_imx, + struct spi_message *msg) +{ + return 0; +} + +static int mx21_prepare_transfer(struct spi_imx_data *spi_imx, + struct spi_device *spi, + struct spi_transfer *t) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; unsigned int clk; - reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, spi_imx->speed_hz, max, &clk) + reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, t->speed_hz, max, &clk) << MX21_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -824,13 +861,20 @@ static void mx1_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int mx1_config(struct spi_device *spi) +static int mx1_prepare_message(struct spi_imx_data *spi_imx, + struct spi_message *msg) +{ + return 0; +} + +static int mx1_prepare_transfer(struct spi_imx_data *spi_imx, + struct spi_device *spi, + struct spi_transfer *t) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; unsigned int clk; - reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->speed_hz, &clk) << + reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, t->speed_hz, &clk) << MX1_CSPICTRL_DR_SHIFT; spi_imx->spi_bus_clk = clk; @@ -858,7 +902,8 @@ static void mx1_reset(struct spi_imx_data *spi_imx) static struct spi_imx_devtype_data imx1_cspi_devtype_data = { .intctrl = mx1_intctrl, - .config = mx1_config, + .prepare_message = mx1_prepare_message, + .prepare_transfer = mx1_prepare_transfer, .trigger = mx1_trigger, .rx_available = mx1_rx_available, .reset = mx1_reset, @@ -871,7 +916,8 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = { static struct spi_imx_devtype_data imx21_cspi_devtype_data = { .intctrl = mx21_intctrl, - .config = mx21_config, + .prepare_message = mx21_prepare_message, + .prepare_transfer = mx21_prepare_transfer, .trigger = mx21_trigger, .rx_available = mx21_rx_available, .reset = mx21_reset, @@ -885,7 +931,8 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = { static struct spi_imx_devtype_data imx27_cspi_devtype_data = { /* i.mx27 cspi shares the functions with i.mx21 one */ .intctrl = mx21_intctrl, - .config = mx21_config, + .prepare_message = mx21_prepare_message, + .prepare_transfer = mx21_prepare_transfer, .trigger = mx21_trigger, .rx_available = mx21_rx_available, .reset = mx21_reset, @@ -898,7 +945,8 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = { static struct spi_imx_devtype_data imx31_cspi_devtype_data = { .intctrl = mx31_intctrl, - .config = mx31_config, + .prepare_message = mx31_prepare_message, + .prepare_transfer = mx31_prepare_transfer, .trigger = mx31_trigger, .rx_available = mx31_rx_available, .reset = mx31_reset, @@ -912,7 +960,8 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = { static struct spi_imx_devtype_data imx35_cspi_devtype_data = { /* i.mx35 and later cspi shares the functions with i.mx31 one */ .intctrl = mx31_intctrl, - .config = mx31_config, + .prepare_message = mx31_prepare_message, + .prepare_transfer = mx31_prepare_transfer, .trigger = mx31_trigger, .rx_available = mx31_rx_available, .reset = mx31_reset, @@ -925,7 +974,8 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { .intctrl = mx51_ecspi_intctrl, - .config = mx51_ecspi_config, + .prepare_message = mx51_ecspi_prepare_message, + .prepare_transfer = mx51_ecspi_prepare_transfer, .trigger = mx51_ecspi_trigger, .rx_available = mx51_ecspi_rx_available, .reset = mx51_ecspi_reset, @@ -940,7 +990,8 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { static struct spi_imx_devtype_data imx53_ecspi_devtype_data = { .intctrl = mx51_ecspi_intctrl, - .config = mx51_ecspi_config, + .prepare_message = mx51_ecspi_prepare_message, + .prepare_transfer = mx51_ecspi_prepare_transfer, .trigger = mx51_ecspi_trigger, .rx_available = mx51_ecspi_rx_available, .reset = mx51_ecspi_reset, @@ -1048,7 +1099,7 @@ static void spi_imx_push(struct spi_imx_data *spi_imx) if (!spi_imx->count) break; if (spi_imx->dynamic_burst && - spi_imx->txfifo >= DIV_ROUND_UP(spi_imx->remainder, + spi_imx->txfifo >= DIV_ROUND_UP(spi_imx->remainder, fifo_words)) break; spi_imx->tx(spi_imx); @@ -1142,7 +1193,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, return 0; spi_imx->bits_per_word = t->bits_per_word; - spi_imx->speed_hz = t->speed_hz; /* * Initialize the functions for transfer. To transfer non byte-aligned @@ -1183,7 +1233,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->slave_burst = t->len; } - spi_imx->devtype_data->config(spi); + spi_imx->devtype_data->prepare_transfer(spi_imx, spi, t); return 0; } @@ -1492,7 +1542,13 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg) return ret; } - return 0; + ret = spi_imx->devtype_data->prepare_message(spi_imx, msg); + if (ret) { + clk_disable(spi_imx->clk_ipg); + clk_disable(spi_imx->clk_per); + } + + return ret; } static int |