xref: /linux/drivers/pmdomain/renesas/r8a78000-mdlc.c (revision ee1b6365f07a14e987dd0f994fc7d46966037ea9)
1*9f79f939SGeert Uytterhoeven // SPDX-License-Identifier: GPL-2.0
2*9f79f939SGeert Uytterhoeven /*
3*9f79f939SGeert Uytterhoeven  * R-Car X5H Module Controller
4*9f79f939SGeert Uytterhoeven  *
5*9f79f939SGeert Uytterhoeven  * Copyright (C) 2026 Glider bv
6*9f79f939SGeert Uytterhoeven  */
7*9f79f939SGeert Uytterhoeven 
8*9f79f939SGeert Uytterhoeven #include <linux/dev_printk.h>
9*9f79f939SGeert Uytterhoeven #include <linux/device-id/of.h>
10*9f79f939SGeert Uytterhoeven #include <linux/module.h>
11*9f79f939SGeert Uytterhoeven #include <linux/of.h>
12*9f79f939SGeert Uytterhoeven #include <linux/platform_device.h>
13*9f79f939SGeert Uytterhoeven #include <linux/pm_domain.h>
14*9f79f939SGeert Uytterhoeven #include <linux/reset-controller.h>
15*9f79f939SGeert Uytterhoeven #include <linux/slab.h>
16*9f79f939SGeert Uytterhoeven 
17*9f79f939SGeert Uytterhoeven #include <dt-bindings/power/renesas,r8a78000-mdlc.h>
18*9f79f939SGeert Uytterhoeven 
19*9f79f939SGeert Uytterhoeven struct mod_map {
20*9f79f939SGeert Uytterhoeven 	int hw_id;		/* Hardware module ID or -1 sentinel */
21*9f79f939SGeert Uytterhoeven };
22*9f79f939SGeert Uytterhoeven 
23*9f79f939SGeert Uytterhoeven struct mdlc_info {
24*9f79f939SGeert Uytterhoeven 	u32 base;
25*9f79f939SGeert Uytterhoeven 	const struct mod_map *mod_map;
26*9f79f939SGeert Uytterhoeven };
27*9f79f939SGeert Uytterhoeven 
28*9f79f939SGeert Uytterhoeven /**
29*9f79f939SGeert Uytterhoeven  * struct r8a78000_mdlc_priv - Module Controller Private Data
30*9f79f939SGeert Uytterhoeven  *
31*9f79f939SGeert Uytterhoeven  * @link: Link into list of MDLC instances
32*9f79f939SGeert Uytterhoeven  * @genpd_data: PM domain provider data
33*9f79f939SGeert Uytterhoeven  * @rcdev: Reset controller entity
34*9f79f939SGeert Uytterhoeven  * @dev: MDLC device
35*9f79f939SGeert Uytterhoeven  * @np: Device node in DT representing the MDLC
36*9f79f939SGeert Uytterhoeven  * @mod_map: Mapping from hardware module IDs
37*9f79f939SGeert Uytterhoeven  */
38*9f79f939SGeert Uytterhoeven struct r8a78000_mdlc_priv {
39*9f79f939SGeert Uytterhoeven 	struct hlist_node link;
40*9f79f939SGeert Uytterhoeven 	struct genpd_onecell_data genpd_data;
41*9f79f939SGeert Uytterhoeven 	struct reset_controller_dev rcdev;
42*9f79f939SGeert Uytterhoeven 	struct device *dev;
43*9f79f939SGeert Uytterhoeven 	struct device_node *np;
44*9f79f939SGeert Uytterhoeven 	const struct mod_map *mod_map;
45*9f79f939SGeert Uytterhoeven };
46*9f79f939SGeert Uytterhoeven 
47*9f79f939SGeert Uytterhoeven static struct generic_pm_domain *r8a78000_genpd_always_on;
48*9f79f939SGeert Uytterhoeven static HLIST_HEAD(r8a78000_mdlc_list);
49*9f79f939SGeert Uytterhoeven static DEFINE_MUTEX(r8a78000_mdlc_lock);	/* protects the two above */
50*9f79f939SGeert Uytterhoeven 
51*9f79f939SGeert Uytterhoeven static struct generic_pm_domain *r8a78000_genpd_xlate(
52*9f79f939SGeert Uytterhoeven 			const struct of_phandle_args *spec, void *data)
53*9f79f939SGeert Uytterhoeven {
54*9f79f939SGeert Uytterhoeven 	struct r8a78000_mdlc_priv *priv = container_of(data,
55*9f79f939SGeert Uytterhoeven 					struct r8a78000_mdlc_priv, genpd_data);
56*9f79f939SGeert Uytterhoeven 	struct device *dev = priv->dev;
57*9f79f939SGeert Uytterhoeven 	u32 id;
58*9f79f939SGeert Uytterhoeven 
59*9f79f939SGeert Uytterhoeven 	if (spec->args_count != 2)
60*9f79f939SGeert Uytterhoeven 		return ERR_PTR(-EINVAL);
61*9f79f939SGeert Uytterhoeven 
62*9f79f939SGeert Uytterhoeven 	id = spec->args[0];
63*9f79f939SGeert Uytterhoeven 
64*9f79f939SGeert Uytterhoeven 	if (id >= R8A78000_MDLC_PD_AON) {
65*9f79f939SGeert Uytterhoeven 		dev_dbg(dev,
66*9f79f939SGeert Uytterhoeven 			"Mapping HW power domain 0x%x to always-on domain\n",
67*9f79f939SGeert Uytterhoeven 			id);
68*9f79f939SGeert Uytterhoeven 		return r8a78000_genpd_always_on;
69*9f79f939SGeert Uytterhoeven 	}
70*9f79f939SGeert Uytterhoeven 
71*9f79f939SGeert Uytterhoeven 	/* For now only always-on domains are supported */
72*9f79f939SGeert Uytterhoeven 	dev_err(dev, "Unknown power domain 0x%x\n", id);
73*9f79f939SGeert Uytterhoeven 	return ERR_PTR(-ENOENT);
74*9f79f939SGeert Uytterhoeven }
75*9f79f939SGeert Uytterhoeven 
76*9f79f939SGeert Uytterhoeven #define rcdev_to_priv(_rcdev)	\
77*9f79f939SGeert Uytterhoeven 	container_of(_rcdev, struct r8a78000_mdlc_priv, rcdev)
78*9f79f939SGeert Uytterhoeven 
79*9f79f939SGeert Uytterhoeven static const struct mod_map *mod_map_find(const struct mod_map *map, u32 id)
80*9f79f939SGeert Uytterhoeven {
81*9f79f939SGeert Uytterhoeven 	if (!map)
82*9f79f939SGeert Uytterhoeven 		return NULL;
83*9f79f939SGeert Uytterhoeven 
84*9f79f939SGeert Uytterhoeven 	for (; map->hw_id >= 0; map++) {
85*9f79f939SGeert Uytterhoeven 		if (map->hw_id == id)
86*9f79f939SGeert Uytterhoeven 			return map;
87*9f79f939SGeert Uytterhoeven 	}
88*9f79f939SGeert Uytterhoeven 
89*9f79f939SGeert Uytterhoeven 	return NULL;
90*9f79f939SGeert Uytterhoeven }
91*9f79f939SGeert Uytterhoeven 
92*9f79f939SGeert Uytterhoeven static int r8a78000_mdlc_reset_xlate(struct reset_controller_dev *rcdev,
93*9f79f939SGeert Uytterhoeven 				     const struct of_phandle_args *spec)
94*9f79f939SGeert Uytterhoeven {
95*9f79f939SGeert Uytterhoeven 	struct r8a78000_mdlc_priv *priv = rcdev_to_priv(rcdev);
96*9f79f939SGeert Uytterhoeven 	struct device *dev = priv->dev;
97*9f79f939SGeert Uytterhoeven 	const struct mod_map *map;
98*9f79f939SGeert Uytterhoeven 	u32 id;
99*9f79f939SGeert Uytterhoeven 
100*9f79f939SGeert Uytterhoeven 	if (spec->args_count != 1)
101*9f79f939SGeert Uytterhoeven 		return -EINVAL;
102*9f79f939SGeert Uytterhoeven 
103*9f79f939SGeert Uytterhoeven 	id = spec->args[0];
104*9f79f939SGeert Uytterhoeven 
105*9f79f939SGeert Uytterhoeven 	map = mod_map_find(priv->mod_map, id);
106*9f79f939SGeert Uytterhoeven 	if (!map) {
107*9f79f939SGeert Uytterhoeven 		dev_err(dev, "Unknown reset 0x%x\n", id);
108*9f79f939SGeert Uytterhoeven 		return -ENOENT;
109*9f79f939SGeert Uytterhoeven 	}
110*9f79f939SGeert Uytterhoeven 
111*9f79f939SGeert Uytterhoeven 	dev_dbg(dev, "Ignoring HW reset 0x%x\n", id);
112*9f79f939SGeert Uytterhoeven 	return id;
113*9f79f939SGeert Uytterhoeven }
114*9f79f939SGeert Uytterhoeven 
115*9f79f939SGeert Uytterhoeven #define DEFINE_MDLC_RESET_WRAPPER(op)					    \
116*9f79f939SGeert Uytterhoeven 	static int r8a78000_mdlc_ ## op(struct reset_controller_dev *rcdev, \
117*9f79f939SGeert Uytterhoeven 					unsigned long id)		    \
118*9f79f939SGeert Uytterhoeven 	{								    \
119*9f79f939SGeert Uytterhoeven 		struct r8a78000_mdlc_priv *priv = rcdev_to_priv(rcdev);	    \
120*9f79f939SGeert Uytterhoeven 									    \
121*9f79f939SGeert Uytterhoeven 		dev_dbg(priv->dev, "%s: Ignoring\n", __func__);		    \
122*9f79f939SGeert Uytterhoeven 		return 0;						    \
123*9f79f939SGeert Uytterhoeven 	}
124*9f79f939SGeert Uytterhoeven 
125*9f79f939SGeert Uytterhoeven DEFINE_MDLC_RESET_WRAPPER(reset)
126*9f79f939SGeert Uytterhoeven DEFINE_MDLC_RESET_WRAPPER(assert)
127*9f79f939SGeert Uytterhoeven DEFINE_MDLC_RESET_WRAPPER(deassert)
128*9f79f939SGeert Uytterhoeven DEFINE_MDLC_RESET_WRAPPER(status)
129*9f79f939SGeert Uytterhoeven 
130*9f79f939SGeert Uytterhoeven static const struct reset_control_ops r8a78000_mdlc_reset_ops = {
131*9f79f939SGeert Uytterhoeven 	.reset = r8a78000_mdlc_reset,
132*9f79f939SGeert Uytterhoeven 	.assert = r8a78000_mdlc_assert,
133*9f79f939SGeert Uytterhoeven 	.deassert = r8a78000_mdlc_deassert,
134*9f79f939SGeert Uytterhoeven 	.status = r8a78000_mdlc_status,
135*9f79f939SGeert Uytterhoeven };
136*9f79f939SGeert Uytterhoeven 
137*9f79f939SGeert Uytterhoeven static int r8a78000_mdlc_attach_dev(struct generic_pm_domain *domain,
138*9f79f939SGeert Uytterhoeven 				    struct device *dev)
139*9f79f939SGeert Uytterhoeven {
140*9f79f939SGeert Uytterhoeven 	struct device_node *np = dev->of_node;
141*9f79f939SGeert Uytterhoeven 	struct r8a78000_mdlc_priv *priv;
142*9f79f939SGeert Uytterhoeven 	struct of_phandle_args pd_spec;
143*9f79f939SGeert Uytterhoeven 	const struct mod_map *map;
144*9f79f939SGeert Uytterhoeven 	unsigned int id;
145*9f79f939SGeert Uytterhoeven 	int ret;
146*9f79f939SGeert Uytterhoeven 
147*9f79f939SGeert Uytterhoeven 	ret = of_parse_phandle_with_args(np, "power-domains",
148*9f79f939SGeert Uytterhoeven 					 "#power-domain-cells", 0, &pd_spec);
149*9f79f939SGeert Uytterhoeven 	if (ret < 0)
150*9f79f939SGeert Uytterhoeven 		return ret;
151*9f79f939SGeert Uytterhoeven 
152*9f79f939SGeert Uytterhoeven 	scoped_guard(mutex, &r8a78000_mdlc_lock) {
153*9f79f939SGeert Uytterhoeven 		hlist_for_each_entry(priv, &r8a78000_mdlc_list, link) {
154*9f79f939SGeert Uytterhoeven 			if (priv->np == pd_spec.np)
155*9f79f939SGeert Uytterhoeven 				break;
156*9f79f939SGeert Uytterhoeven 		}
157*9f79f939SGeert Uytterhoeven 	}
158*9f79f939SGeert Uytterhoeven 
159*9f79f939SGeert Uytterhoeven 	if (!priv) {
160*9f79f939SGeert Uytterhoeven 		dev_err(dev, "%s: MDLC %pOF not found\n", __func__, pd_spec.np);
161*9f79f939SGeert Uytterhoeven 		of_node_put(pd_spec.np);
162*9f79f939SGeert Uytterhoeven 		return -ENODEV;
163*9f79f939SGeert Uytterhoeven 	}
164*9f79f939SGeert Uytterhoeven 
165*9f79f939SGeert Uytterhoeven 	id = pd_spec.args[1];
166*9f79f939SGeert Uytterhoeven 	of_node_put(pd_spec.np);
167*9f79f939SGeert Uytterhoeven 
168*9f79f939SGeert Uytterhoeven 	map = mod_map_find(priv->mod_map, id);
169*9f79f939SGeert Uytterhoeven 	if (!map) {
170*9f79f939SGeert Uytterhoeven 		dev_err(dev, "Unknown module 0x%x\n", id);
171*9f79f939SGeert Uytterhoeven 		return -ENOENT;
172*9f79f939SGeert Uytterhoeven 	}
173*9f79f939SGeert Uytterhoeven 
174*9f79f939SGeert Uytterhoeven 	dev_dbg(dev, "Ignoring HW module 0x%x\n", id);
175*9f79f939SGeert Uytterhoeven 	return 0;
176*9f79f939SGeert Uytterhoeven }
177*9f79f939SGeert Uytterhoeven 
178*9f79f939SGeert Uytterhoeven static void r8a78000_mdlc_unlink(void *data)
179*9f79f939SGeert Uytterhoeven {
180*9f79f939SGeert Uytterhoeven 	struct r8a78000_mdlc_priv *priv = data;
181*9f79f939SGeert Uytterhoeven 
182*9f79f939SGeert Uytterhoeven 	scoped_guard(mutex, &r8a78000_mdlc_lock) {
183*9f79f939SGeert Uytterhoeven 		hlist_del(&priv->link);
184*9f79f939SGeert Uytterhoeven 	}
185*9f79f939SGeert Uytterhoeven }
186*9f79f939SGeert Uytterhoeven 
187*9f79f939SGeert Uytterhoeven static void r8a78000_genpd_del_provider(void *data)
188*9f79f939SGeert Uytterhoeven {
189*9f79f939SGeert Uytterhoeven 	of_genpd_del_provider(data);
190*9f79f939SGeert Uytterhoeven }
191*9f79f939SGeert Uytterhoeven 
192*9f79f939SGeert Uytterhoeven static int r8a78000_genpd_always_on_singleton(struct device *dev)
193*9f79f939SGeert Uytterhoeven {
194*9f79f939SGeert Uytterhoeven 	struct generic_pm_domain *genpd;
195*9f79f939SGeert Uytterhoeven 	int ret;
196*9f79f939SGeert Uytterhoeven 
197*9f79f939SGeert Uytterhoeven 	guard(mutex)(&r8a78000_mdlc_lock);
198*9f79f939SGeert Uytterhoeven 
199*9f79f939SGeert Uytterhoeven 	if (r8a78000_genpd_always_on)
200*9f79f939SGeert Uytterhoeven 		return 0;
201*9f79f939SGeert Uytterhoeven 
202*9f79f939SGeert Uytterhoeven 	genpd = kzalloc_obj(*genpd);
203*9f79f939SGeert Uytterhoeven 	if (!genpd)
204*9f79f939SGeert Uytterhoeven 		return -ENOMEM;
205*9f79f939SGeert Uytterhoeven 
206*9f79f939SGeert Uytterhoeven 	genpd->name = "always-on";
207*9f79f939SGeert Uytterhoeven 	genpd->attach_dev = r8a78000_mdlc_attach_dev;
208*9f79f939SGeert Uytterhoeven 
209*9f79f939SGeert Uytterhoeven 	ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
210*9f79f939SGeert Uytterhoeven 	if (ret) {
211*9f79f939SGeert Uytterhoeven 		kfree(genpd);
212*9f79f939SGeert Uytterhoeven 		return dev_err_probe(dev, ret,
213*9f79f939SGeert Uytterhoeven 				     "Failed to create always-on domain\n");
214*9f79f939SGeert Uytterhoeven 	}
215*9f79f939SGeert Uytterhoeven 
216*9f79f939SGeert Uytterhoeven 	r8a78000_genpd_always_on = genpd;
217*9f79f939SGeert Uytterhoeven 	return 0;
218*9f79f939SGeert Uytterhoeven }
219*9f79f939SGeert Uytterhoeven 
220*9f79f939SGeert Uytterhoeven static int r8a78000_mdlc_probe(struct platform_device *pdev)
221*9f79f939SGeert Uytterhoeven {
222*9f79f939SGeert Uytterhoeven 	struct device *dev = &pdev->dev;
223*9f79f939SGeert Uytterhoeven 	struct device_node *np = dev->of_node;
224*9f79f939SGeert Uytterhoeven 	struct r8a78000_mdlc_priv *priv;
225*9f79f939SGeert Uytterhoeven 	const struct mdlc_info *info;
226*9f79f939SGeert Uytterhoeven 	struct resource *res;
227*9f79f939SGeert Uytterhoeven 	int ret;
228*9f79f939SGeert Uytterhoeven 
229*9f79f939SGeert Uytterhoeven 	ret = r8a78000_genpd_always_on_singleton(dev);
230*9f79f939SGeert Uytterhoeven 	if (ret)
231*9f79f939SGeert Uytterhoeven 		return ret;
232*9f79f939SGeert Uytterhoeven 
233*9f79f939SGeert Uytterhoeven 	info = of_device_get_match_data(dev);
234*9f79f939SGeert Uytterhoeven 	if (!info)
235*9f79f939SGeert Uytterhoeven 		return -ENODEV;
236*9f79f939SGeert Uytterhoeven 
237*9f79f939SGeert Uytterhoeven 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
238*9f79f939SGeert Uytterhoeven 	if (!priv)
239*9f79f939SGeert Uytterhoeven 		return -ENOMEM;
240*9f79f939SGeert Uytterhoeven 
241*9f79f939SGeert Uytterhoeven 	priv->dev = dev;
242*9f79f939SGeert Uytterhoeven 	priv->np = np;
243*9f79f939SGeert Uytterhoeven 
244*9f79f939SGeert Uytterhoeven 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
245*9f79f939SGeert Uytterhoeven 	if (!res)
246*9f79f939SGeert Uytterhoeven 		return -ENODEV;
247*9f79f939SGeert Uytterhoeven 
248*9f79f939SGeert Uytterhoeven 	for (; info->base; info++) {
249*9f79f939SGeert Uytterhoeven 		if (info->base == res->start)
250*9f79f939SGeert Uytterhoeven 			break;
251*9f79f939SGeert Uytterhoeven 	}
252*9f79f939SGeert Uytterhoeven 
253*9f79f939SGeert Uytterhoeven 	if (!info->base) {
254*9f79f939SGeert Uytterhoeven 		dev_dbg(dev, "Unsupported MDLC instance 0x%pa\n", &res->start);
255*9f79f939SGeert Uytterhoeven 		return -ENODEV;
256*9f79f939SGeert Uytterhoeven 	}
257*9f79f939SGeert Uytterhoeven 
258*9f79f939SGeert Uytterhoeven 	priv->mod_map = info->mod_map;
259*9f79f939SGeert Uytterhoeven 
260*9f79f939SGeert Uytterhoeven 	scoped_guard(mutex, &r8a78000_mdlc_lock) {
261*9f79f939SGeert Uytterhoeven 		hlist_add_head(&priv->link, &r8a78000_mdlc_list);
262*9f79f939SGeert Uytterhoeven 	}
263*9f79f939SGeert Uytterhoeven 
264*9f79f939SGeert Uytterhoeven 	ret = devm_add_action_or_reset(dev, r8a78000_mdlc_unlink, priv);
265*9f79f939SGeert Uytterhoeven 	if (ret)
266*9f79f939SGeert Uytterhoeven 		return dev_err_probe(dev, ret, "failed to add action\n");
267*9f79f939SGeert Uytterhoeven 
268*9f79f939SGeert Uytterhoeven 	/* Note that no actual domains are registered, just need translation */
269*9f79f939SGeert Uytterhoeven 	priv->genpd_data.xlate = r8a78000_genpd_xlate;
270*9f79f939SGeert Uytterhoeven 	ret = of_genpd_add_provider_onecell(np, &priv->genpd_data);
271*9f79f939SGeert Uytterhoeven 	if (ret)
272*9f79f939SGeert Uytterhoeven 		return dev_err_probe(dev, ret,
273*9f79f939SGeert Uytterhoeven 				     "Failed to register genpd provider\n");
274*9f79f939SGeert Uytterhoeven 
275*9f79f939SGeert Uytterhoeven 	ret = devm_add_action_or_reset(dev, r8a78000_genpd_del_provider, np);
276*9f79f939SGeert Uytterhoeven 	if (ret)
277*9f79f939SGeert Uytterhoeven 		return dev_err_probe(dev, ret,
278*9f79f939SGeert Uytterhoeven 				     "failed to add unregister action\n");
279*9f79f939SGeert Uytterhoeven 
280*9f79f939SGeert Uytterhoeven 	priv->rcdev.ops = &r8a78000_mdlc_reset_ops;
281*9f79f939SGeert Uytterhoeven 	priv->rcdev.of_node = np;
282*9f79f939SGeert Uytterhoeven 	priv->rcdev.of_reset_n_cells = 1;
283*9f79f939SGeert Uytterhoeven 	priv->rcdev.of_xlate = r8a78000_mdlc_reset_xlate;
284*9f79f939SGeert Uytterhoeven 
285*9f79f939SGeert Uytterhoeven 	ret = devm_reset_controller_register(dev, &priv->rcdev);
286*9f79f939SGeert Uytterhoeven 	if (ret)
287*9f79f939SGeert Uytterhoeven 		return dev_err_probe(dev, ret,
288*9f79f939SGeert Uytterhoeven 				     "Failed to register reset controller\n");
289*9f79f939SGeert Uytterhoeven 
290*9f79f939SGeert Uytterhoeven 	return 0;
291*9f79f939SGeert Uytterhoeven }
292*9f79f939SGeert Uytterhoeven 
293*9f79f939SGeert Uytterhoeven static const struct mod_map r8a78000_mdlc_perw_mod_default[] = {
294*9f79f939SGeert Uytterhoeven 	{ 0x54 },	/* HSCIF0 */
295*9f79f939SGeert Uytterhoeven 	{ -1 }
296*9f79f939SGeert Uytterhoeven };
297*9f79f939SGeert Uytterhoeven 
298*9f79f939SGeert Uytterhoeven static const struct mdlc_info r8a78000_mdlc_default[] = {
299*9f79f939SGeert Uytterhoeven 	{
300*9f79f939SGeert Uytterhoeven 		.base = 0xc05d0000 /* mdlc_perw */,
301*9f79f939SGeert Uytterhoeven 		.mod_map = r8a78000_mdlc_perw_mod_default,
302*9f79f939SGeert Uytterhoeven 	},
303*9f79f939SGeert Uytterhoeven 	{ /* sentinel */ }
304*9f79f939SGeert Uytterhoeven };
305*9f79f939SGeert Uytterhoeven 
306*9f79f939SGeert Uytterhoeven static const struct of_device_id r8a78000_mdlc_match[] = {
307*9f79f939SGeert Uytterhoeven 	{
308*9f79f939SGeert Uytterhoeven 		.compatible = "renesas,r8a78000-mdlc",
309*9f79f939SGeert Uytterhoeven 		.data = &r8a78000_mdlc_default,
310*9f79f939SGeert Uytterhoeven 	},
311*9f79f939SGeert Uytterhoeven 	{ /* sentinel */ }
312*9f79f939SGeert Uytterhoeven };
313*9f79f939SGeert Uytterhoeven 
314*9f79f939SGeert Uytterhoeven static struct platform_driver r8a78000_mdlc_driver = {
315*9f79f939SGeert Uytterhoeven 	.probe = r8a78000_mdlc_probe,
316*9f79f939SGeert Uytterhoeven 	.driver = {
317*9f79f939SGeert Uytterhoeven 		.name = "r8a78000-mdlc",
318*9f79f939SGeert Uytterhoeven 		.of_match_table = r8a78000_mdlc_match,
319*9f79f939SGeert Uytterhoeven 		.suppress_bind_attrs = true,
320*9f79f939SGeert Uytterhoeven 	},
321*9f79f939SGeert Uytterhoeven };
322*9f79f939SGeert Uytterhoeven 
323*9f79f939SGeert Uytterhoeven builtin_platform_driver(r8a78000_mdlc_driver)
324*9f79f939SGeert Uytterhoeven 
325*9f79f939SGeert Uytterhoeven MODULE_DESCRIPTION("R-Car X5H MDLC Driver");
326