Skip to content

Commit f402711

Browse files
committed
Merge tag 'imx-drivers-6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/drivers
i.MX drivers changes for 6.13: - A series from Marek Vasut to probe soc-imx8m as platform driver, so that it works properly with 'driver_async_probe' kernel parameter. * tag 'imx-drivers-6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: soc: imx8m: Use devm_* to simplify probe failure handling soc: imx8m: Remove global soc_uid soc: imx8m: Probe the SoC driver as platform driver Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 73536ab + 22b03a4 commit f402711

File tree

1 file changed

+101
-73
lines changed

1 file changed

+101
-73
lines changed

drivers/soc/imx/soc-imx8m.c

Lines changed: 101 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@
3030

3131
struct imx8_soc_data {
3232
char *name;
33-
u32 (*soc_revision)(void);
33+
int (*soc_revision)(u32 *socrev, u64 *socuid);
3434
};
3535

36-
static u64 soc_uid;
37-
3836
#ifdef CONFIG_HAVE_ARM_SMCCC
3937
static u32 imx8mq_soc_revision_from_atf(void)
4038
{
@@ -51,24 +49,27 @@ static u32 imx8mq_soc_revision_from_atf(void)
5149
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
5250
#endif
5351

54-
static u32 __init imx8mq_soc_revision(void)
52+
static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
5553
{
56-
struct device_node *np;
54+
struct device_node *np __free(device_node) =
55+
of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
5756
void __iomem *ocotp_base;
5857
u32 magic;
5958
u32 rev;
6059
struct clk *clk;
60+
int ret;
6161

62-
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
6362
if (!np)
64-
return 0;
63+
return -EINVAL;
6564

6665
ocotp_base = of_iomap(np, 0);
67-
WARN_ON(!ocotp_base);
66+
if (!ocotp_base)
67+
return -EINVAL;
68+
6869
clk = of_clk_get_by_name(np, NULL);
6970
if (IS_ERR(clk)) {
70-
WARN_ON(IS_ERR(clk));
71-
return 0;
71+
ret = PTR_ERR(clk);
72+
goto err_clk;
7273
}
7374

7475
clk_prepare_enable(clk);
@@ -84,71 +85,78 @@ static u32 __init imx8mq_soc_revision(void)
8485
rev = REV_B1;
8586
}
8687

87-
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
88-
soc_uid <<= 32;
89-
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
88+
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
89+
*socuid <<= 32;
90+
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
91+
92+
*socrev = rev;
9093

9194
clk_disable_unprepare(clk);
9295
clk_put(clk);
9396
iounmap(ocotp_base);
94-
of_node_put(np);
9597

96-
return rev;
98+
return 0;
99+
100+
err_clk:
101+
iounmap(ocotp_base);
102+
return ret;
97103
}
98104

99-
static void __init imx8mm_soc_uid(void)
105+
static int imx8mm_soc_uid(u64 *socuid)
100106
{
107+
struct device_node *np __free(device_node) =
108+
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
101109
void __iomem *ocotp_base;
102-
struct device_node *np;
103110
struct clk *clk;
111+
int ret = 0;
104112
u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
105113
IMX8MP_OCOTP_UID_OFFSET : 0;
106114

107-
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
108115
if (!np)
109-
return;
116+
return -EINVAL;
110117

111118
ocotp_base = of_iomap(np, 0);
112-
WARN_ON(!ocotp_base);
119+
if (!ocotp_base)
120+
return -EINVAL;
121+
113122
clk = of_clk_get_by_name(np, NULL);
114123
if (IS_ERR(clk)) {
115-
WARN_ON(IS_ERR(clk));
116-
return;
124+
ret = PTR_ERR(clk);
125+
goto err_clk;
117126
}
118127

119128
clk_prepare_enable(clk);
120129

121-
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
122-
soc_uid <<= 32;
123-
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
130+
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
131+
*socuid <<= 32;
132+
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
124133

125134
clk_disable_unprepare(clk);
126135
clk_put(clk);
136+
137+
err_clk:
127138
iounmap(ocotp_base);
128-
of_node_put(np);
139+
return ret;
129140
}
130141

131-
static u32 __init imx8mm_soc_revision(void)
142+
static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
132143
{
133-
struct device_node *np;
144+
struct device_node *np __free(device_node) =
145+
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
134146
void __iomem *anatop_base;
135-
u32 rev;
136147

137-
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
138148
if (!np)
139-
return 0;
149+
return -EINVAL;
140150

141151
anatop_base = of_iomap(np, 0);
142-
WARN_ON(!anatop_base);
152+
if (!anatop_base)
153+
return -EINVAL;
143154

144-
rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
155+
*socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
145156

146157
iounmap(anatop_base);
147-
of_node_put(np);
148-
149-
imx8mm_soc_uid();
150158

151-
return rev;
159+
return imx8mm_soc_uid(socuid);
152160
}
153161

154162
static const struct imx8_soc_data imx8mq_soc_data = {
@@ -179,60 +187,57 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = {
179187
{ }
180188
};
181189

182-
#define imx8_revision(soc_rev) \
183-
soc_rev ? \
184-
kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
190+
#define imx8_revision(dev, soc_rev) \
191+
(soc_rev) ? \
192+
devm_kasprintf((dev), GFP_KERNEL, "%d.%d", ((soc_rev) >> 4) & 0xf, (soc_rev) & 0xf) : \
185193
"unknown"
186194

187-
static int __init imx8_soc_init(void)
195+
static int imx8m_soc_probe(struct platform_device *pdev)
188196
{
189197
struct soc_device_attribute *soc_dev_attr;
190-
struct soc_device *soc_dev;
198+
const struct imx8_soc_data *data;
199+
struct device *dev = &pdev->dev;
191200
const struct of_device_id *id;
201+
struct soc_device *soc_dev;
192202
u32 soc_rev = 0;
193-
const struct imx8_soc_data *data;
203+
u64 soc_uid = 0;
194204
int ret;
195205

196-
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
206+
soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
197207
if (!soc_dev_attr)
198208
return -ENOMEM;
199209

200210
soc_dev_attr->family = "Freescale i.MX";
201211

202212
ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
203213
if (ret)
204-
goto free_soc;
214+
return ret;
205215

206216
id = of_match_node(imx8_soc_match, of_root);
207-
if (!id) {
208-
ret = -ENODEV;
209-
goto free_soc;
210-
}
217+
if (!id)
218+
return -ENODEV;
211219

212220
data = id->data;
213221
if (data) {
214222
soc_dev_attr->soc_id = data->name;
215-
if (data->soc_revision)
216-
soc_rev = data->soc_revision();
223+
if (data->soc_revision) {
224+
ret = data->soc_revision(&soc_rev, &soc_uid);
225+
if (ret)
226+
return ret;
227+
}
217228
}
218229

219-
soc_dev_attr->revision = imx8_revision(soc_rev);
220-
if (!soc_dev_attr->revision) {
221-
ret = -ENOMEM;
222-
goto free_soc;
223-
}
230+
soc_dev_attr->revision = imx8_revision(dev, soc_rev);
231+
if (!soc_dev_attr->revision)
232+
return -ENOMEM;
224233

225-
soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
226-
if (!soc_dev_attr->serial_number) {
227-
ret = -ENOMEM;
228-
goto free_rev;
229-
}
234+
soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
235+
if (!soc_dev_attr->serial_number)
236+
return -ENOMEM;
230237

231238
soc_dev = soc_device_register(soc_dev_attr);
232-
if (IS_ERR(soc_dev)) {
233-
ret = PTR_ERR(soc_dev);
234-
goto free_serial_number;
235-
}
239+
if (IS_ERR(soc_dev))
240+
return PTR_ERR(soc_dev);
236241

237242
pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id,
238243
soc_dev_attr->revision);
@@ -241,15 +246,38 @@ static int __init imx8_soc_init(void)
241246
platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
242247

243248
return 0;
249+
}
244250

245-
free_serial_number:
246-
kfree(soc_dev_attr->serial_number);
247-
free_rev:
248-
if (strcmp(soc_dev_attr->revision, "unknown"))
249-
kfree(soc_dev_attr->revision);
250-
free_soc:
251-
kfree(soc_dev_attr);
252-
return ret;
251+
static struct platform_driver imx8m_soc_driver = {
252+
.probe = imx8m_soc_probe,
253+
.driver = {
254+
.name = "imx8m-soc",
255+
},
256+
};
257+
258+
static int __init imx8_soc_init(void)
259+
{
260+
struct platform_device *pdev;
261+
int ret;
262+
263+
/* No match means this is non-i.MX8M hardware, do nothing. */
264+
if (!of_match_node(imx8_soc_match, of_root))
265+
return 0;
266+
267+
ret = platform_driver_register(&imx8m_soc_driver);
268+
if (ret) {
269+
pr_err("Failed to register imx8m-soc platform driver: %d\n", ret);
270+
return ret;
271+
}
272+
273+
pdev = platform_device_register_simple("imx8m-soc", -1, NULL, 0);
274+
if (IS_ERR(pdev)) {
275+
pr_err("Failed to register imx8m-soc platform device: %ld\n", PTR_ERR(pdev));
276+
platform_driver_unregister(&imx8m_soc_driver);
277+
return PTR_ERR(pdev);
278+
}
279+
280+
return 0;
253281
}
254282
device_initcall(imx8_soc_init);
255283
MODULE_DESCRIPTION("NXP i.MX8M SoC driver");

0 commit comments

Comments
 (0)