diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2015-12-08 08:27:47 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-12-08 08:27:47 +0100 |
commit | 29ac6ac467831e9b261465f13e871bc6bf9324a4 (patch) | |
tree | 17a5968802f131304a16a63450fb956356904634 /drivers | |
parent | a2b318fe2142f6032040a0702887086071b05ff6 (diff) | |
parent | 274e0b8dc48956babeaa2faf70bf8066e656b621 (diff) | |
download | barebox-29ac6ac467831e9b261465f13e871bc6bf9324a4.tar.gz barebox-29ac6ac467831e9b261465f13e871bc6bf9324a4.tar.xz |
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/imx_spi.c | 73 | ||||
-rw-r--r-- | drivers/video/imx-ipu-v3/imx-ldb.c | 26 | ||||
-rw-r--r-- | drivers/watchdog/imxwd.c | 5 |
3 files changed, 98 insertions, 6 deletions
diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 9a3f05cdec..2e489674d8 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -380,6 +380,77 @@ static void imx_spi_do_transfer(struct spi_device *spi) } } +static int cspi_2_3_xchg_burst(struct spi_device *spi) +{ + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + int now, txlen, rxlen; + u32 ctrl; + void __iomem *base = imx->regs; + + now = min(imx->xfer_len, 512); + now >>= 2; + + if (!now) + return 0; + + txlen = rxlen = now; + + ctrl = readl(base + CSPI_2_3_CTRL); + ctrl &= ~(0xfff << CSPI_2_3_CTRL_BL_OFFSET); + ctrl |= ((txlen * 32) - 1) << CSPI_2_3_CTRL_BL_OFFSET; + ctrl |= 1 << 3; + writel(ctrl, base + CSPI_2_3_CTRL); + + while (txlen || rxlen) { + u32 status = readl(base + CSPI_2_3_STAT); + + if (txlen && !(status & CSPI_2_3_STAT_TF)) { + if (imx->tx_buf) { + u32 data = swab32(*(u32 *)imx->tx_buf); + writel(data, base + CSPI_2_3_TXDATA); + imx->tx_buf += sizeof(u32); + } else { + writel(0, base + CSPI_2_3_TXDATA); + } + txlen--; + } + + if (rxlen && (status & CSPI_2_3_STAT_RR)) { + u32 data = readl(base + CSPI_2_3_RXDATA); + + if (imx->rx_buf) { + *(u32 *)imx->rx_buf = swab32(data); + imx->rx_buf += sizeof(u32); + } + + rxlen--; + } + } + + imx->xfer_len -= now * 4; + + return now; +} + +static void cspi_2_3_do_transfer(struct spi_device *spi) +{ + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + u32 ctrl; + + if (imx->bits_per_word == 8 && !(spi->mode & SPI_LSB_FIRST)) + while (cspi_2_3_xchg_burst(spi) > 0); + + if (!imx->xfer_len) + return; + + ctrl = readl(imx->regs + CSPI_2_3_CTRL); + ctrl &= ~(0xfff << CSPI_2_3_CTRL_BL_OFFSET); + ctrl |= (spi->bits_per_word - 1) << CSPI_2_3_CTRL_BL_OFFSET; + writel(ctrl, imx->regs + CSPI_2_3_CTRL); + + imx_spi_do_transfer(spi); +} + static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) { struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); @@ -437,7 +508,7 @@ static __maybe_unused struct spi_imx_devtype_data spi_imx_devtype_data_0_7 = { static __maybe_unused struct spi_imx_devtype_data spi_imx_devtype_data_2_3 = { .chipselect = cspi_2_3_chipselect, - .do_transfer = imx_spi_do_transfer, + .do_transfer = cspi_2_3_do_transfer, .xchg_single = cspi_2_3_xchg_single, }; diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c index a41eb1a3fc..2340b9b1d6 100644 --- a/drivers/video/imx-ipu-v3/imx-ldb.c +++ b/drivers/video/imx-ipu-v3/imx-ldb.c @@ -68,7 +68,7 @@ struct imx_ldb_channel { struct imx_ldb_data { void __iomem *base; - int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di); + int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di, unsigned long clkrate); unsigned ipu_mask; int have_mux; }; @@ -114,7 +114,7 @@ static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomo { struct imx_ldb *ldb = imx_ldb_ch->ldb; - ldb->soc_data->prepare(imx_ldb_ch, di); + ldb->soc_data->prepare(imx_ldb_ch, di, PICOS2KHZ(mode->pixclock) * 1000UL); /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */ if (imx_ldb_ch == &ldb->channel[0]) { @@ -146,7 +146,8 @@ static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomo return 0; } -static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) +static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di, + unsigned long pixclk) { struct clk *diclk, *ldbclk; struct imx_ldb *ldb = imx_ldb_ch->ldb; @@ -155,6 +156,7 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc; uint32_t val; int shift; + int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; ipuno = ((di >> 1) & 1) + 1; dino = di & 0x1; @@ -181,6 +183,11 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) return ret; } + if (!dual) + pixclk *= 2; + + clk_set_rate(clk_get_parent(ldbclk), pixclk); + val = readl(gpr3); shift = (imx_ldb_ch->chno == 0) ? 6 : 8; val &= ~(3 << shift); @@ -190,12 +197,14 @@ static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) return 0; } -static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) +static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di, + unsigned long pixclk) { struct clk *diclk, *ldbclk; struct imx_ldb *ldb = imx_ldb_ch->ldb; int ret, dino; char *clkname; + int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; dino = di & 0x1; @@ -221,6 +230,11 @@ static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di) return ret; } + if (!dual) + pixclk *= 2; + + clk_set_rate(clk_get_parent(ldbclk), pixclk); + return 0; } @@ -299,6 +313,10 @@ static int imx_ldb_probe(struct device_d *dev) imx_ldb->base = devtype->base; imx_ldb->soc_data = devtype; + dual = of_property_read_bool(np, "fsl,dual-channel"); + if (dual) + imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; + for_each_child_of_node(np, child) { struct imx_ldb_channel *channel; struct device_node *port; diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c index dd11a62613..1952548fa7 100644 --- a/drivers/watchdog/imxwd.c +++ b/drivers/watchdog/imxwd.c @@ -97,9 +97,12 @@ static int imx21_watchdog_set_timeout(struct imx_wd *priv, int timeout) dev_dbg(priv->dev, "%s: %d\n", __func__, timeout); - if (!timeout || timeout > 128) + if (timeout < -1 || timeout > 128) return -EINVAL; + if (timeout == 0) /* bit 2 (WDE) cannot be set to 0 again */ + return -ENOSYS; + if (timeout > 0) val = ((timeout * 2 - 1) << 8) | IMX21_WDOG_WCR_SRS | IMX21_WDOG_WCR_WDA; |