18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Ultravisor high level interfaces
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2019, IBM Corporation.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/init.h>
98c2ecf20Sopenharmony_ci#include <linux/printk.h>
108c2ecf20Sopenharmony_ci#include <linux/of_fdt.h>
118c2ecf20Sopenharmony_ci#include <linux/of.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <asm/ultravisor.h>
148c2ecf20Sopenharmony_ci#include <asm/firmware.h>
158c2ecf20Sopenharmony_ci#include <asm/machdep.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "powernv.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic struct kobject *ultravisor_kobj;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciint __init early_init_dt_scan_ultravisor(unsigned long node, const char *uname,
228c2ecf20Sopenharmony_ci					 int depth, void *data)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	if (!of_flat_dt_is_compatible(node, "ibm,ultravisor"))
258c2ecf20Sopenharmony_ci		return 0;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	powerpc_firmware_features |= FW_FEATURE_ULTRAVISOR;
288c2ecf20Sopenharmony_ci	pr_debug("Ultravisor detected!\n");
298c2ecf20Sopenharmony_ci	return 1;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic struct memcons *uv_memcons;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic ssize_t uv_msglog_read(struct file *file, struct kobject *kobj,
358c2ecf20Sopenharmony_ci			      struct bin_attribute *bin_attr, char *to,
368c2ecf20Sopenharmony_ci			      loff_t pos, size_t count)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	return memcons_copy(uv_memcons, to, pos, count);
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic struct bin_attribute uv_msglog_attr = {
428c2ecf20Sopenharmony_ci	.attr = {.name = "msglog", .mode = 0400},
438c2ecf20Sopenharmony_ci	.read = uv_msglog_read
448c2ecf20Sopenharmony_ci};
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic int __init uv_init(void)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	struct device_node *node;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
518c2ecf20Sopenharmony_ci		return 0;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	node = of_find_compatible_node(NULL, NULL, "ibm,uv-firmware");
548c2ecf20Sopenharmony_ci	if (!node)
558c2ecf20Sopenharmony_ci		return -ENODEV;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	uv_memcons = memcons_init(node, "memcons");
588c2ecf20Sopenharmony_ci	of_node_put(node);
598c2ecf20Sopenharmony_ci	if (!uv_memcons)
608c2ecf20Sopenharmony_ci		return -ENOENT;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	uv_msglog_attr.size = memcons_get_size(uv_memcons);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	ultravisor_kobj = kobject_create_and_add("ultravisor", firmware_kobj);
658c2ecf20Sopenharmony_ci	if (!ultravisor_kobj)
668c2ecf20Sopenharmony_ci		return -ENOMEM;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	return sysfs_create_bin_file(ultravisor_kobj, &uv_msglog_attr);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_cimachine_subsys_initcall(powernv, uv_init);
71