summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2015-09-02 10:39:28 -0400
committerTom Rini <trini@konsulko.com>2015-09-02 10:39:28 -0400
commit0ffadab1b9ab59816a0f71c927604bb6c402d863 (patch)
tree8338cea40ce53158387da4f708b09487cdebeaf9 /drivers
parent6923b069bd50b3ac519b16b6ae6aabbd2984c391 (diff)
parent37cf215253a488ba6b903989b1eff072f59d266e (diff)
downloadblackbird-obmc-uboot-0ffadab1b9ab59816a0f71c927604bb6c402d863.tar.gz
blackbird-obmc-uboot-0ffadab1b9ab59816a0f71c927604bb6c402d863.zip
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/mxc_gpio.c8
-rw-r--r--drivers/misc/mxc_ocotp.c152
-rw-r--r--drivers/misc/mxs_ocotp.c1
-rw-r--r--drivers/net/fec_mxc.c14
-rw-r--r--drivers/power/pmic/Makefile1
-rw-r--r--drivers/power/pmic/pmic_pfuze3000.c32
-rw-r--r--drivers/video/lg4573.c3
7 files changed, 196 insertions, 15 deletions
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 0c48320966..70fe5b6a4e 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -40,16 +40,18 @@ static unsigned long gpio_ports[] = {
[1] = GPIO2_BASE_ADDR,
[2] = GPIO3_BASE_ADDR,
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
- defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX7)
[3] = GPIO4_BASE_ADDR,
#endif
-#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX7)
[4] = GPIO5_BASE_ADDR,
#ifndef CONFIG_MX6UL
[5] = GPIO6_BASE_ADDR,
#endif
#endif
-#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6) || defined(CONFIG_MX7)
#ifndef CONFIG_MX6UL
[6] = GPIO7_BASE_ADDR,
#endif
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index d92044eeda..65ff8158e5 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -25,8 +25,21 @@
#define BM_CTRL_ERROR 0x00000200
#define BM_CTRL_BUSY 0x00000100
#define BO_CTRL_ADDR 0
+#ifdef CONFIG_MX7
+#define BM_CTRL_ADDR 0x0000000f
+#define BM_CTRL_RELOAD 0x00000400
+#else
#define BM_CTRL_ADDR 0x0000007f
-
+#endif
+
+#ifdef CONFIG_MX7
+#define BO_TIMING_FSOURCE 12
+#define BM_TIMING_FSOURCE 0x0007f000
+#define BV_TIMING_FSOURCE_NS 1001
+#define BO_TIMING_PROG 0
+#define BM_TIMING_PROG 0x00000fff
+#define BV_TIMING_PROG_US 10
+#else
#define BO_TIMING_STROBE_READ 16
#define BM_TIMING_STROBE_READ 0x003f0000
#define BV_TIMING_STROBE_READ_NS 37
@@ -36,6 +49,7 @@
#define BO_TIMING_STROBE_PROG 0
#define BM_TIMING_STROBE_PROG 0x00000fff
#define BV_TIMING_STROBE_PROG_US 10
+#endif
#define BM_READ_CTRL_READ_FUSE 0x00000001
@@ -43,6 +57,68 @@
#define WRITE_POSTAMBLE_US 2
+#if defined(CONFIG_MX6) || defined(CONFIG_VF610)
+#define FUSE_BANK_SIZE 0x80
+#ifdef CONFIG_MX6SL
+#define FUSE_BANKS 8
+#else
+#define FUSE_BANKS 16
+#endif
+#elif defined CONFIG_MX7
+#define FUSE_BANK_SIZE 0x40
+#define FUSE_BANKS 16
+#else
+#error "Unsupported architecture\n"
+#endif
+
+#if defined(CONFIG_MX6)
+#include <asm/arch/sys_proto.h>
+
+/*
+ * There is a hole in shadow registers address map of size 0x100
+ * between bank 5 and bank 6 on iMX6QP, iMX6DQ, iMX6SDL, iMX6SX and iMX6UL.
+ * Bank 5 ends at 0x6F0 and Bank 6 starts at 0x800. When reading the fuses,
+ * we should account for this hole in address space.
+ *
+ * Similar hole exists between bank 14 and bank 15 of size
+ * 0x80 on iMX6QP, iMX6DQ, iMX6SDL and iMX6SX.
+ * Note: iMX6SL has only 0-7 banks and there is no hole.
+ * Note: iMX6UL doesn't have this one.
+ *
+ * This function is to covert user input to physical bank index.
+ * Only needed when read fuse, because we use register offset, so
+ * need to calculate real register offset.
+ * When write, no need to consider hole, always use the bank/word
+ * index from fuse map.
+ */
+u32 fuse_bank_physical(int index)
+{
+ u32 phy_index;
+
+ if (is_cpu_type(MXC_CPU_MX6SL)) {
+ phy_index = index;
+ } else if (is_cpu_type(MXC_CPU_MX6UL)) {
+ if (index >= 6)
+ phy_index = fuse_bank_physical(5) + (index - 6) + 3;
+ else
+ phy_index = index;
+ } else {
+ if (index >= 15)
+ phy_index = fuse_bank_physical(14) + (index - 15) + 2;
+ else if (index >= 6)
+ phy_index = fuse_bank_physical(5) + (index - 6) + 3;
+ else
+ phy_index = index;
+ }
+ return phy_index;
+}
+#else
+u32 fuse_bank_physical(int index)
+{
+ return index;
+}
+#endif
+
static void wait_busy(struct ocotp_regs *regs, unsigned int delay_us)
{
while (readl(&regs->ctrl) & BM_CTRL_BUSY)
@@ -59,9 +135,9 @@ static int prepare_access(struct ocotp_regs **regs, u32 bank, u32 word,
{
*regs = (struct ocotp_regs *)OCOTP_BASE_ADDR;
- if (bank >= ARRAY_SIZE((*regs)->bank) ||
- word >= ARRAY_SIZE((*regs)->bank[0].fuse_regs) >> 2 ||
- !assert) {
+ if (bank >= FUSE_BANKS ||
+ word >= ARRAY_SIZE((*regs)->bank[0].fuse_regs) >> 2 ||
+ !assert) {
printf("mxc_ocotp %s(): Invalid argument\n", caller);
return -EINVAL;
}
@@ -99,16 +175,38 @@ int fuse_read(u32 bank, u32 word, u32 *val)
{
struct ocotp_regs *regs;
int ret;
+ u32 phy_bank;
ret = prepare_read(&regs, bank, word, val, __func__);
if (ret)
return ret;
- *val = readl(&regs->bank[bank].fuse_regs[word << 2]);
+ phy_bank = fuse_bank_physical(bank);
+
+ *val = readl(&regs->bank[phy_bank].fuse_regs[word << 2]);
return finish_access(regs, __func__);
}
+#ifdef CONFIG_MX7
+static void set_timing(struct ocotp_regs *regs)
+{
+ u32 ipg_clk;
+ u32 fsource, prog;
+ u32 timing;
+
+ ipg_clk = mxc_get_clock(MXC_IPG_CLK);
+
+ fsource = DIV_ROUND_UP((ipg_clk / 1000) * BV_TIMING_FSOURCE_NS,
+ + 1000000) + 1;
+ prog = DIV_ROUND_CLOSEST(ipg_clk * BV_TIMING_PROG_US, 1000000) + 1;
+
+ timing = BF(fsource, TIMING_FSOURCE) | BF(prog, TIMING_PROG);
+
+ clrsetbits_le32(&regs->timing, BM_TIMING_FSOURCE | BM_TIMING_PROG,
+ timing);
+}
+#else
static void set_timing(struct ocotp_regs *regs)
{
u32 ipg_clk;
@@ -130,12 +228,17 @@ static void set_timing(struct ocotp_regs *regs)
clrsetbits_le32(&regs->timing, BM_TIMING_STROBE_READ | BM_TIMING_RELAX |
BM_TIMING_STROBE_PROG, timing);
}
+#endif
static void setup_direct_access(struct ocotp_regs *regs, u32 bank, u32 word,
int write)
{
u32 wr_unlock = write ? BV_CTRL_WR_UNLOCK_KEY : 0;
+#ifdef CONFIG_MX7
+ u32 addr = bank;
+#else
u32 addr = bank << 3 | word;
+#endif
set_timing(regs);
clrsetbits_le32(&regs->ctrl, BM_CTRL_WR_UNLOCK | BM_CTRL_ADDR,
@@ -155,7 +258,11 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
setup_direct_access(regs, bank, word, false);
writel(BM_READ_CTRL_READ_FUSE, &regs->read_ctrl);
wait_busy(regs, 1);
+#ifdef CONFIG_MX7
+ *val = readl((&regs->read_fuse_data0) + (word << 2));
+#else
*val = readl(&regs->read_fuse_data);
+#endif
return finish_access(regs, __func__);
}
@@ -176,8 +283,38 @@ int fuse_prog(u32 bank, u32 word, u32 val)
return ret;
setup_direct_access(regs, bank, word, true);
+#ifdef CONFIG_MX7
+ switch (word) {
+ case 0:
+ writel(0, &regs->data1);
+ writel(0, &regs->data2);
+ writel(0, &regs->data3);
+ writel(val, &regs->data0);
+ break;
+ case 1:
+ writel(val, &regs->data1);
+ writel(0, &regs->data2);
+ writel(0, &regs->data3);
+ writel(0, &regs->data0);
+ break;
+ case 2:
+ writel(0, &regs->data1);
+ writel(val, &regs->data2);
+ writel(0, &regs->data3);
+ writel(0, &regs->data0);
+ break;
+ case 3:
+ writel(0, &regs->data1);
+ writel(0, &regs->data2);
+ writel(val, &regs->data3);
+ writel(0, &regs->data0);
+ break;
+ }
+ wait_busy(regs, BV_TIMING_PROG_US);
+#else
writel(val, &regs->data);
wait_busy(regs, BV_TIMING_STROBE_PROG_US);
+#endif
udelay(WRITE_POSTAMBLE_US);
return finish_access(regs, __func__);
@@ -187,12 +324,15 @@ int fuse_override(u32 bank, u32 word, u32 val)
{
struct ocotp_regs *regs;
int ret;
+ u32 phy_bank;
ret = prepare_write(&regs, bank, word, __func__);
if (ret)
return ret;
- writel(val, &regs->bank[bank].fuse_regs[word << 2]);
+ phy_bank = fuse_bank_physical(bank);
+
+ writel(val, &regs->bank[phy_bank].fuse_regs[word << 2]);
return finish_access(regs, __func__);
}
diff --git a/drivers/misc/mxs_ocotp.c b/drivers/misc/mxs_ocotp.c
index 6f0a1d3e6d..6c0d247ed2 100644
--- a/drivers/misc/mxs_ocotp.c
+++ b/drivers/misc/mxs_ocotp.c
@@ -152,6 +152,7 @@ static int mxs_ocotp_scale_hclk(bool enter, uint32_t *val)
/* Return the original HCLK clock speed. */
*val = readl(&clkctrl_regs->hw_clkctrl_hbus);
*val &= CLKCTRL_HBUS_DIV_MASK;
+ *val >>= CLKCTRL_HBUS_DIV_OFFSET;
/* Scale the HCLK to 454/19 = 23.9 MHz . */
scale_val = (~19) << CLKCTRL_HBUS_DIV_OFFSET;
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index c5dcbbbced..bff5fd1119 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -17,6 +17,7 @@
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/sys_proto.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/compiler.h>
@@ -551,12 +552,15 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
writel(0x00000000, &fec->eth->gaddr2);
- /* clear MIB RAM */
- for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
- writel(0, i);
+ /* Do not access reserved register for i.MX6UL */
+ if (!is_cpu_type(MXC_CPU_MX6UL)) {
+ /* clear MIB RAM */
+ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
+ writel(0, i);
- /* FIFO receive start register */
- writel(0x520, &fec->eth->r_fstart);
+ /* FIFO receive start register */
+ writel(0x520, &fec->eth->r_fstart);
+ }
/* size and address of each buffer */
writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 99c5778334..e7a761703e 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
+obj-$(CONFIG_POWER_PFUZE3000) += pmic_pfuze3000.o
obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o
obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
diff --git a/drivers/power/pmic/pmic_pfuze3000.c b/drivers/power/pmic/pmic_pfuze3000.c
new file mode 100644
index 0000000000..ac807a801f
--- /dev/null
+++ b/drivers/power/pmic/pmic_pfuze3000.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Peng Fan <Peng.Fan@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pfuze3000_pmic.h>
+
+int power_pfuze3000_init(unsigned char bus)
+{
+ static const char name[] = "PFUZE3000";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = PMIC_NUM_OF_REGS;
+ p->hw.i2c.addr = CONFIG_POWER_PFUZE3000_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/drivers/video/lg4573.c b/drivers/video/lg4573.c
index 43670fc320..11fef279a9 100644
--- a/drivers/video/lg4573.c
+++ b/drivers/video/lg4573.c
@@ -220,7 +220,8 @@ err_claim_bus:
static int do_lgset(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
- lg4573_spi_startup(0, 0, 10000000, SPI_MODE_0);
+ lg4573_spi_startup(CONFIG_LG4573_BUS, CONFIG_LG4573_CS, 10000000,
+ SPI_MODE_0);
return 0;
}
OpenPOWER on IntegriCloud