struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
unsigned int len = t->len;
- - u8 bits_per_word;
int ret;
- - bits_per_word = spi->bits_per_word;
- - if (t->bits_per_word)
- - bits_per_word = t->bits_per_word;
- -
mpc8xxx_spi->len = t->len;
len = roundup(len, 4) / 4;
m->actual_length = espi_trans.actual_length;
m->status = espi_trans.status;
- --- m->complete(m->context);
+ +++ if (m->complete)
+ +++ m->complete(m->context);
}
static int fsl_espi_setup(struct spi_device *spi)
if (!bits_per_word)
bits_per_word = spi->bits_per_word;
- - /* Make sure its a bit width we support [4..16, 32] */
- - if ((bits_per_word < 4)
- - || ((bits_per_word > 16) && (bits_per_word != 32))
- - || (bits_per_word > mpc8xxx_spi->max_bits_per_word))
- - return -EINVAL;
- -
if (!hz)
hz = spi->max_speed_hz;
static void fsl_spi_do_one_msg(struct spi_message *m)
{
struct spi_device *spi = m->spi;
- - struct spi_transfer *t;
+ + struct spi_transfer *t, *first;
unsigned int cs_change;
const int nsecs = 50;
int status;
- - cs_change = 1;
- - status = 0;
+ + /* Don't allow changes if CS is active */
+ + first = list_first_entry(&m->transfers, struct spi_transfer,
+ + transfer_list);
list_for_each_entry(t, &m->transfers, transfer_list) {
- - if (t->bits_per_word || t->speed_hz) {
- - /* Don't allow changes if CS is active */
+ + if ((first->bits_per_word != t->bits_per_word) ||
+ + (first->speed_hz != t->speed_hz)) {
status = -EINVAL;
+ + dev_err(&spi->dev,
+ + "bits_per_word/speed_hz should be same for the same SPI transfer\n");
+ + return;
+ + }
+ + }
+ + cs_change = 1;
+ + status = -EINVAL;
+ + list_for_each_entry(t, &m->transfers, transfer_list) {
+ + if (t->bits_per_word || t->speed_hz) {
if (cs_change)
status = fsl_spi_setup_transfer(spi, t);
if (status < 0)
}
m->status = status;
- --- m->complete(m->context);
+ +++ if (m->complete)
+ +++ m->complete(m->context);
if (status || !cs_change) {
ndelay(nsecs);
if (mpc8xxx_spi->type == TYPE_GRLIB)
fsl_spi_grlib_probe(dev);
+ + master->bits_per_word_mask =
+ + (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
+ + SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
+ +
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
mpc8xxx_spi->set_shifts = fsl_spi_qe_cpu_set_shifts;
#include <linux/module.h>
#include <linux/kernel.h>
- - #include <linux/init.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/of_address.h>
}
m->status = status;
- --- m->complete(m->context);
+ +++ if (m->complete)
+ +++ m->complete(m->context);
if (status || !cs_change)
mpc512x_psc_spi_deactivate_cs(spi);
gpio_set_value(spi->cs_gpio, onoff);
}
- - /* bus_num is used only for the case dev->platform_data == NULL */
static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
- - u32 size, unsigned int irq,
- - s16 bus_num)
+ + u32 size, unsigned int irq)
{
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc512x_psc_spi *mps;
if (pdata == NULL) {
mps->cs_control = mpc512x_spi_cs_control;
- - master->bus_num = bus_num;
} else {
mps->cs_control = pdata->cs_control;
master->bus_num = pdata->bus_num;
{
const u32 *regaddr_p;
u64 regaddr64, size64;
- - s16 id = -1;
regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL);
if (!regaddr_p) {
}
regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
- - /* get PSC id (0..11, used by port_config) */
- - id = of_alias_get_id(op->dev.of_node, "spi");
- - if (id < 0) {
- - dev_err(&op->dev, "no alias id for %s\n",
- - op->dev.of_node->full_name);
- - return id;
- - }
- -
return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
- - irq_of_parse_and_map(op->dev.of_node, 0), id);
+ + irq_of_parse_and_map(op->dev.of_node, 0));
}
static int mpc512x_psc_spi_of_remove(struct platform_device *op)
*/
#include <linux/module.h>
- - #include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
}
m->status = status;
- --- m->complete(m->context);
+ +++ if (m->complete)
+ +++ m->complete(m->context);
if (status || !cs_change)
mpc52xx_psc_spi_deactivate_cs(spi);
*/
#include <linux/module.h>
- - #include <linux/init.h>
#include <linux/errno.h>
#include <linux/of_platform.h>
#include <linux/interrupt.h>
dev_err(&ms->master->dev, "mode fault\n");
mpc52xx_spi_chipsel(ms, 0);
ms->message->status = -EIO;
- --- ms->message->complete(ms->message->context);
+ +++ if (ms->message->complete)
+ +++ ms->message->complete(ms->message->context);
ms->state = mpc52xx_spi_fsmstate_idle;
return FSM_CONTINUE;
}
ms->msg_count++;
mpc52xx_spi_chipsel(ms, 0);
ms->message->status = 0;
- --- ms->message->complete(ms->message->context);
+ +++ if (ms->message->complete)
+ +++ ms->message->complete(ms->message->context);
ms->state = mpc52xx_spi_fsmstate_idle;
return FSM_CONTINUE;
}
* spi_master ops
*/
- - static int mpc52xx_spi_setup(struct spi_device *spi)
- - {
- - if (spi->bits_per_word % 8)
- - return -EINVAL;
- -
- - if (spi->mode & ~(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST))
- - return -EINVAL;
- -
- - if (spi->chip_select >= spi->master->num_chipselect)
- - return -EINVAL;
- -
- - return 0;
- - }
- -
static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
{
struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
goto err_alloc;
}
- - master->setup = mpc52xx_spi_setup;
master->transfer = mpc52xx_spi_transfer;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+ + master->bits_per_word_mask = SPI_BPW_MASK(8);
master->dev.of_node = op->dev.of_node;
platform_set_drvdata(op, master);
*/
#include <linux/kernel.h>
- - #include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
+ + #define OMAP2_MCSPI_MAX_DIVIDER 4096
#define OMAP2_MCSPI_MAX_FIFODEPTH 64
#define OMAP2_MCSPI_MAX_FIFOWCNT 0xFFFF
#define SPI_AUTOSUSPEND_TIMEOUT 2000
#define OMAP2_MCSPI_CHCONF_FORCE BIT(20)
#define OMAP2_MCSPI_CHCONF_FFET BIT(27)
#define OMAP2_MCSPI_CHCONF_FFER BIT(28)
+ + #define OMAP2_MCSPI_CHCONF_CLKG BIT(29)
#define OMAP2_MCSPI_CHSTAT_RXS BIT(0)
#define OMAP2_MCSPI_CHSTAT_TXS BIT(1)
#define OMAP2_MCSPI_CHSTAT_TXFFE BIT(3)
#define OMAP2_MCSPI_CHCTRL_EN BIT(0)
+ + #define OMAP2_MCSPI_CHCTRL_EXTCLK_MASK (0xff << 8)
#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0)
int word_len;
struct list_head node;
/* Context save and restore shadow register */
- - u32 chconf0;
+ + u32 chconf0, chctrl0;
};
static inline void mcspi_write_reg(struct spi_master *master,
static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
{
+ + struct omap2_mcspi_cs *cs = spi->controller_state;
u32 l;
- - l = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
- - mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, l);
+ + l = cs->chctrl0;
+ + if (enable)
+ + l |= OMAP2_MCSPI_CHCTRL_EN;
+ + else
+ + l &= ~OMAP2_MCSPI_CHCTRL_EN;
+ + cs->chctrl0 = l;
+ + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
/* Flash post-writes */
mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCTRL0);
}
struct omap2_mcspi_cs *cs = spi->controller_state;
struct omap2_mcspi *mcspi;
struct spi_master *spi_cntrl;
- - u32 l = 0, div = 0;
+ + u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
u8 word_len = spi->bits_per_word;
u32 speed_hz = spi->max_speed_hz;
speed_hz = t->speed_hz;
speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
- - div = omap2_mcspi_calc_divisor(speed_hz);
+ + if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
+ + clkd = omap2_mcspi_calc_divisor(speed_hz);
+ + speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
+ + clkg = 0;
+ + } else {
+ + div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
+ + speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
+ + clkd = (div - 1) & 0xf;
+ + extclk = (div - 1) >> 4;
+ + clkg = OMAP2_MCSPI_CHCONF_CLKG;
+ + }
l = mcspi_cached_chconf0(spi);
/* set clock divisor */
l &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
- - l |= div << 2;
+ + l |= clkd << 2;
+ +
+ + /* set clock granularity */
+ + l &= ~OMAP2_MCSPI_CHCONF_CLKG;
+ + l |= clkg;
+ + if (clkg) {
+ + cs->chctrl0 &= ~OMAP2_MCSPI_CHCTRL_EXTCLK_MASK;
+ + cs->chctrl0 |= extclk << 8;
+ + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCTRL0, cs->chctrl0);
+ + }
/* set SPI mode 0..3 */
if (spi->mode & SPI_CPOL)
mcspi_write_chconf0(spi, l);
dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
- - OMAP2_MCSPI_MAX_FREQ >> div,
+ + speed_hz,
(spi->mode & SPI_CPHA) ? "trailing" : "leading",
(spi->mode & SPI_CPOL) ? "inverted" : "normal");
cs->base = mcspi->base + spi->chip_select * 0x14;
cs->phys = mcspi->phys + spi->chip_select * 0x14;
cs->chconf0 = 0;
+ + cs->chctrl0 = 0;
spi->controller_state = cs;
/* Link this to context save list */
list_add_tail(&cs->node, &ctx->cs);
status = -EINVAL;
break;
}
- - if (par_override || t->speed_hz || t->bits_per_word) {
+ + if (par_override ||
+ + (t->speed_hz != spi->max_speed_hz) ||
+ + (t->bits_per_word != spi->bits_per_word)) {
par_override = 1;
status = omap2_mcspi_setup_transfer(spi, t);
if (status < 0)
break;
- - if (!t->speed_hz && !t->bits_per_word)
+ + if (t->speed_hz == spi->max_speed_hz &&
+ + t->bits_per_word == spi->bits_per_word)
par_override = 0;
}
if (cd && cd->cs_per_word) {
m->actual_length = 0;
m->status = 0;
- - /* reject invalid messages and transfers */
- - if (list_empty(&m->transfers))
- - return -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
const void *tx_buf = t->tx_buf;
void *rx_buf = t->rx_buf;
unsigned len = t->len;
- - if (t->speed_hz > OMAP2_MCSPI_MAX_FREQ
- - || (len && !(rx_buf || tx_buf))) {
+ + if ((len && !(rx_buf || tx_buf))) {
dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz,
len,
t->bits_per_word);
return -EINVAL;
}
- - if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
- - dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
- - t->speed_hz,
- - OMAP2_MCSPI_MAX_FREQ >> 15);
- - return -EINVAL;
- - }
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
continue;
master->transfer_one_message = omap2_mcspi_transfer_one_message;
master->cleanup = omap2_mcspi_cleanup;
master->dev.of_node = node;
+ + master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
+ + master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
platform_set_drvdata(pdev, master);
INIT_LIST_HEAD(&mcspi->ctx.cs);
--- - mcspi->dma_channels = kcalloc(master->num_chipselect,
--- - sizeof(struct omap2_mcspi_dma),
--- - GFP_KERNEL);
--- -
--- - if (mcspi->dma_channels == NULL)
+++ + mcspi->dma_channels = devm_kcalloc(&pdev->dev, master->num_chipselect,
+++ + sizeof(struct omap2_mcspi_dma),
+++ + GFP_KERNEL);
+++ + if (mcspi->dma_channels == NULL) {
+++ + status = -ENOMEM;
goto free_master;
+++ + }
for (i = 0; i < master->num_chipselect; i++) {
char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
}
if (status < 0)
--- - goto dma_chnl_free;
+++ + goto free_master;
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
disable_pm:
pm_runtime_disable(&pdev->dev);
--- -dma_chnl_free:
--- - kfree(mcspi->dma_channels);
free_master:
spi_master_put(master);
return status;
static int omap2_mcspi_remove(struct platform_device *pdev)
{
--- - struct spi_master *master;
--- - struct omap2_mcspi *mcspi;
--- - struct omap2_mcspi_dma *dma_channels;
--- -
--- - master = platform_get_drvdata(pdev);
--- - mcspi = spi_master_get_devdata(master);
--- - dma_channels = mcspi->dma_channels;
+++ + struct spi_master *master = platform_get_drvdata(pdev);
+++ + struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
pm_runtime_put_sync(mcspi->dev);
pm_runtime_disable(&pdev->dev);
--- - kfree(dma_channels);
--- -
return 0;
}
void __iomem *membase;
int baseclk;
struct clk *clk;
- - u32 max_speed_hz, min_speed_hz;
int last_chipselect;
int last_chipselect_val;
};
{
struct txx9spi *c = spi_master_get_devdata(spi->master);
- - if (!spi->max_speed_hz
- - || spi->max_speed_hz > c->max_speed_hz
- - || spi->max_speed_hz < c->min_speed_hz)
+ + if (!spi->max_speed_hz)
return -EINVAL;
if (gpio_direction_output(spi->chip_select,
exit:
m->status = status;
- --- m->complete(m->context);
+ +++ if (m->complete)
+ +++ m->complete(m->context);
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
/* check each transfer's parameters */
list_for_each_entry(t, &m->transfers, transfer_list) {
- - u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
- - u8 bits_per_word = t->bits_per_word;
- -
if (!t->tx_buf && !t->rx_buf && t->len)
return -EINVAL;
- - if (t->len & ((bits_per_word >> 3) - 1))
- - return -EINVAL;
- - if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
- - return -EINVAL;
}
spin_lock_irqsave(&c->lock, flags);
goto exit;
}
c->baseclk = clk_get_rate(c->clk);
- - c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
- - c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
+ + master->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1);
+ + master->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- - if (!res)
- - goto exit_busy;
- - if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
- - "spi_txx9"))
- - goto exit_busy;
- - c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
- - if (!c->membase)
+ + c->membase = devm_ioremap_resource(&dev->dev, res);
+ + if (IS_ERR(c->membase))
goto exit_busy;
/* enter config mode */