haven: rm: Update dt parsing to match Haven-supplied nodes

Haven hypervisor provides RM dt entries in a slightly different format
than has been used. Namely: the compatible string, capids are now
described by "reg" property, VMID/owner vmid is in a sibling DT node,
and names of some properties are changed. Thus, update RM driver to
parse accordingly. Common message queue dt parsing was moved into the
msgq driver helper function "hh_msgq_probe".

Change-Id: If3fe026bb6055267705a19d8ed7fd90ef0934270
Signed-off-by: Elliot Berman <eberman@codeaurora.org>
This commit is contained in:
Elliot Berman 2020-04-07 13:00:32 -07:00
parent d5ee68b825
commit a7f85f2873
3 changed files with 110 additions and 51 deletions

View File

@ -7,6 +7,7 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ratelimit.h>
@ -475,6 +476,55 @@ err:
}
EXPORT_SYMBOL(hh_msgq_populate_cap_info);
static int hh_msgq_probe_direction(struct platform_device *pdev,
enum hh_msgq_label label, int direction, int idx)
{
int irq, ret;
u64 capid;
irq = platform_get_irq(pdev, idx);
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get the IRQ%d. ret: %d\n",
idx, irq);
return irq;
}
ret = of_property_read_u64_index(pdev->dev.of_node, "reg", idx, &capid);
if (ret) {
dev_err(&pdev->dev, "Failed to get capid[%d]\n", idx);
return ret;
}
return hh_msgq_populate_cap_info(label, capid, direction, irq);
}
int hh_msgq_probe(struct platform_device *pdev, enum hh_msgq_label label)
{
int ret, idx = 0;
struct device_node *node = pdev->dev.of_node;
bool duplex;
duplex = of_property_read_bool(node, "qcom,is-full-duplex");
if (duplex || of_property_read_bool(node, "qcom,is-sender")) {
ret = hh_msgq_probe_direction(pdev, label, HH_MSGQ_DIRECTION_TX,
idx);
if (ret)
return ret;
idx++;
}
if (duplex || of_property_read_bool(node, "qcom,is-receiver")) {
ret = hh_msgq_probe_direction(pdev, label, HH_MSGQ_DIRECTION_RX,
idx);
if (ret)
return ret;
}
return 0;
}
EXPORT_SYMBOL(hh_msgq_probe);
static void hh_msgq_cleanup(int begin_idx)
{
struct hh_msgq_cap_table *cap_table_entry;

View File

@ -747,67 +747,72 @@ static void hh_rm_get_svm_res_work_fn(struct work_struct *work)
hh_rm_populate_hyp_res();
}
static int hh_vm_probe(struct device *dev, struct device_node *hyp_root)
{
struct device_node *node;
struct hh_vm_property temp_property;
int vmid, owner_vmid, ret;
node = of_find_compatible_node(hyp_root, NULL, "qcom,haven-vm-id-1.0");
if (IS_ERR_OR_NULL(node)) {
dev_err(dev, "Could not find vm-id node\n");
return -ENODEV;
}
ret = of_property_read_u32(node, "qcom,vmid", &vmid);
if (ret) {
dev_err(dev, "Could not read vmid: %d\n", ret);
return ret;
}
ret = of_property_read_u32(node, "qcom,owner-vmid", &owner_vmid);
if (ret) {
/* We must be HH_PRIMARY_VM */
temp_property.vmid = vmid;
hh_update_vm_prop_table(HH_PRIMARY_VM, &temp_property);
} else {
/* We must be HH_TRUSTED_VM */
temp_property.vmid = vmid;
hh_update_vm_prop_table(HH_TRUSTED_VM, &temp_property);
temp_property.vmid = owner_vmid;
hh_update_vm_prop_table(HH_PRIMARY_VM, &temp_property);
/* Query RM for available resources */
schedule_work(&hh_rm_get_svm_res_work);
}
return 0;
}
static const struct of_device_id hh_rm_drv_of_match[] = {
{ .compatible = "qcom,haven-resource-manager-1-0" },
{ .compatible = "qcom,resource-manager-1-0" },
{ }
};
static int hh_rm_drv_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
hh_capid_t tx_cap_id, rx_cap_id;
int tx_irq, rx_irq;
u32 owner_vmid;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
int ret;
ret = of_property_read_u64(node, "qcom,tx-cap", &tx_cap_id);
ret = hh_msgq_probe(pdev, HH_MSGQ_LABEL_RM);
if (ret) {
dev_err(&pdev->dev, "Failed to get the Tx cap-id\n");
return -EINVAL;
dev_err(dev, "Failed to probe message queue: %d\n", ret);
return ret;
}
ret = of_property_read_u64(node, "qcom,rx-cap", &rx_cap_id);
if (ret) {
dev_err(&pdev->dev, "Failed to get the Rx cap-id\n");
return -EINVAL;
}
tx_irq = platform_get_irq_byname(pdev, "rm-tx-irq");
if (tx_irq < 0) {
dev_err(&pdev->dev, "Failed to get the Tx IRQ. ret: %d\n",
tx_irq);
return tx_irq;
}
rx_irq = platform_get_irq_byname(pdev, "rm-rx-irq");
if (rx_irq < 0) {
dev_err(&pdev->dev, "Failed to get the Rx IRQ. ret: %d\n",
rx_irq);
return rx_irq;
}
if (of_property_read_u32(pdev->dev.of_node, "qcom,virq-base",
&hh_rm_base_virq)) {
dev_err(&pdev->dev, "Failed to get the vIRQ base\n");
if (of_property_read_u32(node, "qcom,free-irq-start",
&hh_rm_base_virq)) {
dev_err(dev, "Failed to get the vIRQ base\n");
return -ENXIO;
}
hh_rm_intc = of_irq_find_parent(pdev->dev.of_node);
hh_rm_intc = of_irq_find_parent(node);
if (!hh_rm_intc) {
dev_err(&pdev->dev, "Failed to get the IRQ parent node\n");
dev_err(dev, "Failed to get the IRQ parent node\n");
return -ENXIO;
}
ret = hh_msgq_populate_cap_info(HH_MSGQ_LABEL_RM, tx_cap_id,
HH_MSGQ_DIRECTION_TX, tx_irq);
if (ret)
return ret;
ret = hh_msgq_populate_cap_info(HH_MSGQ_LABEL_RM, rx_cap_id,
HH_MSGQ_DIRECTION_RX, rx_irq);
if (ret)
return ret;
hh_rm_msgq_desc = hh_msgq_register(HH_MSGQ_LABEL_RM);
if (IS_ERR_OR_NULL(hh_rm_msgq_desc))
return PTR_ERR(hh_rm_msgq_desc);
@ -822,14 +827,10 @@ static int hh_rm_drv_probe(struct platform_device *pdev)
goto err_recv_task;
}
/* If the node has a "qcom,owner-vmid" property, it means that it's
* a secondary-VM. Gain the info about it's resources here as there
* won't be any explicit notification from the primary-VM.
*/
if (!of_property_read_u32(pdev->dev.of_node, "qcom,owner-vmid",
&owner_vmid)) {
schedule_work(&hh_rm_get_svm_res_work);
}
/* Probe the vmid */
ret = hh_vm_probe(dev, node->parent);
if (ret < 0 && ret != -ENODEV)
goto err_recv_task;
return 0;

View File

@ -8,6 +8,7 @@
#define __HH_MSGQ_H
#include <linux/types.h>
#include <linux/platform_device.h>
#include "hh_common.h"
@ -37,6 +38,7 @@ int hh_msgq_recv(void *msgq_client_desc,
int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
int direction, int irq);
int hh_msgq_probe(struct platform_device *pdev, enum hh_msgq_label label);
#else
static inline void *hh_msgq_register(enum hh_msgq_label label)
{
@ -68,5 +70,11 @@ static inline int hh_msgq_populate_cap_info(enum hh_msgq_label label,
{
return -EINVAL;
}
static inline int hh_msgq_probe(struct platform_device *pdev,
enum hh_msgq_label label)
{
return -ENODEV;
}
#endif
#endif