1bb04ffe8SClaudio Carvalho // SPDX-License-Identifier: GPL-2.0
2bb04ffe8SClaudio Carvalho /*
3bb04ffe8SClaudio Carvalho * Ultravisor high level interfaces
4bb04ffe8SClaudio Carvalho *
5bb04ffe8SClaudio Carvalho * Copyright 2019, IBM Corporation.
6bb04ffe8SClaudio Carvalho *
7bb04ffe8SClaudio Carvalho */
8bb04ffe8SClaudio Carvalho #include <linux/init.h>
9bb04ffe8SClaudio Carvalho #include <linux/printk.h>
10bb04ffe8SClaudio Carvalho #include <linux/of_fdt.h>
1168e0aa8eSClaudio Carvalho #include <linux/of.h>
12bb04ffe8SClaudio Carvalho
13bb04ffe8SClaudio Carvalho #include <asm/ultravisor.h>
14bb04ffe8SClaudio Carvalho #include <asm/firmware.h>
1568e0aa8eSClaudio Carvalho #include <asm/machdep.h>
1668e0aa8eSClaudio Carvalho
1768e0aa8eSClaudio Carvalho #include "powernv.h"
1868e0aa8eSClaudio Carvalho
1968e0aa8eSClaudio Carvalho static struct kobject *ultravisor_kobj;
20bb04ffe8SClaudio Carvalho
early_init_dt_scan_ultravisor(unsigned long node,const char * uname,int depth,void * data)21bb04ffe8SClaudio Carvalho int __init early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
22bb04ffe8SClaudio Carvalho int depth, void *data)
23bb04ffe8SClaudio Carvalho {
24bb04ffe8SClaudio Carvalho if (!of_flat_dt_is_compatible(node, "ibm,ultravisor"))
25bb04ffe8SClaudio Carvalho return 0;
26bb04ffe8SClaudio Carvalho
27bb04ffe8SClaudio Carvalho powerpc_firmware_features |= FW_FEATURE_ULTRAVISOR;
28bb04ffe8SClaudio Carvalho pr_debug("Ultravisor detected!\n");
29bb04ffe8SClaudio Carvalho return 1;
30bb04ffe8SClaudio Carvalho }
3168e0aa8eSClaudio Carvalho
3268e0aa8eSClaudio Carvalho static struct memcons *uv_memcons;
3368e0aa8eSClaudio Carvalho
uv_msglog_read(struct file * file,struct kobject * kobj,struct bin_attribute * bin_attr,char * to,loff_t pos,size_t count)3468e0aa8eSClaudio Carvalho static ssize_t uv_msglog_read(struct file *file, struct kobject *kobj,
3568e0aa8eSClaudio Carvalho struct bin_attribute *bin_attr, char *to,
3668e0aa8eSClaudio Carvalho loff_t pos, size_t count)
3768e0aa8eSClaudio Carvalho {
3868e0aa8eSClaudio Carvalho return memcons_copy(uv_memcons, to, pos, count);
3968e0aa8eSClaudio Carvalho }
4068e0aa8eSClaudio Carvalho
4168e0aa8eSClaudio Carvalho static struct bin_attribute uv_msglog_attr = {
4268e0aa8eSClaudio Carvalho .attr = {.name = "msglog", .mode = 0400},
4368e0aa8eSClaudio Carvalho .read = uv_msglog_read
4468e0aa8eSClaudio Carvalho };
4568e0aa8eSClaudio Carvalho
uv_init(void)4668e0aa8eSClaudio Carvalho static int __init uv_init(void)
4768e0aa8eSClaudio Carvalho {
4868e0aa8eSClaudio Carvalho struct device_node *node;
4968e0aa8eSClaudio Carvalho
5068e0aa8eSClaudio Carvalho if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
5168e0aa8eSClaudio Carvalho return 0;
5268e0aa8eSClaudio Carvalho
5368e0aa8eSClaudio Carvalho node = of_find_compatible_node(NULL, NULL, "ibm,uv-firmware");
5468e0aa8eSClaudio Carvalho if (!node)
5568e0aa8eSClaudio Carvalho return -ENODEV;
5668e0aa8eSClaudio Carvalho
5768e0aa8eSClaudio Carvalho uv_memcons = memcons_init(node, "memcons");
58a4a6a382SLv Ruyi of_node_put(node);
5968e0aa8eSClaudio Carvalho if (!uv_memcons)
6068e0aa8eSClaudio Carvalho return -ENOENT;
6168e0aa8eSClaudio Carvalho
6268e0aa8eSClaudio Carvalho uv_msglog_attr.size = memcons_get_size(uv_memcons);
6368e0aa8eSClaudio Carvalho
6468e0aa8eSClaudio Carvalho ultravisor_kobj = kobject_create_and_add("ultravisor", firmware_kobj);
6568e0aa8eSClaudio Carvalho if (!ultravisor_kobj)
6668e0aa8eSClaudio Carvalho return -ENOMEM;
6768e0aa8eSClaudio Carvalho
6868e0aa8eSClaudio Carvalho return sysfs_create_bin_file(ultravisor_kobj, &uv_msglog_attr);
6968e0aa8eSClaudio Carvalho }
7068e0aa8eSClaudio Carvalho machine_subsys_initcall(powernv, uv_init);
71