1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2014 ARM Limited
8 #include <linux/init.h>
10 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/of_device.h>
14 #include <linux/sched/signal.h>
15 #include <linux/slab.h>
16 #include <linux/vexpress.h>
19 #define SYS_MISC_MASTERSITE (1 << 14)
21 #define SYS_PROCID0 0x24
22 #define SYS_PROCID1 0x28
23 #define SYS_HBI_MASK 0xfff
24 #define SYS_PROCIDx_HBI_SHIFT 0
26 #define SYS_CFGDATA 0x40
28 #define SYS_CFGCTRL 0x44
29 #define SYS_CFGCTRL_START (1 << 31)
30 #define SYS_CFGCTRL_WRITE (1 << 30)
31 #define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26)
32 #define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20)
33 #define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16)
34 #define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12)
35 #define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0)
37 #define SYS_CFGSTAT 0x48
38 #define SYS_CFGSTAT_ERR (1 << 1)
39 #define SYS_CFGSTAT_COMPLETE (1 << 0)
41 #define VEXPRESS_SITE_MB 0
42 #define VEXPRESS_SITE_DB1 1
43 #define VEXPRESS_SITE_DB2 2
44 #define VEXPRESS_SITE_MASTER 0xf
46 struct vexpress_syscfg
{
49 struct list_head funcs
;
52 struct vexpress_syscfg_func
{
53 struct list_head list
;
54 struct vexpress_syscfg
*syscfg
;
55 struct regmap
*regmap
;
57 u32
template[]; /* Keep it last! */
60 struct vexpress_config_bridge_ops
{
61 struct regmap
* (*regmap_init
)(struct device
*dev
, void *context
);
62 void (*regmap_exit
)(struct regmap
*regmap
, void *context
);
65 struct vexpress_config_bridge
{
66 struct vexpress_config_bridge_ops
*ops
;
71 static DEFINE_MUTEX(vexpress_config_mutex
);
72 static u32 vexpress_config_site_master
= VEXPRESS_SITE_MASTER
;
75 static void vexpress_config_set_master(u32 site
)
77 vexpress_config_site_master
= site
;
80 static void vexpress_config_lock(void *arg
)
82 mutex_lock(&vexpress_config_mutex
);
85 static void vexpress_config_unlock(void *arg
)
87 mutex_unlock(&vexpress_config_mutex
);
91 static void vexpress_config_find_prop(struct device_node
*node
,
92 const char *name
, u32
*val
)
99 if (of_property_read_u32(node
, name
, val
) == 0) {
103 node
= of_get_next_parent(node
);
107 static int vexpress_config_get_topo(struct device_node
*node
, u32
*site
,
108 u32
*position
, u32
*dcc
)
110 vexpress_config_find_prop(node
, "arm,vexpress,site", site
);
111 if (*site
== VEXPRESS_SITE_MASTER
)
112 *site
= vexpress_config_site_master
;
113 if (WARN_ON(vexpress_config_site_master
== VEXPRESS_SITE_MASTER
))
115 vexpress_config_find_prop(node
, "arm,vexpress,position", position
);
116 vexpress_config_find_prop(node
, "arm,vexpress,dcc", dcc
);
122 static void vexpress_config_devres_release(struct device
*dev
, void *res
)
124 struct vexpress_config_bridge
*bridge
= dev_get_drvdata(dev
->parent
);
125 struct regmap
*regmap
= res
;
127 bridge
->ops
->regmap_exit(regmap
, bridge
->context
);
130 struct regmap
*devm_regmap_init_vexpress_config(struct device
*dev
)
132 struct vexpress_config_bridge
*bridge
;
133 struct regmap
*regmap
;
136 bridge
= dev_get_drvdata(dev
->parent
);
137 if (WARN_ON(!bridge
))
138 return ERR_PTR(-EINVAL
);
140 res
= devres_alloc(vexpress_config_devres_release
, sizeof(*res
),
143 return ERR_PTR(-ENOMEM
);
145 regmap
= (bridge
->ops
->regmap_init
)(dev
, bridge
->context
);
146 if (IS_ERR(regmap
)) {
152 devres_add(dev
, res
);
156 EXPORT_SYMBOL_GPL(devm_regmap_init_vexpress_config
);
158 static int vexpress_syscfg_exec(struct vexpress_syscfg_func
*func
,
159 int index
, bool write
, u32
*data
)
161 struct vexpress_syscfg
*syscfg
= func
->syscfg
;
166 if (WARN_ON(index
>= func
->num_templates
))
169 command
= readl(syscfg
->base
+ SYS_CFGCTRL
);
170 if (WARN_ON(command
& SYS_CFGCTRL_START
))
173 command
= func
->template[index
];
174 command
|= SYS_CFGCTRL_START
;
175 command
|= write
? SYS_CFGCTRL_WRITE
: 0;
177 /* Use a canary for reads */
181 dev_dbg(syscfg
->dev
, "func %p, command %x, data %x\n",
182 func
, command
, *data
);
183 writel(*data
, syscfg
->base
+ SYS_CFGDATA
);
184 writel(0, syscfg
->base
+ SYS_CFGSTAT
);
185 writel(command
, syscfg
->base
+ SYS_CFGCTRL
);
188 /* The operation can take ages... Go to sleep, 100us initially */
192 if (!irqs_disabled()) {
193 set_current_state(TASK_INTERRUPTIBLE
);
194 schedule_timeout(usecs_to_jiffies(timeout
));
195 if (signal_pending(current
))
201 status
= readl(syscfg
->base
+ SYS_CFGSTAT
);
202 if (status
& SYS_CFGSTAT_ERR
)
207 } while (--tries
&& !(status
& SYS_CFGSTAT_COMPLETE
));
208 if (WARN_ON_ONCE(!tries
))
212 *data
= readl(syscfg
->base
+ SYS_CFGDATA
);
213 dev_dbg(syscfg
->dev
, "func %p, read data %x\n", func
, *data
);
219 static int vexpress_syscfg_read(void *context
, unsigned int index
,
222 struct vexpress_syscfg_func
*func
= context
;
224 return vexpress_syscfg_exec(func
, index
, false, val
);
227 static int vexpress_syscfg_write(void *context
, unsigned int index
,
230 struct vexpress_syscfg_func
*func
= context
;
232 return vexpress_syscfg_exec(func
, index
, true, &val
);
235 static struct regmap_config vexpress_syscfg_regmap_config
= {
236 .lock
= vexpress_config_lock
,
237 .unlock
= vexpress_config_unlock
,
240 .reg_read
= vexpress_syscfg_read
,
241 .reg_write
= vexpress_syscfg_write
,
242 .reg_format_endian
= REGMAP_ENDIAN_LITTLE
,
243 .val_format_endian
= REGMAP_ENDIAN_LITTLE
,
247 static struct regmap
*vexpress_syscfg_regmap_init(struct device
*dev
,
251 struct vexpress_syscfg
*syscfg
= context
;
252 struct vexpress_syscfg_func
*func
;
253 struct property
*prop
;
254 const __be32
*val
= NULL
;
255 __be32 energy_quirk
[4];
257 u32 site
, position
, dcc
;
260 err
= vexpress_config_get_topo(dev
->of_node
, &site
,
265 prop
= of_find_property(dev
->of_node
,
266 "arm,vexpress-sysreg,func", NULL
);
268 return ERR_PTR(-EINVAL
);
270 num
= prop
->length
/ sizeof(u32
) / 2;
274 * "arm,vexpress-energy" function used to be described
275 * by its first device only, now it requires both
277 if (num
== 1 && of_device_is_compatible(dev
->of_node
,
278 "arm,vexpress-energy")) {
280 energy_quirk
[0] = *val
;
281 energy_quirk
[2] = *val
++;
282 energy_quirk
[1] = *val
;
283 energy_quirk
[3] = cpu_to_be32(be32_to_cpup(val
) + 1);
287 func
= kzalloc(struct_size(func
, template, num
), GFP_KERNEL
);
289 return ERR_PTR(-ENOMEM
);
291 func
->syscfg
= syscfg
;
292 func
->num_templates
= num
;
294 for (i
= 0; i
< num
; i
++) {
295 u32 function
, device
;
297 function
= be32_to_cpup(val
++);
298 device
= be32_to_cpup(val
++);
300 dev_dbg(dev
, "func %p: %u/%u/%u/%u/%u\n",
301 func
, site
, position
, dcc
,
304 func
->template[i
] = SYS_CFGCTRL_DCC(dcc
);
305 func
->template[i
] |= SYS_CFGCTRL_SITE(site
);
306 func
->template[i
] |= SYS_CFGCTRL_POSITION(position
);
307 func
->template[i
] |= SYS_CFGCTRL_FUNC(function
);
308 func
->template[i
] |= SYS_CFGCTRL_DEVICE(device
);
311 vexpress_syscfg_regmap_config
.max_register
= num
- 1;
313 func
->regmap
= regmap_init(dev
, NULL
, func
,
314 &vexpress_syscfg_regmap_config
);
316 if (IS_ERR(func
->regmap
)) {
317 void *err
= func
->regmap
;
323 list_add(&func
->list
, &syscfg
->funcs
);
328 static void vexpress_syscfg_regmap_exit(struct regmap
*regmap
, void *context
)
330 struct vexpress_syscfg
*syscfg
= context
;
331 struct vexpress_syscfg_func
*func
, *tmp
;
335 list_for_each_entry_safe(func
, tmp
, &syscfg
->funcs
, list
) {
336 if (func
->regmap
== regmap
) {
337 list_del(&syscfg
->funcs
);
344 static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops
= {
345 .regmap_init
= vexpress_syscfg_regmap_init
,
346 .regmap_exit
= vexpress_syscfg_regmap_exit
,
350 static int vexpress_syscfg_probe(struct platform_device
*pdev
)
352 struct vexpress_syscfg
*syscfg
;
353 struct resource
*res
;
354 struct vexpress_config_bridge
*bridge
;
355 struct device_node
*node
;
359 syscfg
= devm_kzalloc(&pdev
->dev
, sizeof(*syscfg
), GFP_KERNEL
);
362 syscfg
->dev
= &pdev
->dev
;
363 INIT_LIST_HEAD(&syscfg
->funcs
);
365 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
366 syscfg
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
367 if (IS_ERR(syscfg
->base
))
368 return PTR_ERR(syscfg
->base
);
370 bridge
= devm_kmalloc(&pdev
->dev
, sizeof(*bridge
), GFP_KERNEL
);
374 bridge
->ops
= &vexpress_syscfg_bridge_ops
;
375 bridge
->context
= syscfg
;
377 dev_set_drvdata(&pdev
->dev
, bridge
);
379 master
= readl(syscfg
->base
+ SYS_MISC
) & SYS_MISC_MASTERSITE
?
380 VEXPRESS_SITE_DB2
: VEXPRESS_SITE_DB1
;
381 vexpress_config_set_master(master
);
383 /* Confirm board type against DT property, if available */
384 if (of_property_read_u32(of_root
, "arm,hbi", &dt_hbi
) == 0) {
385 u32 id
= readl(syscfg
->base
+ (master
== VEXPRESS_SITE_DB1
?
386 SYS_PROCID0
: SYS_PROCID1
));
387 u32 hbi
= (id
>> SYS_PROCIDx_HBI_SHIFT
) & SYS_HBI_MASK
;
389 if (WARN_ON(dt_hbi
!= hbi
))
390 dev_warn(&pdev
->dev
, "DT HBI (%x) is not matching hardware (%x)!\n",
394 for_each_compatible_node(node
, NULL
, "arm,vexpress,config-bus") {
395 struct device_node
*bridge_np
;
397 bridge_np
= of_parse_phandle(node
, "arm,vexpress,config-bridge", 0);
398 if (bridge_np
!= pdev
->dev
.parent
->of_node
)
401 of_platform_populate(node
, NULL
, NULL
, &pdev
->dev
);
407 static const struct platform_device_id vexpress_syscfg_id_table
[] = {
408 { "vexpress-syscfg", },
411 MODULE_DEVICE_TABLE(platform
, vexpress_syscfg_id_table
);
413 static struct platform_driver vexpress_syscfg_driver
= {
414 .driver
.name
= "vexpress-syscfg",
415 .id_table
= vexpress_syscfg_id_table
,
416 .probe
= vexpress_syscfg_probe
,
418 module_platform_driver(vexpress_syscfg_driver
);
419 MODULE_LICENSE("GPL v2");