Skip to content

Commit b892924

Browse files
committed
Merge tag 'imx-drivers-6.16' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into soc/drivers
i.MX drivers change for 6.16: - A series from Peng Fan to dump full 128-bits UID for i.MX8MP * tag 'imx-drivers-6.16' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: soc: imx8m: Dump higher 64bits UID soc: imx8m: Introduce soc_uid hook soc: imx8m: Cleanup with adding imx8m_soc_[un]prepare Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 94b2473 + fd0bf2b commit b892924

File tree

1 file changed

+108
-69
lines changed

1 file changed

+108
-69
lines changed

drivers/soc/imx/soc-imx8m.c

Lines changed: 108 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@
2424
#define OCOTP_UID_HIGH 0x420
2525

2626
#define IMX8MP_OCOTP_UID_OFFSET 0x10
27+
#define IMX8MP_OCOTP_UID_HIGH 0xE00
2728

2829
/* Same as ANADIG_DIGPROG_IMX7D */
2930
#define ANADIG_DIGPROG_IMX8MM 0x800
3031

3132
struct imx8_soc_data {
3233
char *name;
33-
int (*soc_revision)(u32 *socrev, u64 *socuid);
34+
const char *ocotp_compatible;
35+
int (*soc_revision)(struct platform_device *pdev, u32 *socrev);
36+
int (*soc_uid)(struct platform_device *pdev, u64 *socuid);
37+
};
38+
39+
struct imx8_soc_drvdata {
40+
void __iomem *ocotp_base;
41+
struct clk *clk;
3442
};
3543

3644
#ifdef CONFIG_HAVE_ARM_SMCCC
@@ -49,30 +57,24 @@ static u32 imx8mq_soc_revision_from_atf(void)
4957
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
5058
#endif
5159

52-
static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
60+
static int imx8m_soc_uid(struct platform_device *pdev, u64 *socuid)
5361
{
54-
struct device_node *np __free(device_node) =
55-
of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
56-
void __iomem *ocotp_base;
57-
u32 magic;
58-
u32 rev;
59-
struct clk *clk;
60-
int ret;
62+
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
63+
void __iomem *ocotp_base = drvdata->ocotp_base;
6164

62-
if (!np)
63-
return -EINVAL;
64-
65-
ocotp_base = of_iomap(np, 0);
66-
if (!ocotp_base)
67-
return -EINVAL;
65+
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
66+
*socuid <<= 32;
67+
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
6868

69-
clk = of_clk_get_by_name(np, NULL);
70-
if (IS_ERR(clk)) {
71-
ret = PTR_ERR(clk);
72-
goto err_clk;
73-
}
69+
return 0;
70+
}
7471

75-
clk_prepare_enable(clk);
72+
static int imx8mq_soc_revision(struct platform_device *pdev, u32 *socrev)
73+
{
74+
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
75+
void __iomem *ocotp_base = drvdata->ocotp_base;
76+
u32 magic;
77+
u32 rev;
7678

7779
/*
7880
* SOC revision on older imx8mq is not available in fuses so query
@@ -85,98 +87,109 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
8587
rev = REV_B1;
8688
}
8789

88-
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
89-
*socuid <<= 32;
90-
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
91-
9290
*socrev = rev;
9391

94-
clk_disable_unprepare(clk);
95-
clk_put(clk);
96-
iounmap(ocotp_base);
97-
9892
return 0;
93+
}
9994

100-
err_clk:
101-
iounmap(ocotp_base);
102-
return ret;
95+
static int imx8mp_soc_uid(struct platform_device *pdev, u64 *socuid)
96+
{
97+
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
98+
void __iomem *ocotp_base = drvdata->ocotp_base;
99+
100+
socuid[0] = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + IMX8MP_OCOTP_UID_OFFSET);
101+
socuid[0] <<= 32;
102+
socuid[0] |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + IMX8MP_OCOTP_UID_OFFSET);
103+
104+
socuid[1] = readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10);
105+
socuid[1] <<= 32;
106+
socuid[1] |= readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH);
107+
108+
return 0;
103109
}
104110

105-
static int imx8mm_soc_uid(u64 *socuid)
111+
static int imx8mm_soc_revision(struct platform_device *pdev, u32 *socrev)
106112
{
107113
struct device_node *np __free(device_node) =
108-
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
109-
void __iomem *ocotp_base;
110-
struct clk *clk;
111-
int ret = 0;
112-
u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
113-
IMX8MP_OCOTP_UID_OFFSET : 0;
114+
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
115+
void __iomem *anatop_base;
114116

115117
if (!np)
116118
return -EINVAL;
117119

118-
ocotp_base = of_iomap(np, 0);
119-
if (!ocotp_base)
120+
anatop_base = of_iomap(np, 0);
121+
if (!anatop_base)
120122
return -EINVAL;
121123

122-
clk = of_clk_get_by_name(np, NULL);
123-
if (IS_ERR(clk)) {
124-
ret = PTR_ERR(clk);
125-
goto err_clk;
126-
}
127-
128-
clk_prepare_enable(clk);
129-
130-
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
131-
*socuid <<= 32;
132-
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
124+
*socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
133125

134-
clk_disable_unprepare(clk);
135-
clk_put(clk);
126+
iounmap(anatop_base);
136127

137-
err_clk:
138-
iounmap(ocotp_base);
139-
return ret;
128+
return 0;
140129
}
141130

142-
static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
131+
static int imx8m_soc_prepare(struct platform_device *pdev, const char *ocotp_compatible)
143132
{
144133
struct device_node *np __free(device_node) =
145-
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
146-
void __iomem *anatop_base;
134+
of_find_compatible_node(NULL, NULL, ocotp_compatible);
135+
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
136+
int ret = 0;
147137

148138
if (!np)
149139
return -EINVAL;
150140

151-
anatop_base = of_iomap(np, 0);
152-
if (!anatop_base)
141+
drvdata->ocotp_base = of_iomap(np, 0);
142+
if (!drvdata->ocotp_base)
153143
return -EINVAL;
154144

155-
*socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
145+
drvdata->clk = of_clk_get_by_name(np, NULL);
146+
if (IS_ERR(drvdata->clk)) {
147+
ret = PTR_ERR(drvdata->clk);
148+
goto err_clk;
149+
}
156150

157-
iounmap(anatop_base);
151+
return clk_prepare_enable(drvdata->clk);
152+
153+
err_clk:
154+
iounmap(drvdata->ocotp_base);
155+
return ret;
156+
}
157+
158+
static void imx8m_soc_unprepare(struct platform_device *pdev)
159+
{
160+
struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
158161

159-
return imx8mm_soc_uid(socuid);
162+
clk_disable_unprepare(drvdata->clk);
163+
clk_put(drvdata->clk);
164+
iounmap(drvdata->ocotp_base);
160165
}
161166

162167
static const struct imx8_soc_data imx8mq_soc_data = {
163168
.name = "i.MX8MQ",
169+
.ocotp_compatible = "fsl,imx8mq-ocotp",
164170
.soc_revision = imx8mq_soc_revision,
171+
.soc_uid = imx8m_soc_uid,
165172
};
166173

167174
static const struct imx8_soc_data imx8mm_soc_data = {
168175
.name = "i.MX8MM",
176+
.ocotp_compatible = "fsl,imx8mm-ocotp",
169177
.soc_revision = imx8mm_soc_revision,
178+
.soc_uid = imx8m_soc_uid,
170179
};
171180

172181
static const struct imx8_soc_data imx8mn_soc_data = {
173182
.name = "i.MX8MN",
183+
.ocotp_compatible = "fsl,imx8mm-ocotp",
174184
.soc_revision = imx8mm_soc_revision,
185+
.soc_uid = imx8m_soc_uid,
175186
};
176187

177188
static const struct imx8_soc_data imx8mp_soc_data = {
178189
.name = "i.MX8MP",
190+
.ocotp_compatible = "fsl,imx8mm-ocotp",
179191
.soc_revision = imx8mm_soc_revision,
192+
.soc_uid = imx8mp_soc_uid,
180193
};
181194

182195
static __maybe_unused const struct of_device_id imx8_soc_match[] = {
@@ -207,17 +220,24 @@ static int imx8m_soc_probe(struct platform_device *pdev)
207220
struct soc_device_attribute *soc_dev_attr;
208221
struct platform_device *cpufreq_dev;
209222
const struct imx8_soc_data *data;
223+
struct imx8_soc_drvdata *drvdata;
210224
struct device *dev = &pdev->dev;
211225
const struct of_device_id *id;
212226
struct soc_device *soc_dev;
213227
u32 soc_rev = 0;
214-
u64 soc_uid = 0;
228+
u64 soc_uid[2] = {0, 0};
215229
int ret;
216230

217231
soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
218232
if (!soc_dev_attr)
219233
return -ENOMEM;
220234

235+
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
236+
if (!drvdata)
237+
return -ENOMEM;
238+
239+
platform_set_drvdata(pdev, drvdata);
240+
221241
soc_dev_attr->family = "Freescale i.MX";
222242

223243
ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
@@ -231,18 +251,37 @@ static int imx8m_soc_probe(struct platform_device *pdev)
231251
data = id->data;
232252
if (data) {
233253
soc_dev_attr->soc_id = data->name;
254+
ret = imx8m_soc_prepare(pdev, data->ocotp_compatible);
255+
if (ret)
256+
return ret;
257+
234258
if (data->soc_revision) {
235-
ret = data->soc_revision(&soc_rev, &soc_uid);
236-
if (ret)
259+
ret = data->soc_revision(pdev, &soc_rev);
260+
if (ret) {
261+
imx8m_soc_unprepare(pdev);
262+
return ret;
263+
}
264+
}
265+
if (data->soc_uid) {
266+
ret = data->soc_uid(pdev, soc_uid);
267+
if (ret) {
268+
imx8m_soc_unprepare(pdev);
237269
return ret;
270+
}
238271
}
272+
imx8m_soc_unprepare(pdev);
239273
}
240274

241275
soc_dev_attr->revision = imx8_revision(dev, soc_rev);
242276
if (!soc_dev_attr->revision)
243277
return -ENOMEM;
244278

245-
soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
279+
if (soc_uid[1])
280+
soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX%016llX",
281+
soc_uid[1], soc_uid[0]);
282+
else
283+
soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX",
284+
soc_uid[0]);
246285
if (!soc_dev_attr->serial_number)
247286
return -ENOMEM;
248287

0 commit comments

Comments
 (0)