summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c12
-rw-r--r--drivers/dma/apbh_dma.c2
-rw-r--r--drivers/i2c/Kconfig5
-rw-r--r--drivers/i2c/mxc_i2c.c129
-rw-r--r--drivers/mtd/nand/raw/mxs_nand.c2
-rw-r--r--drivers/net/dwc_eth_qos.c2
-rw-r--r--drivers/net/rtl8169.c2
-rw-r--r--drivers/net/sh_eth.c3
-rw-r--r--drivers/nvme/nvme.c4
-rw-r--r--drivers/nvme/nvme_show.c4
-rw-r--r--drivers/video/video-uclass.c2
-rw-r--r--drivers/watchdog/bcm6345_wdt.c21
12 files changed, 129 insertions, 59 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 188d8431975..e3135bb75fd 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -55,17 +55,6 @@ __weak void __iomem *ahci_port_base(void __iomem *base, u32 port)
return base + 0x100 + (port * 0x80);
}
-
-static void ahci_setup_port(struct ahci_ioports *port, void __iomem *base,
- unsigned int port_idx)
-{
- base = ahci_port_base(base, port_idx);
-
- port->cmd_addr = base;
- port->scr_addr = base + PORT_SCR;
-}
-
-
#define msleep(a) udelay(a * 1000)
static void ahci_dcache_flush_range(unsigned long begin, unsigned long len)
@@ -240,7 +229,6 @@ static int ahci_host_init(struct ahci_uc_priv *uc_priv)
continue;
uc_priv->port[i].port_mmio = ahci_port_base(mmio, i);
port_mmio = (u8 *)uc_priv->port[i].port_mmio;
- ahci_setup_port(&uc_priv->port[i], mmio, i);
/* make sure port is not active */
tmp = readl(port_mmio + PORT_CMD);
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
index 017cc89a89f..ac589feeb7d 100644
--- a/drivers/dma/apbh_dma.c
+++ b/drivers/dma/apbh_dma.c
@@ -81,7 +81,7 @@ static int mxs_dma_read_semaphore(int channel)
return tmp;
}
-#ifndef CONFIG_SYS_DCACHE_OFF
+#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
{
uint32_t addr;
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 215624020f6..095a9bc6a4d 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -161,7 +161,10 @@ config SYS_I2C_MXC
channels and operating on standard mode up to 100 kbits/s and fast
mode up to 400 kbits/s.
-if SYS_I2C_MXC
+# These settings are not used with DM_I2C, however SPL doesn't use
+# DM_I2C even if DM_I2C is enabled, and so might use these settings even
+# when main u-boot does not!
+if SYS_I2C_MXC && (!DM_I2C || SPL)
config SYS_I2C_MXC_I2C1
bool "NXP MXC I2C1"
help
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 5420afbc8e0..23119cce65d 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -482,8 +482,13 @@ static int i2c_write_data(struct mxc_i2c_bus *i2c_bus, u8 chip, const u8 *buf,
return ret;
}
+/* Will generate a STOP after the last byte if "last" is true, i.e. this is the
+ * final message of a transaction. If not, it switches the bus back to TX mode
+ * and does not send a STOP, leaving the bus in a state where a repeated start
+ * and address can be sent for another message.
+ */
static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
- int len)
+ int len, bool last)
{
int ret;
unsigned int temp;
@@ -513,17 +518,31 @@ static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
return ret;
}
- /*
- * It must generate STOP before read I2DR to prevent
- * controller from generating another clock cycle
- */
if (i == (len - 1)) {
- i2c_imx_stop(i2c_bus);
+ /* Final byte has already been received by master! When
+ * we read it from I2DR, the master will start another
+ * cycle. We must program it first to send a STOP or
+ * switch to TX to avoid this.
+ */
+ if (last) {
+ i2c_imx_stop(i2c_bus);
+ } else {
+ /* Final read, no stop, switch back to tx */
+ temp = readb(base + (I2CR << reg_shift));
+ temp |= I2CR_MTX | I2CR_TX_NO_AK;
+ writeb(temp, base + (I2CR << reg_shift));
+ }
} else if (i == (len - 2)) {
+ /* Master has already recevied penultimate byte. When
+ * we read it from I2DR, master will start RX of final
+ * byte. We must set TX_NO_AK now so it does not ACK
+ * that final byte.
+ */
temp = readb(base + (I2CR << reg_shift));
temp |= I2CR_TX_NO_AK;
writeb(temp, base + (I2CR << reg_shift));
}
+
writeb(I2SR_IIF_CLEAR, base + (I2SR << reg_shift));
buf[i] = readb(base + (I2DR << reg_shift));
}
@@ -533,13 +552,34 @@ static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
debug(" 0x%02x", buf[ret]);
debug("\n");
- i2c_imx_stop(i2c_bus);
+ /* It is not clear to me that this is necessary */
+ if (last)
+ i2c_imx_stop(i2c_bus);
return 0;
}
#ifndef CONFIG_DM_I2C
/*
* Read data from I2C device
+ *
+ * The transactions use the syntax defined in the Linux kernel I2C docs.
+ *
+ * If alen is > 0, then this function will send a transaction of the form:
+ * S Chip Wr [A] Addr [A] S Chip Rd [A] [data] A ... NA P
+ * This is a normal I2C register read: writing the register address, then doing
+ * a repeated start and reading the data.
+ *
+ * If alen == 0, then we get this transaction:
+ * S Chip Wr [A] S Chip Rd [A] [data] A ... NA P
+ * This is somewhat unusual, though valid, transaction. It addresses the chip
+ * in write mode, but doesn't actually write any register address or data, then
+ * does a repeated start and reads data.
+ *
+ * If alen < 0, then we get this transaction:
+ * S Chip Rd [A] [data] A ... NA P
+ * The chip is addressed in read mode and then data is read. No register
+ * address is written first. This is perfectly valid on most devices and
+ * required on some (usually those that don't act like an array of registers).
*/
static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
int alen, u8 *buf, int len)
@@ -566,7 +606,7 @@ static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
return ret;
}
- ret = i2c_read_data(i2c_bus, chip, buf, len);
+ ret = i2c_read_data(i2c_bus, chip, buf, len, true);
i2c_imx_stop(i2c_bus);
return ret;
@@ -574,6 +614,20 @@ static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
/*
* Write data to I2C device
+ *
+ * If alen > 0, we get this transaction:
+ * S Chip Wr [A] addr [A] data [A] ... [A] P
+ * An ordinary write register command.
+ *
+ * If alen == 0, then we get this:
+ * S Chip Wr [A] data [A] ... [A] P
+ * This is a simple I2C write.
+ *
+ * If alen < 0, then we get this:
+ * S data [A] ... [A] P
+ * This is most likely NOT something that should be used. It doesn't send the
+ * chip address first, so in effect, the first byte of data will be used as the
+ * address.
*/
static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
int alen, const u8 *buf, int len)
@@ -881,6 +935,7 @@ static int mxc_i2c_probe(struct udevice *bus)
return 0;
}
+/* Sends: S Addr Wr [A|NA] P */
static int mxc_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
u32 chip_flags)
{
@@ -905,42 +960,54 @@ static int mxc_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
ulong base = i2c_bus->base;
int reg_shift = i2c_bus->driver_data & I2C_QUIRK_FLAG ?
VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT;
+ int read_mode;
- /*
- * Here the 3rd parameter addr and the 4th one alen are set to 0,
- * because here we only want to send out chip address. The register
- * address is wrapped in msg.
+ /* Here address len is set to -1 to not send any address at first.
+ * Otherwise i2c_init_transfer will send the chip address with write
+ * mode set. This is wrong if the 1st message is read.
*/
- ret = i2c_init_transfer(i2c_bus, msg->addr, 0, 0);
+ ret = i2c_init_transfer(i2c_bus, msg->addr, 0, -1);
if (ret < 0) {
debug("i2c_init_transfer error: %d\n", ret);
return ret;
}
+ read_mode = -1; /* So it's always different on the first message */
for (; nmsgs > 0; nmsgs--, msg++) {
- bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
- debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
- if (msg->flags & I2C_M_RD)
- ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
- msg->len);
- else {
- ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
- msg->len);
- if (ret)
- break;
- if (next_is_read) {
- /* Reuse ret */
+ const int msg_is_read = !!(msg->flags & I2C_M_RD);
+
+ debug("i2c_xfer: chip=0x%x, len=0x%x, dir=%c\n", msg->addr,
+ msg->len, msg_is_read ? 'R' : 'W');
+
+ if (msg_is_read != read_mode) {
+ /* Send repeated start if not 1st message */
+ if (read_mode != -1) {
+ debug("i2c_xfer: [RSTART]\n");
ret = readb(base + (I2CR << reg_shift));
ret |= I2CR_RSTA;
writeb(ret, base + (I2CR << reg_shift));
-
- ret = tx_byte(i2c_bus, (msg->addr << 1) | 1);
- if (ret < 0) {
- i2c_imx_stop(i2c_bus);
- break;
- }
}
+ debug("i2c_xfer: [ADDR %02x | %c]\n", msg->addr,
+ msg_is_read ? 'R' : 'W');
+ ret = tx_byte(i2c_bus, (msg->addr << 1) | msg_is_read);
+ if (ret < 0) {
+ debug("i2c_xfer: [STOP]\n");
+ i2c_imx_stop(i2c_bus);
+ break;
+ }
+ read_mode = msg_is_read;
}
+
+ if (msg->flags & I2C_M_RD)
+ ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+ msg->len, nmsgs == 1 ||
+ (msg->flags & I2C_M_STOP));
+ else
+ ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+ msg->len);
+
+ if (ret < 0)
+ break;
}
if (ret)
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index be4ee2c7f8a..b93d77a3951 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -50,7 +50,7 @@ struct nand_ecclayout fake_ecc_layout;
/*
* Cache management functions
*/
-#ifndef CONFIG_SYS_DCACHE_OFF
+#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
static void mxs_nand_flush_data_buf(struct mxs_nand_info *info)
{
uint32_t addr = (uint32_t)info->data_buf;
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 9f1c5af46e9..590e756f5c6 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -241,7 +241,7 @@ struct eqos_tegra186_regs {
*/
#if EQOS_DESCRIPTOR_SIZE < ARCH_DMA_MINALIGN
#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \
- !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86)
+ !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86)
#warning Cache line size is larger than descriptor size
#endif
#endif
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index bc052e72564..521e5909a25 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -302,7 +302,7 @@ static unsigned char rxdata[RX_BUF_LEN];
*/
#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && \
- !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_X86)
+ !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_X86)
#warning cache-line size is larger than descriptor size
#endif
#endif
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 8e54e7cc7a7..da79b766a62 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -34,7 +34,8 @@
# error "Please define CONFIG_SH_ETHER_PHY_ADDR"
#endif
-#if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF)
+#if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && \
+ !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
#define flush_cache_wback(addr, len) \
flush_dcache_range((u32)addr, \
(u32)(addr + ALIGN(len, CONFIG_SH_ETHER_ALIGNE_SIZE)))
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 1ee0a0aefb1..d4965e2ef63 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -577,7 +577,7 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev)
int ret;
int shift = NVME_CAP_MPSMIN(dev->cap) + 12;
- ret = nvme_identify(dev, 0, 1, (dma_addr_t)ctrl);
+ ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl);
if (ret)
return -EIO;
@@ -646,7 +646,7 @@ static int nvme_blk_probe(struct udevice *udev)
ns->dev = ndev;
/* extract the namespace id from the block device name */
ns->ns_id = trailing_strtol(udev->name) + 1;
- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)id))
+ if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id))
return -EIO;
flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c
index 395b0618e64..15e459da1ac 100644
--- a/drivers/nvme/nvme_show.c
+++ b/drivers/nvme/nvme_show.c
@@ -111,14 +111,14 @@ int nvme_print_info(struct udevice *udev)
ALLOC_CACHE_ALIGN_BUFFER(char, buf_ctrl, sizeof(struct nvme_id_ctrl));
struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf_ctrl;
- if (nvme_identify(dev, 0, 1, (dma_addr_t)ctrl))
+ if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl))
return -EIO;
print_optional_admin_cmd(le16_to_cpu(ctrl->oacs), ns->devnum);
print_optional_nvm_cmd(le16_to_cpu(ctrl->oncs), ns->devnum);
print_format_nvme_attributes(ctrl->fna, ns->devnum);
- if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)id))
+ if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id))
return -EIO;
print_formats(id, ns);
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 14aac88d6d2..b19bfb4f2ff 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -149,7 +149,7 @@ void video_sync(struct udevice *vid, bool force)
* architectures do not actually implement it. Is there a way to find
* out whether it exists? For now, ARM is safe.
*/
-#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF)
+#if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
struct video_priv *priv = dev_get_uclass_priv(vid);
if (priv->flush_dcache) {
diff --git a/drivers/watchdog/bcm6345_wdt.c b/drivers/watchdog/bcm6345_wdt.c
index 44f56620382..9f14e7d7774 100644
--- a/drivers/watchdog/bcm6345_wdt.c
+++ b/drivers/watchdog/bcm6345_wdt.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <dm.h>
#include <wdt.h>
+#include <clk.h>
#include <asm/io.h>
/* WDT Value register */
@@ -26,6 +27,7 @@
struct bcm6345_wdt_priv {
void __iomem *regs;
+ unsigned long clk_rate;
};
static int bcm6345_wdt_reset(struct udevice *dev)
@@ -41,16 +43,17 @@ static int bcm6345_wdt_reset(struct udevice *dev)
static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
{
struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+ u32 val = priv->clk_rate / 1000 * timeout;
- if (timeout < WDT_VAL_MIN) {
+ if (val < WDT_VAL_MIN) {
debug("watchdog won't fire with less than 2 ticks\n");
- timeout = WDT_VAL_MIN;
- } else if (timeout > WDT_VAL_MAX) {
+ val = WDT_VAL_MIN;
+ } else if (val > WDT_VAL_MAX) {
debug("maximum watchdog timeout exceeded\n");
- timeout = WDT_VAL_MAX;
+ val = WDT_VAL_MAX;
}
- writel(timeout, priv->regs + WDT_VAL_REG);
+ writel(val, priv->regs + WDT_VAL_REG);
return bcm6345_wdt_reset(dev);
}
@@ -85,11 +88,19 @@ static const struct udevice_id bcm6345_wdt_ids[] = {
static int bcm6345_wdt_probe(struct udevice *dev)
{
struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ int ret;
priv->regs = dev_remap_addr(dev);
if (!priv->regs)
return -EINVAL;
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret)
+ priv->clk_rate = clk_get_rate(&clk);
+ else
+ return -EINVAL;
+
bcm6345_wdt_stop(dev);
return 0;