lkml.org 
[lkml]   [2020]   [Sep]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 3/3] nvmem: qfprom: Don't touch certain fuses
Date
Some fuse ranges are protected by the XPU such that the AP cannot
access them. Attempting to do so causes an SError. Use the newly
introduced per-soc compatible string to attach the set of regions
we should not access. Then tiptoe around those regions.

Signed-off-by: Evan Green <evgreen@chromium.org>
---

drivers/nvmem/qfprom.c | 55 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
index 5e9e60e2e591d..feea39ae52164 100644
--- a/drivers/nvmem/qfprom.c
+++ b/drivers/nvmem/qfprom.c
@@ -12,6 +12,7 @@
#include <linux/mod_devicetable.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>

/* Blow timer clock frequency in Mhz */
@@ -51,6 +52,17 @@ struct qfprom_soc_data {
u32 qfprom_blow_set_freq;
};

+/**
+ * struct qfprom_keepout_region - registers to avoid touching.
+ *
+ * @start: The first byte offset to avoid.
+ * @end: One after the last byte offset to avoid.
+ */
+struct qfprom_keepout_region {
+ u32 start;
+ u32 end;
+};
+
/**
* struct qfprom_priv - structure holding qfprom attributes
*
@@ -63,6 +75,7 @@ struct qfprom_soc_data {
* @secclk: Clock supply.
* @vcc: Regulator supply.
* @soc_data: Data that for things that varies from SoC to SoC.
+ * @keepout: Fuse regions not to access, as they may cause SErrors.
*/
struct qfprom_priv {
void __iomem *qfpraw;
@@ -73,6 +86,7 @@ struct qfprom_priv {
struct clk *secclk;
struct regulator *vcc;
const struct qfprom_soc_data *soc_data;
+ const struct qfprom_keepout_region *keepout;
};

/**
@@ -88,6 +102,12 @@ struct qfprom_touched_values {
u32 timer_val;
};

+const struct qfprom_keepout_region sc7180_qfprom[] = {
+ {.start = 0x128, .end = 0x148},
+ {.start = 0x220, .end = 0x228},
+ {} /* Sentinal where start == end. */
+};
+
/**
* qfprom_disable_fuse_blowing() - Undo enabling of fuse blowing.
* @priv: Our driver data.
@@ -171,6 +191,23 @@ static int qfprom_enable_fuse_blowing(const struct qfprom_priv *priv,
return ret;
}

+static int qfprom_check_reg(struct qfprom_priv *priv, unsigned int reg)
+{
+ const struct qfprom_keepout_region *keepout = priv->keepout;
+
+ if (!keepout)
+ return 1;
+
+ while (keepout->start != keepout->end) {
+ if ((reg >= keepout->start) && (reg < keepout->end))
+ return 0;
+
+ keepout++;
+ }
+
+ return 1;
+}
+
/**
* qfprom_efuse_reg_write() - Write to fuses.
* @context: Our driver data.
@@ -228,8 +265,10 @@ static int qfprom_reg_write(void *context, unsigned int reg, void *_val,
goto exit_enabled_fuse_blowing;
}

- for (i = 0; i < words; i++)
- writel(value[i], priv->qfpraw + reg + (i * 4));
+ for (i = 0; i < words; i++) {
+ if (qfprom_check_reg(priv, reg + (i * 4)))
+ writel(value[i], priv->qfpraw + reg + (i * 4));
+ }

ret = readl_relaxed_poll_timeout(
priv->qfpconf + QFPROM_BLOW_STATUS_OFFSET,
@@ -257,8 +296,14 @@ static int qfprom_reg_read(void *context,
if (read_raw_data && priv->qfpraw)
base = priv->qfpraw;

- while (words--)
- *val++ = readb(base + reg + i++);
+ while (words--) {
+ if (qfprom_check_reg(priv, reg + i))
+ *val++ = readb(base + reg + i);
+ else
+ *val++ = 0;
+
+ i++;
+ }

return 0;
}
@@ -299,6 +344,7 @@ static int qfprom_probe(struct platform_device *pdev)
econfig.priv = priv;

priv->dev = dev;
+ priv->keepout = device_get_match_data(dev);

/*
* If more than one region is provided then the OS has the ability
@@ -354,6 +400,7 @@ static int qfprom_probe(struct platform_device *pdev)

static const struct of_device_id qfprom_of_match[] = {
{ .compatible = "qcom,qfprom",},
+ { .compatible = "qcom,sc7180-qfprom", .data = &sc7180_qfprom},
{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, qfprom_of_match);
--
2.26.2
\
 
 \ /
  Last update: 2020-09-29 22:58    [W:0.107 / U:6.036 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site