summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-12-07 08:12:39 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-12-07 08:12:39 +0100
commit1d8bb9be35508b62a6f6d0d792fa29568710a2a9 (patch)
treef77f02aea8e21522c6b0865916d2bfab4cdf19f5 /drivers
parent3d565eac1c01ed9c50951bd0c097c32e2e650a45 (diff)
parent113677818502a071aeaddffd0b64dce3dcab220d (diff)
downloadbarebox-1d8bb9be35508b62a6f6d0d792fa29568710a2a9.tar.gz
barebox-1d8bb9be35508b62a6f6d0d792fa29568710a2a9.tar.xz
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/imx/clk-imx5.c9
-rw-r--r--drivers/crypto/caam/Kconfig24
-rw-r--r--drivers/crypto/caam/Makefile1
-rw-r--r--drivers/crypto/caam/ctrl.c20
-rw-r--r--drivers/crypto/caam/regs.h4
-rw-r--r--drivers/crypto/caam/rng_self_test.c206
-rw-r--r--drivers/crypto/caam/rng_self_test.h24
-rw-r--r--drivers/hab/habv3.c4
-rw-r--r--drivers/hab/habv4.c93
-rw-r--r--drivers/nvmem/ocotp.c17
-rw-r--r--drivers/video/imx-ipu-v3/imx-pd.c2
-rw-r--r--drivers/video/imx-ipu-v3/ipu-di.c1
12 files changed, 399 insertions, 6 deletions
diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c
index ae94e07f23..f59a41b001 100644
--- a/drivers/clk/imx/clk-imx5.c
+++ b/drivers/clk/imx/clk-imx5.c
@@ -60,6 +60,7 @@
#define CCM_CMEOR 0x84
static struct clk *clks[IMX5_CLK_END];
+static struct clk_onecell_data clk_data;
/* This is used multiple times */
static const char *standard_pll_sel[] = {
@@ -411,6 +412,10 @@ static int imx51_ccm_probe(struct device_d *dev)
mx51_clocks_init(dev, regs);
+ clk_data.clks = clks;
+ clk_data.clk_num = IMX5_CLK_END;
+ of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+
return 0;
}
@@ -503,6 +508,10 @@ static int imx53_ccm_probe(struct device_d *dev)
mx53_clocks_init(dev, regs);
+ clk_data.clks = clks;
+ clk_data.clk_num = IMX5_CLK_END;
+ of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+
return 0;
}
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 2ab509d110..56b90700b8 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -33,3 +33,27 @@ config CRYPTO_DEV_FSL_CAAM_RNG
default y
help
Selecting this will register the SEC4 hardware rng.
+
+if CRYPTO_DEV_FSL_CAAM_RNG
+
+config CRYPTO_DEV_FSL_CAAM_RNG_SELF_TEST
+ bool "Run RNG software self-test on impacted chips"
+ depends on ARCH_IMX6
+ depends on HABV4
+ default y
+ help
+ Some chips with HAB >= 4.2.3 have an incorrect implementation of the
+ RNG self-test in ROM code. In this case, a software self-test should
+ be run to ensure correctness of the RNG. By enabling this config
+ option, the software self-test is run automatically when this case
+ is detected.
+
+ Currently known impacted chips:
+ * i.MX6DQ+ silicon revision 1.1
+ * i.MX6DQ silicon revision 1.6
+ * i.MX6DLS silicon revision 1.4
+ * i.MX6SX silicon revision 1.4
+ * i.MX6UL silicon revision 1.2
+ * i.MX67SD silicon revision 1.3
+
+endif
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 74d32da00e..7bd6f3e23c 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += ctrl.o error.o jr.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_SELF_TEST) += rng_self_test.o
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 9e62bd6fd6..39910131b1 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <clock.h>
#include <driver.h>
+#include <hab.h>
#include <init.h>
#include <linux/barebox-wrapper.h>
#include <linux/spinlock.h>
@@ -19,6 +20,7 @@
#include "desc_constr.h"
#include "error.h"
#include "ctrl.h"
+#include "rng_self_test.h"
bool caam_little_end;
EXPORT_SYMBOL(caam_little_end);
@@ -570,6 +572,24 @@ static int caam_probe(struct device_d *dev)
cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls);
+ /* habv4_need_rng_software_self_test is determined by habv4_get_status() */
+ if (IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_SELF_TEST) &&
+ habv4_need_rng_software_self_test) {
+ u8 caam_era;
+ u8 rngvid;
+ u8 rngrev;
+
+ caam_era = (rd_reg32(&ctrl->perfmon.ccb_id) & CCBVID_ERA_MASK) >> CCBVID_ERA_SHIFT;
+ rngvid = (cha_vid_ls & CHAVID_LS_RNGVID_MASK) >> CHAVID_LS_RNGVID_SHIFT;
+ rngrev = (rd_reg32(&ctrl->perfmon.cha_rev_ls) & CRNR_LS_RNGRN_MASK) >> CRNR_LS_RNGRN_SHIFT;
+
+ ret = caam_rng_self_test(ctrlpriv->jrpdev[0], caam_era, rngvid, rngrev);
+ if (ret != 0) {
+ caam_remove(dev);
+ return ret;
+ }
+ }
+
/*
* If SEC has RNG version >= 4 and RNG state handle has not been
* already instantiated, do RNG instantiation
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 6c9d6d75a0..19e7d6d7e4 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -279,6 +279,8 @@ struct caam_perfmon {
/* CAAM Hardware Instantiation Parameters fa0-fbf */
u32 cha_rev_ms; /* CRNR - CHA Rev No. Most significant half*/
+#define CRNR_LS_RNGRN_SHIFT 16
+#define CRNR_LS_RNGRN_MASK (0xfull << CRNR_LS_RNGRN_SHIFT)
u32 cha_rev_ls; /* CRNR - CHA Rev No. Least significant half*/
#define CTPR_MS_QI_SHIFT 25
#define CTPR_MS_QI_MASK (0x1ull << CTPR_MS_QI_SHIFT)
@@ -311,6 +313,8 @@ struct caam_perfmon {
#define CCBVID_ERA_SHIFT 24
u32 ccb_id; /* CCBVID - CCB Version ID */
u32 cha_id_ms; /* CHAVID - CHA Version ID Most Significant*/
+#define CHAVID_LS_RNGVID_SHIFT 16
+#define CHAVID_LS_RNGVID_MASK (0xfull << CHAVID_LS_RNGVID_SHIFT)
u32 cha_id_ls; /* CHAVID - CHA Version ID Least Significant*/
u32 cha_num_ms; /* CHANUM - CHA Number Most Significant */
u32 cha_num_ls; /* CHANUM - CHA Number Least Significant*/
diff --git a/drivers/crypto/caam/rng_self_test.c b/drivers/crypto/caam/rng_self_test.c
new file mode 100644
index 0000000000..aab4fa2e47
--- /dev/null
+++ b/drivers/crypto/caam/rng_self_test.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2018 NXP
+ * Copyright (C) 2018 Pengutronix, Roland Hieber <r.hieber@pengutronix.de>
+ *
+ * CAAM RNG self-test -- based on the vendor patch for U-Boot:
+ * https://portland.source.codeaurora.org/patches/external/imxsupport/uboot-imx/imx_v2016.03_4.1.15_2.0.0_ga/HAB-238-Run-RNG-self-test-for-impacted-i.MX-chips.zip
+ *
+ * | From: Utkarsh Gupta <utkarsh.gupta@nxp.com>
+ * | Subject: [PATCH] HAB-238 Run RNG self test for impacted i.MX chips
+ * |
+ * | Patch is only applicable to imx_v2016.03_4.1.15_2.0.0_ga branch of u-boot.
+ * | Please adapt the patch for your respective release version.
+ * |
+ * | Background:
+ * | Few i.MX chips which have HAB 4.2.3 or beyond, have oberserved following
+ * | warning message generated by HAB due to incorrect implementation of drng
+ * | self test in boot ROM.
+ * |
+ * | Event |0xdb|0x0024|0x42| SRCE Field: 69 30 e1 1d
+ * | | | | | STS = HAB_WARNING (0x69)
+ * | | | | | RSN = HAB_ENG_FAIL (0x30)
+ * | | | | | CTX = HAB_CTX_ENTRY (0xE1)
+ * | | | | | ENG = HAB_ENG_CAAM (0x1D)
+ * | | | | | Evt Data (hex):
+ * | | | | | 00 08 00 02 40 00 36 06 55 55 00 03 00 00 00 00
+ * | | | | | 00 00 00 00 00 00 00 00 00 00 00 01
+ * |
+ * | It is recommended to run this rng self test before any RNG related crypto
+ * | implementations are done.
+ * [...]
+ * |
+ * | Signed-off-by: Utkarsh Gupta <utkarsh.gupta@nxp.com>
+ *
+ * Known impacted chips:
+ *
+ * - i.MX6DQ+ silicon revision 1.1
+ * - i.MX6DQ silicon revision 1.6
+ * - i.MX6DLS silicon revision 1.4
+ * - i.MX6SX silicon revision 1.4
+ * - i.MX6UL silicon revision 1.2
+ * - i.MX67SD silicon revision 1.3
+ */
+
+#define pr_fmt(fmt) "rng_self_test: " fmt
+
+#include <dma.h>
+#include <common.h>
+#include <linux/kernel.h>
+
+#include "error.h"
+#include "regs.h"
+#include "jr.h"
+
+static const u32 rng_dsc1[] = {
+ 0xb0800036, 0x04800010, 0x3c85a15b, 0x50a9d0b1,
+ 0x71a09fee, 0x2eecf20b, 0x02800020, 0xb267292e,
+ 0x85bf712d, 0xe85ff43a, 0xa716b7fb, 0xc40bb528,
+ 0x27b6f564, 0x8821cb5d, 0x9b5f6c26, 0x12a00020,
+ 0x0a20de17, 0x6529357e, 0x316277ab, 0x2846254e,
+ 0x34d23ba5, 0x6f5e9c32, 0x7abdc1bb, 0x0197a385,
+ 0x82500405, 0xa2000001, 0x10880004, 0x00000005,
+ 0x12820004, 0x00000020, 0x82500001, 0xa2000001,
+ 0x10880004, 0x40000045, 0x02800020, 0x8f389cc7,
+ 0xe7f7cbb0, 0x6bf2073d, 0xfc380b6d, 0xb22e9d1a,
+ 0xee64fcb7, 0xa2b48d49, 0xdf9bc3a4, 0x82500009,
+ 0xa2000001, 0x10880004, 0x00000005, 0x82500001,
+ 0x60340020, 0xFFFFFFFF, 0xa2000001, 0x10880004,
+ 0x00000005, 0x8250000d
+};
+
+static const u8 rng_result1[] = {
+ 0x3a, 0xfe, 0x2c, 0x87, 0xcc, 0xb6, 0x44, 0x49,
+ 0x19, 0x16, 0x9a, 0x74, 0xa1, 0x31, 0x8b, 0xef,
+ 0xf4, 0x86, 0x0b, 0xb9, 0x5e, 0xee, 0xae, 0x91,
+ 0x92, 0xf4, 0xa9, 0x8f, 0xb0, 0x37, 0x18, 0xa4
+};
+
+static const u32 rng_dsc2[] = {
+ 0xb080003a, 0x04800020, 0x27b73130, 0x30b4b10f,
+ 0x7c62b1ad, 0x77abe899, 0x67452301, 0xefcdab89,
+ 0x98badcfe, 0x10325476, 0x02800020, 0x63f757cf,
+ 0xb9165584, 0xc3c1b407, 0xcc4ce8ad, 0x1ffe8a58,
+ 0xfb4fa893, 0xbb5f4af0, 0x3fb946a1, 0x12a00020,
+ 0x56cbcaa5, 0xfff3adad, 0xe804dcbf, 0x9a900c71,
+ 0xa42017e3, 0x826948e2, 0xd0cfeb3e, 0xaf1a136a,
+ 0x82500405, 0xa2000001, 0x10880004, 0x00000005,
+ 0x12820004, 0x00000020, 0x82500001, 0xa2000001,
+ 0x10880004, 0x40000045, 0x02800020, 0x2e882f8a,
+ 0xe929943e, 0x8132c0a8, 0x12037f90, 0x809fbd66,
+ 0x8684ea04, 0x00cbafa7, 0x7b82d12a, 0x82500009,
+ 0xa2000001, 0x10880004, 0x00000005, 0x82500001,
+ 0x60340020, 0xFFFFFFFF, 0xa2000001, 0x10880004,
+ 0x00000005, 0x8250000d
+};
+
+static const u8 rng_result2[] = {
+ 0x76, 0x87, 0x66, 0x4e, 0xd8, 0x1d, 0x1f, 0x43,
+ 0x76, 0x50, 0x85, 0x5d, 0x1e, 0x1d, 0x9d, 0x0f,
+ 0x93, 0x75, 0x83, 0xff, 0x9a, 0x9b, 0x61, 0xa9,
+ 0xa5, 0xeb, 0xa3, 0x28, 0x2a, 0x15, 0xc1, 0x57
+};
+
+/*
+ * construct_rng_self_test_jobdesc() - Implement destination address in RNG self test descriptors
+ * Returns zero on success, and negative on error.
+ */
+static void construct_rng_self_test_jobdesc(u32 *desc, const u32 *rng_st_dsc, u8 *res_addr, int desc_size)
+{
+ int result_addr_idx = desc_size - 5;
+ int i;
+
+ for (i = 0; i < desc_size; i++) {
+ desc[i] = rng_st_dsc[i];
+ }
+
+ /* Replace destination address in the descriptor */
+ desc[result_addr_idx] = (u32)res_addr;
+}
+
+/* rng_self_test_done() - callback for caam_jr_enqueue */
+static void rng_self_test_done(struct device_d *dev, u32 *desc, u32 err, void *arg)
+{
+ int * job_err = arg;
+ *job_err = err;
+}
+
+/*
+ * caam_rng_self_test() - Perform RNG self test
+ * Returns zero on success, and negative on error.
+ */
+int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, const u8 rngrev)
+{
+ int ret, desc_size = 0, result_size = 0, job_err = 0;
+ const u32 *rng_st_dsc;
+ const u8 *exp_result;
+ u32 *desc;
+ u8 *result;
+
+ pr_debug("got CAAM ERA %d, RNG Version ID %d, RNG revision %d\n",
+ caam_era, rngvid, rngrev);
+
+ if (caam_era < 8 && rngvid == 4 && rngrev < 3) {
+ /* older affected i.MX chipsets have CAAM < 8 and have RNG4 < 4.3 */
+ rng_st_dsc = rng_dsc1;
+ desc_size = ARRAY_SIZE(rng_dsc1);
+ exp_result = rng_result1;
+ result_size = ARRAY_SIZE(rng_result1);
+ } else if (caam_era >= 8 || (rngvid >= 4 && rngrev >= 3)) {
+ /* newer affected chipsets have CAAM >= 8 or RNG4 >= 4.3 */
+ rng_st_dsc = rng_dsc2;
+ desc_size = ARRAY_SIZE(rng_dsc2);
+ exp_result = rng_result2;
+ result_size = ARRAY_SIZE(rng_result2);
+ } else {
+ pr_err("Invalid CAAM version: %d,%d,%d\n",
+ caam_era, rngvid, rngrev);
+ return -EINVAL;
+ }
+
+ result = dma_alloc(sizeof(*result) * result_size);
+ desc = dma_alloc(sizeof(*desc) * desc_size);
+
+ if (!result || !desc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ construct_rng_self_test_jobdesc(desc, rng_st_dsc, result, desc_size);
+
+ dma_sync_single_for_device((unsigned long)desc,
+ desc_size * sizeof(*desc), DMA_TO_DEVICE);
+ dma_sync_single_for_device((unsigned long)result,
+ result_size * sizeof(*result), DMA_FROM_DEVICE);
+
+ /* wait for job completion */
+ ret = caam_jr_enqueue(dev, desc, rng_self_test_done, &job_err);
+ if (ret) {
+ pr_err("Running RNG self-test descriptor failed: %d %s\n",
+ ret, strerror(ret));
+ goto err;
+ }
+ if (job_err) {
+ ret = -EINVAL;
+ pr_err("Job Error:\n");
+ caam_jr_strstatus(dev, job_err);
+ goto err;
+ }
+
+ dma_sync_single_for_cpu((unsigned long)result, result_size * sizeof(*result),
+ DMA_FROM_DEVICE);
+
+ if (memcmp(result, exp_result, sizeof(*result) * result_size) != 0) {
+ pr_err("RNG self-test failed with unexpected result\n");
+ ret = -ERANGE;
+ goto err;
+ }
+
+ pr_info("RNG software self-test passed\n");
+ ret = 0;
+
+err:
+ dma_free(desc);
+ dma_free(result);
+ return ret;
+}
diff --git a/drivers/crypto/caam/rng_self_test.h b/drivers/crypto/caam/rng_self_test.h
new file mode 100644
index 0000000000..1f5bf32628
--- /dev/null
+++ b/drivers/crypto/caam/rng_self_test.h
@@ -0,0 +1,24 @@
+/*
+ * CAAM RNG self test
+ *
+ * Copyright (C) 2018 Pengutronix, Roland Hieber <r.hieber@pengutronix.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef RNG_SELF_TEST_H
+#define RNG_SELF_TEST_H
+
+int caam_rng_self_test(struct device_d *dev, const u8 caam_era, const u8 rngvid, const u8 rngrev);
+
+#endif /* RNG_SELF_TEST_H */
diff --git a/drivers/hab/habv3.c b/drivers/hab/habv3.c
index 82ae245f8a..47d3caf864 100644
--- a/drivers/hab/habv3.c
+++ b/drivers/hab/habv3.c
@@ -78,5 +78,9 @@ int imx_habv3_get_status(uint32_t status)
int imx25_hab_get_status(void)
{
+ if (!cpu_is_mx25())
+ return 0;
+
return imx_habv3_get_status(readl(IOMEM(0x780018d4)));
}
+postmmu_initcall(imx25_hab_get_status);
diff --git a/drivers/hab/habv4.c b/drivers/hab/habv4.c
index 28fd42ecd7..ca95c01e7b 100644
--- a/drivers/hab/habv4.c
+++ b/drivers/hab/habv4.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <hab.h>
+#include <init.h>
#include <types.h>
#include <mach/generic.h>
@@ -387,6 +388,39 @@ static void habv4_display_event(uint8_t *data, uint32_t len)
habv4_display_event_record((struct hab_event_record *)data);
}
+/* Some chips with HAB >= 4.2.3 have an incorrect implementation of the RNG
+ * self-test in ROM code. In this case, an HAB event is generated, and a
+ * software self-test should be run. This variable is set to @c true by
+ * habv4_get_status() when this occurs. */
+bool habv4_need_rng_software_self_test = false;
+EXPORT_SYMBOL(habv4_need_rng_software_self_test);
+
+#define RNG_FAIL_EVENT_SIZE 36
+static uint8_t habv4_known_rng_fail_events[][RNG_FAIL_EVENT_SIZE] = {
+ { 0xdb, 0x00, 0x24, 0x42, 0x69, 0x30, 0xe1, 0x1d,
+ 0x00, 0x80, 0x00, 0x02, 0x40, 0x00, 0x36, 0x06,
+ 0x55, 0x55, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 },
+ { 0xdb, 0x00, 0x24, 0x42, 0x69, 0x30, 0xe1, 0x1d,
+ 0x00, 0x04, 0x00, 0x02, 0x40, 0x00, 0x36, 0x06,
+ 0x55, 0x55, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01 },
+};
+
+static bool is_known_rng_fail_event(const uint8_t *data, size_t len)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(habv4_known_rng_fail_events); i++) {
+ if (memcmp(data, habv4_known_rng_fail_events[i],
+ min(len, (uint32_t)RNG_FAIL_EVENT_SIZE)) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
static int habv4_get_status(const struct habv4_rvt *rvt)
{
uint8_t data[256];
@@ -413,10 +447,18 @@ static int habv4_get_status(const struct habv4_rvt *rvt)
len = sizeof(data);
while (rvt->report_event(HAB_STATUS_WARNING, index, data, &len) == HAB_STATUS_SUCCESS) {
- pr_err("-------- HAB warning Event %d --------\n", index);
- pr_err("event data:\n");
- habv4_display_event(data, len);
+ /* suppress RNG self-test fail events if they can be handled in software */
+ if (IS_ENABLED(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_SELF_TEST) &&
+ is_known_rng_fail_event(data, len)) {
+ pr_debug("RNG self-test failure detected, will run software self-test\n");
+ habv4_need_rng_software_self_test = true;
+ } else {
+ pr_err("-------- HAB warning Event %d --------\n", index);
+ pr_err("event data:\n");
+ habv4_display_event(data, len);
+ }
+
len = sizeof(data);
index++;
}
@@ -460,9 +502,54 @@ int imx6_hab_get_status(void)
return -EINVAL;
}
+static int init_imx6_hab_get_status(void)
+{
+ int ret = 0;
+
+ if (!cpu_is_mx6())
+ /* can happen in multi-image builds and is not an error */
+ return 0;
+
+ ret = imx6_hab_get_status();
+
+ /*
+ * Nobody will check the return value if there were HAB errors, but the
+ * initcall will fail spectaculously with a strange error message.
+ */
+ if (ret == -EPERM)
+ return 0;
+ return ret;
+}
+
+/*
+ * Need to run before MMU setup because i.MX6 ROM code is mapped near 0x0,
+ * which will no longer be accessible when the MMU sets the zero page to
+ * faulting.
+ */
+postconsole_initcall(init_imx6_hab_get_status);
+
int imx28_hab_get_status(void)
{
const struct habv4_rvt *rvt = (void *)HABV4_RVT_IMX28;
return habv4_get_status(rvt);
}
+
+static int init_imx28_hab_get_status(void)
+{
+ int ret = 0;
+
+ if (!cpu_is_mx28())
+ /* can happen in multi-image builds and is not an error */
+ return 0;
+
+ ret = imx28_hab_get_status();
+
+ /* nobody will check the return value if there were HAB errors, but the
+ * initcall will fail spectaculously with a strange error message. */
+ if (ret == -EPERM)
+ return 0;
+ return ret;
+}
+/* i.MX28 ROM code can be run after MMU setup to make use of caching */
+postmmu_initcall(init_imx28_hab_get_status);
diff --git a/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c
index e689559ee3..e0cf35f0b7 100644
--- a/drivers/nvmem/ocotp.c
+++ b/drivers/nvmem/ocotp.c
@@ -70,6 +70,7 @@
#define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA
#define DEF_RELAX 20
#define MAC_OFFSET_0 (0x22 * 4)
+#define IMX6UL_MAC_OFFSET_1 (0x23 * 4)
#define MAC_OFFSET_1 (0x24 * 4)
#define MAX_MAC_OFFSETS 2
#define MAC_BYTES 8
@@ -421,10 +422,14 @@ static int imx_ocotp_read_mac(const struct imx_ocotp_data *data,
int ret;
ret = regmap_bulk_read(map, offset, buf, MAC_BYTES);
+
if (ret < 0)
return ret;
- data->format_mac(mac, buf, OCOTP_HW_TO_MAC);
+ if (offset != IMX6UL_MAC_OFFSET_1)
+ data->format_mac(mac, buf, OCOTP_HW_TO_MAC);
+ else
+ data->format_mac(mac, buf + 2, OCOTP_HW_TO_MAC);
return 0;
}
@@ -639,6 +644,14 @@ static struct imx_ocotp_data imx6sl_ocotp_data = {
.format_mac = imx_ocotp_format_mac,
};
+static struct imx_ocotp_data imx6ul_ocotp_data = {
+ .num_regs = 512,
+ .addr_to_offset = imx6q_addr_to_offset,
+ .mac_offsets_num = 2,
+ .mac_offsets = { MAC_OFFSET_0, IMX6UL_MAC_OFFSET_1 },
+ .format_mac = imx_ocotp_format_mac,
+};
+
static struct imx_ocotp_data vf610_ocotp_data = {
.num_regs = 512,
.addr_to_offset = vf610_addr_to_offset,
@@ -667,7 +680,7 @@ static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
.data = &imx6sl_ocotp_data,
}, {
.compatible = "fsl,imx6ul-ocotp",
- .data = &imx6q_ocotp_data,
+ .data = &imx6ul_ocotp_data,
}, {
.compatible = "fsl,imx8mq-ocotp",
.data = &imx8mq_ocotp_data,
diff --git a/drivers/video/imx-ipu-v3/imx-pd.c b/drivers/video/imx-ipu-v3/imx-pd.c
index 09d8a3ae2a..601be35880 100644
--- a/drivers/video/imx-ipu-v3/imx-pd.c
+++ b/drivers/video/imx-ipu-v3/imx-pd.c
@@ -45,7 +45,7 @@ static int imx_pd_ioctl(struct vpl *vpl, unsigned int port,
case IMX_IPU_VPL_DI_MODE:
mode = data;
- mode->di_clkflags = IPU_DI_CLKMODE_SYNC;
+ mode->di_clkflags = IPU_DI_CLKMODE_NON_FRACTIONAL;
mode->bus_format = imx_pd->bus_format;
return 0;
diff --git a/drivers/video/imx-ipu-v3/ipu-di.c b/drivers/video/imx-ipu-v3/ipu-di.c
index b6e64fe16a..b4302412e0 100644
--- a/drivers/video/imx-ipu-v3/ipu-di.c
+++ b/drivers/video/imx-ipu-v3/ipu-di.c
@@ -140,6 +140,7 @@ static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate)
int div;
tmp *= 16;
+ tmp += outrate / 2;
do_div(tmp, outrate);