summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:27:47 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-12-08 08:27:47 +0100
commit29ac6ac467831e9b261465f13e871bc6bf9324a4 (patch)
tree17a5968802f131304a16a63450fb956356904634 /drivers
parenta2b318fe2142f6032040a0702887086071b05ff6 (diff)
parent274e0b8dc48956babeaa2faf70bf8066e656b621 (diff)
downloadbarebox-29ac6ac467831e9b261465f13e871bc6bf9324a4.tar.gz
barebox-29ac6ac467831e9b261465f13e871bc6bf9324a4.tar.xz
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/imx_spi.c73
-rw-r--r--drivers/video/imx-ipu-v3/imx-ldb.c26
-rw-r--r--drivers/watchdog/imxwd.c5
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;